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: buy Emits: TradeEvent via internal log_trade_internal Pool status required: LIVE


Modes & Pool Types

Trade modes

Mode
Semantics

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)

Value
Quote
Creator fee?

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

#
Name
Writable
Seeds / Constraints
Description

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 by tokens_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_ata is 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_internal with TradeLogData (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 = desiredOut

    • is_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

Every successful buy triggers an inner instruction carrying TradeLogData with:

  • pool, trader, mint

  • sol_amount (gross in)

  • token_amount

  • fee_amount, creator_fee, protocol_fee

  • is_buy = true

  • Post-trade: vr_quote, vr_token, raised_quote, sold_supply

  • timestamp

Consume these logs to index trades reliably.


Troubleshooting

  • InvalidWsolAccount (WSOL pools): ensure

    • quote_mint == NATIVE_MINT

    • quote_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 increase sol_amount cap (exact-out).

  • PoolNotLive: target reached or sold out.

Last updated