Install
openclaw skills install grok-implementClawPump V2 Token Launchpad — launch real on-chain SPL tokens priced in CLAW via Meteora DBC, trade, graduate to DAMM v2. Use when user wants to launch a token on Solana with CLAW as quote currency.
openclaw skills install grok-implementDrop this file into your agent (Hermes, OpenClaw, KaiNova, or any LLM agent). The agent reads it and learns how to launch real on-chain SPL tokens against CLAW through a Meteora Dynamic Bonding Curve (DBC) pool, then trade or read live pool state.
This is the real on-chain path, not a proxy. Every transaction is built server-side, signed by a Solana wallet (Phantom / Solflare / Keypair held by the agent or its user), and broadcast directly to mainnet.
v0.7 changelog: removed the 10k-CLAW launch gate (launching is open to anyone), documented how a hosted agent can generate a Solana wallet for a user with only an
agent_api_key, and added the CLAW flywheel explainer.
| Field | Value |
|---|---|
| Platform | ClawPump v2 |
| API base | https://clawpump-v2.vercel.app/api |
| Quote currency | CLAW (739dnZEG4yaBWFsY8L8ZwrfhGG6dhtCSercW8Umspump) |
| AMM | Meteora Dynamic Bonding Curve (dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN) |
| Migration target | DAMM v2 (cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG) |
| Solana cluster | mainnet-beta |
| Token decimals (base) | 6 |
| Quote decimals (CLAW) | 6 |
Legacy SOL-quoted launches via
clawpump.vercel.appare a separate upstream product. This SKILL only covers the CLAW-quoted v2 path.
Read this before you launch anything. Agents that understand the why explain it back to users better.
User wants to launch a meme.
│
▼
User buys CLAW on the open market. ←──── CLAW buy pressure #1
│
▼
User calls /api/launch ─► pool created, priced in CLAW.
│
▼
Traders want to buy the new meme.
│
▼
Traders buy CLAW first (only quote token). ←──── CLAW buy pressure #2
│
▼
Every buy pushes the meme up the curve in CLAW units.
25 bps fee on every trade flows back to the creator.
│
▼
At 100k CLAW of buy volume the curve graduates.
│
▼
Liquidity migrates to a Meteora DAMM v2 pool as MEME/CLAW.
20% of LP is permanent-locked → fees flow forever.
│
▼
Jupiter, Birdeye, DexScreener, Photon index it as MEME/CLAW.
Every future trade of that meme = more CLAW demand. ←──── CLAW buy pressure #3
Bottom line: every successful launch creates three layers of CLAW demand (launcher, traders, locked LP). CLAW holders ride the volume of every meme on the platform, forever.
That is the entire point.
GET /api/claw live CLAW price + curve constants
GET /api/tier?wallet=<PUBKEY> tier + perks (informational, never blocks)
GET /api/pool/<POOL_PUBKEY> live pool reserves + migration %
POST /api/swap/quote pure swap preview, no tx
/api/tier response shape{
"wallet": "<base58>",
"balanceClaw": 12345,
"tier": "Cub",
"canLaunch": true,
"perks": { "feeRebatePct": 25 },
"thresholds": { "Cub": 10000, "Lion": 100000, "Apex": 1000000 }
}
canLaunchis alwaystruesince v0.7. It used to gate launching at 10k CLAW; we removed that gate because the on-chain DBC program never enforced it and it was hostile to first-time users. The field stays in the response for backward compatibility with older agent code.
| Tier | Hold | What you get |
|---|---|---|
| Cub | 10k CLAW | 25% trading-fee rebate · Cub badge on launches |
| Lion | 100k CLAW | 50% rebate · featured slot · priority indexing |
| Apex | 1M CLAW | 100% rebate · co-creator share on house memes · locked-LP revenue |
Anyone with 0 CLAW can launch. Holding CLAW is about earning a share of the flywheel, not unlocking permission.
/api/pool/<POOL_PUBKEY> response{
"pool": "<base58>",
"config": "<base58>",
"baseMint": "<base58>",
"quoteMint": "739dnZEG…pump",
"isMigrated": false,
"baseReserve": "1000000000000000",
"quoteReserve": "12345000000",
"migrationQuoteThreshold": "100000000000",
"progressPct": 12.345
}
poolis the DBC pool pubkey, NOT the base mint. The pool address is what/api/launchreturns aspoolPubkey. Confusing the two is the #1 mistake — store both.
The Meteora DBC program enforces three signers on every launch tx:
| Account | Who signs | Notes |
|---|---|---|
config (ephemeral) | ClawPump server | Pre-signed for you, never leaves the request |
baseMint (ephemeral) | ClawPump server | Pre-signed for you, never leaves the request |
creator (the launcher) | The user/agent wallet | Must hold a real Solana private key. No exceptions. |
payer (SOL fees) | The user/agent wallet | Currently same as creator; future relayer mode may pay this for you |
There is no "public-key-only" launch on Solana. The on-chain program
requires an ed25519 signature from the pool creator. No amount of API
proxying can avoid this — it's enforced by the program at
dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN.
So every launching entity needs one of these three things:
| Path | Where the private key lives | Best for |
|---|---|---|
| A. Browser wallet | Phantom / Solflare extension | Regular humans on the website |
| B. Headless Keypair | Inside your agent's Node process / env var | Autonomous agents you fully control |
| C. Hosted-agent-generated Keypair | User's storage, generated by the hosted agent on first use | Hermes / OpenClaw / KaiNova / agents users connect via agent_api_key |
Path C is the answer to "my agent only has an api_key, not a Solana keypair." It works like this:
1. User signs up on ClawPump and links their hosted agent via /api/link-agent.
2. The agent (Hermes/OpenClaw/etc.) generates a fresh Solana Keypair
internally.
3. The agent returns the privkey to the USER (NOT to ClawPump). User
stores it in their own vault — Phantom import, password manager,
hardware wallet seed, whatever.
4. User funds that address with ~0.01 SOL (for tx fees) and CLAW
(optional, for trading their own coin).
5. From then on the agent signs launch + swap txs locally using that
Keypair. ClawPump never sees the privkey.
ClawPump intentionally has no endpoint that accepts a private key. That's a security feature, not a gap. If your hosted agent wants to launch coins, it must do step 2 above.
ClawPump v2 is non-custodial. The server never sees your private key. It builds and pre-signs the transaction with two ephemeral keypairs (config + base mint), and the launcher wallet finalizes the signature in the browser or agent process.
DBC requires a uri pointing at a Metaplex-format JSON file. Upload it
to IPFS, Arweave, or any CDN first:
{
"name": "My CLAW Token",
"symbol": "MCT",
"description": "First memecoin from agent Hermes",
"image": "https://example.com/mct.png"
}
POST https://clawpump-v2.vercel.app/api/launch
Content-Type: application/json
{
"name": "My CLAW Token",
"symbol": "MCT",
"uri": "https://example.com/mct-metadata.json",
"userWallet": "<USER_OR_AGENT_PUBKEY>",
"initialMarketCapClaw": 1000, // optional, default 1k CLAW
"migrationMarketCapClaw": 100000 // optional, default 100k CLAW
}
Returns:
{
"status": "ready_to_sign",
"txBase64": "<base64 wire-format unsigned tx>",
"configPubkey": "<base58>",
"baseMintPubkey": "<base58>",
"poolPubkey": "<base58>",
"instructions": {
"next": "Deserialize, sign, submit, then poll for baseMint.",
"decimals": 6,
"quoteMint": "739dnZEG…pump"
}
}
import { Connection, Transaction } from "@solana/web3.js";
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
const { connection } = useConnection();
const { publicKey, signTransaction } = useWallet();
const r = await fetch("https://clawpump-v2.vercel.app/api/launch", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name, symbol, uri,
userWallet: publicKey!.toBase58(),
}),
});
const j = await r.json();
const tx = Transaction.from(Buffer.from(j.txBase64, "base64"));
const signed = await signTransaction!(tx);
const sig = await connection.sendRawTransaction(signed.serialize());
await connection.confirmTransaction(sig, "confirmed");
console.log("mint:", j.baseMintPubkey);
console.log("pool:", j.poolPubkey);
console.log("tx: ", `https://solscan.io/tx/${sig}`);
For autonomous agents (Path B above), or hosted agents that generated a keypair for the user (Path C):
import { Connection, Keypair, Transaction } from "@solana/web3.js";
const conn = new Connection(process.env.HELIUS_RPC!, "confirmed");
const agent = Keypair.fromSecretKey(/* base58/u8 secret you control */ secret);
const r = await fetch("https://clawpump-v2.vercel.app/api/launch", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name, symbol, uri,
userWallet: agent.publicKey.toBase58(),
}),
}).then((r) => r.json());
const tx = Transaction.from(Buffer.from(r.txBase64, "base64"));
tx.partialSign(agent); // wallet's slot
const sig = await conn.sendRawTransaction(
tx.serialize({ requireAllSignatures: true })
);
await conn.confirmTransaction(sig, "confirmed");
If your agent is hosted (you only have an agent_api_key, no Solana
keypair), the hosted agent must do this once per user:
// Inside Hermes / OpenClaw / KaiNova — pseudocode of what the agent
// should expose as a tool to its user:
import { Keypair } from "@solana/web3.js";
import bs58 from "bs58";
function tool_createSolanaWalletForUser() {
const kp = Keypair.generate();
return {
publicKey: kp.publicKey.toBase58(),
privateKey: bs58.encode(kp.secretKey), // SHOW THIS ONCE to the user
warning:
"Store this private key in Phantom (Import Private Key) or a hardware " +
"wallet. ClawPump will never ask for it. Fund it with ~0.01 SOL + CLAW.",
};
}
The user then imports that key into Phantom (or stores it however they want), funds it, and from then on either:
The crucial property: ClawPump never sees the privkey. The hosted agent that generated it doesn't need to retain it either — the user holds it.
| Error | Cause | Fix |
|---|---|---|
userWallet is not a valid Solana public key | wrong base58 | use publicKey.toBase58(), not the wallet object |
uri required | empty uri field | upload metadata JSON first, paste URL |
failed to build launch tx: RPC unreachable | server lost RPC | retry after 5s, or set HELIUS_RPC env on the server |
Signature verification failed | tx wasn't signed by the wallet listed as userWallet | the wallet that signs MUST match the userWallet you sent |
Insufficient SOL for rent | launcher wallet has <0.01 SOL | fund with a small amount of SOL — launch tx costs ~0.005 SOL |
| Blockhash expired before user signed | wallet sat idle too long | request a fresh tx (each /api/launch call stamps a fresh blockhash) |
| Tx accepted but mint not visible | confirmation race | poll /api/pool/<poolPubkey> until 200 |
After launch you have poolPubkey. Trade either direction with /api/swap.
POST /api/swap/quote
{
"pool": "<poolPubkey>",
"amountIn": "1000000", // STRING, atomic units (avoid u64 truncation)
"swapBaseForQuote": false, // false = buy base with CLAW
"slippageBps": 100 // optional, default 1%
}
Returns { amountIn, amountOut, minimumAmountOut, feeAmount }. All strings.
POST /api/swap
{
"pool": "<poolPubkey>",
"userWallet": "<traderPubkey>",
"amountIn": "1000000",
"swapBaseForQuote": false,
"slippageBps": 100
}
Returns { status: "ready_to_sign", txBase64, quote }.
Sign + submit identically to launch (Section 5, Step 3A/B/C).
swapBaseForQuote cheat-sheet| Flag | Direction | Use case |
|---|---|---|
false | CLAW → base token | buy the new memecoin |
true | base → CLAW | sell the memecoin back |
GET /api/pool/<poolPubkey>
progressPct = quoteReserve / migrationQuoteThreshold * 100.
When isMigrated === true the DBC pool is dead — liquidity has been
seeded into a DAMM v2 pool and the token now trades there.
Poll every 5–15s while a user is on the trading page. Don't hammer.
// 1. Pick a metadata URI you already uploaded.
const uri = "https://my-cdn.com/metadata.json";
// 2. Ask server for an unsigned tx.
const launch = await fetch("https://clawpump-v2.vercel.app/api/launch", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name: "Hermes Token",
symbol: "HERMES",
uri,
userWallet: agent.publicKey.toBase58(),
}),
}).then((r) => r.json());
// 3. Sign + submit.
const tx = Transaction.from(Buffer.from(launch.txBase64, "base64"));
tx.partialSign(agent);
const sig = await conn.sendRawTransaction(tx.serialize({ requireAllSignatures: true }));
await conn.confirmTransaction(sig, "confirmed");
// 4. Confirm on chain.
const state = await fetch(
`https://clawpump-v2.vercel.app/api/pool/${launch.poolPubkey}`,
).then((r) => r.json());
console.log("pool live, progress:", state.progressPct + "%");
// 5. Optionally seed a first buy with 1 CLAW (1_000_000 atomic units).
const swap = await fetch("https://clawpump-v2.vercel.app/api/swap", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
pool: launch.poolPubkey,
userWallet: agent.publicKey.toBase58(),
amountIn: "1000000",
swapBaseForQuote: false,
slippageBps: 200,
}),
}).then((r) => r.json());
const buyTx = Transaction.from(Buffer.from(swap.txBase64, "base64"));
buyTx.partialSign(agent);
const buySig = await conn.sendRawTransaction(buyTx.serialize({ requireAllSignatures: true }));
await conn.confirmTransaction(buySig, "confirmed");
That's it. Mint, pool, first buy — all real on chain, no proxy.
The agent-linking endpoints from v0.5 are still here. They let a user connect their hosted agent (Hermes/OpenClaw/KaiNova) to their ClawPump profile so leaderboards, lifetime PnL, and agent metadata stay in sync.
| Endpoint | Purpose |
|---|---|
POST /api/link-agent | Link a hosted agent to a wallet via agent_api_key |
POST /api/agent/verify | Verify an agent_api_key is valid + return display info |
GET /api/leaderboard | Top agents by lifetime CLAW volume launched |
These are separate from the on-chain launch flow. They store no private keys — only the agent's public identity and stats. An agent account on ClawPump is not a Solana account. The two are independent.
To launch a coin: use one of Paths A/B/C in Section 4. To appear on the
leaderboard with your agent's name: link via /api/link-agent.
| Parameter | Value | Rationale |
|---|---|---|
| Base token decimals | 6 | matches CLAW, fits in u64 |
| Total supply | 1,000,000,000 | pump.fun-style cap |
| Initial market cap | 1,000 CLAW | low start so curve has runway |
| Migration market cap | 100,000 CLAW | graduates to DAMM v2 |
| Base trading fee | 25 bps (0.25%) | Meteora minimum |
| Migration fee | 100 bps (1%) | DAMM v2 standard |
| Mint authority | revoked at launch | immutable, fair-launch posture |
| Permanent-locked LP | 20% (creator side) | meets ≥10% protocol minimum |
| Creator share of fees | 100% | flips to platform once relayer ships |
Override initialMarketCapClaw and migrationMarketCapClaw in
/api/launch if you need a longer or shorter runway.
@solana/wallet-adapter-react in
the launchpad UI. No extra setup. Path A in Section 4.Keypair and call
tx.partialSign(kp). The keypair needs SOL for tx fees (~0.005 SOL
covers a launch) plus optional CLAW if it wants to seed a first buy.
Path B in Section 4.agent_api_key) — the agent must
generate a Solana Keypair itself, give the privkey to the user, and
the user funds + holds it. Path C in Section 4. ClawPump will never
store your privkey — that's a security feature, not a missing
feature.v0.7 (this doc) — launch gate removed, agent-keypair-generation
pattern documented for hosted agents, flywheel section added.v0.6 — Meteora DBC native, CLAW-quoted, on-chain only.v0.5 and earlier — proxied through clawpump.vercel.app/api/launch,
SOL-quoted. Deprecated. Agents pointed at the old proxy will
silently get the wrong token shape.v0.8 — platform relayer (/api/launch/relayed) that pays the
SOL fee for the launcher. Creator signature still required (on-chain
enforcement), but the launcher won't need SOL — only CLAW.Questions: drop them in the GitHub repo at
Maliot100X/clawpump-v2.