For the complete documentation index, see llms.txt. This page is also available as Markdown.

Auto-launch a token

End-to-end recipe for an agent that deploys a launchpad token, optionally buys at launch, and (optionally) attaches off-chain metadata so it shows up on kumbaya.xyz.

Prerequisites

  • An agent wallet with ETH on MegaETH mainnet for gas (and any initial buy).

  • A SIWE session if you want to attach off-chain metadata. See Sign in with Ethereum.

  • The launchpad contract addresses for your chain - see Contract Addresses.

Step 1: Mine the salt

FireLaunch.ignite() deploys via CREATE2, so the resulting token address is fully determined by (deployer, salt, init code, constructor args). The Kumbaya indexer requires the new token to be token0 (lower address than the numeraire). Mine until you find one:

import { getCreate2Address, keccak256, encodePacked } from 'viem'
import { randomBytes } from 'crypto'

const FIRE_LAUNCH = '0x69FE0908F1211dE66F7067021998f28A5693ABbD'  // mainnet
const WETH        = '0x4200000000000000000000000000000000000006'

// FireToken creation code hash - read once from a deployed FireToken or compute from its bytecode.
// Trust this from the launchpad repo's `forge build` output: keccak256(FireToken.creationCode + abi.encode(...constructorArgs))
function tokenAddrFor(salt: `0x${string}`): `0x${string}` {
  const initCodeHash = computeFireTokenInitCodeHash(/* args identical across launches */)
  return getCreate2Address({
    from: FIRE_LAUNCH,
    salt,
    bytecodeHash: initCodeHash,
  })
}

let salt: `0x${string}` | null = null
let tokenAddr: `0x${string}` | null = null

for (let i = 0; i < 10_000; i++) {
  const candidate = `0x${randomBytes(32).toString('hex')}` as `0x${string}`
  const addr = tokenAddrFor(candidate)
  if (BigInt(addr) < BigInt(WETH)) {
    salt = candidate
    tokenAddr = addr
    break
  }
}

if (!salt) throw new Error('salt mining exhausted - try more attempts')

The constructor args (name, symbol, supply, etc.) feed into the init code hash, so technically the search has to fix those before mining. The frontend uses up to 10,000 attempts without a vanity suffix and 1,000,000 with one. See Token ordering and tick math for the constraints.

Step 2: Call ignite

If the values you pass diverge from what FireRegistry requires (e.g. wrong feeTier, wrong vestingDuration range), the call reverts with a *Mismatch error. See Launching a token → Errors.

Step 3 (optional): Buy at launch

ignite() doesn't accept ETH, so the buy is a separate transaction immediately after.

⚠️ Not atomic with ignite. If the buy reverts (e.g. slippage), the token still deployed. Quote first if you care about the price.

Step 4 (optional): Attach off-chain metadata

If the agent wants its token to render with a description, image, and social links on kumbaya.xyz, attach metadata via the claim flow. If you use the on-chain MCP, the sign_token_claim tool builds and signs this exact proof for you (pass its output straight to app_post_tokens_by_mint_address_claim) - the raw viem below is for integrators not using the MCP:

You can optionally upload an image via POST /v1/tokens/{tokenAddr}/claim/image (multipart, JWT-authenticated).

Watching the launch lifecycle

After deployment, the token is on-chain, indexed, and tradeable. Track its state via:

  • FireLaunch.getLaunchState(token) - full per-launch state (creator, createdAt, graduationConditionMetAt, graduated, graduationFeeBps, isToken0, graduationTick, pool, etc.).

  • Hasura indexer - subscribe to FireToken(where: { address: { _eq: <addr-chainId> } }) for current-state changes; subscribe to Swap(where: { pool_id: { _eq: <pool-addr-chainId> } }) for trade activity.

Triggering graduation

When the price tick crosses the graduation threshold, FireGraduator.canGraduate(token) returns true. Anyone can then push graduation forward:

After graduation, post-grad fees flow via FireStream.claimFees(token) and creators (or anyone) can call it to sweep their share.

Common pitfalls

  • Salt mining mistake. If your token address ≥ numeraire, the bonding curve runs the wrong way and the indexer skips your launch. Always assert BigInt(tokenAddr) < BigInt(numeraire) before broadcasting.

  • Wrong feeTier / vestingDuration. FireRegistry enforces specific values. Read requiredFeeTier, requiredSkimBps, and the vesting bounds before constructing IgniteParams. See Live registry config.

  • Skipping the grace period. Only the guardian can graduate immediately. If your agent isn't the guardian, either wait gracePeriodDuration after recordGraduationCondition, or wait for forceGraduationDelay from createdAt which bypasses the grace check entirely. forceGraduationDelay is governance-set (currently ~180 days / 6 months; its floor is MIN_FORCE_GRADUATION_DELAY = 90 days) - read FireRegistry.forceGraduationDelay() rather than hardcoding a value.

  • Not parsing the receipt. If ignite() reverts after gas was paid, you have no token but you spent gas. Check receipt.status === 'success' before assuming success.

Where to next

Last updated