@lightconexyz/lightcone-sdk 0.8.2 → 0.8.3-rc.43
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/README.md
CHANGED
|
@@ -229,10 +229,13 @@ signed-64-bit admission rules; no tick or size normalization is implicit.
|
|
|
229
229
|
`native_sol_balance` alongside the separate mint-keyed SPL map. Initialize
|
|
230
230
|
`WalletDepositBalancesState` with `applyRestSnapshot(wallet, snapshot)` and feed
|
|
231
231
|
the outer `wallet_deposit_balances` channel's nested snapshot, absolute SPL,
|
|
232
|
-
absolute native-SOL, and status events to `applyEvent()`.
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
232
|
+
absolute native-SOL, and status events to `applyEvent()`. Both methods accept an
|
|
233
|
+
optional minimum snapshot slot; only a complete snapshot below that floor is
|
|
234
|
+
ignored without mutation, while an equal slot and every component/status event
|
|
235
|
+
keep their existing behavior. Without a floor, complete snapshots replace state
|
|
236
|
+
even after a higher component slot. Status and wrong-wallet events do not mutate
|
|
237
|
+
it, pre-baseline component updates are ignored, and explicit-zero SPL updates
|
|
238
|
+
remove their mint. Matching SPL updates with invalid or negative
|
|
236
239
|
idle balances return `rejected` without mutation. `contextSlot` records the latest accepted
|
|
237
240
|
component observation rather than enforcing global monotonic ordering.
|
|
238
241
|
`combinedSolBalance()` sums native SOL and canonical WSOL with `bigint` precision
|
|
@@ -500,7 +503,7 @@ excluded from routine example runs.
|
|
|
500
503
|
|---------|-------------|
|
|
501
504
|
| [`ws_book_and_trades`](examples/ws_book_and_trades.ts) | Live orderbook depth with `OrderbookState` state + rolling `TradeHistory` buffer |
|
|
502
505
|
| [`ws_ticker_and_prices`](examples/ws_ticker_and_prices.ts) | Best bid/ask ticker + price history candles with `PriceHistoryState` |
|
|
503
|
-
| [`ws_user_and_market`](examples/ws_user_and_market.ts) |
|
|
506
|
+
| [`ws_user_and_market`](examples/ws_user_and_market.ts) | Read-only authenticated user/market subscriptions plus one reduced Trading Wallet balance snapshot |
|
|
504
507
|
|
|
505
508
|
## Error Handling
|
|
506
509
|
|
|
@@ -88,19 +88,22 @@ export declare class WalletDepositBalancesState {
|
|
|
88
88
|
nativeSolBalance: string | undefined;
|
|
89
89
|
/**
|
|
90
90
|
* Initialize or wholesale-replace state from a complete REST snapshot.
|
|
91
|
-
* The caller supplies the wallet omitted by REST
|
|
91
|
+
* The caller supplies the wallet omitted by REST. When `minimumSnapshotSlot`
|
|
92
|
+
* is present, a lower complete snapshot is ignored without mutation; otherwise
|
|
93
|
+
* prior slots are not compared.
|
|
92
94
|
* Unlike WebSocket parsing, this TypeScript REST boundary performs no runtime
|
|
93
95
|
* shape validation. Malformed exact values fail when a derived method scales them.
|
|
94
96
|
*/
|
|
95
|
-
applyRestSnapshot(walletAddress: PubkeyStr, snapshot: DepositTokenBalancesSnapshot): WalletDepositBalancesApplyResult;
|
|
97
|
+
applyRestSnapshot(walletAddress: PubkeyStr, snapshot: DepositTokenBalancesSnapshot, minimumSnapshotSlot?: number): WalletDepositBalancesApplyResult;
|
|
96
98
|
/**
|
|
97
99
|
* Apply the wallet event state machine.
|
|
98
100
|
*
|
|
99
|
-
* Complete snapshots
|
|
100
|
-
*
|
|
101
|
-
*
|
|
101
|
+
* Complete snapshots replace state unless they are below an optional minimum
|
|
102
|
+
* snapshot slot. The floor never applies to component or status events.
|
|
103
|
+
* Matching component events replace one absolute value, zero SPL removes its
|
|
104
|
+
* mint, and status, pre-initialization, or wrong-wallet events return `ignored`.
|
|
102
105
|
*/
|
|
103
|
-
applyEvent(event: WalletDepositBalancesEvent): WalletDepositBalancesApplyResult;
|
|
106
|
+
applyEvent(event: WalletDepositBalancesEvent, minimumSnapshotSlot?: number): WalletDepositBalancesApplyResult;
|
|
104
107
|
/**
|
|
105
108
|
* Return exact native SOL plus canonical WSOL with nine fractional digits.
|
|
106
109
|
* Uses arbitrary-width integer arithmetic and never merges the stored assets.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/domain/position/state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EACV,mBAAmB,EACnB,4BAA4B,EAC5B,0BAA0B,EAC3B,MAAM,SAAS,CAAC;AAEjB;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EACsB,SAAS,CAAC;AAE7D,8FAA8F;AAC9F,eAAO,MAAM,0CAA0C,WAAa,CAAC;AACrE,yFAAyF;AACzF,eAAO,MAAM,0CAA0C,WAAa,CAAC;AAIrE,8DAA8D;AAC9D,MAAM,WAAW,oBAAoB;IACnC,0DAA0D;IAC1D,cAAc,EAAE,MAAM,CAAC;IACvB,0EAA0E;IAC1E,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,mBAAmB,EAAE,MAAM,CAAC;IAC5B,8EAA8E;IAC9E,2BAA2B,EAAE,OAAO,CAAC;IACrC,kEAAkE;IAClE,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,qEAAqE;AACrE,MAAM,WAAW,sBAAsB;IACrC,mEAAmE;IACnE,UAAU,EAAE,oBAAoB,CAAC;IACjC,0DAA0D;IAC1D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oFAAoF;IACpF,eAAe,EAAE,MAAM,CAAC;IACxB,iEAAiE;IACjE,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,8FAA8F;AAC9F,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,oBAAoB,EAChC,KAAK,EAAE,cAAc,GACpB,sBAAsB,CA8CxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,oBAAoB,EAChC,KAAK,EAAE,cAAc,GACpB,sBAAsB,CA2CxB;AAED,6EAA6E;AAC7E,MAAM,MAAM,gCAAgC,GACxC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAEzB;;;;;;;;;GASG;AACH,qBAAa,0BAA0B;IACrC,gFAAgF;IAChF,aAAa,EAAE,SAAS,GAAG,SAAS,CAAC;IACrC,gFAAgF;IAChF,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,+EAA+E;IAC/E,QAAQ,CAAC,QAAQ,sCAA6C;IAC9D,+DAA+D;IAC/D,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IAErC
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/domain/position/state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EACV,mBAAmB,EACnB,4BAA4B,EAC5B,0BAA0B,EAC3B,MAAM,SAAS,CAAC;AAEjB;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EACsB,SAAS,CAAC;AAE7D,8FAA8F;AAC9F,eAAO,MAAM,0CAA0C,WAAa,CAAC;AACrE,yFAAyF;AACzF,eAAO,MAAM,0CAA0C,WAAa,CAAC;AAIrE,8DAA8D;AAC9D,MAAM,WAAW,oBAAoB;IACnC,0DAA0D;IAC1D,cAAc,EAAE,MAAM,CAAC;IACvB,0EAA0E;IAC1E,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,mBAAmB,EAAE,MAAM,CAAC;IAC5B,8EAA8E;IAC9E,2BAA2B,EAAE,OAAO,CAAC;IACrC,kEAAkE;IAClE,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,qEAAqE;AACrE,MAAM,WAAW,sBAAsB;IACrC,mEAAmE;IACnE,UAAU,EAAE,oBAAoB,CAAC;IACjC,0DAA0D;IAC1D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oFAAoF;IACpF,eAAe,EAAE,MAAM,CAAC;IACxB,iEAAiE;IACjE,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,8FAA8F;AAC9F,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,oBAAoB,EAChC,KAAK,EAAE,cAAc,GACpB,sBAAsB,CA8CxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,oBAAoB,EAChC,KAAK,EAAE,cAAc,GACpB,sBAAsB,CA2CxB;AAED,6EAA6E;AAC7E,MAAM,MAAM,gCAAgC,GACxC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAEzB;;;;;;;;;GASG;AACH,qBAAa,0BAA0B;IACrC,gFAAgF;IAChF,aAAa,EAAE,SAAS,GAAG,SAAS,CAAC;IACrC,gFAAgF;IAChF,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,+EAA+E;IAC/E,QAAQ,CAAC,QAAQ,sCAA6C;IAC9D,+DAA+D;IAC/D,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IAErC;;;;;;;OAOG;IACH,iBAAiB,CACf,aAAa,EAAE,SAAS,EACxB,QAAQ,EAAE,4BAA4B,EACtC,mBAAmB,CAAC,EAAE,MAAM,GAC3B,gCAAgC;IAgBnC;;;;;;;OAOG;IACH,UAAU,CACR,KAAK,EAAE,0BAA0B,EACjC,mBAAmB,CAAC,EAAE,MAAM,GAC3B,gCAAgC;IA+CnC;;;OAGG;IACH,kBAAkB,IAAI,MAAM;IAS5B,kFAAkF;IAClF,aAAa,IAAI,oBAAoB;IAoBrC,+EAA+E;IAC/E,iBAAiB,IAAI,MAAM;IAO3B,iEAAiE;IACjE,qBAAqB,IAAI,MAAM;IAK/B,OAAO,CAAC,wBAAwB;IAQhC,OAAO,CAAC,OAAO;CAgBhB"}
|
|
@@ -133,24 +133,35 @@ class WalletDepositBalancesState {
|
|
|
133
133
|
nativeSolBalance;
|
|
134
134
|
/**
|
|
135
135
|
* Initialize or wholesale-replace state from a complete REST snapshot.
|
|
136
|
-
* The caller supplies the wallet omitted by REST
|
|
136
|
+
* The caller supplies the wallet omitted by REST. When `minimumSnapshotSlot`
|
|
137
|
+
* is present, a lower complete snapshot is ignored without mutation; otherwise
|
|
138
|
+
* prior slots are not compared.
|
|
137
139
|
* Unlike WebSocket parsing, this TypeScript REST boundary performs no runtime
|
|
138
140
|
* shape validation. Malformed exact values fail when a derived method scales them.
|
|
139
141
|
*/
|
|
140
|
-
applyRestSnapshot(walletAddress, snapshot) {
|
|
142
|
+
applyRestSnapshot(walletAddress, snapshot, minimumSnapshotSlot) {
|
|
143
|
+
if (minimumSnapshotSlot !== undefined &&
|
|
144
|
+
snapshot.context_slot < minimumSnapshotSlot) {
|
|
145
|
+
return { kind: "ignored" };
|
|
146
|
+
}
|
|
141
147
|
this.replace(walletAddress, snapshot.context_slot, snapshot.balances, snapshot.native_sol_balance);
|
|
142
148
|
return { kind: "applied" };
|
|
143
149
|
}
|
|
144
150
|
/**
|
|
145
151
|
* Apply the wallet event state machine.
|
|
146
152
|
*
|
|
147
|
-
* Complete snapshots
|
|
148
|
-
*
|
|
149
|
-
*
|
|
153
|
+
* Complete snapshots replace state unless they are below an optional minimum
|
|
154
|
+
* snapshot slot. The floor never applies to component or status events.
|
|
155
|
+
* Matching component events replace one absolute value, zero SPL removes its
|
|
156
|
+
* mint, and status, pre-initialization, or wrong-wallet events return `ignored`.
|
|
150
157
|
*/
|
|
151
|
-
applyEvent(event) {
|
|
158
|
+
applyEvent(event, minimumSnapshotSlot) {
|
|
152
159
|
switch (event.event_type) {
|
|
153
160
|
case "wallet_deposit_balance_snapshot":
|
|
161
|
+
if (minimumSnapshotSlot !== undefined &&
|
|
162
|
+
event.context_slot < minimumSnapshotSlot) {
|
|
163
|
+
return { kind: "ignored" };
|
|
164
|
+
}
|
|
154
165
|
// Complete snapshots are authoritative even when their lower
|
|
155
166
|
// cross-component slot trails a previously observed update.
|
|
156
167
|
this.replace(event.wallet_address, event.context_slot, event.balances, event.native_sol_balance);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/domain/position/state.ts"],"names":[],"mappings":"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","sourcesContent":["import Decimal from \"decimal.js\";\nimport { SdkError } from \"../../error\";\nimport { exactScaledInteger } from \"../../shared\";\nimport type { PubkeyStr } from \"../../shared\";\nimport type {\n DepositTokenBalance,\n DepositTokenBalancesSnapshot,\n WalletDepositBalancesEvent,\n} from \"./index\";\n\n/**\n * Canonical WSOL mint under Solana's legacy SPL Token Program (“Tokenkeg”).\n * ATA derivation stays pinned to Tokenkeg rather than Token-2022 so state and\n * transaction planning address the protocol's one canonical account.\n */\nexport const WRAPPED_SOL_MINT =\n \"So11111111111111111111111111111111111111112\" as PubkeyStr;\n\n/** Unsponsored native reserve floor, in lamports, when canonical ATA creation is required. */\nexport const SOL_RESERVE_WITH_ACCOUNT_CREATION_LAMPORTS = 3_500_000n;\n/** Unsponsored native reserve floor, in lamports, when canonical WSOL already exists. */\nexport const SOL_RESERVE_WITH_EXISTING_ACCOUNT_LAMPORTS = 1_000_000n;\n/** Maximum exact non-negative lamport value representable by Solana's u64 fields. */\nconst MAX_SOLANA_LAMPORTS = 0xffff_ffff_ffff_ffffn;\n\n/** Exact components behind the single displayed SOL asset. */\nexport interface SolBalanceComponents {\n /** Lamports held by the Trading Wallet system account. */\n nativeLamports: bigint;\n /** Token amount in the Trading Wallet's persistent canonical WSOL ATA. */\n canonicalWsolLamports: bigint;\n}\n\n/**\n * Stores live chain costs used to derive transaction funding requirements.\n *\n * {@link solBalanceAvailability} applies ordinary safety floors.\n * {@link unwrapAllSolBalanceAvailability} rejects account creation, upfront rent,\n * and sponsorship, then uses only `feeLamports` as the unwrap-all reserve.\n */\nexport interface SolActionCosts {\n /** Live `getFeeForMessage` result, in lamports. */\n feeLamports: bigint;\n /** Rent funded up front, even when a temporary account refunds it later. */\n upfrontRentLamports: bigint;\n /** Whether this transaction must create the persistent canonical WSOL ATA. */\n createsCanonicalWsolAccount: boolean;\n /** Exact public sponsorship capability supplied by the caller. */\n sponsored: boolean;\n}\n\n/** Action-specific displayed, reserved, and spendable SOL values. */\nexport interface SolBalanceAvailability {\n /** Separately authoritative native and canonical WSOL balances. */\n components: SolBalanceComponents;\n /** Sum of both components in lamports, before reserve. */\n displayedLamports: bigint;\n /** Native lamports withheld for live costs and any action-specific safety floor. */\n reserveLamports: bigint;\n /** Displayed lamports available to this action after reserve. */\n spendableLamports: bigint;\n}\n\n/** Derive fail-closed availability and type an insufficient native reserve as fee funding. */\nexport function solBalanceAvailability(\n components: SolBalanceComponents,\n costs: SolActionCosts\n): SolBalanceAvailability {\n for (const [label, value] of [\n [\"native SOL\", components.nativeLamports],\n [\"canonical WSOL\", components.canonicalWsolLamports],\n ] as const) {\n if (typeof value !== \"bigint\" || value < 0n || value > MAX_SOLANA_LAMPORTS) {\n throw SdkError.validation(`${label} must fit the non-negative u64 lamport range`);\n }\n }\n for (const [label, value] of [\n [\"transaction fee\", costs.feeLamports],\n [\"upfront rent\", costs.upfrontRentLamports],\n ] as const) {\n if (typeof value !== \"bigint\" || value < 0n || value > MAX_SOLANA_LAMPORTS) {\n throw SdkError.validation(`${label} must fit the non-negative u64 lamport range`);\n }\n }\n const displayedLamports =\n components.nativeLamports + components.canonicalWsolLamports;\n if (displayedLamports > MAX_SOLANA_LAMPORTS) {\n throw SdkError.validation(\"displayed SOL exceeds the transaction u64 range\");\n }\n const liveCosts = costs.feeLamports + costs.upfrontRentLamports;\n if (liveCosts > MAX_SOLANA_LAMPORTS) {\n throw SdkError.validation(\"combined transaction costs must fit u64 lamports\");\n }\n const floor = costs.createsCanonicalWsolAccount\n ? SOL_RESERVE_WITH_ACCOUNT_CREATION_LAMPORTS\n : SOL_RESERVE_WITH_EXISTING_ACCOUNT_LAMPORTS;\n const reserveLamports = costs.sponsored\n ? 0n\n : liveCosts > floor\n ? liveCosts\n : floor;\n if (components.nativeLamports < reserveLamports) {\n throw SdkError.insufficientSolForTransactionFees(\n components.nativeLamports,\n reserveLamports\n );\n }\n return {\n components,\n displayedLamports,\n reserveLamports,\n spendableLamports: displayedLamports - reserveLamports,\n };\n}\n\n/**\n * Return unwrap-all availability with the live fee as its entire reserve.\n *\n * This function rejects costs that include sponsorship, account creation, or\n * upfront rent. It rejects malformed or out-of-range components and costs. It\n * rejects a displayed-balance sum outside Solana's unsigned 64-bit range. Native\n * SOL must fund the fee without relying on lamports that a later `CloseAccount`\n * instruction may transfer. The ordinary persistent-account floor does not apply\n * because unwrap-all removes that account. An insufficient native fee balance\n * returns the typed transaction-fee error.\n */\nexport function unwrapAllSolBalanceAvailability(\n components: SolBalanceComponents,\n costs: SolActionCosts\n): SolBalanceAvailability {\n for (const [label, value] of [\n [\"native SOL\", components.nativeLamports],\n [\"canonical WSOL\", components.canonicalWsolLamports],\n ] as const) {\n if (typeof value !== \"bigint\" || value < 0n || value > MAX_SOLANA_LAMPORTS) {\n throw SdkError.validation(`${label} must fit the non-negative u64 lamport range`);\n }\n }\n for (const [label, value] of [\n [\"transaction fee\", costs.feeLamports],\n [\"upfront rent\", costs.upfrontRentLamports],\n ] as const) {\n if (typeof value !== \"bigint\" || value < 0n || value > MAX_SOLANA_LAMPORTS) {\n throw SdkError.validation(`${label} must fit the non-negative u64 lamport range`);\n }\n }\n if (\n costs.upfrontRentLamports !== 0n ||\n costs.createsCanonicalWsolAccount ||\n costs.sponsored\n ) {\n throw SdkError.validation(\n \"unwrap-all costs must be unsponsored with no upfront rent or account creation\"\n );\n }\n const displayedLamports =\n components.nativeLamports + components.canonicalWsolLamports;\n if (displayedLamports > MAX_SOLANA_LAMPORTS) {\n throw SdkError.validation(\"displayed SOL exceeds the transaction u64 range\");\n }\n if (components.nativeLamports < costs.feeLamports) {\n throw SdkError.insufficientSolForTransactionFees(\n components.nativeLamports,\n costs.feeLamports\n );\n }\n return {\n components,\n displayedLamports,\n reserveLamports: costs.feeLamports,\n spendableLamports: displayedLamports - costs.feeLamports,\n };\n}\n\n/** Whether an event was accepted by, or rejected by, its lifecycle guard. */\nexport type WalletDepositBalancesApplyResult =\n | { kind: \"applied\" }\n | { kind: \"ignored\" }\n | { kind: \"rejected\" };\n\n/**\n * Mutable application-owned wallet balance state.\n *\n * The default instance is uninitialized. A complete REST or WebSocket snapshot\n * establishes its wallet baseline; later component events must match that wallet\n * and carry absolute values. Native SOL never enters the sparse SPL mint map, and\n * complete cross-component snapshots may replace `contextSlot` with a lower slot.\n * Map containers are copied, but mutable balance objects are retained by reference;\n * treat payload entries as immutable after applying them.\n */\nexport class WalletDepositBalancesState {\n /** Wallet owning the current baseline, or `undefined` before initialization. */\n walletAddress: PubkeyStr | undefined;\n /** Slot of the last accepted event, not a globally monotonic stream version. */\n contextSlot: number | undefined;\n /** Sparse mint-keyed SPL balances; explicit zero updates remove their mint. */\n readonly balances = new Map<PubkeyStr, DepositTokenBalance>();\n /** Exact nine-decimal native SOL, separate from `balances`. */\n nativeSolBalance: string | undefined;\n\n /**\n * Initialize or wholesale-replace state from a complete REST snapshot.\n * The caller supplies the wallet omitted by REST; prior slots are not compared.\n * Unlike WebSocket parsing, this TypeScript REST boundary performs no runtime\n * shape validation. Malformed exact values fail when a derived method scales them.\n */\n applyRestSnapshot(\n walletAddress: PubkeyStr,\n snapshot: DepositTokenBalancesSnapshot\n ): WalletDepositBalancesApplyResult {\n this.replace(\n walletAddress,\n snapshot.context_slot,\n snapshot.balances,\n snapshot.native_sol_balance\n );\n return { kind: \"applied\" };\n }\n\n /**\n * Apply the wallet event state machine.\n *\n * Complete snapshots always replace state. Matching component events replace\n * one absolute value, zero SPL removes its mint, and status, pre-initialization,\n * or wrong-wallet events return `ignored` without mutation.\n */\n applyEvent(event: WalletDepositBalancesEvent): WalletDepositBalancesApplyResult {\n switch (event.event_type) {\n case \"wallet_deposit_balance_snapshot\":\n // Complete snapshots are authoritative even when their lower\n // cross-component slot trails a previously observed update.\n this.replace(\n event.wallet_address,\n event.context_slot,\n event.balances,\n event.native_sol_balance\n );\n return { kind: \"applied\" };\n case \"wallet_deposit_balance_update\":\n if (!this.matchesInitializedWallet(event.wallet_address)) {\n return { kind: \"ignored\" };\n }\n let isZero: boolean;\n try {\n isZero = isZeroTokenAmount(event.balance.idle);\n } catch {\n return { kind: \"rejected\" };\n }\n if (isZero) {\n this.balances.delete(event.balance.mint);\n } else {\n this.balances.set(event.balance.mint, event.balance);\n }\n this.contextSlot = event.context_slot;\n return { kind: \"applied\" };\n case \"wallet_native_sol_balance_update\":\n if (!this.matchesInitializedWallet(event.wallet_address)) {\n return { kind: \"ignored\" };\n }\n this.nativeSolBalance = event.native_sol_balance;\n this.contextSlot = event.context_slot;\n return { kind: \"applied\" };\n case \"wallet_deposit_balance_status\":\n return { kind: \"ignored\" };\n }\n }\n\n /**\n * Return exact native SOL plus canonical WSOL with nine fractional digits.\n * Uses arbitrary-width integer arithmetic and never merges the stored assets.\n */\n combinedSolBalance(): string {\n const native = this.nativeSolLamports();\n const wrapped = this.balances.get(WRAPPED_SOL_MINT);\n const wrappedLamports = wrapped\n ? exactScaledInteger(wrapped.idle, 9)\n : 0n;\n return formatLamports(native + wrappedLamports);\n }\n\n /** Return exact native and canonical WSOL components for transaction planning. */\n solComponents(): SolBalanceComponents {\n let nativeLamports: bigint;\n let canonicalWsolLamports: bigint;\n try {\n nativeLamports = this.nativeSolLamports();\n canonicalWsolLamports = this.canonicalWsolLamports();\n } catch (error) {\n throw SdkError.validation(\n `invalid SOL balance component: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n if (\n nativeLamports > MAX_SOLANA_LAMPORTS ||\n canonicalWsolLamports > MAX_SOLANA_LAMPORTS\n ) {\n throw SdkError.validation(\"SOL component exceeds the transaction u64 range\");\n }\n return { nativeLamports, canonicalWsolLamports };\n }\n\n /** Scale cached native SOL exactly to lamports; requires initialized state. */\n nativeSolLamports(): bigint {\n if (this.nativeSolBalance === undefined) {\n throw new Error(\"wallet balance state is not initialized\");\n }\n return exactScaledInteger(this.nativeSolBalance, 9);\n }\n\n /** Scale the canonical WSOL idle balance exactly to lamports. */\n canonicalWsolLamports(): bigint {\n const wrapped = this.balances.get(WRAPPED_SOL_MINT);\n return wrapped ? exactScaledInteger(wrapped.idle, 9) : 0n;\n }\n\n private matchesInitializedWallet(walletAddress: PubkeyStr): boolean {\n return (\n this.walletAddress === walletAddress &&\n this.contextSlot !== undefined &&\n this.nativeSolBalance !== undefined\n );\n }\n\n private replace(\n walletAddress: PubkeyStr,\n contextSlot: number,\n balances: Record<PubkeyStr, DepositTokenBalance>,\n nativeSolBalance: string\n ): void {\n // Own the map lifecycle while retaining payload objects by reference. Callers\n // must treat balance records as immutable after handing them to state.\n this.walletAddress = walletAddress;\n this.contextSlot = contextSlot;\n this.balances.clear();\n for (const balance of Object.values(balances)) {\n this.balances.set(balance.mint, balance);\n }\n this.nativeSolBalance = nativeSolBalance;\n }\n}\n\nfunction formatLamports(value: bigint): string {\n // Integer division restores fixed-scale SOL text without floating-point loss.\n const scale = 1_000_000_000n;\n const whole = value / scale;\n const fraction = (value % scale).toString().padStart(9, \"0\");\n return `${whole}.${fraction}`;\n}\n\n/** Detect explicit zero without imposing SOL's nine-decimal scale on SPL tokens. */\nfunction isZeroTokenAmount(value: string): boolean {\n const amount = new Decimal(value);\n if (!amount.isFinite() || amount.isNegative()) {\n throw new Error(`invalid deposit-token balance: ${value}`);\n }\n return amount.isZero();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/domain/position/state.ts"],"names":[],"mappings":"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","sourcesContent":["import Decimal from \"decimal.js\";\nimport { SdkError } from \"../../error\";\nimport { exactScaledInteger } from \"../../shared\";\nimport type { PubkeyStr } from \"../../shared\";\nimport type {\n DepositTokenBalance,\n DepositTokenBalancesSnapshot,\n WalletDepositBalancesEvent,\n} from \"./index\";\n\n/**\n * Canonical WSOL mint under Solana's legacy SPL Token Program (“Tokenkeg”).\n * ATA derivation stays pinned to Tokenkeg rather than Token-2022 so state and\n * transaction planning address the protocol's one canonical account.\n */\nexport const WRAPPED_SOL_MINT =\n \"So11111111111111111111111111111111111111112\" as PubkeyStr;\n\n/** Unsponsored native reserve floor, in lamports, when canonical ATA creation is required. */\nexport const SOL_RESERVE_WITH_ACCOUNT_CREATION_LAMPORTS = 3_500_000n;\n/** Unsponsored native reserve floor, in lamports, when canonical WSOL already exists. */\nexport const SOL_RESERVE_WITH_EXISTING_ACCOUNT_LAMPORTS = 1_000_000n;\n/** Maximum exact non-negative lamport value representable by Solana's u64 fields. */\nconst MAX_SOLANA_LAMPORTS = 0xffff_ffff_ffff_ffffn;\n\n/** Exact components behind the single displayed SOL asset. */\nexport interface SolBalanceComponents {\n /** Lamports held by the Trading Wallet system account. */\n nativeLamports: bigint;\n /** Token amount in the Trading Wallet's persistent canonical WSOL ATA. */\n canonicalWsolLamports: bigint;\n}\n\n/**\n * Stores live chain costs used to derive transaction funding requirements.\n *\n * {@link solBalanceAvailability} applies ordinary safety floors.\n * {@link unwrapAllSolBalanceAvailability} rejects account creation, upfront rent,\n * and sponsorship, then uses only `feeLamports` as the unwrap-all reserve.\n */\nexport interface SolActionCosts {\n /** Live `getFeeForMessage` result, in lamports. */\n feeLamports: bigint;\n /** Rent funded up front, even when a temporary account refunds it later. */\n upfrontRentLamports: bigint;\n /** Whether this transaction must create the persistent canonical WSOL ATA. */\n createsCanonicalWsolAccount: boolean;\n /** Exact public sponsorship capability supplied by the caller. */\n sponsored: boolean;\n}\n\n/** Action-specific displayed, reserved, and spendable SOL values. */\nexport interface SolBalanceAvailability {\n /** Separately authoritative native and canonical WSOL balances. */\n components: SolBalanceComponents;\n /** Sum of both components in lamports, before reserve. */\n displayedLamports: bigint;\n /** Native lamports withheld for live costs and any action-specific safety floor. */\n reserveLamports: bigint;\n /** Displayed lamports available to this action after reserve. */\n spendableLamports: bigint;\n}\n\n/** Derive fail-closed availability and type an insufficient native reserve as fee funding. */\nexport function solBalanceAvailability(\n components: SolBalanceComponents,\n costs: SolActionCosts\n): SolBalanceAvailability {\n for (const [label, value] of [\n [\"native SOL\", components.nativeLamports],\n [\"canonical WSOL\", components.canonicalWsolLamports],\n ] as const) {\n if (typeof value !== \"bigint\" || value < 0n || value > MAX_SOLANA_LAMPORTS) {\n throw SdkError.validation(`${label} must fit the non-negative u64 lamport range`);\n }\n }\n for (const [label, value] of [\n [\"transaction fee\", costs.feeLamports],\n [\"upfront rent\", costs.upfrontRentLamports],\n ] as const) {\n if (typeof value !== \"bigint\" || value < 0n || value > MAX_SOLANA_LAMPORTS) {\n throw SdkError.validation(`${label} must fit the non-negative u64 lamport range`);\n }\n }\n const displayedLamports =\n components.nativeLamports + components.canonicalWsolLamports;\n if (displayedLamports > MAX_SOLANA_LAMPORTS) {\n throw SdkError.validation(\"displayed SOL exceeds the transaction u64 range\");\n }\n const liveCosts = costs.feeLamports + costs.upfrontRentLamports;\n if (liveCosts > MAX_SOLANA_LAMPORTS) {\n throw SdkError.validation(\"combined transaction costs must fit u64 lamports\");\n }\n const floor = costs.createsCanonicalWsolAccount\n ? SOL_RESERVE_WITH_ACCOUNT_CREATION_LAMPORTS\n : SOL_RESERVE_WITH_EXISTING_ACCOUNT_LAMPORTS;\n const reserveLamports = costs.sponsored\n ? 0n\n : liveCosts > floor\n ? liveCosts\n : floor;\n if (components.nativeLamports < reserveLamports) {\n throw SdkError.insufficientSolForTransactionFees(\n components.nativeLamports,\n reserveLamports\n );\n }\n return {\n components,\n displayedLamports,\n reserveLamports,\n spendableLamports: displayedLamports - reserveLamports,\n };\n}\n\n/**\n * Return unwrap-all availability with the live fee as its entire reserve.\n *\n * This function rejects costs that include sponsorship, account creation, or\n * upfront rent. It rejects malformed or out-of-range components and costs. It\n * rejects a displayed-balance sum outside Solana's unsigned 64-bit range. Native\n * SOL must fund the fee without relying on lamports that a later `CloseAccount`\n * instruction may transfer. The ordinary persistent-account floor does not apply\n * because unwrap-all removes that account. An insufficient native fee balance\n * returns the typed transaction-fee error.\n */\nexport function unwrapAllSolBalanceAvailability(\n components: SolBalanceComponents,\n costs: SolActionCosts\n): SolBalanceAvailability {\n for (const [label, value] of [\n [\"native SOL\", components.nativeLamports],\n [\"canonical WSOL\", components.canonicalWsolLamports],\n ] as const) {\n if (typeof value !== \"bigint\" || value < 0n || value > MAX_SOLANA_LAMPORTS) {\n throw SdkError.validation(`${label} must fit the non-negative u64 lamport range`);\n }\n }\n for (const [label, value] of [\n [\"transaction fee\", costs.feeLamports],\n [\"upfront rent\", costs.upfrontRentLamports],\n ] as const) {\n if (typeof value !== \"bigint\" || value < 0n || value > MAX_SOLANA_LAMPORTS) {\n throw SdkError.validation(`${label} must fit the non-negative u64 lamport range`);\n }\n }\n if (\n costs.upfrontRentLamports !== 0n ||\n costs.createsCanonicalWsolAccount ||\n costs.sponsored\n ) {\n throw SdkError.validation(\n \"unwrap-all costs must be unsponsored with no upfront rent or account creation\"\n );\n }\n const displayedLamports =\n components.nativeLamports + components.canonicalWsolLamports;\n if (displayedLamports > MAX_SOLANA_LAMPORTS) {\n throw SdkError.validation(\"displayed SOL exceeds the transaction u64 range\");\n }\n if (components.nativeLamports < costs.feeLamports) {\n throw SdkError.insufficientSolForTransactionFees(\n components.nativeLamports,\n costs.feeLamports\n );\n }\n return {\n components,\n displayedLamports,\n reserveLamports: costs.feeLamports,\n spendableLamports: displayedLamports - costs.feeLamports,\n };\n}\n\n/** Whether an event was accepted by, or rejected by, its lifecycle guard. */\nexport type WalletDepositBalancesApplyResult =\n | { kind: \"applied\" }\n | { kind: \"ignored\" }\n | { kind: \"rejected\" };\n\n/**\n * Mutable application-owned wallet balance state.\n *\n * The default instance is uninitialized. A complete REST or WebSocket snapshot\n * establishes its wallet baseline; later component events must match that wallet\n * and carry absolute values. Native SOL never enters the sparse SPL mint map, and\n * complete cross-component snapshots may replace `contextSlot` with a lower slot.\n * Map containers are copied, but mutable balance objects are retained by reference;\n * treat payload entries as immutable after applying them.\n */\nexport class WalletDepositBalancesState {\n /** Wallet owning the current baseline, or `undefined` before initialization. */\n walletAddress: PubkeyStr | undefined;\n /** Slot of the last accepted event, not a globally monotonic stream version. */\n contextSlot: number | undefined;\n /** Sparse mint-keyed SPL balances; explicit zero updates remove their mint. */\n readonly balances = new Map<PubkeyStr, DepositTokenBalance>();\n /** Exact nine-decimal native SOL, separate from `balances`. */\n nativeSolBalance: string | undefined;\n\n /**\n * Initialize or wholesale-replace state from a complete REST snapshot.\n * The caller supplies the wallet omitted by REST. When `minimumSnapshotSlot`\n * is present, a lower complete snapshot is ignored without mutation; otherwise\n * prior slots are not compared.\n * Unlike WebSocket parsing, this TypeScript REST boundary performs no runtime\n * shape validation. Malformed exact values fail when a derived method scales them.\n */\n applyRestSnapshot(\n walletAddress: PubkeyStr,\n snapshot: DepositTokenBalancesSnapshot,\n minimumSnapshotSlot?: number\n ): WalletDepositBalancesApplyResult {\n if (\n minimumSnapshotSlot !== undefined &&\n snapshot.context_slot < minimumSnapshotSlot\n ) {\n return { kind: \"ignored\" };\n }\n this.replace(\n walletAddress,\n snapshot.context_slot,\n snapshot.balances,\n snapshot.native_sol_balance\n );\n return { kind: \"applied\" };\n }\n\n /**\n * Apply the wallet event state machine.\n *\n * Complete snapshots replace state unless they are below an optional minimum\n * snapshot slot. The floor never applies to component or status events.\n * Matching component events replace one absolute value, zero SPL removes its\n * mint, and status, pre-initialization, or wrong-wallet events return `ignored`.\n */\n applyEvent(\n event: WalletDepositBalancesEvent,\n minimumSnapshotSlot?: number\n ): WalletDepositBalancesApplyResult {\n switch (event.event_type) {\n case \"wallet_deposit_balance_snapshot\":\n if (\n minimumSnapshotSlot !== undefined &&\n event.context_slot < minimumSnapshotSlot\n ) {\n return { kind: \"ignored\" };\n }\n // Complete snapshots are authoritative even when their lower\n // cross-component slot trails a previously observed update.\n this.replace(\n event.wallet_address,\n event.context_slot,\n event.balances,\n event.native_sol_balance\n );\n return { kind: \"applied\" };\n case \"wallet_deposit_balance_update\":\n if (!this.matchesInitializedWallet(event.wallet_address)) {\n return { kind: \"ignored\" };\n }\n let isZero: boolean;\n try {\n isZero = isZeroTokenAmount(event.balance.idle);\n } catch {\n return { kind: \"rejected\" };\n }\n if (isZero) {\n this.balances.delete(event.balance.mint);\n } else {\n this.balances.set(event.balance.mint, event.balance);\n }\n this.contextSlot = event.context_slot;\n return { kind: \"applied\" };\n case \"wallet_native_sol_balance_update\":\n if (!this.matchesInitializedWallet(event.wallet_address)) {\n return { kind: \"ignored\" };\n }\n this.nativeSolBalance = event.native_sol_balance;\n this.contextSlot = event.context_slot;\n return { kind: \"applied\" };\n case \"wallet_deposit_balance_status\":\n return { kind: \"ignored\" };\n }\n }\n\n /**\n * Return exact native SOL plus canonical WSOL with nine fractional digits.\n * Uses arbitrary-width integer arithmetic and never merges the stored assets.\n */\n combinedSolBalance(): string {\n const native = this.nativeSolLamports();\n const wrapped = this.balances.get(WRAPPED_SOL_MINT);\n const wrappedLamports = wrapped\n ? exactScaledInteger(wrapped.idle, 9)\n : 0n;\n return formatLamports(native + wrappedLamports);\n }\n\n /** Return exact native and canonical WSOL components for transaction planning. */\n solComponents(): SolBalanceComponents {\n let nativeLamports: bigint;\n let canonicalWsolLamports: bigint;\n try {\n nativeLamports = this.nativeSolLamports();\n canonicalWsolLamports = this.canonicalWsolLamports();\n } catch (error) {\n throw SdkError.validation(\n `invalid SOL balance component: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n if (\n nativeLamports > MAX_SOLANA_LAMPORTS ||\n canonicalWsolLamports > MAX_SOLANA_LAMPORTS\n ) {\n throw SdkError.validation(\"SOL component exceeds the transaction u64 range\");\n }\n return { nativeLamports, canonicalWsolLamports };\n }\n\n /** Scale cached native SOL exactly to lamports; requires initialized state. */\n nativeSolLamports(): bigint {\n if (this.nativeSolBalance === undefined) {\n throw new Error(\"wallet balance state is not initialized\");\n }\n return exactScaledInteger(this.nativeSolBalance, 9);\n }\n\n /** Scale the canonical WSOL idle balance exactly to lamports. */\n canonicalWsolLamports(): bigint {\n const wrapped = this.balances.get(WRAPPED_SOL_MINT);\n return wrapped ? exactScaledInteger(wrapped.idle, 9) : 0n;\n }\n\n private matchesInitializedWallet(walletAddress: PubkeyStr): boolean {\n return (\n this.walletAddress === walletAddress &&\n this.contextSlot !== undefined &&\n this.nativeSolBalance !== undefined\n );\n }\n\n private replace(\n walletAddress: PubkeyStr,\n contextSlot: number,\n balances: Record<PubkeyStr, DepositTokenBalance>,\n nativeSolBalance: string\n ): void {\n // Own the map lifecycle while retaining payload objects by reference. Callers\n // must treat balance records as immutable after handing them to state.\n this.walletAddress = walletAddress;\n this.contextSlot = contextSlot;\n this.balances.clear();\n for (const balance of Object.values(balances)) {\n this.balances.set(balance.mint, balance);\n }\n this.nativeSolBalance = nativeSolBalance;\n }\n}\n\nfunction formatLamports(value: bigint): string {\n // Integer division restores fixed-scale SOL text without floating-point loss.\n const scale = 1_000_000_000n;\n const whole = value / scale;\n const fraction = (value % scale).toString().padStart(9, \"0\");\n return `${whole}.${fraction}`;\n}\n\n/** Detect explicit zero without imposing SOL's nine-decimal scale on SPL tokens. */\nfunction isZeroTokenAmount(value: string): boolean {\n const amount = new Decimal(value);\n if (!amount.isFinite() || amount.isNegative()) {\n throw new Error(`invalid deposit-token balance: ${value}`);\n }\n return amount.isZero();\n}\n"]}
|