@gabox-labs/sdk 0.7.0 → 0.7.1
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 +20 -0
- package/README.md +15 -10
- package/dist/{index-C4at2cZ_.d.ts → index-CA0m7AKk.d.ts} +4 -3
- package/dist/index.d.ts +23 -15
- package/dist/index.js +36 -37
- package/dist/index.js.map +1 -1
- package/dist/raydium/index.d.ts +1 -1
- package/package.json +1 -1
- package/skills/gabox-sdk/SKILL.md +4 -2
- package/skills/gabox-sdk/references/api.md +11 -7
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,26 @@
|
|
|
3
3
|
All notable changes to `@gabox-labs/sdk`. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
4
4
|
and the project uses [Semantic Versioning](https://semver.org/) with the `0.x` rule from `CONTRIBUTING.md`.
|
|
5
5
|
|
|
6
|
+
## [0.7.1] - 2026-09-18
|
|
7
|
+
|
|
8
|
+
A product correction. Paying in SOL is for buyers, not for creators.
|
|
9
|
+
|
|
10
|
+
### Removed
|
|
11
|
+
|
|
12
|
+
- The seed-in-SOL option on `createMachine`: the creator pays the seed in the quote token. The
|
|
13
|
+
`payWith` input is gone, and with it the swap leg, the route safety check and the extra compute
|
|
14
|
+
units that creation used to ask for. A machine quoted in USDC now needs its creator to hold at
|
|
15
|
+
least `maxSeedQuoteIn` of USDC before the transaction runs, and `seedCostEstimate` says how much
|
|
16
|
+
that is.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- `SeedCostEstimate.solAmount` stays, and it is a display. It is what the seed is worth in SOL
|
|
21
|
+
through the route provider, not an amount any instruction spends. The create page shows it beside
|
|
22
|
+
the quote-token cost.
|
|
23
|
+
- `buyPack` keeps `payWith` and `sellTokens` keeps `receive`, both unchanged. Only a buyer arrives
|
|
24
|
+
holding SOL alone, so only a pack buy and a sale swap.
|
|
25
|
+
|
|
6
26
|
## [0.7.0] - 2026-09-18
|
|
7
27
|
|
|
8
28
|
Any quote token Raydium enabled, a price shown in SOL, and payment in SOL through a swap that runs
|
package/README.md
CHANGED
|
@@ -46,6 +46,9 @@ Buyers pay in SOL whatever the pool is priced in.
|
|
|
46
46
|
splits the two, because a swap that settled on its own would leave the buyer holding a token they
|
|
47
47
|
never asked for.
|
|
48
48
|
|
|
49
|
+
This is for packs and sales only. **A machine's seed is always paid by its creator, in the
|
|
50
|
+
machine's own quote token**, so `createMachine` never swaps. See "Create a machine" below.
|
|
51
|
+
|
|
49
52
|
```ts
|
|
50
53
|
import { createClient, raydiumCpmmRoute } from '@gabox-labs/sdk';
|
|
51
54
|
|
|
@@ -56,9 +59,8 @@ const client = createClient({
|
|
|
56
59
|
});
|
|
57
60
|
```
|
|
58
61
|
|
|
59
|
-
`payWith: 'quote'` on `buyPack`
|
|
60
|
-
|
|
61
|
-
token is SOL.
|
|
62
|
+
`payWith: 'quote'` on `buyPack` skips the swap and spends the token the wallet already holds.
|
|
63
|
+
`receive: 'quote'` does the same for a sale. A WSOL pool ignores both: its quote token is SOL.
|
|
62
64
|
|
|
63
65
|
The swap has to fit in the same 1,232-byte transaction as the buy. When it does not, the builder
|
|
64
66
|
fails with a clear error rather than splitting the work; supply more address lookup tables, or pay
|
|
@@ -96,9 +98,9 @@ Everything else is fixed: 6 decimals, 1,000,000,000 coins, 793,100,000 of them s
|
|
|
96
98
|
graduate into a CPMM pool, no vesting, the CPMM creator fee paid in the quote token. Metaplex limits
|
|
97
99
|
the three strings to 32, 10 and 200 UTF-8 bytes.
|
|
98
100
|
|
|
99
|
-
`maxSeedQuoteIn` is
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
`maxSeedQuoteIn` is the slippage cap on the seed buy, in the quote token, and the creator must
|
|
102
|
+
already hold that much. `maxSeedNativeDebit` is separate and small: it caps the lamports of rent
|
|
103
|
+
LaunchLab charges for the fee vaults it creates on a coin's first trade.
|
|
102
104
|
|
|
103
105
|
### Another quote asset
|
|
104
106
|
|
|
@@ -112,21 +114,24 @@ const message = await createMachine(client, {
|
|
|
112
114
|
uri: 'https://example.com/metadata.json',
|
|
113
115
|
quote: { mint: usdc },
|
|
114
116
|
raise, // total_quote_fund_raising, in USDC base units
|
|
115
|
-
payWith: 'sol', // the default: the seed is bought with a swap
|
|
116
117
|
maxSeedQuoteIn: (estimate.quoteAmount * 110n) / 100n,
|
|
117
118
|
maxSeedNativeDebit: 100_000_000n,
|
|
118
119
|
});
|
|
119
120
|
```
|
|
120
121
|
|
|
122
|
+
**The creator pays the seed, in the machine's own quote token.** There is no swap here: a machine
|
|
123
|
+
quoted in USDC needs the creator to hold at least `maxSeedQuoteIn` of USDC before this transaction
|
|
124
|
+
runs. Only a buyer arrives holding SOL alone, so only `buyPack` and `sellTokens` swap.
|
|
125
|
+
|
|
121
126
|
`raise` is how much the curve must take in before the coin graduates, in the quote's own base units.
|
|
122
127
|
A WSOL pool has it pinned by the program — 85 SOL on mainnet, 3 SOL on devnet — so leave it out
|
|
123
128
|
there. Any other quote has no default, because the same number means a different amount in every
|
|
124
129
|
token. LaunchLab refuses a raise below `min_quote_fund_raising` in that quote's config, and
|
|
125
130
|
`createMachine` checks the same thing before it builds anything.
|
|
126
131
|
|
|
127
|
-
`seedCostEstimate` reports `quoteAmount` in the quote token
|
|
128
|
-
`raise` it would use
|
|
129
|
-
`null` when nothing can price it.
|
|
132
|
+
`seedCostEstimate` reports `quoteAmount` in the quote token — what the creator actually pays —
|
|
133
|
+
plus `quoteDecimals`, `quoteSymbol` and the `raise` it would use. `solAmount` is what that cost is
|
|
134
|
+
worth in lamports through the route provider, for a display, or `null` when nothing can price it.
|
|
130
135
|
|
|
131
136
|
### The seed
|
|
132
137
|
|
|
@@ -68,8 +68,9 @@ type ClientConfig = {
|
|
|
68
68
|
*
|
|
69
69
|
* Mainnet defaults to Jupiter, which is where the liquidity is. Devnet and localnet default to
|
|
70
70
|
* none, because Jupiter does not serve them: pass `raydiumCpmmRoute(pool)` with a CPMM pool that
|
|
71
|
-
* holds the SOL/quote pair. `null` disables the swap leg, and `payWith: 'sol'` then
|
|
72
|
-
* pool quoted in anything but WSOL.
|
|
71
|
+
* holds the SOL/quote pair. `null` disables the swap leg, and `buyPack`'s `payWith: 'sol'` then
|
|
72
|
+
* fails on a pool quoted in anything but WSOL. Creating a machine never needs it: the creator
|
|
73
|
+
* pays the seed in the machine's own quote token.
|
|
73
74
|
*/
|
|
74
75
|
route?: RouteProvider | null;
|
|
75
76
|
};
|
|
@@ -1181,4 +1182,4 @@ declare namespace index_d_exports {
|
|
|
1181
1182
|
}
|
|
1182
1183
|
//#endregion
|
|
1183
1184
|
export { QuoteBinding as $, assertClusterUrl as $n, CONSTANT_CURVE_TAG as $t, ClaimCreatorFeeInput as A, LAUNCHLAB_SELL_EXACT_IN as An, totalCurveFeeRate as At, cpmmBuyAccounts as B, TOKEN_2022_PROGRAM_ADDRESS as Bn, LaunchlabGlobalConfig as Bt, launchlabPlatformConfig as C, LAUNCHLAB_BUY_EXACT_IN as Cn, cpmmSwapBaseOutput as Ct, platformFeeVaultAddress as D, LAUNCHLAB_INITIALIZE as Dn, initialCurve as Dt, metadataAddress as E, LAUNCHLAB_GLOBAL_CONFIG_DISCRIMINATOR as En, curveSellExactIn as Et, fetchCreatorFees as F, RAYDIUM_DEVNET_IDS as Fn, CpmmAmmConfig as Ft, order as G, CLUSTER_ENDPOINTS as Gn, decodeLaunchlabGlobalConfig as Gt, launchlabBuyAccounts as H, VenueAccountSpec as Hn, LaunchlabPoolState as Ht, getClaimCreatorFeeInstructions as I, RAYDIUM_MAINNET_IDS as In, CpmmPoolState as It, buildMessage as J, DEVNET_HTTP as Jn, metaplexSymbol as Jt, BuildOptions as K, ClientConfig as Kn, decodeLaunchlabPlatformConfig as Kt, getCollectCreatorFeeInstructions as L, RENT_SYSVAR_ADDRESS as Ln, LAUNCHLAB_GLOBAL_CONFIG_HEAD_SIZE as Lt, CreatorFees as M, LAUNCH_TOTAL_BASE_SELL as Mn, CPMM_POOL_OFFSETS as Mt, claimCreatorFee as N, METAPLEX_PROGRAM_ADDRESS as Nn, CPMM_POOL_STATE_HEAD_SIZE as Nt, LaunchInput as O, LAUNCHLAB_PLATFORM_CONFIG_DISCRIMINATOR as On, preFeeAmount as Ot, collectCreatorFee as P, PLATFORM_ADMIN as Pn, CPMM_POOL_STATE_SIZE as Pt, MigratedCpmmPool as Q, GaboxRpcSubscriptions as Qn, tokenAccountOwnerAndMint as Qt, CpmmTradeAccountsInput as R, RaydiumClusterIds as Rn, LAUNCHLAB_PLATFORM_CONFIG_HEAD_SIZE as Rt, launchlabGlobalConfig as S, CPMM_SWAP_BASE_OUTPUT as Sn, cpmmSwapBaseInput as St, launchlabVaultAddress as T, LAUNCHLAB_CLAIM_CREATOR_FEE as Tn, curveBuyExactOut as Tt, launchlabBuyExactInAccounts as U, VenueInstructionAbi as Un, decodeCpmmAmmConfig as Ut, cpmmSellAccounts as V, TOKEN_PROGRAM_ADDRESS as Vn, LaunchlabPlatformConfig as Vt, launchlabSellAccounts as W, WSOL_MINT as Wn, decodeCpmmPool as Wt, CurveSettings as X, GaboxClient as Xn, token2022Symbol as Xt, withRemainingAccounts as Y, DEVNET_WS as Yn, mintDecimals as Yt, FindCpmmPoolOptions as Z, GaboxRpc as Zn, tokenAccountAmount as Zt, cpmmPoolAddress as _, ASSOCIATED_TOKEN_PROGRAM_ADDRESS as _n, CurveFeeRates as _t, decodeBase64 as a, LAUNCHLAB_STATUS_TRADE as an, RouteMode as ar, curveQuote as at, launchlabAuthority as b, CPMM_POOL_STATE_DISCRIMINATOR as bn, ceilDiv as bt, QuoteConfig as c, METADATA_SEED as cn, findCpmmPool as ct, fetchQuoteConfig as d, RAYDIUM_IDS as dn, quoteAccountFor as dt, CPMM_SEEDS as en, clusterNamedBy as er, ResolveVenueOptions as et, fetchQuoteDisplay as f, RaydiumIds as fn, resolveVenue as ft, cpmmCreatorFeeShare as g, sortedMints as gn, CpmmSwapSides as gt, cpmmAuthority as h, raydiumIds as hn, CpmmFeeRates as ht, MaybeAccount$1 as i, LAUNCHLAB_STATUS_MIGRATE as in, Route as ir, creatorFeeOnInput as it, CollectCreatorFeeInput as j, LAUNCH_SUPPLY as jn, CPMM_AMM_CONFIG_HEAD_SIZE as jt, getLaunchInstruction as k, LAUNCHLAB_POOL_STATE_DISCRIMINATOR as kn, remainingBase as kt, QuoteDisplay as l, MIGRATE_TO_CPMM as ln, newCurveBuyCost as lt, ata as m, compareAddresses as mn, wsolAccountFor as mt, CurveBuyExactInInput as n, LAUNCHLAB_SEEDS as nn, defaultRoute as nr, VenueKind as nt, readAccounts as o, LAUNCH_DECIMALS as on, RouteProvider as or, fetchCurveSettings as ot, isQuoteSupported as p, SHARE_FEE_RATE as pn, sellQuote as pt, GaboxTransactionMessage as q, Cluster as qn, decodeLaunchlabPool as qt, getCurveBuyExactInInstruction as r, LAUNCHLAB_STATUS_FUND as rn, websocketUrlFor as rr, cpmmPoolMatches as rt, QuoteAsset as s, METADATA_LIMITS as sn, fetchQuoteBinding as st, index_d_exports as t, CREATOR_FEE_ON_QUOTE as tn, createClient as tr, ResolvedVenue as tt, fetchQuoteAsset as u, RATE_DENOMINATOR as un, newCurveReserves as ut, creatorFeeVaultAddress as v, CPMM_AMM_CONFIG_DISCRIMINATOR as vn, CurveReserves as vt, launchlabPoolAddress as w, LAUNCHLAB_BUY_EXACT_OUT as wn, curveBuyExactIn as wt, launchlabEventAuthority as x, CPMM_SWAP_BASE_INPUT as xn, ceilDivRate as xt, creatorFeeVaultAuthority as y, CPMM_COLLECT_CREATOR_FEE as yn, LaunchParams as yt, LaunchlabTradeAccountsInput as z, SYSTEM_PROGRAM_ADDRESS as zn, LAUNCHLAB_POOL_STATE_HEAD_SIZE as zt };
|
|
1184
|
-
//# sourceMappingURL=index-
|
|
1185
|
+
//# sourceMappingURL=index-CA0m7AKk.d.ts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DRAW_DISCRIMINATOR, Draw, DrawResolvedEvent, POOL_DISCRIMINATOR, PackBoughtEvent, Pool, PoolCreatedEvent, PrizesFundedEvent, RandomnessRetriedEvent, TokensSoldEvent, WALLET_ACTIVITY_DISCRIMINATOR, WalletActivity, decodeDraw, decodePool, decodeWalletActivity, findActivityPda, findDrawPda, findIdentityPda, findPoolPda, t as index_d_exports } from "./generated/index.js";
|
|
2
|
-
import { $n as assertClusterUrl, Gn as CLUSTER_ENDPOINTS, J as buildMessage, Jn as DEVNET_HTTP, K as BuildOptions, Kn as ClientConfig, Nn as METAPLEX_PROGRAM_ADDRESS, Pn as PLATFORM_ADMIN, Qn as GaboxRpcSubscriptions, Vn as TOKEN_PROGRAM_ADDRESS, Wn as WSOL_MINT, Xn as GaboxClient, Y as withRemainingAccounts, Yn as DEVNET_WS, Zn as GaboxRpc, _n as ASSOCIATED_TOKEN_PROGRAM_ADDRESS, ar as RouteMode, er as clusterNamedBy, ir as Route, nr as defaultRoute, nt as VenueKind, on as LAUNCH_DECIMALS, or as RouteProvider, q as GaboxTransactionMessage, qn as Cluster, rr as websocketUrlFor, t as index_d_exports$1, tr as createClient, tt as ResolvedVenue, zn as SYSTEM_PROGRAM_ADDRESS } from "./index-
|
|
2
|
+
import { $n as assertClusterUrl, Gn as CLUSTER_ENDPOINTS, J as buildMessage, Jn as DEVNET_HTTP, K as BuildOptions, Kn as ClientConfig, Nn as METAPLEX_PROGRAM_ADDRESS, Pn as PLATFORM_ADMIN, Qn as GaboxRpcSubscriptions, Vn as TOKEN_PROGRAM_ADDRESS, Wn as WSOL_MINT, Xn as GaboxClient, Y as withRemainingAccounts, Yn as DEVNET_WS, Zn as GaboxRpc, _n as ASSOCIATED_TOKEN_PROGRAM_ADDRESS, ar as RouteMode, er as clusterNamedBy, ir as Route, nr as defaultRoute, nt as VenueKind, on as LAUNCH_DECIMALS, or as RouteProvider, q as GaboxTransactionMessage, qn as Cluster, rr as websocketUrlFor, t as index_d_exports$1, tr as createClient, tt as ResolvedVenue, zn as SYSTEM_PROGRAM_ADDRESS } from "./index-CA0m7AKk.js";
|
|
3
3
|
import { Address, AddressesByLookupTableAddress, Instruction, InstructionWithData, ProgramDerivedAddress, ReadonlyUint8Array, TransactionSigner } from "@solana/kit";
|
|
4
4
|
//#region src/math.d.ts
|
|
5
5
|
/**
|
|
@@ -594,6 +594,17 @@ export type QuoteLeg = {
|
|
|
594
594
|
export type GaboxAccounts = readonly Address[];
|
|
595
595
|
/** Create the wallet's quote account if it is missing. Idempotent, so a second create is free. */
|
|
596
596
|
export declare function createQuoteAccount(owner: TransactionSigner, venue: Pick<ResolvedVenue, 'quoteMint' | 'quoteTokenProgram' | 'userQuoteToken'>): Instruction;
|
|
597
|
+
/**
|
|
598
|
+
* The leg for a wallet that already holds what it is about to spend. No swap.
|
|
599
|
+
*
|
|
600
|
+
* A WSOL pool is the one case where "already holds it" means lamports, so those are wrapped and the
|
|
601
|
+
* account is closed again afterwards. Any other quote only needs its account to exist; closing it
|
|
602
|
+
* would throw away a real balance.
|
|
603
|
+
*
|
|
604
|
+
* `createMachine` uses this and nothing else: the seed is always the creator's own money, in the
|
|
605
|
+
* machine's quote token.
|
|
606
|
+
*/
|
|
607
|
+
export declare function quoteLegFromWallet(venue: Pick<ResolvedVenue, 'quoteMint' | 'quoteTokenProgram' | 'userQuoteToken'>, payer: TransactionSigner, maxQuoteIn: bigint): Promise<QuoteLeg>;
|
|
597
608
|
/**
|
|
598
609
|
* The leg that puts `maxQuoteIn` of the quote token in the buyer's quote account.
|
|
599
610
|
*
|
|
@@ -698,15 +709,9 @@ export type CreateMachineInput = {
|
|
|
698
709
|
*/
|
|
699
710
|
raise?: bigint;
|
|
700
711
|
/**
|
|
701
|
-
*
|
|
702
|
-
*
|
|
703
|
-
|
|
704
|
-
payWith?: PayWith;
|
|
705
|
-
/**
|
|
706
|
-
* Seed slippage cap in the quote token, for `mandatory + extraSeedTokens` together. The
|
|
707
|
-
* transaction puts this much of the quote token in the creator's quote account before the buy, so
|
|
708
|
-
* it must cover the real cost. Anything left over stays there, or comes back as SOL on a WSOL
|
|
709
|
-
* pool.
|
|
712
|
+
* Seed slippage cap in the quote token, for `mandatory + extraSeedTokens` together. The creator
|
|
713
|
+
* must already hold this much of the quote token, so it has to cover the real cost. Anything left
|
|
714
|
+
* over stays in their quote account, or comes back as SOL on a WSOL pool.
|
|
710
715
|
*/
|
|
711
716
|
maxSeedQuoteIn: bigint;
|
|
712
717
|
/**
|
|
@@ -747,8 +752,11 @@ export type SeedCostEstimate = {
|
|
|
747
752
|
/** `total_quote_fund_raising` the launch would use, in the quote's base units. */
|
|
748
753
|
raise: bigint;
|
|
749
754
|
/**
|
|
750
|
-
* What `quoteAmount`
|
|
751
|
-
* no provider or no route. Equal to `quoteAmount` on a WSOL
|
|
755
|
+
* What `quoteAmount` is worth in SOL through the client's route provider, or `null` when there is
|
|
756
|
+
* no provider or no route. Equal to `quoteAmount` on a WSOL machine.
|
|
757
|
+
*
|
|
758
|
+
* A display only. The creator pays the seed in the quote token, not in SOL, so this says what
|
|
759
|
+
* that costs them in familiar money; it is not an amount any instruction spends.
|
|
752
760
|
*/
|
|
753
761
|
solAmount: bigint | null;
|
|
754
762
|
};
|
|
@@ -760,9 +768,9 @@ export type SeedCostEstimate = {
|
|
|
760
768
|
* same transaction, so this is exact up to a change in Raydium's fee rates between the read and the
|
|
761
769
|
* send.
|
|
762
770
|
*
|
|
763
|
-
* `solAmount` is
|
|
764
|
-
*
|
|
765
|
-
* caller passes `raydiumCpmmRoute(pool)`.
|
|
771
|
+
* `solAmount` is what that cost is worth in SOL, priced through the client's route provider. It is
|
|
772
|
+
* a display: the creator pays in the quote token. It is `null` when the client has no provider, or
|
|
773
|
+
* when no route exists: a devnet client has none unless the caller passes `raydiumCpmmRoute(pool)`.
|
|
766
774
|
*
|
|
767
775
|
* Defaults to `DEFAULT_TIERS`, wrapped SOL and no extra seed. Throws if `tiers` fails
|
|
768
776
|
* `validateTiers`/`validatePack`, if `extraSeedTokens` is negative, if the total seed is bigger
|
package/dist/index.js
CHANGED
|
@@ -1060,6 +1060,9 @@ function unwrapWsol(owner, account) {
|
|
|
1060
1060
|
* transaction, before `buy_pack`. A sale does the reverse afterwards. `routeQuoteIn` and
|
|
1061
1061
|
* `routeQuoteOut` build those, and `assertRouteIsSafe` checks the result before it is used.
|
|
1062
1062
|
*
|
|
1063
|
+
* The third shape belongs to packs only. A machine's seed is always paid by its creator, in the
|
|
1064
|
+
* machine's own quote token, so `createMachine` uses `quoteLegFromWallet` and never swaps.
|
|
1065
|
+
*
|
|
1063
1066
|
* Nothing here ever splits the work across two transactions. A swap that settles separately would
|
|
1064
1067
|
* leave the wallet holding a token it never asked for whenever the second half failed.
|
|
1065
1068
|
*/
|
|
@@ -1074,13 +1077,16 @@ function createQuoteAccount(owner, venue) {
|
|
|
1074
1077
|
});
|
|
1075
1078
|
}
|
|
1076
1079
|
/**
|
|
1077
|
-
* The leg
|
|
1080
|
+
* The leg for a wallet that already holds what it is about to spend. No swap.
|
|
1078
1081
|
*
|
|
1079
|
-
*
|
|
1080
|
-
*
|
|
1082
|
+
* A WSOL pool is the one case where "already holds it" means lamports, so those are wrapped and the
|
|
1083
|
+
* account is closed again afterwards. Any other quote only needs its account to exist; closing it
|
|
1084
|
+
* would throw away a real balance.
|
|
1085
|
+
*
|
|
1086
|
+
* `createMachine` uses this and nothing else: the seed is always the creator's own money, in the
|
|
1087
|
+
* machine's quote token.
|
|
1081
1088
|
*/
|
|
1082
|
-
async function
|
|
1083
|
-
const { venue, payer, maxQuoteIn, payWith } = input;
|
|
1089
|
+
async function quoteLegFromWallet(venue, payer, maxQuoteIn) {
|
|
1084
1090
|
if (venue.quoteMint === "So11111111111111111111111111111111111111112") {
|
|
1085
1091
|
const wsol = await fundWsol(payer, maxQuoteIn);
|
|
1086
1092
|
return {
|
|
@@ -1092,7 +1098,7 @@ async function quoteLegIn(client, input) {
|
|
|
1092
1098
|
computeUnits: 0
|
|
1093
1099
|
};
|
|
1094
1100
|
}
|
|
1095
|
-
|
|
1101
|
+
return {
|
|
1096
1102
|
before: [createQuoteAccount(payer, venue)],
|
|
1097
1103
|
after: [],
|
|
1098
1104
|
lookupTables: {},
|
|
@@ -1100,6 +1106,16 @@ async function quoteLegIn(client, input) {
|
|
|
1100
1106
|
solAmount: null,
|
|
1101
1107
|
computeUnits: 0
|
|
1102
1108
|
};
|
|
1109
|
+
}
|
|
1110
|
+
/**
|
|
1111
|
+
* The leg that puts `maxQuoteIn` of the quote token in the buyer's quote account.
|
|
1112
|
+
*
|
|
1113
|
+
* `payWith` decides where it comes from. On a WSOL pool the choice makes no difference: the quote
|
|
1114
|
+
* token is SOL either way, so the builder wraps it.
|
|
1115
|
+
*/
|
|
1116
|
+
async function quoteLegIn(client, input) {
|
|
1117
|
+
const { venue, payer, maxQuoteIn, payWith } = input;
|
|
1118
|
+
if (venue.quoteMint === "So11111111111111111111111111111111111111112" || payWith === "quote") return await quoteLegFromWallet(venue, payer, maxQuoteIn);
|
|
1103
1119
|
const route = await routeQuoteIn(client, providerOf(client, venue.quoteMint), {
|
|
1104
1120
|
quoteMint: venue.quoteMint,
|
|
1105
1121
|
amount: maxQuoteIn,
|
|
@@ -1325,39 +1341,22 @@ async function createMachine(client, input) {
|
|
|
1325
1341
|
maxSeedNativeDebit,
|
|
1326
1342
|
extraSeedTokens
|
|
1327
1343
|
});
|
|
1328
|
-
const leg = await
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
},
|
|
1334
|
-
payer: creator,
|
|
1335
|
-
maxQuoteIn: maxSeedQuoteIn,
|
|
1336
|
-
payWith: seed === 0n ? "quote" : input.payWith ?? "sol",
|
|
1337
|
-
gaboxAccounts: [
|
|
1338
|
-
await poolAddress(mint),
|
|
1339
|
-
await vaultAddress(mint),
|
|
1340
|
-
await ata(creator.address, mint)
|
|
1341
|
-
]
|
|
1342
|
-
});
|
|
1344
|
+
const leg = await quoteLegFromWallet({
|
|
1345
|
+
quoteMint: quote.mint,
|
|
1346
|
+
quoteTokenProgram: quote.tokenProgram,
|
|
1347
|
+
userQuoteToken
|
|
1348
|
+
}, creator, maxSeedQuoteIn);
|
|
1343
1349
|
const instructions = [
|
|
1344
1350
|
create,
|
|
1345
1351
|
...leg.before,
|
|
1346
1352
|
withRemainingAccounts(initialize, venueAccounts),
|
|
1347
1353
|
...leg.after
|
|
1348
1354
|
];
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
},
|
|
1355
|
-
computeUnitLimit: input.computeUnitLimit ?? computeUnitsWithRoute(35e4, leg),
|
|
1356
|
-
...input.computeUnitPrice === void 0 ? {} : { computeUnitPrice: input.computeUnitPrice }
|
|
1357
|
-
});
|
|
1358
|
-
} catch (cause) {
|
|
1359
|
-
throw routeSizeHint(cause, leg);
|
|
1360
|
-
}
|
|
1355
|
+
return await buildMessage(client, creator, instructions, {
|
|
1356
|
+
addressLookupTables: input.addressLookupTables ?? client.addressLookupTables,
|
|
1357
|
+
computeUnitLimit: input.computeUnitLimit ?? 35e4,
|
|
1358
|
+
...input.computeUnitPrice === void 0 ? {} : { computeUnitPrice: input.computeUnitPrice }
|
|
1359
|
+
});
|
|
1361
1360
|
}
|
|
1362
1361
|
/**
|
|
1363
1362
|
* What the seed for this table costs, fees included, and how many tokens it is.
|
|
@@ -1367,9 +1366,9 @@ async function createMachine(client, input) {
|
|
|
1367
1366
|
* same transaction, so this is exact up to a change in Raydium's fee rates between the read and the
|
|
1368
1367
|
* send.
|
|
1369
1368
|
*
|
|
1370
|
-
* `solAmount` is
|
|
1371
|
-
*
|
|
1372
|
-
* caller passes `raydiumCpmmRoute(pool)`.
|
|
1369
|
+
* `solAmount` is what that cost is worth in SOL, priced through the client's route provider. It is
|
|
1370
|
+
* a display: the creator pays in the quote token. It is `null` when the client has no provider, or
|
|
1371
|
+
* when no route exists: a devnet client has none unless the caller passes `raydiumCpmmRoute(pool)`.
|
|
1373
1372
|
*
|
|
1374
1373
|
* Defaults to `DEFAULT_TIERS`, wrapped SOL and no extra seed. Throws if `tiers` fails
|
|
1375
1374
|
* `validateTiers`/`validatePack`, if `extraSeedTokens` is negative, if the total seed is bigger
|
|
@@ -1582,6 +1581,6 @@ async function oracleAccounts() {
|
|
|
1582
1581
|
};
|
|
1583
1582
|
}
|
|
1584
1583
|
//#endregion
|
|
1585
|
-
export { ASSOCIATED_TOKEN_PROGRAM_ADDRESS, BPS, BUY_PACK_COMPUTE_UNITS, CLAIM_COMPUTE_UNITS, CLUSTER_ENDPOINTS, COMPUTE_BUDGET_PROGRAM_ADDRESS, CPMM_ROUTE_COMPUTE_UNITS, CPMM_ROUTE_SLIPPAGE_BPS, CREATE_MACHINE_COMPUTE_UNITS, DEFAULT_COMPUTE_UNIT_LIMIT, DEFAULT_TIERS, DEVNET_ADDRESS_LOOKUP_TABLES, DEVNET_HTTP, DEVNET_LOOKUP_TABLE_ADDRESS, DEVNET_LOOKUP_TABLE_ADDRESSES, DEVNET_WS, DRAW_DISCRIMINATOR, DRAW_POOL_OFFSET, DRAW_PURCHASER_OFFSET, EXACT_IN_MARGIN_BPS, GABOX_PROGRAM_ID, GaboxMathError, IDENTITY_SEED, INSTRUCTIONS_SYSVAR, JUPITER_DEFAULT_COMPUTE_UNITS, JUPITER_DEFAULT_SLIPPAGE_BPS, JUPITER_LITE_URL, LAUNCH_DECIMALS, MAX_ATTEMPTS, MAX_COMPUTE_UNIT_LIMIT, MAX_MULTIPLIER_BPS, METAPLEX_PROGRAM_ADDRESS, MIN_SEED_MULTIPLIER_BPS, PACK_TOKENS, PLATFORM_ADMIN, POOL_CREATOR_OFFSET, POOL_DISCRIMINATOR, POOL_MINT_OFFSET, REDEEM_COMPUTE_UNITS, RETRY_SLOTS, SLOT_HASHES_SYSVAR, SYSTEM_PROGRAM_ADDRESS, TICKETS, TIERS, TIMEOUT_SLOTS, TOKEN_PROGRAM_ADDRESS, VRF_DEFAULT_QUEUE, VRF_PROGRAM_ADDRESS, WALLET_ACTIVITY_DISCRIMINATOR, WSOL_MINT, activityAddress, assertClusterUrl, assertRouteIsSafe, associatedTokenAddress, averageMultiplierBps, buildMessage, buyPack, choose, clusterNamedBy, computeBudgetInstructions, computeUnitsOf, computeUnitsWithRoute, createClient, createMachine, createQuoteAccount, decodeDraw, decodeEvent, decodeEvents, decodePool, decodeWalletActivity, defaultAddressLookupTables, defaultRoute, drawAddress, drawAvailability, expireDraw, fetchAddressLookupTables, fetchDraw, fetchEvents, fetchPoolAt, fetchPoolByMint, fetchPoolInventory, fetchVaultBalance, fetchWalletActivity, findActivityPda, findDrawPda, findIdentityPda, findPoolPda, findResolvedDraw, fundPrizes, fundWsol, generated_exports as generated, getOffer, getSetComputeUnitLimitInstruction, getSetComputeUnitPriceInstruction, jupiterRoute, listDraws, listDrawsByPool, listDrawsByPurchaser, listPools, maxMultiplierBps, offerFromState, oracleAccounts, poolAddress, providerOf, quote, quoteLegIn, quoteLegOut, quotePool, raydium_exports as raydium, raydiumCpmmRoute, resolveReservation, retryDraw, routeFrom, routeQuoteIn, routeQuoteOut, routeSizeHint, scopedVrfIdentityAddress, seedCostEstimate, seedShortfall, seedTokens, sellTokens, solPriceOf, tierAmount, tiersOf, uncappedMaximum, unwrapWsol, validatePack, validateTiers, vaultAddress, vrfIdentityAddress, websocketUrlFor, withRemainingAccounts };
|
|
1584
|
+
export { ASSOCIATED_TOKEN_PROGRAM_ADDRESS, BPS, BUY_PACK_COMPUTE_UNITS, CLAIM_COMPUTE_UNITS, CLUSTER_ENDPOINTS, COMPUTE_BUDGET_PROGRAM_ADDRESS, CPMM_ROUTE_COMPUTE_UNITS, CPMM_ROUTE_SLIPPAGE_BPS, CREATE_MACHINE_COMPUTE_UNITS, DEFAULT_COMPUTE_UNIT_LIMIT, DEFAULT_TIERS, DEVNET_ADDRESS_LOOKUP_TABLES, DEVNET_HTTP, DEVNET_LOOKUP_TABLE_ADDRESS, DEVNET_LOOKUP_TABLE_ADDRESSES, DEVNET_WS, DRAW_DISCRIMINATOR, DRAW_POOL_OFFSET, DRAW_PURCHASER_OFFSET, EXACT_IN_MARGIN_BPS, GABOX_PROGRAM_ID, GaboxMathError, IDENTITY_SEED, INSTRUCTIONS_SYSVAR, JUPITER_DEFAULT_COMPUTE_UNITS, JUPITER_DEFAULT_SLIPPAGE_BPS, JUPITER_LITE_URL, LAUNCH_DECIMALS, MAX_ATTEMPTS, MAX_COMPUTE_UNIT_LIMIT, MAX_MULTIPLIER_BPS, METAPLEX_PROGRAM_ADDRESS, MIN_SEED_MULTIPLIER_BPS, PACK_TOKENS, PLATFORM_ADMIN, POOL_CREATOR_OFFSET, POOL_DISCRIMINATOR, POOL_MINT_OFFSET, REDEEM_COMPUTE_UNITS, RETRY_SLOTS, SLOT_HASHES_SYSVAR, SYSTEM_PROGRAM_ADDRESS, TICKETS, TIERS, TIMEOUT_SLOTS, TOKEN_PROGRAM_ADDRESS, VRF_DEFAULT_QUEUE, VRF_PROGRAM_ADDRESS, WALLET_ACTIVITY_DISCRIMINATOR, WSOL_MINT, activityAddress, assertClusterUrl, assertRouteIsSafe, associatedTokenAddress, averageMultiplierBps, buildMessage, buyPack, choose, clusterNamedBy, computeBudgetInstructions, computeUnitsOf, computeUnitsWithRoute, createClient, createMachine, createQuoteAccount, decodeDraw, decodeEvent, decodeEvents, decodePool, decodeWalletActivity, defaultAddressLookupTables, defaultRoute, drawAddress, drawAvailability, expireDraw, fetchAddressLookupTables, fetchDraw, fetchEvents, fetchPoolAt, fetchPoolByMint, fetchPoolInventory, fetchVaultBalance, fetchWalletActivity, findActivityPda, findDrawPda, findIdentityPda, findPoolPda, findResolvedDraw, fundPrizes, fundWsol, generated_exports as generated, getOffer, getSetComputeUnitLimitInstruction, getSetComputeUnitPriceInstruction, jupiterRoute, listDraws, listDrawsByPool, listDrawsByPurchaser, listPools, maxMultiplierBps, offerFromState, oracleAccounts, poolAddress, providerOf, quote, quoteLegFromWallet, quoteLegIn, quoteLegOut, quotePool, raydium_exports as raydium, raydiumCpmmRoute, resolveReservation, retryDraw, routeFrom, routeQuoteIn, routeQuoteOut, routeSizeHint, scopedVrfIdentityAddress, seedCostEstimate, seedShortfall, seedTokens, sellTokens, solPriceOf, tierAmount, tiersOf, uncappedMaximum, unwrapWsol, validatePack, validateTiers, vaultAddress, vrfIdentityAddress, websocketUrlFor, withRemainingAccounts };
|
|
1586
1585
|
|
|
1587
1586
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/events.ts","../src/lookupTables.ts","../src/route/leg.ts","../src/offer.ts","../src/route/cpmm.ts","../src/route/jupiter.ts","../src/rpc.ts","../src/tx/wsol.ts","../src/tx/quoteLeg.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":["/** 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-18T11:04:06.369Z.\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, getAddressDecoder, type Address, type AddressesByLookupTableAddress } from '@solana/kit';\n\nimport type { Cluster, GaboxClient } 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 address('USDCoctVLVnvTXBEuP9s8hntucdJokbo17RwHuNXemT'),\n address('4wHbNkobu7iARU9MbCEqDSAq6JuQreGupG2Jsf2R3DFP'),\n address('5Eu2G2USTy1pqphmQzQ2SBXWrBq5sdhgEh7hso9R2xix'),\n address('A9qBhPy4k5UYW72hSgAkh1Epr2do69P54yzzcMV3yv6b'),\n address('Aw93pmXP52u6WSW2HcafRxua1LDht5MZhhXaaR7qCjsN'),\n address('CPLUA2NTYSGjsB1E9iXT3MrPn69WRFJvKTdJZw5NdEjh'),\n address('7LnqjXdqJEdccWZQs5YJobQ8MDmcK4sG2oo4Ty4LBC8c'),\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/** The address lookup table program. It owns every table account. */\nconst LOOKUP_TABLE_PROGRAM = address('AddressLookupTab1e1111111111111111111111111');\n\n/**\n * The fixed part of a table account, before its addresses: a 4-byte discriminator, the two slot\n * fields, the start index, the optional authority, and two padding bytes.\n */\nconst LOOKUP_TABLE_HEADER = 56;\n\n/**\n * Read lookup tables off chain by address, for compressing against tables this SDK does not pin.\n *\n * A router picks its own tables per quote, so their contents are only known at run time, and a\n * message can only be compressed against a table whose addresses are loaded. An address with no\n * account, a wrong owner, or a malformed body is skipped rather than failing the whole route: the\n * message then carries those accounts in full, which is correct, only larger.\n */\nexport async function fetchAddressLookupTables(\n client: GaboxClient,\n addresses: Address[],\n): Promise<AddressesByLookupTableAddress> {\n const wanted = [...new Set(addresses)];\n if (wanted.length === 0) return {};\n\n const { value } = await client.rpc\n .getMultipleAccounts(wanted, { encoding: 'base64', commitment: 'confirmed' })\n .send();\n\n const decoder = getAddressDecoder();\n const tables: AddressesByLookupTableAddress = {};\n for (const [index, account] of value.entries()) {\n if (!account || account.owner !== LOOKUP_TABLE_PROGRAM) continue;\n const data = Buffer.from(account.data[0], 'base64');\n const body = data.length - LOOKUP_TABLE_HEADER;\n if (body <= 0 || body % 32 !== 0) continue;\n const stored: Address[] = [];\n for (let at = LOOKUP_TABLE_HEADER; at < data.length; at += 32) {\n stored.push(decoder.decode(new Uint8Array(data.subarray(at, at + 32))));\n }\n tables[wanted[index]!] = stored;\n }\n return tables;\n}\n","/**\n * Turning a route provider into the one swap leg a Gabox transaction needs.\n *\n * Two directions, and they are not symmetric:\n *\n * - **Paying in SOL.** The pack costs an exact amount of the quote token, so `routeQuoteIn` asks\n * for exact-out first. When the pair has no exact-out route it falls back to exact-in, working\n * out the SOL that buys the amount at the exact-in price and adding a margin.\n * - **Receiving SOL.** A sale pays the quote token in, and the seller wants SOL out. The amount\n * is already known, so `routeQuoteOut` is a plain exact-in swap.\n *\n * # Why the leg is checked before it is used\n *\n * A route is built by code outside this SDK. Its instructions go into the same transaction as\n * `buy_pack`, which means they run with the buyer's signature. So two things are checked before\n * any route is composed:\n *\n * 1. no instruction may name a Gabox account or the Gabox program itself, so a route can never\n * touch a pool, a vault, a draw or the activity account;\n * 2. the swap has to name the user's own quote associated token account, which is the account\n * the program binds and measures the quote delta in. A swap that paid somewhere else would\n * leave the buy short.\n */\n\nimport type { Address } from '@solana/kit';\n\nimport type { GaboxClient } from '../rpc';\nimport { WSOL_MINT } from '../raydium/ids';\nimport type { Route, RouteProvider } from './types';\n\n/**\n * The margin added to an exact-in fallback, in basis points.\n *\n * An exact-in quote prices one spend. The spend that buys the amount wanted is worked out from that\n * price, and the price moves against a larger spend, so the result is always a little short without\n * a margin. 1% is the same order as the slippage a caller already signs for on the pack itself.\n */\nexport const EXACT_IN_MARGIN_BPS = 100n;\n\n/**\n * The first exact-in quote's size, in lamports, when a pair has no exact-out route.\n *\n * It exists only to learn a price, so it is small enough that its own impact on the route is\n * small, and large enough that a route quotes it at all. The real spend is worked out from the\n * price it returns and re-quoted.\n */\nconst PROBE_LAMPORTS = 100_000_000n;\n\n/** How many times the exact-in fallback re-quotes before it gives up. */\nconst EXACT_IN_ATTEMPTS = 3;\n\n/**\n * A swap that leaves at least `amount` of `quoteMint` in the user's quote account, paid for in SOL.\n *\n * Exact-out when the pair has such a route, so the buyer spends only what the pack costs. Exact-in\n * otherwise, which overshoots on purpose: the leftover quote stays in the buyer's own account.\n */\nexport async function routeQuoteIn(\n client: GaboxClient,\n provider: RouteProvider,\n input: { quoteMint: Address; amount: bigint; user: Address },\n): Promise<Route> {\n const { quoteMint, amount, user } = input;\n if (amount <= 0n) throw new Error('the quote amount to buy must be positive');\n if (quoteMint === WSOL_MINT) {\n throw new Error('a WSOL-quoted pool needs no route: the builders wrap SOL themselves');\n }\n\n try {\n const route = await provider.exactOut(client, WSOL_MINT, quoteMint, amount, user);\n if (route.outAmount < amount) {\n throw new Error(\n `the exact-out route buys ${route.outAmount} of ${quoteMint}, which is below the ` +\n `${amount} the pack costs`,\n );\n }\n return route;\n } catch (exactOutFailure) {\n return await exactInFallback(client, provider, quoteMint, amount, user, exactOutFailure);\n }\n}\n\n/**\n * Work out the SOL that buys `amount` of the quote at the exact-in price, then swap it.\n *\n * The first quote is a small probe, only to learn a price. Every later quote scales the last one by\n * what it actually returned, so an impact the probe did not show is corrected rather than guessed\n * at. Three quotes at most, and a route that still falls short is an error rather than a buy that\n * fails on chain.\n */\nasync function exactInFallback(\n client: GaboxClient,\n provider: RouteProvider,\n quoteMint: Address,\n amount: bigint,\n user: Address,\n exactOutFailure: unknown,\n): Promise<Route> {\n let spend = PROBE_LAMPORTS;\n let last: Route | undefined;\n for (let attempt = 0; attempt < EXACT_IN_ATTEMPTS; attempt++) {\n let route: Route;\n try {\n route = await provider.exactIn(client, WSOL_MINT, quoteMint, spend, user);\n } catch (exactInFailure) {\n throw new Error(\n `no route from SOL to ${quoteMint}. Exact-out failed with ` +\n `\"${messageOf(exactOutFailure)}\" and exact-in with \"${messageOf(exactInFailure)}\".`,\n );\n }\n last = route;\n if (route.outAmount >= amount) return route;\n if (route.outAmount <= 0n) break;\n // Scale the spend by what this quote actually returned, then add the margin.\n const scaled = ceilDiv(route.inAmount * amount, route.outAmount);\n const next = scaled + (scaled * EXACT_IN_MARGIN_BPS) / 10_000n;\n if (next <= spend) break;\n spend = next;\n }\n throw new Error(\n `no route from SOL to ${quoteMint} buys ${amount}. The best exact-in quote returned ` +\n `${last?.outAmount ?? 0n} for ${last?.inAmount ?? spend} lamports, and exact-out failed ` +\n `with \"${messageOf(exactOutFailure)}\".`,\n );\n}\n\n/**\n * A swap that turns exactly `amount` of `quoteMint` into SOL.\n *\n * `sellTokens` uses it on the proceeds floor it already signs for, so the amount swapped is one the\n * sale is guaranteed to have produced. Anything the sale paid above that floor stays in the\n * seller's quote account.\n */\nexport async function routeQuoteOut(\n client: GaboxClient,\n provider: RouteProvider,\n input: { quoteMint: Address; amount: bigint; user: Address },\n): Promise<Route> {\n const { quoteMint, amount, user } = input;\n if (amount <= 0n) throw new Error('the quote amount to sell must be positive');\n if (quoteMint === WSOL_MINT) {\n throw new Error('a WSOL-quoted pool needs no route: the builders unwrap SOL themselves');\n }\n return await provider.exactIn(client, quoteMint, WSOL_MINT, amount, user);\n}\n\n/**\n * Refuse a route that would touch Gabox state, or that does not settle in the account the program\n * binds.\n *\n * `forbidden` is every Gabox account the transaction itself uses, plus the Gabox program id.\n * `settlesIn` is the user's quote associated token account: the swap has to name it, because that\n * is where `buy_pack` measures the quote it spends and where `sell_tokens` measures the proceeds.\n */\nexport function assertRouteIsSafe(\n route: Route,\n expect: { forbidden: readonly Address[]; settlesIn: Address },\n): void {\n const forbidden = new Set<Address>(expect.forbidden);\n let settles = false;\n for (const instruction of route.instructions) {\n if (forbidden.has(instruction.programAddress as Address)) {\n throw new Error(\n `the route calls ${instruction.programAddress}, which is a Gabox program or account. A ` +\n 'route must never touch Gabox state.',\n );\n }\n for (const account of instruction.accounts ?? []) {\n if (forbidden.has(account.address)) {\n throw new Error(\n `the route names the Gabox account ${account.address}. A route must never touch Gabox ` +\n 'state.',\n );\n }\n if (account.address === expect.settlesIn) settles = true;\n }\n }\n if (!settles) {\n throw new Error(\n `the route never names ${expect.settlesIn}, the quote account the program settles in. The ` +\n 'swap would pay somewhere the buy cannot spend from.',\n );\n }\n}\n\n/**\n * What `amount` of a quote token costs in SOL, through the client's route provider.\n *\n * `null` when the client has no provider, or when the provider has no exact-out route. A price is a\n * display, so a missing one is not an error. A WSOL amount is already SOL and comes back unchanged.\n *\n * No fallback to exact-in here on purpose: an exact-in price answers a different question, and a\n * display that silently swapped the two would be wrong rather than missing.\n */\nexport async function solPriceOf(\n client: GaboxClient,\n quoteMint: Address,\n amount: bigint,\n): Promise<bigint | null> {\n if (quoteMint === WSOL_MINT) return amount;\n if (!client.route || amount <= 0n) return null;\n try {\n // The route is priced, never built, so any address gives a valid quote.\n const route = await client.route.exactOut(client, WSOL_MINT, quoteMint, amount, quoteMint);\n return route.inAmount;\n } catch {\n return null;\n }\n}\n\n/** `ceil(numerator / denominator)` for non-negative values. */\nfunction ceilDiv(numerator: bigint, denominator: bigint): bigint {\n return (numerator + denominator - 1n) / denominator;\n}\n\nconst messageOf = (cause: unknown): string =>\n cause instanceof Error ? cause.message : String(cause);\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 * `quoteAmount` is in the pool's own quote token, which is not always SOL. `solAmount` is the same\n * price in SOL, priced through the client's route provider: the exact-out cost of buying\n * `quoteAmount` of the quote token. It is `null` when the client has no provider or the pair has no\n * route, because a price is a display and a missing one is not an error.\n *\n * Nothing here is an estimate of cash value. Every number is tokens or base units.\n */\n\nimport type { Address } from '@solana/kit';\n\nimport { fetchPoolInventory, tiersOf, type PoolInventory } from './accounts';\nimport { fetchQuoteDisplay } from './raydium/quote';\nimport { solPriceOf } from './route/leg';\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 /** The pool's quote asset. Both venues settle in it; there is no native-SOL path. */\n quoteMint: Address;\n /** The quote mint's decimals, so `quoteAmount` can be shown as a number. */\n quoteDecimals: number;\n /** The quote mint's symbol, from Metaplex or Token-2022 metadata. `null` when it has none. */\n quoteSymbol: string | null;\n /**\n * The same pack price in lamports, through the client's route provider. Equal to `quoteAmount` on\n * a WSOL pool, and `null` when no route can price it.\n */\n solAmount: bigint | null;\n /** What the seed cost the creator at creation, in the quote token. 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. Three round trips: the pool and its vault, the venue, then the\n * quote mint and its metadata. A non-SOL pool adds one HTTP call to the route provider for\n * `solAmount`.\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 const { pool } = inventory;\n\n const venue = await resolveVenue(client, {\n mint,\n user: options.user ?? pool.creator,\n quote: {\n mint: pool.quoteMint,\n config: pool.quoteConfig,\n tokenProgram: pool.quoteTokenProgram,\n },\n ...(options.venue ? { venue: options.venue } : {}),\n });\n\n const quoteAmount = venue.quoteBuy(pool.packTokens);\n const display = await fetchQuoteDisplay(client, pool.quoteMint);\n return offerFromState(inventory, venue.kind, quoteAmount, {\n quoteDecimals: display.decimals,\n quoteSymbol: display.symbol,\n solAmount: await solPriceOf(client, pool.quoteMint, quoteAmount),\n });\n}\n\n/** The three display fields `getOffer` reads separately from the price. */\nexport type QuoteDisplayFields = {\n quoteDecimals: number;\n quoteSymbol: string | null;\n solAmount: bigint | null;\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 *\n * `display` is optional: a caller that only wants the prize numbers can leave it out, and the three\n * display fields then report the quote's own base units with no symbol and no SOL price.\n */\nexport function offerFromState(\n inventory: PoolInventory,\n venue: VenueKind,\n quoteAmount: bigint,\n display: QuoteDisplayFields = { quoteDecimals: 0, quoteSymbol: null, solAmount: null },\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 quoteDecimals: display.quoteDecimals,\n quoteSymbol: display.quoteSymbol,\n solAmount: display.solAmount,\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 * A route provider backed by one Raydium CPMM pool.\n *\n * Jupiter does not serve devnet, so a devnet machine quoted in a test token needs a route this SDK\n * can build itself. Given a CPMM pool that holds the SOL/quote pair, this provider swaps through\n * it with the same two instructions Gabox already forwards for a graduated coin, priced with the\n * same bigint port of Raydium's math.\n *\n * It works anywhere such a pool exists, mainnet included. It is not a router: it uses the one pool\n * the caller names and nothing else.\n *\n * # Wrapping\n *\n * CPMM settles in WSOL, never in native SOL. So the route wraps the SOL it spends and closes the\n * WSOL account afterwards, exactly as Jupiter's `wrapAndUnwrapSol` does. A sale into SOL creates\n * the WSOL account, swaps into it, and closes it, which is what turns the proceeds into SOL.\n *\n * # No signer objects\n *\n * The user is an address, not a signer. Every signing slot is marked as a signer and left for the\n * fee payer to sign, the same way a Jupiter instruction arrives. The wallet paying for the Gabox\n * transaction is the same wallet, so its one signature covers all of them.\n *\n * That is not a shortcut, it is required. Kit refuses to sign a message that carries two distinct\n * signer objects for one address: `signTransactionMessageWithSigners` fails with \"Multiple distinct\n * signers were identified for address\". The token and system builders below only accept a signer,\n * so `withoutSigners` strips the object again and keeps the role.\n */\n\nimport {\n createNoopSigner,\n getU64Encoder,\n type AccountMeta,\n type Address,\n type Instruction,\n type TransactionSigner,\n} from '@solana/kit';\nimport {\n getCloseAccountInstruction,\n getCreateAssociatedTokenIdempotentInstruction,\n getSyncNativeInstruction,\n} from '@solana-program/token';\nimport { getTransferSolInstruction } from '@solana-program/system';\n\nimport { decodeCpmmAmmConfig, decodeCpmmPool, tokenAccountAmount } from '../raydium/adapter';\nimport { CPMM_SWAP_BASE_INPUT, CPMM_SWAP_BASE_OUTPUT } from '../raydium/abi';\nimport { order } from '../raydium/accounts';\nimport {\n cpmmSwapBaseInput,\n cpmmSwapBaseOutput,\n type CpmmFeeRates,\n type CpmmSwapSides,\n} from '../raydium/curve';\nimport { WSOL_MINT, raydiumIds } from '../raydium/ids';\nimport { ata } from '../raydium/pdas';\nimport { readAccounts } from '../raydium/read';\nimport { creatorFeeOnInput } from '../raydium/venue';\nimport type { GaboxClient } from '../rpc';\nimport type { Route, RouteProvider } from './types';\n\nconst u64 = getU64Encoder();\n\n/**\n * The slippage this provider signs for on a pool swap, in basis points. 1%, the same as the\n * Jupiter provider's default. It only widens the on-chain bound; the price itself is exact.\n */\nexport const CPMM_ROUTE_SLIPPAGE_BPS = 100n;\n\n/**\n * The compute units one swap through this provider adds to a transaction.\n *\n * Measured on devnet on 2026-09-18 against one Raydium CPMM pool, as the difference from the same\n * builder with no route: `55,110` and `29,272` on `createMachine`, `21,488` and `52,980` on\n * `buyPack`, and `30,138` and `51,138` on `sellTokens`. The spread is wide because which token\n * accounts already exist changes from run to run, so this rounds up to the top of it.\n *\n * It is a safe figure here and nowhere else: this provider always uses exactly one pool. A router\n * that may pick several hops states its own number; see `JUPITER_DEFAULT_COMPUTE_UNITS`.\n */\nexport const CPMM_ROUTE_COMPUTE_UNITS = 75_000;\n\n/**\n * Swap through one named Raydium CPMM pool.\n *\n * The pool must hold the pair the route asks for. On devnet the SOL/USDC-test pool with the most\n * liquidity is `5Eu2G2USTy1pqphmQzQ2SBXWrBq5sdhgEh7hso9R2xix`, under the fee tier\n * `A9qBhPy4k5UYW72hSgAkh1Epr2do69P54yzzcMV3yv6b`.\n */\nexport function raydiumCpmmRoute(poolAddress: Address): RouteProvider {\n return {\n exactOut: async (client, input, output, amount, user) =>\n await swap(client, poolAddress, { input, output, amount, user, mode: 'exactOut' }),\n exactIn: async (client, input, output, amount, user) =>\n await swap(client, poolAddress, { input, output, amount, user, mode: 'exactIn' }),\n };\n}\n\nasync function swap(\n client: GaboxClient,\n poolAddress: Address,\n request: {\n input: Address;\n output: Address;\n amount: bigint;\n user: Address;\n mode: Route['mode'];\n },\n): Promise<Route> {\n const { input, output, amount, user, mode } = request;\n if (amount <= 0n) throw new Error('the route amount must be positive');\n const ids = raydiumIds(client.cluster);\n\n const [poolAccount] = await readAccounts(client.rpc, [poolAddress]);\n if (!poolAccount || poolAccount.owner !== ids.cpmm) {\n throw new Error(`${poolAddress} is not a Raydium CPMM pool on ${client.cluster}`);\n }\n const pool = decodeCpmmPool(poolAccount.data);\n\n const inputIsToken0 = pool.token0Mint === input;\n const holdsPair = inputIsToken0\n ? pool.token1Mint === output\n : pool.token1Mint === input && pool.token0Mint === output;\n if (!holdsPair) {\n throw new Error(\n `the CPMM pool at ${poolAddress} holds ${pool.token0Mint} and ${pool.token1Mint}, not ` +\n `${input} and ${output}`,\n );\n }\n\n const inputVault = inputIsToken0 ? pool.token0Vault : pool.token1Vault;\n const outputVault = inputIsToken0 ? pool.token1Vault : pool.token0Vault;\n const inputTokenProgram = inputIsToken0 ? pool.token0Program : pool.token1Program;\n const outputTokenProgram = inputIsToken0 ? pool.token1Program : pool.token0Program;\n\n const [configAccount, inputVaultAccount, outputVaultAccount] = await readAccounts(client.rpc, [\n pool.ammConfig,\n inputVault,\n outputVault,\n ]);\n if (!configAccount) throw new Error(`the CPMM pool at ${poolAddress} names a fee tier that is not on chain`);\n if (!inputVaultAccount || !outputVaultAccount) {\n throw new Error(`the CPMM pool at ${poolAddress} has no reserve accounts`);\n }\n const config = decodeCpmmAmmConfig(configAccount.data);\n\n // A swap may not spend what the pool already owes. Raydium subtracts the same three balances.\n const owed = (token0: boolean) =>\n token0\n ? pool.protocolFeesToken0 + pool.fundFeesToken0 + pool.creatorFeesToken0\n : pool.protocolFeesToken1 + pool.fundFeesToken1 + pool.creatorFeesToken1;\n const sides: CpmmSwapSides = {\n inputReserve: tokenAccountAmount(inputVaultAccount.data) - owed(inputIsToken0),\n outputReserve: tokenAccountAmount(outputVaultAccount.data) - owed(!inputIsToken0),\n };\n if (sides.inputReserve <= 0n || sides.outputReserve <= 0n) {\n throw new Error(`the CPMM pool at ${poolAddress} has no tradable reserves`);\n }\n const rates: CpmmFeeRates = {\n tradeFeeRate: config.tradeFeeRate,\n creatorFeeRate: pool.enableCreatorFee ? config.creatorFeeRate : 0n,\n creatorFeeOnInput: creatorFeeOnInput(pool, input),\n };\n\n const userInput = await ata(user, input, inputTokenProgram);\n const userOutput = await ata(user, output, outputTokenProgram);\n const abi = mode === 'exactOut' ? CPMM_SWAP_BASE_OUTPUT : CPMM_SWAP_BASE_INPUT;\n const accounts = order(abi, {\n payer: user,\n authority: ids.cpmmAuthority,\n amm_config: pool.ammConfig,\n pool_state: poolAddress,\n input_token_account: userInput,\n output_token_account: userOutput,\n input_vault: inputVault,\n output_vault: outputVault,\n input_token_program: inputTokenProgram,\n output_token_program: outputTokenProgram,\n input_token_mint: input,\n output_token_mint: output,\n observation_state: pool.observationKey,\n });\n\n // `swap_base_output` takes `(max_amount_in, amount_out)`; `swap_base_input` takes\n // `(amount_in, minimum_amount_out)`. The two orders are the reverse of each other.\n const exactOut = mode === 'exactOut';\n const priced = exactOut\n ? cpmmSwapBaseOutput(sides, rates, amount)\n : cpmmSwapBaseInput(sides, rates, amount);\n const inAmount = exactOut ? widen(priced) : amount;\n const outAmount = exactOut ? amount : narrow(priced);\n const swapInstruction = {\n programAddress: ids.cpmm,\n accounts,\n data: new Uint8Array([\n ...abi.discriminator,\n ...u64.encode(exactOut ? inAmount : amount),\n ...u64.encode(exactOut ? amount : outAmount),\n ]),\n } as Instruction;\n\n return {\n instructions: wrap({\n user,\n input,\n output,\n userInput,\n userOutput,\n inputTokenProgram,\n outputTokenProgram,\n lamportsIn: inAmount,\n middle: [swapInstruction],\n }),\n // The devnet lookup table already carries every Raydium address this route names.\n lookupTables: {},\n inAmount,\n outAmount,\n mode,\n computeUnits: CPMM_ROUTE_COMPUTE_UNITS,\n };\n}\n\n/** Add the slippage margin to a cost the caller signs as a maximum. */\nconst widen = (amount: bigint): bigint => amount + (amount * CPMM_ROUTE_SLIPPAGE_BPS) / 10_000n;\n/** Take the slippage margin off a payout the caller signs as a minimum. */\nconst narrow = (amount: bigint): bigint => amount - (amount * CPMM_ROUTE_SLIPPAGE_BPS) / 10_000n;\n\n/**\n * Create the two token accounts the swap needs, wrap the SOL it spends, and close the WSOL account\n * afterwards.\n *\n * Only one side is ever WSOL here: a Gabox pool quoted in WSOL never uses a route at all.\n */\nfunction wrap(input: {\n user: Address;\n input: Address;\n output: Address;\n userInput: Address;\n userOutput: Address;\n inputTokenProgram: Address;\n outputTokenProgram: Address;\n lamportsIn: bigint;\n middle: Instruction[];\n}): Instruction[] {\n // A placeholder, only so the builders below mark their signing slots. `withoutSigners` removes\n // the object again before the instruction leaves this file.\n const payer = createNoopSigner(input.user);\n const createAta = (account: Address, mint: Address, tokenProgram: Address): Instruction =>\n withoutSigners(\n getCreateAssociatedTokenIdempotentInstruction({\n payer,\n ata: account,\n owner: input.user,\n mint,\n tokenProgram,\n }) as Instruction,\n );\n\n const before: Instruction[] = [\n createAta(input.userInput, input.input, input.inputTokenProgram),\n createAta(input.userOutput, input.output, input.outputTokenProgram),\n ];\n const after: Instruction[] = [];\n\n if (input.input === WSOL_MINT) {\n before.push(\n withoutSigners(\n getTransferSolInstruction({\n source: payer,\n destination: input.userInput,\n amount: input.lamportsIn,\n }) as Instruction,\n ),\n // Without this the token account holds the lamports but still reports a zero balance.\n getSyncNativeInstruction({ account: input.userInput }) as Instruction,\n );\n after.push(closeWsol(input.userInput, payer));\n }\n if (input.output === WSOL_MINT) {\n after.push(closeWsol(input.userOutput, payer));\n }\n return [...before, ...input.middle, ...after];\n}\n\n/**\n * Close a WSOL account, sending every lamport in it back to the owner as SOL.\n *\n * The owner has to sign, so it goes in as a signer and comes out as a plain signing slot.\n */\nconst closeWsol = (account: Address, owner: TransactionSigner): Instruction =>\n withoutSigners(\n getCloseAccountInstruction({ account, destination: owner.address, owner }) as Instruction,\n );\n\n/**\n * Drop every attached signer object, keeping each account's address and role.\n *\n * A signing slot stays a signing slot: the compiled message still requires that signature, and the\n * wallet paying for the transaction provides it. What goes away is the second signer object for an\n * address the fee payer already covers, which kit refuses to sign.\n */\nfunction withoutSigners(instruction: Instruction): Instruction {\n const accounts: AccountMeta[] = (instruction.accounts ?? []).map((account) => ({\n address: account.address,\n role: account.role,\n }));\n return { ...instruction, accounts } as Instruction;\n}\n","/**\n * The Jupiter route provider.\n *\n * Jupiter is an HTTP service, not a program this SDK builds instructions for. Two calls per route:\n *\n * 1. `GET /swap/v1/quote` prices the swap and returns a quote object.\n * 2. `POST /swap/v1/swap-instructions` turns that quote into instructions.\n *\n * The response gives `setupInstructions`, `swapInstruction` and `cleanupInstruction`, each as a\n * program id, a list of accounts and base64 data. This module decodes those into kit instructions\n * and leaves everything else alone. Jupiter's own compute budget instructions are dropped: every\n * builder in this SDK sets its own budget, and two `SetComputeUnitLimit` instructions in one message\n * is one too many. Their **number** is kept, though: it is Jupiter's own answer to \"how much does\n * this route cost\", and a builder adds it to its own limit.\n *\n * `wrapAndUnwrapSol: true` is always sent, so Jupiter creates the wallet's WSOL account, funds it\n * from the wallet's lamports and closes it again inside its own instructions. That is what makes\n * \"pay in SOL\" true from the wallet's side.\n *\n * # No Jupiter package\n *\n * The public surface of this SDK is `@solana/kit` only. Nothing here imports a Jupiter package; the\n * response is plain JSON and the decoding below is a dozen lines.\n *\n * # Exact-out is not always available\n *\n * Jupiter answers `NO_ROUTES_FOUND` for an exact-out quote whenever the best route has more than\n * one hop. Verified on 2026-09-18: SOL to USDC quotes exact-out, while SOL to the stock token\n * `XsDoVfqeBukxuZHWhdvWHBhgEHjGNst4MLodqsJHzoB` only quotes exact-in. `routeQuoteIn` in `leg.ts`\n * handles that fallback; this file only reports the failure.\n */\n\nimport {\n AccountRole,\n getBase64Encoder,\n type AccountMeta,\n type Address,\n type Instruction,\n} from '@solana/kit';\n\nimport { fetchAddressLookupTables } from '../lookupTables';\nimport type { GaboxClient } from '../rpc';\nimport type { Route, RouteProvider } from './types';\n\n/** Jupiter's free endpoint. The keyed host `https://api.jup.ag/swap/v1` has the same shape. */\nexport const JUPITER_LITE_URL = 'https://lite-api.jup.ag/swap/v1';\n\n/** The slippage Jupiter prices a route with when the caller names none. 1%. */\nexport const JUPITER_DEFAULT_SLIPPAGE_BPS = 100;\n\n/**\n * The compute units a Jupiter route is assumed to need when the response carries no limit.\n *\n * Jupiter normally sends a `SetComputeUnitLimit` of its own, and that number is what this SDK uses.\n * When it does not, this is the fallback: enough for a route through several pools, and still far\n * below the 1,400,000-unit ceiling once the Gabox instruction's own budget is added. A caller who\n * knows better passes `computeUnitLimit` to the builder.\n */\nexport const JUPITER_DEFAULT_COMPUTE_UNITS = 400_000;\n\n/** `ComputeBudgetInstruction::SetComputeUnitLimit`, whose data is the tag then a u32 of units. */\nconst SET_COMPUTE_UNIT_LIMIT = 2;\n\nexport type JupiterRouteOptions = {\n /** The base URL of the swap API. Defaults to the free `lite-api` host. */\n url?: string;\n /** Slippage for the quote, in basis points. Defaults to 100, which is 1%. */\n slippageBps?: number;\n};\n\nconst base64 = getBase64Encoder();\n\n/** One account as the swap-instructions response writes it. */\ntype JupiterAccount = { pubkey: string; isSigner: boolean; isWritable: boolean };\ntype JupiterInstruction = { programId: string; accounts: JupiterAccount[]; data: string };\n\n/** The fields of a `swap-instructions` response this SDK reads. */\nexport type JupiterSwapInstructions = {\n /** Read for its unit limit only. These instructions are never copied into the message. */\n computeBudgetInstructions?: JupiterInstruction[] | null;\n setupInstructions?: JupiterInstruction[] | null;\n swapInstruction: JupiterInstruction;\n cleanupInstruction?: JupiterInstruction | null;\n addressLookupTableAddresses?: string[] | null;\n};\n\n/**\n * A route provider backed by Jupiter. Use it on mainnet, where Jupiter has the liquidity.\n *\n * It makes read-only HTTP calls and never sends a transaction: the instructions come back to the\n * caller, who signs them together with the Gabox instruction.\n */\nexport function jupiterRoute(options: JupiterRouteOptions = {}): RouteProvider {\n const url = (options.url ?? JUPITER_LITE_URL).replace(/\\/+$/, '');\n const slippageBps = options.slippageBps ?? JUPITER_DEFAULT_SLIPPAGE_BPS;\n\n const build = async (\n client: GaboxClient,\n input: Address,\n output: Address,\n amount: bigint,\n user: Address,\n swapMode: 'ExactOut' | 'ExactIn',\n ): Promise<Route> => {\n if (amount <= 0n) throw new Error('the route amount must be positive');\n const quote = await fetchQuote(url, { input, output, amount, swapMode, slippageBps });\n const response = await fetchSwapInstructions(url, quote, user);\n // `otherAmountThreshold` is the side the swap is bound to on chain: the most it will spend on\n // an exact-out route, the least it will pay out on an exact-in one. The other side is exact.\n // A `Route` states bounds, not hopes, so the threshold is what goes in it.\n const threshold = BigInt(String(quote.otherAmountThreshold));\n return await routeFrom(client, response, {\n inAmount: swapMode === 'ExactOut' ? threshold : BigInt(String(quote.inAmount)),\n outAmount: swapMode === 'ExactOut' ? BigInt(String(quote.outAmount)) : threshold,\n mode: swapMode === 'ExactOut' ? 'exactOut' : 'exactIn',\n });\n };\n\n return {\n exactOut: async (client, input, output, amount, user) =>\n await build(client, input, output, amount, user, 'ExactOut'),\n exactIn: async (client, input, output, amount, user) =>\n await build(client, input, output, amount, user, 'ExactIn'),\n };\n}\n\n/**\n * The quote object Jupiter returns. It is passed back to `swap-instructions` unchanged, so it\n * carries more fields than these three; only these are read.\n */\ntype JupiterQuote = {\n inAmount: string | number;\n outAmount: string | number;\n /** The bound the swap enforces on chain, once slippage is applied. */\n otherAmountThreshold: string | number;\n};\n\nasync function fetchQuote(\n url: string,\n input: {\n input: Address;\n output: Address;\n amount: bigint;\n swapMode: 'ExactOut' | 'ExactIn';\n slippageBps: number;\n },\n): Promise<JupiterQuote> {\n const query = new URLSearchParams({\n inputMint: input.input,\n outputMint: input.output,\n amount: input.amount.toString(),\n swapMode: input.swapMode,\n slippageBps: String(input.slippageBps),\n });\n const response = await fetch(`${url}/quote?${query.toString()}`);\n const body = (await response.json()) as JupiterQuote & { error?: string; errorCode?: string };\n if (!response.ok || body.error) {\n throw new Error(\n `Jupiter has no ${input.swapMode} route from ${input.input} to ${input.output}: ` +\n `${body.errorCode ?? response.status} ${body.error ?? ''}`.trim(),\n );\n }\n return body;\n}\n\nasync function fetchSwapInstructions(\n url: string,\n quoteResponse: JupiterQuote,\n userPublicKey: Address,\n): Promise<JupiterSwapInstructions> {\n const response = await fetch(`${url}/swap-instructions`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ quoteResponse, userPublicKey, wrapAndUnwrapSol: true }),\n });\n const body = (await response.json()) as JupiterSwapInstructions & { error?: string };\n if (!response.ok || body.error || !body.swapInstruction) {\n throw new Error(\n `Jupiter could not build the swap instructions: ${response.status} ${body.error ?? ''}`.trim(),\n );\n }\n return body;\n}\n\n/**\n * Turn a decoded `swap-instructions` response into a `Route`.\n *\n * Exported so a test can read a recorded response without making an HTTP call. The lookup tables\n * are read through the client, because the response names them by address only.\n */\nexport async function routeFrom(\n client: GaboxClient,\n response: JupiterSwapInstructions,\n amounts: { inAmount: bigint; outAmount: bigint; mode: Route['mode'] },\n): Promise<Route> {\n const instructions: Instruction[] = [\n ...(response.setupInstructions ?? []).map(toKitInstruction),\n toKitInstruction(response.swapInstruction),\n ...(response.cleanupInstruction ? [toKitInstruction(response.cleanupInstruction)] : []),\n ];\n const lookupTables = await fetchAddressLookupTables(\n client,\n (response.addressLookupTableAddresses ?? []) as Address[],\n );\n return { instructions, lookupTables, computeUnits: computeUnitsOf(response), ...amounts };\n}\n\n/**\n * The unit limit Jupiter asked for, or `JUPITER_DEFAULT_COMPUTE_UNITS` when it asked for none.\n *\n * `SetComputeUnitLimit` is five bytes: the tag `2`, then the units as a little-endian u32. Any other\n * compute budget instruction, such as a unit price, is skipped.\n */\nexport function computeUnitsOf(response: JupiterSwapInstructions): number {\n for (const instruction of response.computeBudgetInstructions ?? []) {\n const data = new Uint8Array(base64.encode(instruction.data));\n if (data.length < 5 || data[0] !== SET_COMPUTE_UNIT_LIMIT) continue;\n return new DataView(data.buffer, data.byteOffset).getUint32(1, true);\n }\n return JUPITER_DEFAULT_COMPUTE_UNITS;\n}\n\n/** One Jupiter instruction as a kit instruction. The roles come from the two booleans. */\nfunction toKitInstruction(instruction: JupiterInstruction): Instruction {\n const accounts: AccountMeta[] = instruction.accounts.map((account) => ({\n address: account.pubkey as Address,\n role: account.isSigner\n ? account.isWritable\n ? AccountRole.WRITABLE_SIGNER\n : AccountRole.READONLY_SIGNER\n : account.isWritable\n ? AccountRole.WRITABLE\n : AccountRole.READONLY,\n }));\n return {\n programAddress: instruction.programId as Address,\n accounts,\n data: new Uint8Array(base64.encode(instruction.data)),\n } as Instruction;\n}\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';\nimport { jupiterRoute } from './route/jupiter';\nimport type { RouteProvider } from './route/types';\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 * How a buyer pays in SOL for a machine priced in another token.\n *\n * Mainnet defaults to Jupiter, which is where the liquidity is. Devnet and localnet default to\n * none, because Jupiter does not serve them: pass `raydiumCpmmRoute(pool)` with a CPMM pool that\n * holds the SOL/quote pair. `null` disables the swap leg, and `payWith: 'sol'` then fails on a\n * pool quoted in anything but WSOL.\n */\n route?: RouteProvider | null;\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 /** The swap provider a SOL payment routes through, or `null` when this cluster has none. */\n route: RouteProvider | null;\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 route: config.route === undefined ? defaultRoute(cluster) : config.route,\n };\n}\n\n/**\n * The swap provider a cluster gets when the caller names none.\n *\n * Jupiter on mainnet, nothing anywhere else. Jupiter's API only prices mainnet liquidity, and a\n * devnet caller has to say which pool to route through, so there is nothing to guess.\n */\nexport function defaultRoute(cluster: Cluster): RouteProvider | null {\n return cluster === 'mainnet-beta' ? jupiterRoute() : null;\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 * Getting the quote token into, and out of, the wallet's own quote account.\n *\n * Gabox settles in the pool's quote asset and nothing else. Both venues move that token in and out\n * of one account: the wallet's associated token account for the quote mint, under the quote's own\n * token program. The program pins that address and measures the exact delta there. So every builder\n * in this directory has to make sure the account exists, and holds what the trade will spend.\n *\n * Three shapes, and which one applies follows from the pool's quote and the caller's choice:\n *\n * - **A WSOL pool.** The wallet pays in SOL already. Create the WSOL account, move the lamports\n * into it, `syncNative`, and close it afterwards so the change and any proceeds come back as\n * SOL. This is what every 0.6.0 flow did, unchanged.\n * - **Another quote, paying in that quote.** The wallet already holds the token. Create the\n * account if it is missing and leave it alone: it is not WSOL, so closing it would be wrong.\n * - **Another quote, paying in SOL.** A route turns SOL into the quote token in the same\n * transaction, before `buy_pack`. A sale does the reverse afterwards. `routeQuoteIn` and\n * `routeQuoteOut` build those, and `assertRouteIsSafe` checks the result before it is used.\n *\n * Nothing here ever splits the work across two transactions. A swap that settles separately would\n * leave the wallet holding a token it never asked for whenever the second half failed.\n */\n\nimport { getCreateAssociatedTokenIdempotentInstruction } from '@solana-program/token';\nimport type {\n Address,\n AddressesByLookupTableAddress,\n Instruction,\n TransactionSigner,\n} from '@solana/kit';\n\nimport { MAX_COMPUTE_UNIT_LIMIT } from '../compute';\nimport { GABOX_PROGRAM_ID } from '../ids';\nimport { WSOL_MINT } from '../raydium/ids';\nimport type { ResolvedVenue } from '../raydium/venue';\nimport { assertRouteIsSafe, routeQuoteIn, routeQuoteOut } from '../route/leg';\nimport type { RouteMode, RouteProvider } from '../route/types';\nimport type { GaboxClient } from '../rpc';\nimport { fundWsol, unwrapWsol } from './wsol';\n\n/** Where the money for a purchase comes from. */\nexport type PayWith = 'sol' | 'quote';\n/** What a sale pays out. */\nexport type Receive = 'sol' | 'quote';\n\n/** The instructions that go around the Gabox instruction, and what the route did. */\nexport type QuoteLeg = {\n /** Everything that runs before the Gabox instruction. */\n before: Instruction[];\n /** Everything that runs after it. */\n after: Instruction[];\n /** The lookup tables the route's own instructions need, on top of the client's. */\n lookupTables: AddressesByLookupTableAddress;\n /** Which swap mode the route used, or `null` when no route was needed. */\n mode: RouteMode | null;\n /** SOL the route spends, or `null` when no route was needed. */\n solAmount: bigint | null;\n /**\n * The compute units the route adds to the transaction, or `0` when there is no route.\n *\n * The builder adds this to its own limit, because the swap runs on the same budget. It comes from\n * the route itself, so a Jupiter route through several pools asks for more than a single-pool one.\n */\n computeUnits: number;\n};\n\n/** The Gabox accounts a route must never name. */\nexport type GaboxAccounts = readonly Address[];\n\n/** Create the wallet's quote account if it is missing. Idempotent, so a second create is free. */\nexport function createQuoteAccount(\n owner: TransactionSigner,\n venue: Pick<ResolvedVenue, 'quoteMint' | 'quoteTokenProgram' | 'userQuoteToken'>,\n): Instruction {\n return getCreateAssociatedTokenIdempotentInstruction({\n payer: owner,\n ata: venue.userQuoteToken,\n owner: owner.address,\n mint: venue.quoteMint,\n tokenProgram: venue.quoteTokenProgram,\n }) as Instruction;\n}\n\n/**\n * The leg that puts `maxQuoteIn` of the quote token in the buyer's quote account.\n *\n * `payWith` decides where it comes from. On a WSOL pool the choice makes no difference: the quote\n * token is SOL either way, so the builder wraps it.\n */\nexport async function quoteLegIn(\n client: GaboxClient,\n input: {\n venue: Pick<ResolvedVenue, 'quoteMint' | 'quoteTokenProgram' | 'userQuoteToken'>;\n payer: TransactionSigner;\n maxQuoteIn: bigint;\n payWith: PayWith;\n /** Gabox accounts a route must never name. The Gabox program id is added here. */\n gaboxAccounts: GaboxAccounts;\n },\n): Promise<QuoteLeg> {\n const { venue, payer, maxQuoteIn, payWith } = input;\n\n if (venue.quoteMint === WSOL_MINT) {\n const wsol = await fundWsol(payer, maxQuoteIn);\n return {\n before: wsol.instructions,\n after: [unwrapWsol(payer, wsol.account)],\n lookupTables: {},\n mode: null,\n solAmount: maxQuoteIn,\n computeUnits: 0,\n };\n }\n\n if (payWith === 'quote') {\n return {\n before: [createQuoteAccount(payer, venue)],\n after: [],\n lookupTables: {},\n mode: null,\n solAmount: null,\n computeUnits: 0,\n };\n }\n\n const route = await routeQuoteIn(client, providerOf(client, venue.quoteMint), {\n quoteMint: venue.quoteMint,\n amount: maxQuoteIn,\n user: payer.address,\n });\n assertRouteIsSafe(route, {\n forbidden: [GABOX_PROGRAM_ID, ...input.gaboxAccounts],\n settlesIn: venue.userQuoteToken,\n });\n return {\n before: route.instructions,\n after: [],\n lookupTables: route.lookupTables,\n mode: route.mode,\n solAmount: route.inAmount,\n computeUnits: route.computeUnits,\n };\n}\n\n/**\n * The leg around a sale: make sure the quote account exists, and turn the proceeds into SOL when\n * the seller asked for SOL.\n *\n * The swap is an exact-in of `minQuoteOutput`, the floor the seller already signs for on the sale\n * itself. Anything the venue pays above that floor stays in the seller's quote account: a swap can\n * only spend what the sale is guaranteed to have produced.\n */\nexport async function quoteLegOut(\n client: GaboxClient,\n input: {\n venue: Pick<ResolvedVenue, 'quoteMint' | 'quoteTokenProgram' | 'userQuoteToken'>;\n seller: TransactionSigner;\n minQuoteOutput: bigint;\n receive: Receive;\n gaboxAccounts: GaboxAccounts;\n },\n): Promise<QuoteLeg> {\n const { venue, seller, minQuoteOutput, receive } = input;\n\n if (venue.quoteMint === WSOL_MINT) {\n // A sale needs the account to exist, not to hold anything. The close at the end is what turns\n // the proceeds into SOL.\n const wsol = await fundWsol(seller, 0n);\n return {\n before: wsol.instructions,\n after: [unwrapWsol(seller, wsol.account)],\n lookupTables: {},\n mode: null,\n solAmount: null,\n computeUnits: 0,\n };\n }\n\n const create = createQuoteAccount(seller, venue);\n if (receive === 'quote') {\n return {\n before: [create],\n after: [],\n lookupTables: {},\n mode: null,\n solAmount: null,\n computeUnits: 0,\n };\n }\n\n const route = await routeQuoteOut(client, providerOf(client, venue.quoteMint), {\n quoteMint: venue.quoteMint,\n amount: minQuoteOutput,\n user: seller.address,\n });\n assertRouteIsSafe(route, {\n forbidden: [GABOX_PROGRAM_ID, ...input.gaboxAccounts],\n settlesIn: venue.userQuoteToken,\n });\n return {\n before: [create],\n after: route.instructions,\n lookupTables: route.lookupTables,\n mode: route.mode,\n solAmount: route.outAmount,\n computeUnits: route.computeUnits,\n };\n}\n\n/** The client's route provider, with a message that says what to do when it has none. */\nexport function providerOf(client: GaboxClient, quoteMint: Address): RouteProvider {\n if (!client.route) {\n throw new Error(\n `this ${client.cluster} client has no route provider, so it cannot pay in SOL for a pool ` +\n `quoted in ${quoteMint}. Pass \\`route\\` to createClient — raydiumCpmmRoute(pool) for a ` +\n \"CPMM pool that holds the SOL pair — or pay in the quote token itself.\",\n );\n }\n return client.route;\n}\n\n/**\n * The compute limit a builder asks for: its own budget plus whatever the route needs.\n *\n * Capped at the runtime's ceiling. Jupiter often asks for the whole 1,400,000 units rather than\n * estimating, and a request above the ceiling is rejected outright, so the sum has to be clamped\n * rather than passed through.\n */\nexport function computeUnitsWithRoute(own: number, leg: QuoteLeg): number {\n return Math.min(own + leg.computeUnits, MAX_COMPUTE_UNIT_LIMIT);\n}\n\n/**\n * Add the route to a \"transaction is too large\" error.\n *\n * `buildMessage` already refuses a message above the 1,232-byte limit. When a swap is in the same\n * message, the reason is usually the swap, and the fix is not to split the transaction: the two\n * halves have to settle together. So the message says what a caller can actually do instead.\n */\nexport function routeSizeHint(cause: unknown, leg: QuoteLeg): unknown {\n if (leg.mode === null) return cause;\n if (!(cause instanceof Error) || !cause.message.includes('Solana allows 1232')) return cause;\n return new Error(\n `${cause.message} The swap and the Gabox instruction share one transaction on purpose, so ` +\n 'this SDK never splits them. Supply more address lookup tables, or pay in the quote token.',\n { cause },\n );\n}\n","/**\n * Buying one pack.\n *\n * The Gabox instruction is always the same. What goes around it follows the pool's quote asset:\n *\n * - **A WSOL pool.** Create the purchaser's WSOL account, move `maxQuoteIn` lamports into it,\n * `syncNative`, buy, then close the account so the change comes back as SOL.\n * - **Another quote, `payWith: 'quote'`.** Create the purchaser's quote account if it is missing\n * and buy. The purchaser must already hold at least the pack price.\n * - **Another quote, `payWith: 'sol'` (the default).** A route turns SOL into `maxQuoteIn` of the\n * quote token first, in the same transaction, and `buy_pack` then spends only what the pack\n * costs. Anything the route bought above that stays in the purchaser's quote account.\n *\n * One transaction and one signature in every case. The swap and the buy are never split: a swap\n * that settled on its own would leave the buyer holding a token they never asked for whenever the\n * buy failed.\n *\n * Closing the WSOL account 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 the quote token. `maxNativeDebit` is a\n * separate cap on the lamports the handler watches: the venue's account rent, which LaunchLab\n * charges on a 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 { activityAddress, associatedTokenAddress, drawAddress } from '../pdas';\nimport { resolveVenue, type VenueKind } from '../raydium/venue';\nimport type { GaboxClient } from '../rpc';\nimport { buildMessage, withRemainingAccounts, type BuildOptions } from './message';\nimport { computeUnitsWithRoute, quoteLegIn, routeSizeHint, type PayWith } from './quoteLeg';\n\nexport type BuyPackInput = {\n mint: Address;\n purchaser: TransactionSigner;\n /**\n * The venue slippage cap, in the pool's quote token. The transaction puts this much of the quote\n * token in the buyer's quote account before the buy, so it must cover the real price. Anything\n * left over stays there, or comes back as SOL on a WSOL pool.\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 /**\n * Pay in SOL through a swap, or in the quote token the buyer already holds. Defaults to `'sol'`.\n * A WSOL pool ignores it: its quote token is SOL.\n */\n payWith?: PayWith;\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 quote: {\n mint: pool.quoteMint,\n config: pool.quoteConfig,\n tokenProgram: pool.quoteTokenProgram,\n },\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 quoteTokenProgram: pool.quoteTokenProgram,\n maxQuoteIn: input.maxQuoteIn,\n minMaximum: input.minMaximum,\n maxNativeDebit: input.maxNativeDebit,\n });\n\n const leg = await quoteLegIn(client, {\n venue,\n payer: input.purchaser,\n maxQuoteIn: input.maxQuoteIn,\n payWith: input.payWith ?? 'sol',\n gaboxAccounts: [\n poolAddress,\n pool.vault,\n draw,\n await activityAddress(purchaser),\n await associatedTokenAddress(purchaser, input.mint),\n ],\n });\n\n const instructions: Instruction[] = [\n ...leg.before,\n withRemainingAccounts(buy as Instruction, venue.buyAccounts),\n ...leg.after,\n ];\n\n try {\n return await buildMessage(client, input.purchaser, instructions, {\n addressLookupTables: {\n ...(input.addressLookupTables ?? client.addressLookupTables),\n ...leg.lookupTables,\n },\n computeUnitLimit: input.computeUnitLimit ?? computeUnitsWithRoute(BUY_PACK_COMPUTE_UNITS, leg),\n ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }),\n });\n } catch (cause) {\n throw routeSizeHint(cause, leg);\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. The quote leg: wrap SOL for a WSOL pool, create the quote account for another quote, or swap\n * SOL into the quote token when `payWith: 'sol'` on a non-SOL pool.\n * 3. `initialize_pool`, with the LaunchLab buy accounts as `remainingAccounts`.\n * 4. Close the WSOL account, on a WSOL pool only. Whatever the seed did not spend comes back as SOL.\n *\n * The seed is bought in the pool's quote token, so step 2 is not optional: `initialize_pool`\n * measures the creator's quote balance before and after the seed buy, and the buy cannot spend what\n * the account does not hold.\n *\n * Closing in step 4 also unwraps any WSOL the creator already held. See `tx/wsol.ts`.\n *\n * # The quote and the raise\n *\n * A machine is priced in one quote asset, fixed for its whole life. It defaults to wrapped SOL.\n * Any other quote Raydium enabled on LaunchLab works: pass `quote: { mint }`, and the SDK reads\n * Raydium's own global config for that mint to prove it and to price the curve.\n *\n * `raise` is `total_quote_fund_raising`, in the quote's own base units. A WSOL pool has it pinned\n * by the program, so the SDK supplies 85 SOL on mainnet and 3 SOL on devnet and refuses a different\n * value. Any other quote has no default: 3,000,000,000 means three SOL and three thousand USDC, so\n * the caller has to say. LaunchLab checks the number against `min_quote_fund_raising` in the\n * quote's own config, and this checks it too, before anything is built.\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 { Address, Instruction, TransactionSigner } from '@solana/kit';\n\nimport { CREATE_MACHINE_COMPUTE_UNITS } from '../compute';\nimport { getInitializePoolInstructionAsync } from '../generated/instructions/initializePool';\nimport { PACK_TOKENS } from '../ids';\nimport { DEFAULT_TIERS, seedTokens, validatePack, validateTiers, type Tier } from '../math';\nimport { LAUNCH_TOTAL_BASE_SELL, WSOL_MINT, raydiumIds, type RaydiumIds } from '../raydium/ids';\nimport { getLaunchInstruction } from '../raydium/launch';\nimport { launchlabBuyAccounts } from '../raydium/accounts';\nimport { curveBuyExactOut } from '../raydium/curve';\nimport { fetchQuoteAsset, type QuoteAsset } from '../raydium/quote';\nimport { fetchCurveSettings, newCurveReserves, quoteAccountFor } from '../raydium/venue';\nimport {\n ata,\n creatorFeeVaultAddress,\n launchlabPoolAddress,\n launchlabVaultAddress,\n platformFeeVaultAddress,\n} from '../raydium/pdas';\nimport { poolAddress, vaultAddress } from '../pdas';\nimport type { GaboxClient } from '../rpc';\nimport { buildMessage, withRemainingAccounts, type BuildOptions } from './message';\nimport { solPriceOf } from '../route/leg';\nimport { computeUnitsWithRoute, quoteLegIn, routeSizeHint, type PayWith } from './quoteLeg';\n\n/** Which quote asset a new machine is priced in. Defaults to wrapped SOL. */\nexport type QuoteChoice = { mint: Address };\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 /** The quote asset the machine is priced in. Defaults to wrapped SOL. */\n quote?: QuoteChoice;\n /**\n * `total_quote_fund_raising`, in the quote's own base units. Required for a quote other than\n * wrapped SOL; a WSOL pool uses the raise the program pins for this cluster.\n */\n raise?: bigint;\n /**\n * Pay for the seed in SOL through a swap, or in the quote token the creator already holds.\n * Defaults to `'sol'`. A WSOL pool ignores it: its quote token is SOL.\n */\n payWith?: PayWith;\n /**\n * Seed slippage cap in the quote token, for `mandatory + extraSeedTokens` together. The\n * transaction puts this much of the quote token in the creator's quote account before the buy, so\n * it must cover the real cost. Anything left over stays there, or comes back as SOL on a WSOL\n * pool.\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 the quote's LaunchLab config, the quote mint, and the Gabox platform config, because the\n * seed price and every quote-side account depend on them. 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 { 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 quote = await fetchQuoteAsset(client, input.quote?.mint ?? WSOL_MINT, ids);\n const raise = resolveRaise(client, quote, input.raise, ids);\n\n const create = await getLaunchInstruction(\n {\n mint: mintKeypair,\n creator,\n name,\n symbol,\n uri,\n quoteMint: quote.mint,\n quoteConfig: quote.config,\n quoteTokenProgram: quote.tokenProgram,\n raise,\n },\n ids,\n );\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, quote.mint);\n const userQuoteToken = await quoteAccountFor(creator.address, quote.mint, quote.tokenProgram);\n const venueAccounts = launchlabBuyAccounts({\n launchlab: ids.launchlab,\n launchlabAuthority: ids.launchlabAuthority,\n launchlabEventAuthority: ids.launchlabEventAuthority,\n globalConfig: quote.config,\n platformConfig: ids.gaboxPlatform,\n poolState,\n mint,\n quoteMint: quote.mint,\n baseVault: await launchlabVaultAddress(ids.launchlab, poolState, mint),\n quoteVault: await launchlabVaultAddress(ids.launchlab, poolState, quote.mint),\n user: creator.address,\n userBaseToken: await ata(creator.address, mint),\n userQuoteToken,\n quoteTokenProgram: quote.tokenProgram,\n platformFeeVault: await platformFeeVaultAddress(ids.launchlab, ids.gaboxPlatform, quote.mint),\n creatorFeeVault: await creatorFeeVaultAddress(ids.launchlab, creator.address, quote.mint),\n });\n\n const initialize = await getInitializePoolInstructionAsync({\n creator,\n mint,\n quoteMint: quote.mint,\n quoteConfig: quote.config,\n quoteTokenProgram: quote.tokenProgram,\n venue: ids.launchlab,\n tiers,\n maxSeedQuoteIn,\n maxSeedNativeDebit,\n extraSeedTokens,\n });\n\n const leg = await quoteLegIn(client, {\n venue: { quoteMint: quote.mint, quoteTokenProgram: quote.tokenProgram, userQuoteToken },\n payer: creator,\n maxQuoteIn: maxSeedQuoteIn,\n // A 1x table needs no seed, so there is nothing to swap for. The quote account is still\n // created, because `initialize_pool` reads it either way.\n payWith: seed === 0n ? 'quote' : (input.payWith ?? 'sol'),\n gaboxAccounts: [\n await poolAddress(mint),\n await vaultAddress(mint),\n await ata(creator.address, mint),\n ],\n });\n\n const instructions: Instruction[] = [\n create,\n ...leg.before,\n withRemainingAccounts(initialize as Instruction, venueAccounts),\n ...leg.after,\n ];\n\n try {\n return await buildMessage(client, creator, instructions, {\n addressLookupTables: {\n ...(input.addressLookupTables ?? client.addressLookupTables),\n ...leg.lookupTables,\n },\n computeUnitLimit: input.computeUnitLimit ?? computeUnitsWithRoute(CREATE_MACHINE_COMPUTE_UNITS, leg),\n ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }),\n });\n } catch (cause) {\n throw routeSizeHint(cause, leg);\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 the quote token's base units, Raydium's fees included. */\n quoteAmount: bigint;\n /** The quote asset the machine would be priced in. */\n quoteMint: Address;\n quoteDecimals: number;\n /** The symbol Metaplex or Token-2022 records for the quote mint, when it has one. */\n quoteSymbol: string | null;\n /** `total_quote_fund_raising` the launch would use, in the quote's base units. */\n raise: bigint;\n /**\n * What `quoteAmount` costs in SOL through the client's route provider, or `null` when there is\n * no provider or no route. Equal to `quoteAmount` on a WSOL pool.\n */\n solAmount: bigint | null;\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 launch shape and the raise. Nothing trades on the curve before `initialize_pool` runs in the\n * same transaction, so this is exact up to a change in Raydium's fee rates between the read and the\n * send.\n *\n * `solAmount` is the same cost in SOL, priced through the client's route provider. It is `null`\n * when the client has no provider, or when no route exists: a devnet client has none unless the\n * caller passes `raydiumCpmmRoute(pool)`.\n *\n * Defaults to `DEFAULT_TIERS`, wrapped SOL and no extra seed. Throws if `tiers` fails\n * `validateTiers`/`validatePack`, if `extraSeedTokens` is negative, if the total seed is bigger\n * than the curve sells, or if the raise is missing or below what LaunchLab accepts.\n */\nexport async function seedCostEstimate(\n client: GaboxClient,\n tiers: readonly Readonly<Tier>[] = DEFAULT_TIERS,\n options: { extraSeedTokens?: bigint; quote?: QuoteChoice; raise?: 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 quote = await fetchQuoteAsset(client, options.quote?.mint ?? WSOL_MINT, ids);\n const raise = resolveRaise(client, quote, options.raise, ids);\n const settings = await fetchCurveSettings(client, quote.config, ids);\n const quoteAmount =\n seed === 0n\n ? 0n\n : curveBuyExactOut(newCurveReserves(raise, settings.migrateFee), settings.rates, seed);\n\n return {\n tiers: copiedTiers,\n seedTokens: mandatorySeed,\n extraSeedTokens,\n totalSeedTokens: seed,\n quoteAmount,\n quoteMint: quote.mint,\n quoteDecimals: quote.decimals,\n quoteSymbol: quote.symbol,\n raise,\n solAmount: await solPriceOf(client, quote.mint, quoteAmount),\n };\n}\n\n/**\n * The raise a launch uses, checked before anything is built.\n *\n * The program pins it for a WSOL pool, so a different value there is a launch that would be\n * refused on chain. Any other quote has no default and no pin: the caller names it, and LaunchLab's\n * own minimum for that quote is the floor.\n */\nfunction resolveRaise(\n client: GaboxClient,\n quote: QuoteAsset,\n raise: bigint | undefined,\n ids: RaydiumIds,\n): bigint {\n if (quote.mint === WSOL_MINT) {\n if (raise !== undefined && raise !== ids.launchQuoteRaise) {\n throw new Error(\n `a WSOL pool raises exactly ${ids.launchQuoteRaise} lamports on ${client.cluster}; the ` +\n `program refuses ${raise}. Leave \\`raise\\` out, or pick another quote asset.`,\n );\n }\n return ids.launchQuoteRaise;\n }\n if (raise === undefined) {\n throw new Error(\n `a pool quoted in ${quote.mint} needs a \\`raise\\`, in that token's base units. There is no ` +\n 'default, because the same number means a different amount in every token.',\n );\n }\n if (raise < quote.minQuoteFundRaising) {\n throw new Error(\n `LaunchLab takes at least ${quote.minQuoteFundRaising} base units of ${quote.mint} as a ` +\n `raise, and this launch asks for ${raise}`,\n );\n }\n return raise;\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\n * the venue's own floor, in the pool's quote token, and the program checks it before it returns.\n *\n * What goes around the sale follows the pool's quote asset:\n *\n * - **A WSOL pool.** Create the seller's WSOL account, sell, close it. The proceeds land in the\n * wallet as SOL.\n * - **Another quote, `receive: 'sol'` (the default).** Sell, then swap `minQuoteOutput` of the\n * proceeds into SOL in the same transaction. Anything the venue paid above that floor stays in\n * the seller's quote account.\n * - **Another quote, `receive: 'quote'`.** Sell and stop. The proceeds stay in the quote token.\n *\n * Closing a WSOL account also unwraps any WSOL the wallet 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 { associatedTokenAddress, poolAddress, vaultAddress } from '../pdas';\nimport { resolveVenue, type VenueKind } from '../raydium/venue';\nimport type { GaboxClient } from '../rpc';\nimport { buildMessage, withRemainingAccounts, type BuildOptions } from './message';\nimport { computeUnitsWithRoute, quoteLegOut, routeSizeHint, type Receive } from './quoteLeg';\n\nexport type SellTokensInput = {\n mint: Address;\n seller: TransactionSigner;\n amount: bigint;\n /** The venue's own floor on the quote token 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 /**\n * Take the proceeds as SOL through a swap, or keep them in the quote token. Defaults to `'sol'`.\n * A WSOL pool ignores it: its quote token is SOL.\n */\n receive?: Receive;\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 quote: {\n mint: pool.quoteMint,\n config: pool.quoteConfig,\n tokenProgram: pool.quoteTokenProgram,\n },\n ...(input.venue ? { venue: input.venue } : {}),\n });\n\n const gaboxPool = await poolAddress(input.mint);\n const sell = await getSellTokensInstructionAsync({\n seller: input.seller,\n pool: gaboxPool,\n mint: input.mint,\n quoteMint: pool.quoteMint,\n venue: venue.program,\n quoteTokenProgram: pool.quoteTokenProgram,\n amount: input.amount,\n minQuoteOutput: input.minQuoteOutput,\n maxNativeDebit: input.maxNativeDebit,\n });\n\n const leg = await quoteLegOut(client, {\n venue,\n seller: input.seller,\n minQuoteOutput: input.minQuoteOutput,\n receive: input.receive ?? 'sol',\n gaboxAccounts: [\n gaboxPool,\n await vaultAddress(input.mint),\n await associatedTokenAddress(input.seller.address, input.mint),\n ],\n });\n\n const instructions: Instruction[] = [\n ...leg.before,\n withRemainingAccounts(sell as Instruction, venue.sellAccounts),\n ...leg.after,\n ];\n\n try {\n return await buildMessage(client, input.seller, instructions, {\n addressLookupTables: {\n ...(input.addressLookupTables ?? client.addressLookupTables),\n ...leg.lookupTables,\n },\n computeUnitLimit: input.computeUnitLimit ?? computeUnitsWithRoute(REDEEM_COMPUTE_UNITS, leg),\n ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }),\n });\n } catch (cause) {\n throw routeSizeHint(cause, leg);\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":";;;;;;;;AAmBA,MAAM,MAAM,iBAAiB;AAC7B,MAAM,UAAU,GAAe,MAAmC,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,GAAG,MAAM,EAAE,OAAO,CAAC;AACtH,SAAgB,YAAY,MAAqC;CAC/D,IAAI,OAAO,MAAM,gCAAgC,GAAG,OAAO;EAAE,MAAM;EAAe,MAAM,2BAA2B,CAAC,CAAC,OAAO,IAAI;CAAE;CAClI,IAAI,OAAO,MAAM,iCAAiC,GAAG,OAAO;EAAE,MAAM;EAAgB,MAAM,4BAA4B,CAAC,CAAC,OAAO,IAAI;CAAE;CACrI,IAAI,OAAO,MAAM,+BAA+B,GAAG,OAAO;EAAE,MAAM;EAAc,MAAM,0BAA0B,CAAC,CAAC,OAAO,IAAI;CAAE;CAC/H,IAAI,OAAO,MAAM,sCAAsC,GAAG,OAAO;EAAE,MAAM;EAAqB,MAAM,iCAAiC,CAAC,CAAC,OAAO,IAAI;CAAE;CACpJ,IAAI,OAAO,MAAM,iCAAiC,GAAG,OAAO;EAAE,MAAM;EAAgB,MAAM,4BAA4B,CAAC,CAAC,OAAO,IAAI;CAAE;CACrI,IAAI,OAAO,MAAM,+BAA+B,GAAG,OAAO;EAAE,MAAM;EAAc,MAAM,0BAA0B,CAAC,CAAC,OAAO,IAAI;CAAE;CAC/H,OAAO;AACT;AAEA,MAAM,SAAS;AACf,MAAM,SAAS,IAAI,OAAO,aAAa,OAAO,uBAAuB;AACrE,MAAM,UAAU,IAAI,OAAO,aAAa,OAAO,WAAW;AAC1D,MAAM,SAAS,IAAI,OAAO,aAAa,OAAO,cAAc;;;;;;AAO5D,SAAgB,aAAa,MAAuC;CAClE,MAAM,YAA0B,CAAC;CACjC,MAAM,QAAsB,CAAC;CAC7B,MAAM,0BAA0B;EAAE,MAAM,SAAS;CAAG;CACpD,IAAI,YAAY;CAChB,IAAI,oBAAoB;CACxB,KAAK,MAAM,QAAQ,MAAM;EACvB,MAAM,SAAS,OAAO,KAAK,IAAI;EAC/B,IAAI,QAAQ;GAEV,IADc,OAAO,OAAO,EACpB,MAAM,MAAM,SAAS,GAAG;IAAE,YAAY;IAAM,kBAAkB;IAAG;GAAU;GACnF,MAAM,KAAK;IAAE,WAAW,OAAO;IAAK,SAAS,CAAC;GAAE,CAAC;GACjD;EACF;EACA,MAAM,UAAU,QAAQ,KAAK,IAAI;EACjC,MAAM,SAAS,OAAO,KAAK,IAAI;EAC/B,IAAI,WAAW,QAAQ;GACrB,MAAM,aAAa,WAAW,OAAA,CAAS;GACvC,MAAM,QAAQ,MAAM,GAAG,EAAE;GACzB,IAAI,CAAC,SAAS,MAAM,cAAc,WAAW;IAAE,YAAY;IAAM,kBAAkB;IAAG;GAAU;GAChG,MAAM,IAAI;GACV,IAAI,SAAS;IACX,MAAM,SAAS,MAAM,GAAG,EAAE;IAC1B,IAAI,QAAQ,OAAO,QAAQ,KAAK,GAAG,MAAM,OAAO;SAC3C,UAAU,KAAK,GAAG,MAAM,OAAO;GACtC;GAGA,IAAI,UAAU,MAAM,WAAW,GAAG,oBAAoB;GACtD;EACF;EACA,MAAM,QAAQ,MAAM,GAAG,EAAE;EACzB,IAAI,CAAC,KAAK,WAAW,gBAAgB,KAAK,OAAO,cAAc,kBAAkB;EACjF,IAAI;GACF,MAAM,QAAQ,YAAY,IAAI,WAAW,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;GAC3E,IAAI,OAAO,MAAM,QAAQ,KAAK,KAAK;EACrC,QAAQ,CAA2C;CACrD;CAGA,OAAO,aAAa,qBAAqB,MAAM,WAAW,IAAI,CAAC,IAAI;AACrE;AACA,eAAsB,YAAY,QAAqB,WAA0C;CAAE,OAAO,MAAM,WAAW,OAAO,KAAK,SAAS;AAAG;AACnJ,eAAe,WAAW,KAAe,WAA0C;CACjF,MAAM,KAAK,MAAM,IAAI,eAAe,WAAoB;EAAE,YAAY;EAAa,UAAU;EAAQ,gCAAgC;CAAE,CAAC,CAAC,CAAC,KAAK;CAC/I,MAAM,OAAO,IAAI;CACjB,IAAI,CAAC,MAAM,CAAC,QAAQ,KAAK,KAAK,OAAO,CAAC;CACtC,OAAO,aAAa,KAAK,eAAe,CAAC,CAAC;AAC5C;;AAGA,eAAsB,iBAAiB,QAAqB,SAAgD;CAI1G,IAAI;CACJ,KAAK,IAAI,OAAO,GAAG,OAAO,IAAI,QAAQ;EACpC,MAAM,OAAO,MAAM,OAAO,IAAI,wBAAwB,SAAS;GAC7D,YAAY;GAAa,OAAO;GAAK,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;EAClE,CAAC,CAAC,CAAC,KAAK;EACR,KAAK,MAAM,OAAO,MAAM;GACtB,IAAI,IAAI,KAAK;GACb,KAAK,MAAM,SAAS,MAAM,WAAW,OAAO,KAAK,IAAI,SAAS,GAAG;IAC/D,IAAI,MAAM,SAAS,gBAAgB;IAGnC,IAAI,MAAM,YAAY,MAAM,KAAK,MAAM,MAAM,KAAK,GAAG,MAAM,SAAS,OAAO;KAAE,GAAG,MAAM;KAAM;IAAQ;GACtG;EACF;EACA,IAAI,KAAK,SAAS,KAAK,OAAO;EAC9B,SAAS,KAAK,GAAG,EAAE,CAAC,EAAE;EACtB,IAAI,CAAC,QAAQ,OAAO;CACtB;CACA,OAAO;AACT;;;;;;;;AC1GA,MAAa,8BAA8B,QAAQ,8CAA8C;AACjG,MAAa,gCAAoD;CAC/D,QAAQ,8CAA8C;CACtD,QAAQ,6CAA6C;CACrD,QAAQ,6CAA6C;CACrD,QAAQ,8CAA8C;CACtD,QAAQ,6CAA6C;CACrD,QAAQ,6CAA6C;CACrD,QAAQ,6CAA6C;CACrD,QAAQ,kCAAkC;CAC1C,QAAQ,6CAA6C;CACrD,QAAQ,6CAA6C;CACrD,QAAQ,6CAA6C;CACrD,QAAQ,8CAA8C;CACtD,QAAQ,6CAA6C;CACrD,QAAQ,6CAA6C;CACrD,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,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,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,6CAA6C;CACrD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/events.ts","../src/lookupTables.ts","../src/route/leg.ts","../src/offer.ts","../src/route/cpmm.ts","../src/route/jupiter.ts","../src/rpc.ts","../src/tx/wsol.ts","../src/tx/quoteLeg.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":["/** 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-18T11:04:06.369Z.\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, getAddressDecoder, type Address, type AddressesByLookupTableAddress } from '@solana/kit';\n\nimport type { Cluster, GaboxClient } 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 address('USDCoctVLVnvTXBEuP9s8hntucdJokbo17RwHuNXemT'),\n address('4wHbNkobu7iARU9MbCEqDSAq6JuQreGupG2Jsf2R3DFP'),\n address('5Eu2G2USTy1pqphmQzQ2SBXWrBq5sdhgEh7hso9R2xix'),\n address('A9qBhPy4k5UYW72hSgAkh1Epr2do69P54yzzcMV3yv6b'),\n address('Aw93pmXP52u6WSW2HcafRxua1LDht5MZhhXaaR7qCjsN'),\n address('CPLUA2NTYSGjsB1E9iXT3MrPn69WRFJvKTdJZw5NdEjh'),\n address('7LnqjXdqJEdccWZQs5YJobQ8MDmcK4sG2oo4Ty4LBC8c'),\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/** The address lookup table program. It owns every table account. */\nconst LOOKUP_TABLE_PROGRAM = address('AddressLookupTab1e1111111111111111111111111');\n\n/**\n * The fixed part of a table account, before its addresses: a 4-byte discriminator, the two slot\n * fields, the start index, the optional authority, and two padding bytes.\n */\nconst LOOKUP_TABLE_HEADER = 56;\n\n/**\n * Read lookup tables off chain by address, for compressing against tables this SDK does not pin.\n *\n * A router picks its own tables per quote, so their contents are only known at run time, and a\n * message can only be compressed against a table whose addresses are loaded. An address with no\n * account, a wrong owner, or a malformed body is skipped rather than failing the whole route: the\n * message then carries those accounts in full, which is correct, only larger.\n */\nexport async function fetchAddressLookupTables(\n client: GaboxClient,\n addresses: Address[],\n): Promise<AddressesByLookupTableAddress> {\n const wanted = [...new Set(addresses)];\n if (wanted.length === 0) return {};\n\n const { value } = await client.rpc\n .getMultipleAccounts(wanted, { encoding: 'base64', commitment: 'confirmed' })\n .send();\n\n const decoder = getAddressDecoder();\n const tables: AddressesByLookupTableAddress = {};\n for (const [index, account] of value.entries()) {\n if (!account || account.owner !== LOOKUP_TABLE_PROGRAM) continue;\n const data = Buffer.from(account.data[0], 'base64');\n const body = data.length - LOOKUP_TABLE_HEADER;\n if (body <= 0 || body % 32 !== 0) continue;\n const stored: Address[] = [];\n for (let at = LOOKUP_TABLE_HEADER; at < data.length; at += 32) {\n stored.push(decoder.decode(new Uint8Array(data.subarray(at, at + 32))));\n }\n tables[wanted[index]!] = stored;\n }\n return tables;\n}\n","/**\n * Turning a route provider into the one swap leg a Gabox transaction needs.\n *\n * Two directions, and they are not symmetric:\n *\n * - **Paying in SOL.** The pack costs an exact amount of the quote token, so `routeQuoteIn` asks\n * for exact-out first. When the pair has no exact-out route it falls back to exact-in, working\n * out the SOL that buys the amount at the exact-in price and adding a margin.\n * - **Receiving SOL.** A sale pays the quote token in, and the seller wants SOL out. The amount\n * is already known, so `routeQuoteOut` is a plain exact-in swap.\n *\n * # Why the leg is checked before it is used\n *\n * A route is built by code outside this SDK. Its instructions go into the same transaction as\n * `buy_pack`, which means they run with the buyer's signature. So two things are checked before\n * any route is composed:\n *\n * 1. no instruction may name a Gabox account or the Gabox program itself, so a route can never\n * touch a pool, a vault, a draw or the activity account;\n * 2. the swap has to name the user's own quote associated token account, which is the account\n * the program binds and measures the quote delta in. A swap that paid somewhere else would\n * leave the buy short.\n */\n\nimport type { Address } from '@solana/kit';\n\nimport type { GaboxClient } from '../rpc';\nimport { WSOL_MINT } from '../raydium/ids';\nimport type { Route, RouteProvider } from './types';\n\n/**\n * The margin added to an exact-in fallback, in basis points.\n *\n * An exact-in quote prices one spend. The spend that buys the amount wanted is worked out from that\n * price, and the price moves against a larger spend, so the result is always a little short without\n * a margin. 1% is the same order as the slippage a caller already signs for on the pack itself.\n */\nexport const EXACT_IN_MARGIN_BPS = 100n;\n\n/**\n * The first exact-in quote's size, in lamports, when a pair has no exact-out route.\n *\n * It exists only to learn a price, so it is small enough that its own impact on the route is\n * small, and large enough that a route quotes it at all. The real spend is worked out from the\n * price it returns and re-quoted.\n */\nconst PROBE_LAMPORTS = 100_000_000n;\n\n/** How many times the exact-in fallback re-quotes before it gives up. */\nconst EXACT_IN_ATTEMPTS = 3;\n\n/**\n * A swap that leaves at least `amount` of `quoteMint` in the user's quote account, paid for in SOL.\n *\n * Exact-out when the pair has such a route, so the buyer spends only what the pack costs. Exact-in\n * otherwise, which overshoots on purpose: the leftover quote stays in the buyer's own account.\n */\nexport async function routeQuoteIn(\n client: GaboxClient,\n provider: RouteProvider,\n input: { quoteMint: Address; amount: bigint; user: Address },\n): Promise<Route> {\n const { quoteMint, amount, user } = input;\n if (amount <= 0n) throw new Error('the quote amount to buy must be positive');\n if (quoteMint === WSOL_MINT) {\n throw new Error('a WSOL-quoted pool needs no route: the builders wrap SOL themselves');\n }\n\n try {\n const route = await provider.exactOut(client, WSOL_MINT, quoteMint, amount, user);\n if (route.outAmount < amount) {\n throw new Error(\n `the exact-out route buys ${route.outAmount} of ${quoteMint}, which is below the ` +\n `${amount} the pack costs`,\n );\n }\n return route;\n } catch (exactOutFailure) {\n return await exactInFallback(client, provider, quoteMint, amount, user, exactOutFailure);\n }\n}\n\n/**\n * Work out the SOL that buys `amount` of the quote at the exact-in price, then swap it.\n *\n * The first quote is a small probe, only to learn a price. Every later quote scales the last one by\n * what it actually returned, so an impact the probe did not show is corrected rather than guessed\n * at. Three quotes at most, and a route that still falls short is an error rather than a buy that\n * fails on chain.\n */\nasync function exactInFallback(\n client: GaboxClient,\n provider: RouteProvider,\n quoteMint: Address,\n amount: bigint,\n user: Address,\n exactOutFailure: unknown,\n): Promise<Route> {\n let spend = PROBE_LAMPORTS;\n let last: Route | undefined;\n for (let attempt = 0; attempt < EXACT_IN_ATTEMPTS; attempt++) {\n let route: Route;\n try {\n route = await provider.exactIn(client, WSOL_MINT, quoteMint, spend, user);\n } catch (exactInFailure) {\n throw new Error(\n `no route from SOL to ${quoteMint}. Exact-out failed with ` +\n `\"${messageOf(exactOutFailure)}\" and exact-in with \"${messageOf(exactInFailure)}\".`,\n );\n }\n last = route;\n if (route.outAmount >= amount) return route;\n if (route.outAmount <= 0n) break;\n // Scale the spend by what this quote actually returned, then add the margin.\n const scaled = ceilDiv(route.inAmount * amount, route.outAmount);\n const next = scaled + (scaled * EXACT_IN_MARGIN_BPS) / 10_000n;\n if (next <= spend) break;\n spend = next;\n }\n throw new Error(\n `no route from SOL to ${quoteMint} buys ${amount}. The best exact-in quote returned ` +\n `${last?.outAmount ?? 0n} for ${last?.inAmount ?? spend} lamports, and exact-out failed ` +\n `with \"${messageOf(exactOutFailure)}\".`,\n );\n}\n\n/**\n * A swap that turns exactly `amount` of `quoteMint` into SOL.\n *\n * `sellTokens` uses it on the proceeds floor it already signs for, so the amount swapped is one the\n * sale is guaranteed to have produced. Anything the sale paid above that floor stays in the\n * seller's quote account.\n */\nexport async function routeQuoteOut(\n client: GaboxClient,\n provider: RouteProvider,\n input: { quoteMint: Address; amount: bigint; user: Address },\n): Promise<Route> {\n const { quoteMint, amount, user } = input;\n if (amount <= 0n) throw new Error('the quote amount to sell must be positive');\n if (quoteMint === WSOL_MINT) {\n throw new Error('a WSOL-quoted pool needs no route: the builders unwrap SOL themselves');\n }\n return await provider.exactIn(client, quoteMint, WSOL_MINT, amount, user);\n}\n\n/**\n * Refuse a route that would touch Gabox state, or that does not settle in the account the program\n * binds.\n *\n * `forbidden` is every Gabox account the transaction itself uses, plus the Gabox program id.\n * `settlesIn` is the user's quote associated token account: the swap has to name it, because that\n * is where `buy_pack` measures the quote it spends and where `sell_tokens` measures the proceeds.\n */\nexport function assertRouteIsSafe(\n route: Route,\n expect: { forbidden: readonly Address[]; settlesIn: Address },\n): void {\n const forbidden = new Set<Address>(expect.forbidden);\n let settles = false;\n for (const instruction of route.instructions) {\n if (forbidden.has(instruction.programAddress as Address)) {\n throw new Error(\n `the route calls ${instruction.programAddress}, which is a Gabox program or account. A ` +\n 'route must never touch Gabox state.',\n );\n }\n for (const account of instruction.accounts ?? []) {\n if (forbidden.has(account.address)) {\n throw new Error(\n `the route names the Gabox account ${account.address}. A route must never touch Gabox ` +\n 'state.',\n );\n }\n if (account.address === expect.settlesIn) settles = true;\n }\n }\n if (!settles) {\n throw new Error(\n `the route never names ${expect.settlesIn}, the quote account the program settles in. The ` +\n 'swap would pay somewhere the buy cannot spend from.',\n );\n }\n}\n\n/**\n * What `amount` of a quote token costs in SOL, through the client's route provider.\n *\n * `null` when the client has no provider, or when the provider has no exact-out route. A price is a\n * display, so a missing one is not an error. A WSOL amount is already SOL and comes back unchanged.\n *\n * No fallback to exact-in here on purpose: an exact-in price answers a different question, and a\n * display that silently swapped the two would be wrong rather than missing.\n */\nexport async function solPriceOf(\n client: GaboxClient,\n quoteMint: Address,\n amount: bigint,\n): Promise<bigint | null> {\n if (quoteMint === WSOL_MINT) return amount;\n if (!client.route || amount <= 0n) return null;\n try {\n // The route is priced, never built, so any address gives a valid quote.\n const route = await client.route.exactOut(client, WSOL_MINT, quoteMint, amount, quoteMint);\n return route.inAmount;\n } catch {\n return null;\n }\n}\n\n/** `ceil(numerator / denominator)` for non-negative values. */\nfunction ceilDiv(numerator: bigint, denominator: bigint): bigint {\n return (numerator + denominator - 1n) / denominator;\n}\n\nconst messageOf = (cause: unknown): string =>\n cause instanceof Error ? cause.message : String(cause);\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 * `quoteAmount` is in the pool's own quote token, which is not always SOL. `solAmount` is the same\n * price in SOL, priced through the client's route provider: the exact-out cost of buying\n * `quoteAmount` of the quote token. It is `null` when the client has no provider or the pair has no\n * route, because a price is a display and a missing one is not an error.\n *\n * Nothing here is an estimate of cash value. Every number is tokens or base units.\n */\n\nimport type { Address } from '@solana/kit';\n\nimport { fetchPoolInventory, tiersOf, type PoolInventory } from './accounts';\nimport { fetchQuoteDisplay } from './raydium/quote';\nimport { solPriceOf } from './route/leg';\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 /** The pool's quote asset. Both venues settle in it; there is no native-SOL path. */\n quoteMint: Address;\n /** The quote mint's decimals, so `quoteAmount` can be shown as a number. */\n quoteDecimals: number;\n /** The quote mint's symbol, from Metaplex or Token-2022 metadata. `null` when it has none. */\n quoteSymbol: string | null;\n /**\n * The same pack price in lamports, through the client's route provider. Equal to `quoteAmount` on\n * a WSOL pool, and `null` when no route can price it.\n */\n solAmount: bigint | null;\n /** What the seed cost the creator at creation, in the quote token. 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. Three round trips: the pool and its vault, the venue, then the\n * quote mint and its metadata. A non-SOL pool adds one HTTP call to the route provider for\n * `solAmount`.\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 const { pool } = inventory;\n\n const venue = await resolveVenue(client, {\n mint,\n user: options.user ?? pool.creator,\n quote: {\n mint: pool.quoteMint,\n config: pool.quoteConfig,\n tokenProgram: pool.quoteTokenProgram,\n },\n ...(options.venue ? { venue: options.venue } : {}),\n });\n\n const quoteAmount = venue.quoteBuy(pool.packTokens);\n const display = await fetchQuoteDisplay(client, pool.quoteMint);\n return offerFromState(inventory, venue.kind, quoteAmount, {\n quoteDecimals: display.decimals,\n quoteSymbol: display.symbol,\n solAmount: await solPriceOf(client, pool.quoteMint, quoteAmount),\n });\n}\n\n/** The three display fields `getOffer` reads separately from the price. */\nexport type QuoteDisplayFields = {\n quoteDecimals: number;\n quoteSymbol: string | null;\n solAmount: bigint | null;\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 *\n * `display` is optional: a caller that only wants the prize numbers can leave it out, and the three\n * display fields then report the quote's own base units with no symbol and no SOL price.\n */\nexport function offerFromState(\n inventory: PoolInventory,\n venue: VenueKind,\n quoteAmount: bigint,\n display: QuoteDisplayFields = { quoteDecimals: 0, quoteSymbol: null, solAmount: null },\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 quoteDecimals: display.quoteDecimals,\n quoteSymbol: display.quoteSymbol,\n solAmount: display.solAmount,\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 * A route provider backed by one Raydium CPMM pool.\n *\n * Jupiter does not serve devnet, so a devnet machine quoted in a test token needs a route this SDK\n * can build itself. Given a CPMM pool that holds the SOL/quote pair, this provider swaps through\n * it with the same two instructions Gabox already forwards for a graduated coin, priced with the\n * same bigint port of Raydium's math.\n *\n * It works anywhere such a pool exists, mainnet included. It is not a router: it uses the one pool\n * the caller names and nothing else.\n *\n * # Wrapping\n *\n * CPMM settles in WSOL, never in native SOL. So the route wraps the SOL it spends and closes the\n * WSOL account afterwards, exactly as Jupiter's `wrapAndUnwrapSol` does. A sale into SOL creates\n * the WSOL account, swaps into it, and closes it, which is what turns the proceeds into SOL.\n *\n * # No signer objects\n *\n * The user is an address, not a signer. Every signing slot is marked as a signer and left for the\n * fee payer to sign, the same way a Jupiter instruction arrives. The wallet paying for the Gabox\n * transaction is the same wallet, so its one signature covers all of them.\n *\n * That is not a shortcut, it is required. Kit refuses to sign a message that carries two distinct\n * signer objects for one address: `signTransactionMessageWithSigners` fails with \"Multiple distinct\n * signers were identified for address\". The token and system builders below only accept a signer,\n * so `withoutSigners` strips the object again and keeps the role.\n */\n\nimport {\n createNoopSigner,\n getU64Encoder,\n type AccountMeta,\n type Address,\n type Instruction,\n type TransactionSigner,\n} from '@solana/kit';\nimport {\n getCloseAccountInstruction,\n getCreateAssociatedTokenIdempotentInstruction,\n getSyncNativeInstruction,\n} from '@solana-program/token';\nimport { getTransferSolInstruction } from '@solana-program/system';\n\nimport { decodeCpmmAmmConfig, decodeCpmmPool, tokenAccountAmount } from '../raydium/adapter';\nimport { CPMM_SWAP_BASE_INPUT, CPMM_SWAP_BASE_OUTPUT } from '../raydium/abi';\nimport { order } from '../raydium/accounts';\nimport {\n cpmmSwapBaseInput,\n cpmmSwapBaseOutput,\n type CpmmFeeRates,\n type CpmmSwapSides,\n} from '../raydium/curve';\nimport { WSOL_MINT, raydiumIds } from '../raydium/ids';\nimport { ata } from '../raydium/pdas';\nimport { readAccounts } from '../raydium/read';\nimport { creatorFeeOnInput } from '../raydium/venue';\nimport type { GaboxClient } from '../rpc';\nimport type { Route, RouteProvider } from './types';\n\nconst u64 = getU64Encoder();\n\n/**\n * The slippage this provider signs for on a pool swap, in basis points. 1%, the same as the\n * Jupiter provider's default. It only widens the on-chain bound; the price itself is exact.\n */\nexport const CPMM_ROUTE_SLIPPAGE_BPS = 100n;\n\n/**\n * The compute units one swap through this provider adds to a transaction.\n *\n * Measured on devnet on 2026-09-18 against one Raydium CPMM pool, as the difference from the same\n * builder with no route: `55,110` and `29,272` on `createMachine`, `21,488` and `52,980` on\n * `buyPack`, and `30,138` and `51,138` on `sellTokens`. The spread is wide because which token\n * accounts already exist changes from run to run, so this rounds up to the top of it.\n *\n * It is a safe figure here and nowhere else: this provider always uses exactly one pool. A router\n * that may pick several hops states its own number; see `JUPITER_DEFAULT_COMPUTE_UNITS`.\n */\nexport const CPMM_ROUTE_COMPUTE_UNITS = 75_000;\n\n/**\n * Swap through one named Raydium CPMM pool.\n *\n * The pool must hold the pair the route asks for. On devnet the SOL/USDC-test pool with the most\n * liquidity is `5Eu2G2USTy1pqphmQzQ2SBXWrBq5sdhgEh7hso9R2xix`, under the fee tier\n * `A9qBhPy4k5UYW72hSgAkh1Epr2do69P54yzzcMV3yv6b`.\n */\nexport function raydiumCpmmRoute(poolAddress: Address): RouteProvider {\n return {\n exactOut: async (client, input, output, amount, user) =>\n await swap(client, poolAddress, { input, output, amount, user, mode: 'exactOut' }),\n exactIn: async (client, input, output, amount, user) =>\n await swap(client, poolAddress, { input, output, amount, user, mode: 'exactIn' }),\n };\n}\n\nasync function swap(\n client: GaboxClient,\n poolAddress: Address,\n request: {\n input: Address;\n output: Address;\n amount: bigint;\n user: Address;\n mode: Route['mode'];\n },\n): Promise<Route> {\n const { input, output, amount, user, mode } = request;\n if (amount <= 0n) throw new Error('the route amount must be positive');\n const ids = raydiumIds(client.cluster);\n\n const [poolAccount] = await readAccounts(client.rpc, [poolAddress]);\n if (!poolAccount || poolAccount.owner !== ids.cpmm) {\n throw new Error(`${poolAddress} is not a Raydium CPMM pool on ${client.cluster}`);\n }\n const pool = decodeCpmmPool(poolAccount.data);\n\n const inputIsToken0 = pool.token0Mint === input;\n const holdsPair = inputIsToken0\n ? pool.token1Mint === output\n : pool.token1Mint === input && pool.token0Mint === output;\n if (!holdsPair) {\n throw new Error(\n `the CPMM pool at ${poolAddress} holds ${pool.token0Mint} and ${pool.token1Mint}, not ` +\n `${input} and ${output}`,\n );\n }\n\n const inputVault = inputIsToken0 ? pool.token0Vault : pool.token1Vault;\n const outputVault = inputIsToken0 ? pool.token1Vault : pool.token0Vault;\n const inputTokenProgram = inputIsToken0 ? pool.token0Program : pool.token1Program;\n const outputTokenProgram = inputIsToken0 ? pool.token1Program : pool.token0Program;\n\n const [configAccount, inputVaultAccount, outputVaultAccount] = await readAccounts(client.rpc, [\n pool.ammConfig,\n inputVault,\n outputVault,\n ]);\n if (!configAccount) throw new Error(`the CPMM pool at ${poolAddress} names a fee tier that is not on chain`);\n if (!inputVaultAccount || !outputVaultAccount) {\n throw new Error(`the CPMM pool at ${poolAddress} has no reserve accounts`);\n }\n const config = decodeCpmmAmmConfig(configAccount.data);\n\n // A swap may not spend what the pool already owes. Raydium subtracts the same three balances.\n const owed = (token0: boolean) =>\n token0\n ? pool.protocolFeesToken0 + pool.fundFeesToken0 + pool.creatorFeesToken0\n : pool.protocolFeesToken1 + pool.fundFeesToken1 + pool.creatorFeesToken1;\n const sides: CpmmSwapSides = {\n inputReserve: tokenAccountAmount(inputVaultAccount.data) - owed(inputIsToken0),\n outputReserve: tokenAccountAmount(outputVaultAccount.data) - owed(!inputIsToken0),\n };\n if (sides.inputReserve <= 0n || sides.outputReserve <= 0n) {\n throw new Error(`the CPMM pool at ${poolAddress} has no tradable reserves`);\n }\n const rates: CpmmFeeRates = {\n tradeFeeRate: config.tradeFeeRate,\n creatorFeeRate: pool.enableCreatorFee ? config.creatorFeeRate : 0n,\n creatorFeeOnInput: creatorFeeOnInput(pool, input),\n };\n\n const userInput = await ata(user, input, inputTokenProgram);\n const userOutput = await ata(user, output, outputTokenProgram);\n const abi = mode === 'exactOut' ? CPMM_SWAP_BASE_OUTPUT : CPMM_SWAP_BASE_INPUT;\n const accounts = order(abi, {\n payer: user,\n authority: ids.cpmmAuthority,\n amm_config: pool.ammConfig,\n pool_state: poolAddress,\n input_token_account: userInput,\n output_token_account: userOutput,\n input_vault: inputVault,\n output_vault: outputVault,\n input_token_program: inputTokenProgram,\n output_token_program: outputTokenProgram,\n input_token_mint: input,\n output_token_mint: output,\n observation_state: pool.observationKey,\n });\n\n // `swap_base_output` takes `(max_amount_in, amount_out)`; `swap_base_input` takes\n // `(amount_in, minimum_amount_out)`. The two orders are the reverse of each other.\n const exactOut = mode === 'exactOut';\n const priced = exactOut\n ? cpmmSwapBaseOutput(sides, rates, amount)\n : cpmmSwapBaseInput(sides, rates, amount);\n const inAmount = exactOut ? widen(priced) : amount;\n const outAmount = exactOut ? amount : narrow(priced);\n const swapInstruction = {\n programAddress: ids.cpmm,\n accounts,\n data: new Uint8Array([\n ...abi.discriminator,\n ...u64.encode(exactOut ? inAmount : amount),\n ...u64.encode(exactOut ? amount : outAmount),\n ]),\n } as Instruction;\n\n return {\n instructions: wrap({\n user,\n input,\n output,\n userInput,\n userOutput,\n inputTokenProgram,\n outputTokenProgram,\n lamportsIn: inAmount,\n middle: [swapInstruction],\n }),\n // The devnet lookup table already carries every Raydium address this route names.\n lookupTables: {},\n inAmount,\n outAmount,\n mode,\n computeUnits: CPMM_ROUTE_COMPUTE_UNITS,\n };\n}\n\n/** Add the slippage margin to a cost the caller signs as a maximum. */\nconst widen = (amount: bigint): bigint => amount + (amount * CPMM_ROUTE_SLIPPAGE_BPS) / 10_000n;\n/** Take the slippage margin off a payout the caller signs as a minimum. */\nconst narrow = (amount: bigint): bigint => amount - (amount * CPMM_ROUTE_SLIPPAGE_BPS) / 10_000n;\n\n/**\n * Create the two token accounts the swap needs, wrap the SOL it spends, and close the WSOL account\n * afterwards.\n *\n * Only one side is ever WSOL here: a Gabox pool quoted in WSOL never uses a route at all.\n */\nfunction wrap(input: {\n user: Address;\n input: Address;\n output: Address;\n userInput: Address;\n userOutput: Address;\n inputTokenProgram: Address;\n outputTokenProgram: Address;\n lamportsIn: bigint;\n middle: Instruction[];\n}): Instruction[] {\n // A placeholder, only so the builders below mark their signing slots. `withoutSigners` removes\n // the object again before the instruction leaves this file.\n const payer = createNoopSigner(input.user);\n const createAta = (account: Address, mint: Address, tokenProgram: Address): Instruction =>\n withoutSigners(\n getCreateAssociatedTokenIdempotentInstruction({\n payer,\n ata: account,\n owner: input.user,\n mint,\n tokenProgram,\n }) as Instruction,\n );\n\n const before: Instruction[] = [\n createAta(input.userInput, input.input, input.inputTokenProgram),\n createAta(input.userOutput, input.output, input.outputTokenProgram),\n ];\n const after: Instruction[] = [];\n\n if (input.input === WSOL_MINT) {\n before.push(\n withoutSigners(\n getTransferSolInstruction({\n source: payer,\n destination: input.userInput,\n amount: input.lamportsIn,\n }) as Instruction,\n ),\n // Without this the token account holds the lamports but still reports a zero balance.\n getSyncNativeInstruction({ account: input.userInput }) as Instruction,\n );\n after.push(closeWsol(input.userInput, payer));\n }\n if (input.output === WSOL_MINT) {\n after.push(closeWsol(input.userOutput, payer));\n }\n return [...before, ...input.middle, ...after];\n}\n\n/**\n * Close a WSOL account, sending every lamport in it back to the owner as SOL.\n *\n * The owner has to sign, so it goes in as a signer and comes out as a plain signing slot.\n */\nconst closeWsol = (account: Address, owner: TransactionSigner): Instruction =>\n withoutSigners(\n getCloseAccountInstruction({ account, destination: owner.address, owner }) as Instruction,\n );\n\n/**\n * Drop every attached signer object, keeping each account's address and role.\n *\n * A signing slot stays a signing slot: the compiled message still requires that signature, and the\n * wallet paying for the transaction provides it. What goes away is the second signer object for an\n * address the fee payer already covers, which kit refuses to sign.\n */\nfunction withoutSigners(instruction: Instruction): Instruction {\n const accounts: AccountMeta[] = (instruction.accounts ?? []).map((account) => ({\n address: account.address,\n role: account.role,\n }));\n return { ...instruction, accounts } as Instruction;\n}\n","/**\n * The Jupiter route provider.\n *\n * Jupiter is an HTTP service, not a program this SDK builds instructions for. Two calls per route:\n *\n * 1. `GET /swap/v1/quote` prices the swap and returns a quote object.\n * 2. `POST /swap/v1/swap-instructions` turns that quote into instructions.\n *\n * The response gives `setupInstructions`, `swapInstruction` and `cleanupInstruction`, each as a\n * program id, a list of accounts and base64 data. This module decodes those into kit instructions\n * and leaves everything else alone. Jupiter's own compute budget instructions are dropped: every\n * builder in this SDK sets its own budget, and two `SetComputeUnitLimit` instructions in one message\n * is one too many. Their **number** is kept, though: it is Jupiter's own answer to \"how much does\n * this route cost\", and a builder adds it to its own limit.\n *\n * `wrapAndUnwrapSol: true` is always sent, so Jupiter creates the wallet's WSOL account, funds it\n * from the wallet's lamports and closes it again inside its own instructions. That is what makes\n * \"pay in SOL\" true from the wallet's side.\n *\n * # No Jupiter package\n *\n * The public surface of this SDK is `@solana/kit` only. Nothing here imports a Jupiter package; the\n * response is plain JSON and the decoding below is a dozen lines.\n *\n * # Exact-out is not always available\n *\n * Jupiter answers `NO_ROUTES_FOUND` for an exact-out quote whenever the best route has more than\n * one hop. Verified on 2026-09-18: SOL to USDC quotes exact-out, while SOL to the stock token\n * `XsDoVfqeBukxuZHWhdvWHBhgEHjGNst4MLodqsJHzoB` only quotes exact-in. `routeQuoteIn` in `leg.ts`\n * handles that fallback; this file only reports the failure.\n */\n\nimport {\n AccountRole,\n getBase64Encoder,\n type AccountMeta,\n type Address,\n type Instruction,\n} from '@solana/kit';\n\nimport { fetchAddressLookupTables } from '../lookupTables';\nimport type { GaboxClient } from '../rpc';\nimport type { Route, RouteProvider } from './types';\n\n/** Jupiter's free endpoint. The keyed host `https://api.jup.ag/swap/v1` has the same shape. */\nexport const JUPITER_LITE_URL = 'https://lite-api.jup.ag/swap/v1';\n\n/** The slippage Jupiter prices a route with when the caller names none. 1%. */\nexport const JUPITER_DEFAULT_SLIPPAGE_BPS = 100;\n\n/**\n * The compute units a Jupiter route is assumed to need when the response carries no limit.\n *\n * Jupiter normally sends a `SetComputeUnitLimit` of its own, and that number is what this SDK uses.\n * When it does not, this is the fallback: enough for a route through several pools, and still far\n * below the 1,400,000-unit ceiling once the Gabox instruction's own budget is added. A caller who\n * knows better passes `computeUnitLimit` to the builder.\n */\nexport const JUPITER_DEFAULT_COMPUTE_UNITS = 400_000;\n\n/** `ComputeBudgetInstruction::SetComputeUnitLimit`, whose data is the tag then a u32 of units. */\nconst SET_COMPUTE_UNIT_LIMIT = 2;\n\nexport type JupiterRouteOptions = {\n /** The base URL of the swap API. Defaults to the free `lite-api` host. */\n url?: string;\n /** Slippage for the quote, in basis points. Defaults to 100, which is 1%. */\n slippageBps?: number;\n};\n\nconst base64 = getBase64Encoder();\n\n/** One account as the swap-instructions response writes it. */\ntype JupiterAccount = { pubkey: string; isSigner: boolean; isWritable: boolean };\ntype JupiterInstruction = { programId: string; accounts: JupiterAccount[]; data: string };\n\n/** The fields of a `swap-instructions` response this SDK reads. */\nexport type JupiterSwapInstructions = {\n /** Read for its unit limit only. These instructions are never copied into the message. */\n computeBudgetInstructions?: JupiterInstruction[] | null;\n setupInstructions?: JupiterInstruction[] | null;\n swapInstruction: JupiterInstruction;\n cleanupInstruction?: JupiterInstruction | null;\n addressLookupTableAddresses?: string[] | null;\n};\n\n/**\n * A route provider backed by Jupiter. Use it on mainnet, where Jupiter has the liquidity.\n *\n * It makes read-only HTTP calls and never sends a transaction: the instructions come back to the\n * caller, who signs them together with the Gabox instruction.\n */\nexport function jupiterRoute(options: JupiterRouteOptions = {}): RouteProvider {\n const url = (options.url ?? JUPITER_LITE_URL).replace(/\\/+$/, '');\n const slippageBps = options.slippageBps ?? JUPITER_DEFAULT_SLIPPAGE_BPS;\n\n const build = async (\n client: GaboxClient,\n input: Address,\n output: Address,\n amount: bigint,\n user: Address,\n swapMode: 'ExactOut' | 'ExactIn',\n ): Promise<Route> => {\n if (amount <= 0n) throw new Error('the route amount must be positive');\n const quote = await fetchQuote(url, { input, output, amount, swapMode, slippageBps });\n const response = await fetchSwapInstructions(url, quote, user);\n // `otherAmountThreshold` is the side the swap is bound to on chain: the most it will spend on\n // an exact-out route, the least it will pay out on an exact-in one. The other side is exact.\n // A `Route` states bounds, not hopes, so the threshold is what goes in it.\n const threshold = BigInt(String(quote.otherAmountThreshold));\n return await routeFrom(client, response, {\n inAmount: swapMode === 'ExactOut' ? threshold : BigInt(String(quote.inAmount)),\n outAmount: swapMode === 'ExactOut' ? BigInt(String(quote.outAmount)) : threshold,\n mode: swapMode === 'ExactOut' ? 'exactOut' : 'exactIn',\n });\n };\n\n return {\n exactOut: async (client, input, output, amount, user) =>\n await build(client, input, output, amount, user, 'ExactOut'),\n exactIn: async (client, input, output, amount, user) =>\n await build(client, input, output, amount, user, 'ExactIn'),\n };\n}\n\n/**\n * The quote object Jupiter returns. It is passed back to `swap-instructions` unchanged, so it\n * carries more fields than these three; only these are read.\n */\ntype JupiterQuote = {\n inAmount: string | number;\n outAmount: string | number;\n /** The bound the swap enforces on chain, once slippage is applied. */\n otherAmountThreshold: string | number;\n};\n\nasync function fetchQuote(\n url: string,\n input: {\n input: Address;\n output: Address;\n amount: bigint;\n swapMode: 'ExactOut' | 'ExactIn';\n slippageBps: number;\n },\n): Promise<JupiterQuote> {\n const query = new URLSearchParams({\n inputMint: input.input,\n outputMint: input.output,\n amount: input.amount.toString(),\n swapMode: input.swapMode,\n slippageBps: String(input.slippageBps),\n });\n const response = await fetch(`${url}/quote?${query.toString()}`);\n const body = (await response.json()) as JupiterQuote & { error?: string; errorCode?: string };\n if (!response.ok || body.error) {\n throw new Error(\n `Jupiter has no ${input.swapMode} route from ${input.input} to ${input.output}: ` +\n `${body.errorCode ?? response.status} ${body.error ?? ''}`.trim(),\n );\n }\n return body;\n}\n\nasync function fetchSwapInstructions(\n url: string,\n quoteResponse: JupiterQuote,\n userPublicKey: Address,\n): Promise<JupiterSwapInstructions> {\n const response = await fetch(`${url}/swap-instructions`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ quoteResponse, userPublicKey, wrapAndUnwrapSol: true }),\n });\n const body = (await response.json()) as JupiterSwapInstructions & { error?: string };\n if (!response.ok || body.error || !body.swapInstruction) {\n throw new Error(\n `Jupiter could not build the swap instructions: ${response.status} ${body.error ?? ''}`.trim(),\n );\n }\n return body;\n}\n\n/**\n * Turn a decoded `swap-instructions` response into a `Route`.\n *\n * Exported so a test can read a recorded response without making an HTTP call. The lookup tables\n * are read through the client, because the response names them by address only.\n */\nexport async function routeFrom(\n client: GaboxClient,\n response: JupiterSwapInstructions,\n amounts: { inAmount: bigint; outAmount: bigint; mode: Route['mode'] },\n): Promise<Route> {\n const instructions: Instruction[] = [\n ...(response.setupInstructions ?? []).map(toKitInstruction),\n toKitInstruction(response.swapInstruction),\n ...(response.cleanupInstruction ? [toKitInstruction(response.cleanupInstruction)] : []),\n ];\n const lookupTables = await fetchAddressLookupTables(\n client,\n (response.addressLookupTableAddresses ?? []) as Address[],\n );\n return { instructions, lookupTables, computeUnits: computeUnitsOf(response), ...amounts };\n}\n\n/**\n * The unit limit Jupiter asked for, or `JUPITER_DEFAULT_COMPUTE_UNITS` when it asked for none.\n *\n * `SetComputeUnitLimit` is five bytes: the tag `2`, then the units as a little-endian u32. Any other\n * compute budget instruction, such as a unit price, is skipped.\n */\nexport function computeUnitsOf(response: JupiterSwapInstructions): number {\n for (const instruction of response.computeBudgetInstructions ?? []) {\n const data = new Uint8Array(base64.encode(instruction.data));\n if (data.length < 5 || data[0] !== SET_COMPUTE_UNIT_LIMIT) continue;\n return new DataView(data.buffer, data.byteOffset).getUint32(1, true);\n }\n return JUPITER_DEFAULT_COMPUTE_UNITS;\n}\n\n/** One Jupiter instruction as a kit instruction. The roles come from the two booleans. */\nfunction toKitInstruction(instruction: JupiterInstruction): Instruction {\n const accounts: AccountMeta[] = instruction.accounts.map((account) => ({\n address: account.pubkey as Address,\n role: account.isSigner\n ? account.isWritable\n ? AccountRole.WRITABLE_SIGNER\n : AccountRole.READONLY_SIGNER\n : account.isWritable\n ? AccountRole.WRITABLE\n : AccountRole.READONLY,\n }));\n return {\n programAddress: instruction.programId as Address,\n accounts,\n data: new Uint8Array(base64.encode(instruction.data)),\n } as Instruction;\n}\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';\nimport { jupiterRoute } from './route/jupiter';\nimport type { RouteProvider } from './route/types';\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 * How a buyer pays in SOL for a machine priced in another token.\n *\n * Mainnet defaults to Jupiter, which is where the liquidity is. Devnet and localnet default to\n * none, because Jupiter does not serve them: pass `raydiumCpmmRoute(pool)` with a CPMM pool that\n * holds the SOL/quote pair. `null` disables the swap leg, and `buyPack`'s `payWith: 'sol'` then\n * fails on a pool quoted in anything but WSOL. Creating a machine never needs it: the creator\n * pays the seed in the machine's own quote token.\n */\n route?: RouteProvider | null;\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 /** The swap provider a SOL payment routes through, or `null` when this cluster has none. */\n route: RouteProvider | null;\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 route: config.route === undefined ? defaultRoute(cluster) : config.route,\n };\n}\n\n/**\n * The swap provider a cluster gets when the caller names none.\n *\n * Jupiter on mainnet, nothing anywhere else. Jupiter's API only prices mainnet liquidity, and a\n * devnet caller has to say which pool to route through, so there is nothing to guess.\n */\nexport function defaultRoute(cluster: Cluster): RouteProvider | null {\n return cluster === 'mainnet-beta' ? jupiterRoute() : null;\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 * Getting the quote token into, and out of, the wallet's own quote account.\n *\n * Gabox settles in the pool's quote asset and nothing else. Both venues move that token in and out\n * of one account: the wallet's associated token account for the quote mint, under the quote's own\n * token program. The program pins that address and measures the exact delta there. So every builder\n * in this directory has to make sure the account exists, and holds what the trade will spend.\n *\n * Three shapes, and which one applies follows from the pool's quote and the caller's choice:\n *\n * - **A WSOL pool.** The wallet pays in SOL already. Create the WSOL account, move the lamports\n * into it, `syncNative`, and close it afterwards so the change and any proceeds come back as\n * SOL. This is what every 0.6.0 flow did, unchanged.\n * - **Another quote, paying in that quote.** The wallet already holds the token. Create the\n * account if it is missing and leave it alone: it is not WSOL, so closing it would be wrong.\n * - **Another quote, paying in SOL.** A route turns SOL into the quote token in the same\n * transaction, before `buy_pack`. A sale does the reverse afterwards. `routeQuoteIn` and\n * `routeQuoteOut` build those, and `assertRouteIsSafe` checks the result before it is used.\n *\n * The third shape belongs to packs only. A machine's seed is always paid by its creator, in the\n * machine's own quote token, so `createMachine` uses `quoteLegFromWallet` and never swaps.\n *\n * Nothing here ever splits the work across two transactions. A swap that settles separately would\n * leave the wallet holding a token it never asked for whenever the second half failed.\n */\n\nimport { getCreateAssociatedTokenIdempotentInstruction } from '@solana-program/token';\nimport type {\n Address,\n AddressesByLookupTableAddress,\n Instruction,\n TransactionSigner,\n} from '@solana/kit';\n\nimport { MAX_COMPUTE_UNIT_LIMIT } from '../compute';\nimport { GABOX_PROGRAM_ID } from '../ids';\nimport { WSOL_MINT } from '../raydium/ids';\nimport type { ResolvedVenue } from '../raydium/venue';\nimport { assertRouteIsSafe, routeQuoteIn, routeQuoteOut } from '../route/leg';\nimport type { RouteMode, RouteProvider } from '../route/types';\nimport type { GaboxClient } from '../rpc';\nimport { fundWsol, unwrapWsol } from './wsol';\n\n/** Where the money for a purchase comes from. */\nexport type PayWith = 'sol' | 'quote';\n/** What a sale pays out. */\nexport type Receive = 'sol' | 'quote';\n\n/** The instructions that go around the Gabox instruction, and what the route did. */\nexport type QuoteLeg = {\n /** Everything that runs before the Gabox instruction. */\n before: Instruction[];\n /** Everything that runs after it. */\n after: Instruction[];\n /** The lookup tables the route's own instructions need, on top of the client's. */\n lookupTables: AddressesByLookupTableAddress;\n /** Which swap mode the route used, or `null` when no route was needed. */\n mode: RouteMode | null;\n /** SOL the route spends, or `null` when no route was needed. */\n solAmount: bigint | null;\n /**\n * The compute units the route adds to the transaction, or `0` when there is no route.\n *\n * The builder adds this to its own limit, because the swap runs on the same budget. It comes from\n * the route itself, so a Jupiter route through several pools asks for more than a single-pool one.\n */\n computeUnits: number;\n};\n\n/** The Gabox accounts a route must never name. */\nexport type GaboxAccounts = readonly Address[];\n\n/** Create the wallet's quote account if it is missing. Idempotent, so a second create is free. */\nexport function createQuoteAccount(\n owner: TransactionSigner,\n venue: Pick<ResolvedVenue, 'quoteMint' | 'quoteTokenProgram' | 'userQuoteToken'>,\n): Instruction {\n return getCreateAssociatedTokenIdempotentInstruction({\n payer: owner,\n ata: venue.userQuoteToken,\n owner: owner.address,\n mint: venue.quoteMint,\n tokenProgram: venue.quoteTokenProgram,\n }) as Instruction;\n}\n\n/**\n * The leg for a wallet that already holds what it is about to spend. No swap.\n *\n * A WSOL pool is the one case where \"already holds it\" means lamports, so those are wrapped and the\n * account is closed again afterwards. Any other quote only needs its account to exist; closing it\n * would throw away a real balance.\n *\n * `createMachine` uses this and nothing else: the seed is always the creator's own money, in the\n * machine's quote token.\n */\nexport async function quoteLegFromWallet(\n venue: Pick<ResolvedVenue, 'quoteMint' | 'quoteTokenProgram' | 'userQuoteToken'>,\n payer: TransactionSigner,\n maxQuoteIn: bigint,\n): Promise<QuoteLeg> {\n if (venue.quoteMint === WSOL_MINT) {\n const wsol = await fundWsol(payer, maxQuoteIn);\n return {\n before: wsol.instructions,\n after: [unwrapWsol(payer, wsol.account)],\n lookupTables: {},\n mode: null,\n solAmount: maxQuoteIn,\n computeUnits: 0,\n };\n }\n return {\n before: [createQuoteAccount(payer, venue)],\n after: [],\n lookupTables: {},\n mode: null,\n solAmount: null,\n computeUnits: 0,\n };\n}\n\n/**\n * The leg that puts `maxQuoteIn` of the quote token in the buyer's quote account.\n *\n * `payWith` decides where it comes from. On a WSOL pool the choice makes no difference: the quote\n * token is SOL either way, so the builder wraps it.\n */\nexport async function quoteLegIn(\n client: GaboxClient,\n input: {\n venue: Pick<ResolvedVenue, 'quoteMint' | 'quoteTokenProgram' | 'userQuoteToken'>;\n payer: TransactionSigner;\n maxQuoteIn: bigint;\n payWith: PayWith;\n /** Gabox accounts a route must never name. The Gabox program id is added here. */\n gaboxAccounts: GaboxAccounts;\n },\n): Promise<QuoteLeg> {\n const { venue, payer, maxQuoteIn, payWith } = input;\n\n if (venue.quoteMint === WSOL_MINT || payWith === 'quote') {\n return await quoteLegFromWallet(venue, payer, maxQuoteIn);\n }\n\n const route = await routeQuoteIn(client, providerOf(client, venue.quoteMint), {\n quoteMint: venue.quoteMint,\n amount: maxQuoteIn,\n user: payer.address,\n });\n assertRouteIsSafe(route, {\n forbidden: [GABOX_PROGRAM_ID, ...input.gaboxAccounts],\n settlesIn: venue.userQuoteToken,\n });\n return {\n before: route.instructions,\n after: [],\n lookupTables: route.lookupTables,\n mode: route.mode,\n solAmount: route.inAmount,\n computeUnits: route.computeUnits,\n };\n}\n\n/**\n * The leg around a sale: make sure the quote account exists, and turn the proceeds into SOL when\n * the seller asked for SOL.\n *\n * The swap is an exact-in of `minQuoteOutput`, the floor the seller already signs for on the sale\n * itself. Anything the venue pays above that floor stays in the seller's quote account: a swap can\n * only spend what the sale is guaranteed to have produced.\n */\nexport async function quoteLegOut(\n client: GaboxClient,\n input: {\n venue: Pick<ResolvedVenue, 'quoteMint' | 'quoteTokenProgram' | 'userQuoteToken'>;\n seller: TransactionSigner;\n minQuoteOutput: bigint;\n receive: Receive;\n gaboxAccounts: GaboxAccounts;\n },\n): Promise<QuoteLeg> {\n const { venue, seller, minQuoteOutput, receive } = input;\n\n if (venue.quoteMint === WSOL_MINT) {\n // A sale needs the account to exist, not to hold anything. The close at the end is what turns\n // the proceeds into SOL.\n const wsol = await fundWsol(seller, 0n);\n return {\n before: wsol.instructions,\n after: [unwrapWsol(seller, wsol.account)],\n lookupTables: {},\n mode: null,\n solAmount: null,\n computeUnits: 0,\n };\n }\n\n const create = createQuoteAccount(seller, venue);\n if (receive === 'quote') {\n return {\n before: [create],\n after: [],\n lookupTables: {},\n mode: null,\n solAmount: null,\n computeUnits: 0,\n };\n }\n\n const route = await routeQuoteOut(client, providerOf(client, venue.quoteMint), {\n quoteMint: venue.quoteMint,\n amount: minQuoteOutput,\n user: seller.address,\n });\n assertRouteIsSafe(route, {\n forbidden: [GABOX_PROGRAM_ID, ...input.gaboxAccounts],\n settlesIn: venue.userQuoteToken,\n });\n return {\n before: [create],\n after: route.instructions,\n lookupTables: route.lookupTables,\n mode: route.mode,\n solAmount: route.outAmount,\n computeUnits: route.computeUnits,\n };\n}\n\n/** The client's route provider, with a message that says what to do when it has none. */\nexport function providerOf(client: GaboxClient, quoteMint: Address): RouteProvider {\n if (!client.route) {\n throw new Error(\n `this ${client.cluster} client has no route provider, so it cannot pay in SOL for a pool ` +\n `quoted in ${quoteMint}. Pass \\`route\\` to createClient — raydiumCpmmRoute(pool) for a ` +\n \"CPMM pool that holds the SOL pair — or pay in the quote token itself.\",\n );\n }\n return client.route;\n}\n\n/**\n * The compute limit a builder asks for: its own budget plus whatever the route needs.\n *\n * Capped at the runtime's ceiling. Jupiter often asks for the whole 1,400,000 units rather than\n * estimating, and a request above the ceiling is rejected outright, so the sum has to be clamped\n * rather than passed through.\n */\nexport function computeUnitsWithRoute(own: number, leg: QuoteLeg): number {\n return Math.min(own + leg.computeUnits, MAX_COMPUTE_UNIT_LIMIT);\n}\n\n/**\n * Add the route to a \"transaction is too large\" error.\n *\n * `buildMessage` already refuses a message above the 1,232-byte limit. When a swap is in the same\n * message, the reason is usually the swap, and the fix is not to split the transaction: the two\n * halves have to settle together. So the message says what a caller can actually do instead.\n */\nexport function routeSizeHint(cause: unknown, leg: QuoteLeg): unknown {\n if (leg.mode === null) return cause;\n if (!(cause instanceof Error) || !cause.message.includes('Solana allows 1232')) return cause;\n return new Error(\n `${cause.message} The swap and the Gabox instruction share one transaction on purpose, so ` +\n 'this SDK never splits them. Supply more address lookup tables, or pay in the quote token.',\n { cause },\n );\n}\n","/**\n * Buying one pack.\n *\n * The Gabox instruction is always the same. What goes around it follows the pool's quote asset:\n *\n * - **A WSOL pool.** Create the purchaser's WSOL account, move `maxQuoteIn` lamports into it,\n * `syncNative`, buy, then close the account so the change comes back as SOL.\n * - **Another quote, `payWith: 'quote'`.** Create the purchaser's quote account if it is missing\n * and buy. The purchaser must already hold at least the pack price.\n * - **Another quote, `payWith: 'sol'` (the default).** A route turns SOL into `maxQuoteIn` of the\n * quote token first, in the same transaction, and `buy_pack` then spends only what the pack\n * costs. Anything the route bought above that stays in the purchaser's quote account.\n *\n * One transaction and one signature in every case. The swap and the buy are never split: a swap\n * that settled on its own would leave the buyer holding a token they never asked for whenever the\n * buy failed.\n *\n * Closing the WSOL account 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 the quote token. `maxNativeDebit` is a\n * separate cap on the lamports the handler watches: the venue's account rent, which LaunchLab\n * charges on a 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 { activityAddress, associatedTokenAddress, drawAddress } from '../pdas';\nimport { resolveVenue, type VenueKind } from '../raydium/venue';\nimport type { GaboxClient } from '../rpc';\nimport { buildMessage, withRemainingAccounts, type BuildOptions } from './message';\nimport { computeUnitsWithRoute, quoteLegIn, routeSizeHint, type PayWith } from './quoteLeg';\n\nexport type BuyPackInput = {\n mint: Address;\n purchaser: TransactionSigner;\n /**\n * The venue slippage cap, in the pool's quote token. The transaction puts this much of the quote\n * token in the buyer's quote account before the buy, so it must cover the real price. Anything\n * left over stays there, or comes back as SOL on a WSOL pool.\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 /**\n * Pay in SOL through a swap, or in the quote token the buyer already holds. Defaults to `'sol'`.\n * A WSOL pool ignores it: its quote token is SOL.\n */\n payWith?: PayWith;\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 quote: {\n mint: pool.quoteMint,\n config: pool.quoteConfig,\n tokenProgram: pool.quoteTokenProgram,\n },\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 quoteTokenProgram: pool.quoteTokenProgram,\n maxQuoteIn: input.maxQuoteIn,\n minMaximum: input.minMaximum,\n maxNativeDebit: input.maxNativeDebit,\n });\n\n const leg = await quoteLegIn(client, {\n venue,\n payer: input.purchaser,\n maxQuoteIn: input.maxQuoteIn,\n payWith: input.payWith ?? 'sol',\n gaboxAccounts: [\n poolAddress,\n pool.vault,\n draw,\n await activityAddress(purchaser),\n await associatedTokenAddress(purchaser, input.mint),\n ],\n });\n\n const instructions: Instruction[] = [\n ...leg.before,\n withRemainingAccounts(buy as Instruction, venue.buyAccounts),\n ...leg.after,\n ];\n\n try {\n return await buildMessage(client, input.purchaser, instructions, {\n addressLookupTables: {\n ...(input.addressLookupTables ?? client.addressLookupTables),\n ...leg.lookupTables,\n },\n computeUnitLimit: input.computeUnitLimit ?? computeUnitsWithRoute(BUY_PACK_COMPUTE_UNITS, leg),\n ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }),\n });\n } catch (cause) {\n throw routeSizeHint(cause, leg);\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. The quote leg: wrap SOL for a WSOL pool, or create the creator's quote account for any other\n * quote.\n * 3. `initialize_pool`, with the LaunchLab buy accounts as `remainingAccounts`.\n * 4. Close the WSOL account, on a WSOL pool only. Whatever the seed did not spend comes back as SOL.\n *\n * The seed is bought in the pool's quote token, so step 2 is not optional: `initialize_pool`\n * measures the creator's quote balance before and after the seed buy, and the buy cannot spend what\n * the account does not hold.\n *\n * **The creator pays the seed themselves, in the machine's own quote token.** There is no swap\n * here. A machine quoted in USDC needs the creator to hold USDC before this transaction runs, and\n * `seedCostEstimate` says how much. Only a pack buy and a sale swap, because only a buyer arrives\n * holding SOL alone; see `tx/buyPack.ts` and `tx/redeem.ts`.\n *\n * Closing in step 4 also unwraps any WSOL the creator already held. See `tx/wsol.ts`.\n *\n * # The quote and the raise\n *\n * A machine is priced in one quote asset, fixed for its whole life. It defaults to wrapped SOL.\n * Any other quote Raydium enabled on LaunchLab works: pass `quote: { mint }`, and the SDK reads\n * Raydium's own global config for that mint to prove it and to price the curve.\n *\n * `raise` is `total_quote_fund_raising`, in the quote's own base units. A WSOL pool has it pinned\n * by the program, so the SDK supplies 85 SOL on mainnet and 3 SOL on devnet and refuses a different\n * value. Any other quote has no default: 3,000,000,000 means three SOL and three thousand USDC, so\n * the caller has to say. LaunchLab checks the number against `min_quote_fund_raising` in the\n * quote's own config, and this checks it too, before anything is built.\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 { Address, Instruction, TransactionSigner } from '@solana/kit';\n\nimport { CREATE_MACHINE_COMPUTE_UNITS } from '../compute';\nimport { getInitializePoolInstructionAsync } from '../generated/instructions/initializePool';\nimport { PACK_TOKENS } from '../ids';\nimport { DEFAULT_TIERS, seedTokens, validatePack, validateTiers, type Tier } from '../math';\nimport { LAUNCH_TOTAL_BASE_SELL, WSOL_MINT, raydiumIds, type RaydiumIds } from '../raydium/ids';\nimport { getLaunchInstruction } from '../raydium/launch';\nimport { launchlabBuyAccounts } from '../raydium/accounts';\nimport { curveBuyExactOut } from '../raydium/curve';\nimport { fetchQuoteAsset, type QuoteAsset } from '../raydium/quote';\nimport { fetchCurveSettings, newCurveReserves, quoteAccountFor } 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 { solPriceOf } from '../route/leg';\nimport { quoteLegFromWallet } from './quoteLeg';\n\n/** Which quote asset a new machine is priced in. Defaults to wrapped SOL. */\nexport type QuoteChoice = { mint: Address };\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 /** The quote asset the machine is priced in. Defaults to wrapped SOL. */\n quote?: QuoteChoice;\n /**\n * `total_quote_fund_raising`, in the quote's own base units. Required for a quote other than\n * wrapped SOL; a WSOL pool uses the raise the program pins for this cluster.\n */\n raise?: bigint;\n /**\n * Seed slippage cap in the quote token, for `mandatory + extraSeedTokens` together. The creator\n * must already hold this much of the quote token, so it has to cover the real cost. Anything left\n * over stays in their quote account, or comes back as SOL on a WSOL pool.\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 the quote's LaunchLab config, the quote mint, and the Gabox platform config, because the\n * seed price and every quote-side account depend on them. 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 { 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 quote = await fetchQuoteAsset(client, input.quote?.mint ?? WSOL_MINT, ids);\n const raise = resolveRaise(client, quote, input.raise, ids);\n\n const create = await getLaunchInstruction(\n {\n mint: mintKeypair,\n creator,\n name,\n symbol,\n uri,\n quoteMint: quote.mint,\n quoteConfig: quote.config,\n quoteTokenProgram: quote.tokenProgram,\n raise,\n },\n ids,\n );\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, quote.mint);\n const userQuoteToken = await quoteAccountFor(creator.address, quote.mint, quote.tokenProgram);\n const venueAccounts = launchlabBuyAccounts({\n launchlab: ids.launchlab,\n launchlabAuthority: ids.launchlabAuthority,\n launchlabEventAuthority: ids.launchlabEventAuthority,\n globalConfig: quote.config,\n platformConfig: ids.gaboxPlatform,\n poolState,\n mint,\n quoteMint: quote.mint,\n baseVault: await launchlabVaultAddress(ids.launchlab, poolState, mint),\n quoteVault: await launchlabVaultAddress(ids.launchlab, poolState, quote.mint),\n user: creator.address,\n userBaseToken: await ata(creator.address, mint),\n userQuoteToken,\n quoteTokenProgram: quote.tokenProgram,\n platformFeeVault: await platformFeeVaultAddress(ids.launchlab, ids.gaboxPlatform, quote.mint),\n creatorFeeVault: await creatorFeeVaultAddress(ids.launchlab, creator.address, quote.mint),\n });\n\n const initialize = await getInitializePoolInstructionAsync({\n creator,\n mint,\n quoteMint: quote.mint,\n quoteConfig: quote.config,\n quoteTokenProgram: quote.tokenProgram,\n venue: ids.launchlab,\n tiers,\n maxSeedQuoteIn,\n maxSeedNativeDebit,\n extraSeedTokens,\n });\n\n // The creator's own money, in the machine's quote token. A WSOL machine wraps the lamports; any\n // other quote only needs the account to exist, because `initialize_pool` reads it either way.\n const leg = await quoteLegFromWallet(\n { quoteMint: quote.mint, quoteTokenProgram: quote.tokenProgram, userQuoteToken },\n creator,\n maxSeedQuoteIn,\n );\n\n const instructions: Instruction[] = [\n create,\n ...leg.before,\n withRemainingAccounts(initialize as Instruction, venueAccounts),\n ...leg.after,\n ];\n\n return await buildMessage(client, creator, instructions, {\n addressLookupTables: input.addressLookupTables ?? client.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 the quote token's base units, Raydium's fees included. */\n quoteAmount: bigint;\n /** The quote asset the machine would be priced in. */\n quoteMint: Address;\n quoteDecimals: number;\n /** The symbol Metaplex or Token-2022 records for the quote mint, when it has one. */\n quoteSymbol: string | null;\n /** `total_quote_fund_raising` the launch would use, in the quote's base units. */\n raise: bigint;\n /**\n * What `quoteAmount` is worth in SOL through the client's route provider, or `null` when there is\n * no provider or no route. Equal to `quoteAmount` on a WSOL machine.\n *\n * A display only. The creator pays the seed in the quote token, not in SOL, so this says what\n * that costs them in familiar money; it is not an amount any instruction spends.\n */\n solAmount: bigint | null;\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 launch shape and the raise. Nothing trades on the curve before `initialize_pool` runs in the\n * same transaction, so this is exact up to a change in Raydium's fee rates between the read and the\n * send.\n *\n * `solAmount` is what that cost is worth in SOL, priced through the client's route provider. It is\n * a display: the creator pays in the quote token. It is `null` when the client has no provider, or\n * when no route exists: a devnet client has none unless the caller passes `raydiumCpmmRoute(pool)`.\n *\n * Defaults to `DEFAULT_TIERS`, wrapped SOL and no extra seed. Throws if `tiers` fails\n * `validateTiers`/`validatePack`, if `extraSeedTokens` is negative, if the total seed is bigger\n * than the curve sells, or if the raise is missing or below what LaunchLab accepts.\n */\nexport async function seedCostEstimate(\n client: GaboxClient,\n tiers: readonly Readonly<Tier>[] = DEFAULT_TIERS,\n options: { extraSeedTokens?: bigint; quote?: QuoteChoice; raise?: 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 quote = await fetchQuoteAsset(client, options.quote?.mint ?? WSOL_MINT, ids);\n const raise = resolveRaise(client, quote, options.raise, ids);\n const settings = await fetchCurveSettings(client, quote.config, ids);\n const quoteAmount =\n seed === 0n\n ? 0n\n : curveBuyExactOut(newCurveReserves(raise, settings.migrateFee), settings.rates, seed);\n\n return {\n tiers: copiedTiers,\n seedTokens: mandatorySeed,\n extraSeedTokens,\n totalSeedTokens: seed,\n quoteAmount,\n quoteMint: quote.mint,\n quoteDecimals: quote.decimals,\n quoteSymbol: quote.symbol,\n raise,\n solAmount: await solPriceOf(client, quote.mint, quoteAmount),\n };\n}\n\n/**\n * The raise a launch uses, checked before anything is built.\n *\n * The program pins it for a WSOL pool, so a different value there is a launch that would be\n * refused on chain. Any other quote has no default and no pin: the caller names it, and LaunchLab's\n * own minimum for that quote is the floor.\n */\nfunction resolveRaise(\n client: GaboxClient,\n quote: QuoteAsset,\n raise: bigint | undefined,\n ids: RaydiumIds,\n): bigint {\n if (quote.mint === WSOL_MINT) {\n if (raise !== undefined && raise !== ids.launchQuoteRaise) {\n throw new Error(\n `a WSOL pool raises exactly ${ids.launchQuoteRaise} lamports on ${client.cluster}; the ` +\n `program refuses ${raise}. Leave \\`raise\\` out, or pick another quote asset.`,\n );\n }\n return ids.launchQuoteRaise;\n }\n if (raise === undefined) {\n throw new Error(\n `a pool quoted in ${quote.mint} needs a \\`raise\\`, in that token's base units. There is no ` +\n 'default, because the same number means a different amount in every token.',\n );\n }\n if (raise < quote.minQuoteFundRaising) {\n throw new Error(\n `LaunchLab takes at least ${quote.minQuoteFundRaising} base units of ${quote.mint} as a ` +\n `raise, and this launch asks for ${raise}`,\n );\n }\n return raise;\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\n * the venue's own floor, in the pool's quote token, and the program checks it before it returns.\n *\n * What goes around the sale follows the pool's quote asset:\n *\n * - **A WSOL pool.** Create the seller's WSOL account, sell, close it. The proceeds land in the\n * wallet as SOL.\n * - **Another quote, `receive: 'sol'` (the default).** Sell, then swap `minQuoteOutput` of the\n * proceeds into SOL in the same transaction. Anything the venue paid above that floor stays in\n * the seller's quote account.\n * - **Another quote, `receive: 'quote'`.** Sell and stop. The proceeds stay in the quote token.\n *\n * Closing a WSOL account also unwraps any WSOL the wallet 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 { associatedTokenAddress, poolAddress, vaultAddress } from '../pdas';\nimport { resolveVenue, type VenueKind } from '../raydium/venue';\nimport type { GaboxClient } from '../rpc';\nimport { buildMessage, withRemainingAccounts, type BuildOptions } from './message';\nimport { computeUnitsWithRoute, quoteLegOut, routeSizeHint, type Receive } from './quoteLeg';\n\nexport type SellTokensInput = {\n mint: Address;\n seller: TransactionSigner;\n amount: bigint;\n /** The venue's own floor on the quote token 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 /**\n * Take the proceeds as SOL through a swap, or keep them in the quote token. Defaults to `'sol'`.\n * A WSOL pool ignores it: its quote token is SOL.\n */\n receive?: Receive;\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 quote: {\n mint: pool.quoteMint,\n config: pool.quoteConfig,\n tokenProgram: pool.quoteTokenProgram,\n },\n ...(input.venue ? { venue: input.venue } : {}),\n });\n\n const gaboxPool = await poolAddress(input.mint);\n const sell = await getSellTokensInstructionAsync({\n seller: input.seller,\n pool: gaboxPool,\n mint: input.mint,\n quoteMint: pool.quoteMint,\n venue: venue.program,\n quoteTokenProgram: pool.quoteTokenProgram,\n amount: input.amount,\n minQuoteOutput: input.minQuoteOutput,\n maxNativeDebit: input.maxNativeDebit,\n });\n\n const leg = await quoteLegOut(client, {\n venue,\n seller: input.seller,\n minQuoteOutput: input.minQuoteOutput,\n receive: input.receive ?? 'sol',\n gaboxAccounts: [\n gaboxPool,\n await vaultAddress(input.mint),\n await associatedTokenAddress(input.seller.address, input.mint),\n ],\n });\n\n const instructions: Instruction[] = [\n ...leg.before,\n withRemainingAccounts(sell as Instruction, venue.sellAccounts),\n ...leg.after,\n ];\n\n try {\n return await buildMessage(client, input.seller, instructions, {\n addressLookupTables: {\n ...(input.addressLookupTables ?? client.addressLookupTables),\n ...leg.lookupTables,\n },\n computeUnitLimit: input.computeUnitLimit ?? computeUnitsWithRoute(REDEEM_COMPUTE_UNITS, leg),\n ...(input.computeUnitPrice === undefined ? {} : { computeUnitPrice: input.computeUnitPrice }),\n });\n } catch (cause) {\n throw routeSizeHint(cause, leg);\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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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,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,6CAA6C;CACrD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;CACtD,QAAQ,8CAA8C;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"}
|
package/dist/raydium/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as QuoteBinding, $t as CONSTANT_CURVE_TAG, A as ClaimCreatorFeeInput, An as LAUNCHLAB_SELL_EXACT_IN, At as totalCurveFeeRate, B as cpmmBuyAccounts, Bn as TOKEN_2022_PROGRAM_ADDRESS, Bt as LaunchlabGlobalConfig, C as launchlabPlatformConfig, Cn as LAUNCHLAB_BUY_EXACT_IN, Ct as cpmmSwapBaseOutput, D as platformFeeVaultAddress, Dn as LAUNCHLAB_INITIALIZE, Dt as initialCurve, E as metadataAddress, En as LAUNCHLAB_GLOBAL_CONFIG_DISCRIMINATOR, Et as curveSellExactIn, F as fetchCreatorFees, Fn as RAYDIUM_DEVNET_IDS, Ft as CpmmAmmConfig, G as order, Gt as decodeLaunchlabGlobalConfig, H as launchlabBuyAccounts, Hn as VenueAccountSpec, Ht as LaunchlabPoolState, I as getClaimCreatorFeeInstructions, In as RAYDIUM_MAINNET_IDS, It as CpmmPoolState, Jt as metaplexSymbol, Kt as decodeLaunchlabPlatformConfig, L as getCollectCreatorFeeInstructions, Ln as RENT_SYSVAR_ADDRESS, Lt as LAUNCHLAB_GLOBAL_CONFIG_HEAD_SIZE, M as CreatorFees, Mn as LAUNCH_TOTAL_BASE_SELL, Mt as CPMM_POOL_OFFSETS, N as claimCreatorFee, Nn as METAPLEX_PROGRAM_ADDRESS, Nt as CPMM_POOL_STATE_HEAD_SIZE, O as LaunchInput, On as LAUNCHLAB_PLATFORM_CONFIG_DISCRIMINATOR, Ot as preFeeAmount, P as collectCreatorFee, Pn as PLATFORM_ADMIN, Pt as CPMM_POOL_STATE_SIZE, Q as MigratedCpmmPool, Qt as tokenAccountOwnerAndMint, R as CpmmTradeAccountsInput, Rn as RaydiumClusterIds, Rt as LAUNCHLAB_PLATFORM_CONFIG_HEAD_SIZE, S as launchlabGlobalConfig, Sn as CPMM_SWAP_BASE_OUTPUT, St as cpmmSwapBaseInput, T as launchlabVaultAddress, Tn as LAUNCHLAB_CLAIM_CREATOR_FEE, Tt as curveBuyExactOut, U as launchlabBuyExactInAccounts, Un as VenueInstructionAbi, Ut as decodeCpmmAmmConfig, V as cpmmSellAccounts, Vn as TOKEN_PROGRAM_ADDRESS, Vt as LaunchlabPlatformConfig, W as launchlabSellAccounts, Wn as WSOL_MINT, Wt as decodeCpmmPool, X as CurveSettings, Xt as token2022Symbol, Yt as mintDecimals, Z as FindCpmmPoolOptions, Zt as tokenAccountAmount, _ as cpmmPoolAddress, _n as ASSOCIATED_TOKEN_PROGRAM_ADDRESS, _t as CurveFeeRates, a as decodeBase64, an as LAUNCHLAB_STATUS_TRADE, at as curveQuote, b as launchlabAuthority, bn as CPMM_POOL_STATE_DISCRIMINATOR, bt as ceilDiv, c as QuoteConfig, cn as METADATA_SEED, ct as findCpmmPool, d as fetchQuoteConfig, dn as RAYDIUM_IDS, dt as quoteAccountFor, en as CPMM_SEEDS, et as ResolveVenueOptions, f as fetchQuoteDisplay, fn as RaydiumIds, ft as resolveVenue, g as cpmmCreatorFeeShare, gn as sortedMints, gt as CpmmSwapSides, h as cpmmAuthority, hn as raydiumIds, ht as CpmmFeeRates, i as MaybeAccount, in as LAUNCHLAB_STATUS_MIGRATE, it as creatorFeeOnInput, j as CollectCreatorFeeInput, jn as LAUNCH_SUPPLY, jt as CPMM_AMM_CONFIG_HEAD_SIZE, k as getLaunchInstruction, kn as LAUNCHLAB_POOL_STATE_DISCRIMINATOR, kt as remainingBase, l as QuoteDisplay, ln as MIGRATE_TO_CPMM, lt as newCurveBuyCost, m as ata, mn as compareAddresses, mt as wsolAccountFor, n as CurveBuyExactInInput, nn as LAUNCHLAB_SEEDS, nt as VenueKind, o as readAccounts, on as LAUNCH_DECIMALS, ot as fetchCurveSettings, p as isQuoteSupported, pn as SHARE_FEE_RATE, pt as sellQuote, qt as decodeLaunchlabPool, r as getCurveBuyExactInInstruction, rn as LAUNCHLAB_STATUS_FUND, rt as cpmmPoolMatches, s as QuoteAsset, sn as METADATA_LIMITS, st as fetchQuoteBinding, tn as CREATOR_FEE_ON_QUOTE, tt as ResolvedVenue, u as fetchQuoteAsset, un as RATE_DENOMINATOR, ut as newCurveReserves, v as creatorFeeVaultAddress, vn as CPMM_AMM_CONFIG_DISCRIMINATOR, vt as CurveReserves, w as launchlabPoolAddress, wn as LAUNCHLAB_BUY_EXACT_OUT, wt as curveBuyExactIn, x as launchlabEventAuthority, xn as CPMM_SWAP_BASE_INPUT, xt as ceilDivRate, y as creatorFeeVaultAuthority, yn as CPMM_COLLECT_CREATOR_FEE, yt as LaunchParams, z as LaunchlabTradeAccountsInput, zn as SYSTEM_PROGRAM_ADDRESS, zt as LAUNCHLAB_POOL_STATE_HEAD_SIZE } from "../index-
|
|
1
|
+
import { $ as QuoteBinding, $t as CONSTANT_CURVE_TAG, A as ClaimCreatorFeeInput, An as LAUNCHLAB_SELL_EXACT_IN, At as totalCurveFeeRate, B as cpmmBuyAccounts, Bn as TOKEN_2022_PROGRAM_ADDRESS, Bt as LaunchlabGlobalConfig, C as launchlabPlatformConfig, Cn as LAUNCHLAB_BUY_EXACT_IN, Ct as cpmmSwapBaseOutput, D as platformFeeVaultAddress, Dn as LAUNCHLAB_INITIALIZE, Dt as initialCurve, E as metadataAddress, En as LAUNCHLAB_GLOBAL_CONFIG_DISCRIMINATOR, Et as curveSellExactIn, F as fetchCreatorFees, Fn as RAYDIUM_DEVNET_IDS, Ft as CpmmAmmConfig, G as order, Gt as decodeLaunchlabGlobalConfig, H as launchlabBuyAccounts, Hn as VenueAccountSpec, Ht as LaunchlabPoolState, I as getClaimCreatorFeeInstructions, In as RAYDIUM_MAINNET_IDS, It as CpmmPoolState, Jt as metaplexSymbol, Kt as decodeLaunchlabPlatformConfig, L as getCollectCreatorFeeInstructions, Ln as RENT_SYSVAR_ADDRESS, Lt as LAUNCHLAB_GLOBAL_CONFIG_HEAD_SIZE, M as CreatorFees, Mn as LAUNCH_TOTAL_BASE_SELL, Mt as CPMM_POOL_OFFSETS, N as claimCreatorFee, Nn as METAPLEX_PROGRAM_ADDRESS, Nt as CPMM_POOL_STATE_HEAD_SIZE, O as LaunchInput, On as LAUNCHLAB_PLATFORM_CONFIG_DISCRIMINATOR, Ot as preFeeAmount, P as collectCreatorFee, Pn as PLATFORM_ADMIN, Pt as CPMM_POOL_STATE_SIZE, Q as MigratedCpmmPool, Qt as tokenAccountOwnerAndMint, R as CpmmTradeAccountsInput, Rn as RaydiumClusterIds, Rt as LAUNCHLAB_PLATFORM_CONFIG_HEAD_SIZE, S as launchlabGlobalConfig, Sn as CPMM_SWAP_BASE_OUTPUT, St as cpmmSwapBaseInput, T as launchlabVaultAddress, Tn as LAUNCHLAB_CLAIM_CREATOR_FEE, Tt as curveBuyExactOut, U as launchlabBuyExactInAccounts, Un as VenueInstructionAbi, Ut as decodeCpmmAmmConfig, V as cpmmSellAccounts, Vn as TOKEN_PROGRAM_ADDRESS, Vt as LaunchlabPlatformConfig, W as launchlabSellAccounts, Wn as WSOL_MINT, Wt as decodeCpmmPool, X as CurveSettings, Xt as token2022Symbol, Yt as mintDecimals, Z as FindCpmmPoolOptions, Zt as tokenAccountAmount, _ as cpmmPoolAddress, _n as ASSOCIATED_TOKEN_PROGRAM_ADDRESS, _t as CurveFeeRates, a as decodeBase64, an as LAUNCHLAB_STATUS_TRADE, at as curveQuote, b as launchlabAuthority, bn as CPMM_POOL_STATE_DISCRIMINATOR, bt as ceilDiv, c as QuoteConfig, cn as METADATA_SEED, ct as findCpmmPool, d as fetchQuoteConfig, dn as RAYDIUM_IDS, dt as quoteAccountFor, en as CPMM_SEEDS, et as ResolveVenueOptions, f as fetchQuoteDisplay, fn as RaydiumIds, ft as resolveVenue, g as cpmmCreatorFeeShare, gn as sortedMints, gt as CpmmSwapSides, h as cpmmAuthority, hn as raydiumIds, ht as CpmmFeeRates, i as MaybeAccount, in as LAUNCHLAB_STATUS_MIGRATE, it as creatorFeeOnInput, j as CollectCreatorFeeInput, jn as LAUNCH_SUPPLY, jt as CPMM_AMM_CONFIG_HEAD_SIZE, k as getLaunchInstruction, kn as LAUNCHLAB_POOL_STATE_DISCRIMINATOR, kt as remainingBase, l as QuoteDisplay, ln as MIGRATE_TO_CPMM, lt as newCurveBuyCost, m as ata, mn as compareAddresses, mt as wsolAccountFor, n as CurveBuyExactInInput, nn as LAUNCHLAB_SEEDS, nt as VenueKind, o as readAccounts, on as LAUNCH_DECIMALS, ot as fetchCurveSettings, p as isQuoteSupported, pn as SHARE_FEE_RATE, pt as sellQuote, qt as decodeLaunchlabPool, r as getCurveBuyExactInInstruction, rn as LAUNCHLAB_STATUS_FUND, rt as cpmmPoolMatches, s as QuoteAsset, sn as METADATA_LIMITS, st as fetchQuoteBinding, tn as CREATOR_FEE_ON_QUOTE, tt as ResolvedVenue, u as fetchQuoteAsset, un as RATE_DENOMINATOR, ut as newCurveReserves, v as creatorFeeVaultAddress, vn as CPMM_AMM_CONFIG_DISCRIMINATOR, vt as CurveReserves, w as launchlabPoolAddress, wn as LAUNCHLAB_BUY_EXACT_OUT, wt as curveBuyExactIn, x as launchlabEventAuthority, xn as CPMM_SWAP_BASE_INPUT, xt as ceilDivRate, y as creatorFeeVaultAuthority, yn as CPMM_COLLECT_CREATOR_FEE, yt as LaunchParams, z as LaunchlabTradeAccountsInput, zn as SYSTEM_PROGRAM_ADDRESS, zt as LAUNCHLAB_POOL_STATE_HEAD_SIZE } from "../index-CA0m7AKk.js";
|
|
2
2
|
export { ASSOCIATED_TOKEN_PROGRAM_ADDRESS, CONSTANT_CURVE_TAG, CPMM_AMM_CONFIG_DISCRIMINATOR, CPMM_AMM_CONFIG_HEAD_SIZE, CPMM_COLLECT_CREATOR_FEE, CPMM_POOL_OFFSETS, CPMM_POOL_STATE_DISCRIMINATOR, CPMM_POOL_STATE_HEAD_SIZE, CPMM_POOL_STATE_SIZE, CPMM_SEEDS, CPMM_SWAP_BASE_INPUT, CPMM_SWAP_BASE_OUTPUT, CREATOR_FEE_ON_QUOTE, ClaimCreatorFeeInput, CollectCreatorFeeInput, CpmmAmmConfig, CpmmFeeRates, CpmmPoolState, CpmmSwapSides, CpmmTradeAccountsInput, CreatorFees, CurveBuyExactInInput, CurveFeeRates, CurveReserves, CurveSettings, FindCpmmPoolOptions, LAUNCHLAB_BUY_EXACT_IN, LAUNCHLAB_BUY_EXACT_OUT, LAUNCHLAB_CLAIM_CREATOR_FEE, LAUNCHLAB_GLOBAL_CONFIG_DISCRIMINATOR, LAUNCHLAB_GLOBAL_CONFIG_HEAD_SIZE, LAUNCHLAB_INITIALIZE, LAUNCHLAB_PLATFORM_CONFIG_DISCRIMINATOR, LAUNCHLAB_PLATFORM_CONFIG_HEAD_SIZE, LAUNCHLAB_POOL_STATE_DISCRIMINATOR, LAUNCHLAB_POOL_STATE_HEAD_SIZE, LAUNCHLAB_SEEDS, LAUNCHLAB_SELL_EXACT_IN, LAUNCHLAB_STATUS_FUND, LAUNCHLAB_STATUS_MIGRATE, LAUNCHLAB_STATUS_TRADE, LAUNCH_DECIMALS, LAUNCH_SUPPLY, LAUNCH_TOTAL_BASE_SELL, LaunchInput, LaunchParams, LaunchlabGlobalConfig, LaunchlabPlatformConfig, LaunchlabPoolState, LaunchlabTradeAccountsInput, METADATA_LIMITS, METADATA_SEED, METAPLEX_PROGRAM_ADDRESS, MIGRATE_TO_CPMM, MaybeAccount, MigratedCpmmPool, PLATFORM_ADMIN, QuoteAsset, QuoteBinding, QuoteConfig, QuoteDisplay, RATE_DENOMINATOR, RAYDIUM_DEVNET_IDS, RAYDIUM_IDS, RAYDIUM_MAINNET_IDS, RENT_SYSVAR_ADDRESS, RaydiumClusterIds, RaydiumIds, ResolveVenueOptions, ResolvedVenue, SHARE_FEE_RATE, SYSTEM_PROGRAM_ADDRESS, TOKEN_2022_PROGRAM_ADDRESS, TOKEN_PROGRAM_ADDRESS, VenueAccountSpec, VenueInstructionAbi, VenueKind, WSOL_MINT, ata, ceilDiv, ceilDivRate, claimCreatorFee, collectCreatorFee, compareAddresses, cpmmAuthority, cpmmBuyAccounts, cpmmCreatorFeeShare, cpmmPoolAddress, cpmmPoolMatches, cpmmSellAccounts, cpmmSwapBaseInput, cpmmSwapBaseOutput, creatorFeeOnInput, creatorFeeVaultAddress, creatorFeeVaultAuthority, curveBuyExactIn, curveBuyExactOut, curveQuote, curveSellExactIn, decodeBase64, decodeCpmmAmmConfig, decodeCpmmPool, decodeLaunchlabGlobalConfig, decodeLaunchlabPlatformConfig, decodeLaunchlabPool, fetchCreatorFees, fetchCurveSettings, fetchQuoteAsset, fetchQuoteBinding, fetchQuoteConfig, fetchQuoteDisplay, findCpmmPool, getClaimCreatorFeeInstructions, getCollectCreatorFeeInstructions, getCurveBuyExactInInstruction, getLaunchInstruction, initialCurve, isQuoteSupported, launchlabAuthority, launchlabBuyAccounts, launchlabBuyExactInAccounts, launchlabEventAuthority, launchlabGlobalConfig, launchlabPlatformConfig, launchlabPoolAddress, launchlabSellAccounts, launchlabVaultAddress, metadataAddress, metaplexSymbol, mintDecimals, newCurveBuyCost, newCurveReserves, order, platformFeeVaultAddress, preFeeAmount, quoteAccountFor, raydiumIds, readAccounts, remainingBase, resolveVenue, sellQuote, sortedMints, token2022Symbol, tokenAccountAmount, tokenAccountOwnerAndMint, totalCurveFeeRate, wsolAccountFor };
|
package/package.json
CHANGED
|
@@ -27,7 +27,9 @@ the WSOL account afterwards, so the wallet spends and receives plain SOL; that c
|
|
|
27
27
|
WSOL the wallet already held. On any other pool a route provider swaps SOL into the quote token **in
|
|
28
28
|
the same transaction** as the Gabox instruction, and back after a sale. `createClient` gives mainnet
|
|
29
29
|
`jupiterRoute()`; devnet has no router, so pass `route: raydiumCpmmRoute(pool)` with a CPMM pool for
|
|
30
|
-
the SOL pair. `payWith: 'quote'` and `receive: 'quote'` skip the swap.
|
|
30
|
+
the SOL pair. `payWith: 'quote'` and `receive: 'quote'` skip the swap. Only packs and sales swap: a
|
|
31
|
+
machine's seed is always paid by its creator, in the machine's own quote token, so `createMachine`
|
|
32
|
+
has no `payWith` and the creator must hold `maxSeedQuoteIn` of that token first.
|
|
31
33
|
|
|
32
34
|
```ts
|
|
33
35
|
import { buyPack, createClient, getOffer } from '@gabox-labs/sdk';
|
|
@@ -53,7 +55,7 @@ For creation use `createMachine` with `name`, `symbol`, `uri`, `maxSeedQuoteIn`
|
|
|
53
55
|
`maxSeedNativeDebit`. Metaplex limits the three strings to 32, 10 and 200 UTF-8 bytes. Add
|
|
54
56
|
`quote: { mint }` and `raise` for a machine priced in another token: `raise` is
|
|
55
57
|
`total_quote_fund_raising` in that token's base units, and a WSOL pool uses the raise the program
|
|
56
|
-
pins instead. Everything else about the launch is pinned. It buys a mandatory seed: enough for a 3x
|
|
58
|
+
pins instead. `seedCostEstimate` says what the seed costs in that token. Everything else about the launch is pinned. It buys a mandatory seed: enough for a 3x
|
|
57
59
|
top prize on the first pack, or the table's full top prize when that pays less than 3x. A table's
|
|
58
60
|
top tier can be at most 20x. Pass `extraSeedTokens` to buy more seed in the same trade, and read
|
|
59
61
|
`seedCostEstimate` for the mandatory, extra and total amounts plus the exact cost.
|
|
@@ -31,7 +31,7 @@ Each returns a kit transaction message. Nothing here signs or sends.
|
|
|
31
31
|
|
|
32
32
|
| Function | Input highlights |
|
|
33
33
|
| --- | --- |
|
|
34
|
-
| `createMachine` | `name`, `symbol`, `uri`, `tiers?`, `quote?`, `raise?`, `
|
|
34
|
+
| `createMachine` | `name`, `symbol`, `uri`, `tiers?`, `quote?`, `raise?`, `maxSeedQuoteIn`, `maxSeedNativeDebit`, `extraSeedTokens?` |
|
|
35
35
|
| `buyPack` | `maxQuoteIn`, `minMaximum`, `maxNativeDebit`, `payWith?`, `venue?`, `seq?` |
|
|
36
36
|
| `fundPrizes` | donate coins the funder already holds into the prize vault |
|
|
37
37
|
| `sellTokens` | `amount`, `minQuoteOutput`, `maxNativeDebit`, `receive?`, `venue?` |
|
|
@@ -43,10 +43,13 @@ On a WSOL pool every builder wraps the SOL its trade needs into the wallet's WSO
|
|
|
43
43
|
that account afterwards, so the wallet spends and receives plain SOL. Closing unwraps any WSOL the
|
|
44
44
|
wallet already held.
|
|
45
45
|
|
|
46
|
-
On any other pool the wallet's quote account is created if missing, and `payWith: 'sol'`
|
|
47
|
-
default) prepends a swap that turns SOL into the quote token. `receive: 'sol'` appends the
|
|
48
|
-
after a sale. `payWith: 'quote'` and `receive: 'quote'` skip the swap. The swap and the
|
|
49
|
-
instruction always share one transaction.
|
|
46
|
+
On any other pool the wallet's quote account is created if missing, and `buyPack`'s `payWith: 'sol'`
|
|
47
|
+
(the default) prepends a swap that turns SOL into the quote token. `receive: 'sol'` appends the
|
|
48
|
+
reverse after a sale. `payWith: 'quote'` and `receive: 'quote'` skip the swap. The swap and the
|
|
49
|
+
Gabox instruction always share one transaction.
|
|
50
|
+
|
|
51
|
+
`createMachine` never swaps. The seed is the creator's own money, in the machine's quote token, so
|
|
52
|
+
the creator must hold at least `maxSeedQuoteIn` of it before the transaction runs.
|
|
50
53
|
|
|
51
54
|
`createMachine` builds one transaction with LaunchLab's `initialize_v2` first and `initialize_pool`
|
|
52
55
|
second. The mint keypair and the creator both sign. It buys a mandatory seed,
|
|
@@ -68,8 +71,9 @@ the VRF request on a pack buy.
|
|
|
68
71
|
`createMachine` takes `quote: { mint }` and `raise`. The quote defaults to wrapped SOL, whose raise
|
|
69
72
|
the program pins per cluster; any other quote needs a `raise` in its own base units, at or above
|
|
70
73
|
`min_quote_fund_raising` in its config. `seedCostEstimate(client, tiers?, { extraSeedTokens?,
|
|
71
|
-
quote?, raise? })` reports the seed cost in the quote token,
|
|
72
|
-
`solAmount
|
|
74
|
+
quote?, raise? })` reports the seed cost in the quote token, which is what the creator pays, plus
|
|
75
|
+
its decimals and symbol, the raise, and `solAmount`: what that cost is worth in SOL through the
|
|
76
|
+
route provider, for a display.
|
|
73
77
|
|
|
74
78
|
## The venue
|
|
75
79
|
|