Integrating the Pina Bonding Curve
Pick the client that matches where your code runs:
| You are writing | Use | Guide |
|---|---|---|
| A web app, bot, or backend in TypeScript | @pina-rs/bonding-curve with @solana/kit |
TypeScript client |
| A Flutter app or Dart backend | pina_bonding_curve with solana_kit |
Dart and Flutter client |
| A Rust service, keeper, or test | pina_bonding_curve_client |
Rust client |
| Another on-chain program | pina_bonding_curve_cpi |
Calling the curve from another program |
| Scripts and operations | the pina-curve CLI |
The pina-curve CLI |
All clients are generated from the same IDL, so names match across languages (getBuyInstruction in TypeScript is Buy in Rust).
Addresses you will need
| Address | How to get it |
|---|---|
| Program | CurveqeE6jzkyHQMcWaGENzd7jrd8m9R1u4dZ17GnSa9, exported by every client |
| Configuration | findLaunchConfigPda({ authority, index }) |
| Launch | findLaunchPda({ baseMint }) |
| Vaults | stored on the launch as baseVault and quoteVault, or findLaunchVaultPda({ launch, mint }) |
| AMM authority | findAmmAuthorityPda() |
| Token programs | the owner of each mint account |
| Graduated pool | stored on the launch as pool; before graduation, derive it as shown in Completion and graduation |
A launch is found from its token’s mint alone, so a front end only needs the mint to show a token’s page.
A buy, step by step
- Fetch the launch and confirm its owner is the curve program. Generated decoders only check the discriminator, so the owner check is yours. Check
statusis0(trading) andactivationTimehas passed. - Quote. Simulate the
BuywithminimumBaseOut = 0and read theTradedevent:baseAmountis what you receive andquoteAmountis what you pay. Or compute it yourself from Designing curves and Fees. - Apply slippage:
minimumBaseOut = floor(baseAmount * (10_000 - bps) / 10_000). - Make sure both token accounts exist. Prepend idempotent associated-token-account creations; the base account uses the base mint’s token program.
- Wrap SOL if needed. When the quote mint is wrapped SOL, transfer
quoteAmountInlamports into the trader’s wrapped SOL account and callSyncNativefirst. - Send. If the curve moved more than your tolerance, the program fails with
SlippageExceededand nothing changes.
A sale is the same with Sell, baseAmountIn, and minimumQuoteOut. The opening fee decays every second, so quote close to when you send, especially during the first minute of a launch.
Showing a launch
| Value | From |
|---|---|
| Current price | (sqrtPrice / 2^64)^2 quote base units per base base unit |
| Progress | quoteReserve / config.migrationQuoteThreshold |
| Market value | price × config.totalSupply |
| Current fee | the linear decay in Fees at the cluster time |
| Tokens sold | config.totalSupply minus the base vault balance minus creatorClaimed |
To list every launch under a configuration, filter Launch accounts by their config field (a memcmp at byte offset 2, after the discriminator and version bytes) with getProgramAccounts, or index LaunchCreated events.
Compute budget
| Instruction | Measured | Suggested limit |
|---|---|---|
Buy |
~8,400 CU | 15,000 |
Sell |
~9,000 CU | 15,000 |
CreateLaunch |
~20,000 CU | 40,000 |
Graduate |
65,000–90,000 CU, about 25,000 more with LP payouts | 150,000 |
Add the cost of anything else in the transaction, such as associated-token-account creation (~10,000 to 25,000 CU each). See Performance.
Reading events
Every state change emits an event: ConfigCreated, LaunchCreated, Traded, Completed, Graduated, and Claimed. Pass the complete, ordered log messages of a transaction to parsePinaBondingCurveEventsFromLogs. It follows the runtime’s invoke frames and only returns records the curve itself wrote, so the AMM’s PoolCreated during graduation, or a program that calls the curve, cannot be mistaken for a curve event. The per-event parse*FromLog helpers skip that attribution and are only safe for bytes you already know came from the curve.
Errors
Program errors arrive as Custom(code). Every client exports the codes and messages; the table is in Instruction reference. The most common in practice:
| Error | Usual cause |
|---|---|
SlippageExceeded (14) |
The curve moved, or the fee decayed less than expected; re-quote |
NotActive (12) |
Trading opens at activationTime |
NotTrading (11) |
The launch completed; trade on the AMM after graduation |
InsufficientLiquidity (16) |
A sale larger than everything bought since launch |
InvalidBaseMint (8) |
The mint has supply, a freeze authority, wrong decimals, or another mint authority |
MissingLpAccount (21) |
Graduate without the creator or partner LP accounts the configuration requires |