@gabox-labs/sdk 0.2.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,164 +1,62 @@
1
1
  ---
2
2
  name: gabox-sdk
3
- description: Integrate gabox machines on Solana with @gabox-labs/sdk (TypeScript, @solana/kit 7). Create a machine on a new Pump.fun coin, price and buy packs, watch a draw resolve, sell the prize, handle referrals and stuck draws. Use when a task mentions gabox, machines, packs, draws, prize pools on Pump.fun coins, or @gabox-labs/sdk.
3
+ description: Integrate Gabox machines on Solana with @gabox-labs/sdk and @solana/kit. Use for Gabox pools, packs, Raydium LaunchLab and CPMM venues, draws, prizes, creator fees, and SDK integration.
4
4
  ---
5
5
 
6
- # gabox SDK
6
+ # Gabox SDK
7
7
 
8
- `@gabox-labs/sdk` is the TypeScript client for gabox machines. A **machine** is a prize pool tied to a
9
- new Pump.fun coin. A **pack** is 1,000,000 tokens of that coin; its price follows the coin. Buying
10
- a pack creates a **draw** with a frozen prize table; verifiable randomness picks the prize and the
11
- tokens land in the buyer's wallet. Full docs: `README.md` in the package. Every exported
12
- function and type: `references/api.md`.
8
+ Gabox binds a prize machine to a brand-new Raydium LaunchLab coin. The coin trades on its LaunchLab
9
+ curve until it raises the pinned amount, then Raydium migrates it into a Raydium CPMM pool. Gabox
10
+ delivers awards and closes draw accounts itself; there is no Ready, claim or sell-prize flow, and no
11
+ referral program.
13
12
 
14
- ## Setup
13
+ Use only devnet clients today. Pass `GaboxClient` first to every chain function; all amounts are
14
+ `bigint`.
15
15
 
16
- ```sh
17
- npm install @gabox-labs/sdk @solana/kit
18
- ```
19
-
20
- ESM only. Node 24+. `@solana/kit` is a peer dependency. The program is on **devnet only** today.
21
-
22
- ```ts
23
- import { createClient } from '@gabox-labs/sdk';
24
- const gabox = createClient({ cluster: 'devnet' }); // public devnet RPC
25
- const gabox = createClient({ cluster: 'devnet', url: RPC }); // your provider; wsUrl follows
26
- ```
16
+ Gabox charges no fee at all. Every price the SDK shows already includes Raydium's own fees: on the
17
+ curve, 0.5% to the Gabox platform wallet and 0.5% to the coin creator plus Raydium's trade fee; after
18
+ graduation, the CPMM pool fee and the pool creator fee.
27
19
 
28
- Pass `gabox` as the first argument to every SDK function. `cluster` is required and the URL must
29
- agree with it: a devnet client refuses a URL without `devnet` in it. This throws at
30
- `createClient`, before any request.
31
-
32
- ## Conventions that trip people up
33
-
34
- - **All amounts are `bigint`.** Lamports for SOL, base units for tokens (6 decimals: one pack is
35
- `1_000_000n * 1_000_000n`). Never mix `number` into arithmetic. Basis points are `number`.
36
- - **Builders return a message, not a signature.** Sign with kit's
37
- `signTransactionMessageWithSigners` and send with `sendAndConfirmTransactionFactory({ rpc:
38
- gabox.rpc, rpcSubscriptions: gabox.rpcSubscriptions })`. The SDK never signs or sends.
39
- - **Build right before signing.** The message carries a blockhash that expires in about a minute.
40
- - **Address derivation is async.** `await poolAddress(mint)`, `await drawAddress(pool, seq)`.
41
- - **Low-level `generated.*` functions take `gabox.rpc`**, not the client.
42
- - **Keep the surface kit-only.** Do not import `@solana/web3.js` to talk to this SDK.
43
-
44
- ## Flow 1: price and buy a pack
20
+ Both venues settle in wrapped SOL. Every builder wraps the SOL its trade needs and closes the WSOL
21
+ account afterwards, so the wallet spends and receives plain SOL. That close also unwraps any WSOL the
22
+ wallet already held.
45
23
 
46
24
  ```ts
47
- import { buyPack, drawAddress, fetchPoolByMint, getOffer, share, watchDraw } from '@gabox-labs/sdk';
25
+ import { buyPack, createClient, getOffer } from '@gabox-labs/sdk';
48
26
 
27
+ const gabox = createClient({ cluster: 'devnet' });
49
28
  const offer = await getOffer(gabox, mint, { user: purchaser.address });
50
- // offer.quoteLamports the pack price now (venue fees included)
51
- // offer.prizes [{ amount, tickets }], amounts in tokens, already capped by inventory
52
- // offer.maximum top prize; offer.isSeeded === false means the cap is biting: warn the user
53
-
54
- const pool = await fetchPoolByMint(gabox, mint);
55
- const seq = pool!.nextSeq; // pin the draw
56
- const maxQuoteIn = (offer.quoteLamports * 102n) / 100n; // 2% slippage
57
29
  const message = await buyPack(gabox, {
58
30
  mint,
59
- purchaser, // TransactionSigner, the only signer
60
- seq,
61
- maxQuoteIn,
62
- minMaximum: offer.maximum,
63
- maxTotalDebit: maxQuoteIn + share(maxQuoteIn, 200n) + 20_000_000n,
64
- });
65
- // ...sign and send...
66
- const draw = await drawAddress(offer.pool, seq);
67
- const resolved = await watchDraw(gabox, draw, { signal: AbortSignal.timeout(180_000) });
68
- // resolved.amount = tokens won, already in the purchaser's associated token account
69
- ```
70
-
71
- The three limits the buyer signs:
72
-
73
- | limit | caps | set it to |
74
- | --------------- | -------------------------------------------------------------------- | -------------------------------------- |
75
- | `maxQuoteIn` | the venue price in lamports | `quoteLamports` + your slippage |
76
- | `minMaximum` | the top prize in tokens; fails if inventory dropped | `offer.maximum` |
77
- | `maxTotalDebit` | price + creator fee + protocol fee + randomness fee (both fees ≈ 1%) | `maxQuoteIn + share(maxQuoteIn, 200n) + margin` |
78
-
79
- `maxTotalDebit` excludes rent and the transaction fee. Add ~0.02 SOL of margin. Always pass `seq`
80
- so a retry after a stale blockhash cannot buy a second pack.
81
-
82
- ## Flow 2: keep or sell
83
-
84
- Keeping needs no transaction. Selling routes through the SDK:
85
-
86
- ```ts
87
- import { pump, sellTokens } from '@gabox-labs/sdk';
88
- const gross = await pump.sellQuote(gabox, mint, amount, { user: seller.address });
89
- const message = await sellTokens(gabox, {
90
- mint, seller, amount,
91
- minQuoteOutput: (gross * 95n) / 100n, // must be > 0
31
+ purchaser,
32
+ maxQuoteIn: (offer.quoteAmount * 102n) / 100n,
33
+ minMaximum: (offer.maximum * 98n) / 100n,
34
+ maxNativeDebit: 100_000_000n,
92
35
  });
93
36
  ```
94
37
 
95
- On the Pump route the seller gets SOL. On PumpSwap (a graduated coin) the seller gets WSOL.
38
+ `offer.quoteAmount` is the exact venue price for one pack. `maxQuoteIn` is the slippage cap and the
39
+ number of lamports wrapped first. `maxNativeDebit` is a separate cap on the lamports the handler
40
+ watches: the VRF request and any venue account rent.
96
41
 
97
- ## Flow 3: create a machine
98
-
99
- ```ts
100
- import { createMachine, DEFAULT_TIERS, seedCostEstimate } from '@gabox-labs/sdk';
101
- import { generateKeyPairSigner } from '@solana/kit';
42
+ For creation use `createMachine` with `name`, `symbol`, `uri`, `maxSeedQuoteIn` and
43
+ `maxSeedNativeDebit`. Metaplex limits the three strings to 32, 10 and 200 UTF-8 bytes. Everything
44
+ else about the launch is pinned. It buys a mandatory seed: enough for a 3x top prize on the first
45
+ pack, or the table's full top prize when that pays less than 3x. A table's top tier can be at most
46
+ 20x. Pass `extraSeedTokens` to buy more seed in the same trade, and read `seedCostEstimate` for the
47
+ mandatory, extra and total amounts plus the exact cost.
102
48
 
103
- const mintKeypair = await generateKeyPairSigner();
104
- const seed = await seedCostEstimate(gabox); // DEFAULT_TIERS
105
- const message = await createMachine(gabox, {
106
- creator, mintKeypair, // two signers
107
- name, symbol, uri, // Pump metadata
108
- feeBps: 100, // creator fee, 0..100 (max 1%)
109
- tiers: DEFAULT_TIERS, // optional; default top prize = 20 packs
110
- maxSeedLamports: (seed.lamports * 105n) / 100n,
111
- });
112
- ```
113
-
114
- The creator buys the **seed** that backs the top prize. `DEFAULT_TIERS` needs nineteen extra packs
115
- of tokens. Pass a custom eight-row `Tier[]` only after validating its odds and seed with
116
- `seedCostEstimate(gabox, tiers)`; the SDK and program both validate it.
117
-
118
- ## Flow 4: stuck draws (permissionless)
119
-
120
- ```ts
121
- import { drawAvailability, expireDraw, retryDraw } from '@gabox-labs/sdk';
122
- const s = await drawAvailability(gabox, draw);
123
- if (s?.canRetry) await retryDraw(gabox, { payer, pool, draw, maxVrfDebit: 5_000_000n });
124
- if (s?.canExpire) await expireDraw(gabox, { payer, pool, draw });
125
- ```
126
-
127
- Retry: 300 slots after the last attempt, 3 attempts total. Expire: after 216,000 slots (~1 day),
128
- only while the draw is `Pending`; it pays the **smallest** prize, not a refund. A `Ready` draw must
129
- go through normal delivery. Show `slotsUntilRetry` / `slotsUntilExpiry` as a countdown.
130
-
131
- ## Referrals
132
-
133
- ```ts
134
- await bindReferrer(gabox, referee, referrerAddress); // referee signs, permanent
135
- await buyPack(gabox, { ...input, referrer: referrerAddress }); // or bind + buy in one tx
136
- await claimReferral(gabox, referrer, poolAddress); // referrer collects
137
- ```
138
-
139
- The referrer earns 1% of the creator's fee per pack. The buyer pays nothing extra.
140
-
141
- ## Reading state
142
-
143
- `fetchPoolByMint`, `fetchPoolInventory`, `fetchDraw`, `listPools`, `listDraws({ pool?, purchaser? })`,
144
- `fetchEvents(gabox, signature)`. `list*` uses `getProgramAccounts`: cache it. Events:
145
- `PoolCreated`, `PackBought`, `DrawResolved`, `TokensSold`, `PrizesFunded`, `RandomnessRetried`.
146
-
147
- ## Errors
148
-
149
- ```ts
150
- import { generated } from '@gabox-labs/sdk';
151
- if (generated.isGaboxV2Error(error, message, generated.GABOX_V2_ERROR__SLIPPAGE_EXCEEDED)) { /* widen maxQuoteIn */ }
152
- if (generated.isGaboxV2Error(error, message)) console.log(generated.getGaboxV2ErrorMessage(error.context.code));
153
- ```
49
+ `raydium.resolveVenue(client, { mint, user })` says which venue is live. It throws while a coin is
50
+ migrating, which on devnet lasts under a minute. A migrated CPMM pool can sit at any address, so the
51
+ SDK proves it from its own data and reads its fee tier, vaults and oracle out of the pool account.
154
52
 
155
- Common: `SlippageExceeded`, `PrizeCapChanged` (refresh the offer), `RetryTooSoon`,
156
- `RetryUnavailable`, `NotExpired`, `NotPending`, `InvalidReferral`, `ZeroAmount`.
53
+ Creators collect their share with `raydium.claimCreatorFee(client, { creator })`, which sweeps every
54
+ coin they launched on the curve, and `raydium.collectCreatorFee(client, { mint, creator })` for one
55
+ graduated coin. `raydium.fetchCreatorFees` reads both.
157
56
 
158
- ## Do not
57
+ `buyPack` keeps a per-wallet `WalletActivity` account (`fetchWalletActivity(client, wallet)`, `null`
58
+ before a wallet's first purchase); it resolves the account itself.
159
59
 
160
- - Do not guess the draw address: derive it with `drawAddress(pool, seq)` from the `seq` you pinned.
161
- - Do not set `minQuoteOutput` or `maxQuoteIn` to `0n`. The program rejects them.
162
- - Do not call `getOffer` once and reuse it for minutes. Prices move with the coin.
163
- - Do not point a `'devnet'` client at any other URL. Use `cluster: 'localnet'` for a test validator.
164
- - Do not run against mainnet. The program is not deployed there.
60
+ Use `fetchEvents` and `findResolvedDraw` for final delivery, and `retryDraw` or `expireDraw` for
61
+ permissionless recovery. `fundPrizes` moves coins a funder already holds into the irrevocable prize
62
+ vault. See `references/api.md` and the package README for complete signatures.
@@ -1,148 +1,106 @@
1
- # `@gabox-labs/sdk` API reference
2
-
3
- Every function that reads or writes the chain takes `client: GaboxClient` first. Every builder
4
- returns `Promise<GaboxTransactionMessage>`: a version 0 kit message with the fee payer and a fresh
5
- blockhash set, ready for `signTransactionMessageWithSigners`. All amounts are `bigint`.
6
-
7
- ## Client (`src/rpc.ts`)
8
-
9
- | function / type | signature | notes |
10
- | --- | --- | --- |
11
- | `createClient` | `(config: ClientConfig) => GaboxClient` | the init step. Throws if the URL contradicts the cluster |
12
- | `ClientConfig` | `{ cluster: Cluster; url?: string; wsUrl?: string; addressLookupTables?: AddressesByLookupTableAddress }` | `cluster` is required |
13
- | `GaboxClient` | `{ cluster; url; wsUrl; rpc: GaboxRpc; rpcSubscriptions: GaboxRpcSubscriptions; addressLookupTables }` | a plain object; spread to replace `rpc` |
14
- | `Cluster` | `'devnet' \| 'mainnet-beta' \| 'localnet'` | |
15
- | `CLUSTER_ENDPOINTS` | `Record<Cluster, { url; wsUrl }>` | the defaults |
16
- | `clusterNamedBy` | `(url: string) => Cluster \| 'testnet' \| null` | substring check |
17
- | `assertClusterUrl` | `(cluster: Cluster, url: string) => void` | the guard, exported for scripts |
18
- | `websocketUrlFor` | `(url: string) => string` | `https`→`wss`, `http`→`ws` |
19
- | `defaultAddressLookupTables` | `(cluster: Cluster) => AddressesByLookupTableAddress` | devnet's shared table; `{}` elsewhere |
20
- | `GaboxRpc`, `GaboxRpcSubscriptions` | kit `Rpc<SolanaRpcApi>`, `RpcSubscriptions<SolanaRpcSubscriptionsApi>` | |
21
-
22
- ## Offers and prices (`src/offer.ts`)
23
-
24
- | function | signature | notes |
25
- | --- | --- | --- |
26
- | `getOffer` | `(client, mint: Address, options?: { user?: Address; venue?: VenueKind }) => Promise<PackOffer>` | two reads: pool + vault, then the venue. Throws if the mint has no machine |
27
- | `offerFromState` | `(inventory: PoolInventory, venue: VenueKind, quoteLamports: bigint) => PackOffer` | pure |
28
- | `seedShortfall` | `(offer: PackOffer) => bigint` | tokens that would uncap the top prize |
29
-
30
- `PackOffer` fields: `mint`, `pool`, `packTokens`, `quoteLamports`, `feeBps`, `feeLamports`,
31
- `protocolLamports`, `seedLamports`, `seedTokens`, `venue`, `prizes: Prize[]`, `maximum`, `minimum`,
32
- `uncapped`, `inventory`, `reserved`, `free`, `isFirstPack`, `isSeeded`, `maxMultiplierBps`,
33
- `averageMultiplierBps`.
34
-
35
- ## Transaction builders (`src/tx/`, `src/referral.ts`)
36
-
37
- | function | input | signers |
38
- | --- | --- | --- |
39
- | `createMachine` | `{ creator; mintKeypair; name; symbol; uri; feeBps: number; tiers?: readonly Tier[]; maxSeedLamports: bigint; feeRecipientIndex?; buybackRecipientIndex? }` | creator, mintKeypair |
40
- | `seedCostEstimate` | `(client, tiers?: readonly Tier[]) => Promise<{ tiers: readonly Tier[]; seedTokens: bigint; lamports: bigint }>` | read only |
41
- | `buyPack` | `{ mint; purchaser; maxQuoteIn: bigint; minMaximum: bigint; maxTotalDebit: bigint; seq?: bigint; venue?; wrapLamports?; cashback?; referrer?: Address }` | purchaser |
42
- | `sellTokens` | `{ mint; seller; amount: bigint; minQuoteOutput: bigint; venue? }` | seller |
43
- | `fundPrizes` | `{ mint; funder; amount: bigint; source?: Address }` | funder |
44
- | `fundPrizesWithBuy` | `{ mint; funder; tokens: bigint; maxQuoteIn: bigint; venue?; wrapLamports? }` | funder |
45
- | `retryDraw` | `{ payer; pool; draw; maxVrfDebit: bigint }` | payer (anyone) |
46
- | `expireDraw` | `{ payer; pool; draw }` | payer (anyone); only for an expired `Pending` draw |
47
- | `bindReferrer` | `(client, referee: TransactionSigner, referrer: Address, options?) ` | referee |
48
- | `claimReferral` | `(client, referrer: TransactionSigner, pool: Address, options?)` | referrer |
49
- | `claimPrize`, `sellPrize`, `quoteSellPrize` | legacy draws only (created before automatic delivery) | purchaser |
50
- | `buildMessage` | `(client, feePayer, instructions: Instruction[], options: BuildOptions)` | assemble your own |
51
-
52
- Every input also accepts `BuildOptions`: `computeUnitLimit?: number`, `computeUnitPrice?: number | bigint`
53
- (micro-lamports per unit), `addressLookupTables?`.
54
-
55
- `drawAvailability(client, draw) => Promise<DrawAvailability | null>` returns
56
- `{ status, attempts, slotsUntilRetry, slotsUntilExpiry, canRetry, canExpire }`.
57
-
58
- ## Readers (`src/accounts.ts`, `src/events.ts`)
59
-
60
- | function | returns |
1
+ # Gabox SDK API
2
+
3
+ All chain-touching functions take `client: GaboxClient` first. Addresses use `Address`; all token
4
+ amounts use base-unit `bigint`. Every venue is Raydium: LaunchLab before a coin graduates, Raydium
5
+ CPMM after. Both settle in WSOL.
6
+
7
+ ## Client and reads
8
+
9
+ | Function | Result |
61
10
  | --- | --- |
11
+ | `createClient({ cluster: 'devnet', ... })` | `GaboxClient` |
62
12
  | `fetchPoolByMint(client, mint)` | `Pool \| null` |
63
- | `fetchPoolAt(client, poolAddress)` | `Pool \| null` |
64
- | `fetchPoolInventory(client, mint)` | `{ pool, poolAddress, vault, inventory, reserved, free } \| null` |
65
- | `fetchVaultBalance(client, mint)` | `bigint` |
66
- | `fetchDraw(client, drawAddress)` | `Draw \| null` (null once delivered and closed) |
67
- | `fetchReferralReward(client, pool, referrer)` | `Referral \| null` |
68
- | `listPools(client)` | `{ address, data: Pool }[]` |
69
- | `listDraws(client, { pool?, purchaser? })` | `{ address, data: Draw }[]` |
70
- | `listDrawsByPool(client, pool)`, `listDrawsByPurchaser(client, wallet)` | same |
71
- | `listReferralLinksByReferrer(client, referrer)` | `{ address, data: ReferralLink }[]` |
72
- | `resolveReferral(client, purchaser, pool)` | `{ link, referrer, referral } \| null` |
73
- | `fetchEvents(client, signature)` | `GaboxEvent[]` |
74
- | `decodeEvents(logs: string[])`, `decodeEvent(bytes)` | pure |
75
- | `watchDraw(client, drawAddress, { signal?, onChange? })` | `Promise<Draw>` resolves on delivery |
76
-
77
- `Pool` fields: `creator`, `mint`, `tokenProgram`, `vault`, `bump`, `packTokens`, `feeBps`,
78
- `seedLamports`, `seedTokens`, `tiers: Tier[]`, `nextSeq`, `reserved`.
79
-
80
- `Draw` fields: `pool`, `purchaser`, `seq`, `status: DrawStatus` (`Pending | Ready`), `requestSlot`,
81
- `lastAttemptSlot`, `attempts`, `maximum`, `minimum`, `prizes`, `amount`, `randomness`, `timedOut`.
82
-
83
- `GaboxEvent` is a union on `name`: `PoolCreated`, `PrizesFunded`, `PackBought`, `RandomnessRetried`,
84
- `DrawResolved`, `PrizeRedeemed`, `TokensSold`. `PackBought.data` has `pool`, `seq`, `purchaser`,
85
- `venue`, `tokensBought`, `venueDebit`, `feeLamports`, `referralLamports`, `protocolLamports`,
86
- `vrfDebit`, `prizes`. `DrawResolved.data` has `pool`, `seq`, `purchaser`, `amount`, `randomness`,
87
- `timedOut`.
88
-
89
- ## Addresses (`src/pdas.ts`), all async
90
-
91
- `poolAddress(mint)`, `drawAddress(pool, seq)`, `vaultAddress(mint, tokenProgram?)`,
92
- `associatedTokenAddress(owner, mint, tokenProgram?)`, `referralLinkAddress(referee)`,
93
- `referralAddress(pool, referrer)`, `feeCollectorWsolAddress()`, `vrfIdentityAddress()`.
94
- Also the generated `findPoolPda`, `findDrawPda`, `findReferralLinkPda`, `findIdentityPda`.
95
-
96
- ## Math (`src/math.ts`), pure
97
-
98
- | function | signature | notes |
99
- | --- | --- | --- |
100
- | `share` | `(amount: bigint, bps: bigint) => bigint` |
101
- | `DEFAULT_TIERS` | `readonly Tier[]` | 75% / 20% / 4% / 1% odds at 0.52× / 1.2× / 3× / 20× |
102
- | `seedTokens` | `(packTokens: bigint, tiers: Tier[]) => bigint` |
103
- | `quote` | `(base: bigint, tiers: Tier[], inventory: bigint, reserved: bigint) => Offer` |
104
- | `uncappedMaximum` | `(base: bigint, tiers: Tier[]) => bigint` |
105
- | `tierAmount` | `(base: bigint, multiplierBps: number) => bigint` |
106
- | `choose` | `(prizes: Prize[], ticket: number) => bigint` |
107
- | `maxMultiplierBps`, `averageMultiplierBps` | `(tiers: Tier[]) => number` |
108
- | `validateTiers`, `validatePack` | throw `GaboxMathError` on a bad table |
109
-
110
- Types: `Tier = { multiplierBps: number; tickets: number }`, `Prize = { amount: bigint; tickets: number }`,
111
- `Offer = { prizes: Prize[]; maximum: bigint; minimum: bigint }`. Constants `BPS = 10_000n`, `TICKETS = 65_536`,
112
- `TIERS = 8`.
113
-
114
- ## Constants (`src/ids.ts`)
115
-
116
- `GABOX_PROGRAM_ID`, `PACK_TOKENS`, `PROTOCOL_FEE_BPS` (`100n`), `MAX_FEE_BPS` (`100`),
117
- `REFERRAL_FEE_BPS` (`100n`), `RETRY_SLOTS` (`300n`), `MAX_ATTEMPTS` (`3`), `TIMEOUT_SLOTS`
118
- (`216_000n`), `WSOL_MINT`, `TOKEN_PROGRAM_ADDRESS`, `TOKEN_2022_PROGRAM_ADDRESS`,
119
- `ASSOCIATED_TOKEN_PROGRAM_ADDRESS`, `PUMP_PROGRAM_ADDRESS`, `PUMP_SWAP_PROGRAM_ADDRESS`,
120
- `VRF_PROGRAM_ADDRESS`, `VRF_DEFAULT_QUEUE`.
121
-
122
- ## Venue layer (`pump` namespace, `@gabox-labs/sdk/pump`)
123
-
124
- | function | signature |
13
+ | `fetchPoolInventory(client, mint)` | pool, vault inventory, reservations, free inventory |
14
+ | `getOffer(client, mint, options?)` | current `PackOffer` |
15
+ | `listPools(client)` / `listDrawsByPurchaser(client, wallet)` | current account scans |
16
+ | `fetchWalletActivity(client, wallet)` | `WalletActivity \| null`, a buyer's lifetime `packsBought`/`nativeSpent` |
17
+
18
+ `Pool` records `creator`, `mint`, `vault`, `quoteMint` (always WSOL), `packTokens`,
19
+ `seedQuoteAmount`, `tiers`, `nextSeq` and `reserved`. It stores no token program, because classic
20
+ SPL Token owns both sides, and no fee, because Gabox charges none.
21
+
22
+ `PackOffer` gives `quoteAmount` (the whole pack price, the venue's fees included), `venue`
23
+ (`'launchlab'` or `'cpmm'`), the frozen prize table, `maximum`, `minimum`, `uncapped`, the inventory
24
+ numbers and `isSeeded`.
25
+
26
+ ## Builders
27
+
28
+ Each returns a kit transaction message. Nothing here signs or sends.
29
+
30
+ | Function | Input highlights |
31
+ | --- | --- |
32
+ | `createMachine` | `name`, `symbol`, `uri`, `tiers?`, `maxSeedQuoteIn`, `maxSeedNativeDebit`, `extraSeedTokens?` |
33
+ | `buyPack` | `maxQuoteIn`, `minMaximum`, `maxNativeDebit`, `venue?`, `seq?` |
34
+ | `fundPrizes` | donate coins the funder already holds into the prize vault |
35
+ | `sellTokens` | `amount`, `minQuoteOutput`, `maxNativeDebit`, `venue?` |
36
+ | `retryDraw` / `expireDraw` | permissionless recovery |
37
+ | `raydium.claimCreatorFee` | `creator`; sweeps every coin that wallet launched on the curve |
38
+ | `raydium.collectCreatorFee` | `mint`, `creator`; one graduated coin's CPMM creator fee |
39
+
40
+ Every builder wraps the SOL its trade needs into the wallet's WSOL account and closes that account
41
+ afterwards, so the wallet spends and receives plain SOL. Closing unwraps any WSOL the wallet already
42
+ held.
43
+
44
+ `createMachine` builds one transaction with LaunchLab's `initialize_v2` first and `initialize_pool`
45
+ second. The mint keypair and the creator both sign. It buys a mandatory seed,
46
+ `seedTokens(PACK_TOKENS, tiers)`: enough for a 3x top prize on the first pack, or the table's full
47
+ top prize when that pays less than 3x. A table's top tier can be at most 20x. `extraSeedTokens`
48
+ (default `0n`) adds more in the same trade. `seedCostEstimate` returns `seedTokens`,
49
+ `extraSeedTokens`, `totalSeedTokens` and the exact `quoteAmount` a fresh curve would charge.
50
+
51
+ `buyPack` also resolves a per-wallet `WalletActivity` account (`findActivityPda({ purchaser })` or
52
+ `activityAddress(wallet)`); callers do not pass it. It does not create the purchaser's coin account
53
+ either: the program declares it `init_if_needed`, so Anchor does that and the purchaser pays its rent
54
+ once.
55
+
56
+ `maxQuoteIn` and `maxSeedQuoteIn` are venue slippage caps in WSOL, and each is also the amount
57
+ wrapped before the trade. `maxNativeDebit` and `maxSeedNativeDebit` are separate lamport caps for
58
+ what the handler watches: venue account rent, and the VRF request on a pack buy.
59
+
60
+ ## The venue
61
+
62
+ | Function | Result |
125
63
  | --- | --- |
126
- | `resolveVenue` | `(client, { mint; user; venue?; feeRecipientIndex?; buybackRecipientIndex? }) => Promise<ResolvedVenue>` |
127
- | `curveQuote` | `(client, mint, tokens: bigint, { user?, venue? }?) => Promise<bigint>` lamports to buy `tokens` |
128
- | `sellQuote` | `(client, mint, tokens: bigint, { user?, venue? }?) => Promise<bigint>` lamports a sale returns |
129
- | `newCurveBuyCost` | `(client, tokens: bigint) => Promise<bigint>` on a fresh curve |
130
- | `wsolAccountFor` | `(user: Address) => Address` |
131
- | `tokenAccountAmount` | `(data: Uint8Array) => bigint` |
132
-
133
- `ResolvedVenue`: `{ kind: 'pump' | 'pumpswap'; program; mint; tokenProgram; complete; creator;
134
- buyAccounts; sellAccounts; quoteBuy(tokens); quoteSell(tokens) }`. `VenueKind = 'pump' | 'pumpswap'`.
135
-
136
- ## Generated client (`generated` namespace, `@gabox-labs/sdk/generated`)
137
-
138
- Codama output for `@solana/kit`: `get*Instruction` builders, `fetch*` / `decode*` account readers
139
- (these take a kit `Rpc`, i.e. `gabox.rpc`), event codecs, PDAs, and errors:
140
-
141
- - `isGaboxV2Error(error, transactionMessage, code?)` narrows a kit `SolanaError`.
142
- - `getGaboxV2ErrorMessage(code)` — readable outside `NODE_ENV=production`.
143
- - `GABOX_V2_ERROR__*` codes, from `6000`: `ARITHMETIC`, `INVALID_DISTRIBUTION`,
144
- `UNFUNDED_EXPECTATION`, `UNSUPPORTED_MINT`, `INSOLVENT_INVENTORY`, `PRIZE_CAP_CHANGED`,
145
- `PACK_TOO_SMALL`, `JACKPOT_BELOW_ONE_PACK`, `INVALID_VENUE`, `INCORRECT_TOKEN_DELTA`,
146
- `SLIPPAGE_EXCEEDED`, `NOT_PENDING`, `NOT_READY`, `RETRY_TOO_SOON`, `RETRY_UNAVAILABLE`,
147
- `NOT_EXPIRED`, `ZERO_AMOUNT`, `INVALID_FEE`, `COIN_NOT_CREATED_HERE`, `INVALID_REFERRAL`,
148
- `NOTHING_OWED_TO_REFERRER`, `INVALID_FEE_COLLECTOR`.
64
+ | `raydium.resolveVenue(client, { mint, user, venue? })` | `ResolvedVenue`: `kind`, `program`, `poolState`, `status`, `creator`, `ammConfig`, `remainingCurveBase`, `buyAccounts`, `sellAccounts`, `quoteBuy`, `quoteSell` |
65
+ | `raydium.curveQuote(client, mint, tokens)` | the buy price, for a display |
66
+ | `raydium.sellQuote(client, mint, tokens)` | the sale proceeds |
67
+ | `raydium.newCurveBuyCost(client, tokens)` | what a buy costs on a curve that does not exist yet |
68
+ | `raydium.findCpmmPool(client, { mint, creator, cpswapConfig })` | the migrated CPMM pool, proved from its own data |
69
+ | `raydium.fetchCurveSettings(client)` | the fee rates, the migrate fee and the CPMM fee tier, read from chain |
70
+ | `raydium.fetchCreatorFees(client, { creator, mint? })` | `{ curveLamports, cpmmLamports, cpmmTokens }` |
71
+ | `raydium.wsolAccountFor(user)` | the WSOL account every venue settles in |
72
+
73
+ `resolveVenue` follows the LaunchLab pool's `status`: `0` routes to the curve, `2` to the CPMM pool,
74
+ and `1` throws because the coin is migrating right now. A migrated CPMM pool does not have to sit at
75
+ a derived address, so it proves itself from its own data, and its fee tier, its two vaults and its
76
+ oracle are read out of the pool account. The program checks the same things.
77
+
78
+ `quoteBuy` on the curve throws when the amount is larger than the curve has left to sell. That is not
79
+ a price failure: the program requires an exact one-pack delta, so such a buy cannot succeed until the
80
+ coin graduates.
81
+
82
+ ## Math and low-level builders
83
+
84
+ `raydium.curve` exports exact bigint ports of Raydium's own math: `curveBuyExactOut`,
85
+ `curveBuyExactIn`, `curveSellExactIn`, `initialCurve`, `cpmmSwapBaseOutput`, `cpmmSwapBaseInput`, and
86
+ the `ceilDivRate` / `preFeeAmount` helpers they are built from. Every rounding step matches
87
+ Raydium's.
88
+
89
+ `raydium.getLaunchInstruction(input, ids)` builds LaunchLab's `initialize_v2` with the pinned launch
90
+ shape. `raydium.getCurveBuyExactInInstruction(client, input, ids?)` builds a plain curve buy that
91
+ Gabox never makes itself; the devnet end-to-end test uses it to buy a curve out and force graduation.
92
+
93
+ `raydiumIds(cluster)` gives one cluster's Raydium deployment. Mainnet and devnet run different
94
+ programs and PDAs, and devnet raises 3 SOL where mainnet raises 85. `localnet` uses the mainnet set,
95
+ which is what the program's default build pins.
96
+
97
+ ## Events
98
+
99
+ `decodeEvents` and `fetchEvents` return only `PoolCreated`, `PrizesFunded`, `PackBought`,
100
+ `RandomnessRetried`, `DrawResolved` and `TokensSold`. None carries a Gabox fee field any more.
101
+ `PackBought` reports `quoteDebit` (what the venue charged), `nativeDebit` (venue account rent),
102
+ `vrfNativeDebit` and `totalNativeDebit`.
103
+
104
+ Delivery closes a draw atomically; use `findResolvedDraw` rather than a Ready or claim flow. It
105
+ searches a bounded recent signature history, so production indexers should persist `DrawResolved`
106
+ events as the authoritative history.