@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.
- package/CHANGELOG.md +226 -0
- package/README.md +116 -460
- package/dist/generated/index.d.ts +334 -755
- package/dist/generated/index.js +2403 -338
- package/dist/generated/index.js.map +1 -1
- package/dist/index-BDfGvmgF.d.ts +934 -0
- package/dist/index.d.ts +191 -448
- package/dist/index.js +468 -1034
- package/dist/index.js.map +1 -1
- package/dist/raydium/index.d.ts +2 -0
- package/dist/raydium/index.js +2 -0
- package/dist/raydium-B-l9V3O-.js +2604 -0
- package/dist/raydium-B-l9V3O-.js.map +1 -0
- package/llms.txt +4 -2
- package/package.json +11 -16
- package/skills/gabox-sdk/SKILL.md +40 -142
- package/skills/gabox-sdk/references/api.md +103 -145
- package/dist/gaboxV2-CV2XltqC.js +0 -3347
- package/dist/gaboxV2-CV2XltqC.js.map +0 -1
- package/dist/index-BxvSkzCO.d.ts +0 -471
- package/dist/pump/index.d.ts +0 -2
- package/dist/pump/index.js +0 -2
- package/dist/pump-D0K_0uiC.js +0 -1531
- package/dist/pump-D0K_0uiC.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["base64","wsolPreparation","SPL_TOKEN_PROGRAM_ADDRESS","wsolPreparation","SPL_TOKEN_PROGRAM_ADDRESS","SPL_TOKEN_PROGRAM_ADDRESS"],"sources":["../src/math.ts","../src/pdas.ts","../src/accounts.ts","../src/compute.ts","../src/events.ts","../src/lookupTables.ts","../src/offer.ts","../src/rpc.ts","../src/tx/message.ts","../src/referral.ts","../src/tx/buyPack.ts","../src/tx/createMachine.ts","../src/tx/draw.ts","../src/tx/fundPrizes.ts","../src/tx/redeem.ts","../src/vrf.ts"],"sourcesContent":["/**\n * A bigint port of `programs/gabox-v2/src/math.rs`.\n *\n * The point is that a client can show a buyer the exact prize table the program will freeze into\n * their `Draw`, before they pay. Every rounding step here matches the Rust, including the direction\n * of each division. `test/math.test.ts` runs the same vectors as `programs/gabox-v2/tests/\n * economics.rs`.\n *\n * All amounts are `bigint`, in the mint's smallest unit. `multiplierBps` and `tickets` are numbers\n * because both are `u32` in the program and both stay small.\n */\n\n/** Basis points. A multiplier of 10_000 pays back exactly one pack. */\nexport const BPS = 10_000n;\n\n/** `math::share`. `bps` basis points of `amount`, rounded down. */\nexport function share(amount: bigint, bps: bigint): bigint {\n return (amount * bps) / BPS;\n}\n\n/** Ticket counts must sum to this. A uniform 16-bit word then maps with no modulo bias. */\nexport const TICKETS = 65_536;\n\n/** The prize table has exactly this many slots. Unused slots are all-zero. */\nexport const TIERS = 8;\n\n/** One row of the immutable prize table. Counts, not cumulative thresholds. */\nexport type Tier = {\n /** `floor(base * multiplierBps / 10_000)` tokens. `0` only on an unused row. */\n multiplierBps: number;\n /** Out of 65,536. `0` marks the row unused, and then `multiplierBps` must be `0` too. */\n tickets: number;\n};\n\n/** One row of a frozen offer: a real token amount, already capped by inventory. */\nexport type Prize = {\n amount: bigint;\n tickets: number;\n};\n\n/** What `buy_pack` writes into the `Draw`. `minimum` is also the timeout payout. */\nexport type Offer = {\n prizes: Prize[];\n maximum: bigint;\n minimum: bigint;\n};\n\n/** Thrown by every function here. `code` matches a `GaboxError` variant name. */\nexport class GaboxMathError extends Error {\n readonly code: string;\n constructor(code: string, message: string) {\n super(`${code}: ${message}`);\n this.name = \"GaboxMathError\";\n this.code = code;\n }\n}\n\nconst U64_MAX = (1n << 64n) - 1n;\nconst U32_MAX = 0xffff_ffff;\n\n/**\n * The default prize table. The program does not enforce this table: it accepts any table that\n * passes `validateTiers`. This is only the table the Gabox app creates its pools with, and the\n * starting point for a client that has no reason to pick another one.\n *\n * Common 75% at 0.52x, Rare 20% at 1.2x, Epic 4% at 3x, Mythic 1% at 20x. Expected payout is\n * 0.9499x of a pack, so the seed is 19 packs.\n */\nexport const DEFAULT_TIERS: readonly Readonly<Tier>[] = Object.freeze([\n Object.freeze({ multiplierBps: 5_201, tickets: 49_153 }),\n Object.freeze({ multiplierBps: 12_000, tickets: 13_107 }),\n Object.freeze({ multiplierBps: 30_000, tickets: 2_621 }),\n Object.freeze({ multiplierBps: 200_000, tickets: 655 }),\n Object.freeze({ multiplierBps: 0, tickets: 0 }),\n Object.freeze({ multiplierBps: 0, tickets: 0 }),\n Object.freeze({ multiplierBps: 0, tickets: 0 }),\n Object.freeze({ multiplierBps: 0, tickets: 0 }),\n]);\n\nfunction checkedU64(value: bigint, what: string): bigint {\n if (value < 0n || value > U64_MAX) {\n throw new GaboxMathError(\"Arithmetic\", `${what} does not fit in u64`);\n }\n return value;\n}\n\n/** Tier fields encode as program `u32`s. Reject JavaScript-only values before `BigInt` or codecs. */\nfunction checkedU32(value: number, what: string): number {\n if (!Number.isInteger(value) || value < 0 || value > U32_MAX) {\n throw new GaboxMathError(\n \"InvalidDistribution\",\n `${what} must be an integer from 0 to ${U32_MAX}`,\n );\n }\n return value;\n}\n\n/** `math::tokens`. Floor division, and an overflow past u64 is an error, not a wrap. */\nexport function tierAmount(base: bigint, multiplierBps: number): bigint {\n return checkedU64((base * BigInt(checkedU32(multiplierBps, \"multiplierBps\"))) / BPS, \"tier amount\");\n}\n\n/**\n * `math::validate`. Checks the table alone, with no base.\n *\n * Three rules, and each one closes a way to sell a bad ticket:\n * - ticket counts sum to exactly 65,536, so the 16-bit draw is uniform;\n * - an unused row is all-zero, so a hidden multiplier cannot ride along;\n * - the expected multiplier over all tickets is at most 1x, so the table cannot promise more\n * tokens than a pack buys. This bounds tokens, not cash value.\n */\nexport function validateTiers(tiers: readonly Readonly<Tier>[]): void {\n if (tiers.length !== TIERS) {\n throw new GaboxMathError(\n \"InvalidDistribution\",\n `expected ${TIERS} tiers, got ${tiers.length}`,\n );\n }\n let count = 0n;\n let expected = 0n;\n for (const [index, tier] of tiers.entries()) {\n checkedU32(tier.tickets, `tier ${index} tickets`);\n checkedU32(tier.multiplierBps, `tier ${index} multiplierBps`);\n if (tier.tickets === 0) {\n if (tier.multiplierBps !== 0) {\n throw new GaboxMathError(\n \"InvalidDistribution\",\n \"a tier with no tickets must have no multiplier\",\n );\n }\n continue;\n }\n if (tier.multiplierBps <= 0) {\n throw new GaboxMathError(\n \"InvalidDistribution\",\n \"a ticketed tier must pay something; it would sell a ticket that can only win zero\",\n );\n }\n count += BigInt(tier.tickets);\n expected += BigInt(tier.multiplierBps) * BigInt(tier.tickets);\n }\n if (count !== BigInt(TICKETS)) {\n throw new GaboxMathError(\n \"InvalidDistribution\",\n `tickets must sum to ${TICKETS}, they sum to ${count}`,\n );\n }\n if (expected > BPS * BigInt(TICKETS)) {\n throw new GaboxMathError(\n \"UnfundedExpectation\",\n \"the expected token award exceeds the tokens a pack buys\",\n );\n }\n}\n\n/**\n * `math::validate_pack`. Every ticketed tier must pay at least one token for a pack of this size.\n *\n * The program checks this once at creation. At `PACK_TOKENS` no sane table fails it; it exists so\n * a table cannot sell a ticket that can only win zero.\n */\nexport function validatePack(packTokens: bigint, tiers: readonly Readonly<Tier>[]): void {\n if (packTokens <= 0n) throw new GaboxMathError(\"ZeroAmount\", \"packTokens must be positive\");\n checkedU64(packTokens, \"pack tokens\");\n validateTiers(tiers);\n for (const [i, tier] of tiers.entries()) {\n if (tier.tickets === 0) continue;\n if (tierAmount(packTokens, tier.multiplierBps) === 0n) {\n throw new GaboxMathError(\"PackTooSmall\", `tier ${i} rounds to zero tokens at this pack size`);\n }\n }\n}\n\n/**\n * `math::seed_tokens`. The seed a table needs, in tokens.\n *\n * The first pack must be able to pay the largest tier in full. The pack itself brings `packTokens`\n * into the vault, so the vault has to hold the rest beforehand:\n *\n * seedTokens = uncappedMaximum(packTokens, tiers) - packTokens\n *\n * A 5x jackpot on a 1M-token pack needs a 4M-token seed. A table whose top tier pays exactly one\n * pack needs no seed. A top tier below one pack is refused: every ticket would lose.\n *\n * `initialize_pool` computes this number itself and buys exactly that many tokens on the curve.\n * The creator only signs a maximum SOL cost.\n */\nexport function seedTokens(packTokens: bigint, tiers: readonly Readonly<Tier>[]): bigint {\n validateTiers(tiers);\n const largest = uncappedMaximum(packTokens, tiers);\n if (largest < packTokens) {\n throw new GaboxMathError(\n \"JackpotBelowOnePack\",\n \"the largest tier must pay at least one pack\",\n );\n }\n return largest - packTokens;\n}\n\n/**\n * `math::uncapped_maximum`. The largest tier's award for this base, before any inventory cap.\n *\n * At `packTokens` this is the jackpot in tokens. `seedTokens` is this minus one pack.\n */\nexport function uncappedMaximum(base: bigint, tiers: readonly Readonly<Tier>[]): bigint {\n validateTiers(tiers);\n let largest = 0n;\n for (const tier of tiers) {\n if (tier.tickets === 0) continue;\n const amount = tierAmount(base, tier.multiplierBps);\n if (amount > largest) largest = amount;\n }\n return largest;\n}\n\n/**\n * `math::quote`. The offer a pack of `base` tokens would freeze right now. `base` is always\n * `pool.packTokens`; the parameter stays general so the vectors can use small numbers.\n *\n * `inventory` is the vault's token balance and `reserved` is `pool.reserved`. The difference is\n * free inventory. This pack's own `base` is added to it, because the purchase and the offer are\n * one transaction — the tokens are in the vault before the draw is written.\n *\n * Every amount is capped at what is actually available. A tier that rounds to zero tokens is an\n * error: the pool must not sell a ticket that can only win nothing.\n */\nexport function quote(\n base: bigint,\n tiers: readonly Readonly<Tier>[],\n inventory: bigint,\n reserved: bigint,\n): Offer {\n validateTiers(tiers);\n if (inventory < reserved) {\n throw new GaboxMathError(\n \"InsolventInventory\",\n \"the vault holds less than the pool has already reserved\",\n );\n }\n const available = checkedU64(\n inventory - reserved + base,\n \"available inventory\",\n );\n\n const prizes: Prize[] = Array.from({ length: TIERS }, () => ({\n amount: 0n,\n tickets: 0,\n }));\n let maximum = 0n;\n let minimum = U64_MAX;\n\n for (const [i, tier] of tiers.entries()) {\n if (tier.tickets === 0) continue;\n const uncapped = tierAmount(base, tier.multiplierBps);\n if (uncapped === 0n) {\n throw new GaboxMathError(\n \"PackTooSmall\",\n `tier ${i} rounds to zero tokens at this pack size`,\n );\n }\n const amount = uncapped < available ? uncapped : available;\n prizes[i] = { amount, tickets: tier.tickets };\n if (amount > maximum) maximum = amount;\n if (amount < minimum) minimum = amount;\n }\n\n return { prizes, maximum, minimum };\n}\n\n/**\n * `math::choose`. Which prize a 16-bit ticket wins.\n *\n * The rows are consecutive ranges in table order, so this is a running total and a comparison.\n * A ticket past the last row returns `0`, which cannot happen for a validated table.\n */\nexport function choose(prizes: readonly Prize[], ticket: number): bigint {\n let end = 0;\n for (const prize of prizes) {\n end += prize.tickets;\n if (ticket < end) return prize.amount;\n }\n return 0n;\n}\n\n/** `math::resolve_reservation`. Release the unwon part of a maximum, keep the award reserved. */\nexport function resolveReservation(\n reserved: bigint,\n maximum: bigint,\n award: bigint,\n): bigint {\n if (award > maximum) {\n throw new GaboxMathError(\n \"InsolventInventory\",\n \"the award exceeds the reserved maximum\",\n );\n }\n if (reserved < maximum) {\n throw new GaboxMathError(\n \"Arithmetic\",\n \"the pool has reserved less than this draw holds\",\n );\n }\n return checkedU64(reserved - maximum + award, \"reserved\");\n}\n\n/** The largest `multiplierBps` on any ticketed row. `0` for a table with no rows. */\nexport function maxMultiplierBps(tiers: readonly Readonly<Tier>[]): number {\n validateTiers(tiers);\n let largest = 0;\n for (const tier of tiers) {\n if (tier.tickets === 0) continue;\n if (tier.multiplierBps > largest) largest = tier.multiplierBps;\n }\n return largest;\n}\n\n/**\n * The expected multiplier over all 65,536 tickets, in basis points. Rounded down.\n *\n * `validateTiers` caps this at 10,000. A table at 9,800 keeps 2% of every pack's tokens in the\n * vault on average, which is what lets a pool survive a run of top-tier wins.\n */\nexport function averageMultiplierBps(tiers: readonly Readonly<Tier>[]): number {\n validateTiers(tiers);\n let weighted = 0n;\n for (const tier of tiers) {\n if (tier.tickets === 0) continue;\n weighted += BigInt(tier.multiplierBps) * BigInt(tier.tickets);\n }\n return Number(weighted / BigInt(TICKETS));\n}\n","/**\n * Every program-derived address a client needs.\n *\n * The three gabox PDAs come from the generated tree, which Codama built from the IDL's own seed\n * metadata. Re-exported here so callers have one import, and so the seeds stay in exactly one\n * place. The two written by hand are the ones Codama cannot generate: an ATA, and a PDA that lives\n * under a program other than ours.\n */\n\nimport {\n getAddressEncoder,\n getBytesEncoder,\n getProgramDerivedAddress,\n type Address,\n type ProgramDerivedAddress,\n} from '@solana/kit';\n\nimport {\n ASSOCIATED_TOKEN_PROGRAM_ADDRESS,\n GABOX_PROGRAM_ID,\n IDENTITY_SEED,\n PROTOCOL_FEE_COLLECTOR,\n TOKEN_2022_PROGRAM_ADDRESS,\n TOKEN_PROGRAM_ADDRESS,\n VRF_PROGRAM_ADDRESS,\n WSOL_MINT,\n} from './ids';\nimport { findDrawPda } from './generated/pdas/draw';\nimport { findIdentityPda } from './generated/pdas/identity';\nimport { findPoolPda } from './generated/pdas/pool';\nimport { findReferralPda } from './generated/pdas/referral';\nimport { findReferralLinkPda } from './generated/pdas/referralLink';\n\nexport { findDrawPda, findIdentityPda, findPoolPda, findReferralLinkPda };\n\n/** `['referral', referee]`. A wallet's permanent referral binding. */\nexport async function referralLinkAddress(referee: Address): Promise<Address> {\n return (await findReferralLinkPda({ purchaser: referee }))[0];\n}\n\n/** `['referral', pool, referrer]`. A referrer's accrued rewards for one pool. */\nexport async function referralAddress(pool: Address, referrer: Address): Promise<Address> {\n // The generated seed is named referralLink because Anchor cannot express the field read from\n // that optional account. The on-chain seed is the referrer's address, so pass it explicitly.\n return (await findReferralPda({ pool, referralLink: referrer }))[0];\n}\n\n/** `[\"pool\", mint]`. One pool per coin, and the mint alone is the seed. */\nexport async function poolAddress(mint: Address): Promise<Address> {\n return (await findPoolPda({ mint }))[0];\n}\n\n/** `[\"draw\", pool, seq_u64_le]`. `seq` is `pool.nextSeq` at the moment of the purchase. */\nexport async function drawAddress(pool: Address, seq: bigint): Promise<Address> {\n return (await findDrawPda({ pool, seq }))[0];\n}\n\n/**\n * `[\"identity\"]` under gabox. This is the PDA gabox signs the VRF request with — the `identity`\n * account of the `Oracle` group on `buy_pack` and `retry_draw`.\n */\nexport async function vrfIdentityAddress(): Promise<Address> {\n return (await findIdentityPda())[0];\n}\n\n/**\n * `[\"identity\", gabox_program_id]` under the **VRF program**. A different address from\n * `vrfIdentityAddress`, and it belongs to the other side: MagicBlock signs the `deliver_draw`\n * callback with it. A client never puts it in an instruction. It is here so a client can recognise\n * the signer on a callback transaction.\n */\nexport async function scopedVrfIdentityAddress(): Promise<ProgramDerivedAddress> {\n return await getProgramDerivedAddress({\n programAddress: VRF_PROGRAM_ADDRESS,\n seeds: [getBytesEncoder().encode(IDENTITY_SEED), getAddressEncoder().encode(GABOX_PROGRAM_ID)],\n });\n}\n\n/**\n * An associated token account. The seed order is `[owner, token_program, mint]`, which is the ATA\n * program's own order and not the argument order most callers remember.\n */\nexport async function associatedTokenAddress(\n owner: Address,\n mint: Address,\n tokenProgram: Address = TOKEN_2022_PROGRAM_ADDRESS,\n): Promise<Address> {\n const encoder = getAddressEncoder();\n const [address] = await getProgramDerivedAddress({\n programAddress: ASSOCIATED_TOKEN_PROGRAM_ADDRESS,\n seeds: [encoder.encode(owner), encoder.encode(tokenProgram), encoder.encode(mint)],\n });\n return address;\n}\n\n/**\n * The protocol fee collector's WSOL ATA, under classic SPL Token. A sale on PumpSwap pays its\n * protocol fee here. The account must exist before the first PumpSwap sale; see `DEPLOYMENT.md`.\n */\nexport async function feeCollectorWsolAddress(): Promise<Address> {\n return await associatedTokenAddress(PROTOCOL_FEE_COLLECTOR, WSOL_MINT, TOKEN_PROGRAM_ADDRESS);\n}\n\n/**\n * The pool's prize inventory: the pool PDA's ATA for the mint's own token program.\n *\n * `tokenProgram` defaults to Token-2022 because Pump `create_v2` mints there, and every machine is\n * built on a coin Pump created. Pass the mint's real owner if you have it.\n */\nexport async function vaultAddress(\n mint: Address,\n tokenProgram: Address = TOKEN_2022_PROGRAM_ADDRESS,\n): Promise<Address> {\n return await associatedTokenAddress(await poolAddress(mint), mint, tokenProgram);\n}\n","/**\n * Reading gabox state: pools, draws, and the vault balance that turns a pool into an offer.\n *\n * The decoders are the generated ones. What this file adds is the queries — the discriminator and\n * `memcmp` filters that let a client list every machine, or every draw a wallet is waiting on,\n * without an indexer.\n *\n * # The offsets are computed, not counted\n *\n * A `memcmp` filter is a byte offset into an account. Counting field widths by hand is how a filter\n * silently matches nothing. Each offset below is built from the widths of the fields before it, in\n * the same order `state.rs` declares them, so the arithmetic is visible and a field inserted in the\n * middle changes it.\n */\n\nimport {\n fetchEncodedAccount,\n fetchEncodedAccounts,\n getBase58Decoder,\n getBase64Encoder,\n type Address,\n type Base58EncodedBytes,\n type MaybeAccount,\n type MaybeEncodedAccount,\n} from '@solana/kit';\n\nimport { DRAW_DISCRIMINATOR, decodeDraw, fetchMaybeDraw, type Draw } from './generated/accounts/draw';\nimport { POOL_DISCRIMINATOR, decodePool, getPoolSize, type Pool } from './generated/accounts/pool';\nimport { fetchMaybeReferral, type Referral } from './generated/accounts/referral';\nimport {\n REFERRAL_LINK_DISCRIMINATOR,\n decodeReferralLink,\n getReferralLinkSize,\n type ReferralLink,\n} from './generated/accounts/referralLink';\nimport { GABOX_PROGRAM_ID } from './ids';\nimport { quote, type Offer, type Tier } from './math';\nimport { poolAddress, referralAddress, vaultAddress } from './pdas';\nimport { tokenAccountAmount } from './pump/venue';\nimport type { GaboxClient, GaboxRpc } from './rpc';\n\nexport { decodeDraw, decodePool, DRAW_DISCRIMINATOR, POOL_DISCRIMINATOR };\nexport type { Draw, Pool };\nexport type { Referral, ReferralLink };\n\nconst DISCRIMINATOR = 8;\nconst PUBKEY = 32;\n\n/** `Draw.pool` sits straight after the discriminator. */\nexport const DRAW_POOL_OFFSET = DISCRIMINATOR;\n/** `Draw.purchaser` sits after the discriminator and `pool`. */\nexport const DRAW_PURCHASER_OFFSET = DISCRIMINATOR + PUBKEY;\n/** `Pool.creator` sits straight after the discriminator. */\nexport const POOL_CREATOR_OFFSET = DISCRIMINATOR;\n/** `Pool.mint` sits after the discriminator and `creator`. */\nexport const POOL_MINT_OFFSET = DISCRIMINATOR + PUBKEY;\n/** `ReferralLink.referrer` sits after the discriminator and `referee`. */\nexport const REFERRAL_LINK_REFERRER_OFFSET = DISCRIMINATOR + PUBKEY;\n\nconst base58 = getBase58Decoder();\nconst base64 = getBase64Encoder();\n\n/** A `memcmp` filter wants base58, and both discriminators and addresses arrive as other things. */\nconst asBase58 = (bytes: Uint8Array): Base58EncodedBytes =>\n base58.decode(bytes) as Base58EncodedBytes;\n\ntype ProgramAccountFilter = {\n memcmp: { offset: bigint; bytes: Base58EncodedBytes; encoding: 'base58' };\n} | { dataSize: bigint };\n\nconst memcmp = (offset: number, bytes: Base58EncodedBytes): ProgramAccountFilter => ({\n memcmp: { offset: BigInt(offset), bytes, encoding: 'base58' },\n});\n\nasync function scan<T>(\n rpc: GaboxRpc,\n filters: ProgramAccountFilter[],\n decode: (account: { address: Address; data: Uint8Array }) => T,\n): Promise<T[]> {\n const accounts = await rpc\n .getProgramAccounts(GABOX_PROGRAM_ID, {\n encoding: 'base64',\n commitment: 'confirmed',\n filters,\n })\n .send();\n return accounts.map(({ pubkey, account }) =>\n decode({ address: pubkey, data: new Uint8Array(base64.encode(account.data[0])) }),\n );\n}\n\n/** Wrap raw bytes in the shape the generated decoders expect. */\nconst encoded = (address: Address, data: Uint8Array) => ({\n address,\n data,\n executable: false,\n lamports: 0n as never,\n programAddress: GABOX_PROGRAM_ID,\n space: BigInt(data.length),\n});\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Single accounts\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** The pool for a coin, or `null` when the coin has no machine. */\nexport async function fetchPoolByMint(client: GaboxClient, mint: Address): Promise<Pool | null> {\n return await fetchPoolAt(client, await poolAddress(mint));\n}\n\n/**\n * A pool by its own address, or `null`.\n *\n * `fetchPoolByMint` is the usual way in, because a coin's mint is the natural key. This one is for\n * the other direction: a `Draw` names its pool and not its mint, so a client holding a draw reads\n * the pool to learn which coin it belongs to.\n */\nexport async function fetchPoolAt(client: GaboxClient, address: Address): Promise<Pool | null> {\n const account = await fetchEncodedAccount(client.rpc, address, { commitment: 'confirmed' });\n return decodeCurrentPool(account);\n}\n\n/** `null` for a missing pool; an error for one on the older devnet layout. */\nfunction decodeCurrentPool(account: MaybeEncodedAccount): Pool | null {\n if (!account.exists) return null;\n if (account.data.length !== getPoolSize()) {\n throw new Error(`Machine ${account.address} uses an older devnet account layout and needs migration or recreation.`);\n }\n return decodePool(account).data;\n}\n\n/** A draw by address, or `null`. Delivered and legacy-claimed draws are closed. */\nexport async function fetchDraw(client: GaboxClient, address: Address): Promise<Draw | null> {\n const account: MaybeAccount<Draw> = await fetchMaybeDraw(client.rpc, address, {\n commitment: 'confirmed',\n });\n return account.exists ? account.data : null;\n}\n\n/** Accrued referral reward for one referrer and pool, or zero when no referred pack has settled. */\nexport async function fetchReferralReward(\n client: GaboxClient,\n pool: Address,\n referrer: Address,\n): Promise<Referral | null> {\n const address = await referralAddress(pool, referrer);\n const account = await fetchMaybeReferral(client.rpc, address, { commitment: 'confirmed' });\n return account.exists ? account.data : null;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Scans\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type PoolRecord = { address: Address; data: Pool };\nexport type DrawRecord = { address: Address; data: Draw };\n\n/**\n * Every current-layout machine, by discriminator and account size. Older devnet\n * pools predate seed fields and must not be decoded with the current schema.\n *\n * There is no on-chain registry — the design says so on purpose — so discovery is this scan plus\n * the `PoolCreated` event. Public RPCs limit `getProgramAccounts`, so an app that lists machines\n * for users should cache the result rather than call this per page view.\n */\nexport async function listPools(client: GaboxClient): Promise<PoolRecord[]> {\n return await scan(client.rpc, [\n memcmp(0, asBase58(POOL_DISCRIMINATOR as Uint8Array)),\n { dataSize: BigInt(getPoolSize()) },\n ], ({ address, data }) => ({\n address,\n data: decodePool(encoded(address, data)).data,\n }));\n}\n\n/** Every draw of one pool, pending or ready. Closed draws are gone and never appear. */\nexport async function listDrawsByPool(client: GaboxClient, pool: Address): Promise<DrawRecord[]> {\n return await listDraws(client, { pool });\n}\n\n/**\n * Every open draw of one wallet, across all pools. This is the \"what am I owed\" query.\n *\n * An address is already base58, so it goes into the filter unchanged.\n */\nexport async function listDrawsByPurchaser(\n client: GaboxClient,\n purchaser: Address,\n): Promise<DrawRecord[]> {\n return await listDraws(client, { purchaser });\n}\n\nexport type DrawQuery = {\n /** A pool PDA. */\n pool?: Address;\n /** A buyer's wallet. */\n purchaser?: Address;\n};\n\n/**\n * Open draws, narrowed by pool, by purchaser, or by both.\n *\n * Both filters in one scan, because a UI asks for exactly that: \"my pulls on this machine\". Two\n * separate scans and an intersection in the client would move twice the bytes and could disagree\n * with itself, since the two reads happen at different slots. With neither filter this lists every\n * open draw of every machine.\n */\nexport async function listDraws(client: GaboxClient, query: DrawQuery = {}): Promise<DrawRecord[]> {\n const filters = [memcmp(0, asBase58(DRAW_DISCRIMINATOR as Uint8Array))];\n if (query.pool) {\n filters.push(memcmp(DRAW_POOL_OFFSET, query.pool as unknown as Base58EncodedBytes));\n }\n if (query.purchaser) {\n filters.push(memcmp(DRAW_PURCHASER_OFFSET, query.purchaser as unknown as Base58EncodedBytes));\n }\n return await scan(client.rpc, filters, ({ address, data }) => ({\n address,\n data: decodeDraw(encoded(address, data)).data,\n }));\n}\n\nexport type ReferralLinkRecord = { address: Address; data: ReferralLink };\n\n/**\n * Every wallet bound to one referrer. This is the \"who did I refer\" query.\n *\n * A scan, because a link is seeded on the referee and nothing on chain indexes it by referrer.\n * The list is small in practice, and a dashboard reads it once per load, not per poll.\n */\nexport async function listReferralLinksByReferrer(\n client: GaboxClient,\n referrer: Address,\n): Promise<ReferralLinkRecord[]> {\n return await scan(client.rpc, [\n memcmp(0, asBase58(REFERRAL_LINK_DISCRIMINATOR as Uint8Array)),\n { dataSize: BigInt(getReferralLinkSize()) },\n memcmp(REFERRAL_LINK_REFERRER_OFFSET, referrer as unknown as Base58EncodedBytes),\n ], ({ address, data }) => ({\n address,\n data: decodeReferralLink(encoded(address, data)).data,\n }));\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Inventory\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** The vault's token balance. `0` when the vault does not exist yet. */\nexport async function fetchVaultBalance(\n client: GaboxClient,\n mint: Address,\n tokenProgram?: Address,\n): Promise<bigint> {\n const vault = await vaultAddress(mint, tokenProgram);\n const { value } = await client.rpc\n .getAccountInfo(vault, { encoding: 'base64', commitment: 'confirmed' })\n .send();\n if (!value) return 0n;\n return tokenAccountAmount(new Uint8Array(base64.encode(value.data[0])));\n}\n\nexport type PoolInventory = {\n pool: Pool;\n poolAddress: Address;\n vault: Address;\n /** The vault's whole token balance. */\n inventory: bigint;\n /** `pool.reserved`: maximum awards reserved by pending draws. */\n reserved: bigint;\n /** `inventory - reserved`. What a new pack's prizes can be paid from, besides its own tokens. */\n free: bigint;\n};\n\n/**\n * A pool with its live inventory. This is the pair every price display needs: the tiers are\n * immutable, but what they actually pay depends on what is free in the vault right now.\n *\n * # Why one request reads both accounts\n *\n * The oracle callback lowers the vault and `pool.reserved` in one transaction, a few seconds after\n * a buy. Two separate reads can land on either side of it: the old `reserved` with the new, smaller\n * vault. That pair looks insolvent, and `quote` rightly refuses it. One `getMultipleAccounts` call\n * returns both accounts from the same slot, so the pair is always one the chain actually held.\n */\nexport async function fetchPoolInventory(\n client: GaboxClient,\n mint: Address,\n): Promise<PoolInventory | null> {\n const address = await poolAddress(mint);\n const readPair = async (vault: Address) => {\n // The explicit tuple type keeps the result a pair rather than an array of maybes.\n const [poolAccount, vaultAccount] = await fetchEncodedAccounts<[string, string]>(\n client.rpc,\n [address, vault],\n { commitment: 'confirmed' },\n );\n const pool = decodeCurrentPool(poolAccount);\n if (!pool) return null;\n const inventory = vaultAccount.exists ? tokenAccountAmount(vaultAccount.data) : 0n;\n return { pool, inventory };\n };\n // Every machine's coin is a Token-2022 mint, so this is the vault in practice. The pool is still\n // the authority: if it names a different vault, read that one together with the pool again.\n const expectedVault = await vaultAddress(mint);\n let pair = await readPair(expectedVault);\n if (pair && pair.pool.vault !== expectedVault) pair = await readPair(pair.pool.vault);\n if (!pair) return null;\n const { pool, inventory } = pair;\n const reserved = pool.reserved;\n\n return {\n pool,\n poolAddress: address,\n vault: pool.vault,\n inventory,\n reserved,\n // A vault below its reservations is an invariant break, not a negative number to show.\n free: inventory >= reserved ? inventory - reserved : 0n,\n };\n}\n\n/** The generated `Tier` uses the same field names as `math.ts`, so this is only a widening. */\nexport const tiersOf = (pool: Pool): Tier[] =>\n pool.tiers.map((t) => ({ multiplierBps: t.multiplierBps, tickets: t.tickets }));\n\n/**\n * The offer a pack of `base` tokens would freeze against this inventory. Pure — the same\n * computation `buy_pack` performs, and the reason a client can show real amounts before paying.\n */\nexport const offerFor = (inventory: PoolInventory, base: bigint): Offer =>\n quote(base, tiersOf(inventory.pool), inventory.inventory, inventory.reserved);\n","/**\n * The two `ComputeBudget` instructions the transaction builders prepend.\n *\n * # Why every gabox transaction needs one\n *\n * The default budget is 200,000 compute units for the whole transaction. `buy_pack` alone does a\n * CPI into Pump (which does its own CPIs into two token programs and its fee program), a\n * `transfer_checked`, an account init, a system transfer, and a CPI into MagicBlock's VRF program\n * that allocates a request account. `createMachine` adds Pump's `create_v2` to that, which mints a\n * Token-2022 coin with metadata. Neither fits in the default, and nothing on chain can raise its\n * own budget.\n *\n * # The numbers are headroom, not measurements\n *\n * They have not been measured on chain. They sit comfortably above what these instruction mixes\n * plausibly cost and comfortably below the 1,400,000 ceiling. **Measure them on devnet before they\n * matter**, because the prioritisation fee is `price x requested limit`: a request that is three\n * times too large costs three times too much on every pack. Until then, treat them as a starting\n * point a caller may override.\n */\n\nimport {\n getStructEncoder,\n getU32Encoder,\n getU64Encoder,\n getU8Encoder,\n type Address,\n type Instruction,\n type InstructionWithData,\n type ReadonlyUint8Array,\n} from '@solana/kit';\n\nexport const COMPUTE_BUDGET_PROGRAM_ADDRESS =\n 'ComputeBudget111111111111111111111111111111' as Address;\n\n/** The runtime's per-transaction ceiling. A larger request is rejected outright. */\nexport const MAX_COMPUTE_UNIT_LIMIT = 1_400_000;\n\n/** What an instruction gets when no `SetComputeUnitLimit` is present. */\nexport const DEFAULT_COMPUTE_UNIT_LIMIT = 200_000;\n\n/**\n * UNVERIFIED: none of the three figures below has been measured on chain. They are headroom, chosen\n * above what these instruction mixes plausibly cost. Measure them on devnet before they matter: the\n * prioritisation fee is `price x requested limit`, so a request three times too large costs three\n * times too much on every pack.\n */\n\n/** Pump `create_v2` plus `initialize_pool` plus a seed buy, in one transaction. */\nexport const CREATE_MACHINE_COMPUTE_UNITS = 600_000;\n\n/** A venue buy, an escrow transfer, a draw init and a VRF request. */\nexport const BUY_PACK_COMPUTE_UNITS = 500_000;\n\n/** A vault transfer, or a vault transfer plus a venue sale. */\nexport const REDEEM_COMPUTE_UNITS = 300_000;\n\n/** `bind_referrer` riding ahead of a pack: one small account init. */\nexport const BIND_REFERRER_COMPUTE_UNITS = 50_000;\n\n/** `ComputeBudgetInstruction`'s discriminants. Positional and append-only upstream. */\nconst SET_COMPUTE_UNIT_LIMIT = 2;\nconst SET_COMPUTE_UNIT_PRICE = 3;\n\n/** `[u8 discriminant, u32 units]` — five bytes. */\nconst LIMIT_ENCODER = getStructEncoder([\n ['discriminant', getU8Encoder()],\n ['units', getU32Encoder()],\n]);\n\n/** `[u8 discriminant, u64 microLamports]` — nine bytes. */\nconst PRICE_ENCODER = getStructEncoder([\n ['discriminant', getU8Encoder()],\n ['microLamports', getU64Encoder()],\n]);\n\n/** An instruction for the compute budget program: no accounts, all of it in the data. */\nexport type ComputeBudgetInstruction = Instruction<string, readonly []> &\n InstructionWithData<ReadonlyUint8Array>;\n\nexport function getSetComputeUnitLimitInstruction(units: number): ComputeBudgetInstruction {\n if (!Number.isInteger(units) || units < 0 || units > MAX_COMPUTE_UNIT_LIMIT) {\n throw new Error(\n `compute unit limit must be an integer in 0..=${MAX_COMPUTE_UNIT_LIMIT}, got ${units}`,\n );\n }\n return {\n programAddress: COMPUTE_BUDGET_PROGRAM_ADDRESS,\n accounts: [],\n data: LIMIT_ENCODER.encode({ discriminant: SET_COMPUTE_UNIT_LIMIT, units }),\n };\n}\n\n/**\n * `SetComputeUnitPrice(microLamports)` — the priority fee, per compute unit.\n *\n * No default, deliberately. The fee that lands a transaction is a property of the network at the\n * moment you send it. A hardcoded price is either money burnt on an idle chain or a transaction\n * that quietly stops landing under load. Sample `getRecentPrioritizationFees`, or take it from\n * config.\n */\nexport function getSetComputeUnitPriceInstruction(\n microLamports: number | bigint,\n): ComputeBudgetInstruction {\n const price = BigInt(microLamports);\n if (price < 0n) throw new Error(`compute unit price must not be negative, got ${price}`);\n return {\n programAddress: COMPUTE_BUDGET_PROGRAM_ADDRESS,\n accounts: [],\n data: PRICE_ENCODER.encode({ discriminant: SET_COMPUTE_UNIT_PRICE, microLamports: price }),\n };\n}\n\n/** The compute budget prefix a builder prepends: a limit, and a price only when one is asked for. */\nexport function computeBudgetInstructions(\n units: number,\n microLamports?: number | bigint,\n): ComputeBudgetInstruction[] {\n const instructions = [getSetComputeUnitLimitInstruction(units)];\n if (microLamports !== undefined) {\n instructions.push(getSetComputeUnitPriceInstruction(microLamports));\n }\n return instructions;\n}\n","/**\n * Events, and waiting for a draw to resolve.\n *\n * # Where the events are\n *\n * Anchor's `emit!` writes the event through `sol_log_data`, which the runtime renders as a log line\n * `Program data: <base64>`. So decoding an event is: find those lines, base64-decode each one,\n * match the first eight bytes against a discriminator, and hand the rest to the generated decoder.\n *\n * The design leans on this. There is no on-chain market registry, so `PoolCreated` is how a new\n * machine is discovered, and `DrawResolved` stays readable after the `Draw` account is closed and\n * its rent returned. The event is the audit trail; the account is only the pending state.\n *\n * # Waiting\n *\n * `watchDraw` subscribes to the draw account. A normal callback, retry callback, or expiry\n * delivers the prize and closes that account; the watcher then reconstructs the result from the\n * transaction's `PackBought` and `DrawResolved` events. It also accepts a legacy open `Ready`\n * account from a callback requested before automatic delivery.\n */\n\nimport {\n getBase64Encoder,\n type Address,\n type ReadonlyUint8Array,\n} from '@solana/kit';\n\nimport { DRAW_DISCRIMINATOR, decodeDraw, type Draw } from './generated/accounts/draw';\nimport {\n DRAW_RESOLVED_EVENT_DISCRIMINATOR,\n getDrawResolvedEventDecoder,\n type DrawResolvedEvent,\n} from './generated/events/drawResolved';\nimport {\n PACK_BOUGHT_EVENT_DISCRIMINATOR,\n getPackBoughtEventDecoder,\n type PackBoughtEvent,\n} from './generated/events/packBought';\nimport {\n POOL_CREATED_EVENT_DISCRIMINATOR,\n getPoolCreatedEventDecoder,\n type PoolCreatedEvent,\n} from './generated/events/poolCreated';\nimport {\n PRIZE_REDEEMED_EVENT_DISCRIMINATOR,\n getPrizeRedeemedEventDecoder,\n type PrizeRedeemedEvent,\n} from './generated/events/prizeRedeemed';\nimport {\n PRIZES_FUNDED_EVENT_DISCRIMINATOR,\n getPrizesFundedEventDecoder,\n type PrizesFundedEvent,\n} from './generated/events/prizesFunded';\nimport {\n RANDOMNESS_RETRIED_EVENT_DISCRIMINATOR,\n getRandomnessRetriedEventDecoder,\n type RandomnessRetriedEvent,\n} from './generated/events/randomnessRetried';\nimport {\n TOKENS_SOLD_EVENT_DISCRIMINATOR,\n getTokensSoldEventDecoder,\n type TokensSoldEvent,\n} from './generated/events/tokensSold';\nimport { GABOX_PROGRAM_ID } from './ids';\nimport { DrawStatus } from './generated/types/drawStatus';\nimport { findDrawPda } from './generated/pdas/draw';\nimport type { GaboxClient, GaboxRpc } from './rpc';\n\nexport type GaboxEvent =\n | { name: 'PoolCreated'; data: PoolCreatedEvent }\n | { name: 'PrizesFunded'; data: PrizesFundedEvent }\n | { name: 'PackBought'; data: PackBoughtEvent }\n | { name: 'RandomnessRetried'; data: RandomnessRetriedEvent }\n | { name: 'DrawResolved'; data: DrawResolvedEvent }\n | { name: 'PrizeRedeemed'; data: PrizeRedeemedEvent }\n | { name: 'TokensSold'; data: TokensSoldEvent };\n\nconst base64 = getBase64Encoder();\n\nconst startsWith = (data: Uint8Array, discriminator: ReadonlyUint8Array): boolean => {\n if (data.length < discriminator.length) return false;\n for (let i = 0; i < discriminator.length; i++) if (data[i] !== discriminator[i]) return false;\n return true;\n};\n\n/** The prefix Anchor's `emit!` produces. Anything else in the log is not an event. */\nconst PROGRAM_DATA = 'Program data: ';\n\n/** Decode one `Program data:` payload, or `null` when it is not one of ours. */\nexport function decodeEvent(data: Uint8Array): GaboxEvent | null {\n if (startsWith(data, POOL_CREATED_EVENT_DISCRIMINATOR)) {\n return { name: 'PoolCreated', data: getPoolCreatedEventDecoder().decode(data) };\n }\n if (startsWith(data, PRIZES_FUNDED_EVENT_DISCRIMINATOR)) {\n return { name: 'PrizesFunded', data: getPrizesFundedEventDecoder().decode(data) };\n }\n if (startsWith(data, PACK_BOUGHT_EVENT_DISCRIMINATOR)) {\n return { name: 'PackBought', data: getPackBoughtEventDecoder().decode(data) };\n }\n if (startsWith(data, RANDOMNESS_RETRIED_EVENT_DISCRIMINATOR)) {\n return { name: 'RandomnessRetried', data: getRandomnessRetriedEventDecoder().decode(data) };\n }\n if (startsWith(data, DRAW_RESOLVED_EVENT_DISCRIMINATOR)) {\n return { name: 'DrawResolved', data: getDrawResolvedEventDecoder().decode(data) };\n }\n if (startsWith(data, PRIZE_REDEEMED_EVENT_DISCRIMINATOR)) {\n return { name: 'PrizeRedeemed', data: getPrizeRedeemedEventDecoder().decode(data) };\n }\n if (startsWith(data, TOKENS_SOLD_EVENT_DISCRIMINATOR)) {\n return { name: 'TokensSold', data: getTokensSoldEventDecoder().decode(data) };\n }\n return null;\n}\n\n/**\n * Every gabox event in a transaction's logs, in order.\n *\n * A log line that is not `Program data:`, or whose payload matches no discriminator, is skipped\n * rather than reported. Another program in the same transaction emits its own events, and they are\n * not an error here.\n */\nexport function decodeEvents(logs: readonly string[]): GaboxEvent[] {\n const events: GaboxEvent[] = [];\n for (const line of logs) {\n if (!line.startsWith(PROGRAM_DATA)) continue;\n const payload = line.slice(PROGRAM_DATA.length).trim();\n let bytes: Uint8Array;\n try {\n bytes = new Uint8Array(base64.encode(payload));\n } catch {\n continue;\n }\n const event = decodeEvent(bytes);\n if (event) events.push(event);\n }\n return events;\n}\n\n/** Fetch a transaction and decode the gabox events it emitted. */\nexport async function fetchEvents(client: GaboxClient, signature: string): Promise<GaboxEvent[]> {\n return await readEvents(client.rpc, signature);\n}\n\n/** The RPC half of `fetchEvents`, for the internal readers that already hold one. */\nasync function readEvents(rpc: GaboxRpc, signature: string): Promise<GaboxEvent[]> {\n const transaction = await rpc\n .getTransaction(signature as never, {\n commitment: 'confirmed',\n encoding: 'json',\n maxSupportedTransactionVersion: 0,\n })\n .send();\n return decodeEvents(transaction?.meta?.logMessages ?? []);\n}\n\nexport { GABOX_PROGRAM_ID };\n\n// ─────────────────────────────────────────────────────────────────────────────\n// watchDraw\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type WatchDrawOptions = {\n /** Stop watching. The returned promise then rejects with the abort reason. */\n signal?: AbortSignal;\n /** Called on every account change, including the ones that are still `Pending`. */\n onChange?: (draw: Draw) => void;\n};\n\n/**\n * Watch one draw and resolve when its callback delivers the prize.\n *\n * The first notification is the account as it is now, so a draw that resolved before the call\n * resolves the promise immediately. Automatic delivery closes the account, so the watcher rebuilds\n * the resolved snapshot from the purchase and resolution events when it sees that closure.\n *\n * There is no timeout here on purpose. The program's own deadline is 216,000 slots, which is about\n * a day, and a UI should decide its own patience rather than inherit one.\n */\nexport async function watchDraw(\n client: GaboxClient,\n address: Address,\n options: WatchDrawOptions = {},\n): Promise<Draw> {\n const { rpc, rpcSubscriptions } = client;\n const controller = new AbortController();\n const abort = () => controller.abort(options.signal?.reason);\n options.signal?.addEventListener('abort', abort, { once: true });\n\n try {\n const notifications = await rpcSubscriptions\n .accountNotifications(address, { encoding: 'base64', commitment: 'confirmed' })\n .subscribe({ abortSignal: controller.signal });\n\n // The subscription only fires on a change, so read the account once first. A draw that is\n // already `Ready` would otherwise wait for a notification that never comes.\n const current = await readDraw(rpc, address);\n if (current) {\n options.onChange?.(current);\n if (current.status === DrawStatus.Ready) return current;\n } else {\n const delivered = await readDeliveredDraw(rpc, address);\n if (delivered) return delivered;\n }\n\n for await (const notification of notifications) {\n const account = notification.value;\n if (!account || account.data[0] === '') {\n for (let attempt = 0; attempt < 10; attempt++) {\n const delivered = await readDeliveredDraw(rpc, address);\n if (delivered) return delivered;\n await new Promise((resolve) => setTimeout(resolve, 500));\n }\n throw new Error(`draw ${address} closed before its resolution event became readable`);\n }\n const draw = decodeDrawBytes(address, new Uint8Array(base64.encode(account.data[0])));\n options.onChange?.(draw);\n if (draw.status === DrawStatus.Ready) return draw;\n }\n throw new Error(`the subscription for draw ${address} ended before it resolved`);\n } finally {\n options.signal?.removeEventListener('abort', abort);\n controller.abort();\n }\n}\n\nfunction decodeDrawBytes(address: Address, data: Uint8Array): Draw {\n return decodeDraw({\n address,\n data,\n executable: false,\n lamports: 0n as never,\n programAddress: GABOX_PROGRAM_ID,\n space: BigInt(data.length),\n }).data;\n}\n\nasync function readDraw(rpc: GaboxRpc, address: Address): Promise<Draw | null> {\n const { value } = await rpc\n .getAccountInfo(address, { encoding: 'base64', commitment: 'confirmed' })\n .send();\n if (!value) return null;\n return decodeDrawBytes(address, new Uint8Array(base64.encode(value.data[0])));\n}\n\n/** Recover the final snapshot after automatic delivery closed the draw account. */\nasync function readDeliveredDraw(rpc: GaboxRpc, address: Address): Promise<Draw | null> {\n const signatures = await rpc\n .getSignaturesForAddress(address, { commitment: 'confirmed', limit: 10 })\n .send();\n const rows = await Promise.all(\n signatures\n .filter((row) => !row.err)\n .map(async (row) => ({\n slot: row.slot,\n events: await readEvents(rpc, row.signature),\n })),\n );\n const bought = rows.flatMap((row) =>\n row.events.flatMap((event) =>\n event.name === 'PackBought' ? [{ slot: row.slot, data: event.data }] : [],\n ),\n )[0];\n const resolved = rows.flatMap((row) =>\n row.events.flatMap((event) =>\n event.name === 'DrawResolved' ? [{ slot: row.slot, data: event.data }] : [],\n ),\n )[0];\n if (!bought || !resolved) return null;\n if (\n bought.data.pool !== resolved.data.pool ||\n bought.data.seq !== resolved.data.seq ||\n bought.data.purchaser !== resolved.data.purchaser\n ) return null;\n const [derived, bump] = await findDrawPda({ pool: bought.data.pool, seq: bought.data.seq });\n if (derived !== address) return null;\n const ticketed = bought.data.prizes.filter((prize) => prize.tickets > 0);\n if (ticketed.length === 0) return null;\n const retries = rows.flatMap((row) =>\n row.events.flatMap((event) =>\n event.name === 'RandomnessRetried' &&\n event.data.pool === bought.data.pool &&\n event.data.seq === bought.data.seq\n ? [{ slot: row.slot, attempt: event.data.attempt }]\n : [],\n ),\n );\n const lastRetry = retries.reduce<(typeof retries)[number] | null>(\n (latest, row) => !latest || row.slot > latest.slot ? row : latest,\n null,\n );\n return {\n discriminator: DRAW_DISCRIMINATOR,\n pool: bought.data.pool,\n purchaser: bought.data.purchaser,\n seq: bought.data.seq,\n bump,\n status: DrawStatus.Ready,\n requestSlot: bought.slot,\n lastAttemptSlot: lastRetry?.slot ?? bought.slot,\n attempts: lastRetry?.attempt ?? 1,\n maximum: ticketed.reduce((a, prize) => a > prize.amount ? a : prize.amount, 0n),\n minimum: ticketed.reduce((a, prize) => a < prize.amount ? a : prize.amount, ticketed[0]!.amount),\n prizes: bought.data.prizes,\n amount: resolved.data.amount,\n randomness: resolved.data.randomness,\n timedOut: resolved.data.timedOut,\n };\n}\n","/**\n * Shared devnet address lookup table, verified on 2026-09-10T13:05:37.919Z.\n * Generated by scripts/deploy-lookup-table.ts. Existing indices are immutable;\n * keep this table active while clients use it. Authority is the devnet deploy wallet.\n */\nimport { address, type Address, type AddressesByLookupTableAddress } from '@solana/kit';\n\nimport type { Cluster } from './rpc';\n\nexport const DEVNET_LOOKUP_TABLE_ADDRESS = address('Cx4ri1BU2bnDXPjnJykF3nbY2u4MD5pPvzFCJtNizWFa');\nexport const DEVNET_LOOKUP_TABLE_ADDRESSES: readonly Address[] = [\n address('GaBoxR9nYcK1zeu8EvSJVHV3SrYpCFmvbh2MLgobMcUA'),\n address('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'),\n address('TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'),\n address('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL'),\n address('6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P'),\n address('pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA'),\n address('pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ'),\n address('11111111111111111111111111111111'),\n address('MAyhSmzXzV1pTf7LsNkrNwkWKTo4ougAJ1PPg47MD4e'),\n address('So11111111111111111111111111111111111111112'),\n address('Vrf1RNUjXmQGjmQrQLvJHs9SNkvDJEsRVFPkfSQUwGz'),\n address('Cuj97ggrhhidhbu39TijNVqE74xvKJ69gDervRUXAxGh'),\n address('SysvarS1otHashes111111111111111111111111111'),\n address('Sysvar1nstructions1111111111111111111111111'),\n address('4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf'),\n address('Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1'),\n address('8Wf5TiAheLUqBrKXeYg2JtAFFMWtKdG2BSFgqUcPVwTt'),\n address('Hq2wp8uJ9jCPsYgNHex8RtqdvMPfVGoYwjvF1ATiwn2Y'),\n address('TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM'),\n address('13ec7XdrjF3h3YcqBTFDSReRcUFwbCnJaAQspM4j6DDJ'),\n address('BwWK17cbHxwWBKZkUYvzxLcNQ1YVyaFezduWbtm2de6s'),\n address('ADyA8hdefvWN2dbGGWFotbzWxrAvLW83WG6QCVXvJKqw'),\n address('GS4CU59F31iL7aR2Q8zVS8DRrcRnXX1yjQ66TqNVQnaR'),\n address('5PHirr8joyTMp9JMm6nW7hNDVyEYdkzDqazxPD7RaTjx'),\n address('C2aFPdENg4A2HQsmrd5rTw5TaYBX5Ku887cWjbFKtZpw'),\n address('7ahYg76P8bhifT1Uj3hNHGKRFPp6bLkx1ppNrWbnsfu2'),\n address('68yFSZxzLWJXkxxRGydZ63C6mHx1NLEDWmwN9Lb5yySg'),\n address('DLP9ADYpdQV4Z4UQDZof7iLHu2qqdzmMPjcAHDGe4jTt'),\n address('6QgPshH1egekJ2TURfakiiApDdv98qfRuRe7RectX8xs'),\n address('FmFPTNDmmVDhqzaqZYhnt4fj5fJP3pffcMWf2b5JnRTk'),\n address('78i5hpHxbtmosSJdfJ74WzwdUr3eKWg9RbCPpBeAF78t'),\n address('7611SPS3UkjsA43auxPpJpPVAkgEHg4dTVorK839GonW'),\n address('8RMFYhsVsfdGCuWPFLxMCbSpSesiofabDdNorGqFrBNe'),\n address('9GbQXDFHKLdr4BzZ8Cx2pkX2aM2Kg7yEeYnUCKjZGE4M'),\n address('9GDepfBcjJMvNgmijXWVWa97Am7VZYCqXx7kJV44E9ij'),\n address('3fyMEgHADGRrBnCVLU7u9AwpiMtmGDWViJzDQC8kgRa5'),\n address('9ppkS5madL2uXozoEnMnZi5bKDq9jgdKkSavjWTS5NfW'),\n address('C3PvwRFdKT6caSLxnwy8h67KWNevoboNDg6bwJZYzWB5'),\n address('DDMCfwbcaNYTeMk1ca8tr8BQKFaUfFCWFwBJq8JcnyCw'),\n address('FrYoobDtL7w1HrTjHAc8Ya7qQzEdJPhGXXFKskCDaA3p'),\n address('DRDBsRMst21CJUhwD16pncgiXnBrFaRAPvA2G6SUQceE'),\n address('J7JbDVnGKus2M9PKzH7ZbeCYugEYDgpGBfqKL85dQbU7'),\n address('5YxQFdt3Tr9zJLvkFccqXVUwhdTWJQc1fFg2YPbxvxeD'),\n address('HjQjngTDqoHE6aaGhUqfz9aQ7WZcBRjy5xB8PScLSr8i'),\n address('9M4giFFMxmFGXtc3feFzRai56WbBqehoSeRE5GK7gf7'),\n address('GAFuhgcd328SkkBYHpfadzmef9hTGAFRCi9QoCnsZQug'),\n address('GXPFM2caqTtQYC2cJ5yJRi9VDkpsYZXzYdwYpGnLmtDL'),\n address('AktftA98kSWAxn6kVSoqBXBELUArjKu2H9WmKB48ULFY'),\n address('3BpXnfJaUTiwXnJNe7Ej1rcbzqTTQUvLShZaWazebsVR'),\n address('6rVkF4HSgy1jrnC3HogfRgPHrq4CtLg5f11URpsC4i9D'),\n address('5cjcW9wExnJJiqgLjq7DEG75Pm6JBgE1hNv4B2vHXUW6'),\n address('GYH1Gae1wJytMSvMvw8JVcv7nuAbxi8i9erNVbERnzXd'),\n address('EHAAiTxcdDwQ3U4bU6YcMsQGaekdzLS3B5SmYo46kJtL'),\n address('CA7v8gHfbquYXyDnDx6QxWW8hmL1H7X6Y2RYDrGLnuck'),\n address('5eHhjP8JaYkz83CWwvGU2uMUXefd3AazWGx4gpcuEEYD'),\n address('CASRL2zkwDnppxEFQ4LgdwgR9pdz5Q8R8nEMKVZ9QoLp'),\n address('A7hAgCzFw14fejgCp387JUJRMNyz4j89JKnhtKU8piqW'),\n address('qkYdTGRPHbWTWuBMz45bCiU6a23axRqf6sBHm9295WY'),\n address('12e2F4DKkD3Lff6WPYsU7Xd76SHPEyN9T8XSsTJNF8oT'),\n address('GjJkcak9e4L2HsxSZqVsc81L7coChdR7F3ciJYnQcSnU'),\n address('2Ej38XSkmpvXzoUg5ZLma7Y9rCiZVgxzTdvE3Kph5juM'),\n address('2daQRytJgLzLLziPNQBNJ7w1Ltz3XqZG4dZxBamLAf7v'),\n address('3PAxmkxnM2vHno9amWQCsaaFjYnPGcD87HZGx1ChVjPj'),\n address('BWS634asUFdrpYpfofFA1CrGB9wEbh9gt8XswZ4AWz9J'),\n address('4QZqaBNm2F7viBDhhs8AQ5wC9FshgLJEiLLFGoxZZrTn'),\n address('4JaPhJE7WgQZ3xFbxn2spU97reA13SiM99wD3RF4Lqro'),\n address('9xvDPD6G7NRCEu7W2M9vCLeo8we23Ww7pzQEhXcuJAmA'),\n address('AHEgRGXFn8JbhXccWM4i1meRGPFbx8kzb9BGN6ocqRFL'),\n address('CdkG7sp1LT9YLsDaTWREaQcX6W4gZySk3o1eSjoL2uTh'),\n address('2pLUmsYktT7gR6P5hXs9Ldo6Vg1oQB2Q4NPbJqHUjZhq'),\n address('Freijj9xKLefjrb5fHgT6KMbYG1XBP2mA83tqeXYUMYM'),\n address('4uzPz9TPskXiiEZ6X78rqud8LvfdxkJBr5EKHgbx4azP'),\n address('Hxzab4UjjVH2KjsdAqzdxGdYUpNN5FKhpu7iikB869uH'),\n address('Frkwunr9dQM9d4TthfQ2unxC994XpkLMpkRP2e7yfirk'),\n];\nexport const DEVNET_ADDRESS_LOOKUP_TABLES: AddressesByLookupTableAddress = {\n [DEVNET_LOOKUP_TABLE_ADDRESS]: [...DEVNET_LOOKUP_TABLE_ADDRESSES],\n};\n\n/**\n * The tables a client compresses with when its config names none.\n *\n * Only devnet has a shared table today. Mainnet gets one when the program is deployed there; until\n * then a mainnet or localnet client compresses with nothing, and a message over 1,232 bytes fails\n * in `buildMessage` with a request for tables. Pass `addressLookupTables` to `createClient` to\n * supply your own.\n */\nexport function defaultAddressLookupTables(cluster: Cluster): AddressesByLookupTableAddress {\n return cluster === 'devnet' ? { ...DEVNET_ADDRESS_LOOKUP_TABLES } : {};\n}\n","/**\n * What one pack costs and what it can win, right now, for a real coin.\n *\n * This is the read every buyer-facing screen makes. It puts three things together that are useless\n * apart:\n *\n * 1. the venue's own quote — what `pool.packTokens` costs at this moment, fees included;\n * 2. `math.quote` over the pack size and the vault's live inventory — the exact prize amounts\n * `buy_pack` would freeze into the `Draw`;\n * 3. whether the pool can pay the whole table.\n *\n * The prize amounts only move when the inventory cap bites. The price moves with the coin.\n * Nothing here is an estimate of cash value. Every number is tokens or lamports.\n */\n\nimport type { Address } from '@solana/kit';\n\nimport { fetchPoolInventory, tiersOf, type PoolInventory } from './accounts';\nimport { PROTOCOL_FEE_BPS } from './ids';\nimport {\n averageMultiplierBps,\n maxMultiplierBps,\n quote,\n seedTokens,\n share,\n uncappedMaximum,\n type Offer,\n type Prize,\n} from './math';\nimport { resolveVenue, type VenueKind } from './pump/venue';\nimport type { GaboxClient } from './rpc';\n\nexport type PackOffer = {\n mint: Address;\n pool: Address;\n /** The fixed token count of one pack. Every prize is a multiple of this. */\n packTokens: bigint;\n /** What the venue charges for `packTokens` right now, its own fees included. The pack price. */\n quoteLamports: bigint;\n /** The creator's fee, in bps of `quoteLamports`. */\n feeBps: number;\n /** The creator's fee at this price, paid on top of `quoteLamports`. */\n feeLamports: bigint;\n /** The protocol's 1% of `quoteLamports`, also paid on top. */\n protocolLamports: bigint;\n /** What the seed cost the creator at creation. Display only. */\n seedLamports: bigint;\n /** Tokens the seed locked in the vault: `(maxMultiplier - 1x)` packs. */\n seedTokens: bigint;\n /** Which venue the buy would route to right now. */\n venue: VenueKind;\n /** The frozen prize table this pack would get: real amounts, already capped by inventory. */\n prizes: Prize[];\n /** The top prize, after the cap. Sign `minMaximum` just below this. */\n maximum: bigint;\n /** The smallest prize. Also what a timed-out draw pays. */\n minimum: bigint;\n /** The top prize with no inventory cap: the jackpot in tokens. Equal to `maximum` unless the\n * inventory cap bites. */\n uncapped: bigint;\n /** Vault balance, `pool.reserved`, and the difference. */\n inventory: bigint;\n reserved: bigint;\n free: bigint;\n /** `pool.nextSeq === 0`. No pack has been sold yet. */\n isFirstPack: boolean;\n /**\n * Does the pool pay the whole table right now?\n *\n * `offer.maximum === uncapped`. The seed guarantees this for the first pack. Later it is a\n * quality signal: a capped top prize is legal and the pool still sells the pack. It just pays\n * less than the table says, and a buyer should see that.\n */\n isSeeded: boolean;\n /** The largest and the ticket-weighted average multiplier of the immutable table, in bps. */\n maxMultiplierBps: number;\n averageMultiplierBps: number;\n};\n\nexport type GetOfferOptions = {\n /** Force a venue instead of reading the bonding curve's `complete` flag. */\n venue?: VenueKind;\n /** The buyer, when you already know it. Only changes the account list, never the numbers. */\n user?: Address;\n};\n\n/**\n * The full offer for one machine. Two round trips: the pool and its vault, then the venue.\n *\n * Throws when the coin has no pool.\n */\nexport async function getOffer(\n client: GaboxClient,\n mint: Address,\n options: GetOfferOptions = {},\n): Promise<PackOffer> {\n const inventory = await fetchPoolInventory(client, mint);\n if (!inventory) throw new Error(`no gabox pool for mint ${mint}`);\n\n const venue = await resolveVenue(client, {\n mint,\n user: options.user ?? inventory.pool.creator,\n ...(options.venue ? { venue: options.venue } : {}),\n });\n\n return offerFromState(inventory, venue.kind, venue.quoteBuy(inventory.pool.packTokens));\n}\n\n/**\n * The same computation with the reads already done. Useful when a caller holds a `ResolvedVenue`\n * and wants to re-price without touching the network. `quoteLamports` is\n * `venue.quoteBuy(pool.packTokens)`.\n */\nexport function offerFromState(\n inventory: PoolInventory,\n venue: VenueKind,\n quoteLamports: bigint,\n): PackOffer {\n const { pool } = inventory;\n const tiers = tiersOf(pool);\n const offer: Offer = quote(pool.packTokens, tiers, inventory.inventory, inventory.reserved);\n const uncapped = uncappedMaximum(pool.packTokens, tiers);\n\n return {\n mint: pool.mint,\n pool: inventory.poolAddress,\n packTokens: pool.packTokens,\n quoteLamports,\n feeBps: pool.feeBps,\n feeLamports: share(quoteLamports, BigInt(pool.feeBps)),\n protocolLamports: share(quoteLamports, PROTOCOL_FEE_BPS),\n seedLamports: pool.seedLamports,\n seedTokens: pool.seedTokens,\n venue,\n prizes: offer.prizes,\n maximum: offer.maximum,\n minimum: offer.minimum,\n uncapped,\n inventory: inventory.inventory,\n reserved: inventory.reserved,\n free: inventory.free,\n isFirstPack: pool.nextSeq === 0n,\n isSeeded: offer.maximum === uncapped,\n maxMultiplierBps: maxMultiplierBps(tiers),\n averageMultiplierBps: averageMultiplierBps(tiers),\n };\n}\n\n/**\n * How short of the top prize a pool is, in tokens. `0` when it pays the whole table.\n *\n * The pack brings its own `packTokens` into the vault before the offer is computed, so the vault\n * only has to hold `uncapped - packTokens` beforehand. Anything already reserved by another draw\n * does not count. A donation of this size through `fund_prizes` uncaps the top prize again.\n */\nexport function seedShortfall(offer: PackOffer): bigint {\n const needed = offer.uncapped > offer.packTokens ? offer.uncapped - offer.packTokens : 0n;\n return offer.free >= needed ? 0n : needed - offer.free;\n}\n\nexport { seedTokens };\n","/**\n * The client, and the cluster guard.\n *\n * `createClient` is the SDK's init step. It takes the cluster and the RPC endpoint once and returns\n * one object that every other chain-touching function in this SDK takes as its first argument: the\n * RPC, the subscriptions client, and the address lookup tables that cluster compresses with.\n *\n * # Why `cluster` has no default\n *\n * v1's simulator was one empty wallet away from running against mainnet. Nothing in the code said\n * which cluster it was pointed at; the answer lived in a shell variable and in the operator's head.\n * The failure would not have been a crash. It would have been real transactions on real money,\n * discovered afterwards.\n *\n * So the cluster is a property of the code, not of the environment. The caller names it in the\n * same call that names the URL, and the two are checked against each other:\n *\n * - `devnet` needs a URL that names devnet. A URL that names nothing is refused too, because\n * \"I thought this was devnet\" is exactly the accident this guard exists for.\n * - `mainnet-beta` and `localnet` refuse a URL that names a different cluster. A URL that names\n * nothing is allowed: private mainnet endpoints often do not say \"mainnet\", and a local\n * validator never says anything.\n *\n * Mainnet is one word away. It is a word the caller has to write.\n */\n\nimport {\n createSolanaRpc,\n createSolanaRpcSubscriptions,\n type AddressesByLookupTableAddress,\n type Rpc,\n type RpcSubscriptions,\n type SolanaRpcApi,\n type SolanaRpcSubscriptionsApi,\n} from '@solana/kit';\n\nimport { defaultAddressLookupTables } from './lookupTables';\n\nexport type Cluster = 'devnet' | 'mainnet-beta' | 'localnet';\n\n/** Solana's public endpoints, and the test validator's default ports. */\nexport const CLUSTER_ENDPOINTS: Readonly<Record<Cluster, { url: string; wsUrl: string }>> = {\n devnet: { url: 'https://api.devnet.solana.com', wsUrl: 'wss://api.devnet.solana.com' },\n 'mainnet-beta': {\n url: 'https://api.mainnet-beta.solana.com',\n wsUrl: 'wss://api.mainnet-beta.solana.com',\n },\n localnet: { url: 'http://127.0.0.1:8899', wsUrl: 'ws://127.0.0.1:8900' },\n};\n\nexport const DEVNET_HTTP = CLUSTER_ENDPOINTS.devnet.url;\nexport const DEVNET_WS = CLUSTER_ENDPOINTS.devnet.wsUrl;\n\nexport type GaboxRpc = Rpc<SolanaRpcApi>;\nexport type GaboxRpcSubscriptions = RpcSubscriptions<SolanaRpcSubscriptionsApi>;\n\nexport type ClientConfig = {\n /** The cluster this client talks to. Required: see the file comment. */\n cluster: Cluster;\n /** HTTP endpoint. Defaults to the cluster's entry in `CLUSTER_ENDPOINTS`. */\n url?: string;\n /**\n * WebSocket endpoint. Left out, it follows `url`: `https` becomes `wss`, `http` becomes `ws`.\n * When `url` is left out too, it is the cluster's default.\n */\n wsUrl?: string;\n /**\n * Address lookup tables every builder compresses with. Defaults to the cluster's shared table,\n * which only devnet has today; other clusters default to none. Pass `{}` to disable compression.\n */\n addressLookupTables?: AddressesByLookupTableAddress;\n};\n\n/**\n * Everything the SDK needs to talk to one cluster. Pass it to every chain-touching function.\n *\n * A plain object, so a caller who needs a custom transport can spread it:\n * `{ ...createClient({ cluster }), rpc: createSolanaRpcFromTransport(transport) }`.\n */\nexport type GaboxClient = Readonly<{\n cluster: Cluster;\n url: string;\n wsUrl: string;\n rpc: GaboxRpc;\n rpcSubscriptions: GaboxRpcSubscriptions;\n addressLookupTables: AddressesByLookupTableAddress;\n}>;\n\n/**\n * The cluster a URL names, from its text alone. A substring check, deliberately: providers spell\n * it many ways. `null` when the URL names none, which is a local validator or a private endpoint.\n */\nexport function clusterNamedBy(url: string): Cluster | 'testnet' | null {\n const lower = url.toLowerCase();\n if (lower.includes('devnet')) return 'devnet';\n if (lower.includes('mainnet')) return 'mainnet-beta';\n if (lower.includes('testnet')) return 'testnet';\n return null;\n}\n\n/**\n * Refuse a URL that contradicts the declared cluster. Exported so a script can check a URL before\n * it does anything else with it. The rules are in the file comment.\n */\nexport function assertClusterUrl(cluster: Cluster, url: string): void {\n const named = clusterNamedBy(url);\n if (cluster === 'devnet' && named !== 'devnet') {\n throw new Error(\n `refusing to use ${url} as a devnet endpoint: it does not name devnet.\\n` +\n 'Every address in this SDK — the Pump programs, the MagicBlock queue, the pools — exists ' +\n 'on every cluster, so a wrong URL is a live transaction, not an error. Pass ' +\n \"{ cluster: 'localnet' } for a local validator, or name the cluster the URL really is.\",\n );\n }\n if (cluster !== 'devnet' && named !== null && named !== cluster) {\n throw new Error(\n `refusing to use ${url} as a ${cluster} endpoint: the URL names ${named}.\\n` +\n 'Every address in this SDK exists on every cluster, so a wrong URL is a live transaction, ' +\n 'not an error. Pass the cluster the URL really names.',\n );\n }\n}\n\n/** `https://x` becomes `wss://x`, `http://x` becomes `ws://x`. Anything else is returned as is. */\nexport function websocketUrlFor(url: string): string {\n if (url.startsWith('https://')) return `wss://${url.slice('https://'.length)}`;\n if (url.startsWith('http://')) return `ws://${url.slice('http://'.length)}`;\n return url;\n}\n\n/**\n * The SDK's init step. Call it once and pass the result everywhere.\n *\n * Both RPC clients are created together because everything in this SDK that watches a draw needs\n * the pair: the subscription reports the change, and the RPC reads the account that changed.\n */\nexport function createClient(config: ClientConfig): GaboxClient {\n const { cluster } = config;\n const defaults = CLUSTER_ENDPOINTS[cluster];\n if (!defaults) {\n throw new Error(\n `unknown cluster ${JSON.stringify(cluster)}; expected 'devnet', 'mainnet-beta' or 'localnet'`,\n );\n }\n\n const url = config.url ?? defaults.url;\n assertClusterUrl(cluster, url);\n\n // A custom `url` without a `wsUrl` gets the same host over WebSocket. The cluster's default\n // pair is only used as a pair: the test validator serves WebSocket on a different port.\n const wsUrl = config.wsUrl ?? (config.url === undefined ? defaults.wsUrl : websocketUrlFor(url));\n assertClusterUrl(cluster, wsUrl);\n\n return {\n cluster,\n url,\n wsUrl,\n rpc: createSolanaRpc(url),\n rpcSubscriptions: createSolanaRpcSubscriptions(wsUrl),\n addressLookupTables: config.addressLookupTables ?? defaultAddressLookupTables(cluster),\n };\n}\n","/**\n * Assembling a transaction message.\n *\n * Every builder in this directory ends here: compute budget first, then the program instructions,\n * with a fee payer and a blockhash lifetime. The result is a message a wallet can sign and send —\n * nothing in this SDK signs or sends anything itself.\n */\n\nimport {\n appendTransactionMessageInstructions,\n compileTransaction,\n compressTransactionMessageUsingAddressLookupTables,\n createTransactionMessage,\n getTransactionEncoder,\n pipe,\n setTransactionMessageFeePayerSigner,\n setTransactionMessageLifetimeUsingBlockhash,\n type AddressesByLookupTableAddress,\n type Instruction,\n type TransactionMessage,\n type TransactionMessageWithBlockhashLifetime,\n type TransactionMessageWithFeePayerSigner,\n type TransactionSigner,\n} from '@solana/kit';\n\nimport { computeBudgetInstructions } from '../compute';\nimport type { GaboxClient } from '../rpc';\n\n/**\n * What every builder returns: a version 0 message with a fee-payer signer and a blockhash\n * lifetime, ready for `signTransactionMessageWithSigners`.\n *\n * Named, and built only from types `@solana/kit` exports, so the published declaration file\n * refers to kit's types instead of copying them. `pipe`'s inferred type is a long intersection\n * of kit-internal brands, and a copy of a branded type is not assignable to the original.\n */\nexport type GaboxTransactionMessage = Extract<TransactionMessage, { version: 0 }> &\n TransactionMessageWithFeePayerSigner &\n TransactionMessageWithBlockhashLifetime;\n\nexport type BuildOptions = {\n /** Compute units to request. Each builder passes its own default. */\n computeUnitLimit: number;\n /** Priority fee in micro-lamports per compute unit. Left out, no price instruction is added. */\n computeUnitPrice?: number | bigint;\n /** Defaults to the client's tables, which the cluster chose. Pass `{}` to disable compression. */\n addressLookupTables?: AddressesByLookupTableAddress;\n};\n\n/**\n * Build the message. One RPC read, for the blockhash.\n *\n * The blockhash expires in about a minute, so build the message when the user is ready to sign\n * rather than when the page loads.\n */\nexport async function buildMessage(\n client: GaboxClient,\n feePayer: TransactionSigner,\n instructions: Instruction[],\n options: BuildOptions,\n): Promise<GaboxTransactionMessage> {\n const { value: latestBlockhash } = await client.rpc\n .getLatestBlockhash({ commitment: 'confirmed' })\n .send();\n\n const budget = computeBudgetInstructions(\n options.computeUnitLimit,\n options.computeUnitPrice,\n ) as unknown as Instruction[];\n\n const message = pipe(\n createTransactionMessage({ version: 0 }),\n (m) => setTransactionMessageFeePayerSigner(feePayer, m),\n (m) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),\n (m) => appendTransactionMessageInstructions([...budget, ...instructions], m),\n (m) => compressTransactionMessageUsingAddressLookupTables(\n m,\n options.addressLookupTables ?? client.addressLookupTables,\n ),\n );\n const size = getTransactionEncoder().encode(compileTransaction(message)).length;\n if (size > 1232) {\n throw new Error(`Transaction is ${size} bytes; Solana allows 1232. Shorten metadata or supply additional address lookup tables.`);\n }\n return message;\n}\n\n/** Append `remainingAccounts` to a generated instruction, which is how a venue's list is passed. */\nexport function withRemainingAccounts<T extends Instruction>(\n instruction: T,\n remaining: readonly NonNullable<T['accounts']>[number][],\n): T {\n return {\n ...instruction,\n accounts: [...(instruction.accounts ?? []), ...remaining],\n };\n}\n","import type { Address, Instruction, TransactionSigner } from '@solana/kit';\n\nimport { fetchMaybeReferralLink } from './generated/accounts/referralLink';\nimport { getBindReferrerInstructionAsync } from './generated/instructions/bindReferrer';\nimport { getClaimReferralInstructionAsync } from './generated/instructions/claimReferral';\nimport { referralAddress, referralLinkAddress } from './pdas';\nimport type { GaboxClient } from './rpc';\nimport { buildMessage, type BuildOptions } from './tx/message';\n\nexport type ReferralResolution = Readonly<{\n link: Address;\n referrer: Address;\n referral: Address;\n}>;\n\n/** Resolve the purchaser's permanent referral binding for a pack purchase. */\nexport async function resolveReferral(\n client: GaboxClient,\n purchaser: Address,\n pool: Address,\n): Promise<ReferralResolution | null> {\n const link = await referralLinkAddress(purchaser);\n const account = await fetchMaybeReferralLink(client.rpc, link, { commitment: 'confirmed' });\n if (!account.exists) return null;\n const referrer = account.data.referrer;\n return { link, referrer, referral: await referralAddress(pool, referrer) };\n}\n\n/** Bind a wallet to a referrer. The purchaser signs and the binding is permanent. */\nexport async function bindReferrer(\n client: GaboxClient,\n referee: TransactionSigner,\n referrer: Address,\n options: Partial<BuildOptions> = {},\n) {\n const ix = await getBindReferrerInstructionAsync({ referee, referrer });\n return await buildMessage(client, referee, [ix as Instruction], {\n addressLookupTables: options.addressLookupTables,\n computeUnitLimit: options.computeUnitLimit ?? 80_000,\n ...(options.computeUnitPrice === undefined ? {} : { computeUnitPrice: options.computeUnitPrice }),\n });\n}\n\n/** Claim all accrued referral rewards for one pool. */\nexport async function claimReferral(\n client: GaboxClient,\n referrer: TransactionSigner,\n pool: Address,\n options: Partial<BuildOptions> = {},\n) {\n const ix = await getClaimReferralInstructionAsync({ referrer, pool });\n return await buildMessage(client, referrer, [ix as Instruction], {\n addressLookupTables: options.addressLookupTables,\n computeUnitLimit: options.computeUnitLimit ?? 80_000,\n ...(options.computeUnitPrice === undefined ? {} : { computeUnitPrice: options.computeUnitPrice }),\n });\n}\n","/**\n * Buying a pack.\n *\n * One instruction does the whole thing: buy exactly `pool.packTokens` at the venue, move the\n * tokens into gabox custody, freeze a prize table into a new `Draw`, pay the creator's fee and\n * the protocol's 1% of the venue cost, and ask MagicBlock for randomness. Either all of it happens\n * or none of it does.\n *\n * # The three numbers the buyer signs\n *\n * `maxQuoteIn` is the slippage cap at the venue, in lamports (WSOL on PumpSwap). The token count\n * is fixed by the pool, so the cost is the only thing that moves. Set it from `offer.quoteLamports`\n * plus a margin, for example 2%.\n *\n * `minMaximum` is a floor on the top prize, in tokens. The table is fixed, so only an inventory\n * cap can lower it. Set it from `offer.maximum`.\n *\n * `maxTotalDebit` caps the venue debit plus the creator fee plus the protocol fee plus the VRF\n * request, measured in SOL and WSOL together. Both fees are a share of the venue debit, so budget\n * them from `maxQuoteIn`. It does **not** cover the rent Anchor pays for the `Draw` and any ATA it\n * creates, nor the transaction fee: the runtime charges those before the handler runs. Budget for\n * them separately.\n *\n * # PumpSwap needs WSOL first\n *\n * On the curve, Pump spends native SOL. On PumpSwap the quote is a classic WSOL token account, so\n * the buyer's WSOL ATA must exist and hold enough before the pack instruction runs. This builder\n * adds the create/fund/sync instructions when the route is PumpSwap. They are the buyer's own\n * instructions, signed by the buyer, and gabox never touches that account.\n */\n\nimport {\n getCreateAssociatedTokenIdempotentInstruction,\n getSyncNativeInstruction,\n TOKEN_PROGRAM_ADDRESS as SPL_TOKEN_PROGRAM_ADDRESS,\n} from '@solana-program/token';\nimport { getTransferSolInstruction } from '@solana-program/system';\nimport type { Address, Instruction, TransactionSigner } from '@solana/kit';\n\nimport { fetchPoolInventory } from '../accounts';\nimport { resolveReferral } from '../referral';\nimport { BIND_REFERRER_COMPUTE_UNITS, BUY_PACK_COMPUTE_UNITS } from '../compute';\nimport { getBindReferrerInstructionAsync } from '../generated/instructions/bindReferrer';\nimport { getBuyPackInstruction } from '../generated/instructions/buyPack';\nimport { WSOL_MINT } from '../ids';\nimport { drawAddress, referralAddress, referralLinkAddress, vrfIdentityAddress } from '../pdas';\nimport { swapCashbackAccount } from '../pump/accounts';\nimport { resolveVenue, wsolAccountFor, type VenueKind } from '../pump/venue';\nimport type { GaboxClient } from '../rpc';\nimport { buildMessage, withRemainingAccounts, type BuildOptions } from './message';\n\nexport type BuyPackInput = {\n mint: Address;\n /** Pays for everything and signs. Becomes `draw.purchaser`. */\n purchaser: TransactionSigner;\n /** Slippage cap on the venue trade, in lamports (WSOL on PumpSwap). Must be positive. */\n maxQuoteIn: bigint;\n /** Floor on the top prize, in tokens. */\n minMaximum: bigint;\n /** Cap on venue debit + creator fee + protocol fee + VRF request, in lamports. Rent and tx fee\n * are extra. */\n maxTotalDebit: bigint;\n /** Force a venue. Left out, the bonding curve's `complete` flag decides. */\n venue?: VenueKind;\n /**\n * Pin the draw's sequence number instead of reading `pool.nextSeq` now.\n *\n * The draw's address is `[\"draw\", pool, seq]`, so a caller that has already told somebody which\n * draw this purchase will create has to keep that promise if it rebuilds the message - after a\n * stale blockhash, say. Rebuilding without a pin reads `nextSeq` again, and if the first attempt\n * actually landed, the second one buys a **second pack** at the next sequence number rather than\n * failing. With the pin it fails on the `init` constraint, which is the right outcome.\n */\n seq?: bigint;\n /**\n * Lamports to wrap into the buyer's WSOL account on the PumpSwap route. Left out, the builder\n * wraps `maxQuoteIn`: the venue never takes more than that, and any surplus stays in the buyer's\n * own WSOL account.\n */\n wrapLamports?: bigint;\n /** Append PumpSwap's optional cashback account. Only for a cashback coin. */\n cashback?: boolean;\n /**\n * A referrer to bind before the purchase, in the same transaction.\n *\n * A share link leaves the referrer's wallet in a cookie, and the first pack is where it matters:\n * `bind_referrer` runs one instruction ahead of `buy_pack`, so the pack that converts the buyer\n * is the pack that pays. Ignored when the buyer already has a link (the chain wins), when it\n * names the buyer, or when it is the all-zero address. The link's rent is extra, on top of\n * `maxTotalDebit`.\n */\n referrer?: Address;\n} & Partial<BuildOptions>;\n\nexport async function buyPack(client: GaboxClient, input: BuyPackInput) {\n const { mint, purchaser } = input;\n if (input.maxQuoteIn <= 0n) throw new Error('maxQuoteIn must be positive');\n\n const inventory = await fetchPoolInventory(client, mint);\n if (!inventory) throw new Error(`no gabox pool for mint ${mint}`);\n const { pool, poolAddress } = inventory;\n\n const venue = await resolveVenue(client, {\n mint,\n user: purchaser.address,\n ...(input.venue ? { venue: input.venue } : {}),\n });\n\n // `pool.nextSeq` is read now and used as the draw's seed, unless the caller pinned one. Another\n // buyer landing first makes this address wrong and the transaction fails on the `init`\n // constraint — which is the right outcome: two buyers must not share a draw.\n const seq = input.seq ?? pool.nextSeq;\n const draw = await drawAddress(poolAddress, seq);\n let referral = await resolveReferral(client, purchaser.address, poolAddress);\n let bind: Instruction | null = null;\n if (referral === null && input.referrer && canBind(purchaser.address, input.referrer)) {\n const referrer = input.referrer;\n bind = (await getBindReferrerInstructionAsync({ referee: purchaser, referrer })) as Instruction;\n // `resolveReferral` cannot answer here: the link does not exist yet. The bind one instruction\n // earlier in this very transaction creates it, so the accounts are derived by hand.\n referral = {\n link: await referralLinkAddress(purchaser.address),\n referrer,\n referral: await referralAddress(poolAddress, referrer),\n };\n }\n\n const buy = getBuyPackInstruction({\n purchaser,\n pool: poolAddress,\n creator: pool.creator,\n draw,\n mint,\n vault: pool.vault,\n userTokens: venueUserTokens(venue.buyAccounts, venue.kind),\n venue: venue.program,\n identity: await vrfIdentityAddress(),\n tokenProgram: pool.tokenProgram,\n maxQuoteIn: input.maxQuoteIn,\n minMaximum: input.minMaximum,\n maxTotalDebit: input.maxTotalDebit,\n referralLink: referral?.link,\n referral: referral?.referral,\n });\n\n const remaining = input.cashback\n ? [...venue.buyAccounts, swapCashbackAccount(purchaser.address)]\n : venue.buyAccounts;\n\n const instructions: Instruction[] = [\n ...(bind === null ? [] : [bind]),\n ...(venue.kind === 'pumpswap'\n ? wsolPreparation(purchaser, input.wrapLamports ?? input.maxQuoteIn)\n : []),\n withRemainingAccounts(buy as Instruction, remaining),\n ];\n\n return await buildMessage(client, purchaser, instructions, {\n addressLookupTables: input.addressLookupTables,\n computeUnitLimit:\n input.computeUnitLimit ??\n BUY_PACK_COMPUTE_UNITS + (bind === null ? 0 : BIND_REFERRER_COMPUTE_UNITS),\n ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }),\n });\n}\n\n/** The default `Pubkey`: all zero bytes. `bind_referrer` refuses a link pointing at it. */\nconst NO_REFERRER = '11111111111111111111111111111111' as Address;\n\n/**\n * The program refuses a self-referral and a link to the all-zero address. Both would take the\n * pack down with them, so the bind is skipped instead and the pack goes through unreferred.\n */\nfunction canBind(purchaser: Address, referrer: Address): boolean {\n return referrer !== purchaser && referrer !== NO_REFERRER;\n}\n\n/**\n * The purchaser's base-token ATA, taken out of the venue account list rather than re-derived.\n *\n * `market.rs` requires `user_tokens` to equal the venue list's own `associated_base_user` (Pump) or\n * `user_base_token_account` (PumpSwap). Reading it back from the list makes the two agree by\n * construction instead of by two derivations that happen to match.\n */\nfunction venueUserTokens(accounts: readonly { address: Address }[], kind: VenueKind): Address {\n // Pump: index 14 is `associated_base_user`. PumpSwap: index 5 is `user_base_token_account`.\n const index = kind === 'pump' ? 14 : 5;\n const account = accounts[index];\n if (!account) throw new Error(`the ${kind} account list is too short`);\n return account.address;\n}\n\n/**\n * Create the buyer's WSOL account if needed, fund it, and sync its balance.\n *\n * `SyncNative` is the step people forget. A plain SOL transfer into a WSOL account raises its\n * lamports but not the `amount` field the token program reads, so the venue sees an empty account\n * until this instruction copies one to the other.\n */\nfunction wsolPreparation(purchaser: TransactionSigner, lamports: bigint): Instruction[] {\n const wsol = wsolAccountFor(purchaser.address);\n return [\n getCreateAssociatedTokenIdempotentInstruction({\n payer: purchaser,\n ata: wsol,\n owner: purchaser.address,\n mint: WSOL_MINT,\n tokenProgram: SPL_TOKEN_PROGRAM_ADDRESS,\n }) as Instruction,\n getTransferSolInstruction({ source: purchaser, destination: wsol, amount: lamports }) as Instruction,\n getSyncNativeInstruction({ account: wsol }) as Instruction,\n ];\n}\n","/**\n * Creating a machine: one transaction, two instructions, two signers.\n *\n * # Why it has to be one transaction\n *\n * `initialize_pool` reads the Instructions sysvar and refuses to run unless the same transaction\n * also carries a Pump `create_v2` for the same mint, signed by the same creator. That is what makes\n * \"one pool per coin\" true and stops anyone wrapping an existing coin in a machine. The create must\n * come **first**: the mint account has to exist and deserialize before Anchor validates\n * `initialize_pool`'s accounts.\n *\n * # The seed\n *\n * The creator owns none of the coin yet — it does not exist until this transaction runs. So\n * `initialize_pool` buys the seed on the curve itself, into the creator's own ATA, and moves it\n * straight into the vault. The Pump buy accounts ride along as `remainingAccounts`, in the same\n * order `buy_pack` uses.\n *\n * The seed follows from the tier table. The program accepts any table that passes `math::validate`;\n * it does not enforce one table. A creator may pass their own `tiers`; the default is\n * `DEFAULT_TIERS`. The program buys exactly `largestTierAmount - PACK_TOKENS` tokens as the seed,\n * so the first pack can pay the top tier in full. The creator only signs a maximum SOL cost for\n * that buy. The seed buy moves the curve, so a bigger jackpot means a slightly higher starting\n * pack price. A fresh Pump curve only holds so many tokens (`Global.initialRealTokenReserves`),\n * so a table whose seed exceeds that cannot be created; `createMachine` and `seedCostEstimate`\n * both check this before spending anything.\n *\n * # Two signers\n *\n * The mint keypair signs `create_v2` — Pump takes it as a signer rather than deriving it — and the\n * creator signs both instructions and pays for everything.\n */\n\nimport {\n getBase64Encoder,\n type AccountMeta,\n type Address,\n type Instruction,\n type TransactionSigner,\n} from \"@solana/kit\";\n\nimport { CREATE_MACHINE_COMPUTE_UNITS } from \"../compute\";\nimport { getInitializePoolInstructionAsync } from \"../generated/instructions/initializePool\";\nimport {\n PUMP_CREATE_TOKEN_PROGRAM_ADDRESS,\n PUMP_PROGRAM_ADDRESS,\n} from \"../pump/abi\";\nimport { pumpBuyAccounts } from \"../pump/accounts\";\nimport { decodePumpGlobal, PUMP_GLOBAL } from \"../pump/adapter\";\nimport { getPumpCreateV2Instruction } from \"../pump/create\";\nimport { newCurveBuyCost } from \"../pump/venue\";\nimport { MAX_FEE_BPS, PACK_TOKENS } from \"../ids\";\nimport {\n DEFAULT_TIERS,\n seedTokens,\n validatePack,\n validateTiers,\n type Tier,\n} from \"../math\";\nimport type { GaboxClient } from \"../rpc\";\nimport {\n buildMessage,\n withRemainingAccounts,\n type BuildOptions,\n} from \"./message\";\n\nexport type CreateMachineInput = {\n /** Pays for everything and signs both instructions. Becomes `pool.creator`. */\n creator: TransactionSigner;\n /** A fresh keypair for the coin. Signs `create_v2` and is never needed again. */\n mintKeypair: TransactionSigner;\n name: string;\n symbol: string;\n /** The metadata URI Pump writes onto the mint. */\n uri: string;\n /** The creator's fee per pack, in bps of what the venue charges. `0` to `MAX_FEE_BPS`. Immutable. */\n feeBps: number;\n /**\n * The prize table. Immutable once the pool exists. Must pass `validateTiers` and\n * `validatePack(PACK_TOKENS, tiers)`; the program checks both again on-chain. Defaults to\n * `DEFAULT_TIERS`, the table the Gabox app uses.\n */\n tiers?: readonly Readonly<Tier>[];\n /**\n * The creator's slippage cap on the seed buy, in lamports. Pump fails the buy above it.\n * Take `seedCostEstimate` and add a margin. Ignored for a 1x jackpot, which buys nothing.\n */\n maxSeedLamports: bigint;\n /** Which Pump fee recipient to use, as an index. Left out, one is picked at random. */\n feeRecipientIndex?: number;\n /** Same, for the buyback recipient list. */\n buybackRecipientIndex?: number;\n} & Partial<BuildOptions>;\n\n/**\n * Build the transaction message. Sign it with both `creator` and `mintKeypair`.\n *\n * Reads Pump's `Global` account, because two of the buy accounts — the fee recipient and the\n * buyback fee recipient — are chosen from lists held there. Nothing else needs the chain: the coin\n * does not exist yet, so every other account is a derivation.\n */\nexport async function createMachine(client: GaboxClient, input: CreateMachineInput) {\n const {\n creator,\n mintKeypair,\n name,\n symbol,\n uri,\n feeBps,\n maxSeedLamports,\n } = input;\n\n if (!Number.isInteger(feeBps) || feeBps < 0 || feeBps > MAX_FEE_BPS) {\n throw new Error(`feeBps must be a whole number from 0 to ${MAX_FEE_BPS}`);\n }\n // Snapshot caller input before validation and the first await. A caller can otherwise mutate a\n // nested tier while Pump's Global account is loading, changing the transaction after validation.\n const tiers = cloneTiers(input.tiers ?? DEFAULT_TIERS);\n validateTiers(tiers);\n validatePack(PACK_TOKENS, tiers);\n const seed = seedTokens(PACK_TOKENS, tiers);\n if (seed > 0n && maxSeedLamports <= 0n) {\n throw new Error(\"maxSeedLamports must be positive when the jackpot needs a seed\");\n }\n await assertSeedFitsFreshCurve(client, seed);\n\n const mint = mintKeypair.address;\n\n const create = getPumpCreateV2Instruction({\n mint: mintKeypair,\n user: creator,\n name,\n symbol,\n uri,\n // gabox reads `bondingCurve.creator` to derive the creator vault on every later trade, so the\n // coin's Pump creator and the pool's creator are kept the same on purpose.\n creator: creator.address,\n mayhemMode: false,\n cashback: false,\n });\n\n const venueAccounts = await pumpSeedBuyAccounts(client, {\n mint,\n user: creator.address,\n ...(input.feeRecipientIndex === undefined\n ? {}\n : { feeRecipientIndex: input.feeRecipientIndex }),\n ...(input.buybackRecipientIndex === undefined\n ? {}\n : { buybackRecipientIndex: input.buybackRecipientIndex }),\n });\n\n const initialize = await getInitializePoolInstructionAsync({\n creator,\n mint,\n // Pump `create_v2` always mints Token-2022, so the vault and the creator's ATA live there.\n tokenProgram: PUMP_CREATE_TOKEN_PROGRAM_ADDRESS,\n venue: PUMP_PROGRAM_ADDRESS,\n feeBps,\n tiers,\n maxSeedLamports,\n });\n\n const instructions: Instruction[] = [\n create,\n withRemainingAccounts(initialize as Instruction, venueAccounts),\n ];\n\n return await buildMessage(client, creator, instructions, {\n addressLookupTables: input.addressLookupTables,\n computeUnitLimit: input.computeUnitLimit ?? CREATE_MACHINE_COMPUTE_UNITS,\n ...(input.computeUnitPrice === undefined\n ? {}\n : { computeUnitPrice: input.computeUnitPrice }),\n });\n}\n\n/**\n * What the seed for this table costs, fees included, and how many tokens it is.\n *\n * The coin does not exist yet, so the price is Pump's default new curve. Nothing else trades on\n * it before `initialize_pool` runs in the same transaction, so this is exact up to a change in\n * Pump's fee settings between the read and the send. Add a small margin for `maxSeedLamports`.\n *\n * Defaults to `DEFAULT_TIERS`. Throws if `tiers` fails `validateTiers`/`validatePack`, or if the\n * seed is bigger than a fresh Pump curve can sell in one buy.\n */\nexport async function seedCostEstimate(\n client: GaboxClient,\n tiers: readonly Readonly<Tier>[] = DEFAULT_TIERS,\n): Promise<{ tiers: readonly Tier[]; seedTokens: bigint; lamports: bigint }> {\n // Do not validate one mutable table and then quote another after an await. The result owns its\n // own mutable copy too, never a reference to DEFAULT_TIERS or the caller's array.\n const copiedTiers = cloneTiers(tiers);\n validateTiers(copiedTiers);\n validatePack(PACK_TOKENS, copiedTiers);\n const seed = seedTokens(PACK_TOKENS, copiedTiers);\n await assertSeedFitsFreshCurve(client, seed);\n const lamports = seed === 0n ? 0n : await newCurveBuyCost(client, seed);\n return { tiers: copiedTiers, seedTokens: seed, lamports };\n}\n\n/** A mutable encoded-table shape, owned by this call and safe to pass to Codama's builder. */\nfunction cloneTiers(tiers: readonly Readonly<Tier>[]): Tier[] {\n return tiers.map(({ multiplierBps, tickets }) => ({ multiplierBps, tickets }));\n}\n\n/**\n * Pump's quote silently caps at the curve's real token reserves, so a seed above them would look\n * cheap instead of failing. A fresh curve holds `Global.initialRealTokenReserves`\n * (793,100,000 tokens today), so a jackpot above about 794x of a 1,000,000-token pack cannot be\n * seeded. This throws before any buy is attempted.\n */\nasync function assertSeedFitsFreshCurve(client: GaboxClient, seed: bigint): Promise<void> {\n if (seed === 0n) return;\n const { value } = await client.rpc\n .getAccountInfo(PUMP_GLOBAL, { encoding: \"base64\", commitment: \"confirmed\" })\n .send();\n if (!value) throw new Error(`Pump's Global account is missing at ${PUMP_GLOBAL}`);\n const global = decodePumpGlobal(\n new Uint8Array(getBase64Encoder().encode(value.data[0])),\n );\n if (seed > global.initialRealTokenReserves) {\n throw new Error(\n `the seed (${seed} tokens) is bigger than a fresh Pump curve holds ` +\n `(${global.initialRealTokenReserves} tokens); this table's top tier cannot be seeded on a new coin`,\n );\n }\n}\n\n/**\n * The Pump buy accounts for the seed, built without reading the bonding curve.\n *\n * The curve does not exist yet — `create_v2` in the same transaction is what creates it — so\n * `resolveVenue` cannot be used here. Everything the account list needs is known anyway: the\n * creator vault follows from the `creator` argument that `create_v2` records on the curve, and the\n * two fee recipients come from `Global`.\n */\nexport async function pumpSeedBuyAccounts(\n client: GaboxClient,\n options: {\n mint: Address;\n user: Address;\n feeRecipientIndex?: number;\n buybackRecipientIndex?: number;\n },\n): Promise<AccountMeta[]> {\n const { value } = await client.rpc\n .getAccountInfo(PUMP_GLOBAL, {\n encoding: \"base64\",\n commitment: \"confirmed\",\n })\n .send();\n if (!value)\n throw new Error(`Pump's Global account is missing at ${PUMP_GLOBAL}`);\n\n const global = decodePumpGlobal(\n new Uint8Array(getBase64Encoder().encode(value.data[0])),\n );\n\n const recipients = [global.feeRecipient, ...global.feeRecipients];\n const feeRecipient =\n recipients[options.feeRecipientIndex ?? randomIndex(recipients.length)];\n const buyback =\n global.buybackFeeRecipients[\n options.buybackRecipientIndex ??\n randomIndex(global.buybackFeeRecipients.length)\n ];\n\n if (!feeRecipient) throw new Error(\"Pump Global holds no fee recipient\");\n if (!buyback) throw new Error(\"Pump Global holds no buyback fee recipient\");\n\n return pumpBuyAccounts({\n mint: options.mint,\n user: options.user,\n tokenProgram: PUMP_CREATE_TOKEN_PROGRAM_ADDRESS,\n creator: options.user,\n feeRecipient,\n buybackFeeRecipient: buyback,\n });\n}\n\nconst randomIndex = (length: number): number => {\n if (length === 0) throw new Error(\"the list is empty\");\n return Math.floor(Math.random() * length);\n};\n","/**\n * Keeping a draw moving: retry the oracle, or expire it.\n *\n * Both are permissionless. Anyone can send them, which is the point — a buyer whose draw is stuck\n * does not have to wait for an operator, and there is no crank service in this repository.\n *\n * # retryDraw\n *\n * Asks MagicBlock for randomness again. Up to three attempts in total, counting the one `buy_pack`\n * made, and at least 300 slots apart. The **signer pays the oracle fee**, which is why\n * `maxVrfDebit` exists: a permissionless crank must not be able to spend an unbounded amount of\n * someone else's wallet.\n *\n * A retry never extends the deadline. `expire_draw` still becomes available 216,000 slots after the\n * original purchase.\n *\n * # expireDraw\n *\n * Resolves an unanswered draw at its **committed minimum** award — the smallest prize on the table\n * it was sold with. Not a refund. The tokens were already bought, and paying the worst committed\n * outcome gives an exit without letting a buyer improve a losing result by withholding settlement.\n * It applies only while the draw is still `Pending`; a `Ready` draw must use normal delivery so its\n * resolved award cannot be closed unpaid.\n *\n * `expire_draw` takes no signer at all: it needs no payer and allocates nothing. A caller still\n * has to supply a fee payer for the transaction.\n */\n\nimport type { Address, Instruction, TransactionSigner } from '@solana/kit';\n\nimport { fetchDraw, fetchPoolAt } from '../accounts';\nimport { getExpireDrawInstruction } from '../generated/instructions/expireDraw';\nimport { getRetryDrawInstruction } from '../generated/instructions/retryDraw';\nimport { DrawStatus } from '../generated/types/drawStatus';\nimport { MAX_ATTEMPTS, RETRY_SLOTS, TIMEOUT_SLOTS } from '../ids';\nimport { associatedTokenAddress, vrfIdentityAddress } from '../pdas';\nimport type { GaboxClient } from '../rpc';\nimport { buildMessage, type BuildOptions } from './message';\n\n/** A retry and an expiry are both small. The default budget is plenty. */\nconst DRAW_COMPUTE_UNITS = 200_000;\n\nexport type RetryDrawInput = {\n /** Pays the oracle fee and the transaction fee. Any wallet. */\n payer: TransactionSigner;\n pool: Address;\n draw: Address;\n /** Cap on what the oracle request may take from `payer`, in lamports. */\n maxVrfDebit: bigint;\n} & Partial<BuildOptions>;\n\nexport async function retryDraw(client: GaboxClient, input: RetryDrawInput) {\n const retry = getRetryDrawInstruction({\n payer: input.payer,\n pool: input.pool,\n draw: input.draw,\n identity: await vrfIdentityAddress(),\n maxVrfDebit: input.maxVrfDebit,\n });\n\n return await buildMessage(client, input.payer, [retry as Instruction], {\n addressLookupTables: input.addressLookupTables,\n computeUnitLimit: input.computeUnitLimit ?? DRAW_COMPUTE_UNITS,\n ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }),\n });\n}\n\nexport type ExpireDrawInput = {\n /** Only pays the transaction fee. `expire_draw` itself has no signer account. */\n payer: TransactionSigner;\n pool: Address;\n draw: Address;\n} & Partial<BuildOptions>;\n\nexport async function expireDraw(client: GaboxClient, input: ExpireDrawInput) {\n const draw = await fetchDraw(client, input.draw);\n if (!draw) throw new Error(`no draw at ${input.draw}`);\n if (draw.pool !== input.pool) throw new Error(`draw ${input.draw} does not belong to ${input.pool}`);\n const pool = await fetchPoolAt(client, input.pool);\n if (!pool) throw new Error(`no pool at ${input.pool}`);\n const expire = getExpireDrawInstruction({\n pool: input.pool,\n draw: input.draw,\n purchaser: draw.purchaser,\n mint: pool.mint,\n vault: pool.vault,\n userTokens: await associatedTokenAddress(draw.purchaser, pool.mint, pool.tokenProgram),\n tokenProgram: pool.tokenProgram,\n });\n\n return await buildMessage(client, input.payer, [expire as Instruction], {\n addressLookupTables: input.addressLookupTables,\n computeUnitLimit: input.computeUnitLimit ?? DRAW_COMPUTE_UNITS,\n ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }),\n });\n}\n\nexport type DrawAvailability = {\n status: DrawStatus;\n attempts: number;\n /** Slots remaining before a retry is allowed. `0` when it is allowed now. */\n slotsUntilRetry: bigint;\n /** Slots remaining before an unanswered draw reaches its expiry deadline. */\n slotsUntilExpiry: bigint;\n /** All three conditions the program checks for `retry_draw`, together. */\n canRetry: boolean;\n /** True only when the draw is still `Pending` and its expiry deadline passed. */\n canExpire: boolean;\n};\n\n/**\n * What a client may do to a draw right now.\n *\n * Reads the draw and the current slot, and reproduces the program's three retry conditions and the\n * pending-status-plus-deadline expiry conditions. Showing a disabled button with a countdown beats\n * sending a transaction that fails with `RetryTooSoon` or `NotPending`.\n */\nexport async function drawAvailability(\n client: GaboxClient,\n draw: Address,\n): Promise<DrawAvailability | null> {\n const record = await fetchDraw(client, draw);\n if (!record) return null;\n\n const slot = await client.rpc.getSlot({ commitment: 'confirmed' }).send();\n const now = BigInt(slot);\n\n const retryAt = record.lastAttemptSlot + RETRY_SLOTS;\n const expireAt = record.requestSlot + TIMEOUT_SLOTS;\n const slotsUntilRetry = now >= retryAt ? 0n : retryAt - now;\n const slotsUntilExpiry = now >= expireAt ? 0n : expireAt - now;\n const pending = record.status === DrawStatus.Pending;\n\n return {\n status: record.status,\n attempts: record.attempts,\n slotsUntilRetry,\n slotsUntilExpiry,\n canRetry:\n pending &&\n slotsUntilRetry === 0n &&\n record.attempts < MAX_ATTEMPTS &&\n slotsUntilExpiry > 0n,\n canExpire: pending && slotsUntilExpiry === 0n,\n };\n}\n","/**\n * Donating prize inventory.\n *\n * `fund_prizes` moves tokens from any wallet into the pool's vault. It is a donation and it is\n * irrevocable: there is no withdrawal instruction, and no authority can move vault tokens. The only\n * way out of the vault is prize delivery.\n *\n * Funding raises what later packs can pay. It does not change the tiers, which are immutable, and\n * it does not change any draw that is already frozen — `math.quote` is computed at purchase time\n * and stored in the `Draw`.\n */\n\nimport {\n getCreateAssociatedTokenIdempotentInstruction,\n getSyncNativeInstruction,\n TOKEN_PROGRAM_ADDRESS as SPL_TOKEN_PROGRAM_ADDRESS,\n} from '@solana-program/token';\nimport { getTransferSolInstruction } from '@solana-program/system';\nimport type { Address, Instruction, TransactionSigner } from '@solana/kit';\n\nimport { fetchPoolByMint } from '../accounts';\nimport { getFundPrizesInstruction } from '../generated/instructions/fundPrizes';\nimport { WSOL_MINT } from '../ids';\nimport { associatedTokenAddress, poolAddress } from '../pdas';\nimport { venueBuyInstruction } from '../pump/trade';\nimport { resolveVenue, wsolAccountFor, type VenueKind } from '../pump/venue';\nimport type { GaboxClient } from '../rpc';\nimport { buildMessage, type BuildOptions } from './message';\n\nconst FUND_COMPUTE_UNITS = 200_000;\n\n/** A venue buy plus the vault transfer. The buy is the expensive half. */\nconst FUND_WITH_BUY_COMPUTE_UNITS = 400_000;\n\nexport type FundPrizesInput = {\n mint: Address;\n /** The donor. Signs, and the tokens leave its account. */\n funder: TransactionSigner;\n /** Tokens to donate, in the mint's smallest unit. Must be positive. */\n amount: bigint;\n /**\n * The account the tokens come from. Defaults to the funder's associated token account, which is\n * where a wallet holds them. Any token account the funder is the authority of works.\n */\n source?: Address;\n} & Partial<BuildOptions>;\n\nexport async function fundPrizes(client: GaboxClient, input: FundPrizesInput) {\n const { mint, funder, amount } = input;\n if (amount <= 0n) throw new Error('amount must be positive');\n\n const pool = await fetchPoolByMint(client, mint);\n if (!pool) throw new Error(`no gabox pool for mint ${mint}`);\n\n const fund = getFundPrizesInstruction({\n funder,\n pool: await poolAddress(mint),\n mint,\n source: input.source ?? (await associatedTokenAddress(funder.address, mint, pool.tokenProgram)),\n vault: pool.vault,\n tokenProgram: pool.tokenProgram,\n amount,\n });\n\n return await buildMessage(client, funder, [fund as Instruction], {\n addressLookupTables: input.addressLookupTables,\n computeUnitLimit: input.computeUnitLimit ?? FUND_COMPUTE_UNITS,\n ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }),\n });\n}\n\nexport type FundPrizesWithBuyInput = {\n mint: Address;\n /** The donor. Buys the tokens, then gives them away. Signs both instructions. */\n funder: TransactionSigner;\n /** Exact tokens to buy and donate. `seedShortfall(offer)` is the amount that uncaps the top prize. */\n tokens: bigint;\n /** The donor's slippage cap on the buy, in lamports (WSOL on PumpSwap). */\n maxQuoteIn: bigint;\n /** Force a venue. Left out, the bonding curve's `complete` flag decides. */\n venue?: VenueKind;\n /**\n * Lamports to wrap on the PumpSwap route. Left out, `maxQuoteIn`. The venue never takes more\n * than that, and any surplus stays in the donor's own WSOL account.\n */\n wrapLamports?: bigint;\n} & Partial<BuildOptions>;\n\n/**\n * Buy tokens at the venue with SOL and donate them to the vault, in one transaction.\n *\n * This is what a donor with SOL and no coins needs. `fundPrizes` moves tokens the donor already\n * holds; this one buys them first. Both are irrevocable — there is no withdrawal instruction, and\n * no authority can move vault tokens.\n *\n * Three instructions on the curve route: create the donor's token account if it is missing, buy,\n * donate. Pump creates the account itself, but the idempotent instruction costs nothing when it\n * already exists and it makes the transaction correct on its own terms. The PumpSwap route adds the\n * WSOL create/fund/sync prefix, for the same reason `buyPack` does: PumpSwap spends WSOL.\n */\nexport async function fundPrizesWithBuy(client: GaboxClient, input: FundPrizesWithBuyInput) {\n const { mint, funder, tokens, maxQuoteIn } = input;\n if (tokens <= 0n) throw new Error('tokens must be positive');\n if (maxQuoteIn <= 0n) throw new Error('maxQuoteIn must be positive');\n\n const pool = await fetchPoolByMint(client, mint);\n if (!pool) throw new Error(`no gabox pool for mint ${mint}`);\n\n const venue = await resolveVenue(client, {\n mint,\n user: funder.address,\n ...(input.venue ? { venue: input.venue } : {}),\n });\n\n const source = await associatedTokenAddress(funder.address, mint, pool.tokenProgram);\n\n const wsol: Instruction[] =\n venue.kind === 'pumpswap' ? wsolPreparation(funder, input.wrapLamports ?? maxQuoteIn) : [];\n\n const instructions: Instruction[] = [\n ...wsol,\n getCreateAssociatedTokenIdempotentInstruction({\n payer: funder,\n ata: source,\n owner: funder.address,\n mint,\n tokenProgram: pool.tokenProgram,\n }) as Instruction,\n venueBuyInstruction({ venue, user: funder, tokens, maxQuoteIn }),\n getFundPrizesInstruction({\n funder,\n pool: await poolAddress(mint),\n mint,\n source,\n vault: pool.vault,\n tokenProgram: pool.tokenProgram,\n amount: tokens,\n }) as Instruction,\n ];\n\n return await buildMessage(client, funder, instructions, {\n addressLookupTables: input.addressLookupTables,\n computeUnitLimit: input.computeUnitLimit ?? FUND_WITH_BUY_COMPUTE_UNITS,\n ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }),\n });\n}\n\n/** Create the donor's WSOL account if needed, fund it, and sync its balance. See `buyPack.ts`. */\nfunction wsolPreparation(funder: TransactionSigner, lamports: bigint): Instruction[] {\n const wsol = wsolAccountFor(funder.address);\n return [\n getCreateAssociatedTokenIdempotentInstruction({\n payer: funder,\n ata: wsol,\n owner: funder.address,\n mint: WSOL_MINT,\n tokenProgram: SPL_TOKEN_PROGRAM_ADDRESS,\n }) as Instruction,\n getTransferSolInstruction({ source: funder, destination: wsol, amount: lamports }) as Instruction,\n getSyncNativeInstruction({ account: wsol }) as Instruction,\n ];\n}\n","/**\n * Selling an automatically delivered prize, plus settlement helpers for legacy resolve-only draws.\n *\n * Every sale here goes through the program (`sell_tokens` or `sell_prize`), which does the venue\n * CPI and then pays the protocol 1% of what the sale returned. On Pump the proceeds and the fee are\n * native SOL. On PumpSwap both are WSOL: the proceeds land in the seller's WSOL account and the fee\n * moves from there to the collector's WSOL account. Add an unwrap afterwards if the seller wants\n * lamports.\n *\n * `minQuoteOutput` is the venue's own floor, checked before the fee. The seller keeps 99% of\n * whatever the venue paid above it.\n */\n\nimport {\n getCreateAssociatedTokenIdempotentInstruction,\n TOKEN_PROGRAM_ADDRESS as SPL_TOKEN_PROGRAM_ADDRESS,\n} from '@solana-program/token';\nimport type { Address, Instruction, TransactionSigner } from '@solana/kit';\n\nimport { fetchDraw, fetchPoolByMint } from '../accounts';\nimport { REDEEM_COMPUTE_UNITS } from '../compute';\nimport { getClaimPrizeInstruction } from '../generated/instructions/claimPrize';\nimport { getSellPrizeInstruction } from '../generated/instructions/sellPrize';\nimport { getSellTokensInstruction } from '../generated/instructions/sellTokens';\nimport { WSOL_MINT } from '../ids';\nimport { associatedTokenAddress, feeCollectorWsolAddress, poolAddress } from '../pdas';\nimport { resolveVenue, wsolAccountFor, type ResolvedVenue, type VenueKind } from '../pump/venue';\nimport type { GaboxClient } from '../rpc';\nimport { buildMessage, withRemainingAccounts, type BuildOptions } from './message';\n\nexport type SellTokensInput = {\n mint: Address;\n /** Wallet that owns the tokens and signs the venue sale. */\n seller: TransactionSigner;\n /** Exact token amount to sell. Must be positive. */\n amount: bigint;\n /** Floor on the venue's net output, in lamports or WSOL, before the protocol fee. Must be\n * positive: the program rejects zero, because a zero floor is not slippage protection. */\n minQuoteOutput: bigint;\n /** Force a venue. Left out, the bonding curve's `complete` flag decides. */\n venue?: VenueKind;\n} & Partial<BuildOptions>;\n\n/**\n * Sell a prize that the VRF callback already delivered to the wallet, through `sell_tokens`.\n *\n * The program needs the coin's pool: it keeps the vault out of the venue's account list. A mint\n * with no pool cannot be sold this way; use a plain venue trade for that.\n */\nexport async function sellTokens(client: GaboxClient, input: SellTokensInput) {\n const { mint, seller, amount, minQuoteOutput } = input;\n if (amount <= 0n) throw new Error('amount must be positive');\n if (minQuoteOutput <= 0n) throw new Error('minQuoteOutput must be positive');\n\n const pool = await fetchPoolByMint(client, mint);\n if (!pool) throw new Error(`no gabox pool for mint ${mint}`);\n\n const venue = await resolveVenue(client, {\n mint,\n user: seller.address,\n ...(input.venue ? { venue: input.venue } : {}),\n });\n\n const sell = getSellTokensInstruction({\n seller,\n pool: await poolAddress(mint),\n mint,\n userTokens: await associatedTokenAddress(seller.address, mint, pool.tokenProgram),\n venue: venue.program,\n feeCollectorWsol: await feeCollectorWsolAddress(),\n tokenProgram: pool.tokenProgram,\n amount,\n minQuoteOutput,\n });\n\n return await buildMessage(\n client,\n seller,\n [...wsolPreparation(seller, venue), withRemainingAccounts(sell as Instruction, venue.sellAccounts)],\n {\n addressLookupTables: input.addressLookupTables,\n computeUnitLimit: input.computeUnitLimit ?? REDEEM_COMPUTE_UNITS,\n ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }),\n },\n );\n}\n\nexport type ClaimPrizeInput = {\n mint: Address;\n /** The wallet that bought the legacy pack. Only it can settle the draw. */\n purchaser: TransactionSigner;\n /** The draw to redeem. */\n draw: Address;\n} & Partial<BuildOptions>;\n\n/** Transfer a legacy resolve-only award into the purchaser's token account and close the draw. */\nexport async function claimPrize(client: GaboxClient, input: ClaimPrizeInput) {\n const { mint, purchaser, draw } = input;\n const pool = await fetchPoolByMint(client, mint);\n if (!pool) throw new Error(`no gabox pool for mint ${mint}`);\n\n const claim = getClaimPrizeInstruction({\n purchaser,\n pool: await poolAddress(mint),\n draw,\n mint,\n vault: pool.vault,\n userTokens: await associatedTokenAddress(purchaser.address, mint, pool.tokenProgram),\n tokenProgram: pool.tokenProgram,\n });\n\n return await buildMessage(client, purchaser, [claim as Instruction], {\n addressLookupTables: input.addressLookupTables,\n computeUnitLimit: input.computeUnitLimit ?? REDEEM_COMPUTE_UNITS,\n ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }),\n });\n}\n\nexport type SellPrizeInput = ClaimPrizeInput & {\n /**\n * The seller's floor on the venue's net output, in lamports or WSOL. Must be positive: the\n * program rejects zero, because a zero floor is not slippage protection.\n *\n * This is the venue's own net quote, before the protocol fee. It is not net of the transaction\n * fee or of any rent the transaction pays.\n */\n minQuoteOutput: bigint;\n /** Force a venue. Left out, the bonding curve's `complete` flag decides. */\n venue?: VenueKind;\n};\n\n/**\n * Claim and sell a legacy resolve-only draw in one transaction.\n *\n * The award is read off the draw so the caller can price the sale before signing. A draw that has\n * not resolved has no award yet, and this throws rather than building a sale of zero tokens.\n */\nexport async function sellPrize(client: GaboxClient, input: SellPrizeInput) {\n const { mint, purchaser, draw, minQuoteOutput } = input;\n if (minQuoteOutput <= 0n) throw new Error('minQuoteOutput must be positive');\n\n const pool = await fetchPoolByMint(client, mint);\n if (!pool) throw new Error(`no gabox pool for mint ${mint}`);\n\n const record = await fetchDraw(client, draw);\n if (!record) throw new Error(`no draw at ${draw} — it may already be redeemed`);\n if (record.amount === 0n) {\n throw new Error(`draw ${draw} has no award yet; it has not resolved`);\n }\n\n const venue = await resolveVenue(client, {\n mint,\n user: purchaser.address,\n ...(input.venue ? { venue: input.venue } : {}),\n });\n\n const sell = getSellPrizeInstruction({\n purchaser,\n pool: await poolAddress(mint),\n draw,\n mint,\n vault: pool.vault,\n userTokens: await associatedTokenAddress(purchaser.address, mint, pool.tokenProgram),\n tokenProgram: pool.tokenProgram,\n venue: venue.program,\n feeCollectorWsol: await feeCollectorWsolAddress(),\n minQuoteOutput,\n });\n\n return await buildMessage(\n client,\n purchaser,\n [...wsolPreparation(purchaser, venue), withRemainingAccounts(sell as Instruction, venue.sellAccounts)],\n {\n addressLookupTables: input.addressLookupTables,\n computeUnitLimit: input.computeUnitLimit ?? REDEEM_COMPUTE_UNITS,\n ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }),\n },\n );\n}\n\n/**\n * On PumpSwap the proceeds land in the seller's WSOL account, so it has to exist before the sale.\n * Pump's own SDK does the same before its sells. The instruction is idempotent and the account is\n * the seller's own; gabox never touches it. Pump pays native SOL, so the curve route adds nothing.\n */\nfunction wsolPreparation(seller: TransactionSigner, venue: ResolvedVenue): Instruction[] {\n if (venue.kind !== 'pumpswap') return [];\n return [\n getCreateAssociatedTokenIdempotentInstruction({\n payer: seller,\n ata: wsolAccountFor(seller.address),\n owner: seller.address,\n mint: WSOL_MINT,\n tokenProgram: SPL_TOKEN_PROGRAM_ADDRESS,\n }) as Instruction,\n ];\n}\n\n/**\n * Quote the award held by a legacy open draw before the seller signs a floor.\n *\n * Read the draw, ask the venue, and subtract your own slippage tolerance to get `minQuoteOutput`.\n */\nexport async function quoteSellPrize(\n client: GaboxClient,\n mint: Address,\n draw: Address,\n user: Address,\n): Promise<{ award: bigint; grossOutput: bigint }> {\n const record = await fetchDraw(client, draw);\n if (!record) throw new Error(`no draw at ${draw}`);\n const venue = await resolveVenue(client, { mint, user });\n return { award: record.amount, grossOutput: venue.quoteSell(record.amount) };\n}\n","/**\n * The four oracle accounts.\n *\n * `buy_pack` and `retry_draw` both carry an `Oracle` account group. Anchor flattens it into four\n * slots, and the generated client takes them as `identity`, `queue`, `program` and `slotHashes`.\n * Three of the four are pinned by an `address` constraint, so the only one a client computes is the\n * identity PDA.\n *\n * # Why the queue is not a choice\n *\n * `vrf.rs` pins MagicBlock's default queue with `address = QUEUE` and `owner = ID`. A pool creator\n * therefore cannot point their pool's draws at an oracle they run. That is the reason the address\n * is a constant here rather than a parameter: making it configurable in the client would suggest a\n * freedom the program does not give.\n */\n\nimport type { Address } from '@solana/kit';\n\nimport { SLOT_HASHES_SYSVAR, VRF_DEFAULT_QUEUE, VRF_PROGRAM_ADDRESS } from './ids';\nimport { vrfIdentityAddress } from './pdas';\n\n/** The four accounts, named as the generated client names them. */\nexport type OracleAccounts = {\n /** `[\"identity\"]` under gabox. The PDA gabox signs the randomness request with. */\n identity: Address;\n /** MagicBlock's default queue. Writable. */\n queue: Address;\n /** The VRF program itself. */\n program: Address;\n /** The slot-hashes sysvar, which seeds the request. */\n slotHashes: Address;\n};\n\n/**\n * Build the group. Nothing here reads the chain, so it is safe to call on every render.\n *\n * The generated instruction builders default `queue`, `program` and `slotHashes` on their own, so\n * passing this whole object is belt and braces. It is worth having anyway: a caller can show the\n * four accounts a draw request will touch before asking for a signature.\n */\nexport async function oracleAccounts(): Promise<OracleAccounts> {\n return {\n identity: await vrfIdentityAddress(),\n queue: VRF_DEFAULT_QUEUE,\n program: VRF_PROGRAM_ADDRESS,\n slotHashes: SLOT_HASHES_SYSVAR,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/ids.ts","../src/math.ts","../src/pdas.ts","../src/accounts.ts","../src/events.ts","../src/lookupTables.ts","../src/offer.ts","../src/rpc.ts","../src/tx/wsol.ts","../src/tx/buyPack.ts","../src/tx/createMachine.ts","../src/tx/draw.ts","../src/tx/fundPrizes.ts","../src/tx/redeem.ts","../src/vrf.ts"],"sourcesContent":["/**\n * Every fixed address this SDK needs at the top level, in one place.\n *\n * None of these is typed twice. The gabox program id comes from the generated client, which Codama\n * took from `target/idl/gabox.json`. The Raydium addresses come from `src/raydium/abi.ts`, which\n * `scripts/codegen.mjs` read out of the Rust program's `venue/ids.rs`. Retyping a base58 string is\n * a way to be wrong that no test would catch, so the strings live where the generator put them.\n *\n * Raydium runs a different deployment on each cluster, so its addresses are not constants here.\n * They come from `raydiumIds(client.cluster)`; see `src/raydium/ids.ts`.\n */\n\nimport type { Address } from '@solana/kit';\n\nimport { GABOX_PROGRAM_ADDRESS } from './generated/programs/gabox';\nimport {\n ASSOCIATED_TOKEN_PROGRAM_ADDRESS,\n METAPLEX_PROGRAM_ADDRESS,\n PLATFORM_ADMIN,\n SYSTEM_PROGRAM_ADDRESS,\n TOKEN_PROGRAM_ADDRESS,\n WSOL_MINT,\n} from './raydium/abi';\nimport { LAUNCH_DECIMALS } from './raydium/ids';\n\n/** `declare_id!` in `programs/gabox/src/lib.rs`. */\nexport const GABOX_PROGRAM_ID = GABOX_PROGRAM_ADDRESS;\n\nexport {\n ASSOCIATED_TOKEN_PROGRAM_ADDRESS,\n LAUNCH_DECIMALS,\n METAPLEX_PROGRAM_ADDRESS,\n PLATFORM_ADMIN,\n SYSTEM_PROGRAM_ADDRESS,\n TOKEN_PROGRAM_ADDRESS,\n WSOL_MINT,\n};\n\n/** MagicBlock's ephemeral VRF program. `vrf.rs` pins it and refuses any other. */\nexport const VRF_PROGRAM_ADDRESS = 'Vrf1RNUjXmQGjmQrQLvJHs9SNkvDJEsRVFPkfSQUwGz' as Address;\n\n/**\n * MagicBlock's default oracle queue. The program pins this one address, so a pool creator cannot\n * point a draw at an oracle they control.\n */\nexport const VRF_DEFAULT_QUEUE = 'Cuj97ggrhhidhbu39TijNVqE74xvKJ69gDervRUXAxGh' as Address;\n\n/** The seed of both identity PDAs. See `pdas.ts` — there are two, under different programs. */\nexport const IDENTITY_SEED = new Uint8Array([0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79]); // \"identity\"\n\nexport const SLOT_HASHES_SYSVAR = 'SysvarS1otHashes111111111111111111111111111' as Address;\n\nexport const INSTRUCTIONS_SYSVAR = 'Sysvar1nstructions1111111111111111111111111' as Address;\n\n/** `constants.rs`. A retry may not run sooner than this after the last attempt. */\nexport const RETRY_SLOTS = 300n;\n\n/** `constants.rs`. After this many slots from the purchase, anyone may expire the draw. */\nexport const TIMEOUT_SLOTS = 216_000n;\n\n/** `constants.rs`. Three requests in total, counting the one `buy_pack` makes. */\nexport const MAX_ATTEMPTS = 3;\n\n/**\n * `constants.rs`. Tokens in one pack, in base units: 1,000,000 tokens at the fixed 6 decimals, or\n * 0.1% of the 1,000,000,000 supply. Every pool sells packs of this size. The venue decides what a\n * pack costs, so the pack price follows the coin. Read `pool.packTokens` rather than this when a\n * pool is at hand: a later program version may change the constant.\n */\nexport const PACK_TOKENS = 1_000_000n * 1_000_000n;\n","/**\n * A bigint port of `programs/gabox/src/math.rs`.\n *\n * The point is that a client can show a buyer the exact prize table the program will freeze into\n * their `Draw`, before they pay. Every rounding step here matches the Rust, including the direction\n * of each division. `test/math.test.ts` runs the same vectors as `programs/gabox/tests/math.rs`.\n *\n * All amounts are `bigint`, in the mint's smallest unit. `multiplierBps` and `tickets` are numbers\n * because both are `u32` in the program and both stay small.\n */\n\n/** Basis points. A multiplier of 10_000 pays back exactly one pack. */\nexport const BPS = 10_000n;\n\n/**\n * `constants::MIN_SEED_MULTIPLIER_BPS`. The mandatory seed makes a 3x top prize payable on the\n * first pack, or the full top prize when the table's top tier is below 3x. A creator can add more\n * seed on top through `extraSeedTokens`.\n */\nexport const MIN_SEED_MULTIPLIER_BPS = 30_000;\n\n/**\n * `constants::MAX_MULTIPLIER_BPS`. A table's top tier can be at most 20x. Seed beyond what a 20x\n * prize needs stays in the vault as backup for the draws after a top-tier hit.\n */\nexport const MAX_MULTIPLIER_BPS = 200_000;\n\n/** Ticket counts must sum to this. A uniform 16-bit word then maps with no modulo bias. */\nexport const TICKETS = 65_536;\n\n/** The prize table has exactly this many slots. Unused slots are all-zero. */\nexport const TIERS = 8;\n\n/** One row of the immutable prize table. Counts, not cumulative thresholds. */\nexport type Tier = {\n /** `floor(base * multiplierBps / 10_000)` tokens. `0` only on an unused row. */\n multiplierBps: number;\n /** Out of 65,536. `0` marks the row unused, and then `multiplierBps` must be `0` too. */\n tickets: number;\n};\n\n/** One row of a frozen offer: a real token amount, already capped by inventory. */\nexport type Prize = {\n amount: bigint;\n tickets: number;\n};\n\n/** What a pack buy writes into the `Draw`. `minimum` is also the timeout payout. */\nexport type Offer = {\n prizes: Prize[];\n maximum: bigint;\n minimum: bigint;\n};\n\n/** Thrown by every function here. `code` matches a `GaboxError` variant name. */\nexport class GaboxMathError extends Error {\n readonly code: string;\n constructor(code: string, message: string) {\n super(`${code}: ${message}`);\n this.name = \"GaboxMathError\";\n this.code = code;\n }\n}\n\nconst U64_MAX = (1n << 64n) - 1n;\nconst U32_MAX = 0xffff_ffff;\n\n/**\n * The default prize table. The program does not enforce this table: it accepts any table that\n * passes `validateTiers`. This is only the table the Gabox app creates its pools with, and the\n * starting point for a client that has no reason to pick another one.\n *\n * Common 75% at 0.52x, Rare 20% at 1.2x, Epic 4% at 3x, Mythic 1% at 20x. Expected payout is\n * 0.9499x of a pack, so the seed is 19 packs.\n */\nexport const DEFAULT_TIERS: readonly Readonly<Tier>[] = Object.freeze([\n Object.freeze({ multiplierBps: 5_201, tickets: 49_153 }),\n Object.freeze({ multiplierBps: 12_000, tickets: 13_107 }),\n Object.freeze({ multiplierBps: 30_000, tickets: 2_621 }),\n Object.freeze({ multiplierBps: 200_000, tickets: 655 }),\n Object.freeze({ multiplierBps: 0, tickets: 0 }),\n Object.freeze({ multiplierBps: 0, tickets: 0 }),\n Object.freeze({ multiplierBps: 0, tickets: 0 }),\n Object.freeze({ multiplierBps: 0, tickets: 0 }),\n]);\n\nfunction checkedU64(value: bigint, what: string): bigint {\n if (value < 0n || value > U64_MAX) {\n throw new GaboxMathError(\"Arithmetic\", `${what} does not fit in u64`);\n }\n return value;\n}\n\n/** Tier fields encode as program `u32`s. Reject JavaScript-only values before `BigInt` or codecs. */\nfunction checkedU32(value: number, what: string): number {\n if (!Number.isInteger(value) || value < 0 || value > U32_MAX) {\n throw new GaboxMathError(\n \"InvalidDistribution\",\n `${what} must be an integer from 0 to ${U32_MAX}`,\n );\n }\n return value;\n}\n\n/** `math::tokens`. Floor division, and an overflow past u64 is an error, not a wrap. */\nexport function tierAmount(base: bigint, multiplierBps: number): bigint {\n return checkedU64((base * BigInt(checkedU32(multiplierBps, \"multiplierBps\"))) / BPS, \"tier amount\");\n}\n\n/**\n * `math::validate`. Checks the table alone, with no base.\n *\n * Four rules, and each one closes a way to sell a bad ticket:\n * - ticket counts sum to exactly 65,536, so the 16-bit draw is uniform;\n * - an unused row is all-zero, so a hidden multiplier cannot ride along;\n * - a ticketed tier's multiplier is from 1 to `MAX_MULTIPLIER_BPS` (20x);\n * - the expected multiplier over all tickets is at most 1x, so the table cannot promise more\n * tokens than a pack buys. This bounds tokens, not cash value.\n */\nexport function validateTiers(tiers: readonly Readonly<Tier>[]): void {\n if (tiers.length !== TIERS) {\n throw new GaboxMathError(\n \"InvalidDistribution\",\n `expected ${TIERS} tiers, got ${tiers.length}`,\n );\n }\n let count = 0n;\n let expected = 0n;\n for (const [index, tier] of tiers.entries()) {\n checkedU32(tier.tickets, `tier ${index} tickets`);\n checkedU32(tier.multiplierBps, `tier ${index} multiplierBps`);\n if (tier.tickets === 0) {\n if (tier.multiplierBps !== 0) {\n throw new GaboxMathError(\n \"InvalidDistribution\",\n \"a tier with no tickets must have no multiplier\",\n );\n }\n continue;\n }\n if (tier.multiplierBps <= 0) {\n throw new GaboxMathError(\n \"InvalidDistribution\",\n \"a ticketed tier must pay something; it would sell a ticket that can only win zero\",\n );\n }\n if (tier.multiplierBps > MAX_MULTIPLIER_BPS) {\n throw new GaboxMathError(\n \"InvalidDistribution\",\n `tier ${index} multiplierBps exceeds the ${MAX_MULTIPLIER_BPS} maximum (20x)`,\n );\n }\n count += BigInt(tier.tickets);\n expected += BigInt(tier.multiplierBps) * BigInt(tier.tickets);\n }\n if (count !== BigInt(TICKETS)) {\n throw new GaboxMathError(\n \"InvalidDistribution\",\n `tickets must sum to ${TICKETS}, they sum to ${count}`,\n );\n }\n if (expected > BPS * BigInt(TICKETS)) {\n throw new GaboxMathError(\n \"UnfundedExpectation\",\n \"the expected token award exceeds the tokens a pack buys\",\n );\n }\n}\n\n/**\n * `math::validate_pack`. Every ticketed tier must pay at least one token for a pack of this size.\n *\n * The program checks this once at creation. At `PACK_TOKENS` no sane table fails it; it exists so\n * a table cannot sell a ticket that can only win zero.\n */\nexport function validatePack(packTokens: bigint, tiers: readonly Readonly<Tier>[]): void {\n if (packTokens <= 0n) throw new GaboxMathError(\"ZeroAmount\", \"packTokens must be positive\");\n checkedU64(packTokens, \"pack tokens\");\n validateTiers(tiers);\n for (const [i, tier] of tiers.entries()) {\n if (tier.tickets === 0) continue;\n if (tierAmount(packTokens, tier.multiplierBps) === 0n) {\n throw new GaboxMathError(\"PackTooSmall\", `tier ${i} rounds to zero tokens at this pack size`);\n }\n }\n}\n\n/**\n * `math::seed_tokens`. The mandatory seed a table needs, in tokens.\n *\n * The mandatory seed makes a 3x top prize payable on the first pack, or the full top prize when\n * the table's top tier is below 3x. A jackpot above 3x still shows the full table once later\n * packs grow the free vault; the mandatory seed alone does not have to fund it. The pack itself\n * brings `packTokens` into the vault, so the vault has to hold the rest beforehand:\n *\n * seedTokens = min(uncappedMaximum(packTokens, tiers), tierAmount(packTokens, MIN_SEED_MULTIPLIER_BPS)) - packTokens\n *\n * A 20x or a 3x top tier on a 1M-token pack both need a 2M-token seed, since the mandatory seed\n * stops at the 3x minimum. A 2x top tier needs a 1M-token seed, already below the minimum. A\n * table whose top tier pays exactly one pack needs no seed. A top tier below one pack is refused:\n * every ticket would lose. `createMachine` lets a creator add more seed on top of this mandatory\n * amount through `extraSeedTokens`, for example to fund a top tier above 3x from the first pack.\n *\n * Pool initialization computes this number itself and buys exactly that many tokens on the curve.\n * The creator only signs a maximum SOL cost.\n */\nexport function seedTokens(packTokens: bigint, tiers: readonly Readonly<Tier>[]): bigint {\n validateTiers(tiers);\n const largest = uncappedMaximum(packTokens, tiers);\n if (largest < packTokens) {\n throw new GaboxMathError(\n \"JackpotBelowOnePack\",\n \"the largest tier must pay at least one pack\",\n );\n }\n const minimum = tierAmount(packTokens, MIN_SEED_MULTIPLIER_BPS);\n const capped = largest < minimum ? largest : minimum;\n return capped - packTokens;\n}\n\n/**\n * `math::uncapped_maximum`. The largest tier's award for this base, before any inventory cap.\n *\n * At `packTokens` this is the jackpot in tokens. `seedTokens` is this minus one pack.\n */\nexport function uncappedMaximum(base: bigint, tiers: readonly Readonly<Tier>[]): bigint {\n validateTiers(tiers);\n let largest = 0n;\n for (const tier of tiers) {\n if (tier.tickets === 0) continue;\n const amount = tierAmount(base, tier.multiplierBps);\n if (amount > largest) largest = amount;\n }\n return largest;\n}\n\n/**\n * `math::quote`. The offer a pack of `base` tokens would freeze right now. `base` is always\n * `pool.packTokens`; the parameter stays general so the vectors can use small numbers.\n *\n * `inventory` is the vault's token balance and `reserved` is `pool.reserved`. The difference is\n * free inventory. This pack's own `base` is added to it, because the purchase and the offer are\n * one transaction — the tokens are in the vault before the draw is written.\n *\n * Every amount is capped at what is actually available. A tier that rounds to zero tokens is an\n * error: the pool must not sell a ticket that can only win nothing.\n */\nexport function quote(\n base: bigint,\n tiers: readonly Readonly<Tier>[],\n inventory: bigint,\n reserved: bigint,\n): Offer {\n validateTiers(tiers);\n if (inventory < reserved) {\n throw new GaboxMathError(\n \"InsolventInventory\",\n \"the vault holds less than the pool has already reserved\",\n );\n }\n const available = checkedU64(\n inventory - reserved + base,\n \"available inventory\",\n );\n\n const prizes: Prize[] = Array.from({ length: TIERS }, () => ({\n amount: 0n,\n tickets: 0,\n }));\n let maximum = 0n;\n let minimum = U64_MAX;\n\n for (const [i, tier] of tiers.entries()) {\n if (tier.tickets === 0) continue;\n const uncapped = tierAmount(base, tier.multiplierBps);\n if (uncapped === 0n) {\n throw new GaboxMathError(\n \"PackTooSmall\",\n `tier ${i} rounds to zero tokens at this pack size`,\n );\n }\n const amount = uncapped < available ? uncapped : available;\n prizes[i] = { amount, tickets: tier.tickets };\n if (amount > maximum) maximum = amount;\n if (amount < minimum) minimum = amount;\n }\n\n return { prizes, maximum, minimum };\n}\n\n/**\n * `math::choose`. Which prize a 16-bit ticket wins.\n *\n * The rows are consecutive ranges in table order, so this is a running total and a comparison.\n * A ticket past the last row returns `0`, which cannot happen for a validated table.\n */\nexport function choose(prizes: readonly Prize[], ticket: number): bigint {\n let end = 0;\n for (const prize of prizes) {\n end += prize.tickets;\n if (ticket < end) return prize.amount;\n }\n return 0n;\n}\n\n/** `math::resolve_reservation`. Release the unwon part of a maximum, keep the award reserved. */\nexport function resolveReservation(\n reserved: bigint,\n maximum: bigint,\n award: bigint,\n): bigint {\n if (award > maximum) {\n throw new GaboxMathError(\n \"InsolventInventory\",\n \"the award exceeds the reserved maximum\",\n );\n }\n if (reserved < maximum) {\n throw new GaboxMathError(\n \"Arithmetic\",\n \"the pool has reserved less than this draw holds\",\n );\n }\n return checkedU64(reserved - maximum + award, \"reserved\");\n}\n\n/** The largest `multiplierBps` on any ticketed row. `0` for a table with no rows. */\nexport function maxMultiplierBps(tiers: readonly Readonly<Tier>[]): number {\n validateTiers(tiers);\n let largest = 0;\n for (const tier of tiers) {\n if (tier.tickets === 0) continue;\n if (tier.multiplierBps > largest) largest = tier.multiplierBps;\n }\n return largest;\n}\n\n/**\n * The expected multiplier over all 65,536 tickets, in basis points. Rounded down.\n *\n * `validateTiers` caps this at 10,000. A table at 9,800 keeps 2% of every pack's tokens in the\n * vault on average, which is what lets a pool survive a run of top-tier wins.\n */\nexport function averageMultiplierBps(tiers: readonly Readonly<Tier>[]): number {\n validateTiers(tiers);\n let weighted = 0n;\n for (const tier of tiers) {\n if (tier.tickets === 0) continue;\n weighted += BigInt(tier.multiplierBps) * BigInt(tier.tickets);\n }\n return Number(weighted / BigInt(TICKETS));\n}\n","/**\n * Gabox's own program-derived addresses.\n *\n * Raydium's live in `src/raydium/pdas.ts`, because they depend on the cluster. These do not: the\n * Gabox program id is the same everywhere.\n *\n * Classic SPL Token only. Both venues use it, and the accepted LaunchLab create instruction mints\n * the coin with it, so no derivation here takes a token program any more.\n */\n\nimport {\n getAddressEncoder,\n getBytesEncoder,\n getProgramDerivedAddress,\n type Address,\n type ProgramDerivedAddress,\n} from '@solana/kit';\n\nimport { findActivityPda } from './generated/pdas/activity';\nimport { findDrawPda } from './generated/pdas/draw';\nimport { findIdentityPda } from './generated/pdas/identity';\nimport { findPoolPda } from './generated/pdas/pool';\nimport { GABOX_PROGRAM_ID, IDENTITY_SEED, TOKEN_PROGRAM_ADDRESS, VRF_PROGRAM_ADDRESS } from './ids';\nimport { ata } from './raydium/pdas';\n\nexport { findActivityPda, findDrawPda, findIdentityPda, findPoolPda };\n\n/** `[\"pool\", mint]`. One pool per coin. */\nexport const poolAddress = async (mint: Address): Promise<Address> => (await findPoolPda({ mint }))[0];\n\n/** `[\"draw\", pool, seq]`, with the sequence as eight little-endian bytes. */\nexport const drawAddress = async (pool: Address, seq: bigint): Promise<Address> =>\n (await findDrawPda({ pool, seq }))[0];\n\n/** The per-wallet `WalletActivity` PDA. `buy_pack` derives it from the purchaser automatically. */\nexport const activityAddress = async (wallet: Address): Promise<Address> =>\n (await findActivityPda({ purchaser: wallet }))[0];\n\n/** `[\"identity\"]` under Gabox. The PDA the program signs its randomness request with. */\nexport const vrfIdentityAddress = async (): Promise<Address> => (await findIdentityPda())[0];\n\n/** `[\"identity\", gabox_program_id]` under the VRF program. MagicBlock signs the callback with it. */\nexport async function scopedVrfIdentityAddress(): Promise<ProgramDerivedAddress> {\n return await getProgramDerivedAddress({\n programAddress: VRF_PROGRAM_ADDRESS,\n seeds: [getBytesEncoder().encode(IDENTITY_SEED), getAddressEncoder().encode(GABOX_PROGRAM_ID)],\n });\n}\n\n/** An associated token account under classic SPL Token. */\nexport const associatedTokenAddress = async (\n owner: Address,\n mint: Address,\n tokenProgram: Address = TOKEN_PROGRAM_ADDRESS,\n): Promise<Address> => await ata(owner, mint, tokenProgram);\n\n/** The prize vault: the pool PDA's own associated token account for the coin. */\nexport const vaultAddress = async (mint: Address): Promise<Address> =>\n await associatedTokenAddress(await poolAddress(mint), mint);\n","/** Account readers and bounded discovery scans. Old pool layouts are intentionally unsupported. */\nimport {\n fetchEncodedAccount, getBase58Decoder, getBase64Encoder,\n type Address, type Base58EncodedBytes, type MaybeEncodedAccount,\n} from '@solana/kit';\nimport { DRAW_DISCRIMINATOR, decodeDraw, getDrawSize, type Draw } from './generated/accounts/draw';\nimport { POOL_DISCRIMINATOR, decodePool, getPoolSize, type Pool } from './generated/accounts/pool';\nimport { WALLET_ACTIVITY_DISCRIMINATOR, decodeWalletActivity, getWalletActivitySize, type WalletActivity } from './generated/accounts/walletActivity';\nimport { GABOX_PROGRAM_ID } from './ids';\nimport { quote, type Tier } from './math';\nimport { activityAddress, poolAddress, vaultAddress } from './pdas';\nimport { tokenAccountAmount } from './raydium/adapter';\nimport type { GaboxClient, GaboxRpc } from './rpc';\n\nexport { decodeDraw, decodePool, decodeWalletActivity, DRAW_DISCRIMINATOR, POOL_DISCRIMINATOR, WALLET_ACTIVITY_DISCRIMINATOR };\nexport type { Draw, Pool, WalletActivity };\n\nconst DISCRIMINATOR = 8;\nconst PUBKEY = 32;\nexport const DRAW_POOL_OFFSET = DISCRIMINATOR;\nexport const DRAW_PURCHASER_OFFSET = DISCRIMINATOR + PUBKEY;\nexport const POOL_CREATOR_OFFSET = DISCRIMINATOR;\nexport const POOL_MINT_OFFSET = DISCRIMINATOR + PUBKEY;\nconst base58 = getBase58Decoder();\nconst base64 = getBase64Encoder();\n\ntype ProgramAccountFilter = { memcmp: { offset: bigint; bytes: Base58EncodedBytes; encoding: 'base58' } } | { dataSize: bigint };\nconst asBase58 = (bytes: Uint8Array): Base58EncodedBytes => base58.decode(bytes) as Base58EncodedBytes;\nconst memcmp = (offset: number, bytes: Base58EncodedBytes): ProgramAccountFilter => ({ memcmp: { offset: BigInt(offset), bytes, encoding: 'base58' } });\nconst encoded = (address: Address, data: Uint8Array) => ({ address, data, exists: true as const, executable: false, lamports: 0n as never, programAddress: GABOX_PROGRAM_ID, space: BigInt(data.length) });\n\nexport async function fetchPoolByMint(client: GaboxClient, mint: Address): Promise<Pool | null> {\n return await fetchPoolAt(client, await poolAddress(mint));\n}\n\nexport async function fetchPoolAt(client: GaboxClient, address: Address): Promise<Pool | null> {\n const account = await fetchEncodedAccount(client.rpc, address, { commitment: 'confirmed' });\n return decodeCurrentPool(account);\n}\n\nfunction decodeCurrentPool(account: MaybeEncodedAccount): Pool | null {\n if (!account.exists) return null;\n if (account.data.length !== getPoolSize()) {\n throw new Error(`pool ${account.address} is not a Gabox pool and is intentionally unsupported`);\n }\n return decodePool(account).data;\n}\n\nfunction decodeCurrentDraw(account: MaybeEncodedAccount): Draw | null {\n if (!account.exists) return null;\n if (account.data.length !== getDrawSize()) {\n throw new Error(`draw ${account.address} is not a Gabox draw and is intentionally unsupported`);\n }\n return decodeDraw(account).data;\n}\n\nexport async function fetchDraw(client: GaboxClient, address: Address): Promise<Draw | null> {\n const account = await fetchEncodedAccount(client.rpc, address, { commitment: 'confirmed' });\n return decodeCurrentDraw(account);\n}\n\nfunction decodeCurrentWalletActivity(account: MaybeEncodedAccount): WalletActivity | null {\n if (!account.exists) return null;\n if (account.data.length !== getWalletActivitySize()) {\n throw new Error(`activity account ${account.address} is not a Gabox WalletActivity and is intentionally unsupported`);\n }\n return decodeWalletActivity(account).data;\n}\n\n/**\n * A wallet's lifetime pack-buying activity, or `null` before it has bought its first pack.\n * `buy_pack` creates this account `init_if_needed`, so a fresh wallet has none yet.\n */\nexport async function fetchWalletActivity(client: GaboxClient, wallet: Address): Promise<WalletActivity | null> {\n const account = await fetchEncodedAccount(client.rpc, await activityAddress(wallet), { commitment: 'confirmed' });\n return decodeCurrentWalletActivity(account);\n}\n\nexport type PoolRecord = { address: Address; data: Pool };\nexport type DrawRecord = { address: Address; data: Draw };\n\nasync function scan<T>(rpc: GaboxRpc, filters: ProgramAccountFilter[], decode: (address: Address, data: Uint8Array) => T): Promise<T[]> {\n const accounts = await rpc.getProgramAccounts(GABOX_PROGRAM_ID, { encoding: 'base64', commitment: 'confirmed', filters }).send();\n return accounts.map(({ pubkey, account }) => decode(pubkey, new Uint8Array(base64.encode(account.data[0]))));\n}\n\nexport async function listPools(client: GaboxClient): Promise<PoolRecord[]> {\n return await scan(client.rpc, [memcmp(0, asBase58(POOL_DISCRIMINATOR as Uint8Array)), { dataSize: BigInt(getPoolSize()) }],\n (address, data) => ({ address, data: decodePool(encoded(address, data)).data }));\n}\n\nexport type DrawQuery = { pool?: Address; purchaser?: Address };\nexport async function listDraws(client: GaboxClient, query: DrawQuery = {}): Promise<DrawRecord[]> {\n const filters: ProgramAccountFilter[] = [memcmp(0, asBase58(DRAW_DISCRIMINATOR as Uint8Array)), { dataSize: BigInt(getDrawSize()) }];\n if (query.pool) filters.push(memcmp(DRAW_POOL_OFFSET, query.pool as unknown as Base58EncodedBytes));\n if (query.purchaser) filters.push(memcmp(DRAW_PURCHASER_OFFSET, query.purchaser as unknown as Base58EncodedBytes));\n return await scan(client.rpc, filters, (address, data) => ({ address, data: decodeDraw(encoded(address, data)).data }));\n}\nexport const listDrawsByPool = async (client: GaboxClient, pool: Address): Promise<DrawRecord[]> => await listDraws(client, { pool });\nexport const listDrawsByPurchaser = async (client: GaboxClient, purchaser: Address): Promise<DrawRecord[]> => await listDraws(client, { purchaser });\n\nexport async function fetchVaultBalance(client: GaboxClient, mint: Address): Promise<bigint> {\n const vault = await vaultAddress(mint);\n const { value } = await client.rpc.getAccountInfo(vault, { encoding: 'base64', commitment: 'confirmed' }).send();\n return value ? tokenAccountAmount(new Uint8Array(base64.encode(value.data[0]))) : 0n;\n}\n\nexport type PoolInventory = { poolAddress: Address; pool: Pool; inventory: bigint; reserved: bigint; free: bigint };\nexport async function fetchPoolInventory(client: GaboxClient, mint: Address): Promise<PoolInventory | null> {\n // `reserved` and the vault amount form one invariant. Fetching them in separate RPC calls can\n // advertise free inventory that never existed at one slot while a buy or delivery is in flight.\n // Classic SPL Token owns every Gabox coin, so this is the sole supported vault PDA.\n const poolPda = await poolAddress(mint);\n const vaultPda = await vaultAddress(mint);\n const { value } = await client.rpc.getMultipleAccounts(\n [poolPda, vaultPda], { encoding: 'base64', commitment: 'confirmed' },\n ).send();\n const poolAccount = value[0];\n if (!poolAccount) return null;\n const pool = decodeCurrentPool(encoded(poolPda, new Uint8Array(base64.encode(poolAccount.data[0]))));\n if (!pool) return null;\n if (pool.vault !== vaultPda) {\n throw new Error(`pool ${poolPda} has an unexpected vault; it is not a supported Gabox pool`);\n }\n const vaultAccount = value[1];\n const inventory = vaultAccount\n ? tokenAccountAmount(new Uint8Array(base64.encode(vaultAccount.data[0])))\n : 0n;\n return { poolAddress: poolPda, pool, inventory, reserved: pool.reserved, free: inventory > pool.reserved ? inventory - pool.reserved : 0n };\n}\nexport const tiersOf = (pool: Pool): Tier[] => pool.tiers.map(({ multiplierBps, tickets }) => ({ multiplierBps, tickets }));\nexport const quotePool = (inventory: PoolInventory) => quote(inventory.pool.packTokens, tiersOf(inventory.pool), inventory.inventory, inventory.reserved);\n","/** Decode Gabox's Anchor events. Draw accounts are closed on delivery; use `DrawResolved` as final state. */\nimport { getBase64Encoder, type Address, type ReadonlyUint8Array, type Signature } from '@solana/kit';\nimport { DRAW_RESOLVED_EVENT_DISCRIMINATOR, getDrawResolvedEventDecoder, type DrawResolvedEvent } from './generated/events/drawResolved';\nimport { PACK_BOUGHT_EVENT_DISCRIMINATOR, getPackBoughtEventDecoder, type PackBoughtEvent } from './generated/events/packBought';\nimport { POOL_CREATED_EVENT_DISCRIMINATOR, getPoolCreatedEventDecoder, type PoolCreatedEvent } from './generated/events/poolCreated';\nimport { PRIZES_FUNDED_EVENT_DISCRIMINATOR, getPrizesFundedEventDecoder, type PrizesFundedEvent } from './generated/events/prizesFunded';\nimport { RANDOMNESS_RETRIED_EVENT_DISCRIMINATOR, getRandomnessRetriedEventDecoder, type RandomnessRetriedEvent } from './generated/events/randomnessRetried';\nimport { TOKENS_SOLD_EVENT_DISCRIMINATOR, getTokensSoldEventDecoder, type TokensSoldEvent } from './generated/events/tokensSold';\nimport { drawAddress } from './pdas';\nimport { GABOX_PROGRAM_ID } from './ids';\nimport type { GaboxClient, GaboxRpc } from './rpc';\n\nexport type GaboxEvent =\n | { name: 'PoolCreated'; data: PoolCreatedEvent }\n | { name: 'PrizesFunded'; data: PrizesFundedEvent }\n | { name: 'PackBought'; data: PackBoughtEvent }\n | { name: 'RandomnessRetried'; data: RandomnessRetriedEvent }\n | { name: 'DrawResolved'; data: DrawResolvedEvent }\n | { name: 'TokensSold'; data: TokensSoldEvent };\nconst b64 = getBase64Encoder();\nconst starts = (a: Uint8Array, b: ReadonlyUint8Array): boolean => a.length >= b.length && b.every((v, i) => a[i] === v);\nexport function decodeEvent(data: Uint8Array): GaboxEvent | null {\n if (starts(data, POOL_CREATED_EVENT_DISCRIMINATOR)) return { name: 'PoolCreated', data: getPoolCreatedEventDecoder().decode(data) };\n if (starts(data, PRIZES_FUNDED_EVENT_DISCRIMINATOR)) return { name: 'PrizesFunded', data: getPrizesFundedEventDecoder().decode(data) };\n if (starts(data, PACK_BOUGHT_EVENT_DISCRIMINATOR)) return { name: 'PackBought', data: getPackBoughtEventDecoder().decode(data) };\n if (starts(data, RANDOMNESS_RETRIED_EVENT_DISCRIMINATOR)) return { name: 'RandomnessRetried', data: getRandomnessRetriedEventDecoder().decode(data) };\n if (starts(data, DRAW_RESOLVED_EVENT_DISCRIMINATOR)) return { name: 'DrawResolved', data: getDrawResolvedEventDecoder().decode(data) };\n if (starts(data, TOKENS_SOLD_EVENT_DISCRIMINATOR)) return { name: 'TokensSold', data: getTokensSoldEventDecoder().decode(data) };\n return null;\n}\ntype EventFrame = { programId: string; pending: GaboxEvent[] };\nconst BASE58 = '[1-9A-HJ-NP-Za-km-z]+';\nconst INVOKE = new RegExp(`^Program (${BASE58}) invoke \\\\[(\\\\d+)\\\\]$`);\nconst SUCCESS = new RegExp(`^Program (${BASE58}) success$`);\nconst FAILED = new RegExp(`^Program (${BASE58}) failed: .*$`);\n\n/**\n * Decode only Gabox events committed by successful runtime frames. Program logs are emitted before\n * transaction commit and are forgeable by arbitrary programs, so `Program data` is authenticated\n * by the canonical invoke/success stack and buffered until every enclosing frame succeeds.\n */\nexport function decodeEvents(logs: readonly string[]): GaboxEvent[] {\n const committed: GaboxEvent[] = [];\n const stack: EventFrame[] = [];\n const discardOpenFrames = () => { stack.length = 0; };\n let malformed = false;\n let transactionFailed = false;\n for (const line of logs) {\n const invoke = INVOKE.exec(line);\n if (invoke) {\n const depth = Number(invoke[2]);\n if (depth !== stack.length + 1) { malformed = true; discardOpenFrames(); continue; }\n stack.push({ programId: invoke[1]!, pending: [] });\n continue;\n }\n const success = SUCCESS.exec(line);\n const failed = FAILED.exec(line);\n if (success || failed) {\n const programId = (success ?? failed)![1]!;\n const frame = stack.at(-1);\n if (!frame || frame.programId !== programId) { malformed = true; discardOpenFrames(); continue; }\n stack.pop();\n if (success) {\n const parent = stack.at(-1);\n if (parent) parent.pending.push(...frame.pending);\n else committed.push(...frame.pending);\n }\n // A failed frame's pending events are deliberately discarded, including caught CPI logs.\n // A depth-one failure rolls the entire transaction back, including earlier root frames.\n if (failed && stack.length === 0) transactionFailed = true;\n continue;\n }\n const frame = stack.at(-1);\n if (!line.startsWith('Program data: ') || frame?.programId !== GABOX_PROGRAM_ID) continue;\n try {\n const event = decodeEvent(new Uint8Array(b64.encode(line.slice(14).trim())));\n if (event) frame.pending.push(event);\n } catch { /* malformed or unrelated event bytes */ }\n }\n // A truncated/malformed lifecycle cannot authenticate any output. A failed root means the whole\n // transaction rolled back, even if a previous root instruction had logged an event successfully.\n return malformed || transactionFailed || stack.length !== 0 ? [] : committed;\n}\nexport async function fetchEvents(client: GaboxClient, signature: string): Promise<GaboxEvent[]> { return await readEvents(client.rpc, signature); }\nasync function readEvents(rpc: GaboxRpc, signature: string): Promise<GaboxEvent[]> {\n const tx = await rpc.getTransaction(signature as never, { commitment: 'confirmed', encoding: 'json', maxSupportedTransactionVersion: 0 }).send();\n const meta = tx?.meta;\n if (!tx || !meta || meta.err) return [];\n return decodeEvents(meta.logMessages ?? []);\n}\nexport type ResolvedDraw = DrawResolvedEvent & { address: Address };\n/** Poll final resolution events for one closed draw address. There is no separate Ready/claim state to poll instead. */\nexport async function findResolvedDraw(client: GaboxClient, address: Address): Promise<ResolvedDraw | null> {\n // Closed draw PDAs can still be mentioned by arbitrary transactions. Search a bounded 1,000\n // signatures rather than only the newest ten so that this convenience lookup is not trivially\n // buried. Production history/indexing should still persist `DrawResolved` events itself.\n let before: Signature | undefined;\n for (let page = 0; page < 10; page++) {\n const rows = await client.rpc.getSignaturesForAddress(address, {\n commitment: 'confirmed', limit: 100, ...(before ? { before } : {}),\n }).send();\n for (const row of rows) {\n if (row.err) continue;\n for (const event of await readEvents(client.rpc, row.signature)) {\n if (event.name !== 'DrawResolved') continue;\n // One transaction can resolve multiple draws; bind the decoded event, not just the\n // transaction signature, to the queried draw PDA.\n if (await drawAddress(event.data.pool, event.data.seq) === address) return { ...event.data, address };\n }\n }\n if (rows.length < 100) return null;\n before = rows.at(-1)?.signature;\n if (!before) return null;\n }\n return null;\n}\n","/**\n * Shared devnet address lookup table, verified on 2026-09-18T07:26:38.218Z.\n * Generated by scripts/deploy-lookup-table.ts. Existing indices are immutable;\n * keep this table active while clients use it. Authority is the devnet deploy wallet.\n */\nimport { address, type Address, type AddressesByLookupTableAddress } from '@solana/kit';\n\nimport type { Cluster } from './rpc';\n\nexport const DEVNET_LOOKUP_TABLE_ADDRESS = address('Cx4ri1BU2bnDXPjnJykF3nbY2u4MD5pPvzFCJtNizWFa');\nexport const DEVNET_LOOKUP_TABLE_ADDRESSES: readonly Address[] = [\n address('GaBoxR9nYcK1zeu8EvSJVHV3SrYpCFmvbh2MLgobMcUA'),\n address('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'),\n address('TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'),\n address('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL'),\n address('6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P'),\n address('pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA'),\n address('pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ'),\n address('11111111111111111111111111111111'),\n address('MAyhSmzXzV1pTf7LsNkrNwkWKTo4ougAJ1PPg47MD4e'),\n address('So11111111111111111111111111111111111111112'),\n address('Vrf1RNUjXmQGjmQrQLvJHs9SNkvDJEsRVFPkfSQUwGz'),\n address('Cuj97ggrhhidhbu39TijNVqE74xvKJ69gDervRUXAxGh'),\n address('SysvarS1otHashes111111111111111111111111111'),\n address('Sysvar1nstructions1111111111111111111111111'),\n address('4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf'),\n address('Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1'),\n address('8Wf5TiAheLUqBrKXeYg2JtAFFMWtKdG2BSFgqUcPVwTt'),\n address('Hq2wp8uJ9jCPsYgNHex8RtqdvMPfVGoYwjvF1ATiwn2Y'),\n address('TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM'),\n address('13ec7XdrjF3h3YcqBTFDSReRcUFwbCnJaAQspM4j6DDJ'),\n address('BwWK17cbHxwWBKZkUYvzxLcNQ1YVyaFezduWbtm2de6s'),\n address('ADyA8hdefvWN2dbGGWFotbzWxrAvLW83WG6QCVXvJKqw'),\n address('GS4CU59F31iL7aR2Q8zVS8DRrcRnXX1yjQ66TqNVQnaR'),\n address('5PHirr8joyTMp9JMm6nW7hNDVyEYdkzDqazxPD7RaTjx'),\n address('C2aFPdENg4A2HQsmrd5rTw5TaYBX5Ku887cWjbFKtZpw'),\n address('7ahYg76P8bhifT1Uj3hNHGKRFPp6bLkx1ppNrWbnsfu2'),\n address('68yFSZxzLWJXkxxRGydZ63C6mHx1NLEDWmwN9Lb5yySg'),\n address('DLP9ADYpdQV4Z4UQDZof7iLHu2qqdzmMPjcAHDGe4jTt'),\n address('6QgPshH1egekJ2TURfakiiApDdv98qfRuRe7RectX8xs'),\n address('FmFPTNDmmVDhqzaqZYhnt4fj5fJP3pffcMWf2b5JnRTk'),\n address('78i5hpHxbtmosSJdfJ74WzwdUr3eKWg9RbCPpBeAF78t'),\n address('7611SPS3UkjsA43auxPpJpPVAkgEHg4dTVorK839GonW'),\n address('8RMFYhsVsfdGCuWPFLxMCbSpSesiofabDdNorGqFrBNe'),\n address('9GbQXDFHKLdr4BzZ8Cx2pkX2aM2Kg7yEeYnUCKjZGE4M'),\n address('9GDepfBcjJMvNgmijXWVWa97Am7VZYCqXx7kJV44E9ij'),\n address('3fyMEgHADGRrBnCVLU7u9AwpiMtmGDWViJzDQC8kgRa5'),\n address('9ppkS5madL2uXozoEnMnZi5bKDq9jgdKkSavjWTS5NfW'),\n address('C3PvwRFdKT6caSLxnwy8h67KWNevoboNDg6bwJZYzWB5'),\n address('DDMCfwbcaNYTeMk1ca8tr8BQKFaUfFCWFwBJq8JcnyCw'),\n address('FrYoobDtL7w1HrTjHAc8Ya7qQzEdJPhGXXFKskCDaA3p'),\n address('DRDBsRMst21CJUhwD16pncgiXnBrFaRAPvA2G6SUQceE'),\n address('J7JbDVnGKus2M9PKzH7ZbeCYugEYDgpGBfqKL85dQbU7'),\n address('5YxQFdt3Tr9zJLvkFccqXVUwhdTWJQc1fFg2YPbxvxeD'),\n address('HjQjngTDqoHE6aaGhUqfz9aQ7WZcBRjy5xB8PScLSr8i'),\n address('9M4giFFMxmFGXtc3feFzRai56WbBqehoSeRE5GK7gf7'),\n address('GAFuhgcd328SkkBYHpfadzmef9hTGAFRCi9QoCnsZQug'),\n address('GXPFM2caqTtQYC2cJ5yJRi9VDkpsYZXzYdwYpGnLmtDL'),\n address('AktftA98kSWAxn6kVSoqBXBELUArjKu2H9WmKB48ULFY'),\n address('3BpXnfJaUTiwXnJNe7Ej1rcbzqTTQUvLShZaWazebsVR'),\n address('6rVkF4HSgy1jrnC3HogfRgPHrq4CtLg5f11URpsC4i9D'),\n address('5cjcW9wExnJJiqgLjq7DEG75Pm6JBgE1hNv4B2vHXUW6'),\n address('GYH1Gae1wJytMSvMvw8JVcv7nuAbxi8i9erNVbERnzXd'),\n address('EHAAiTxcdDwQ3U4bU6YcMsQGaekdzLS3B5SmYo46kJtL'),\n address('CA7v8gHfbquYXyDnDx6QxWW8hmL1H7X6Y2RYDrGLnuck'),\n address('5eHhjP8JaYkz83CWwvGU2uMUXefd3AazWGx4gpcuEEYD'),\n address('CASRL2zkwDnppxEFQ4LgdwgR9pdz5Q8R8nEMKVZ9QoLp'),\n address('A7hAgCzFw14fejgCp387JUJRMNyz4j89JKnhtKU8piqW'),\n address('qkYdTGRPHbWTWuBMz45bCiU6a23axRqf6sBHm9295WY'),\n address('12e2F4DKkD3Lff6WPYsU7Xd76SHPEyN9T8XSsTJNF8oT'),\n address('GjJkcak9e4L2HsxSZqVsc81L7coChdR7F3ciJYnQcSnU'),\n address('2Ej38XSkmpvXzoUg5ZLma7Y9rCiZVgxzTdvE3Kph5juM'),\n address('2daQRytJgLzLLziPNQBNJ7w1Ltz3XqZG4dZxBamLAf7v'),\n address('3PAxmkxnM2vHno9amWQCsaaFjYnPGcD87HZGx1ChVjPj'),\n address('BWS634asUFdrpYpfofFA1CrGB9wEbh9gt8XswZ4AWz9J'),\n address('4QZqaBNm2F7viBDhhs8AQ5wC9FshgLJEiLLFGoxZZrTn'),\n address('4JaPhJE7WgQZ3xFbxn2spU97reA13SiM99wD3RF4Lqro'),\n address('9xvDPD6G7NRCEu7W2M9vCLeo8we23Ww7pzQEhXcuJAmA'),\n address('AHEgRGXFn8JbhXccWM4i1meRGPFbx8kzb9BGN6ocqRFL'),\n address('CdkG7sp1LT9YLsDaTWREaQcX6W4gZySk3o1eSjoL2uTh'),\n address('2pLUmsYktT7gR6P5hXs9Ldo6Vg1oQB2Q4NPbJqHUjZhq'),\n address('Freijj9xKLefjrb5fHgT6KMbYG1XBP2mA83tqeXYUMYM'),\n address('4uzPz9TPskXiiEZ6X78rqud8LvfdxkJBr5EKHgbx4azP'),\n address('Hxzab4UjjVH2KjsdAqzdxGdYUpNN5FKhpu7iikB869uH'),\n address('Frkwunr9dQM9d4TthfQ2unxC994XpkLMpkRP2e7yfirk'),\n address('E6ShohW57z5CJPBeEcFAEbvPqUyt6QxHcxnkh4hMaNrg'),\n address('6z6GDdfb2AjR9ZhJmAUQ5cipJCVxQvLJhB2H8mCwTFBP'),\n address('D9LwzTvJ5XoGxorcdaZvBgq7Qruqewu2P9WVsgSrKURd'),\n address('4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU'),\n address('GCow1cTVRa43v8EX1eVwVobiKXoyZjfQpwAvgpZ8B2KP'),\n address('65LkFkYo9gMD6AwXTbSsxR3d28pCVbJp5AtE9NK3634n'),\n address('8wDZLhae9WbNvm3eCgHVDrXUhJbd3gx6DnTnhsw45XEj'),\n address('CPgoAkfWjiUZfNLRp94hD7BjmDSFy96mS8xcQKoPFB4H'),\n address('GXVKyyXsoUihF1uzGCx7YXVqQ7kimUDAo3xyqULvgDyB'),\n address('5tpFHeni6NYD6pQpkuReVPGtCJLyaXDq97FTJJzyZMjt'),\n address('DNscAYMk2LW55Aq7FTj24mRbwVPZ6EgvCUoabhhtdVCW'),\n address('7Q2wpniGesAyAkjACpg58BAcDjBKcdcX9a6RAgszVh4M'),\n address('7gx9ZEwMSd1ifHBEgVaUsCkQmHTFJTWVs3C1bQABQ22T'),\n address('GsVBKjffkB769p9tHTZWoAX3r9T6dXoDTJr3f7XutJH7'),\n address('9NFrxdnmedHKHs1tnhYm9G5XTJh7Lt7xN6uxgZzwQNM7'),\n address('BhMknQ4j9RZUbJk6GS4QJh8MSKxcqZHS2x9MZh2AH9hA'),\n address('9NW32ymMo8Qx6DTbgkxtnD8Dh9hssQYpcyY2Brdpg2hs'),\n address('5a8Gfgwx4hrCtYKgvjtX57FsirXPRN7Jzm9aXmn6hQs8'),\n address('5KUNmCZatysY7fxLtTgo2bpkqevPRZZG8fkrh3e1P89F'),\n address('HPfEytxa5JGqmGiVwrSepAcNTkWboxvtQKbyWN9DNCoQ'),\n address('Gr5kHfDBd7GAdjK6Ct3EDC566XFPjCr3mLCkKVxJYrMD'),\n address('HzCwuA6T48enyWvCJWrLhNvMpJJR43kddjMGFf6LyA9L'),\n address('Do4esSd37h4uHz35piua8rRtcXDNt27re8NDqqZfjsGJ'),\n address('2GC6K75FS6MpRrMZYXifinC2sVXP3htsJpayerx7ACci'),\n address('FvEpzodkyvMzRHQo4q7fhvfa287hnjfr1oiumRtQXrse'),\n address('8SwxZnhYHeC9S93ZFzLTd9dC2c44hfCdGyoXYzA7U6Db'),\n address('6B1oS2LSDYHyXpRF9S8C6r5LffitosDrhie2WWsUtfRV'),\n address('F2pzDCn3vqXcNWF6osLxSvVtf3CyTkHd4tRxhGjyRZQ9'),\n address('DKESpHxobrT9Ra4snSXCD4cdhQMqpzmGhZN1HZ3sUYMY'),\n address('metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s'),\n address('SysvarRent111111111111111111111111111111111'),\n address('DRay6fNdQ5J82H7xV6uq2aV3mNrUZ1J4PgSKsWgptcm6'),\n address('5xqNaZXX5eUi4p5HU4oz9i5QnwRNT2y6oN7yyn4qENeq'),\n address('4uAB7seenFJKPUXqYewAdfra2u6baBgjiXU8x1SC7Ycz'),\n address('7ZR4zD7PYfY2XxoG1Gxcy2EgEeGYrpxrwzPuwdUBssEt'),\n address('DdEeCPXbCAzHE2PZSoR3RZng4WA4bSztrezQznrJ4ooB'),\n address('DRaycpLY18LhpbydsBWbVJtxpNv9oXPgjRSfpF2bWpYb'),\n address('CXniRufdq5xL8t8jZAPxsPZDpuudwuJSPWnbcD5Y5Nxq'),\n address('G7YfJJp1TX1VtzN4V2yhPNSU23AKPSy1U2miRdwAByK5'),\n address('5WcPTEQ59UqpQzjZUPbU8QRGCbj7NeQNLDa7DbsLkLKT'),\n];\nexport const DEVNET_ADDRESS_LOOKUP_TABLES: AddressesByLookupTableAddress = {\n [DEVNET_LOOKUP_TABLE_ADDRESS]: [...DEVNET_LOOKUP_TABLE_ADDRESSES],\n};\n\n/**\n * The tables a client compresses with when its config names none.\n *\n * Only devnet has a shared table today. Mainnet gets one when the program is deployed there; until\n * then a mainnet or localnet client compresses with nothing, and a message over 1,232 bytes fails\n * in `buildMessage` with a request for tables. Pass `addressLookupTables` to `createClient` to\n * supply your own.\n */\nexport function defaultAddressLookupTables(cluster: Cluster): AddressesByLookupTableAddress {\n return cluster === 'devnet' ? { ...DEVNET_ADDRESS_LOOKUP_TABLES } : {};\n}\n","/**\n * What one pack costs and what it can win, right now, for a real coin.\n *\n * This is the read every buyer-facing screen makes. It puts three things together that are useless\n * apart:\n *\n * 1. the venue's own quote — what `pool.packTokens` costs at this moment, its fees included;\n * 2. `math.quote` over the pack size and the vault's live inventory — the exact prize amounts a\n * pack buy would freeze into the `Draw`;\n * 3. whether the pool can pay the whole table.\n *\n * The prize amounts only move when the inventory cap bites. The price moves with the coin.\n *\n * Gabox charges nothing, so `quoteAmount` is the whole pack price. It already includes what\n * Raydium takes: on the curve, 0.5% to the Gabox platform wallet and 0.5% to the coin creator, plus\n * Raydium's own trade fee; on a graduated coin, the CPMM pool fee and the pool creator fee.\n *\n * Nothing here is an estimate of cash value. Every number is tokens or lamports.\n */\n\nimport type { Address } from '@solana/kit';\n\nimport { fetchPoolInventory, tiersOf, type PoolInventory } from './accounts';\nimport {\n averageMultiplierBps,\n maxMultiplierBps,\n quote,\n seedTokens,\n uncappedMaximum,\n type Offer,\n type Prize,\n} from './math';\nimport { resolveVenue, type VenueKind } from './raydium/venue';\nimport type { GaboxClient } from './rpc';\n\nexport type PackOffer = {\n mint: Address;\n pool: Address;\n /** The fixed token count of one pack. Every prize is a multiple of this. */\n packTokens: bigint;\n /** What the venue charges for `packTokens` right now, its own fees included. The pack price. */\n quoteAmount: bigint;\n /** Always WSOL today. Both venues settle in it; there is no native-SOL path. */\n quoteMint: Address;\n /** What the seed cost the creator at creation, in WSOL. Display only. */\n seedQuoteAmount: bigint;\n /** Tokens the seed locked in the vault. Derived from the live table. */\n seedTokens: bigint;\n /** Which venue the buy would route to right now. */\n venue: VenueKind;\n /** The frozen prize table this pack would get: real amounts, already capped by inventory. */\n prizes: Prize[];\n /** The top prize, after the cap. Sign `minMaximum` just below this. */\n maximum: bigint;\n /** The smallest prize. Also what a timed-out draw pays. */\n minimum: bigint;\n /**\n * The top prize with no inventory cap: the jackpot in tokens. Equal to `maximum` unless the\n * inventory cap bites.\n */\n uncapped: bigint;\n /** Vault balance, `pool.reserved`, and the difference. */\n inventory: bigint;\n reserved: bigint;\n free: bigint;\n /** `pool.nextSeq === 0`. No pack has been sold yet. */\n isFirstPack: boolean;\n /**\n * Does the pool pay the whole table right now?\n *\n * `offer.maximum === uncapped`. The seed guarantees this for the first pack. Later it is a\n * quality signal: a capped top prize is legal and the pool still sells the pack. It just pays\n * less than the table says, and a buyer should see that.\n */\n isSeeded: boolean;\n /** The largest and the ticket-weighted average multiplier of the immutable table, in bps. */\n maxMultiplierBps: number;\n averageMultiplierBps: number;\n};\n\nexport type GetOfferOptions = {\n /** Force a venue instead of reading the LaunchLab pool's `status`. */\n venue?: VenueKind;\n /** The buyer, when you already know it. Only changes the account list, never the numbers. */\n user?: Address;\n};\n\n/**\n * The full offer for one machine. Two round trips: the pool and its vault, then the venue.\n *\n * Throws when the coin has no pool.\n */\nexport async function getOffer(\n client: GaboxClient,\n mint: Address,\n options: GetOfferOptions = {},\n): Promise<PackOffer> {\n const inventory = await fetchPoolInventory(client, mint);\n if (!inventory) throw new Error(`no gabox pool for mint ${mint}`);\n\n const venue = await resolveVenue(client, {\n mint,\n user: options.user ?? inventory.pool.creator,\n ...(options.venue ? { venue: options.venue } : {}),\n });\n\n return offerFromState(inventory, venue.kind, venue.quoteBuy(inventory.pool.packTokens));\n}\n\n/**\n * The same computation with the reads already done. Useful when a caller holds a `ResolvedVenue`\n * and wants to re-price without touching the network. `quoteAmount` is\n * `venue.quoteBuy(pool.packTokens)`.\n */\nexport function offerFromState(\n inventory: PoolInventory,\n venue: VenueKind,\n quoteAmount: bigint,\n): PackOffer {\n const { pool } = inventory;\n const tiers = tiersOf(pool);\n const offer: Offer = quote(pool.packTokens, tiers, inventory.inventory, inventory.reserved);\n const uncapped = uncappedMaximum(pool.packTokens, tiers);\n\n return {\n mint: pool.mint,\n pool: inventory.poolAddress,\n packTokens: pool.packTokens,\n quoteAmount,\n quoteMint: pool.quoteMint,\n seedQuoteAmount: pool.seedQuoteAmount,\n seedTokens: seedTokens(pool.packTokens, tiers),\n venue,\n prizes: offer.prizes,\n maximum: offer.maximum,\n minimum: offer.minimum,\n uncapped,\n inventory: inventory.inventory,\n reserved: inventory.reserved,\n free: inventory.free,\n isFirstPack: pool.nextSeq === 0n,\n isSeeded: offer.maximum === uncapped,\n maxMultiplierBps: maxMultiplierBps(tiers),\n averageMultiplierBps: averageMultiplierBps(tiers),\n };\n}\n\n/**\n * How short of the top prize a pool is, in tokens. `0` when it pays the whole table.\n *\n * The pack brings its own `packTokens` into the vault before the offer is computed, so the vault\n * only has to hold `uncapped - packTokens` beforehand. Anything already reserved by another draw\n * does not count. A donation of this size through `fund_prizes` uncaps the top prize again.\n */\nexport function seedShortfall(offer: PackOffer): bigint {\n const needed = offer.uncapped > offer.packTokens ? offer.uncapped - offer.packTokens : 0n;\n return offer.free >= needed ? 0n : needed - offer.free;\n}\n\nexport { seedTokens };\n","/**\n * The client, and the cluster guard.\n *\n * `createClient` is the SDK's init step. It takes the cluster and the RPC endpoint once and returns\n * one object that every other chain-touching function in this SDK takes as its first argument: the\n * RPC, the subscriptions client, and the address lookup tables that cluster compresses with.\n *\n * # Why `cluster` has no default\n *\n * v1's simulator was one empty wallet away from running against mainnet. Nothing in the code said\n * which cluster it was pointed at; the answer lived in a shell variable and in the operator's head.\n * The failure would not have been a crash. It would have been real transactions on real money,\n * discovered afterwards.\n *\n * So the cluster is a property of the code, not of the environment. The caller names it in the\n * same call that names the URL, and the two are checked against each other:\n *\n * - `devnet` needs a URL that names devnet. A URL that names nothing is refused too, because\n * \"I thought this was devnet\" is exactly the accident this guard exists for.\n * - `mainnet-beta` and `localnet` refuse a URL that names a different cluster. A URL that names\n * nothing is allowed: private mainnet endpoints often do not say \"mainnet\", and a local\n * validator never says anything.\n *\n * Mainnet is one word away. It is a word the caller has to write.\n */\n\nimport {\n createSolanaRpc,\n createSolanaRpcSubscriptions,\n type AddressesByLookupTableAddress,\n type Rpc,\n type RpcSubscriptions,\n type SolanaRpcApi,\n type SolanaRpcSubscriptionsApi,\n} from '@solana/kit';\n\nimport { defaultAddressLookupTables } from './lookupTables';\n\nexport type Cluster = 'devnet' | 'mainnet-beta' | 'localnet';\n\n/** Solana's public endpoints, and the test validator's default ports. */\nexport const CLUSTER_ENDPOINTS: Readonly<Record<Cluster, { url: string; wsUrl: string }>> = {\n devnet: { url: 'https://api.devnet.solana.com', wsUrl: 'wss://api.devnet.solana.com' },\n 'mainnet-beta': {\n url: 'https://api.mainnet-beta.solana.com',\n wsUrl: 'wss://api.mainnet-beta.solana.com',\n },\n localnet: { url: 'http://127.0.0.1:8899', wsUrl: 'ws://127.0.0.1:8900' },\n};\n\nexport const DEVNET_HTTP = CLUSTER_ENDPOINTS.devnet.url;\nexport const DEVNET_WS = CLUSTER_ENDPOINTS.devnet.wsUrl;\n\nexport type GaboxRpc = Rpc<SolanaRpcApi>;\nexport type GaboxRpcSubscriptions = RpcSubscriptions<SolanaRpcSubscriptionsApi>;\n\nexport type ClientConfig = {\n /** The cluster this client talks to. Required: see the file comment. */\n cluster: Cluster;\n /** HTTP endpoint. Defaults to the cluster's entry in `CLUSTER_ENDPOINTS`. */\n url?: string;\n /**\n * WebSocket endpoint. Left out, it follows `url`: `https` becomes `wss`, `http` becomes `ws`.\n * When `url` is left out too, it is the cluster's default.\n */\n wsUrl?: string;\n /**\n * Address lookup tables every builder compresses with. Defaults to the cluster's shared table,\n * which only devnet has today; other clusters default to none. Pass `{}` to disable compression.\n */\n addressLookupTables?: AddressesByLookupTableAddress;\n};\n\n/**\n * Everything the SDK needs to talk to one cluster. Pass it to every chain-touching function.\n *\n * A plain object, so a caller who needs a custom transport can spread it:\n * `{ ...createClient({ cluster }), rpc: createSolanaRpcFromTransport(transport) }`.\n */\nexport type GaboxClient = Readonly<{\n cluster: Cluster;\n url: string;\n wsUrl: string;\n rpc: GaboxRpc;\n rpcSubscriptions: GaboxRpcSubscriptions;\n addressLookupTables: AddressesByLookupTableAddress;\n}>;\n\n/**\n * The cluster a URL names, from its text alone. A substring check, deliberately: providers spell\n * it many ways. `null` when the URL names none, which is a local validator or a private endpoint.\n */\nexport function clusterNamedBy(url: string): Cluster | 'testnet' | null {\n const lower = url.toLowerCase();\n if (lower.includes('devnet')) return 'devnet';\n if (lower.includes('mainnet')) return 'mainnet-beta';\n if (lower.includes('testnet')) return 'testnet';\n return null;\n}\n\n/**\n * Refuse a URL that contradicts the declared cluster. Exported so a script can check a URL before\n * it does anything else with it. The rules are in the file comment.\n */\nexport function assertClusterUrl(cluster: Cluster, url: string): void {\n const named = clusterNamedBy(url);\n if (cluster === 'devnet' && named !== 'devnet') {\n throw new Error(\n `refusing to use ${url} as a devnet endpoint: it does not name devnet.\\n` +\n 'A Gabox program id, a MagicBlock queue and a pool address all exist on every cluster, so ' +\n 'a wrong URL is a live transaction, not an error. Pass ' +\n \"{ cluster: 'localnet' } for a local validator, or name the cluster the URL really is.\",\n );\n }\n if (cluster !== 'devnet' && named !== null && named !== cluster) {\n throw new Error(\n `refusing to use ${url} as a ${cluster} endpoint: the URL names ${named}.\\n` +\n 'A Gabox address exists on every cluster, so a wrong URL is a live transaction, not an ' +\n 'error. Pass the cluster the URL really names.',\n );\n }\n}\n\n/** `https://x` becomes `wss://x`, `http://x` becomes `ws://x`. Anything else is returned as is. */\nexport function websocketUrlFor(url: string): string {\n if (url.startsWith('https://')) return `wss://${url.slice('https://'.length)}`;\n if (url.startsWith('http://')) return `ws://${url.slice('http://'.length)}`;\n return url;\n}\n\n/**\n * The SDK's init step. Call it once and pass the result everywhere.\n *\n * Both RPC clients are created together because everything in this SDK that watches a draw needs\n * the pair: the subscription reports the change, and the RPC reads the account that changed.\n */\nexport function createClient(config: ClientConfig): GaboxClient {\n const { cluster } = config;\n const defaults = CLUSTER_ENDPOINTS[cluster];\n if (!defaults) {\n throw new Error(\n `unknown cluster ${JSON.stringify(cluster)}; expected 'devnet', 'mainnet-beta' or 'localnet'`,\n );\n }\n\n const url = config.url ?? defaults.url;\n assertClusterUrl(cluster, url);\n\n // A custom `url` without a `wsUrl` gets the same host over WebSocket. The cluster's default\n // pair is only used as a pair: the test validator serves WebSocket on a different port.\n const wsUrl = config.wsUrl ?? (config.url === undefined ? defaults.wsUrl : websocketUrlFor(url));\n assertClusterUrl(cluster, wsUrl);\n\n return {\n cluster,\n url,\n wsUrl,\n rpc: createSolanaRpc(url),\n rpcSubscriptions: createSolanaRpcSubscriptions(wsUrl),\n addressLookupTables: config.addressLookupTables ?? defaultAddressLookupTables(cluster),\n };\n}\n","/**\n * Wrapping and unwrapping SOL around a venue trade.\n *\n * Both venues settle in WSOL, never in native SOL. So every builder in this directory does the same\n * three things around its Gabox instruction:\n *\n * 1. create the wallet's WSOL associated token account, if it is missing;\n * 2. move the lamports it is going to spend into that account and `syncNative` it, so the token\n * balance matches the lamports;\n * 3. close the account afterwards, which sends everything left back to the wallet as SOL.\n *\n * A sale needs no step 2: the proceeds arrive in the account, and the close is what turns them into\n * SOL.\n *\n * # Closing unwraps everything\n *\n * If the wallet already held WSOL in that account, the close turns that into SOL too. Nothing is\n * lost and the wallet still owns every lamport, but the balance moves out of the token account. A\n * wallet that keeps a WSOL position on purpose should build its own instructions instead of using\n * these builders.\n */\n\nimport {\n getCloseAccountInstruction,\n getCreateAssociatedTokenIdempotentInstruction,\n getSyncNativeInstruction,\n} from '@solana-program/token';\nimport { getTransferSolInstruction } from '@solana-program/system';\nimport type { Address, Instruction, TransactionSigner } from '@solana/kit';\n\nimport { TOKEN_PROGRAM_ADDRESS, WSOL_MINT } from '../ids';\nimport { wsolAccountFor } from '../raydium/venue';\n\n/** The wallet's WSOL account, and the instructions that put `lamports` of spendable WSOL in it. */\nexport async function fundWsol(\n owner: TransactionSigner,\n lamports: bigint,\n): Promise<{ account: Address; instructions: Instruction[] }> {\n if (lamports < 0n) throw new Error('lamports must not be negative');\n const account = await wsolAccountFor(owner.address);\n const instructions: Instruction[] = [\n getCreateAssociatedTokenIdempotentInstruction({\n payer: owner,\n ata: account,\n owner: owner.address,\n mint: WSOL_MINT,\n tokenProgram: TOKEN_PROGRAM_ADDRESS,\n }) as Instruction,\n ];\n if (lamports > 0n) {\n instructions.push(\n getTransferSolInstruction({\n source: owner,\n destination: account,\n amount: lamports,\n }) as Instruction,\n // Without this the token account holds the lamports but still reports a zero balance.\n getSyncNativeInstruction({ account }) as Instruction,\n );\n }\n return { account, instructions };\n}\n\n/** Close the WSOL account, sending every lamport in it back to the owner as SOL. */\nexport function unwrapWsol(owner: TransactionSigner, account: Address): Instruction {\n return getCloseAccountInstruction({\n account,\n destination: owner.address,\n owner,\n }) as Instruction;\n}\n","/**\n * Buying one pack.\n *\n * Four instructions around the Gabox one, because both venues settle in WSOL:\n *\n * 1. Create the purchaser's WSOL account, move `maxQuoteIn` lamports into it, `syncNative`.\n * 2. `buy_pack`, with the venue's buy accounts as `remainingAccounts`.\n * 3. Close the WSOL account. Whatever the buy did not spend comes back as SOL.\n *\n * Closing also unwraps any WSOL the wallet already held. See `tx/wsol.ts`.\n *\n * # The purchaser's coin account\n *\n * The program declares `user_tokens` as `init_if_needed`, so Anchor creates the account when it is\n * missing and the purchaser pays its rent. There is no idempotent create here on purpose: two paths\n * that both create the same account make the transaction longer for no gain, and the program's own\n * path is the one that has to work anyway.\n *\n * # The two caps\n *\n * `maxQuoteIn` is the buyer's slippage cap at the venue, in WSOL. `maxNativeDebit` is a separate cap\n * on the lamports the handler watches: the venue's account rent, which LaunchLab charges on a\n * coin's first trade, plus the VRF request fee. Gabox itself charges nothing.\n */\n\nimport type { Address, Instruction, TransactionSigner } from '@solana/kit';\n\nimport { fetchPoolInventory } from '../accounts';\nimport { BUY_PACK_COMPUTE_UNITS } from '../compute';\nimport { getBuyPackInstructionAsync } from '../generated/instructions/buyPack';\nimport { drawAddress } from '../pdas';\nimport { resolveVenue, type VenueKind } from '../raydium/venue';\nimport type { GaboxClient } from '../rpc';\nimport { buildMessage, withRemainingAccounts, type BuildOptions } from './message';\nimport { fundWsol, unwrapWsol } from './wsol';\n\nexport type BuyPackInput = {\n mint: Address;\n purchaser: TransactionSigner;\n /**\n * The venue slippage cap, in WSOL. This many lamports are wrapped before the buy, so it must\n * cover the real price. Anything left comes back as SOL.\n */\n maxQuoteIn: bigint;\n /** The floor on the top prize this pack may win. Refresh the offer if it fails. */\n minMaximum: bigint;\n /** Caps every lamport the handler sees: venue account rent and the VRF request. */\n maxNativeDebit: bigint;\n /** Force a venue instead of reading the LaunchLab pool's `status`. */\n venue?: VenueKind;\n /** Pin `pool.nextSeq` to make a rebuild fail rather than buy a second pack. */\n seq?: bigint;\n} & Partial<BuildOptions>;\n\nexport async function buyPack(client: GaboxClient, input: BuyPackInput) {\n if (input.maxQuoteIn <= 0n) throw new Error('maxQuoteIn must be positive');\n if (input.maxNativeDebit < 0n) throw new Error('maxNativeDebit must not be negative');\n\n const inventory = await fetchPoolInventory(client, input.mint);\n if (!inventory) throw new Error(`no Gabox pool for mint ${input.mint}`);\n const { pool, poolAddress } = inventory;\n const purchaser = input.purchaser.address;\n\n const venue = await resolveVenue(client, {\n mint: input.mint,\n user: purchaser,\n ...(input.venue ? { venue: input.venue } : {}),\n });\n const draw = await drawAddress(poolAddress, input.seq ?? pool.nextSeq);\n\n const buy = await getBuyPackInstructionAsync({\n purchaser: input.purchaser,\n pool: poolAddress,\n draw,\n mint: input.mint,\n quoteMint: pool.quoteMint,\n vault: pool.vault,\n venue: venue.program,\n maxQuoteIn: input.maxQuoteIn,\n minMaximum: input.minMaximum,\n maxNativeDebit: input.maxNativeDebit,\n });\n\n const wsol = await fundWsol(input.purchaser, input.maxQuoteIn);\n const instructions: Instruction[] = [\n ...wsol.instructions,\n withRemainingAccounts(buy as Instruction, venue.buyAccounts),\n unwrapWsol(input.purchaser, wsol.account),\n ];\n\n return await buildMessage(client, input.purchaser, instructions, {\n addressLookupTables: input.addressLookupTables,\n computeUnitLimit: input.computeUnitLimit ?? BUY_PACK_COMPUTE_UNITS,\n ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }),\n });\n}\n","/**\n * Creating a machine: one transaction, two signers.\n *\n * # Why it has to be one transaction\n *\n * `initialize_pool` reads the Instructions sysvar and refuses to run unless the same transaction\n * also carries a LaunchLab `initialize_v2` for the same mint, signed by the same creator, with the\n * pinned Gabox launch arguments. That is what makes \"one pool per coin\" true and stops anyone\n * wrapping an existing coin in a machine. The create must come **first**: the mint account has to\n * exist and deserialize before Anchor validates the pool accounts.\n *\n * # The instructions, in order\n *\n * 1. LaunchLab `initialize_v2`. The mint keypair signs; the creator pays.\n * 2. Create the creator's WSOL account, move `maxSeedQuoteIn` lamports into it, `syncNative`.\n * 3. `initialize_pool`, with the LaunchLab buy accounts as `remainingAccounts`.\n * 4. Close the WSOL account. Whatever the seed did not spend comes back as SOL.\n *\n * Both venues settle in WSOL, so step 2 is not optional. `initialize_pool` measures the creator's\n * WSOL balance before and after the seed buy, and the buy cannot spend lamports the account does\n * not hold.\n *\n * Closing in step 4 also unwraps any WSOL the creator already held. See `tx/wsol.ts`.\n *\n * # The seed\n *\n * The creator owns none of the coin yet — it does not exist until this transaction runs. So\n * `initialize_pool` buys the seed on the curve itself, into the creator's own coin account, and\n * moves it straight into the vault.\n *\n * The seed follows from the tier table. The program accepts any table that passes `math::validate`;\n * it does not enforce one table. A creator may pass their own `tiers`; the default is\n * `DEFAULT_TIERS`. The program buys a mandatory `seedTokens(PACK_TOKENS, tiers)` (see `math.ts`):\n * it makes a 3x top prize payable on the first pack, or pays the full top prize when the table's\n * top tier is below 3x. A table's top tier can be at most 20x; seed beyond what a 20x prize needs\n * stays in the vault as backup for the draws after a top-tier hit. A creator adds more on top with\n * `extraSeedTokens`; the program then buys `mandatory + extraSeedTokens` in the same seed trade.\n * The creator only signs a maximum cost for that buy.\n *\n * The seed buy moves the curve, so a bigger seed means a slightly higher starting pack price. The\n * curve only sells `LAUNCH_TOTAL_BASE_SELL` coins in total, so a seed above that cannot be bought;\n * `createMachine` and `seedCostEstimate` both check this before spending anything.\n *\n * # Two signers\n *\n * The mint keypair signs `initialize_v2` — LaunchLab takes it as a signer rather than deriving it —\n * and the creator signs everything and pays.\n */\n\nimport type { Instruction, TransactionSigner } from '@solana/kit';\n\nimport { CREATE_MACHINE_COMPUTE_UNITS } from '../compute';\nimport { getInitializePoolInstructionAsync } from '../generated/instructions/initializePool';\nimport { PACK_TOKENS, WSOL_MINT } from '../ids';\nimport { DEFAULT_TIERS, seedTokens, validatePack, validateTiers, type Tier } from '../math';\nimport { LAUNCH_TOTAL_BASE_SELL, raydiumIds } from '../raydium/ids';\nimport { getLaunchInstruction } from '../raydium/launch';\nimport { launchlabBuyAccounts } from '../raydium/accounts';\nimport { curveBuyExactOut } from '../raydium/curve';\nimport { fetchCurveSettings, newCurveReserves } from '../raydium/venue';\nimport {\n ata,\n creatorFeeVaultAddress,\n launchlabPoolAddress,\n launchlabVaultAddress,\n platformFeeVaultAddress,\n} from '../raydium/pdas';\nimport type { GaboxClient } from '../rpc';\nimport { buildMessage, withRemainingAccounts, type BuildOptions } from './message';\nimport { fundWsol, unwrapWsol } from './wsol';\n\nexport type CreateMachineInput = {\n /** Pays for everything and signs both instructions. Becomes `pool.creator`. */\n creator: TransactionSigner;\n /** A fresh keypair for the coin. Signs `initialize_v2` and is never needed again. */\n mintKeypair: TransactionSigner;\n /** At most 32 UTF-8 bytes. */\n name: string;\n /** At most 10 UTF-8 bytes. */\n symbol: string;\n /** The metadata URI. At most 200 UTF-8 bytes. */\n uri: string;\n /**\n * The prize table. Immutable once the pool exists. Must pass `validateTiers` and\n * `validatePack(PACK_TOKENS, tiers)`; the program checks both again on chain. Defaults to\n * `DEFAULT_TIERS`, the table the Gabox app uses.\n */\n tiers?: readonly Readonly<Tier>[];\n /**\n * Seed slippage cap in WSOL, for `mandatory + extraSeedTokens` together. This is also the number\n * of lamports wrapped into the creator's WSOL account before the buy, so it must cover the real\n * cost. Anything left over comes back as SOL when the account is closed.\n */\n maxSeedQuoteIn: bigint;\n /**\n * A separate cap on the lamports the seed buy itself spends. LaunchLab creates its platform and\n * creator fee vaults on a coin's first trade and charges that rent to the payer, which is the\n * only SOL the buy touches. It is not the price.\n */\n maxSeedNativeDebit: bigint;\n /**\n * Extra tokens to seed on top of the mandatory amount `seedTokens(PACK_TOKENS, tiers)` computes.\n * Defaults to `0n`. Must not be negative.\n */\n extraSeedTokens?: bigint;\n} & Partial<BuildOptions>;\n\n/**\n * Build the transaction message. Sign it with both `creator` and `mintKeypair`.\n *\n * Reads LaunchLab's global config and the Gabox platform config, because the seed price depends on\n * their fee rates. Nothing else needs the chain: the coin does not exist yet, so every other\n * account is a derivation.\n */\nexport async function createMachine(client: GaboxClient, input: CreateMachineInput) {\n const { creator, mintKeypair, name, symbol, uri, maxSeedQuoteIn, maxSeedNativeDebit } = input;\n\n // Snapshot caller input before validation and the first await. A caller can otherwise mutate a\n // nested tier while the config accounts are loading, changing the transaction after validation.\n const tiers = cloneTiers(input.tiers ?? DEFAULT_TIERS);\n validateTiers(tiers);\n validatePack(PACK_TOKENS, tiers);\n const extraSeedTokens = input.extraSeedTokens ?? 0n;\n if (extraSeedTokens < 0n) throw new Error('extraSeedTokens must not be negative');\n const mandatorySeed = seedTokens(PACK_TOKENS, tiers);\n const seed = mandatorySeed + extraSeedTokens;\n assertSeedFitsCurve(seed);\n if (seed > 0n && maxSeedQuoteIn <= 0n) {\n throw new Error('maxSeedQuoteIn must be positive when the jackpot needs a seed');\n }\n if (maxSeedQuoteIn < 0n) throw new Error('maxSeedQuoteIn must not be negative');\n if (maxSeedNativeDebit < 0n) throw new Error('maxSeedNativeDebit must not be negative');\n\n const ids = raydiumIds(client.cluster);\n const mint = mintKeypair.address;\n const quoteMint = WSOL_MINT;\n\n const create = await getLaunchInstruction({ mint: mintKeypair, creator, name, symbol, uri }, ids);\n\n // The curve does not exist yet, so `resolveVenue` cannot build this list. Every address it needs\n // is a derivation anyway, and the creator is the wallet signing right here.\n const poolState = await launchlabPoolAddress(ids.launchlab, mint, quoteMint);\n const venueAccounts = launchlabBuyAccounts({\n launchlab: ids.launchlab,\n launchlabAuthority: ids.launchlabAuthority,\n launchlabEventAuthority: ids.launchlabEventAuthority,\n globalConfig: ids.solGlobalConfig,\n platformConfig: ids.gaboxPlatform,\n poolState,\n mint,\n quoteMint,\n baseVault: await launchlabVaultAddress(ids.launchlab, poolState, mint),\n quoteVault: await launchlabVaultAddress(ids.launchlab, poolState, quoteMint),\n user: creator.address,\n userBaseToken: await ata(creator.address, mint),\n userQuoteToken: await ata(creator.address, quoteMint),\n platformFeeVault: await platformFeeVaultAddress(ids.launchlab, ids.gaboxPlatform, quoteMint),\n creatorFeeVault: await creatorFeeVaultAddress(ids.launchlab, creator.address, quoteMint),\n });\n\n const initialize = await getInitializePoolInstructionAsync({\n creator,\n mint,\n quoteMint,\n venue: ids.launchlab,\n tiers,\n maxSeedQuoteIn,\n maxSeedNativeDebit,\n extraSeedTokens,\n });\n\n const wsol = await fundWsol(creator, maxSeedQuoteIn);\n const instructions: Instruction[] = [\n create,\n ...wsol.instructions,\n withRemainingAccounts(initialize as Instruction, venueAccounts),\n unwrapWsol(creator, wsol.account),\n ];\n\n return await buildMessage(client, creator, instructions, {\n addressLookupTables: input.addressLookupTables,\n computeUnitLimit: input.computeUnitLimit ?? CREATE_MACHINE_COMPUTE_UNITS,\n ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }),\n });\n}\n\nexport type SeedCostEstimate = {\n tiers: readonly Tier[];\n /** The mandatory seed alone: `seedTokens(PACK_TOKENS, tiers)`. */\n seedTokens: bigint;\n /** `options.extraSeedTokens`, defaulted to `0n`. */\n extraSeedTokens: bigint;\n /** `seedTokens + extraSeedTokens`. What `createMachine` actually buys in the seed trade. */\n totalSeedTokens: bigint;\n /** Exact fresh-curve cost in lamports, Raydium's fees included. */\n quoteAmount: bigint;\n /** Always WSOL today. */\n quoteMint: typeof WSOL_MINT;\n};\n\n/**\n * What the seed for this table costs, fees included, and how many tokens it is.\n *\n * The coin does not exist yet, so the price comes from the starting reserves LaunchLab derives from\n * the pinned launch shape. Nothing trades on the curve before `initialize_pool` runs in the same\n * transaction, so this is exact up to a change in Raydium's fee rates between the read and the\n * send.\n *\n * Defaults to `DEFAULT_TIERS` and no extra seed. Throws if `tiers` fails\n * `validateTiers`/`validatePack`, if `extraSeedTokens` is negative, or if the total seed is bigger\n * than the curve sells.\n */\nexport async function seedCostEstimate(\n client: GaboxClient,\n tiers: readonly Readonly<Tier>[] = DEFAULT_TIERS,\n options: { extraSeedTokens?: bigint } = {},\n): Promise<SeedCostEstimate> {\n // Do not validate one mutable table and then quote another after an await. The result owns its\n // own mutable copy too, never a reference to DEFAULT_TIERS or the caller's array.\n const copiedTiers = cloneTiers(tiers);\n validateTiers(copiedTiers);\n validatePack(PACK_TOKENS, copiedTiers);\n const extraSeedTokens = options.extraSeedTokens ?? 0n;\n if (extraSeedTokens < 0n) throw new Error('extraSeedTokens must not be negative');\n const mandatorySeed = seedTokens(PACK_TOKENS, copiedTiers);\n const seed = mandatorySeed + extraSeedTokens;\n assertSeedFitsCurve(seed);\n\n const ids = raydiumIds(client.cluster);\n const settings = await fetchCurveSettings(client, ids);\n const quoteAmount =\n seed === 0n\n ? 0n\n : curveBuyExactOut(newCurveReserves(ids, settings.migrateFee), settings.rates, seed);\n\n return {\n tiers: copiedTiers,\n seedTokens: mandatorySeed,\n extraSeedTokens,\n totalSeedTokens: seed,\n quoteAmount,\n quoteMint: WSOL_MINT,\n };\n}\n\n/** A mutable table shape, owned by this call and safe to pass to Codama's builder. */\nfunction cloneTiers(tiers: readonly Readonly<Tier>[]): Tier[] {\n return tiers.map(({ multiplierBps, tickets }) => ({ multiplierBps, tickets }));\n}\n\n/**\n * The curve sells `LAUNCH_TOTAL_BASE_SELL` coins in total, so a seed above that cannot be bought at\n * any price. A buy for more than the curve has left is capped rather than refused, so it would look\n * cheap instead of failing. This throws before any transaction is built.\n */\nfunction assertSeedFitsCurve(seed: bigint): void {\n if (seed > LAUNCH_TOTAL_BASE_SELL) {\n throw new Error(\n `the seed (${seed} base units) is bigger than the whole curve sells ` +\n `(${LAUNCH_TOTAL_BASE_SELL}); this table's top tier cannot be seeded on a new coin`,\n );\n }\n}\n","/** Permissionless draw recovery: retry VRF or deliver the committed minimum after timeout. */\nimport type { Address, Instruction, TransactionSigner } from '@solana/kit';\nimport { fetchDraw, fetchPoolAt } from '../accounts';\nimport { getExpireDrawInstruction } from '../generated/instructions/expireDraw';\nimport { getRetryDrawInstruction } from '../generated/instructions/retryDraw';\nimport { RETRY_SLOTS, TIMEOUT_SLOTS } from '../ids';\nimport { associatedTokenAddress, vrfIdentityAddress } from '../pdas';\nimport type { GaboxClient } from '../rpc';\nimport { buildMessage, type BuildOptions } from './message';\nconst DRAW_COMPUTE_UNITS = 200_000;\nexport type RetryDrawInput = { payer: TransactionSigner; pool: Address; draw: Address; maxVrfDebit: bigint } & Partial<BuildOptions>;\nexport async function retryDraw(client: GaboxClient, input: RetryDrawInput) {\n const ix = await getRetryDrawInstruction({ payer: input.payer, pool: input.pool, draw: input.draw, identity: await vrfIdentityAddress(), maxVrfDebit: input.maxVrfDebit });\n return await buildMessage(client, input.payer, [ix as Instruction], { addressLookupTables: input.addressLookupTables, computeUnitLimit: input.computeUnitLimit ?? DRAW_COMPUTE_UNITS, ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }) });\n}\nexport type ExpireDrawInput = { payer: TransactionSigner; pool: Address; draw: Address } & Partial<BuildOptions>;\nexport async function expireDraw(client: GaboxClient, input: ExpireDrawInput) {\n const draw = await fetchDraw(client, input.draw); if (!draw || draw.pool !== input.pool) throw new Error('draw does not belong to pool or was already delivered');\n const pool = await fetchPoolAt(client, input.pool); if (!pool) throw new Error(`no pool at ${input.pool}`);\n const ix = getExpireDrawInstruction({ pool: input.pool, draw: input.draw, purchaser: draw.purchaser, mint: pool.mint, vault: pool.vault, userTokens: await associatedTokenAddress(draw.purchaser, pool.mint) });\n return await buildMessage(client, input.payer, [ix as Instruction], { addressLookupTables: input.addressLookupTables, computeUnitLimit: input.computeUnitLimit ?? DRAW_COMPUTE_UNITS, ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }) });\n}\nexport type DrawAvailability = { attempts: number; slotsUntilRetry: bigint; slotsUntilExpiry: bigint; canRetry: boolean; canExpire: boolean };\nexport async function drawAvailability(client: GaboxClient, address: Address): Promise<DrawAvailability | null> {\n const draw = await fetchDraw(client, address); if (!draw) return null;\n const now = BigInt(await client.rpc.getSlot({ commitment: 'confirmed' }).send());\n const retryAt = draw.lastAttemptSlot + RETRY_SLOTS; const expireAt = draw.requestSlot + TIMEOUT_SLOTS;\n const slotsUntilRetry = now >= retryAt ? 0n : retryAt - now; const slotsUntilExpiry = now >= expireAt ? 0n : expireAt - now;\n return { attempts: draw.attempts, slotsUntilRetry, slotsUntilExpiry, canRetry: draw.attempts < 3 && slotsUntilRetry === 0n && slotsUntilExpiry > 0n, canExpire: slotsUntilExpiry === 0n };\n}\n","/** Irrevocably transfer existing base tokens into a Gabox prize vault. */\nimport type { Address, Instruction, TransactionSigner } from '@solana/kit';\nimport { fetchPoolByMint } from '../accounts';\nimport { getFundPrizesInstruction } from '../generated/instructions/fundPrizes';\nimport { associatedTokenAddress, poolAddress } from '../pdas';\nimport type { GaboxClient } from '../rpc';\nimport { buildMessage, type BuildOptions } from './message';\nconst FUND_COMPUTE_UNITS = 200_000;\nexport type FundPrizesInput = { mint: Address; funder: TransactionSigner; amount: bigint; source?: Address } & Partial<BuildOptions>;\nexport async function fundPrizes(client: GaboxClient, input: FundPrizesInput) {\n if (input.amount <= 0n) throw new Error('amount must be positive');\n const pool = await fetchPoolByMint(client, input.mint); if (!pool) throw new Error(`no Gabox pool for mint ${input.mint}`);\n const ix = getFundPrizesInstruction({\n funder: input.funder, pool: await poolAddress(input.mint), mint: input.mint,\n source: input.source ?? await associatedTokenAddress(input.funder.address, input.mint),\n vault: pool.vault, amount: input.amount,\n });\n return await buildMessage(client, input.funder, [ix as Instruction], {\n addressLookupTables: input.addressLookupTables, computeUnitLimit: input.computeUnitLimit ?? FUND_COMPUTE_UNITS,\n ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }),\n });\n}\n","/**\n * Selling tokens through Gabox.\n *\n * The seller keeps the full venue proceeds: Gabox charges nothing on a sale. `minQuoteOutput` is the\n * venue's own floor, and the program checks it before it returns.\n *\n * Both venues pay into the seller's WSOL account, so this creates that account first and closes it\n * afterwards. The proceeds then land in the wallet as SOL. Closing also unwraps any WSOL the wallet\n * already held; see `tx/wsol.ts`.\n */\n\nimport type { Address, Instruction, TransactionSigner } from '@solana/kit';\n\nimport { fetchPoolByMint } from '../accounts';\nimport { REDEEM_COMPUTE_UNITS } from '../compute';\nimport { getSellTokensInstructionAsync } from '../generated/instructions/sellTokens';\nimport { poolAddress } from '../pdas';\nimport { resolveVenue, type VenueKind } from '../raydium/venue';\nimport type { GaboxClient } from '../rpc';\nimport { buildMessage, withRemainingAccounts, type BuildOptions } from './message';\nimport { fundWsol, unwrapWsol } from './wsol';\n\nexport type SellTokensInput = {\n mint: Address;\n seller: TransactionSigner;\n amount: bigint;\n /** The venue's own floor on the WSOL it pays out. Nothing else is taken out of the sale. */\n minQuoteOutput: bigint;\n /**\n * Caps the lamports the sale itself spends. A sale normally spends none, but LaunchLab charges\n * the payer for a fee vault it has to create on a coin's first trade.\n */\n maxNativeDebit: bigint;\n venue?: VenueKind;\n} & Partial<BuildOptions>;\n\nexport async function sellTokens(client: GaboxClient, input: SellTokensInput) {\n if (input.amount <= 0n || input.minQuoteOutput <= 0n) {\n throw new Error('amount and minQuoteOutput must be positive');\n }\n if (input.maxNativeDebit < 0n) throw new Error('maxNativeDebit must not be negative');\n\n const pool = await fetchPoolByMint(client, input.mint);\n if (!pool) throw new Error(`no Gabox pool for mint ${input.mint}`);\n\n const venue = await resolveVenue(client, {\n mint: input.mint,\n user: input.seller.address,\n ...(input.venue ? { venue: input.venue } : {}),\n });\n\n const sell = await getSellTokensInstructionAsync({\n seller: input.seller,\n pool: await poolAddress(input.mint),\n mint: input.mint,\n quoteMint: pool.quoteMint,\n venue: venue.program,\n amount: input.amount,\n minQuoteOutput: input.minQuoteOutput,\n maxNativeDebit: input.maxNativeDebit,\n });\n\n // A sale needs the account to exist, not to hold anything. The close at the end is what turns the\n // proceeds into SOL.\n const wsol = await fundWsol(input.seller, 0n);\n const instructions: Instruction[] = [\n ...wsol.instructions,\n withRemainingAccounts(sell as Instruction, venue.sellAccounts),\n unwrapWsol(input.seller, wsol.account),\n ];\n\n return await buildMessage(client, input.seller, instructions, {\n addressLookupTables: input.addressLookupTables,\n computeUnitLimit: input.computeUnitLimit ?? REDEEM_COMPUTE_UNITS,\n ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }),\n });\n}\n","/**\n * The four oracle accounts.\n *\n * `buy_pack` and `retry_draw` both carry an `Oracle` account group. Anchor flattens it into four\n * slots, and the generated client takes them as `identity`, `queue`, `program` and `slotHashes`.\n * Three of the four are pinned by an `address` constraint, so the only one a client computes is the\n * identity PDA.\n *\n * # Why the queue is not a choice\n *\n * `vrf.rs` pins MagicBlock's default queue with `address = QUEUE` and `owner = ID`. A pool creator\n * therefore cannot point their pool's draws at an oracle they run. That is the reason the address\n * is a constant here rather than a parameter: making it configurable in the client would suggest a\n * freedom the program does not give.\n */\n\nimport type { Address } from '@solana/kit';\n\nimport { SLOT_HASHES_SYSVAR, VRF_DEFAULT_QUEUE, VRF_PROGRAM_ADDRESS } from './ids';\nimport { vrfIdentityAddress } from './pdas';\n\n/** The four accounts, named as the generated client names them. */\nexport type OracleAccounts = {\n /** `[\"identity\"]` under gabox. The PDA gabox signs the randomness request with. */\n identity: Address;\n /** MagicBlock's default queue. Writable. */\n queue: Address;\n /** The VRF program itself. */\n program: Address;\n /** The slot-hashes sysvar, which seeds the request. */\n slotHashes: Address;\n};\n\n/**\n * Build the group. Nothing here reads the chain, so it is safe to call on every render.\n *\n * The generated instruction builders default `queue`, `program` and `slotHashes` on their own, so\n * passing this whole object is belt and braces. It is worth having anyway: a caller can show the\n * four accounts a draw request will touch before asking for a signature.\n */\nexport async function oracleAccounts(): Promise<OracleAccounts> {\n return {\n identity: await vrfIdentityAddress(),\n queue: VRF_DEFAULT_QUEUE,\n program: VRF_PROGRAM_ADDRESS,\n slotHashes: SLOT_HASHES_SYSVAR,\n };\n}\n"],"mappings":"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8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,6CAA6C;CACrD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,6CAA6C;CACrD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,6CAA6C;CACrD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAA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"}
|