Koine docs

Verify a launch yourself

You don't have to trust Koine's site, server or database to know a launch followed its rules. One script reads the chain and prints PASS, FAIL or INFO for each rule. It needs only the coin's mint address and any Solana RPC.

Run it #

You need Node 22.18 or later and a copy of this repository.

cd app
npm install
node --env-file-if-exists=.env scripts/launch-check.ts <mint> --cluster mainnet

Options:

  • --cluster mainnet reads Solana mainnet. Keep it: without it, the script falls back to CLUSTER from .env, and then to a Solana test network.
  • --json out.json also saves every check, with the transaction links, as JSON.
  • --buyback <address> checks that the spike fees went to this exact buyback wallet. Without it, the checker reports where they went.
  • --split-from <ISO time> sets when the keeper started the current fee split. Claims before it are counted on the earlier split. The default is 2026-11-08 19:00 UTC.

For the RPC, set RPC_URL to any RPC address, or HELIUS_API_KEY to a Helius key. With neither, it uses Solana's public RPC, which is slow and rate-limits. The script never prints the RPC address or key.

It exits 0 when nothing failed, 1 when any check failed, and 2 when it couldn't finish (for example, the address isn't a mint).

If you use an AI assistant, point it at this page and the script, and ask it to run the command for your mint.

Source: app/scripts/launch-check.ts, app/package.json

What it reads #

It starts from the mint and finds everything else on chain:

  • the pool, at the address Meteora derives from the coin and SOL;
  • the launch position, from the transaction that created the pool;
  • the presale vault, which the pool records;
  • the keeper, which the pool records as its creator;
  • the buyback wallet, which received the spike-fee claim.

It never calls Koine's API and never reads Koine's launch database (koine.db). The expected values are copied from app/server/config.ts into the script, so you can compare the two files.

Source: app/scripts/launch-check.ts (EXPECTED), app/server/config.ts (RULES, FEES)

The coin #

Check What it proves
decimals The token has 6 decimals.
mint-authority Nobody can ever mint more. The mint authority is gone.
freeze-authority Nobody can freeze your tokens. The mint has no freeze authority.
metadata-immutable The name, ticker and link can never change.
metadata-match The metadata belongs to this mint: the ticker is in capitals and the link ends in /meta/<mint>.json.
supply All 1 billion tokens went into the pool in the transaction that created it. Nothing was kept back for a team or the creator.
supply-now The supply today is 1 billion minus what was burned. No extra tokens were ever minted.

Source: app/server/launch.ts (step 1), app/server/config.ts (RULES.supply, RULES.decimals)

The pool and its fee #

Check What it proves
pool A Meteora DAMM v2 pool pairs the coin with SOL.
fee-start The trading fee starts at 99% at open.
fee-schedule The fee falls on an exponential schedule with the parameters in config: 100 steps of 1 second. The output shows the fee at +0, +10, +30, +60 and +100 seconds.
fee-end The fee reaches 1% at open + 100 s and stays there.
pool-config The pool opens at a fixed time, collects fees in SOL only, and has no dynamic fee.
start-mcap The pool's starting price is a 120 SOL market cap, over the full price range.
activation INFO: when trading opened and when the fee reached its floor.

The fee schedule lives in the pool account, and Meteora's program applies it. Koine can't change it after the pool exists.

Source: app/server/launch.ts (step 2), app/server/config.ts (RULES.fee, RULES.startMcapSol, RULES.spikeSeconds)

The lock #

Check What it proves
lock The launch liquidity is permanently locked, in the same transaction that created the pool. None of it is unlocked or vesting.
pool-liquidity All of the pool's liquidity is locked. If someone else adds their own liquidity later, this turns INFO.
position-nft INFO: who holds the position NFT. The holder can claim trading fees. It can never withdraw the locked liquidity.

The holder is the keeper at first. With Squads custody on, the keeper moves the NFT to the Squads multisig after the spike claim.

Source: app/server/launch.ts (step 2, isLockLiquidity), app/server/squads.ts (moveNft)

The presale vault #

Check What it proves
vault-config The vault is Pro Rata, open to anyone, charges no escrow fee and belongs to this pool.
deposit-close Deposits closed 65 minutes before open.
presale-length The presale lasted between 5 minutes and 7 days, counted from the pool's creation.
unlock-start Presale tokens start to unlock at the fee floor, open + 100 s.
unlock-length They unlock evenly over 24 hours.
vault-buy The vault bought with every SOL deposited, in the hour before open. The output shows when, who ran it, the fee it paid and the presale price.

If nothing was deposited, vault-buy is INFO. If SOL was deposited and nobody ran the buy before open, it fails and shows how much depositors got back.

Source: app/server/launch.ts (step 3), app/server/keeper.ts (crank), app/server/config.ts (RULES.protocolGapSeconds, RULES.unlockSeconds)

Fees and buybacks #

Check What it proves
spike-claim The fees from the 99% → 1% spike were claimed at or after the fee floor, and all of them reached the buyback wallet. The note shows the 25% owed from there to Koine's treasury.
buyback-wallet The wallet that received the spike fees. With --buyback, PASS or FAIL against the address you gave.
fee-claims INFO: every later claim, how much it held, and where it went.
split INFO: what 40% steward, 20% buyback and 40% platform comes to on those claims.
buyback-burns The buyback wallet bought this coin on this pool, and burned every token it bought.
buyback-budget Buyback spending stays within 75% of the spike fees plus the buyback share of later fees. That share is 20%, or up to 60% when the steward's 40% is forfeited. From an hour after the 7-day window ends, it also checks that at least 75% of the spike fees plus the 20% share were spent.

Claims before 2026-11-08 19:00 UTC ran on the earlier split: spike fees all to buyback, later fees 40% steward / 30% buyback / 30% platform. The checker counts those claims that way and says so in the notes. --split-from <ISO time> moves that cutoff, if the keeper started the new split at another time.

Claim amounts come from the pool program's own claim events, not from balance changes. If the spike claim moved more SOL than the fees in it, the output says so. For later claims it shows the fees and what the receivers got, in total and per claim in the JSON.

Each coin's receipt gives the same story from Koine's side: every swap in the pool, what the spike collected, and the buybacks. The checker and Koine's swap indexer decode the pool's events with the same code (app/server/damm.ts), and every receipt number names its transactions, so you can check any of them here or on an explorer.

Source: app/server/keeper.ts (claimToBuyback, claimSpike, claimFees, buyback), app/server/config.ts (FEES, RULES.buybackHours), app/server/damm.ts

What the chain alone can't prove #

The checker lists the first five in its output instead of guessing. These parts depend on Koine:

  • The 40/20/40 split per hour. Whether the steward earned their 40% in a given hour depends on checks Koine runs off chain: the 1% bond over time, an update on the coin's page in the previous 72 hours, and holder flags. So the checker shows what the split would be, not whether each hour was right.
  • Payouts. The steward's claims and the platform's share leave the buyback wallet as plain SOL transfers. They carry no reference to the coin, so they can't be matched to one launch.
  • Who launched it. The launch fee carries a one-time memo, not the mint. Nothing on chain ties the creator to the coin.
  • Votes, flags, nominations and handovers. These are account actions Koine stores. They are not transactions.
  • The coin page. The description, image and links sit behind the metadata link on Koine's server. Only the link itself is on chain.
  • Which code Koine runs. The checker shows what happened, not what the server will do next.

Source: app/scripts/launch-check.ts (notDerivable), app/server/steward.ts, app/server/launch.ts (prepareLaunch)