@vultisig/core-chain 2.24.2 → 2.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/amount/toChainAmount.d.ts.map +1 -1
  3. package/dist/amount/toChainAmount.js +5 -3
  4. package/dist/amount/toChainAmount.js.map +1 -1
  5. package/dist/chains/ripple/account/lines.d.ts +13 -0
  6. package/dist/chains/ripple/account/lines.d.ts.map +1 -0
  7. package/dist/chains/ripple/account/lines.js +28 -0
  8. package/dist/chains/ripple/account/lines.js.map +1 -0
  9. package/dist/chains/ripple/issuedCurrency.d.ts +17 -3
  10. package/dist/chains/ripple/issuedCurrency.d.ts.map +1 -1
  11. package/dist/chains/ripple/issuedCurrency.js +30 -3
  12. package/dist/chains/ripple/issuedCurrency.js.map +1 -1
  13. package/dist/chains/solana/assertSafeSolanaSwapInstructions.d.ts +96 -0
  14. package/dist/chains/solana/assertSafeSolanaSwapInstructions.d.ts.map +1 -0
  15. package/dist/chains/solana/assertSafeSolanaSwapInstructions.js +260 -0
  16. package/dist/chains/solana/assertSafeSolanaSwapInstructions.js.map +1 -0
  17. package/dist/coin/balance/resolvers/ripple.d.ts.map +1 -1
  18. package/dist/coin/balance/resolvers/ripple.js +40 -3
  19. package/dist/coin/balance/resolvers/ripple.js.map +1 -1
  20. package/dist/coin/find/CoinFinderChainKind.d.ts +1 -1
  21. package/dist/coin/find/CoinFinderChainKind.d.ts.map +1 -1
  22. package/dist/coin/find/CoinFinderChainKind.js +1 -1
  23. package/dist/coin/find/CoinFinderChainKind.js.map +1 -1
  24. package/dist/coin/find/index.d.ts.map +1 -1
  25. package/dist/coin/find/index.js +2 -0
  26. package/dist/coin/find/index.js.map +1 -1
  27. package/dist/coin/find/resolvers/ripple.d.ts +12 -0
  28. package/dist/coin/find/resolvers/ripple.d.ts.map +1 -0
  29. package/dist/coin/find/resolvers/ripple.js +50 -0
  30. package/dist/coin/find/resolvers/ripple.js.map +1 -0
  31. package/dist/coin/knownTokens/index.d.ts.map +1 -1
  32. package/dist/coin/knownTokens/index.js +2 -0
  33. package/dist/coin/knownTokens/index.js.map +1 -1
  34. package/dist/swap/general/jupiter/api/getJupiterSwapQuote.d.ts.map +1 -1
  35. package/dist/swap/general/jupiter/api/getJupiterSwapQuote.js +9 -0
  36. package/dist/swap/general/jupiter/api/getJupiterSwapQuote.js.map +1 -1
  37. package/dist/swap/general/jupiter/api/jupiterFeeAta.d.ts +2 -1
  38. package/dist/swap/general/jupiter/api/jupiterFeeAta.d.ts.map +1 -1
  39. package/dist/swap/general/jupiter/api/jupiterFeeAta.js +7 -35
  40. package/dist/swap/general/jupiter/api/jupiterFeeAta.js.map +1 -1
  41. package/fixtures/jupiter-swap-transactions.json +30 -0
  42. package/package.json +17 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @vultisig/core-chain
2
2
 
3
+ ## 2.25.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#1169](https://github.com/vultisig/vultisig-sdk/pull/1169) [`1ef64a3`](https://github.com/vultisig/vultisig-sdk/commit/1ef64a39f856d9f1d412df8f5e69c66f7130d8c7) Thanks [@Ehsan-saradar](https://github.com/Ehsan-saradar)! - Surface XRP issued-currency (trust-line) token balances.
8
+
9
+ - `getRippleAccountLines` reads an account's trust lines, following `account_lines` pagination so a large set is not truncated.
10
+ - `getRippleCoinBalance` now dispatches on the coin id: native XRP still returns the reserve-adjusted spendable balance, while an issued-currency coin returns that trust line's balance. Previously the resolver ignored the id and returned the XRP balance for _every_ Ripple coin, so a token row displayed the account's XRP balance.
11
+ - `findRippleCoins` discovers held trust lines for the coin finder, so XRPL tokens appear in the asset list. Lines with a negative balance (the account is the issuer and owes the counterparty) and zero-balance lines are excluded.
12
+ - `rippleKnownIssuedTokens` (RLUSD) is now wired into `knownTokens`, so it is selectable before a trust line exists.
13
+
14
+ ## 2.24.3
15
+
16
+ ### Patch Changes
17
+
18
+ - [#1115](https://github.com/vultisig/vultisig-sdk/pull/1115) [`4483754`](https://github.com/vultisig/vultisig-sdk/commit/4483754748190fe25654de79fc12fba0edb73963) Thanks [@rcoderdev](https://github.com/rcoderdev)! - Expand large scientific-notation numeric amounts before base-unit parsing.
19
+
3
20
  ## 2.24.2
4
21
 
5
22
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"toChainAmount.d.ts","sourceRoot":"","sources":["../../../../../packages/core/chain/amount/toChainAmount.ts"],"names":[],"mappings":"AAEA,iFAAiF;AACjF,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,SAAkB,IAAI,2BAA0B;gBAEpC,OAAO,EAAE,MAAM;CAG5B;AA+FD,eAAO,MAAM,aAAa,GAAI,QAAQ,MAAM,GAAG,MAAM,EAAE,UAAU,MAAM,WAetE,CAAA"}
1
+ {"version":3,"file":"toChainAmount.d.ts","sourceRoot":"","sources":["../../../../../packages/core/chain/amount/toChainAmount.ts"],"names":[],"mappings":"AAEA,iFAAiF;AACjF,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,SAAkB,IAAI,2BAA0B;gBAEpC,OAAO,EAAE,MAAM;CAG5B;AAoGD,eAAO,MAAM,aAAa,GAAI,QAAQ,MAAM,GAAG,MAAM,EAAE,UAAU,MAAM,WAatE,CAAA"}
@@ -75,6 +75,10 @@ const expandScientificNotationToDecimalString = (s) => {
75
75
  }
76
76
  return absResult;
77
77
  };
78
+ const formatNumberAmount = (amount) => {
79
+ const str = amount.toString();
80
+ return /[eE]/.test(str) ? expandScientificNotationToDecimalString(str) : str;
81
+ };
78
82
  /**
79
83
  * Truncate a plain decimal string to at most `decimals` fractional digits so
80
84
  * parseUnits cannot round up. viem's parseUnits rounds half-up at decimals=0
@@ -105,8 +109,6 @@ export const toChainAmount = (amount, decimals) => {
105
109
  }
106
110
  return parseUnits(truncateToDecimals(trimmed, decimals), decimals);
107
111
  }
108
- const str = amount.toString();
109
- const value = /[eE]/.test(str) ? amount.toFixed(decimals) : str;
110
- return parseUnits(truncateToDecimals(value, decimals), decimals);
112
+ return parseUnits(truncateToDecimals(formatNumberAmount(amount), decimals), decimals);
111
113
  };
112
114
  //# sourceMappingURL=toChainAmount.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"toChainAmount.js","sourceRoot":"","sources":["../../../../../packages/core/chain/amount/toChainAmount.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"toChainAmount.js","sourceRoot":"","sources":["../../../../../packages/core/chain/amount/toChainAmount.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { AccountLinesTrustline } from 'xrpl';
2
+ /**
3
+ * Every trust line held by `address`, following `account_lines` pagination to
4
+ * completion. The XRP Ledger returns trust lines in pages, so a single request
5
+ * would silently truncate the set of an account with many lines and hide token
6
+ * balances rather than fail.
7
+ *
8
+ * Balances are signed from `address`'s perspective: a negative balance means
9
+ * `address` is the issuer and owes the counterparty, not that it holds the token.
10
+ * @see https://xrpl.org/docs/references/http-websocket-apis/public-api-methods/account-methods/account_lines
11
+ */
12
+ export declare const getRippleAccountLines: (address: string) => Promise<AccountLinesTrustline[]>;
13
+ //# sourceMappingURL=lines.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lines.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/ripple/account/lines.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,MAAM,CAAA;AAI5C;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,qBAAqB,EAAE,CAmB5F,CAAA"}
@@ -0,0 +1,28 @@
1
+ import { getRippleClient } from '../client.js';
2
+ /**
3
+ * Every trust line held by `address`, following `account_lines` pagination to
4
+ * completion. The XRP Ledger returns trust lines in pages, so a single request
5
+ * would silently truncate the set of an account with many lines and hide token
6
+ * balances rather than fail.
7
+ *
8
+ * Balances are signed from `address`'s perspective: a negative balance means
9
+ * `address` is the issuer and owes the counterparty, not that it holds the token.
10
+ * @see https://xrpl.org/docs/references/http-websocket-apis/public-api-methods/account-methods/account_lines
11
+ */
12
+ export const getRippleAccountLines = async (address) => {
13
+ const client = await getRippleClient();
14
+ const lines = [];
15
+ let marker = undefined;
16
+ do {
17
+ const { result } = await client.request({
18
+ command: 'account_lines',
19
+ account: address,
20
+ ledger_index: 'current',
21
+ ...(marker === undefined ? {} : { marker }),
22
+ });
23
+ lines.push(...result.lines);
24
+ marker = result.marker;
25
+ } while (marker !== undefined);
26
+ return lines;
27
+ };
28
+ //# sourceMappingURL=lines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lines.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/ripple/account/lines.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAE3C;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EAAE,OAAe,EAAoC,EAAE;IAC/F,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAA;IAEtC,MAAM,KAAK,GAA4B,EAAE,CAAA;IACzC,IAAI,MAAM,GAAY,SAAS,CAAA;IAE/B,GAAG,CAAC;QACF,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;YACtC,OAAO,EAAE,eAAe;YACxB,OAAO,EAAE,OAAO;YAChB,YAAY,EAAE,SAAS;YACvB,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;SAC5C,CAAC,CAAA;QAEF,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;QAC3B,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;IACxB,CAAC,QAAQ,MAAM,KAAK,SAAS,EAAC;IAE9B,OAAO,KAAK,CAAA;AACd,CAAC,CAAA"}
@@ -47,9 +47,23 @@ export declare const formatIssuedCurrencyValue: (amount: bigint, decimals: numbe
47
47
  */
48
48
  export declare const rippleIssuedCurrencyDecimals = 15;
49
49
  /**
50
- * Curated XRPL issued tokens surfaced in the "open trust line" flow. Not wired
51
- * into `knownTokens` — issued-currency balances / asset-list display are handled
52
- * separately (vultisig-windows#4307 / vultisig-sdk#997).
50
+ * Parses an XRPL issued-currency value string (as returned by `account_lines`)
51
+ * into a base-unit bigint at {@link rippleIssuedCurrencyDecimals}. The inverse of
52
+ * {@link formatIssuedCurrencyValue}.
53
+ *
54
+ * The ledger may return scientific notation (e.g. `1e-8`) as well as plain
55
+ * decimals, and values are signed — a negative balance means the account is the
56
+ * issuer of the line rather than a holder of it.
57
+ *
58
+ * Fractional digits beyond our modelled precision are truncated, never rounded
59
+ * up, so a dust balance can never be inflated into a larger holding.
60
+ */
61
+ export declare const parseIssuedCurrencyValue: (value: string) => bigint;
62
+ /**
63
+ * Curated XRPL issued tokens, surfaced both in the "open trust line" flow and —
64
+ * via `knownTokens` — in the asset list. Trust lines the account already holds are
65
+ * discovered from the ledger by the Ripple coin finder; this list is what a user
66
+ * can pick before any trust line exists.
53
67
  */
54
68
  export declare const rippleKnownIssuedTokens: KnownCoin[];
55
69
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"issuedCurrency.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/ripple/issuedCurrency.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAA;AAE1D;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,UAAU,CAAA;AAqB9C;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,KAAG,MAYrD,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAAI,UAAU,MAAM,KAAG,OAEyB,CAAA;AAIpF,KAAK,oBAAoB,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,sBAAsB,oBAAoB,KAAG,MACZ,CAAA;AAE/D,iFAAiF;AACjF,eAAO,MAAM,kBAAkB,GAAI,IAAI,MAAM,KAAG,oBAU/C,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,GAAI,QAAQ,MAAM,EAAE,UAAU,MAAM,KAAG,MAU5E,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,KAAK,CAAA;AAE9C;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,SAAS,EAY9C,CAAA"}
1
+ {"version":3,"file":"issuedCurrency.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/ripple/issuedCurrency.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAA;AAE1D;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,UAAU,CAAA;AAqB9C;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,KAAG,MAYrD,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAAI,UAAU,MAAM,KAAG,OAEyB,CAAA;AAIpF,KAAK,oBAAoB,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,sBAAsB,oBAAoB,KAAG,MACZ,CAAA;AAE/D,iFAAiF;AACjF,eAAO,MAAM,kBAAkB,GAAI,IAAI,MAAM,KAAG,oBAU/C,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,GAAI,QAAQ,MAAM,EAAE,UAAU,MAAM,KAAG,MAU5E,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,KAAK,CAAA;AAE9C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,wBAAwB,GAAI,OAAO,MAAM,KAAG,MAiBxD,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,SAAS,EAY9C,CAAA"}
@@ -84,9 +84,36 @@ export const formatIssuedCurrencyValue = (amount, decimals) => {
84
84
  */
85
85
  export const rippleIssuedCurrencyDecimals = 15;
86
86
  /**
87
- * Curated XRPL issued tokens surfaced in the "open trust line" flow. Not wired
88
- * into `knownTokens` — issued-currency balances / asset-list display are handled
89
- * separately (vultisig-windows#4307 / vultisig-sdk#997).
87
+ * Parses an XRPL issued-currency value string (as returned by `account_lines`)
88
+ * into a base-unit bigint at {@link rippleIssuedCurrencyDecimals}. The inverse of
89
+ * {@link formatIssuedCurrencyValue}.
90
+ *
91
+ * The ledger may return scientific notation (e.g. `1e-8`) as well as plain
92
+ * decimals, and values are signed — a negative balance means the account is the
93
+ * issuer of the line rather than a holder of it.
94
+ *
95
+ * Fractional digits beyond our modelled precision are truncated, never rounded
96
+ * up, so a dust balance can never be inflated into a larger holding.
97
+ */
98
+ export const parseIssuedCurrencyValue = (value) => {
99
+ const match = /^([+-]?)(\d+)(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/.exec(value.trim());
100
+ if (!match) {
101
+ throw new Error(`Invalid XRPL issued-currency value: "${value}"`);
102
+ }
103
+ const [, sign, intPart, fracPart = '', exponent = '0'] = match;
104
+ // The literal is `digits * 10^(exponent - fracPart.length)`, so scaling it to
105
+ // base units shifts by that plus our modelled decimals. Shifting the digit
106
+ // string rather than round-tripping through a float keeps full precision.
107
+ const shift = Number(exponent) - fracPart.length + rippleIssuedCurrencyDecimals;
108
+ const digits = BigInt(`${intPart}${fracPart}`);
109
+ const magnitude = shift >= 0 ? digits * 10n ** BigInt(shift) : digits / 10n ** BigInt(-shift);
110
+ return sign === '-' ? -magnitude : magnitude;
111
+ };
112
+ /**
113
+ * Curated XRPL issued tokens, surfaced both in the "open trust line" flow and —
114
+ * via `knownTokens` — in the asset list. Trust lines the account already holds are
115
+ * discovered from the ledger by the Ripple coin finder; this list is what a user
116
+ * can pick before any trust line exists.
90
117
  */
91
118
  export const rippleKnownIssuedTokens = [
92
119
  {
@@ -1 +1 @@
1
- {"version":3,"file":"issuedCurrency.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/ripple/issuedCurrency.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAGlD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,OAAO,CAAA;AAE9C,+EAA+E;AAC/E,MAAM,0BAA0B,GAAG,CAAC,CAAA;AAEpC,+EAA+E;AAC/E,MAAM,qBAAqB,GAAG,EAAE,CAAA;AAEhC,MAAM,oBAAoB,GAAG,mBAAmB,CAAA;AAEhD,MAAM,sBAAsB,GAAG,CAAC,QAAgB,EAAU,EAAE;IAC1D,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC5C,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,kBAAkB,CAAC,CAAA;IAC9E,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;SAC3D,QAAQ,CAAC,KAAK,CAAC;SACf,WAAW,EAAE,CAAA;AAClB,CAAC,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,QAAgB,EAAU,EAAE;IAC7D,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAA;IAE7B,IAAI,KAAK,CAAC,MAAM,KAAK,0BAA0B,EAAE,CAAC;QAChD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,qBAAqB,IAAI,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/E,OAAO,KAAK,CAAC,WAAW,EAAE,CAAA;IAC5B,CAAC;IAED,OAAO,sBAAsB,CAAC,KAAK,CAAC,CAAA;AACtC,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,QAAgB,EAAW,EAAE,CACnE,QAAQ,CAAC,MAAM,KAAK,0BAA0B;IAC9C,CAAC,QAAQ,CAAC,MAAM,KAAK,qBAAqB,IAAI,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAA;AAEpF,MAAM,gBAAgB,GAAG,GAAG,CAAA;AAO5B;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAwB,EAAU,EAAE,CAClF,GAAG,kBAAkB,CAAC,QAAQ,CAAC,GAAG,gBAAgB,GAAG,MAAM,EAAE,CAAA;AAE/D,iFAAiF;AACjF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,EAAU,EAAwB,EAAE;IACrE,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAC1C,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAA;IACrD,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;QAC5B,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;KAC5B,CAAA;AACH,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,MAAc,EAAE,QAAgB,EAAU,EAAE;IACpF,MAAM,QAAQ,GAAG,MAAM,GAAG,EAAE,CAAA;IAC5B,MAAM,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,QAAQ,GAAG,CAAC,EAAE,GAAG,CAAC,CAAA;IAEnF,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,IAAI,GAAG,CAAA;IAChE,MAAM,QAAQ,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAE9F,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC,OAAO,CAAA;IAE/D,OAAO,QAAQ,IAAI,SAAS,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;AACpE,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAA;AAE9C;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAgB;IAClD;QACE,KAAK,EAAE,KAAK,CAAC,MAAM;QACnB,EAAE,EAAE,aAAa,CAAC;YAChB,QAAQ,EAAE,OAAO;YACjB,MAAM,EAAE,oCAAoC;SAC7C,CAAC;QACF,MAAM,EAAE,OAAO;QACf,IAAI,EAAE,OAAO;QACb,QAAQ,EAAE,4BAA4B;QACtC,eAAe,EAAE,YAAY;KAC9B;CACF,CAAA"}
1
+ {"version":3,"file":"issuedCurrency.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/ripple/issuedCurrency.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ import { AddressLookupTableAccount, PublicKey, VersionedMessage } from '@solana/web3.js';
2
+ /**
3
+ * Programs a legitimate Jupiter swap is expected to invoke as a TOP-LEVEL
4
+ * instruction. Captured empirically (2026-07-09) by fetching real `/swap`
5
+ * responses from Jupiter's public API (`lite-api.jup.ag`) and decoding the
6
+ * returned `VersionedTransaction` across four scenarios:
7
+ * - a single-hop SOL -> USDC route
8
+ * - a 3-hop SOL -> BONK route (AlphaQ -> Hadron -> Raydium CLMM)
9
+ * - a Token-2022 output mint (SOL -> PYUSD)
10
+ * - a platform-fee-included swap (feeAccount + platformFeeBps set)
11
+ *
12
+ * Every one of them resolved to exactly this program set. `useSharedAccounts`
13
+ * (Jupiter's default) routes the actual AMM legs through the router via CPI,
14
+ * so the individual AMM programs (Raydium, Whirlpool, etc.) never surface as
15
+ * top-level instructions — only the router itself plus the
16
+ * wrapping/bookkeeping instructions (SOL wrap/unwrap, ATA create, compute
17
+ * budget) do. Token-2022 is allow-listed defensively even though it did not
18
+ * surface in any captured fixture (the wSOL leg always uses the legacy Token
19
+ * program): the SDK's own fee-ATA derivation
20
+ * (`packages/core/chain/swap/general/jupiter/api/jupiterFeeAta.ts`)
21
+ * explicitly supports Token-2022 mints, so a route with no wSOL leg could
22
+ * plausibly need it.
23
+ */
24
+ export declare const JUPITER_SWAP_ALLOWED_PROGRAM_IDS: ReadonlySet<string>;
25
+ /**
26
+ * Thrown when a Solana swap message contains a top-level instruction that
27
+ * targets a program outside {@link JUPITER_SWAP_ALLOWED_PROGRAM_IDS}.
28
+ */
29
+ export declare class UnsafeSolanaSwapInstructionError extends Error {
30
+ readonly instructionIndex: number;
31
+ readonly programId: string;
32
+ constructor(instructionIndex: number, programId: string);
33
+ }
34
+ /**
35
+ * Thrown when a fund-moving instruction (System/Token) in a swap message has
36
+ * a destination or authority that does not belong to the user.
37
+ *
38
+ * Audit finding SOL-01 residual: a program-only allow-list permits injected
39
+ * top-level `SystemProgram.Transfer { from: user, to: attacker }` or
40
+ * `Token.Approve { owner: user, delegate: attacker }` because those programs
41
+ * are allow-listed (needed for SOL wrap/unwrap). This error is thrown when the
42
+ * decoded instruction accounts don't match the user's controlled addresses.
43
+ */
44
+ export declare class UnsafeSolanaSwapFundMovementError extends Error {
45
+ readonly instructionIndex: number;
46
+ readonly reason: string;
47
+ constructor(instructionIndex: number, reason: string);
48
+ }
49
+ /**
50
+ * Fund-safety guard (audit finding SOL-01, vultisig/vultisig-sdk#1056): a
51
+ * compromised Jupiter proxy could inject an arbitrary instruction (e.g. a
52
+ * drain transfer) into the `VersionedTransaction` returned from `/swap`
53
+ * before it reaches MPC signing. Vultisig's signing UI cannot meaningfully
54
+ * render raw Solana instruction bytes for the user to review, so the
55
+ * transaction would be effectively blind-signed.
56
+ *
57
+ * Two-layer defense:
58
+ *
59
+ * 1. **Program allow-list**: every top-level instruction's `programIdIndex`
60
+ * must resolve to a program in {@link JUPITER_SWAP_ALLOWED_PROGRAM_IDS}.
61
+ * Throws {@link UnsafeSolanaSwapInstructionError} on any unrecognized program.
62
+ *
63
+ * 2. **Destination/authority validation for fund-moving programs**: a
64
+ * program-only check is insufficient because `SystemProgram`,
65
+ * `TOKEN_PROGRAM_ID`, and `TOKEN_2022_PROGRAM_ID` are allow-listed (they
66
+ * perform legitimate SOL wrap/unwrap) but also implement drain/seize
67
+ * primitives (`Transfer`, `Approve`, `SetAuthority`). For each instruction
68
+ * targeting those programs, the decoded accounts are validated:
69
+ * - `SystemProgram.Transfer`: destination must be the user's wSOL ATA; any
70
+ * other System discriminant (TransferWithSeed / CreateAccount*) rejected.
71
+ * - `Token.Transfer/TransferChecked`: rejected outright — a top-level token
72
+ * move is never part of a legitimate Jupiter shared-accounts swap (the
73
+ * router moves tokens via CPI), and validating authority==user is
74
+ * meaningless since the authority is definitionally the user for any drain
75
+ * of their own account. The distinguishing account is the destination.
76
+ * - `Token.CloseAccount`: destination must be the user wallet.
77
+ * - `Token.Approve/ApproveChecked/SetAuthority`: rejected outright.
78
+ * Throws {@link UnsafeSolanaSwapFundMovementError} on any violation.
79
+ *
80
+ * Does NOT — and cannot, via static inspection alone — see into CPI (a
81
+ * program invoked from inside another instruction); that's exactly what the
82
+ * allow-listed Jupiter router is trusted to CPI into on the user's behalf.
83
+ */
84
+ export declare const assertSafeSolanaSwapInstructions: (message: VersionedMessage, addressLookupTableAccounts: AddressLookupTableAccount[] | undefined, userWallet: PublicKey) => void;
85
+ /**
86
+ * Resolve every address-lookup-table referenced by a v0 message. Returns an
87
+ * empty array for legacy messages (which cannot reference LUTs).
88
+ */
89
+ export declare const resolveSolanaAddressLookupTables: (message: VersionedMessage) => Promise<AddressLookupTableAccount[]>;
90
+ /**
91
+ * Convenience wrapper: deserialize a base64-encoded `VersionedTransaction`,
92
+ * resolve any referenced LUTs, and assert its top-level instructions are
93
+ * all allow-listed and fund-movement-safe. See {@link assertSafeSolanaSwapInstructions}.
94
+ */
95
+ export declare const assertSafeSolanaSwapTransactionBase64: (txData: string, userWallet: PublicKey) => Promise<void>;
96
+ //# sourceMappingURL=assertSafeSolanaSwapInstructions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertSafeSolanaSwapInstructions.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/solana/assertSafeSolanaSwapInstructions.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,yBAAyB,EAEzB,SAAS,EACT,gBAAgB,EAEjB,MAAM,iBAAiB,CAAA;AASxB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,gCAAgC,EAAE,WAAW,CAAC,MAAM,CAO/D,CAAA;AAoBF;;;GAGG;AACH,qBAAa,gCAAiC,SAAQ,KAAK;aAEvC,gBAAgB,EAAE,MAAM;aACxB,SAAS,EAAE,MAAM;gBADjB,gBAAgB,EAAE,MAAM,EACxB,SAAS,EAAE,MAAM;CAOpC;AAED;;;;;;;;;GASG;AACH,qBAAa,iCAAkC,SAAQ,KAAK;aAExC,gBAAgB,EAAE,MAAM;aACxB,MAAM,EAAE,MAAM;gBADd,gBAAgB,EAAE,MAAM,EACxB,MAAM,EAAE,MAAM;CAKjC;AAgHD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,gCAAgC,GAC3C,SAAS,gBAAgB,EACzB,4BAA4B,yBAAyB,EAAE,YAAK,EAC5D,YAAY,SAAS,KACpB,IAuBF,CAAA;AAyBD;;;GAGG;AACH,eAAO,MAAM,gCAAgC,GAC3C,SAAS,gBAAgB,KACxB,OAAO,CAAC,yBAAyB,EAAE,CAarC,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,qCAAqC,GAAU,QAAQ,MAAM,EAAE,YAAY,SAAS,KAAG,OAAO,CAAC,IAAI,CAI/G,CAAA"}
@@ -0,0 +1,260 @@
1
+ import { ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync, NATIVE_MINT, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID, } from '@solana/spl-token';
2
+ import { VersionedTransaction, } from '@solana/web3.js';
3
+ import { getSolanaClient } from './client.js';
4
+ /** Jupiter v6 aggregator router. Every Jupiter swap routes through this program. */
5
+ const JUPITER_V6_PROGRAM_ID = 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4';
6
+ const COMPUTE_BUDGET_PROGRAM_ID = 'ComputeBudget111111111111111111111111111111';
7
+ const SYSTEM_PROGRAM_ID = '11111111111111111111111111111111';
8
+ /**
9
+ * Programs a legitimate Jupiter swap is expected to invoke as a TOP-LEVEL
10
+ * instruction. Captured empirically (2026-07-09) by fetching real `/swap`
11
+ * responses from Jupiter's public API (`lite-api.jup.ag`) and decoding the
12
+ * returned `VersionedTransaction` across four scenarios:
13
+ * - a single-hop SOL -> USDC route
14
+ * - a 3-hop SOL -> BONK route (AlphaQ -> Hadron -> Raydium CLMM)
15
+ * - a Token-2022 output mint (SOL -> PYUSD)
16
+ * - a platform-fee-included swap (feeAccount + platformFeeBps set)
17
+ *
18
+ * Every one of them resolved to exactly this program set. `useSharedAccounts`
19
+ * (Jupiter's default) routes the actual AMM legs through the router via CPI,
20
+ * so the individual AMM programs (Raydium, Whirlpool, etc.) never surface as
21
+ * top-level instructions — only the router itself plus the
22
+ * wrapping/bookkeeping instructions (SOL wrap/unwrap, ATA create, compute
23
+ * budget) do. Token-2022 is allow-listed defensively even though it did not
24
+ * surface in any captured fixture (the wSOL leg always uses the legacy Token
25
+ * program): the SDK's own fee-ATA derivation
26
+ * (`packages/core/chain/swap/general/jupiter/api/jupiterFeeAta.ts`)
27
+ * explicitly supports Token-2022 mints, so a route with no wSOL leg could
28
+ * plausibly need it.
29
+ */
30
+ export const JUPITER_SWAP_ALLOWED_PROGRAM_IDS = new Set([
31
+ JUPITER_V6_PROGRAM_ID,
32
+ COMPUTE_BUDGET_PROGRAM_ID,
33
+ SYSTEM_PROGRAM_ID,
34
+ TOKEN_PROGRAM_ID.toBase58(),
35
+ TOKEN_2022_PROGRAM_ID.toBase58(),
36
+ ASSOCIATED_TOKEN_PROGRAM_ID.toBase58(),
37
+ ]);
38
+ /** Programs that can move funds — require destination/authority validation beyond a program-only check. */
39
+ const FUND_MOVING_PROGRAM_IDS = new Set([
40
+ SYSTEM_PROGRAM_ID,
41
+ TOKEN_PROGRAM_ID.toBase58(),
42
+ TOKEN_2022_PROGRAM_ID.toBase58(),
43
+ ]);
44
+ // SystemProgram instruction type discriminants (LE uint32 at data[0..4])
45
+ const SYSTEM_TRANSFER = 2;
46
+ // Token/Token-2022 instruction discriminants (uint8 at data[0])
47
+ const TOKEN_TRANSFER = 3;
48
+ const TOKEN_APPROVE = 4;
49
+ const TOKEN_SET_AUTHORITY = 6;
50
+ const TOKEN_CLOSE_ACCOUNT = 9;
51
+ const TOKEN_TRANSFER_CHECKED = 12;
52
+ const TOKEN_APPROVE_CHECKED = 13;
53
+ /**
54
+ * Thrown when a Solana swap message contains a top-level instruction that
55
+ * targets a program outside {@link JUPITER_SWAP_ALLOWED_PROGRAM_IDS}.
56
+ */
57
+ export class UnsafeSolanaSwapInstructionError extends Error {
58
+ instructionIndex;
59
+ programId;
60
+ constructor(instructionIndex, programId) {
61
+ super(`SOL_SWAP_UNEXPECTED_PROGRAM: instruction ${instructionIndex} targets unrecognized program ${programId}; refusing to sign`);
62
+ this.instructionIndex = instructionIndex;
63
+ this.programId = programId;
64
+ this.name = 'UnsafeSolanaSwapInstructionError';
65
+ }
66
+ }
67
+ /**
68
+ * Thrown when a fund-moving instruction (System/Token) in a swap message has
69
+ * a destination or authority that does not belong to the user.
70
+ *
71
+ * Audit finding SOL-01 residual: a program-only allow-list permits injected
72
+ * top-level `SystemProgram.Transfer { from: user, to: attacker }` or
73
+ * `Token.Approve { owner: user, delegate: attacker }` because those programs
74
+ * are allow-listed (needed for SOL wrap/unwrap). This error is thrown when the
75
+ * decoded instruction accounts don't match the user's controlled addresses.
76
+ */
77
+ export class UnsafeSolanaSwapFundMovementError extends Error {
78
+ instructionIndex;
79
+ reason;
80
+ constructor(instructionIndex, reason) {
81
+ super(`SOL_SWAP_UNSAFE_FUND_MOVEMENT: instruction ${instructionIndex} — ${reason}`);
82
+ this.instructionIndex = instructionIndex;
83
+ this.reason = reason;
84
+ this.name = 'UnsafeSolanaSwapFundMovementError';
85
+ }
86
+ }
87
+ const assertSystemInstruction = (ix, keys, userWallet, index) => {
88
+ if (ix.data.length < 4)
89
+ return;
90
+ const type = new DataView(ix.data.buffer, ix.data.byteOffset, 4).getUint32(0, /* littleEndian */ true);
91
+ // A legitimate top-level Jupiter swap only ever emits SystemProgram.Transfer
92
+ // (the SOL→wSOL wrap). Every OTHER System instruction that moves lamports —
93
+ // TransferWithSeed (11), CreateAccount (0), CreateAccountWithSeed (3) — is
94
+ // rejected outright rather than silently allowed: a program-only allow-list
95
+ // would let a spliced TransferWithSeed to an attacker survive into the signed
96
+ // bytes exactly like the Token.Transfer drain. Mirrors the reject-outright
97
+ // stance the token branch takes for non-wrap fund movers. Non-lamport-moving
98
+ // System instructions don't appear top-level in a swap, so a blanket reject of
99
+ // "not SYSTEM_TRANSFER" is the safe, tight floor (fail-closed on the unknown).
100
+ if (type !== SYSTEM_TRANSFER) {
101
+ throw new UnsafeSolanaSwapFundMovementError(index, `SystemProgram instruction (discriminant ${type}) is not a legitimate top-level Jupiter swap instruction — only SystemProgram.Transfer (SOL wrap) is expected`);
102
+ }
103
+ // Transfer accounts[1] = destination. The only legitimate SOL transfer in
104
+ // a Jupiter swap is wrapping: from: userWallet → to: userWallet's wSOL ATA.
105
+ const destIdx = ix.accountKeyIndexes[1];
106
+ if (destIdx === undefined) {
107
+ throw new UnsafeSolanaSwapFundMovementError(index, 'SystemProgram.Transfer: missing destination account index');
108
+ }
109
+ const dest = keys.get(destIdx);
110
+ if (!dest) {
111
+ throw new UnsafeSolanaSwapFundMovementError(index, `SystemProgram.Transfer: destination index ${destIdx} could not be resolved`);
112
+ }
113
+ const wSolAta = getAssociatedTokenAddressSync(NATIVE_MINT, userWallet);
114
+ if (!dest.equals(wSolAta)) {
115
+ throw new UnsafeSolanaSwapFundMovementError(index, `SystemProgram.Transfer destination ${dest.toBase58()} is not the expected wSOL ATA ${wSolAta.toBase58()} — possible drain injection`);
116
+ }
117
+ };
118
+ const assertTokenInstruction = (ix, keys, userWallet, index) => {
119
+ if (ix.data.length === 0)
120
+ return;
121
+ const type = ix.data[0];
122
+ // Reject instructions that can delegate or transfer authority — these are
123
+ // never present as top-level instructions in legitimate Jupiter shared-accounts swaps.
124
+ if (type === TOKEN_APPROVE || type === TOKEN_APPROVE_CHECKED) {
125
+ throw new UnsafeSolanaSwapFundMovementError(index, `Token.${type === TOKEN_APPROVE ? 'Approve' : 'ApproveChecked'} is not a legitimate top-level Jupiter swap instruction — possible authority delegation to attacker`);
126
+ }
127
+ if (type === TOKEN_SET_AUTHORITY) {
128
+ throw new UnsafeSolanaSwapFundMovementError(index, 'Token.SetAuthority is not a legitimate top-level Jupiter swap instruction — possible account seizure');
129
+ }
130
+ // Transfer (type=3) and TransferChecked (type=12): reject outright as
131
+ // top-level instructions. Jupiter shared-accounts routing performs token
132
+ // moves via CPI inside the router — a top-level Token.Transfer with
133
+ // authority==user and destination==attacker would pass an authority check
134
+ // and silently drain the user's tokens. Same rationale as Approve.
135
+ if (type === TOKEN_TRANSFER) {
136
+ throw new UnsafeSolanaSwapFundMovementError(index, 'Token.Transfer is not a legitimate top-level Jupiter swap instruction — possible token drain to attacker');
137
+ }
138
+ if (type === TOKEN_TRANSFER_CHECKED) {
139
+ throw new UnsafeSolanaSwapFundMovementError(index, 'Token.TransferChecked is not a legitimate top-level Jupiter swap instruction — possible token drain to attacker');
140
+ }
141
+ // CloseAccount (type=9): layout [account, destination, authority].
142
+ // accounts[1]=destination must be the user wallet so unwrapped SOL/rent
143
+ // returns to the user and cannot be swept to an attacker address.
144
+ if (type === TOKEN_CLOSE_ACCOUNT) {
145
+ const destIdx = ix.accountKeyIndexes[1];
146
+ if (destIdx === undefined)
147
+ throw new UnsafeSolanaSwapFundMovementError(index, 'Token.CloseAccount: missing destination account index');
148
+ const dest = keys.get(destIdx);
149
+ if (!dest || !dest.equals(userWallet)) {
150
+ throw new UnsafeSolanaSwapFundMovementError(index, `Token.CloseAccount destination ${dest?.toBase58() ?? '<unresolved>'} is not the user wallet ${userWallet.toBase58()} — possible SOL/rent drain`);
151
+ }
152
+ }
153
+ // SyncNative (17), InitializeAccount (1), and other Token instructions
154
+ // that do not move funds to an arbitrary destination: allowed.
155
+ };
156
+ /**
157
+ * Fund-safety guard (audit finding SOL-01, vultisig/vultisig-sdk#1056): a
158
+ * compromised Jupiter proxy could inject an arbitrary instruction (e.g. a
159
+ * drain transfer) into the `VersionedTransaction` returned from `/swap`
160
+ * before it reaches MPC signing. Vultisig's signing UI cannot meaningfully
161
+ * render raw Solana instruction bytes for the user to review, so the
162
+ * transaction would be effectively blind-signed.
163
+ *
164
+ * Two-layer defense:
165
+ *
166
+ * 1. **Program allow-list**: every top-level instruction's `programIdIndex`
167
+ * must resolve to a program in {@link JUPITER_SWAP_ALLOWED_PROGRAM_IDS}.
168
+ * Throws {@link UnsafeSolanaSwapInstructionError} on any unrecognized program.
169
+ *
170
+ * 2. **Destination/authority validation for fund-moving programs**: a
171
+ * program-only check is insufficient because `SystemProgram`,
172
+ * `TOKEN_PROGRAM_ID`, and `TOKEN_2022_PROGRAM_ID` are allow-listed (they
173
+ * perform legitimate SOL wrap/unwrap) but also implement drain/seize
174
+ * primitives (`Transfer`, `Approve`, `SetAuthority`). For each instruction
175
+ * targeting those programs, the decoded accounts are validated:
176
+ * - `SystemProgram.Transfer`: destination must be the user's wSOL ATA; any
177
+ * other System discriminant (TransferWithSeed / CreateAccount*) rejected.
178
+ * - `Token.Transfer/TransferChecked`: rejected outright — a top-level token
179
+ * move is never part of a legitimate Jupiter shared-accounts swap (the
180
+ * router moves tokens via CPI), and validating authority==user is
181
+ * meaningless since the authority is definitionally the user for any drain
182
+ * of their own account. The distinguishing account is the destination.
183
+ * - `Token.CloseAccount`: destination must be the user wallet.
184
+ * - `Token.Approve/ApproveChecked/SetAuthority`: rejected outright.
185
+ * Throws {@link UnsafeSolanaSwapFundMovementError} on any violation.
186
+ *
187
+ * Does NOT — and cannot, via static inspection alone — see into CPI (a
188
+ * program invoked from inside another instruction); that's exactly what the
189
+ * allow-listed Jupiter router is trusted to CPI into on the user's behalf.
190
+ */
191
+ export const assertSafeSolanaSwapInstructions = (message, addressLookupTableAccounts = [], userWallet) => {
192
+ const accountKeys = message.version === 'legacy' ? message.getAccountKeys() : message.getAccountKeys({ addressLookupTableAccounts });
193
+ message.compiledInstructions.forEach((instruction, index) => {
194
+ const programId = accountKeys.get(instruction.programIdIndex);
195
+ if (!programId) {
196
+ throw new UnsafeSolanaSwapInstructionError(index, `<unresolved account index ${instruction.programIdIndex}>`);
197
+ }
198
+ const programIdBase58 = programId.toBase58();
199
+ if (!JUPITER_SWAP_ALLOWED_PROGRAM_IDS.has(programIdBase58)) {
200
+ throw new UnsafeSolanaSwapInstructionError(index, programIdBase58);
201
+ }
202
+ // Layer 2: for fund-moving programs, validate destination/authority
203
+ if (FUND_MOVING_PROGRAM_IDS.has(programIdBase58)) {
204
+ if (programIdBase58 === SYSTEM_PROGRAM_ID) {
205
+ assertSystemInstruction(instruction, accountKeys, userWallet, index);
206
+ }
207
+ else {
208
+ assertTokenInstruction(instruction, accountKeys, userWallet, index);
209
+ }
210
+ }
211
+ });
212
+ };
213
+ /** Maximum attempts for a LUT fetch before giving up on that table. */
214
+ const MAX_LUT_FETCH_ATTEMPTS = 3;
215
+ const fetchLutWithRetry = async (client, accountKey) => {
216
+ const errors = [];
217
+ for (let attempt = 0; attempt < MAX_LUT_FETCH_ATTEMPTS; attempt++) {
218
+ try {
219
+ const result = await client.getAddressLookupTable(accountKey);
220
+ return result.value ?? null;
221
+ }
222
+ catch (err) {
223
+ errors.push(err);
224
+ if (attempt < MAX_LUT_FETCH_ATTEMPTS - 1) {
225
+ await new Promise(resolve => setTimeout(resolve, 200 * 2 ** attempt));
226
+ }
227
+ }
228
+ }
229
+ console.warn('[assertSafeSolanaSwapInstructions] LUT fetch failed after retries:', errors);
230
+ return null;
231
+ };
232
+ /**
233
+ * Resolve every address-lookup-table referenced by a v0 message. Returns an
234
+ * empty array for legacy messages (which cannot reference LUTs).
235
+ */
236
+ export const resolveSolanaAddressLookupTables = async (message) => {
237
+ if (message.version !== 0) {
238
+ return [];
239
+ }
240
+ const client = getSolanaClient();
241
+ const lutAccounts = [];
242
+ for (const lut of message.addressTableLookups) {
243
+ const lutAccount = await fetchLutWithRetry(client, lut.accountKey);
244
+ if (lutAccount) {
245
+ lutAccounts.push(lutAccount);
246
+ }
247
+ }
248
+ return lutAccounts;
249
+ };
250
+ /**
251
+ * Convenience wrapper: deserialize a base64-encoded `VersionedTransaction`,
252
+ * resolve any referenced LUTs, and assert its top-level instructions are
253
+ * all allow-listed and fund-movement-safe. See {@link assertSafeSolanaSwapInstructions}.
254
+ */
255
+ export const assertSafeSolanaSwapTransactionBase64 = async (txData, userWallet) => {
256
+ const versionedTx = VersionedTransaction.deserialize(Buffer.from(txData, 'base64'));
257
+ const lutAccounts = await resolveSolanaAddressLookupTables(versionedTx.message);
258
+ assertSafeSolanaSwapInstructions(versionedTx.message, lutAccounts, userWallet);
259
+ };
260
+ //# sourceMappingURL=assertSafeSolanaSwapInstructions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertSafeSolanaSwapInstructions.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/solana/assertSafeSolanaSwapInstructions.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ripple.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/balance/resolvers/ripple.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,eAAO,MAAM,oBAAoB,EAAE,mBAgClC,CAAA"}
1
+ {"version":3,"file":"ripple.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/coin/balance/resolvers/ripple.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AA2EjD,eAAO,MAAM,oBAAoB,EAAE,mBAM3B,CAAA"}