> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inkyswap.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Launchpad Quickstart

> Create an InkyPump launch from a partner app, prove the receipt, and wait for API discovery.

This is the supported first integration for launchpads such as Fomo: create a native-quoted token with the user's connected wallet, prove the result from the transaction receipt, then poll the read API until the indexer publishes it.

<Note>
  Verified against production on September 21, 2026. Fetch [Capabilities](/api-reference/inkypump/capabilities) at runtime. Do not copy a hook address from an old guide.
</Note>

## The whole flow

1. Your server fetches the active deployment for the selected chain.
2. The user's wallet simulates and signs `createLaunch` on that exact hook.
3. Your app records the transaction hash before it waits for a receipt.
4. Your app accepts the launch only after it decodes one valid `LaunchCreated` event from that hook.
5. Your server polls `GET /api/token` until the token is indexed.

The caller becomes the creator and fee recipient. Let the creator's wallet call the hook directly. If your backend or a wrapper contract submits the transaction, that address becomes the creator.

## 1. Resolve the current deployment

Call this from your server. InkyPump read APIs do not currently promise cross-origin browser access.

```ts theme={null}
const chainId = 57073

const response = await fetch(
  `https://inkypump.com/api/capabilities?chainId=${chainId}`,
  { cache: "no-store" },
)

if (!response.ok) throw new Error(`Capabilities failed: ${response.status}`)

const capabilities = await response.json()
if (!capabilities.flags.create) throw new Error("Creation is disabled")

const deployment = capabilities.activeCreationDeployment
if (!deployment || deployment.status !== "active") {
  throw new Error("No active creation deployment")
}

// Send only this allowlisted data to your browser.
const launchConfig = {
  chainId: capabilities.chainId,
  releaseCommit: capabilities.releaseCommit,
  hook: deployment.hook,
  hookRuntimeHash: deployment.hookRuntimeHash,
}
```

Use chain `57073` for Ink or `4663` for Robinhood. Always send `chainId`; never rely on a default.

## 2. Use the creation ABI

```ts theme={null}
export const CREATE_LAUNCH_ABI = [
  {
    type: "function",
    name: "createLaunch",
    stateMutability: "payable",
    inputs: [
      {
        name: "params",
        type: "tuple",
        components: [
          { name: "name", type: "string" },
          { name: "ticker", type: "string" },
          { name: "description", type: "string" },
          { name: "imageUrl", type: "string" },
          { name: "telegram", type: "string" },
          { name: "twitter", type: "string" },
          { name: "website", type: "string" },
          { name: "creatorFeeSplitBps", type: "uint16" },
          { name: "gainBps", type: "uint32" },
          { name: "targetRaise", type: "uint96" },
          { name: "antiSnipeDuration", type: "uint32" },
          { name: "startTime", type: "uint64" },
        ],
      },
    ],
    outputs: [{ name: "launchId", type: "uint256" }],
  },
  {
    type: "event",
    name: "LaunchCreated",
    anonymous: false,
    inputs: [
      { name: "launchId", type: "uint256", indexed: true },
      { name: "creator", type: "address", indexed: true },
      { name: "token", type: "address", indexed: false },
      { name: "targetRaise", type: "uint96", indexed: false },
    ],
  },
] as const
```

## 3. Simulate, sign, and prove the receipt

This browser example uses [viem](https://viem.sh/) and an injected wallet.

```ts theme={null}
import {
  createPublicClient,
  createWalletClient,
  custom,
  http,
  isAddressEqual,
  keccak256,
  parseEther,
  parseEventLogs,
} from "viem"

const chains = {
  57073: {
    id: 57073,
    name: "Ink",
    nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
    rpcUrls: { default: { http: ["https://rpc-gel.inkonchain.com"] } },
  },
  4663: {
    id: 4663,
    name: "Robinhood Chain",
    nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
    rpcUrls: {
      default: { http: ["https://rpc.mainnet.chain.robinhood.com"] },
    },
  },
} as const

const chain = chains[launchConfig.chainId as keyof typeof chains]
if (!chain || chain.id !== launchConfig.chainId) {
  throw new Error("Unsupported or mismatched capability chain")
}

const publicClient = createPublicClient({ chain, transport: http() })
const walletClient = createWalletClient({
  chain,
  transport: custom(window.ethereum),
})

if ((await publicClient.getChainId()) !== chain.id) {
  throw new Error("RPC returned the wrong chain")
}
if ((await walletClient.getChainId()) !== chain.id) {
  throw new Error("Connect the wallet to the selected chain")
}

const [account] = await walletClient.requestAddresses()
const hook = launchConfig.hook as `0x${string}`

const code = await publicClient.getCode({ address: hook })
if (!code || code === "0x") throw new Error("Creation hook has no code")
if (keccak256(code).toLowerCase() !== launchConfig.hookRuntimeHash.toLowerCase()) {
  throw new Error("Creation hook does not match the published runtime")
}

const params = {
  name: "My Token",
  ticker: "MINE",
  description: "Created through my launchpad",
  imageUrl: "https://cdn.example.com/mine.png",
  telegram: "",
  twitter: "",
  website: "",
  creatorFeeSplitBps: 5_000,
  gainBps: 50_000,
  targetRaise: parseEther("1"),
  antiSnipeDuration: 0,
  startTime: 0n,
} as const

const prebuy = 0n // Set a native amount, such as parseEther("0.01"), if wanted.

const { request } = await publicClient.simulateContract({
  account,
  address: hook,
  abi: CREATE_LAUNCH_ABI,
  functionName: "createLaunch",
  args: [params],
  value: prebuy,
})

const transactionHash = await walletClient.writeContract(request)

// Save transactionHash now. A page reload must resume this transaction, not send a new one.
const receipt = await publicClient.waitForTransactionReceipt({
  hash: transactionHash,
  confirmations: 1,
})
if (receipt.status !== "success") throw new Error("Launch reverted")

const created = parseEventLogs({
  abi: CREATE_LAUNCH_ABI,
  eventName: "LaunchCreated",
  logs: receipt.logs,
}).filter((log) => isAddressEqual(log.address, hook))

if (created.length !== 1) throw new Error("Expected one LaunchCreated event")

const launch = created[0].args
if (!isAddressEqual(launch.creator, account)) {
  throw new Error("Receipt creator does not match the connected wallet")
}
if (launch.targetRaise !== params.targetRaise) {
  throw new Error("Receipt target does not match the signed launch")
}

const result = {
  chainId: chain.id,
  hook,
  launchId: launch.launchId,
  tokenAddress: launch.token,
  transactionHash,
}
```

Persist all five identity fields. A token address without its chain, hook, and launch ID is not enough to route future reads and trades safely.

## 4. Wait for discovery

The receipt is the launch truth. The API is an indexed view and may appear shortly after the receipt.

```ts theme={null}
async function waitForToken(chainId: number, address: string) {
  const delays = [500, 1_000, 2_000, 4_000, 8_000]

  for (const delay of delays) {
    const response = await fetch(
      `https://inkypump.com/api/token?chainId=${chainId}&address=${address}`,
      { cache: "no-store" },
    )
    if (response.ok) return response.json()
    if (response.status !== 404) {
      throw new Error(`Token lookup failed: ${response.status}`)
    }
    await new Promise((resolve) => setTimeout(resolve, delay))
  }

  return null // Confirmed on-chain, still indexing. Do not resubmit the launch.
}
```

Run this on your server and return the result to your frontend. While it returns `null`, show **Confirmed — indexing** with the transaction link.

## 5. Link to the token

```ts theme={null}
const chainSlug = result.chainId === 57073 ? "ink" : "robinhood"
const tradeUrl = `https://inkypump.com/${chainSlug}/trade/${result.tokenAddress}`
```

## Native launch limits

| Field                | Current native rule                           |
| -------------------- | --------------------------------------------- |
| `targetRaise`        | 1 to 5 ETH                                    |
| `gainBps`            | 0 to 200,000                                  |
| `creatorFeeSplitBps` | 0 to 10,000                                   |
| `startTime`          | `0` for immediate, or a future Unix timestamp |
| `msg.value`          | Optional creator prebuy in native wei         |
| Total token supply   | 1,000,000,000 tokens with 18 decimals         |

Read contract limits from the selected deployment before exposing them in a long-lived client. For xStocks launches, the limits and units are per asset; use the [xStocks guide](/integrations/xstocks-launches).

## Do not do these things

* Do not hardcode the deprecated Ink hook `0x4cC8…6AC4` for new launches.
* Do not retry `createLaunch` because receipt waiting timed out. Resume by hash.
* Do not treat an API `404` just after confirmation as a failed launch.
* Do not submit from a shared backend wallet unless that wallet should own the creator fees.
* Do not guess a post-bond pool. Use `getLaunchPoolKey` on corrected/current hooks and complete indexed fields on `ink-legacy`, then validate the computed pool ID.
* Do not expose a private key in a browser or partner API.

<CardGroup cols={2}>
  <Card title="Deployments" icon="link" href="/integrations/networks-and-deployments">
    Runtime discovery, active hooks, and legacy routing.
  </Card>

  <Card title="Production checklist" icon="shield" href="/integrations/production-checklist">
    Failure cases and release gates before you ship.
  </Card>
</CardGroup>
