Overview
On pump.fun a coin's curve is normally priced in SOL. Pump also lets a curve be priced in another pump.fun coin. We build on that.
When you launch on CHAIN you pick a parent. Your coin's curve is quoted in that parent, so every buy of your coin is also a buy of the parent, and of the parent's parent, all the way up to a SOL root. Coins linked this way form a family tree, and the home page ranks those trees.
| Piece | Who runs it |
|---|---|
| Bonding curves | pump.fun. Every coin here is a normal pump.fun coin, listed on pump.fun itself. |
| Quote currency | Set once at creation and stored on the curve. It never changes. |
| Routing | CHAIN builds one transaction that hops through each curve in the chain. |
| Custody | None. You sign every transaction in your own wallet. |
| Term | Meaning |
|---|---|
| Root | A coin quoted in SOL (or a base pump.fun allows, like USDC). Generation 0. |
| Parent | The coin your coin is quoted in. Your curve holds parent tokens, not SOL. |
| Child | A coin quoted in yours. Anyone can launch one. |
| Generation | How many links sit between a coin and its root. G0 is the root, G1 its child, and so on. |
| Family tree | A root and every coin launched under it here. |
| Route | The path a trade takes, e.g. SOL → ROOT → CHILD → YOURS. |
Launching a coin
One signature. The mint key is generated and signed on the server, so you only approve once.
- 1
Pick a parent, or none
Paste any pump.fun mint, on its curve or graduated. We check its generation against the live limit before you fill anything in. Leave it empty to start a SOL root. - 2
Name, ticker, image
Name up to 32 characters, ticker up to 10 letters or numbers, image PNG, JPEG, GIF or WebP under 3.5 MB. - 3
Optional dev buy
Bought in the same transaction as the create. For a child it's an amount of the parent coin, so you need to hold some. For a root it's SOL, capped at 50. - 4
Sign and land
The server checks the signed bytes match what it built, then sends it. The coin appears on the board within seconds.
Trading a chain
You trade with SOL. We do the hops.
A buy of a G2 coin swaps SOL into the root, the root into the G1 coin, and the G1 coin into yours, in one atomic transaction. If any hop fails, nothing happens. Sells run the same path backwards and pay out in SOL.
| Setting | Detail |
|---|---|
| Slippage | Default 5%, from 0.1% to 50%. It protects the final output of the whole route. |
| Fees | Each hop is a normal pump.fun trade, so each hop pays pump.fun’s usual fee. |
| Creator fees | Every coin launched here is a pump.fun holder-rewards coin: its creator is the holder-rewards account, so creator fees are paid out to holders, not to the launcher. This is set at creation and is permanent. |
| Graduated coins | Routes through the PumpSwap pool instead of the curve, automatically. |
| Roots not in SOL | If a root is quoted in USDC or another base, the route starts from that base. |
pump.fun's program allows chains up to 5 generations deep, but the limit it actually enforces is a setting it can change. We read it live from pump's global account.
Enforced right now
G2
Deepest generation you can launch today.
Program cap
G5
Unlocks only if pump.fun raises the setting.
The board, search, feed and coin pages only show coins launched through CHAIN. You can still launch a child of any pump.fun coin; that outside parent appears in your coin's lineage as plain text, without a page.
API basics
The site runs on the same public JSON API you can call. No key needed.
| Base URL | https://www.chainpad.tech |
| Format | JSON in and out, except launch prepare, which is multipart. |
| Transactions | Base64-encoded v0 transactions. You sign; we never hold keys. |
| Amounts | Human units as strings, e.g. "0.5" SOL. Decimals are handled for you. |
GET/api/parent/:mint
Check whether a coin can be a parent, and what generation your coin would be.
curl https://www.chainpad.tech/api/parent/2yPZk2wkw16r1BvDRSqKfqyKQumeCvs9EdUNRetNpump{
"mint": "2yPZk2wkw16r1BvDRSqKfqyKQumeCvs9EdUNRetNpump",
"source": "pumpCoin",
"depth": 1,
"decimals": 6,
"maxDepth": 2,
"symbol": "EXAMPLE",
"name": "Example coin",
"icon": "https://…",
"mcap": 182400,
"allowed": true
}Your coin would be generation depth + 1. allowed is false once the parent already sits at the live limit.
POST/api/launch/prepare
Multipart form with an image file and a data field holding JSON.
| Field | Description |
|---|---|
| launcher | Your wallet address. It pays and signs. |
| name | 1 to 32 characters. |
| symbol | 1 to 10 letters or numbers. A leading $ is dropped. |
| description | Optional, up to 600 characters. |
| parent | Optional parent mint. Omit for a SOL root. |
| devBuy | Optional. Parent-coin amount for a child, SOL for a root (max 50). |
Returns { mint, depth, tx }.
POST/api/launch/confirm
Send { mint, tx } with the signed transaction. Anything other than the exact prepared transaction is rejected with 422. Calling it again after success returns the same signature.
import { VersionedTransaction } from '@solana/web3.js'
const b64 = (bytes: Uint8Array) => btoa(String.fromCharCode(...bytes))
const fromB64 = (s: string) => Uint8Array.from(atob(s), (c) => c.charCodeAt(0))
export async function launchChild(wallet: Wallet, image: File) {
// 1. Prepare: the server pins metadata and builds the create transaction.
const form = new FormData()
form.append('image', image)
form.append(
'data',
JSON.stringify({
launcher: wallet.publicKey.toBase58(),
name: 'Grandchild',
symbol: 'GRAND',
description: 'Quoted in its parent, not SOL.',
parent: '2yPZk2wkw16r1BvDRSqKfqyKQumeCvs9EdUNRetNpump', // omit for a SOL root
devBuy: '1000', // optional, in the parent coin
}),
)
const prepared = await fetch('https://www.chainpad.tech/api/launch/prepare', { method: 'POST', body: form })
.then((r) => r.json())
if (prepared.error) throw new Error(prepared.error)
// 2. Sign: one signature from the launcher. The mint key is already on it.
const tx = VersionedTransaction.deserialize(fromB64(prepared.tx))
const signed = await wallet.signTransaction(tx)
// 3. Confirm: the server checks it is the exact transaction it built, then sends it.
const done = await fetch('https://www.chainpad.tech/api/launch/confirm', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ mint: prepared.mint, tx: b64(signed.serialize()) }),
}).then((r) => r.json())
if (done.error) throw new Error(done.error)
return { mint: done.mint, signature: done.signature, generation: prepared.depth }
}POST/api/trade
One endpoint, four actions. route and quote need no wallet.
| action | Body | Returns |
|---|---|---|
| route | mint, side | path, hops, currency |
| quote | + amount | + amountOut |
| prepare | + user, slippageBps | + minOut, tx |
| send | mint, user, tx (signed) | signature |
curl -X POST https://www.chainpad.tech/api/trade \
-H 'content-type: application/json' \
-d '{"action":"quote","mint":"<coin>","side":"buy","amount":"0.5"}'{
"path": ["So111…1112", "<root>", "<child>", "<coin>"],
"hops": ["SOL → ROOT", "ROOT → CHILD", "CHILD → COIN"],
"currency": "SOL",
"amountOut": 1843210.55
}// Buy 0.5 SOL worth of any coin launched here, however deep it sits.
const prepared = await post({
action: 'prepare',
mint: coin,
side: 'buy',
amount: '0.5',
user: wallet.publicKey.toBase58(),
slippageBps: 500, // 5%, applies to the final output
})
const signed = await wallet.signTransaction(
VersionedTransaction.deserialize(fromB64(prepared.tx)),
)
const { signature } = await post({
action: 'send',
mint: coin,
side: 'buy',
user: wallet.publicKey.toBase58(),
tx: b64(signed.serialize()),
})
function post(body: object) {
return fetch('https://www.chainpad.tech/api/trade', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(body),
}).then(async (r) => {
const json = await r.json()
if (!r.ok) throw new Error(json.error)
return json
})
}| Endpoint | Returns |
|---|---|
| GET /api/feed | Recent trades on coins launched here. Cached 15 s. |
| GET /api/search?q= | Coins launched here matching a name, ticker or mint. |
| GET /api/coin/:mint/tree | Children and grandchildren launched here. |
| GET /api/coin/:mint/candles?tf= | OHLCV candles. tf is 1m, 5m, 15m, 1h, 4h or 1d. |
| GET /api/coin/:mint/trades | The last 50 trades. |
| GET /api/balances?owner=&mints= | Token balances for up to 8 comma-separated mints. |
# Live trades on coins launched here
curl https://www.chainpad.tech/api/feed
# Children and grandchildren of a coin
curl https://www.chainpad.tech/api/coin/<mint>/tree
# Candles: 1m 5m 15m 1h 4h 1d
curl "https://www.chainpad.tech/api/coin/<mint>/candles?tf=15m"
# Search coins launched here by name, ticker or mint
curl "https://www.chainpad.tech/api/search?q=grand"Failures return a non-2xx status and a readable message you can show to users as-is.
{ "error": "That chain is already as deep as pump.fun allows." }| Status | When |
|---|---|
| 400 | Bad input: invalid address, name too long, depth limit reached. |
| 401 | Trade prepare without a wallet. |
| 404 | Unknown launch, or a coin not launched here. |
| 422 | Signed transaction does not match what was prepared. |
| 5xx | Solana RPC or upstream trouble. Safe to retry. |
Can I launch under a coin I didn’t create?
Yes. Any pump.fun coin can be a parent, as long as its chain is below the live depth limit.
Does buying my coin really buy the parent?
Yes. Your curve can only accept the parent coin, so every SOL buy first acquires parent tokens on the open market.
What happens when my coin graduates?
It moves to a PumpSwap pool paired with its parent, just like a SOL coin pairs with SOL. Routing switches over automatically.
Can the quote currency change later?
No. It is fixed in the curve at creation.
Do you hold my funds?
No. Every launch and trade is a transaction you sign in your own wallet.
