# launch:create-launch — Ammora SDK 0.3.8 Launch a token on a registered config. npm run launch:create-launch -- [decimals] The config decides the curve, the fees and what happens at graduation; this only names the token. Read the config first with `launch:get-config`, because once a launch is created it follows that config for its whole life. [Read in Docs](https://docs.ammora.org/examples?command=launch%3Acreate-launch) · [Detailed guide](https://docs.ammora.org/guides/launchpad) · [Local setup](https://docs.ammora.org/guides/example-setup) ## Context and execution GIWA Sepolia 91342. Public SDK 0.3.8, Math 0.3.0. Source revision: `a9b3fd798fa51495e8defec99a25de59e4d70672`. Install the SDK in your app, or prepare the example project using the local setup guide for its npm commands. Review the entry source and guide for required arguments, roles and deployment selection. `AMMORA_SEND=0` does not turn send-only commands into previews. Never put CLI keys in a browser or resend an uncertain transaction. Command: `npm run launch:create-launch -- ` (`tsx src/launch/create-launch.ts`). Omit `--` and arguments when the source accepts none. ## Entry file: `src/launch/create-launch.ts` ```typescript /** * Launch a token on a registered config. * * npm run launch:create-launch -- [decimals] * * The config decides the curve, the fees and what happens at graduation; this only names * the token. Read the config first with `launch:get-config`, because once a launch is created it * follows that config for its whole life. */ import { buildCreateAmmoraV4Launch, getAmmoraV4ConfigAtBlock, parseAmmoraV4LaunchCreatedReceipt, verifyAmmoraV4CoreAtBlock, } from "@ammora-protocol/sdk"; import { integer, rawAmount } from "../shared/input.js"; import { readBlock, reader, signer, v4Deployment } from "../shared/env.js"; import { main, send } from "../shared/run.js"; main(async () => { const [idArgument, name, symbol, metadataURI, decimalsArgument] = process.argv.slice(2); if (!idArgument || !name || !symbol || !metadataURI) { throw new Error("usage: [decimals]"); } if (!/^\d+$/.test(idArgument)) throw new Error("config id must be a positive integer"); const configId = rawAmount(idArgument, "config id"); // The curve stores balances in this many decimals; the contract accepts 6 to 9. const { wallet, account } = signer(); const client = await reader(); const contracts = v4Deployment().contracts.launch; const { number: snapshotBlock } = await readBlock(client); await verifyAmmoraV4CoreAtBlock(client, { configRegistry: contracts.configRegistry, launchFactory: contracts.factory, graduationAdapter: contracts.graduationAdapter, feePolicy: contracts.feePolicy, }, snapshotBlock); const entry = await getAmmoraV4ConfigAtBlock( client, contracts.configRegistry, configId, snapshotBlock, ); const tokenDecimals = integer(decimalsArgument ?? String(entry.config.tokenDecimals), "decimals", 6, 9); if (tokenDecimals !== entry.config.tokenDecimals) throw new Error("decimals must match the selected immutable Config"); if (!entry.enabled) throw new Error(`config #${configId} is disabled, so it cannot be launched on`); const transaction = buildCreateAmmoraV4Launch({ name, symbol, metadataURI, creatorMetadataURI: metadataURI, tokenDecimals, }, configId, entry.config.poolCreationFee); console.log(`factory ${contracts.factory}`); console.log(`config #${configId} (${entry.segments.length} segment(s))`); console.log(`token ${name} (${symbol}), ${tokenDecimals} decimals`); console.log(`fee ${transaction.value ?? 0n} wei`); console.log(""); const hash = await send( "createLaunch", { to: contracts.factory, ...transaction }, wallet, account, client, ); // The receipt is canonical. Do not infer token or curve addresses from an unconfirmed // latest-state read because public RPCs can lag immediately after a write. const receipt = await client.getTransactionReceipt({ hash }); const created = parseAmmoraV4LaunchCreatedReceipt(receipt, contracts.factory); if (created.configId !== configId || created.configHash !== entry.configHash) { throw new Error("V4 launch receipt does not match the selected immutable Config"); } console.log(""); console.log(`token ${created.token}`); console.log(`curve ${created.curve}`); console.log(`version ${created.protocolVersion}`); console.log(`block ${receipt.blockNumber}`); }); ``` ## Supporting files Keep relative paths intact. Local imports are listed recursively; JSON templates are choices to review, not approved inputs. Runtime-selected files and wallet/environment setup still follow the detailed guide. - [src/shared/env.ts](https://docs.ammora.org/examples/source/src/shared/env.ts.txt) - [src/shared/input.ts](https://docs.ammora.org/examples/source/src/shared/input.ts.txt) - [src/shared/retry.ts](https://docs.ammora.org/examples/source/src/shared/retry.ts.txt) - [src/shared/rpc.ts](https://docs.ammora.org/examples/source/src/shared/rpc.ts.txt) - [src/shared/run.ts](https://docs.ammora.org/examples/source/src/shared/run.ts.txt) - [src/launch/config-document.example.json](https://docs.ammora.org/examples/source/src/launch/config-document.example.json.txt) - [src/launch/team/fees.example.json](https://docs.ammora.org/examples/source/src/launch/team/fees.example.json.txt) - [src/launch/team/recipients.example.json](https://docs.ammora.org/examples/source/src/launch/team/recipients.example.json.txt) - [package.json](https://docs.ammora.org/examples/source/package.json.txt) - [package-lock.json](https://docs.ammora.org/examples/source/package-lock.json.txt) - [tsconfig.json](https://docs.ammora.org/examples/source/tsconfig.json.txt) - [.env.giwa.example](https://docs.ammora.org/examples/source/file.env.giwa.example.txt) - [.nvmrc](https://docs.ammora.org/examples/source/file.nvmrc.txt) ## AI implementation checklist Use the actual SDK exports and parameter types in the linked files. Start with reads and unsigned plans where supported. Use a connected wallet for browser signing. Preserve raw integer units, exact approvals, caller authority, deadlines and receipt reconciliation. Report local checks separately from live-chain verification.