buy
Buy launchpad tokens with SOL or WSOL. The instruction supports exact-in and exact-out modes, applies protocol/creator fees, updates pool state, transfers tokens to the buyer, and emits a structured trade log (log_trade_internal) for indexers.
Program: Tradersdex Curve (Launchpad) Instruction:
buyEmits:TradeEventvia internallog_trade_internalPool status required:LIVE
Modes & Pool Types
Trade modes
Exact-in (is_exact_in = true)
Spend up to sol_amount, must receive ≥ min_tokens_out
Exact-out (is_exact_in = false)
Receive exactly min_tokens_out, must spend ≤ sol_amount
Pool types (on-chain pool_type)
pool_type)0 (Basic)
SOL
❌
1 (WithCreator)
SOL
✅
2 (WithCustomQuote)
WSOL
❌
3 (Full)
WSOL
✅
QuoteVault rule:
WSOL pools (2/3):
quote_vault = ATA(NATIVE_MINT, pool)SOL pools (0/1):
quote_vault = pool(lamports live on the pool PDA)
Arguments
Accounts
0
pool
✅
["pool", mint], owner = program
Pool PDA; custom-deserialized
1
mint
Sale token mint
2
quote_mint
For WSOL must be NATIVE_MINT
For SOL may be Pubkey::default()
3
token_vault
✅
ATA(mint, pool) & amount > 0
Pool’s base token vault
4
quote_vault
WSOL: ATA(NATIVE_MINT, pool) • SOL: pool
Pool’s quote holding
5
user_token_account
✅
ATA(mint, payer), init_if_needed
Buyer’s receiving ATA
6
user_quote_account
WSOL: ATA(NATIVE_MINT, payer)
Buyer’s WSOL ATA (unused for SOL)
7
fee_recipient
✅
Must equal one of PDA(["protocol_fee_vault",[i]])
Protocol fee receiver
8
payer
✅
Buyer
9
token_program
= anchor_spl::token::ID
SPL Token program
10
associated_token_program
For ATA ops
11
system_program
For SOL transfers
12
tradersdex_curve
= crate::ID
Self-check
13
event_authority
["event_authority"]
Signs inner log ix
14
token_creator
Must equal pool creator for fee pools
Creator pubkey
15
token_creator_ata
ATA(NATIVE_MINT, token_creator)
Needed to activate creator fee (WSOL path)
Behavior (summary)
Math
Uses virtual reserves:
vr_quote,vr_token.Exact-in: fee is taken from input;
out = floor(rt * x_eff / (rb + x_eff)), capped bytokens_for_sell. If capped, recomputes the minimal gross-in needed for the cap.Exact-out: solves minimal gross-in (after fees) to receive exactly
min_tokens_out.
Fees
fee_bps = PROTOCOL_FEE_BPS (+ CREATOR_FEE_BPS if creator path is active)Creator fee is active for pool types 1/3 and only if
token_creator_atais the correct WSOL ATA (and initialized).Split:
creator_fee = total_fee * CREATOR_FEE_BPS / fee_bps,protocol_fee = total_fee - creator_fee.
Indexer
Emits inner
log_trade_internalwithTradeLogData(pool, trader, mint, gross in, tokens out, fees, new reserves, timestamp).
Client recipe: Quote → Slippage → Build IX
1) Fetch & parse pool
2) Quote (pick one path)
Exact-in quote
Exact-out quote
3) Build the instruction (no send)
Putting it together
Exact-in send:
sol_amount = grossIn(your planned spend)min_tokens_out = minTokensOut(slippage protected)is_exact_in = true
Exact-out send:
sol_amount = maxSolIn(slippage padded cap)min_tokens_out = desiredOutis_exact_in = false
Fee vault PDAs
Protocol fee vaults are derived as:
Use i ∈ [0..NUM_FEE_ACCOUNTS) and pass the derived PDA as fee_recipient.
Indexer: log_trade_internal
log_trade_internalEvery successful buy triggers an inner instruction carrying TradeLogData with:
pool,trader,mintsol_amount(gross in)token_amountfee_amount,creator_fee,protocol_feeis_buy = truePost-trade:
vr_quote,vr_token,raised_quote,sold_supplytimestamp
Consume these logs to index trades reliably.
Troubleshooting
InvalidWsolAccount (WSOL pools): ensure
quote_mint == NATIVE_MINTquote_vault == ATA(NATIVE_MINT, pool)user_quote_account == ATA(NATIVE_MINT, payer)For creator-fee pools,
token_creator_ata == ATA(NATIVE_MINT, token_creator)
InvalidFeeRecipient: derive one of
protocol_fee_vault[i].SlippageExceeded: relax
min_tokens_out(exact-in) or increasesol_amountcap (exact-out).PoolNotLive: target reached or sold out.
Last updated