# How a launch works

A Koine launch is a presale vault where every depositor pays the same price, a 65-minute wait, a trading fee that falls from 99% to about 1% over 100 seconds, and a 24-hour unlock of presale tokens. This page walks through it in order, with the exact times and numbers from the code.

Koine is preparing for its public launch on Solana mainnet. Everything below describes the code in this repository.

## What does the timeline look like?

All times are measured from the pool's activation time, called "open" here. The server stores each one per coin (`presale_end`, `activation`, `unlock_start`, `unlock_end`) and returns them from `GET /api/launches/<mint>` as `times`.

| When | What happens |
|---|---|
| Creation | The keeper creates the token, the pool and the presale vault. Deposits open. |
| Creation + 90 s + presale length | Presale ends. Deposits and withdrawals close. |
| Open − 3,900 s (65 min) | Same moment as the presale end. |
| Open − 3,595 s (59 min 55 s) | The vault buy becomes possible. The keeper runs it on its next tick. |
| Open − 3,535 s | If the vault still hasn't bought and holds deposits, the coin page offers anyone a button to run it. |
| Open − 900 s (15 min) | If the vault still hasn't bought, the operator gets an alert. |
| Open | Trading starts. The fee is 99%. |
| Open + 100 s | The fee reaches its floor, about 1%. Presale tokens start unlocking. The keeper claims the "spike" fees: 75% for buyback and burn, 25% to Koine. |
| Open + 100 s + 24 h | Presale tokens are fully unlocked. |
| Open + 100 s + 168 h (7 days) | The buyback of the spike fees' 75% is spread up to this point. |

The shortest possible launch takes 90 s + 5 min + 65 min = 71.5 minutes from creation to open.

Source: `app/server/launch.ts` (`createLaunch`), `app/server/config.ts` (`RULES.createMarginSeconds`, `RULES.protocolGapSeconds`, `RULES.spikeSeconds`, `RULES.unlockSeconds`, `RULES.buybackHours`), `app/server/keeper.ts` (`CRANK_OPENS`), `app/web/src/Trade.tsx` (`stuck`).

## Step 1: How does a creator launch a coin?

The creator fills in a form at `/create`:

- name: required, up to 32 characters;
- ticker: 1 to 10 letters or digits (a leading `$` is allowed and dropped);
- description: required, up to 500 characters;
- image: required, an `https://` URL (no upload yet);
- an X link (a tweet or profile URL) or a website, at least one;
- presale length: 5 minutes to 7 days (10,080 minutes). The form offers 5 min, 30 min, 1 hour, 6 hours, 1 day, 3 days and 7 days.

The server then checks the duplicate rules. A coin can't reuse the ticker, name, tweet or website of any earlier Koine launch. Matching ignores case, a leading `$`, spaces, punctuation, accents and look-alike characters (for example Cyrillic `а` and Latin `a`, or `0` and `o`). Tweets match by status ID, so `x.com` and `twitter.com` links are the same. Websites match by host and path, without `www`, protocol, query or trailing slash. These rules apply only on Koine. Anyone can still create a token with the same name elsewhere on Solana.

If the form passes, the server keeps a draft for 15 minutes. The launch fee (0.25 SOL by default; the operator sets it with `LAUNCH_FEE_SOL`) is paid from the creator's Koine wallet, the one they fund and trade from: the page shows how much SOL that needs, and launching waits until the wallet has it. The trading service signs one transaction that sends exactly the fee to the Koine treasury with a one-time memo `koine:launch:<nonce>`; that wallet's signing rules allow nothing else to the treasury (see [Security](https://docs.koine.markets/terminal/security#signing-rules)). The Koine wallet becomes the coin's steward. The server checks that the fee transaction is confirmed, came from the creator, paid the treasury at least the fee, carries the memo, and wasn't used before. If the payment is slow to show, pressing **Try again** waits for that same payment; it's never paid twice for one draft.

The creator gets no free tokens. To hold any, they deposit in the presale like everyone else or buy after open.

Source: `app/server/rules.ts` (`validate`, `normalize`, `normalizeTweet`, `normalizeSite`), `app/server/launch.ts` (`prepareLaunch`, `checkFee`, `notePaid`), `app/server/http.ts` (`/api/launches`), `trade/server/launchfee.ts` (`payLaunchFee`), `trade/server/policy.ts` (`launchFeeRules`), `app/server/store.ts` (`duplicates`), `app/server/config.ts` (`RULES.launchFeeSol`, `RULES.presaleMinMinutes`, `RULES.presaleMaxMinutes`), `app/web/src/Create.tsx` (`LENGTHS`).

## Step 2: What does the keeper create on chain?

After the fee is confirmed, the keeper (Koine's server wallet) runs these transactions:

1. **The token.** A classic SPL token (not Token-2022) with 6 decimals. Its address ends in `koin`; the server grinds these addresses ahead of time. The keeper is mint authority only long enough to mint the supply. No freeze authority is ever set.
2. **The metadata.** A Metaplex metadata account with the name (up to 32 characters), the ticker (up to 10) and a URI of `<site>/meta/<mint>.json`. It is created with `isMutable: false`, so nobody can change the name, ticker or URI later. The JSON at that URI is served by Koine's server and can change (see [trust.md](https://docs.koine.markets/launchpad/trust)).
3. **The supply.** Exactly 1,000,000,000 tokens are minted to the keeper. Then the mint authority is set to none, so no more can ever be minted.
4. **The pool.** A Meteora DAMM v2 pool with all 1,000,000,000 tokens and 0 SOL. Its starting price puts the market cap at 120 SOL, so one token starts at 120 / 1,000,000,000 = 0.00000012 SOL. The liquidity covers every price from there up to the maximum, and it is permanently locked in the same transaction (`isLockLiquidity: true`). The pool has an Alpha Vault attached, takes every fee in SOL, and opens at a fixed timestamp.
5. **The vault.** A Meteora Alpha Vault in Pro Rata mode, open to anyone, with no escrow fee. Its buying cap is 1,000,000 SOL, so in practice every deposit is used.

Source: `app/server/launch.ts` (`createLaunch`), `app/server/config.ts` (`RULES.supply`, `RULES.decimals`, `RULES.startMcapSol`), `app/server/vanity.ts`.

## Step 3: How does the presale work?

From creation until the presale ends, anyone can deposit SOL into the vault, and withdraw any amount of it again. Deposits and withdrawals go straight to Meteora's Alpha Vault program. Koine never holds them.

There is no minimum raise. The coin opens with whatever was deposited, even nothing.

Everyone pays the same price. When the vault buys, each depositor's tokens are:

> your tokens = tokens the vault bought × your deposit ÷ all deposits

So depositing first or last makes no difference, and splitting a deposit across wallets gets nothing extra.

On koine.markets you deposit and withdraw from your Koine wallet, the custodial wallet the terminal trades from: the trade drawer sends it through the trading service, with no wallet popup, and the trading service checks every instruction of the launchpad's transaction before signing (see [presales](https://docs.koine.markets/terminal/presales)). The vault sees that wallet as the depositor. Claims and refunds go back to it.

There is no per-wallet cap. One wallet can deposit most of the vault. During the presale, the coin page shows the largest depositor's share of the vault (once there are two depositors or more), and the launch list at `/explore` marks any presale with more than one depositor where one wallet holds 30% or more of the vault.

Source: `app/web/src/Trade.tsx` (`PresalePanel`, `runKoine`), `trade/server/web.ts` (`/web/presale/*`), `trade/server/presale.ts` (`presaleAction`, `checkPresaleTx`), `app/server/tx.ts` (`depositTx`, `withdrawTx`, `stageOf`), `app/server/launch.ts` (vault creation: `WhitelistMode.Permissionless`, `maxBuyingCap`, `escrowFee`), `app/server/http.ts` (`largestPct`), `app/server/tx.ts` (`largestPct`), `app/web/src/explore/Screener.tsx` (`topPct`), `app/web/src/Coin.tsx` (Largest depositor).

## Step 4: What happens in the 65-minute wait?

When the presale ends, deposits close and nobody can trade. Before its open time the pool rejects every swap, including Koine's. The only exception is the vault's own buy.

The 65 minutes come from Meteora. Its pools require deposits to close at least 3,900 seconds before trading opens.

About an hour before open, the vault makes one buy with all deposits. The keeper does this as soon as it can (3,595 s before open), and keeps trying. Anyone can run it on chain (Meteora's vault allows it), but the site connects no wallet to do it: if the vault hasn't bought 60 seconds into the window, the trade drawer says so.

The buy pays the pool's fee floor (about 1%), not the 99% open fee. `launch-check.ts` shows the fee each vault buy paid (`vault-buy`, see [verify.md](https://docs.koine.markets/launchpad/verify#the-presale-vault)).

After the buy, the presale price is final and public. The coin page shows your own allocation.

If nobody runs the buy before open, depositors take their SOL back: from the open time, the coin page offers "Withdraw my SOL" (the vault's `withdrawRemainingQuote`). The pool still opens and trades without the presale buy.

Source: `app/server/keeper.ts` (`crank`, `CRANK_OPENS`), `app/server/tx.ts` (`crankTx`, `refundTx`), `app/server/config.ts` (`RULES.protocolGapSeconds`), `app/web/src/Trade.tsx` (`RevealPanel`, `ClaimPanel`), `app/scripts/launch-check.ts`.

## How much of the supply does the presale buy?

The pool holds only tokens at the start, along a constant-product curve whose starting market cap is 120 SOL. A vault buy of D SOL, after the ~1% fee (D' = 0.99 × D), gets:

> share of supply = D' ÷ (D' + 120)

and moves the market cap to 120 × (1 + D' ÷ 120)².

| Deposits (SOL) | Share of supply bought | Tokens | Market cap at the average presale price (SOL) | Market cap right after the buy (SOL) |
|---|---|---|---|---|
| 1 | 0.82% | 8,182,494 | 122.2 | 122.0 |
| 10 | 7.62% | 76,212,471 | 131.2 | 140.6 |
| 30 | 19.84% | 198,396,794 | 151.2 | 186.8 |
| 120 | 49.75% | 497,487,437 | 241.2 | 475.2 |

These are worked from the formula, ignoring rounding.

Source: `app/server/config.ts` (`RULES.startMcapSol`), `app/server/launch.ts` (`sqrtMinPrice`, `MAX_SQRT_PRICE`).

## Step 5: How does the fee fall at open?

At open the pool's fee is 99%. It falls every second by a fixed factor until it reaches its floor at 100 seconds:

> fee(t) = 99% × (1 − r)^t, with r = 1 − (1 ÷ 99)^(1/100) ≈ 4.49%

So the fee halves about every 15 s (ln 2 ÷ −ln(1 − r) ≈ 15.08 s):

| Seconds after open | Fee |
|---|---|
| 0 | 99% |
| 5 | 78.7% |
| 15 | 49.7% |
| 30 | 24.9% |
| 60 | 6.3% |
| 90 | 1.6% |
| 100 and later | about 1% |

The fee is set in the pool at creation (`startingFeeBps: 9900`, `endingFeeBps: 100`, `numberOfPeriod: 100`, `totalDuration: 100`, exponential mode). Koine can't change it afterwards.

Buyers in the first seconds pay a large share of their SOL in fees. On Koine's site, any buy or sell while the fee is above 10% asks for confirmation first. Other apps that route to the pool (aggregators, terminals) may not warn. Presale depositors don't pay this fee.

Source: `app/server/config.ts` (`RULES.fee`, `RULES.spikeSeconds`), `app/server/tx.ts` (`feeAt`), `app/web/src/Trade.tsx` (the `high` confirmation).

## Step 6: How do presale tokens unlock?

Presale tokens unlock in a straight line, starting when the fee reaches its floor (open + 100 s) and ending 24 hours later (86,400 s). There is no cliff. Halfway through, half is claimable. Depositors claim whenever they like, as often as they like.

The unlock length is set per coin in its vault at creation. The default is 86,400 s and the operator can change it for future launches with `UNLOCK_SECONDS`. Each coin's own unlock times are on its page and in the API (`times.unlockStart`, `times.unlockEnd`).

Source: `app/server/launch.ts` (`startVestingPoint`, `endVestingPoint`), `app/server/config.ts` (`RULES.unlockSeconds`), `app/server/tx.ts` (`claimTx`).

## Step 7: What does the keeper do after open?

The keeper is a loop on Koine's server that runs every 10 seconds. For each coin it:

1. runs the vault buy in the hour before open;
2. at open + 100 s, claims every fee earned so far (the "spike" fees) into the buyback wallet, and pays 25% of them to Koine's treasury;
3. every hour after that, claims the pool's fees and splits them 40% steward, 20% buyback, 40% platform (see [fees.md](https://docs.koine.markets/launchpad/fees) and [creator-share.md](https://docs.koine.markets/launchpad/creator-share));
4. every hour, spends part of the buyback budget buying the coin and burns what it buys;
5. closes takeover votes when they end.

Each action is added to the coin's public log. The coin's receipt ([receipt.md](https://docs.koine.markets/launchpad/receipt)) adds it up with every swap in the pool. The log keeps every entry. The coin page shows the latest few and links to the full log, which `GET /api/launches/<mint>/log` returns 100 entries at a time (up to 500 with `limit`); pass a page's `before` value to get the page before it.

If the server is down, claims and buybacks catch up when it restarts. The vault buy can't: it must happen before open, which is why anyone can run it.

Source: `app/server/keeper.ts` (`tick`, `crank`, `claimSpike`, `claimFees`, `buyback`, `votes`), `app/server/store.ts` (`appendLog`, `logPage`), `app/server/http.ts`, `app/server/receipt.ts`.
