@vultisig/core-chain 2.17.11 → 2.19.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 (70) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/chains/cosmos/qbtc/governance/getQbtcGovParams.d.ts +8 -0
  3. package/dist/chains/cosmos/qbtc/governance/getQbtcGovParams.d.ts.map +1 -0
  4. package/dist/chains/cosmos/qbtc/governance/getQbtcGovParams.js +31 -0
  5. package/dist/chains/cosmos/qbtc/governance/getQbtcGovParams.js.map +1 -0
  6. package/dist/chains/cosmos/qbtc/governance/getQbtcMyVote.d.ts +12 -0
  7. package/dist/chains/cosmos/qbtc/governance/getQbtcMyVote.d.ts.map +1 -0
  8. package/dist/chains/cosmos/qbtc/governance/getQbtcMyVote.js +32 -0
  9. package/dist/chains/cosmos/qbtc/governance/getQbtcMyVote.js.map +1 -0
  10. package/dist/chains/cosmos/qbtc/governance/getQbtcProposalTally.d.ts +4 -0
  11. package/dist/chains/cosmos/qbtc/governance/getQbtcProposalTally.d.ts.map +1 -0
  12. package/dist/chains/cosmos/qbtc/governance/getQbtcProposalTally.js +8 -0
  13. package/dist/chains/cosmos/qbtc/governance/getQbtcProposalTally.js.map +1 -0
  14. package/dist/chains/cosmos/qbtc/governance/getQbtcProposals.d.ts +7 -0
  15. package/dist/chains/cosmos/qbtc/governance/getQbtcProposals.d.ts.map +1 -0
  16. package/dist/chains/cosmos/qbtc/governance/getQbtcProposals.js +13 -0
  17. package/dist/chains/cosmos/qbtc/governance/getQbtcProposals.js.map +1 -0
  18. package/dist/chains/cosmos/qbtc/governance/parseGov.d.ts +26 -0
  19. package/dist/chains/cosmos/qbtc/governance/parseGov.d.ts.map +1 -0
  20. package/dist/chains/cosmos/qbtc/governance/parseGov.js +46 -0
  21. package/dist/chains/cosmos/qbtc/governance/parseGov.js.map +1 -0
  22. package/dist/chains/cosmos/qbtc/governance/proposal.d.ts +64 -0
  23. package/dist/chains/cosmos/qbtc/governance/proposal.d.ts.map +1 -0
  24. package/dist/chains/cosmos/qbtc/governance/proposal.js +39 -0
  25. package/dist/chains/cosmos/qbtc/governance/proposal.js.map +1 -0
  26. package/dist/chains/cosmos/qbtc/governance/voteOption.d.ts +17 -0
  27. package/dist/chains/cosmos/qbtc/governance/voteOption.d.ts.map +1 -0
  28. package/dist/chains/cosmos/qbtc/governance/voteOption.js +38 -0
  29. package/dist/chains/cosmos/qbtc/governance/voteOption.js.map +1 -0
  30. package/dist/chains/ton/address.d.ts +9 -0
  31. package/dist/chains/ton/address.d.ts.map +1 -1
  32. package/dist/chains/ton/address.js +13 -0
  33. package/dist/chains/ton/address.js.map +1 -1
  34. package/dist/chains/ton/staking.d.ts +104 -0
  35. package/dist/chains/ton/staking.d.ts.map +1 -0
  36. package/dist/chains/ton/staking.js +137 -0
  37. package/dist/chains/ton/staking.js.map +1 -0
  38. package/dist/coin/balance/getEvmChainBalances.d.ts +11 -0
  39. package/dist/coin/balance/getEvmChainBalances.d.ts.map +1 -0
  40. package/dist/coin/balance/getEvmChainBalances.js +57 -0
  41. package/dist/coin/balance/getEvmChainBalances.js.map +1 -0
  42. package/dist/swap/general/GeneralSwapProvider.d.ts +1 -1
  43. package/dist/swap/general/GeneralSwapProvider.d.ts.map +1 -1
  44. package/dist/swap/general/GeneralSwapProvider.js +2 -1
  45. package/dist/swap/general/GeneralSwapProvider.js.map +1 -1
  46. package/dist/swap/general/jupiter/JupiterSwapEnabledChains.d.ts +9 -0
  47. package/dist/swap/general/jupiter/JupiterSwapEnabledChains.d.ts.map +1 -0
  48. package/dist/swap/general/jupiter/JupiterSwapEnabledChains.js +9 -0
  49. package/dist/swap/general/jupiter/JupiterSwapEnabledChains.js.map +1 -0
  50. package/dist/swap/general/jupiter/api/getJupiterSwapQuote.d.ts +25 -0
  51. package/dist/swap/general/jupiter/api/getJupiterSwapQuote.d.ts.map +1 -0
  52. package/dist/swap/general/jupiter/api/getJupiterSwapQuote.js +112 -0
  53. package/dist/swap/general/jupiter/api/getJupiterSwapQuote.js.map +1 -0
  54. package/dist/swap/general/jupiter/api/jupiterFeeAta.d.ts +48 -0
  55. package/dist/swap/general/jupiter/api/jupiterFeeAta.d.ts.map +1 -0
  56. package/dist/swap/general/jupiter/api/jupiterFeeAta.js +115 -0
  57. package/dist/swap/general/jupiter/api/jupiterFeeAta.js.map +1 -0
  58. package/dist/swap/general/jupiter/config.d.ts +13 -0
  59. package/dist/swap/general/jupiter/config.d.ts.map +1 -0
  60. package/dist/swap/general/jupiter/config.js +52 -0
  61. package/dist/swap/general/jupiter/config.js.map +1 -0
  62. package/dist/swap/quote/findSwapQuote.d.ts +1 -1
  63. package/dist/swap/quote/findSwapQuote.d.ts.map +1 -1
  64. package/dist/swap/quote/findSwapQuote.js +33 -1
  65. package/dist/swap/quote/findSwapQuote.js.map +1 -1
  66. package/dist/swap/utils/getSwapExplorerUrl/index.d.ts +2 -2
  67. package/dist/swap/utils/getSwapExplorerUrl/index.d.ts.map +1 -1
  68. package/dist/swap/utils/getSwapExplorerUrl/index.js +11 -2
  69. package/dist/swap/utils/getSwapExplorerUrl/index.js.map +1 -1
  70. package/package.json +66 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staking.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/ton/staking.ts"],"names":[],"mappings":"AAYA;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,2BAA4B,CAAA;AAEpE,MAAM,MAAM,0BAA0B,GAAG,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,CAAC,CAAA;AAErF,eAAO,MAAM,4BAA4B,GACvC,gBAAgB,MAAM,GAAG,SAAS,KACjC,cAAc,IAAI,0BAC4E,CAAA;AAqBjG,mGAAmG;AACnG,eAAO,MAAM,wBAAwB,GAAI,gBAAgB,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,SACe,CAAA;AAEtG,oGAAoG;AACpG,eAAO,MAAM,yBAAyB,GAAI,gBAAgB,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,SACe,CAAA;AAOvG;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,GAAG,SAAS,KAAG,OAAwD,CAAA;AAEvH;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,cAAiB,CAAA;AAErD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,aAAe,CAAA;AAEjD;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,YAAc,CAAA;AAc/C;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAiBD,2FAA2F;AAC3F,eAAO,MAAM,kBAAkB,GAAI,MAAM,cAAc,KAAG,OAMzD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAI,MAAM,cAAc,KAAG,OACsC,CAAA;AAEhG;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,QAAa,OAAO,CAAC,cAAc,EAAE,CAKnE,CAAA;AAWD;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,6EAA6E;AAC7E,eAAO,MAAM,qBAAqB,GAAU,aAAa,MAAM,KAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAavG,CAAA;AAUD;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,CAAA;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;CACtB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAAU,WAAW,MAAM,KAAG,OAAO,CAAC,oBAAoB,EAAE,CAW5F,CAAA"}
@@ -0,0 +1,137 @@
1
+ import { queryUrl } from '@vultisig/lib-utils/query/queryUrl';
2
+ import { tonAddressToBounceable } from './address.js';
3
+ /**
4
+ * Public TonAPI host. The staking endpoints (`/v2/staking/*`) are served
5
+ * exclusively by `tonapi.io` — the Vultisig `/ton` proxy fronts toncenter v3,
6
+ * which has no staking routes — so we hit tonapi.io directly. The extension's
7
+ * wildcard https host permission covers it.
8
+ */
9
+ const tonApiPublicUrl = 'https://tonapi.io';
10
+ /**
11
+ * tonapi `implementation` values that are genuine **nominator pools** — the
12
+ * only ones the text-comment deposit/withdraw mechanism can stake into.
13
+ * `liquidTF` (Tonstakers) mints a jetton instead and is excluded; unknown
14
+ * implementations are treated as non-nominator (excluded).
15
+ */
16
+ export const tonNominatorImplementations = ['whales', 'tf'];
17
+ export const isTonNominatorImplementation = (implementation) => !!implementation && tonNominatorImplementations.includes(implementation);
18
+ /**
19
+ * The deposit/withdraw text comments a TON nominator-pool contract expects.
20
+ * Each pool *implementation* uses a DIFFERENT word — sending the wrong one is
21
+ * rejected on-chain (exit code 72). These are contract protocol tokens, NOT
22
+ * user-facing UI: never translate them.
23
+ *
24
+ * The Whales pool repo README's "Stake" is stale and rejected by the live
25
+ * pools; the verified on-chain word is "Deposit".
26
+ */
27
+ const tonStakingDepositComments = {
28
+ tf: 'd',
29
+ whales: 'Deposit',
30
+ };
31
+ const tonStakingWithdrawComments = {
32
+ tf: 'w',
33
+ whales: 'Withdraw',
34
+ };
35
+ /** Deposit comment for a pool implementation, or `undefined` if unsupported (block the action). */
36
+ export const tonStakingDepositComment = (implementation) => isTonNominatorImplementation(implementation) ? tonStakingDepositComments[implementation] : undefined;
37
+ /** Withdraw comment for a pool implementation, or `undefined` if unsupported (block the action). */
38
+ export const tonStakingWithdrawComment = (implementation) => isTonNominatorImplementation(implementation) ? tonStakingWithdrawComments[implementation] : undefined;
39
+ const tonStakingComments = new Set([
40
+ ...Object.values(tonStakingDepositComments),
41
+ ...Object.values(tonStakingWithdrawComments),
42
+ ]);
43
+ /**
44
+ * Whether a memo is a nominator-pool deposit/withdraw comment (`d`/`w`/`Deposit`
45
+ * /`Withdraw`). The signer uses this to force the transfer bounceable: a pool
46
+ * deposit/withdraw sent non-bounceable can be absorbed (lost) by the pool
47
+ * instead of bounced back if rejected.
48
+ */
49
+ export const isTonStakingComment = (memo) => !!memo && tonStakingComments.has(memo.trim());
50
+ /**
51
+ * Processing-commission buffer (nanotons) added on top of a pool's `min_stake`
52
+ * for the minimum acceptable deposit. Depositing exactly the minimum is
53
+ * rejected; the pool needs ~1 TON headroom for its processing commission.
54
+ */
55
+ export const tonStakingDepositBuffer = 1000000000n;
56
+ /**
57
+ * Amount (nanotons) accompanying a withdraw message — the pool's 0.2 TON
58
+ * withdraw fee. The pool returns the full staked balance separately; sending
59
+ * more (e.g. 1 TON) fails.
60
+ */
61
+ export const tonStakingWithdrawFee = 200000000n;
62
+ /**
63
+ * Conservative network-fee reserve (nanotons ≈ 0.05 TON) held back from the
64
+ * spendable balance when sizing a stake deposit or checking the unstake fee is
65
+ * affordable. Larger than the bare base fee because the text-comment cell adds
66
+ * compute; matches the iOS reserve.
67
+ */
68
+ export const tonStakingFeeReserve = 50000000n;
69
+ const mapPoolEntry = (entry) => ({
70
+ // Normalize to the bounceable `EQ…` form at the boundary so no caller can
71
+ // build a staking transfer to a raw/non-bounceable destination (which the
72
+ // pool would absorb instead of bouncing back on rejection).
73
+ address: tonAddressToBounceable(entry.address),
74
+ name: entry.name,
75
+ apy: entry.apy,
76
+ minStake: BigInt(Math.trunc(entry.min_stake)),
77
+ verified: entry.verified,
78
+ currentNominators: entry.current_nominators,
79
+ maxNominators: entry.max_nominators,
80
+ implementation: entry.implementation,
81
+ cycleEnd: entry.cycle_end,
82
+ });
83
+ /** Whether a pool has room for another nominator (pools at capacity reject new stakes). */
84
+ export const tonPoolHasCapacity = (pool) => {
85
+ const { currentNominators, maxNominators } = pool;
86
+ if (currentNominators === undefined || maxNominators === undefined || maxNominators <= 0) {
87
+ return true;
88
+ }
89
+ return currentNominators < maxNominators;
90
+ };
91
+ /**
92
+ * Whether a pool is a verified nominator pool with capacity — i.e. one the
93
+ * picker should surface and a stake can succeed into.
94
+ */
95
+ export const isStakeableTonPool = (pool) => pool.verified && isTonNominatorImplementation(pool.implementation) && tonPoolHasCapacity(pool);
96
+ /**
97
+ * Fetches all verified TON staking pools from tonapi (`/v2/staking/pools`).
98
+ * Includes every implementation; callers filter to stakeable nominator pools
99
+ * via `isStakeableTonPool`.
100
+ */
101
+ export const getTonStakingPools = async () => {
102
+ const url = `${tonApiPublicUrl}/v2/staking/pools?include_unverified=false`;
103
+ const { pools } = await queryUrl(url);
104
+ return pools.map(mapPoolEntry);
105
+ };
106
+ /** Fetches computed pool metadata (name, APY, implementation, cycle end). */
107
+ export const getTonStakingPoolInfo = async (poolAddress) => {
108
+ const url = `${tonApiPublicUrl}/v2/staking/pool/${encodeURIComponent(poolAddress)}`;
109
+ const { pool } = await queryUrl(url);
110
+ if (!pool)
111
+ return undefined;
112
+ return {
113
+ address: pool.address ? tonAddressToBounceable(pool.address) : undefined,
114
+ name: pool.name,
115
+ apy: pool.apy,
116
+ minStake: pool.min_stake !== undefined ? BigInt(Math.trunc(pool.min_stake)) : undefined,
117
+ implementation: pool.implementation,
118
+ cycleEnd: pool.cycle_end,
119
+ };
120
+ };
121
+ /**
122
+ * Fetches an account's nominator-pool positions
123
+ * (`/v2/staking/nominator/{accountId}/pools`) — the authoritative source for
124
+ * staked positions. `accountId` accepts the user-friendly wallet address.
125
+ */
126
+ export const getTonNominatorPools = async (accountId) => {
127
+ const url = `${tonApiPublicUrl}/v2/staking/nominator/${encodeURIComponent(accountId)}/pools`;
128
+ const { pools } = await queryUrl(url);
129
+ return pools.map(position => ({
130
+ pool: tonAddressToBounceable(position.pool),
131
+ amount: BigInt(Math.trunc(position.amount)),
132
+ pendingDeposit: BigInt(Math.trunc(position.pending_deposit)),
133
+ pendingWithdraw: BigInt(Math.trunc(position.pending_withdraw)),
134
+ readyWithdraw: BigInt(Math.trunc(position.ready_withdraw)),
135
+ }));
136
+ };
137
+ //# sourceMappingURL=staking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staking.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/ton/staking.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { EvmChain } from '@vultisig/core-chain/Chain';
2
+ import { AccountCoinKey } from '@vultisig/core-chain/coin/AccountCoin';
3
+ import { Address } from 'viem';
4
+ export type GetEvmChainBalancesInput = {
5
+ chain: EvmChain;
6
+ address: Address;
7
+ coins: AccountCoinKey<EvmChain>[];
8
+ };
9
+ export type EvmChainBalances = Record<string, bigint>;
10
+ export declare const getEvmChainBalances: (input: GetEvmChainBalancesInput) => Promise<EvmChainBalances>;
11
+ //# sourceMappingURL=getEvmChainBalances.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getEvmChainBalances.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/coin/balance/getEvmChainBalances.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAErD,OAAO,EAAE,cAAc,EAA0B,MAAM,uCAAuC,CAAA;AAE9F,OAAO,EAAE,OAAO,EAAsB,MAAM,MAAM,CAAA;AAMlD,MAAM,MAAM,wBAAwB,GAAG;IACrC,KAAK,EAAE,QAAQ,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAkBrD,eAAO,MAAM,mBAAmB,GAAU,OAAO,wBAAwB,KAAG,OAAO,CAAC,gBAAgB,CAiDnG,CAAA"}
@@ -0,0 +1,57 @@
1
+ import { getEvmClient } from '@vultisig/core-chain/chains/evm/client';
2
+ import { accountCoinKeyToString } from '@vultisig/core-chain/coin/AccountCoin';
3
+ import { isFeeCoin } from '@vultisig/core-chain/coin/utils/isFeeCoin';
4
+ import { erc20Abi, parseAbi } from 'viem';
5
+ import { getEvmCoinBalance } from './resolvers/evm.js';
6
+ const multicall3Abi = parseAbi(['function getEthBalance(address addr) view returns (uint256)']);
7
+ const getFallbackBalances = async ({ chain, address, coins }) => {
8
+ const entries = await Promise.all(coins.map(async (coin) => {
9
+ const input = { ...coin, chain, address };
10
+ try {
11
+ return [accountCoinKeyToString(input), await getEvmCoinBalance(input)];
12
+ }
13
+ catch {
14
+ return [accountCoinKeyToString(input), 0n];
15
+ }
16
+ }));
17
+ return Object.fromEntries(entries);
18
+ };
19
+ export const getEvmChainBalances = async (input) => {
20
+ const { chain, address, coins } = input;
21
+ if (coins.length === 0) {
22
+ return {};
23
+ }
24
+ const publicClient = getEvmClient(chain);
25
+ const multicall3Address = publicClient.chain?.contracts?.multicall3?.address;
26
+ if (!multicall3Address) {
27
+ return getFallbackBalances(input);
28
+ }
29
+ const contracts = coins.map(coin => isFeeCoin(coin)
30
+ ? {
31
+ address: multicall3Address,
32
+ abi: multicall3Abi,
33
+ functionName: 'getEthBalance',
34
+ args: [address],
35
+ }
36
+ : {
37
+ address: coin.id,
38
+ abi: erc20Abi,
39
+ functionName: 'balanceOf',
40
+ args: [address],
41
+ });
42
+ const results = await publicClient
43
+ .multicall({
44
+ allowFailure: true,
45
+ contracts,
46
+ })
47
+ .catch(() => undefined);
48
+ if (!results) {
49
+ return getFallbackBalances(input);
50
+ }
51
+ return Object.fromEntries(coins.map((coin, index) => {
52
+ const result = results[index];
53
+ const amount = result?.status === 'success' ? BigInt(result.result) : 0n;
54
+ return [accountCoinKeyToString({ ...coin, chain, address }), amount];
55
+ }));
56
+ };
57
+ //# sourceMappingURL=getEvmChainBalances.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getEvmChainBalances.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/coin/balance/getEvmChainBalances.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAA;AACrE,OAAO,EAAkB,sBAAsB,EAAE,MAAM,uCAAuC,CAAA;AAC9F,OAAO,EAAE,SAAS,EAAE,MAAM,2CAA2C,CAAA;AACrE,OAAO,EAAW,QAAQ,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAA;AAElD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAEnD,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAC,6DAA6D,CAAC,CAAC,CAAA;AAU/F,MAAM,mBAAmB,GAAG,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAA4B,EAA6B,EAAE;IACnH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,KAAK,CAAC,GAAG,CAAC,KAAK,EAAC,IAAI,EAAC,EAAE;QACrB,MAAM,KAAK,GAAG,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAA;QAEzC,IAAI,CAAC;YACH,OAAO,CAAC,sBAAsB,CAAC,KAAK,CAAC,EAAE,MAAM,iBAAiB,CAAC,KAAK,CAAC,CAAU,CAAA;QACjF,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,sBAAsB,CAAC,KAAK,CAAC,EAAE,EAAE,CAAU,CAAA;QACrD,CAAC;IACH,CAAC,CAAC,CACH,CAAA;IAED,OAAO,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;AACpC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EAAE,KAA+B,EAA6B,EAAE;IACtG,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,KAAK,CAAA;IAEvC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,CAAA;IACX,CAAC;IAED,MAAM,YAAY,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;IACxC,MAAM,iBAAiB,GAAG,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,CAAA;IAE5E,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,OAAO,mBAAmB,CAAC,KAAK,CAAC,CAAA;IACnC,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CACjC,SAAS,CAAC,IAAI,CAAC;QACb,CAAC,CAAC;YACE,OAAO,EAAE,iBAAiB;YAC1B,GAAG,EAAE,aAAa;YAClB,YAAY,EAAE,eAAe;YAC7B,IAAI,EAAE,CAAC,OAAO,CAAC;SAChB;QACH,CAAC,CAAC;YACE,OAAO,EAAE,IAAI,CAAC,EAAa;YAC3B,GAAG,EAAE,QAAQ;YACb,YAAY,EAAE,WAAW;YACzB,IAAI,EAAE,CAAC,OAAO,CAAC;SAChB,CACN,CAAA;IAED,MAAM,OAAO,GAAG,MAAM,YAAY;SAC/B,SAAS,CAAC;QACT,YAAY,EAAE,IAAI;QAClB,SAAS;KACV,CAAC;SACD,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;IAEzB,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,mBAAmB,CAAC,KAAK,CAAC,CAAA;IACnC,CAAC;IAED,OAAO,MAAM,CAAC,WAAW,CACvB,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACxB,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;QAC7B,MAAM,MAAM,GAAG,MAAM,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAElF,OAAO,CAAC,sBAAsB,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,CAAU,CAAA;IAC/E,CAAC,CAAC,CACH,CAAA;AACH,CAAC,CAAA"}
@@ -1,4 +1,4 @@
1
- export declare const generalSwapProviders: readonly ["1inch", "li.fi", "kyber", "swapkit", "cowswap"];
1
+ export declare const generalSwapProviders: readonly ["1inch", "li.fi", "kyber", "swapkit", "cowswap", "jupiter"];
2
2
  export type GeneralSwapProvider = (typeof generalSwapProviders)[number];
3
3
  export declare const generalSwapProviderName: Record<GeneralSwapProvider, string>;
4
4
  //# sourceMappingURL=GeneralSwapProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GeneralSwapProvider.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/swap/general/GeneralSwapProvider.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,4DAA6D,CAAA;AAE9F,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEvE,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAMvE,CAAA"}
1
+ {"version":3,"file":"GeneralSwapProvider.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/swap/general/GeneralSwapProvider.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,uEAAwE,CAAA;AAEzG,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEvE,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAOvE,CAAA"}
@@ -1,9 +1,10 @@
1
- export const generalSwapProviders = ['1inch', 'li.fi', 'kyber', 'swapkit', 'cowswap'];
1
+ export const generalSwapProviders = ['1inch', 'li.fi', 'kyber', 'swapkit', 'cowswap', 'jupiter'];
2
2
  export const generalSwapProviderName = {
3
3
  '1inch': '1Inch',
4
4
  'li.fi': 'LI.FI',
5
5
  kyber: 'KyberSwap',
6
6
  swapkit: 'SwapKit',
7
7
  cowswap: 'CowSwap',
8
+ jupiter: 'Jupiter',
8
9
  };
9
10
  //# sourceMappingURL=GeneralSwapProvider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"GeneralSwapProvider.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/swap/general/GeneralSwapProvider.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,CAAU,CAAA;AAI9F,MAAM,CAAC,MAAM,uBAAuB,GAAwC;IAC1E,OAAO,EAAE,OAAO;IAChB,OAAO,EAAE,OAAO;IAChB,KAAK,EAAE,WAAW;IAClB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;CACnB,CAAA"}
1
+ {"version":3,"file":"GeneralSwapProvider.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/swap/general/GeneralSwapProvider.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAU,CAAA;AAIzG,MAAM,CAAC,MAAM,uBAAuB,GAAwC;IAC1E,OAAO,EAAE,OAAO;IAChB,OAAO,EAAE,OAAO;IAChB,KAAK,EAAE,WAAW;IAClB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;CACnB,CAAA"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Jupiter is a Solana-only, same-chain aggregator. It can route SOL↔SPL and
3
+ * SPL↔SPL pairs that stay on Solana, and nothing else — there is no cross-chain
4
+ * Jupiter route. `findSwapQuote` therefore only offers Jupiter when both legs
5
+ * are on Solana.
6
+ */
7
+ export declare const jupiterSwapEnabledChains: readonly [import("@vultisig/core-chain/Chain").OtherChain.Solana];
8
+ export type JupiterSwapEnabledChain = (typeof jupiterSwapEnabledChains)[number];
9
+ //# sourceMappingURL=JupiterSwapEnabledChains.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JupiterSwapEnabledChains.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/swap/general/jupiter/JupiterSwapEnabledChains.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,mEAA0B,CAAA;AAE/D,MAAM,MAAM,uBAAuB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAA"}
@@ -0,0 +1,9 @@
1
+ import { Chain } from '@vultisig/core-chain/Chain';
2
+ /**
3
+ * Jupiter is a Solana-only, same-chain aggregator. It can route SOL↔SPL and
4
+ * SPL↔SPL pairs that stay on Solana, and nothing else — there is no cross-chain
5
+ * Jupiter route. `findSwapQuote` therefore only offers Jupiter when both legs
6
+ * are on Solana.
7
+ */
8
+ export const jupiterSwapEnabledChains = [Chain.Solana];
9
+ //# sourceMappingURL=JupiterSwapEnabledChains.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JupiterSwapEnabledChains.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/swap/general/jupiter/JupiterSwapEnabledChains.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAElD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,KAAK,CAAC,MAAM,CAAU,CAAA"}
@@ -0,0 +1,25 @@
1
+ import { AccountCoin } from '@vultisig/core-chain/coin/AccountCoin';
2
+ import { GeneralSwapQuote } from '@vultisig/core-chain/swap/general/GeneralSwapQuote';
3
+ import { JupiterSwapEnabledChain } from '@vultisig/core-chain/swap/general/jupiter/JupiterSwapEnabledChains';
4
+ import { TransferDirection } from '@vultisig/lib-utils/TransferDirection';
5
+ type Input = Record<TransferDirection, AccountCoin<JupiterSwapEnabledChain>> & {
6
+ amount: bigint;
7
+ /** VULT-scaled affiliate fee in bps. `0` disables the platform fee entirely. */
8
+ affiliateBps?: number;
9
+ /** Slippage tolerance in bps (e.g. 50 = 0.5%). Defaults to 50. */
10
+ slippageBps?: number;
11
+ };
12
+ /**
13
+ * Fetch a Solana same-chain swap quote from Jupiter and build the signed-tx
14
+ * payload the keysign pipeline expects.
15
+ *
16
+ * Affiliate fee: when `affiliateBps > 0`, `platformFeeBps` is sent on the quote.
17
+ * The fee ATA (output mint, owner = `jupiterFeeOwnerAddress`) is derived, passed
18
+ * to `/swap` as `feeAccount`, and an idempotent create instruction is prepended
19
+ * to the returned transaction only when the quote actually returns a non-zero
20
+ * `platformFee.amount`. When `affiliateBps` is 0 (e.g. an Ultimate-tier VULT
21
+ * holder) or Jupiter floors the fee to zero, no fee account is touched.
22
+ */
23
+ export declare const getJupiterSwapQuote: ({ from, to, amount, affiliateBps, slippageBps, }: Input) => Promise<GeneralSwapQuote>;
24
+ export {};
25
+ //# sourceMappingURL=getJupiterSwapQuote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getJupiterSwapQuote.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/jupiter/api/getJupiterSwapQuote.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAA;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oDAAoD,CAAA;AAErF,OAAO,EAAE,uBAAuB,EAAE,MAAM,oEAAoE,CAAA;AAC5G,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAUzE,KAAK,KAAK,GAAG,MAAM,CAAC,iBAAiB,EAAE,WAAW,CAAC,uBAAuB,CAAC,CAAC,GAAG;IAC7E,MAAM,EAAE,MAAM,CAAA;IACd,gFAAgF;IAChF,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AA2CD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,GAAU,kDAMvC,KAAK,KAAG,OAAO,CAAC,gBAAgB,CAuFlC,CAAA"}
@@ -0,0 +1,112 @@
1
+ import { Chain } from '@vultisig/core-chain/Chain';
2
+ import { solanaConfig } from '@vultisig/core-chain/chains/solana/solanaConfig';
3
+ import { getJupiterConfig, jupiterFeeOwnerAddress } from '@vultisig/core-chain/swap/general/jupiter/config';
4
+ import { deriveJupiterFeeAccount, prependJupiterFeeAta } from './jupiterFeeAta.js';
5
+ /** Canonical wrapped-SOL mint, used as the mint address for native SOL legs. */
6
+ const solanaNativeMint = 'So11111111111111111111111111111111111111112';
7
+ /** Jupiter default slippage when the caller does not override (bps). */
8
+ const DEFAULT_JUPITER_SLIPPAGE_BPS = 50;
9
+ const mintFor = ({ id }) => id ?? solanaNativeMint;
10
+ const requestJson = async (url, init) => {
11
+ const response = await fetch(url, init);
12
+ const rawText = await response.text().catch(() => '');
13
+ if (!response.ok) {
14
+ const hint = rawText ? ` ${rawText.slice(0, 200)}` : '';
15
+ throw new Error(`Jupiter request failed (${response.status}): ${response.statusText}${hint}`);
16
+ }
17
+ try {
18
+ return JSON.parse(rawText);
19
+ }
20
+ catch {
21
+ throw new Error('Jupiter returned a non-JSON response.');
22
+ }
23
+ };
24
+ /**
25
+ * Fetch a Solana same-chain swap quote from Jupiter and build the signed-tx
26
+ * payload the keysign pipeline expects.
27
+ *
28
+ * Affiliate fee: when `affiliateBps > 0`, `platformFeeBps` is sent on the quote.
29
+ * The fee ATA (output mint, owner = `jupiterFeeOwnerAddress`) is derived, passed
30
+ * to `/swap` as `feeAccount`, and an idempotent create instruction is prepended
31
+ * to the returned transaction only when the quote actually returns a non-zero
32
+ * `platformFee.amount`. When `affiliateBps` is 0 (e.g. an Ultimate-tier VULT
33
+ * holder) or Jupiter floors the fee to zero, no fee account is touched.
34
+ */
35
+ export const getJupiterSwapQuote = async ({ from, to, amount, affiliateBps = 0, slippageBps = DEFAULT_JUPITER_SLIPPAGE_BPS, }) => {
36
+ const { baseUrl } = getJupiterConfig();
37
+ const inputMint = mintFor(from);
38
+ const outputMint = mintFor(to);
39
+ const requestsPlatformFee = affiliateBps > 0;
40
+ const quoteParams = new URLSearchParams({
41
+ swapMode: 'ExactIn',
42
+ inputMint,
43
+ outputMint,
44
+ amount: amount.toString(),
45
+ slippageBps: slippageBps.toString(),
46
+ });
47
+ if (requestsPlatformFee) {
48
+ quoteParams.set('platformFeeBps', affiliateBps.toString());
49
+ }
50
+ const quoteResponse = await requestJson(`${baseUrl}/swap/v1/quote?${quoteParams.toString()}`, {
51
+ headers: { Accept: 'application/json' },
52
+ });
53
+ // Gate the fee-account flow on the actually quoted fee, not just the requested
54
+ // bps: Jupiter can floor `platformFee.amount` to 0 (tiny amounts, route with no
55
+ // fee-eligible mint) even when we asked for a fee. Deriving a fee account and
56
+ // paying ATA rent for a zero fee would break the "no fee account when the fee
57
+ // floors to zero" contract. Require both a requested fee and a non-zero quoted
58
+ // amount before touching the fee account.
59
+ const swapFeeAmount = BigInt(quoteResponse.platformFee?.amount ?? '0');
60
+ const chargesFee = requestsPlatformFee && swapFeeAmount > 0n;
61
+ // The fee mint is the OUTPUT mint (ExactIn). Derive the fee ATA up front so
62
+ // it can be sent to /swap and so we know which program owns it for the
63
+ // prepended create instruction.
64
+ const feeAccountInfo = chargesFee
65
+ ? await deriveJupiterFeeAccount({ outputMint, feeOwner: jupiterFeeOwnerAddress })
66
+ : undefined;
67
+ const swapResponse = await requestJson(`${baseUrl}/swap/v1/swap`, {
68
+ method: 'POST',
69
+ headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
70
+ body: JSON.stringify({
71
+ quoteResponse,
72
+ userPublicKey: from.address,
73
+ wrapAndUnwrapSol: true,
74
+ dynamicComputeUnitLimit: true,
75
+ ...(feeAccountInfo ? { feeAccount: feeAccountInfo.feeAccount } : {}),
76
+ }),
77
+ });
78
+ if (!swapResponse.swapTransaction) {
79
+ throw new Error('Jupiter swap response did not include a serialized transaction.');
80
+ }
81
+ const data = feeAccountInfo
82
+ ? await prependJupiterFeeAta({
83
+ txData: swapResponse.swapTransaction,
84
+ feeAccount: feeAccountInfo.feeAccount,
85
+ mintPubkey: feeAccountInfo.mintPubkey,
86
+ ownerPubkey: feeAccountInfo.ownerPubkey,
87
+ tokenProgramId: feeAccountInfo.tokenProgramId,
88
+ })
89
+ : swapResponse.swapTransaction;
90
+ // Network fee is an upper-bound estimate: Solana's per-signature base fee plus
91
+ // the fee-ATA rent buffer when we prepend a create instruction (charged once
92
+ // per fee mint; idempotent thereafter). Jupiter embeds its own priority fee in
93
+ // the returned tx, which the consumer surfaces at broadcast time.
94
+ const networkFee = BigInt(solanaConfig.baseFee) + (chargesFee ? BigInt(solanaConfig.ataRentLamports) : 0n);
95
+ return {
96
+ dstAmount: quoteResponse.outAmount,
97
+ provider: 'jupiter',
98
+ tx: {
99
+ solana: {
100
+ data,
101
+ networkFee,
102
+ swapFee: {
103
+ amount: swapFeeAmount,
104
+ decimals: to.decimals,
105
+ chain: Chain.Solana,
106
+ id: to.id,
107
+ },
108
+ },
109
+ },
110
+ };
111
+ };
112
+ //# sourceMappingURL=getJupiterSwapQuote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getJupiterSwapQuote.js","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/jupiter/api/getJupiterSwapQuote.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,iDAAiD,CAAA;AAG9E,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,kDAAkD,CAAA;AAI3G,OAAO,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAE/E,gFAAgF;AAChF,MAAM,gBAAgB,GAAG,6CAA6C,CAAA;AAEtE,wEAAwE;AACxE,MAAM,4BAA4B,GAAG,EAAE,CAAA;AAiCvC,MAAM,OAAO,GAAG,CAAC,EAAE,EAAE,EAAe,EAAU,EAAE,CAAC,EAAE,IAAI,gBAAgB,CAAA;AAEvE,MAAM,WAAW,GAAG,KAAK,EAAK,GAAW,EAAE,IAAkB,EAAc,EAAE;IAC3E,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IACvC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;IAErD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QACvD,MAAM,IAAI,KAAK,CAAC,2BAA2B,QAAQ,CAAC,MAAM,MAAM,QAAQ,CAAC,UAAU,GAAG,IAAI,EAAE,CAAC,CAAA;IAC/F,CAAC;IAED,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAM,CAAA;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAA;IAC1D,CAAC;AACH,CAAC,CAAA;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EAAE,EACxC,IAAI,EACJ,EAAE,EACF,MAAM,EACN,YAAY,GAAG,CAAC,EAChB,WAAW,GAAG,4BAA4B,GACpC,EAA6B,EAAE;IACrC,MAAM,EAAE,OAAO,EAAE,GAAG,gBAAgB,EAAE,CAAA;IAEtC,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/B,MAAM,UAAU,GAAG,OAAO,CAAC,EAAE,CAAC,CAAA;IAE9B,MAAM,mBAAmB,GAAG,YAAY,GAAG,CAAC,CAAA;IAE5C,MAAM,WAAW,GAAG,IAAI,eAAe,CAAC;QACtC,QAAQ,EAAE,SAAS;QACnB,SAAS;QACT,UAAU;QACV,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE;QACzB,WAAW,EAAE,WAAW,CAAC,QAAQ,EAAE;KACpC,CAAC,CAAA;IACF,IAAI,mBAAmB,EAAE,CAAC;QACxB,WAAW,CAAC,GAAG,CAAC,gBAAgB,EAAE,YAAY,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC5D,CAAC;IAED,MAAM,aAAa,GAAG,MAAM,WAAW,CAAuB,GAAG,OAAO,kBAAkB,WAAW,CAAC,QAAQ,EAAE,EAAE,EAAE;QAClH,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;KACxC,CAAC,CAAA;IAEF,+EAA+E;IAC/E,gFAAgF;IAChF,8EAA8E;IAC9E,8EAA8E;IAC9E,+EAA+E;IAC/E,0CAA0C;IAC1C,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC,WAAW,EAAE,MAAM,IAAI,GAAG,CAAC,CAAA;IACtE,MAAM,UAAU,GAAG,mBAAmB,IAAI,aAAa,GAAG,EAAE,CAAA;IAE5D,4EAA4E;IAC5E,uEAAuE;IACvE,gCAAgC;IAChC,MAAM,cAAc,GAAG,UAAU;QAC/B,CAAC,CAAC,MAAM,uBAAuB,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,sBAAsB,EAAE,CAAC;QACjF,CAAC,CAAC,SAAS,CAAA;IAEb,MAAM,YAAY,GAAG,MAAM,WAAW,CAAsB,GAAG,OAAO,eAAe,EAAE;QACrF,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,EAAE,kBAAkB,EAAE;QAC3E,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,aAAa;YACb,aAAa,EAAE,IAAI,CAAC,OAAO;YAC3B,gBAAgB,EAAE,IAAI;YACtB,uBAAuB,EAAE,IAAI;YAC7B,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,cAAc,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACrE,CAAC;KACH,CAAC,CAAA;IAEF,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAA;IACpF,CAAC;IAED,MAAM,IAAI,GAAG,cAAc;QACzB,CAAC,CAAC,MAAM,oBAAoB,CAAC;YACzB,MAAM,EAAE,YAAY,CAAC,eAAe;YACpC,UAAU,EAAE,cAAc,CAAC,UAAU;YACrC,UAAU,EAAE,cAAc,CAAC,UAAU;YACrC,WAAW,EAAE,cAAc,CAAC,WAAW;YACvC,cAAc,EAAE,cAAc,CAAC,cAAc;SAC9C,CAAC;QACJ,CAAC,CAAC,YAAY,CAAC,eAAe,CAAA;IAEhC,+EAA+E;IAC/E,6EAA6E;IAC7E,+EAA+E;IAC/E,kEAAkE;IAClE,MAAM,UAAU,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IAE1G,OAAO;QACL,SAAS,EAAE,aAAa,CAAC,SAAS;QAClC,QAAQ,EAAE,SAAS;QACnB,EAAE,EAAE;YACF,MAAM,EAAE;gBACN,IAAI;gBACJ,UAAU;gBACV,OAAO,EAAE;oBACP,MAAM,EAAE,aAAa;oBACrB,QAAQ,EAAE,EAAE,CAAC,QAAQ;oBACrB,KAAK,EAAE,KAAK,CAAC,MAAM;oBACnB,EAAE,EAAE,EAAE,CAAC,EAAE;iBACV;aACF;SACF;KACF,CAAA;AACH,CAAC,CAAA"}
@@ -0,0 +1,48 @@
1
+ import { PublicKey } from '@solana/web3.js';
2
+ export type JupiterFeeAccount = {
3
+ /** Base58 ATA address Jupiter must credit the platform fee to. */
4
+ feeAccount: string;
5
+ /** Token program (Token vs Token-2022) that owns the fee-mint. */
6
+ tokenProgramId: PublicKey;
7
+ mintPubkey: PublicKey;
8
+ ownerPubkey: PublicKey;
9
+ };
10
+ /**
11
+ * Derive the Jupiter platform-fee Associated Token Account for `(owner =
12
+ * feeOwner, mint = outputMint)`. Jupiter charges the affiliate fee in the
13
+ * OUTPUT mint (the only mint allowed for an ExactIn swap besides the input),
14
+ * so the fee mint is always the swap's output mint.
15
+ *
16
+ * The token program is resolved from the mint owner so Token-2022 mints derive
17
+ * the correct ATA. This must be called BEFORE the `/swap` request so the
18
+ * derived `feeAccount` can be passed to Jupiter.
19
+ */
20
+ export declare const deriveJupiterFeeAccount: ({ outputMint, feeOwner, }: {
21
+ outputMint: string;
22
+ feeOwner: string;
23
+ }) => Promise<JupiterFeeAccount>;
24
+ /**
25
+ * Prepend an idempotent `createAssociatedTokenAccount` instruction for the
26
+ * Jupiter fee ATA to the serialized swap transaction.
27
+ *
28
+ * Jupiter's `/swap` endpoint auto-creates the *user's* output ATA but treats
29
+ * the `feeAccount` as a precondition it never initializes — so we must prepend
30
+ * our own create instruction. The idempotent variant is a no-op (no rent
31
+ * charged) when the ATA already exists, making this safe to run on every swap
32
+ * without an existence probe.
33
+ *
34
+ * Rent (~0.002 SOL, the first time per fee mint) is paid by the tx fee-payer
35
+ * (the user), matching the existing LiFi Solana ATA-injection behaviour.
36
+ *
37
+ * `recentBlockhash` is preserved verbatim from Jupiter's quote. The consumer's
38
+ * keysign path refreshes the blockhash before broadcast (same as every other
39
+ * Solana general-swap route), so we do not refresh it here.
40
+ */
41
+ export declare const prependJupiterFeeAta: ({ txData, feeAccount, mintPubkey, ownerPubkey, tokenProgramId, }: {
42
+ txData: string;
43
+ feeAccount: string;
44
+ mintPubkey: PublicKey;
45
+ ownerPubkey: PublicKey;
46
+ tokenProgramId: PublicKey;
47
+ }) => Promise<string>;
48
+ //# sourceMappingURL=jupiterFeeAta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jupiterFeeAta.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/jupiter/api/jupiterFeeAta.ts"],"names":[],"mappings":"AAMA,OAAO,EAA6B,SAAS,EAA4C,MAAM,iBAAiB,CAAA;AAsDhH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAA;IAClB,kEAAkE;IAClE,cAAc,EAAE,SAAS,CAAA;IACzB,UAAU,EAAE,SAAS,CAAA;IACrB,WAAW,EAAE,SAAS,CAAA;CACvB,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,GAAU,2BAG3C;IACD,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;CACjB,KAAG,OAAO,CAAC,iBAAiB,CAa5B,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,oBAAoB,GAAU,kEAMxC;IACD,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,SAAS,CAAA;IACrB,WAAW,EAAE,SAAS,CAAA;IACtB,cAAc,EAAE,SAAS,CAAA;CAC1B,KAAG,OAAO,CAAC,MAAM,CAgDjB,CAAA"}
@@ -0,0 +1,115 @@
1
+ import { createAssociatedTokenAccountIdempotentInstruction, getAssociatedTokenAddressSync, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID, } from '@solana/spl-token';
2
+ import { PublicKey, TransactionMessage, VersionedTransaction } from '@solana/web3.js';
3
+ import { getSolanaClient } from '@vultisig/core-chain/chains/solana/client';
4
+ /** Maximum attempts for LUT fetches before giving up. */
5
+ const MAX_LUT_FETCH_ATTEMPTS = 3;
6
+ /**
7
+ * Fetch a LUT account with simple retry (exponential back-off, up to 3 attempts).
8
+ * RPC timeouts are transient; retrying avoids spurious quote failures.
9
+ */
10
+ const fetchLutWithRetry = async (client, accountKey) => {
11
+ const errors = [];
12
+ for (let attempt = 0; attempt < MAX_LUT_FETCH_ATTEMPTS; attempt++) {
13
+ try {
14
+ const result = await client.getAddressLookupTable(accountKey);
15
+ return result.value ?? null;
16
+ }
17
+ catch (err) {
18
+ errors.push(err);
19
+ if (attempt < MAX_LUT_FETCH_ATTEMPTS - 1) {
20
+ await new Promise(resolve => setTimeout(resolve, 200 * 2 ** attempt));
21
+ }
22
+ }
23
+ }
24
+ console.warn('[jupiterFeeAta] LUT fetch failed after retries:', errors);
25
+ return null;
26
+ };
27
+ /**
28
+ * Resolve the SPL token program (Token vs Token-2022) that owns a mint.
29
+ *
30
+ * Failing to resolve the mint (RPC timeout, bad address, closed account) must
31
+ * throw rather than fall back to TOKEN_PROGRAM_ID — a silent fallback would
32
+ * derive the wrong ATA and produce an opaque simulation failure downstream.
33
+ */
34
+ const resolveTokenProgramId = async (mintPubkey) => {
35
+ const client = getSolanaClient();
36
+ const mintInfo = await client.getAccountInfo(mintPubkey);
37
+ if (!mintInfo) {
38
+ throw new Error(`Mint account ${mintPubkey.toBase58()} not found - cannot determine Token vs Token-2022 program`);
39
+ }
40
+ if (mintInfo.owner.equals(TOKEN_PROGRAM_ID)) {
41
+ return TOKEN_PROGRAM_ID;
42
+ }
43
+ if (mintInfo.owner.equals(TOKEN_2022_PROGRAM_ID)) {
44
+ return TOKEN_2022_PROGRAM_ID;
45
+ }
46
+ throw new Error(`Mint ${mintPubkey.toBase58()} is owned by unsupported program ${mintInfo.owner.toBase58()} - expected Token or Token-2022`);
47
+ };
48
+ /**
49
+ * Derive the Jupiter platform-fee Associated Token Account for `(owner =
50
+ * feeOwner, mint = outputMint)`. Jupiter charges the affiliate fee in the
51
+ * OUTPUT mint (the only mint allowed for an ExactIn swap besides the input),
52
+ * so the fee mint is always the swap's output mint.
53
+ *
54
+ * The token program is resolved from the mint owner so Token-2022 mints derive
55
+ * the correct ATA. This must be called BEFORE the `/swap` request so the
56
+ * derived `feeAccount` can be passed to Jupiter.
57
+ */
58
+ export const deriveJupiterFeeAccount = async ({ outputMint, feeOwner, }) => {
59
+ const mintPubkey = new PublicKey(outputMint);
60
+ const ownerPubkey = new PublicKey(feeOwner);
61
+ const tokenProgramId = await resolveTokenProgramId(mintPubkey);
62
+ const feeAccount = getAssociatedTokenAddressSync(mintPubkey, ownerPubkey,
63
+ /* allowOwnerOffCurve */ false, tokenProgramId).toBase58();
64
+ return { feeAccount, tokenProgramId, mintPubkey, ownerPubkey };
65
+ };
66
+ /**
67
+ * Prepend an idempotent `createAssociatedTokenAccount` instruction for the
68
+ * Jupiter fee ATA to the serialized swap transaction.
69
+ *
70
+ * Jupiter's `/swap` endpoint auto-creates the *user's* output ATA but treats
71
+ * the `feeAccount` as a precondition it never initializes — so we must prepend
72
+ * our own create instruction. The idempotent variant is a no-op (no rent
73
+ * charged) when the ATA already exists, making this safe to run on every swap
74
+ * without an existence probe.
75
+ *
76
+ * Rent (~0.002 SOL, the first time per fee mint) is paid by the tx fee-payer
77
+ * (the user), matching the existing LiFi Solana ATA-injection behaviour.
78
+ *
79
+ * `recentBlockhash` is preserved verbatim from Jupiter's quote. The consumer's
80
+ * keysign path refreshes the blockhash before broadcast (same as every other
81
+ * Solana general-swap route), so we do not refresh it here.
82
+ */
83
+ export const prependJupiterFeeAta = async ({ txData, feeAccount, mintPubkey, ownerPubkey, tokenProgramId, }) => {
84
+ const client = getSolanaClient();
85
+ const versionedTx = VersionedTransaction.deserialize(Buffer.from(txData, 'base64'));
86
+ const lutAccounts = [];
87
+ if (versionedTx.message.version === 0) {
88
+ const lookups = versionedTx.message.addressTableLookups;
89
+ for (const lut of lookups) {
90
+ const lutAccount = await fetchLutWithRetry(client, lut.accountKey);
91
+ if (lutAccount) {
92
+ lutAccounts.push(lutAccount);
93
+ }
94
+ }
95
+ }
96
+ let decompiledMessage;
97
+ try {
98
+ decompiledMessage = TransactionMessage.decompile(versionedTx.message, {
99
+ addressLookupTableAccounts: lutAccounts,
100
+ });
101
+ }
102
+ catch (err) {
103
+ throw new Error(`Failed to decompile Jupiter transaction message - one or more LUT accounts could not be resolved (fetched ${lutAccounts.length} of ${versionedTx.message.addressTableLookups?.length ?? 0} referenced LUTs). Original error: ${err instanceof Error ? err.message : String(err)}`);
104
+ }
105
+ const createFeeAtaIx = createAssociatedTokenAccountIdempotentInstruction(decompiledMessage.payerKey, new PublicKey(feeAccount), ownerPubkey, mintPubkey, tokenProgramId);
106
+ const updatedMessage = new TransactionMessage({
107
+ payerKey: decompiledMessage.payerKey,
108
+ recentBlockhash: decompiledMessage.recentBlockhash,
109
+ instructions: [createFeeAtaIx, ...decompiledMessage.instructions],
110
+ }).compileToV0Message(lutAccounts.length > 0 ? lutAccounts : undefined);
111
+ // Do NOT copy versionedTx.signatures: the message bytes changed, so any
112
+ // signature over the old bytes is invalid. Jupiter does not pre-sign quotes.
113
+ return Buffer.from(new VersionedTransaction(updatedMessage).serialize()).toString('base64');
114
+ };
115
+ //# sourceMappingURL=jupiterFeeAta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jupiterFeeAta.js","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/jupiter/api/jupiterFeeAta.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iDAAiD,EACjD,6BAA6B,EAC7B,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAA6B,SAAS,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAChH,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAA;AAE3E,yDAAyD;AACzD,MAAM,sBAAsB,GAAG,CAAC,CAAA;AAEhC;;;GAGG;AACH,MAAM,iBAAiB,GAAG,KAAK,EAC7B,MAA0C,EAC1C,UAAqB,EACsB,EAAE;IAC7C,MAAM,MAAM,GAAc,EAAE,CAAA;IAC5B,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,sBAAsB,EAAE,OAAO,EAAE,EAAE,CAAC;QAClE,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAA;YAC7D,OAAO,MAAM,CAAC,KAAK,IAAI,IAAI,CAAA;QAC7B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAChB,IAAI,OAAO,GAAG,sBAAsB,GAAG,CAAC,EAAE,CAAC;gBACzC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC,CAAA;YACvE,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,iDAAiD,EAAE,MAAM,CAAC,CAAA;IACvE,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAED;;;;;;GAMG;AACH,MAAM,qBAAqB,GAAG,KAAK,EAAE,UAAqB,EAAsB,EAAE;IAChF,MAAM,MAAM,GAAG,eAAe,EAAE,CAAA;IAChC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,CAAA;IACxD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,gBAAgB,UAAU,CAAC,QAAQ,EAAE,2DAA2D,CAAC,CAAA;IACnH,CAAC;IACD,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC5C,OAAO,gBAAgB,CAAA;IACzB,CAAC;IACD,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,qBAAqB,CAAC,EAAE,CAAC;QACjD,OAAO,qBAAqB,CAAA;IAC9B,CAAC;IACD,MAAM,IAAI,KAAK,CACb,QAAQ,UAAU,CAAC,QAAQ,EAAE,oCAAoC,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,iCAAiC,CAC5H,CAAA;AACH,CAAC,CAAA;AAWD;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,EAAE,EAC5C,UAAU,EACV,QAAQ,GAIT,EAA8B,EAAE;IAC/B,MAAM,UAAU,GAAG,IAAI,SAAS,CAAC,UAAU,CAAC,CAAA;IAC5C,MAAM,WAAW,GAAG,IAAI,SAAS,CAAC,QAAQ,CAAC,CAAA;IAC3C,MAAM,cAAc,GAAG,MAAM,qBAAqB,CAAC,UAAU,CAAC,CAAA;IAE9D,MAAM,UAAU,GAAG,6BAA6B,CAC9C,UAAU,EACV,WAAW;IACX,wBAAwB,CAAC,KAAK,EAC9B,cAAc,CACf,CAAC,QAAQ,EAAE,CAAA;IAEZ,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,CAAA;AAChE,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,EAAE,EACzC,MAAM,EACN,UAAU,EACV,UAAU,EACV,WAAW,EACX,cAAc,GAOf,EAAmB,EAAE;IACpB,MAAM,MAAM,GAAG,eAAe,EAAE,CAAA;IAEhC,MAAM,WAAW,GAAG,oBAAoB,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAA;IAEnF,MAAM,WAAW,GAAgC,EAAE,CAAA;IACnD,IAAI,WAAW,CAAC,OAAO,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;QACtC,MAAM,OAAO,GACX,WAAW,CAAC,OAGb,CAAC,mBAAmB,CAAA;QACrB,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,UAAU,CAAC,CAAA;YAClE,IAAI,UAAU,EAAE,CAAC;gBACf,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,iBAAqC,CAAA;IACzC,IAAI,CAAC;QACH,iBAAiB,GAAG,kBAAkB,CAAC,SAAS,CAAC,WAAW,CAAC,OAAO,EAAE;YACpE,0BAA0B,EAAE,WAAW;SACxC,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,6GAA6G,WAAW,CAAC,MAAM,OAAQ,WAAW,CAAC,OAA+C,CAAC,mBAAmB,EAAE,MAAM,IAAI,CAAC,sCAAsC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAC5T,CAAA;IACH,CAAC;IAED,MAAM,cAAc,GAAG,iDAAiD,CACtE,iBAAiB,CAAC,QAAQ,EAC1B,IAAI,SAAS,CAAC,UAAU,CAAC,EACzB,WAAW,EACX,UAAU,EACV,cAAc,CACf,CAAA;IAED,MAAM,cAAc,GAAG,IAAI,kBAAkB,CAAC;QAC5C,QAAQ,EAAE,iBAAiB,CAAC,QAAQ;QACpC,eAAe,EAAE,iBAAiB,CAAC,eAAe;QAClD,YAAY,EAAE,CAAC,cAAc,EAAE,GAAG,iBAAiB,CAAC,YAAY,CAAC;KAClE,CAAC,CAAC,kBAAkB,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IAEvE,wEAAwE;IACxE,6EAA6E;IAC7E,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,oBAAoB,CAAC,cAAc,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC7F,CAAC,CAAA"}