Documentation
How NinetiqPad works
What the launch program does, the arithmetic it uses, what is deployed where, and what it does not do. Everything here describes the code in this release.
What NinetiqPad does
NinetiqPad runs one kind of token launch on Solana: a capped, fixed-price sale of an SPL token for SOL. A creator publishes the terms, deposits the tokens for sale into an escrow that belongs to that launch alone, and opens a contribution window. Participants send SOL into the launch’s SOL escrow. When the window closes, or the hard cap is reached, the launch is settled: if the soft cap was met participants claim their tokens and the creator withdraws the SOL; if not, participants take their SOL back.
Every rule in that paragraph is enforced by a program on Solana, not by this website. The website reads the program’s accounts and builds transactions for a wallet to sign.
An escrow controls how assets can be released. It does not guarantee a token’s future value.
How a sale works
A launch moves through a small, fixed set of states:
Draft → Active → Successful or Failed · Draft → Cancelled
| State | What can happen |
|---|---|
| Draft | The creator deposits the sale inventory, then opens the launch or cancels it. Nobody can contribute. |
| Active | Inside the window, anyone can contribute. The terms cannot change and the creator cannot cancel or withdraw anything. |
| Successful | Each participant claims their tokens once. The creator withdraws the proceeds once and recovers unsold tokens once. |
| Failed | Each participant is refunded their contribution once. The creator recovers the whole inventory. No fee is charged. |
| Cancelled | Reached only from Draft. The creator recovers any deposited inventory. Nothing was ever contributed. |
Before a launch can open, all of the following must be true, and the program checks each one:
- The whole sale inventory is in the launch’s token escrow. The amount is computed by the program (see Allocation and rounding), so the escrow can be neither short nor over-filled.
- The token’s mint authority is revoked, so the supply can never grow.
- The token’s freeze authority is revoked, so no holder’s tokens can be frozen.
- The token belongs to the original SPL Token program. Token-2022 mints are refused, because transfer fees, transfer hooks or a permanent delegate would break the escrow’s accounting.
- The contribution window lies in the future, is within the length bounds of the program’s configuration, and opens at most 90 days ahead.
Contributions are accepted only while the launch is Active and the cluster clock is inside the window. A contribution must be at least the launch minimum, unless it is exactly the capacity that remains. A contribution larger than the remaining capacity is refused as a whole: it is never trimmed, and nothing is taken from the wallet.
Allocation and rounding
Amounts are integers everywhere: SOL in lamports (1 SOL = 1,000,000,000 lamports) and tokens in base units (1 token = 10decimals base units). There is no floating-point arithmetic in the program or in the interface’s calculations.
A launch stores its price as a rate: token base units per 1 SOL. A wallet’s allocation is always computed from its total contribution:
allocation = floor(total lamports contributed × rate ÷ 1,000,000,000)
- Rounding is always down, by less than one base unit.
- Because the total is used, splitting a contribution into several transactions gives exactly the same allocation as sending it at once.
- A contribution that would not add at least one base unit is refused, so nobody pays for nothing.
- The required inventory is
floor(hard cap × rate ÷ 1,000,000,000). The sum of rounded-down allocations can never exceed it, so the escrow always holds every token it has promised.
The price per token shown in the interface is derived from the rate for display and is rounded down to nine decimals. Allocations are never computed from it.
Fees
| Cost | Amount | Who receives it |
|---|---|---|
| Success fee | A share of the SOL raised, set in the program’s configuration and limited to 5% by the program. Charged once, only when a launch succeeds. | The fee recipient recorded in the launch |
| Failed or cancelled launch | No fee | Nobody |
| Contributing, claiming, refunding | No platform fee | Nobody |
| Creating a launch | No platform fee | Nobody |
| Account rent | A deposit Solana requires for each account: the launch, its two escrows, and each participant’s receipt | Held by the accounts themselves |
| Network fee | Solana’s fee per transaction, paid by whoever sends it | The network |
| Token metadata | 0.01 SOL when a new token is created | The Metaplex Token Metadata program |
fee = floor(SOL raised × fee rate in basis points ÷ 10,000)
The fee rate and the fee recipient in force when a launch is created are copied into the launch account. Changing the program’s configuration afterwards does not change them, so a launch’s economics are fixed before anyone contributes. The current rate is shown under Network and deployment status.
A participant’s receipt deposit is returned when they close the receipt after claiming or being refunded. The rent of the launch account and its two escrows, paid by the creator, is not returned in this version.
Settlement
Settlement is one transaction that anyone can send. It is allowed once the contribution window has closed, or earlier if the hard cap has been reached. It moves no funds and takes no arguments: it compares the amount raised with the soft cap and records the result.
- Raised at least the soft cap: Successful. Raising exactly the soft cap is a success.
- Raised less than the soft cap: Failed.
Because anyone can settle, participants never depend on the creator returning. The interface offers the button to every visitor.
Claims
After a successful settlement, each participant claims the allocation recorded on their receipt. The program sends the tokens only to a token account that belongs to the wallet signing the claim, and marks the receipt as claimed, so a second claim is refused.
Tokens that have been sold stay in the token escrow until their owner claims them. There is no deadline, and the creator’s recovery of unsold tokens cannot reach them.
Refunds
After a failed settlement, each participant is refunded the full amount recorded on their receipt, in SOL, once. No fee is deducted from a refund.
Network fees a participant paid for their own transactions are spent and are not part of the refund. The receipt’s rent deposit comes back separately, when the receipt is closed.
Creator withdrawals
SOL. Only after a successful settlement, and only once, the creator withdraws the amount raised minus the fee. Before settlement, and after a failed one, the program has no instruction that pays SOL to the creator.
Unsold tokens. Once per launch the creator recovers the inventory nobody is entitled to: after success, the inventory minus the tokens sold; after failure or cancellation, the whole inventory. The amount comes from the launch’s records, not from the escrow’s balance, so tokens owed to participants are never included.
The fee is forwarded to its recipient by a separate transaction that anyone can send. Keeping it separate means the state of the recipient’s account can never block the creator’s withdrawal.
Network and deployment status
This site is configured for Solana Mainnet. The block below is read from the chain when you open this page. Transactions are offered only when it shows the program deployed and configured on this network; until then every action in the app is disabled and says why.
Program, accounts and authority
The launch program’s address on each network, as built into this site. An address being listed does not mean a program is deployed there; the status block above says whether it is.
- mainnet-beta
- 9tiqiNpy9C8Hn1fsk1ozVTMQxRw1HiSEs3NvX2q4QbLGthis deployment
- devnet
- 9tiqiNpy9C8Hn1fsk1ozVTMQxRw1HiSEs3NvX2q4QbLG
- localnet
- 4YMwAxqAVpLBPMyFgLDjcpn2sWGqbSfpFQAC5oHu144d
Each launch uses accounts at addresses derived from the launch, so they can be recomputed and checked by anyone:
| Account | Address seeds | Holds |
|---|---|---|
| Launch | launch, creator, launch id | The terms, the totals, the state, and the fee terms copied at creation |
| SOL escrow | vault, launch | Contributed SOL, plus a rent reserve that no payout can touch |
| Token escrow | escrow, launch | The sale inventory. An SPL token account whose only authority is the launch address |
| Receipt | receipt, launch, contributor | One wallet’s total contribution and token allocation, and whether it was claimed or refunded |
| Configuration | config | Fee rate (at most 5%), fee recipient, window bounds, a pause switch for new launches, and the admin |
Configuration authority. The configuration is created by the program’s upgrade authority and afterwards changed only by its admin. The admin can change the fee rate within the 5% limit, the fee recipient, the window bounds, and pause the creation and opening of new launches. None of that reaches a launch that is already open. There is no instruction that lets the admin, the fee recipient or anyone else withdraw a launch’s escrowed SOL or tokens.
Upgrade authority. The program is deployed as an upgradeable Solana program. While it has an upgrade authority, that key can replace the program’s code, which could change any rule on this page. The program is therefore not immutable, and using it means trusting whoever holds that key. The current authority is shown in the status block above.
The program’s source, its interface description (IDL) and a TypeScript client are in the repository under onchain/ and src/lib/program/. The program has not been reviewed by an independent security firm.
Public visibility and privacy
NinetiqPad uses ordinary Solana transactions and accounts. Everything a launch does is public and permanent, exactly as for any other Solana program. A program-derived escrow account is not a shielded account: it hides nothing.
| Information | Visibility in this release | Private option |
|---|---|---|
| Wallet identity (the address that contributes, claims or creates) | Public, onchain | None |
| Contribution amount | Public, onchain, per wallet | None |
| Balances (wallets, SOL escrow, token escrow) | Public, onchain | None |
| Token allocation, claims and refunds | Public, onchain, per wallet | None |
| Launch terms and state | Public, onchain | None |
| Token metadata (name, symbol, logo, description) | Public. Name and symbol are onchain; logo and description are served by whoever hosts them | None |
| Verified privacy integration | None is integrated | Not available |
This site keeps no database of users or contributions. A launch draft you are editing is stored in your browser only, until you submit it. The site’s server relays your requests to a Solana RPC endpoint; an RPC provider is infrastructure and gives transactions no privacy.
Private participation is a direction for later work, not a feature. It would need a supported provider, a clearly defined scope of what is hidden and from whom, and independent review, before being offered. Until then, assume that anyone can see which wallet contributed how much to which launch.
Current limitations
- The program has not been audited. It is covered by automated tests against a local validator, which is not the same thing.
- The program is upgradeable while an upgrade authority exists.
- One mechanism only: a fixed-price sale for SOL. There are no bonding curves, no automatic liquidity or exchange listing, no vesting, no allowlists, and no creator-programmable rules.
- Only tokens of the original SPL Token program. Token-2022 is refused.
- The escrow governs the tokens for sale and the SOL raised, nothing else. Whoever holds the rest of a token’s supply can do with it what they like, and a token can be worth nothing.
- A per-wallet maximum limits a wallet, not a person. One person can use several wallets.
- Deadlines follow the Solana cluster clock, which can differ from wall-clock time by a small amount.
- SOL or tokens sent directly to an escrow address, outside the program’s instructions, are not recorded and cannot be withdrawn.
- The rent of a launch account and its escrows is not returned to the creator in this version.
- Launches are found by scanning the program’s accounts through the RPC endpoint. There is no indexer, so a very large number of launches would need one.
- Logos uploaded here are stored by this deployment’s operator, not on permanent storage. A token’s onchain name and symbol do not depend on that.
- Listing is automatic. A launch appears because its account exists, not because anyone reviewed it.
Local development
Requirements: Node.js 22 or newer and pnpm 9. The program tests and the local network also need the Solana command-line tools; the repository’s development notes list the exact versions and the Windows specifics.
pnpm install
pnpm dev # the site on http://localhost:28500, configured for Solana Mainnet
pnpm check # type check, lint and unit tests
pnpm program:build # compile the launch program to onchain/artifacts/
pnpm test:program # run the program tests on a local validator
pnpm localnet # terminal 1: local validator with the program, configured
pnpm dev:local # terminal 2: the site against that validator
pnpm localnet:flow # scripted end-to-end run: one successful and one failed launchThe site runs without any environment file. With no program deployed on its network it shows that state and offers no transaction.
Deploying the program
Deployment is a manual, deliberate step. Nothing in this repository deploys on its own, and the mainnet path asks for an explicit confirmation flag.
# Devnet
pnpm program:deploy --cluster=devnet --payer=<keypair.json> --program-keypair=<program-keypair.json>
pnpm program:init-config --cluster=devnet --authority=<keypair.json> --fee-bps=0
pnpm program:status --cluster=devnet
# Mainnet: prints the cost and what will happen; sends nothing without the last flag
pnpm program:deploy --cluster=mainnet-beta --payer=<keypair.json> --program-keypair=<program-keypair.json>
pnpm program:deploy --cluster=mainnet-beta --payer=<keypair.json> --program-keypair=<program-keypair.json> --i-understand-mainnetThe payer becomes the program’s upgrade authority. program:init-config must be signed by that authority; it sets the fee (--fee-bps=0 needs no recipient, any other value needs --fee-recipient), the window bounds and the admin. After deploying, set NEXT_PUBLIC_SOLANA_CLUSTER and, if the address differs from the built-in one, NEXT_PUBLIC_PROGRAM_ID.
Environment configuration
| Variable | Purpose | Default |
|---|---|---|
NEXT_PUBLIC_SOLANA_CLUSTER | Network the site uses: mainnet-beta, devnet or localnet | mainnet-beta |
NEXT_PUBLIC_PROGRAM_ID | Launch program address on that network | The built-in address for the network |
SOLANA_RPC_URL | RPC endpoint, used on the server only. It may contain a provider key; browsers reach Solana through this site’s relay and never see it | The public endpoint of the network |
NEXT_PUBLIC_SITE_URL | Public address of the site, used in page metadata and in token metadata links | The request’s origin |
METADATA_STORAGE | Where uploaded logos go: local, blob or none | local; on Vercel blob when a store is connected, otherwise none |
BLOB_READ_WRITE_TOKEN | Access token of the object store, set by the host when a store is connected | Not set |
NEXT_PUBLIC_SOURCE_URL | Link to the source repository, shown in the footer when set | Not set |
Variables without the NEXT_PUBLIC_ prefix stay on the server. No private key is ever read by the site: wallets sign in the browser, and deployment keys are used only by the command-line scripts.