@vultisig/core-chain 2.36.0 → 2.38.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 (104) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/chains/cosmos/cosmosGasLimitRecord.d.ts.map +1 -1
  3. package/dist/chains/cosmos/cosmosGasLimitRecord.js +13 -14
  4. package/dist/chains/cosmos/cosmosGasLimitRecord.js.map +1 -1
  5. package/dist/chains/cosmos/gas.d.ts +16 -0
  6. package/dist/chains/cosmos/gas.d.ts.map +1 -1
  7. package/dist/chains/cosmos/gas.js +17 -1
  8. package/dist/chains/cosmos/gas.js.map +1 -1
  9. package/dist/chains/solana/kamino/KaminoServiceError.d.ts +63 -0
  10. package/dist/chains/solana/kamino/KaminoServiceError.d.ts.map +1 -0
  11. package/dist/chains/solana/kamino/KaminoServiceError.js +29 -0
  12. package/dist/chains/solana/kamino/KaminoServiceError.js.map +1 -0
  13. package/dist/chains/solana/kamino/amount.d.ts +141 -0
  14. package/dist/chains/solana/kamino/amount.d.ts.map +1 -0
  15. package/dist/chains/solana/kamino/amount.js +156 -0
  16. package/dist/chains/solana/kamino/amount.js.map +1 -0
  17. package/dist/chains/solana/kamino/api.d.ts +20 -0
  18. package/dist/chains/solana/kamino/api.d.ts.map +1 -0
  19. package/dist/chains/solana/kamino/api.js +59 -0
  20. package/dist/chains/solana/kamino/api.js.map +1 -0
  21. package/dist/chains/solana/kamino/baseUnits.d.ts +23 -0
  22. package/dist/chains/solana/kamino/baseUnits.d.ts.map +1 -0
  23. package/dist/chains/solana/kamino/baseUnits.js +30 -0
  24. package/dist/chains/solana/kamino/baseUnits.js.map +1 -0
  25. package/dist/chains/solana/kamino/config.d.ts +27 -0
  26. package/dist/chains/solana/kamino/config.d.ts.map +1 -0
  27. package/dist/chains/solana/kamino/config.js +27 -0
  28. package/dist/chains/solana/kamino/config.js.map +1 -0
  29. package/dist/chains/solana/kamino/decimal.d.ts +24 -0
  30. package/dist/chains/solana/kamino/decimal.d.ts.map +1 -0
  31. package/dist/chains/solana/kamino/decimal.js +52 -0
  32. package/dist/chains/solana/kamino/decimal.js.map +1 -0
  33. package/dist/chains/solana/kamino/models.d.ts +148 -0
  34. package/dist/chains/solana/kamino/models.d.ts.map +1 -0
  35. package/dist/chains/solana/kamino/models.js +2 -0
  36. package/dist/chains/solana/kamino/models.js.map +1 -0
  37. package/dist/chains/solana/kamino/position.d.ts +79 -0
  38. package/dist/chains/solana/kamino/position.d.ts.map +1 -0
  39. package/dist/chains/solana/kamino/position.js +52 -0
  40. package/dist/chains/solana/kamino/position.js.map +1 -0
  41. package/dist/chains/solana/kamino/rate.d.ts +57 -0
  42. package/dist/chains/solana/kamino/rate.d.ts.map +1 -0
  43. package/dist/chains/solana/kamino/rate.js +88 -0
  44. package/dist/chains/solana/kamino/rate.js.map +1 -0
  45. package/dist/chains/solana/kamino/registry.d.ts +70 -0
  46. package/dist/chains/solana/kamino/registry.d.ts.map +1 -0
  47. package/dist/chains/solana/kamino/registry.js +67 -0
  48. package/dist/chains/solana/kamino/registry.js.map +1 -0
  49. package/dist/chains/solana/kamino/tx/actions.d.ts +22 -0
  50. package/dist/chains/solana/kamino/tx/actions.d.ts.map +1 -0
  51. package/dist/chains/solana/kamino/tx/actions.js +85 -0
  52. package/dist/chains/solana/kamino/tx/actions.js.map +1 -0
  53. package/dist/chains/solana/kamino/tx/computeBudget.d.ts +66 -0
  54. package/dist/chains/solana/kamino/tx/computeBudget.d.ts.map +1 -0
  55. package/dist/chains/solana/kamino/tx/computeBudget.js +73 -0
  56. package/dist/chains/solana/kamino/tx/computeBudget.js.map +1 -0
  57. package/dist/chains/solana/kamino/tx/decode.d.ts +121 -0
  58. package/dist/chains/solana/kamino/tx/decode.d.ts.map +1 -0
  59. package/dist/chains/solana/kamino/tx/decode.js +458 -0
  60. package/dist/chains/solana/kamino/tx/decode.js.map +1 -0
  61. package/dist/chains/solana/kamino/tx/instructions.d.ts +260 -0
  62. package/dist/chains/solana/kamino/tx/instructions.d.ts.map +1 -0
  63. package/dist/chains/solana/kamino/tx/instructions.js +256 -0
  64. package/dist/chains/solana/kamino/tx/instructions.js.map +1 -0
  65. package/dist/chains/solana/kamino/tx/sequence.d.ts +123 -0
  66. package/dist/chains/solana/kamino/tx/sequence.d.ts.map +1 -0
  67. package/dist/chains/solana/kamino/tx/sequence.js +235 -0
  68. package/dist/chains/solana/kamino/tx/sequence.js.map +1 -0
  69. package/dist/chains/solana/kamino/tx/validate.d.ts +138 -0
  70. package/dist/chains/solana/kamino/tx/validate.d.ts.map +1 -0
  71. package/dist/chains/solana/kamino/tx/validate.js +542 -0
  72. package/dist/chains/solana/kamino/tx/validate.js.map +1 -0
  73. package/dist/chains/solana/kamino/tx/wire.d.ts +107 -0
  74. package/dist/chains/solana/kamino/tx/wire.d.ts.map +1 -0
  75. package/dist/chains/solana/kamino/tx/wire.js +274 -0
  76. package/dist/chains/solana/kamino/tx/wire.js.map +1 -0
  77. package/dist/chains/solana/kamino/vaultInfo.d.ts +17 -0
  78. package/dist/chains/solana/kamino/vaultInfo.d.ts.map +1 -0
  79. package/dist/chains/solana/kamino/vaultInfo.js +150 -0
  80. package/dist/chains/solana/kamino/vaultInfo.js.map +1 -0
  81. package/dist/chains/thorchain/ruji/services/fetchMergeableTokenBalances.d.ts +6 -1
  82. package/dist/chains/thorchain/ruji/services/fetchMergeableTokenBalances.d.ts.map +1 -1
  83. package/dist/chains/thorchain/ruji/services/fetchMergeableTokenBalances.js +6 -35
  84. package/dist/chains/thorchain/ruji/services/fetchMergeableTokenBalances.js.map +1 -1
  85. package/dist/swap/quote/findSwapQuote.d.ts +39 -0
  86. package/dist/swap/quote/findSwapQuote.d.ts.map +1 -1
  87. package/dist/swap/quote/findSwapQuote.js +33 -2
  88. package/dist/swap/quote/findSwapQuote.js.map +1 -1
  89. package/dist/tx/broadcast/cosmosSequenceMismatch.d.ts +26 -0
  90. package/dist/tx/broadcast/cosmosSequenceMismatch.d.ts.map +1 -0
  91. package/dist/tx/broadcast/cosmosSequenceMismatch.js +79 -0
  92. package/dist/tx/broadcast/cosmosSequenceMismatch.js.map +1 -0
  93. package/dist/tx/broadcast/resolvers/cosmos.d.ts +1 -0
  94. package/dist/tx/broadcast/resolvers/cosmos.d.ts.map +1 -1
  95. package/dist/tx/broadcast/resolvers/cosmos.js +7 -1
  96. package/dist/tx/broadcast/resolvers/cosmos.js.map +1 -1
  97. package/dist/tx/broadcast/transientRetry.d.ts.map +1 -1
  98. package/dist/tx/broadcast/transientRetry.js +6 -0
  99. package/dist/tx/broadcast/transientRetry.js.map +1 -1
  100. package/dist/utils/isValidTokenId.d.ts +6 -3
  101. package/dist/utils/isValidTokenId.d.ts.map +1 -1
  102. package/dist/utils/isValidTokenId.js +10 -3
  103. package/dist/utils/isValidTokenId.js.map +1 -1
  104. package/package.json +97 -2
@@ -0,0 +1,107 @@
1
+ import { VersionedTransaction } from '@solana/web3.js';
2
+ /**
3
+ * Wire-level operations over the v0 transaction Kamino's builder returns:
4
+ * parsing, the two injections (compute budget in front, attribution memo
5
+ * behind), and the blockhash replacement that keeps a built transaction
6
+ * signable after a slow ceremony.
7
+ *
8
+ * Injection appends the program as a new static, read-only, unsigned account
9
+ * key. Static keys are ordered by privilege — writable signers, read-only
10
+ * signers, writable non-signers, read-only non-signers — so the read-only
11
+ * unsigned block is the tail, and appending there plus incrementing
12
+ * `numReadonlyUnsignedAccounts` preserves the ordering without moving any
13
+ * existing key.
14
+ *
15
+ * The one consequence is index drift: indexes at or above the old static
16
+ * count addressed lookup-table-loaded accounts, which now begin one slot
17
+ * later, so each is shifted by one. `programIdIndex` values are untouched — a
18
+ * versioned message may not invoke a program loaded from a lookup table, so
19
+ * every program is already a static key below the insertion point. The
20
+ * indexes *inside* each address-table lookup are positions in the table
21
+ * itself, not in this message, so they are untouched too.
22
+ */
23
+ /** A failure to parse or edit the wire bytes. */
24
+ export declare class KaminoWireError extends Error {
25
+ constructor(detail: string);
26
+ }
27
+ /**
28
+ * Parses the base64 transaction the build endpoints return. `undefined` for
29
+ * bytes that are not a v0 versioned transaction — a legacy message invoking
30
+ * the kVaults program must be surfaced as unreadable, never edited or
31
+ * described.
32
+ */
33
+ export declare const parseKaminoWireTransaction: (base64Transaction: string) => VersionedTransaction | undefined;
34
+ /** Serializes back to the base64 form the keysign payload carries. */
35
+ export declare const serializeKaminoWireTransaction: (transaction: VersionedTransaction) => string;
36
+ /**
37
+ * Whether this is the shape the app is willing to sign: one required
38
+ * signature, no read-only signers, every signature slot still an empty
39
+ * placeholder, and — when `feePayer` is given — that account in slot 0.
40
+ */
41
+ export declare const isUnsignedSingleSigner: (transaction: VersionedTransaction, feePayer?: string) => boolean;
42
+ /** The number of accounts the message addresses, static and lookup-loaded. */
43
+ export declare const totalKaminoAccountCount: (transaction: VersionedTransaction) => number;
44
+ /**
45
+ * Every account the message addresses, in runtime index order: static keys,
46
+ * then every table's writable loads, then every table's read-only loads.
47
+ * `undefined` when a table is missing from `lookupTables` or an index falls
48
+ * outside it — resolution either accounts for every index or fails whole.
49
+ */
50
+ export declare const resolveKaminoAccountAddresses: ({ transaction, lookupTables, }: {
51
+ transaction: VersionedTransaction;
52
+ /** Table address to that table's full address list. */
53
+ lookupTables: Record<string, string[]>;
54
+ }) => string[] | undefined;
55
+ /**
56
+ * Whether the account at a runtime index may be written to, from the header
57
+ * privileges (static region) or the lookup section it was loaded through.
58
+ */
59
+ export declare const isKaminoAccountWritable: ({ transaction, index, }: {
60
+ transaction: VersionedTransaction;
61
+ index: number;
62
+ }) => boolean;
63
+ /**
64
+ * The contents of every lookup table the transaction reads from, via RPC.
65
+ *
66
+ * Every failure surfaces as `KaminoWireError` — a missing table, a stalled
67
+ * node past the deadline, or a transport error — so callers see one rejection
68
+ * type from resolution rather than raw RPC errors.
69
+ */
70
+ export declare const resolveKaminoLookupTables: (transaction: VersionedTransaction) => Promise<Record<string, string[]>>;
71
+ /**
72
+ * Injects the app's ComputeBudget pair in front of the existing instructions.
73
+ *
74
+ * Kamino's builder emits no ComputeBudget instruction, so a transaction that
75
+ * already carries the program — as a key or as an instruction — is not one
76
+ * this app built the fee for, and appending a second pair would double-charge
77
+ * rather than repair it.
78
+ */
79
+ export declare const injectKaminoComputeBudget: ({ transaction, unitLimit, unitPriceMicroLamports, }: {
80
+ transaction: VersionedTransaction;
81
+ unitLimit: number;
82
+ unitPriceMicroLamports: bigint;
83
+ }) => VersionedTransaction;
84
+ /**
85
+ * Appends the attribution memo behind every existing instruction: one SPL
86
+ * Memo instruction carrying exactly the tag, no accounts.
87
+ *
88
+ * The key and the instruction are two ways for a memo to already be here, and
89
+ * appending a second one would both duplicate the account and leave the
90
+ * transaction carrying two attributions — so either form is a refusal.
91
+ */
92
+ export declare const injectKaminoAttributionMemo: (transaction: VersionedTransaction) => VersionedTransaction;
93
+ /**
94
+ * The same transaction over a new recent blockhash.
95
+ *
96
+ * The build endpoints embed a blockhash worth ~60–90 seconds, and an MPC
97
+ * ceremony can outlive it — so the blockhash is replaced immediately before
98
+ * keysign rather than trusted to survive the wait. Nothing else in the
99
+ * message changes.
100
+ */
101
+ export declare const withKaminoRecentBlockhash: ({ transaction, recentBlockhash, }: {
102
+ transaction: VersionedTransaction;
103
+ recentBlockhash: string;
104
+ }) => VersionedTransaction;
105
+ /** Fetches the current blockhash and stamps it onto the transaction. */
106
+ export declare const refreshKaminoRecentBlockhash: (transaction: VersionedTransaction) => Promise<VersionedTransaction>;
107
+ //# sourceMappingURL=wire.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/chains/solana/kamino/tx/wire.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAK5E;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,iDAAiD;AACjD,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,MAAM,EAAE,MAAM;CAI3B;AAED;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,GAAI,mBAAmB,MAAM,KAAG,oBAAoB,GAAG,SAO7F,CAAA;AAED,sEAAsE;AACtE,eAAO,MAAM,8BAA8B,GAAI,aAAa,oBAAoB,KAAG,MAC1B,CAAA;AAEzD;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GAAI,aAAa,oBAAoB,EAAE,WAAW,MAAM,KAAG,OAO7F,CAAA;AAED,8EAA8E;AAC9E,eAAO,MAAM,uBAAuB,GAAI,aAAa,oBAAoB,KAAG,MAKzE,CAAA;AAEH;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,GAAI,gCAG3C;IACD,WAAW,EAAE,oBAAoB,CAAA;IACjC,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;CACvC,KAAG,MAAM,EAAE,GAAG,SAuBd,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAAI,yBAGrC;IACD,WAAW,EAAE,oBAAoB,CAAA;IACjC,KAAK,EAAE,MAAM,CAAA;CACd,KAAG,OAaH,CAAA;AAUD;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GACpC,aAAa,oBAAoB,KAChC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CA6BlC,CAAA;AAkED;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,GAAI,qDAIvC;IACD,WAAW,EAAE,oBAAoB,CAAA;IACjC,SAAS,EAAE,MAAM,CAAA;IACjB,sBAAsB,EAAE,MAAM,CAAA;CAC/B,KAAG,oBAsBH,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,GAAI,aAAa,oBAAoB,KAAG,oBAiB/E,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,GAAI,mCAGvC;IACD,WAAW,EAAE,oBAAoB,CAAA;IACjC,eAAe,EAAE,MAAM,CAAA;CACxB,KAAG,oBAWH,CAAA;AAED,wEAAwE;AACxE,eAAO,MAAM,4BAA4B,GACvC,aAAa,oBAAoB,KAChC,OAAO,CAAC,oBAAoB,CAG9B,CAAA"}
@@ -0,0 +1,274 @@
1
+ import { MessageV0, PublicKey, VersionedTransaction } from '@solana/web3.js';
2
+ import { getSolanaClient } from '../../client.js';
3
+ import { computeBudgetDiscriminators, kaminoAllowedPrograms, kaminoAttributionMemoTagBytes } from './instructions.js';
4
+ /**
5
+ * Wire-level operations over the v0 transaction Kamino's builder returns:
6
+ * parsing, the two injections (compute budget in front, attribution memo
7
+ * behind), and the blockhash replacement that keeps a built transaction
8
+ * signable after a slow ceremony.
9
+ *
10
+ * Injection appends the program as a new static, read-only, unsigned account
11
+ * key. Static keys are ordered by privilege — writable signers, read-only
12
+ * signers, writable non-signers, read-only non-signers — so the read-only
13
+ * unsigned block is the tail, and appending there plus incrementing
14
+ * `numReadonlyUnsignedAccounts` preserves the ordering without moving any
15
+ * existing key.
16
+ *
17
+ * The one consequence is index drift: indexes at or above the old static
18
+ * count addressed lookup-table-loaded accounts, which now begin one slot
19
+ * later, so each is shifted by one. `programIdIndex` values are untouched — a
20
+ * versioned message may not invoke a program loaded from a lookup table, so
21
+ * every program is already a static key below the insertion point. The
22
+ * indexes *inside* each address-table lookup are positions in the table
23
+ * itself, not in this message, so they are untouched too.
24
+ */
25
+ /** A failure to parse or edit the wire bytes. */
26
+ export class KaminoWireError extends Error {
27
+ constructor(detail) {
28
+ super(`Kamino wire transaction: ${detail}`);
29
+ this.name = 'KaminoWireError';
30
+ }
31
+ }
32
+ /**
33
+ * Parses the base64 transaction the build endpoints return. `undefined` for
34
+ * bytes that are not a v0 versioned transaction — a legacy message invoking
35
+ * the kVaults program must be surfaced as unreadable, never edited or
36
+ * described.
37
+ */
38
+ export const parseKaminoWireTransaction = (base64Transaction) => {
39
+ try {
40
+ const transaction = VersionedTransaction.deserialize(Buffer.from(base64Transaction, 'base64'));
41
+ return transaction.version === 0 ? transaction : undefined;
42
+ }
43
+ catch {
44
+ return undefined;
45
+ }
46
+ };
47
+ /** Serializes back to the base64 form the keysign payload carries. */
48
+ export const serializeKaminoWireTransaction = (transaction) => Buffer.from(transaction.serialize()).toString('base64');
49
+ /**
50
+ * Whether this is the shape the app is willing to sign: one required
51
+ * signature, no read-only signers, every signature slot still an empty
52
+ * placeholder, and — when `feePayer` is given — that account in slot 0.
53
+ */
54
+ export const isUnsignedSingleSigner = (transaction, feePayer) => {
55
+ const { header, staticAccountKeys } = transaction.message;
56
+ if (header.numRequiredSignatures !== 1 || header.numReadonlySignedAccounts !== 0)
57
+ return false;
58
+ if (transaction.signatures.length !== 1)
59
+ return false;
60
+ if (transaction.signatures.some(signature => signature.some(byte => byte !== 0)))
61
+ return false;
62
+ if (feePayer !== undefined && staticAccountKeys[0]?.toBase58() !== feePayer)
63
+ return false;
64
+ return true;
65
+ };
66
+ /** The number of accounts the message addresses, static and lookup-loaded. */
67
+ export const totalKaminoAccountCount = (transaction) => transaction.message.staticAccountKeys.length +
68
+ transaction.message.addressTableLookups.reduce((count, lookup) => count + lookup.writableIndexes.length + lookup.readonlyIndexes.length, 0);
69
+ /**
70
+ * Every account the message addresses, in runtime index order: static keys,
71
+ * then every table's writable loads, then every table's read-only loads.
72
+ * `undefined` when a table is missing from `lookupTables` or an index falls
73
+ * outside it — resolution either accounts for every index or fails whole.
74
+ */
75
+ export const resolveKaminoAccountAddresses = ({ transaction, lookupTables, }) => {
76
+ const resolved = transaction.message.staticAccountKeys.map(key => key.toBase58());
77
+ const load = (tableAddress, indexes) => {
78
+ const table = lookupTables[tableAddress];
79
+ if (!table)
80
+ return undefined;
81
+ const addresses = [];
82
+ for (const index of indexes) {
83
+ const address = table[index];
84
+ if (address === undefined)
85
+ return undefined;
86
+ addresses.push(address);
87
+ }
88
+ return addresses;
89
+ };
90
+ for (const kind of ['writableIndexes', 'readonlyIndexes']) {
91
+ for (const lookup of transaction.message.addressTableLookups) {
92
+ const addresses = load(lookup.accountKey.toBase58(), lookup[kind]);
93
+ if (!addresses)
94
+ return undefined;
95
+ resolved.push(...addresses);
96
+ }
97
+ }
98
+ return resolved;
99
+ };
100
+ /**
101
+ * Whether the account at a runtime index may be written to, from the header
102
+ * privileges (static region) or the lookup section it was loaded through.
103
+ */
104
+ export const isKaminoAccountWritable = ({ transaction, index, }) => {
105
+ const { header, staticAccountKeys, addressTableLookups } = transaction.message;
106
+ const staticCount = staticAccountKeys.length;
107
+ if (index < staticCount) {
108
+ const writableSigners = header.numRequiredSignatures - header.numReadonlySignedAccounts;
109
+ if (index < writableSigners)
110
+ return true;
111
+ if (index < header.numRequiredSignatures)
112
+ return false;
113
+ return index < staticCount - header.numReadonlyUnsignedAccounts;
114
+ }
115
+ const writableLoads = addressTableLookups.reduce((count, lookup) => count + lookup.writableIndexes.length, 0);
116
+ return index < staticCount + writableLoads;
117
+ };
118
+ /**
119
+ * Deadline for one lookup-table read. This sits on the signing critical path
120
+ * and the RPC client itself carries no timeout, so an unbounded call would
121
+ * let a stalled node wedge the prepare indefinitely. Matches the HTTP layer's
122
+ * default deadline — comfortably above a healthy read, still bounding a hang.
123
+ */
124
+ const lookupTableReadTimeoutMs = 20_000;
125
+ /**
126
+ * The contents of every lookup table the transaction reads from, via RPC.
127
+ *
128
+ * Every failure surfaces as `KaminoWireError` — a missing table, a stalled
129
+ * node past the deadline, or a transport error — so callers see one rejection
130
+ * type from resolution rather than raw RPC errors.
131
+ */
132
+ export const resolveKaminoLookupTables = async (transaction) => {
133
+ const client = getSolanaClient();
134
+ const tables = {};
135
+ for (const lookup of transaction.message.addressTableLookups) {
136
+ const address = lookup.accountKey.toBase58();
137
+ if (tables[address])
138
+ continue;
139
+ let timeoutId;
140
+ const deadline = new Promise((_, reject) => {
141
+ timeoutId = setTimeout(() => reject(new KaminoWireError(`address lookup table ${address} read timed out after ${lookupTableReadTimeoutMs}ms`)), lookupTableReadTimeoutMs);
142
+ });
143
+ try {
144
+ const table = await Promise.race([client.getAddressLookupTable(lookup.accountKey), deadline]);
145
+ if (!table.value)
146
+ throw new KaminoWireError(`address lookup table ${address} not found`);
147
+ tables[address] = table.value.state.addresses.map(key => key.toBase58());
148
+ }
149
+ catch (error) {
150
+ if (error instanceof KaminoWireError)
151
+ throw error;
152
+ throw new KaminoWireError(`address lookup table ${address} could not be read: ${extractErrorMessage(error)}`);
153
+ }
154
+ finally {
155
+ clearTimeout(timeoutId);
156
+ }
157
+ }
158
+ return tables;
159
+ };
160
+ const extractErrorMessage = (error) => (error instanceof Error ? error.message : String(error));
161
+ /**
162
+ * Appends `programKey` as a new static, read-only, unsigned account key and
163
+ * rebuilds the message with `leading` instructions in front of the existing
164
+ * ones and `trailing` behind them. Both callbacks receive the index the new
165
+ * key lands at. See the module doc for why lookup-region indexes shift.
166
+ */
167
+ const injectProgram = (transaction, programKey, leading, trailing) => {
168
+ const message = transaction.message;
169
+ const staticCount = message.staticAccountKeys.length;
170
+ const shift = (index) => (index >= staticCount ? index + 1 : index);
171
+ const shifted = message.compiledInstructions.map(instruction => ({
172
+ programIdIndex: instruction.programIdIndex,
173
+ accountKeyIndexes: instruction.accountKeyIndexes.map(shift),
174
+ data: instruction.data,
175
+ }));
176
+ const injected = new MessageV0({
177
+ header: {
178
+ numRequiredSignatures: message.header.numRequiredSignatures,
179
+ numReadonlySignedAccounts: message.header.numReadonlySignedAccounts,
180
+ numReadonlyUnsignedAccounts: message.header.numReadonlyUnsignedAccounts + 1,
181
+ },
182
+ staticAccountKeys: [...message.staticAccountKeys, new PublicKey(programKey)],
183
+ recentBlockhash: message.recentBlockhash,
184
+ compiledInstructions: [...leading(staticCount), ...shifted, ...trailing(staticCount)],
185
+ addressTableLookups: message.addressTableLookups,
186
+ });
187
+ return new VersionedTransaction(injected);
188
+ };
189
+ const invokesProgram = (transaction, programKey) => {
190
+ const keys = transaction.message.staticAccountKeys.map(key => key.toBase58());
191
+ return transaction.message.compiledInstructions.some(instruction => keys[instruction.programIdIndex] === programKey);
192
+ };
193
+ const hasStaticKey = (transaction, key) => transaction.message.staticAccountKeys.some(existing => existing.toBase58() === key);
194
+ const u32LittleEndian = (value) => {
195
+ const bytes = new Uint8Array(4);
196
+ new DataView(bytes.buffer).setUint32(0, value, true);
197
+ return bytes;
198
+ };
199
+ const u64LittleEndian = (value) => {
200
+ const bytes = new Uint8Array(8);
201
+ new DataView(bytes.buffer).setBigUint64(0, value, true);
202
+ return bytes;
203
+ };
204
+ /**
205
+ * Injects the app's ComputeBudget pair in front of the existing instructions.
206
+ *
207
+ * Kamino's builder emits no ComputeBudget instruction, so a transaction that
208
+ * already carries the program — as a key or as an instruction — is not one
209
+ * this app built the fee for, and appending a second pair would double-charge
210
+ * rather than repair it.
211
+ */
212
+ export const injectKaminoComputeBudget = ({ transaction, unitLimit, unitPriceMicroLamports, }) => {
213
+ const program = kaminoAllowedPrograms.computeBudget;
214
+ if (hasStaticKey(transaction, program) || invokesProgram(transaction, program)) {
215
+ throw new KaminoWireError('compute budget already present');
216
+ }
217
+ return injectProgram(transaction, program, programIdIndex => [
218
+ {
219
+ programIdIndex,
220
+ accountKeyIndexes: [],
221
+ data: Uint8Array.from([computeBudgetDiscriminators.setUnitLimit, ...u32LittleEndian(unitLimit)]),
222
+ },
223
+ {
224
+ programIdIndex,
225
+ accountKeyIndexes: [],
226
+ data: Uint8Array.from([computeBudgetDiscriminators.setUnitPrice, ...u64LittleEndian(unitPriceMicroLamports)]),
227
+ },
228
+ ], () => []);
229
+ };
230
+ /**
231
+ * Appends the attribution memo behind every existing instruction: one SPL
232
+ * Memo instruction carrying exactly the tag, no accounts.
233
+ *
234
+ * The key and the instruction are two ways for a memo to already be here, and
235
+ * appending a second one would both duplicate the account and leave the
236
+ * transaction carrying two attributions — so either form is a refusal.
237
+ */
238
+ export const injectKaminoAttributionMemo = (transaction) => {
239
+ const program = kaminoAllowedPrograms.memo;
240
+ if (hasStaticKey(transaction, program) || invokesProgram(transaction, program)) {
241
+ throw new KaminoWireError('attribution memo already present');
242
+ }
243
+ return injectProgram(transaction, program, () => [], programIdIndex => [
244
+ {
245
+ programIdIndex,
246
+ accountKeyIndexes: [],
247
+ data: kaminoAttributionMemoTagBytes,
248
+ },
249
+ ]);
250
+ };
251
+ /**
252
+ * The same transaction over a new recent blockhash.
253
+ *
254
+ * The build endpoints embed a blockhash worth ~60–90 seconds, and an MPC
255
+ * ceremony can outlive it — so the blockhash is replaced immediately before
256
+ * keysign rather than trusted to survive the wait. Nothing else in the
257
+ * message changes.
258
+ */
259
+ export const withKaminoRecentBlockhash = ({ transaction, recentBlockhash, }) => {
260
+ const message = transaction.message;
261
+ return new VersionedTransaction(new MessageV0({
262
+ header: message.header,
263
+ staticAccountKeys: message.staticAccountKeys,
264
+ recentBlockhash,
265
+ compiledInstructions: message.compiledInstructions,
266
+ addressTableLookups: message.addressTableLookups,
267
+ }));
268
+ };
269
+ /** Fetches the current blockhash and stamps it onto the transaction. */
270
+ export const refreshKaminoRecentBlockhash = async (transaction) => {
271
+ const { blockhash } = await getSolanaClient().getLatestBlockhash();
272
+ return withKaminoRecentBlockhash({ transaction, recentBlockhash: blockhash });
273
+ };
274
+ //# sourceMappingURL=wire.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire.js","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/chains/solana/kamino/tx/wire.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { KaminoVaultInfo } from './models.js';
2
+ /**
3
+ * Hydrates a curated vault with live state and metrics.
4
+ *
5
+ * Takes an address and resolves the descriptor from the registry itself, so
6
+ * descriptor-shaped data from anywhere else can never decide a vault's
7
+ * identity; an address the registry does not carry is refused. The response's
8
+ * account of the vault is then checked against the pinned identity, every
9
+ * numeric field is parsed under the strict decimal rules (a value that fails
10
+ * throws rather than defaulting to zero), and the published minimums are
11
+ * replaced by the effective ones the program actually accepts.
12
+ *
13
+ * Uncached — client layers own caching (and their caches then hold only
14
+ * hydrations that cleared every check here).
15
+ */
16
+ export declare const fetchKaminoVaultInfo: (vaultAddress: string) => Promise<KaminoVaultInfo>;
17
+ //# sourceMappingURL=vaultInfo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vaultInfo.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/solana/kamino/vaultInfo.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,eAAe,EAA4B,MAAM,UAAU,CAAA;AA6EpE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,oBAAoB,GAAU,cAAc,MAAM,KAAG,OAAO,CAAC,eAAe,CAmExF,CAAA"}
@@ -0,0 +1,150 @@
1
+ import { isValidKaminoRequestAmount, kaminoTokenAmount, kaminoTokenAmountFromBaseUnitString, kaminoTokenAmountFromDecimalString, kaminoTokenToShareAmountRoundedUp, } from './amount.js';
2
+ import { fetchKaminoVaultMetrics, fetchKaminoVaultState } from './api.js';
3
+ import { parseKaminoDisplayDecimal } from './decimal.js';
4
+ import { KaminoServiceError } from './KaminoServiceError.js';
5
+ import { isPositiveKaminoRate, parseKaminoRate } from './rate.js';
6
+ import { getKaminoVaultDescriptor } from './registry.js';
7
+ /**
8
+ * A margin of one part in this many — a tenth of a percent — added to the
9
+ * published minimum deposit.
10
+ */
11
+ const minimumDepositMarginDivisor = 1000n;
12
+ /**
13
+ * Smallest deposit margin in base units, for a minimum too small for the
14
+ * proportional one to clear a rounding loss. Larger than either measured
15
+ * shortfall (8 and 10 base units on the launch vaults).
16
+ */
17
+ const minimumDepositMarginFloor = 16n;
18
+ /**
19
+ * Multiple of the published minimum a withdraw's token value must reach.
20
+ *
21
+ * The floor measured on-chain sits just above two; the third is margin,
22
+ * because the rule is a reading of observed behaviour rather than a documented
23
+ * contract.
24
+ */
25
+ const minimumWithdrawMultiple = 3n;
26
+ /** The Solana default/system address doubles as "no farm attached". */
27
+ const systemProgramAddress = '11111111111111111111111111111111';
28
+ /**
29
+ * The smallest deposit a form may offer.
30
+ *
31
+ * The published `minDepositAmount` is in the right unit — unlike its withdraw
32
+ * counterpart — but the program still refuses a deposit *at* it, with
33
+ * `DepositAmountBelowMinimum`. Measured at one base unit of resolution the
34
+ * shortfall is a handful of base units and moves with the share rate — a
35
+ * rounding loss in the share the deposit mints, not a second threshold. The
36
+ * margin is therefore proportional with an absolute floor, both generous
37
+ * against what was measured and both invisible in money.
38
+ */
39
+ const effectiveMinimumDeposit = (published) => {
40
+ const proportional = (published.baseUnits + minimumDepositMarginDivisor - 1n) / minimumDepositMarginDivisor;
41
+ const margin = proportional > minimumDepositMarginFloor ? proportional : minimumDepositMarginFloor;
42
+ return kaminoTokenAmount(published.baseUnits + margin, published.decimals);
43
+ };
44
+ const malformed = (field, value) => new KaminoServiceError({ malformedNumber: { field, value } });
45
+ const assertFieldMatchesRegistry = (field, actual, expected) => {
46
+ if (actual !== expected) {
47
+ throw new KaminoServiceError({ vaultMetadataMismatch: { field, expected, actual } });
48
+ }
49
+ };
50
+ /**
51
+ * Refuses a response whose account of the vault differs from the registry's.
52
+ *
53
+ * The mints, their decimals and the farm are immutable properties of a kVault,
54
+ * so this can never fire on a legitimate change. It exists because those
55
+ * values decide where funds go and how amounts are scaled: taking them from
56
+ * the API would mean validating a transaction the API built against values the
57
+ * same API supplied, and the pair could be made consistent. Checking here
58
+ * means the whole feature works from a vault identity the app already knew.
59
+ */
60
+ const assertMatchesRegistry = (state, descriptor) => {
61
+ assertFieldMatchesRegistry('tokenMint', state.tokenMint, descriptor.tokenMint);
62
+ assertFieldMatchesRegistry('sharesMint', state.sharesMint, descriptor.sharesMint);
63
+ assertFieldMatchesRegistry('tokenMintDecimals', String(state.tokenMintDecimals), String(descriptor.tokenDecimals));
64
+ assertFieldMatchesRegistry('sharesMintDecimals', String(state.sharesMintDecimals), String(descriptor.sharesDecimals));
65
+ assertFieldMatchesRegistry('vaultFarm', normalizeFarm(state.vaultFarm) ?? '', descriptor.farm ?? '');
66
+ };
67
+ const normalizeFarm = (address) => {
68
+ if (!address || address === systemProgramAddress)
69
+ return undefined;
70
+ return address;
71
+ };
72
+ /**
73
+ * Hydrates a curated vault with live state and metrics.
74
+ *
75
+ * Takes an address and resolves the descriptor from the registry itself, so
76
+ * descriptor-shaped data from anywhere else can never decide a vault's
77
+ * identity; an address the registry does not carry is refused. The response's
78
+ * account of the vault is then checked against the pinned identity, every
79
+ * numeric field is parsed under the strict decimal rules (a value that fails
80
+ * throws rather than defaulting to zero), and the published minimums are
81
+ * replaced by the effective ones the program actually accepts.
82
+ *
83
+ * Uncached — client layers own caching (and their caches then hold only
84
+ * hydrations that cleared every check here).
85
+ */
86
+ export const fetchKaminoVaultInfo = async (vaultAddress) => {
87
+ const descriptor = getKaminoVaultDescriptor(vaultAddress);
88
+ if (!descriptor) {
89
+ throw new KaminoServiceError({ vaultNotInRegistry: vaultAddress });
90
+ }
91
+ const [{ state }, metrics] = await Promise.all([
92
+ fetchKaminoVaultState(descriptor.address),
93
+ fetchKaminoVaultMetrics(descriptor.address),
94
+ ]);
95
+ assertMatchesRegistry(state, descriptor);
96
+ // The published figures are numbers a remote service hands us, and they end
97
+ // up bounding what a user may spend. A non-positive or absurd one is refused
98
+ // rather than propagated into a minimum nothing can satisfy.
99
+ const publishedMinDeposit = kaminoTokenAmountFromBaseUnitString(state.minDepositAmount, descriptor.tokenDecimals);
100
+ if (!publishedMinDeposit)
101
+ throw malformed('minDepositAmount', state.minDepositAmount);
102
+ const minDeposit = effectiveMinimumDeposit(publishedMinDeposit);
103
+ if (!isValidKaminoRequestAmount(publishedMinDeposit) || !isValidKaminoRequestAmount(minDeposit)) {
104
+ throw malformed('minDepositAmount', state.minDepositAmount);
105
+ }
106
+ // TOKEN base units, despite the field naming the unit the withdraw endpoint
107
+ // takes. The two scales differ on the SOL vault (9 vs 6), so reading it
108
+ // wrong is silent there and a ~930× error — see `models.ts`.
109
+ const publishedMinWithdraw = kaminoTokenAmountFromBaseUnitString(state.minWithdrawAmount, descriptor.tokenDecimals);
110
+ if (!publishedMinWithdraw)
111
+ throw malformed('minWithdrawAmount', state.minWithdrawAmount);
112
+ const apy30d = parseKaminoDisplayDecimal(metrics.apy30d);
113
+ if (apy30d === undefined)
114
+ throw malformed('apy30d', metrics.apy30d);
115
+ const tokenPriceUsd = parseKaminoDisplayDecimal(metrics.tokenPrice);
116
+ if (tokenPriceUsd === undefined)
117
+ throw malformed('tokenPrice', metrics.tokenPrice);
118
+ // Parsed exactly rather than as a display decimal: this rate converts a
119
+ // user's token amount into the shares a withdraw burns.
120
+ const tokensPerShare = parseKaminoRate(metrics.tokensPerShare);
121
+ if (!tokensPerShare || !isPositiveKaminoRate(tokensPerShare)) {
122
+ throw malformed('tokensPerShare', metrics.tokensPerShare);
123
+ }
124
+ // The program's own withdraw floor is higher than the published figure, so
125
+ // the form minimum is a multiple of it, converted to the share count a
126
+ // withdraw has to name — rounded up, because a share count worth
127
+ // fractionally less than the minimum is exactly the failure being avoided.
128
+ const minWithdraw = kaminoTokenToShareAmountRoundedUp({
129
+ tokens: kaminoTokenAmount(publishedMinWithdraw.baseUnits * minimumWithdrawMultiple, publishedMinWithdraw.decimals),
130
+ tokensPerShare,
131
+ shareDecimals: descriptor.sharesDecimals,
132
+ });
133
+ if (!minWithdraw || !isValidKaminoRequestAmount(publishedMinWithdraw) || !isValidKaminoRequestAmount(minWithdraw)) {
134
+ throw malformed('minWithdrawAmount', state.minWithdrawAmount);
135
+ }
136
+ return {
137
+ descriptor,
138
+ name: state.name,
139
+ minDeposit,
140
+ minWithdraw,
141
+ lookupTable: state.vaultLookupTable,
142
+ apy30d,
143
+ tokensPerShare,
144
+ tokenPriceUsd,
145
+ // Advisory, so an unreadable value drops the liquidity notice rather than
146
+ // failing the whole hydration and blocking deposits too.
147
+ tokensAvailable: kaminoTokenAmountFromDecimalString(metrics.tokensAvailable, descriptor.tokenDecimals),
148
+ };
149
+ };
150
+ //# sourceMappingURL=vaultInfo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vaultInfo.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/solana/kamino/vaultInfo.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAE1B,iBAAiB,EACjB,mCAAmC,EACnC,kCAAkC,EAClC,iCAAiC,GAClC,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,OAAO,CAAA;AACtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAA;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAEzD,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAA;AAC9D,OAAO,EAAE,wBAAwB,EAAyB,MAAM,YAAY,CAAA;AAE5E;;;GAGG;AACH,MAAM,2BAA2B,GAAG,KAAK,CAAA;AAEzC;;;;GAIG;AACH,MAAM,yBAAyB,GAAG,GAAG,CAAA;AAErC;;;;;;GAMG;AACH,MAAM,uBAAuB,GAAG,EAAE,CAAA;AAElC,uEAAuE;AACvE,MAAM,oBAAoB,GAAG,kCAAkC,CAAA;AAE/D;;;;;;;;;;GAUG;AACH,MAAM,uBAAuB,GAAG,CAAC,SAA4B,EAAqB,EAAE;IAClF,MAAM,YAAY,GAAG,CAAC,SAAS,CAAC,SAAS,GAAG,2BAA2B,GAAG,EAAE,CAAC,GAAG,2BAA2B,CAAA;IAC3G,MAAM,MAAM,GAAG,YAAY,GAAG,yBAAyB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,yBAAyB,CAAA;IAClG,OAAO,iBAAiB,CAAC,SAAS,CAAC,SAAS,GAAG,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAA;AAC5E,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,CAAC,KAAa,EAAE,KAAa,EAAE,EAAE,CAAC,IAAI,kBAAkB,CAAC,EAAE,eAAe,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAA;AAEjH,MAAM,0BAA0B,GAAG,CAAC,KAAa,EAAE,MAAc,EAAE,QAAgB,EAAE,EAAE;IACrF,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,MAAM,IAAI,kBAAkB,CAAC,EAAE,qBAAqB,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,CAAA;IACtF,CAAC;AACH,CAAC,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,qBAAqB,GAAG,CAAC,KAAwC,EAAE,UAAiC,EAAE,EAAE;IAC5G,0BAA0B,CAAC,WAAW,EAAE,KAAK,CAAC,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,CAAA;IAC9E,0BAA0B,CAAC,YAAY,EAAE,KAAK,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,CAAA;IACjF,0BAA0B,CAAC,mBAAmB,EAAE,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAA;IAClH,0BAA0B,CAAC,oBAAoB,EAAE,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAA;IACrH,0BAA0B,CAAC,WAAW,EAAE,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,UAAU,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;AACtG,CAAC,CAAA;AAED,MAAM,aAAa,GAAG,CAAC,OAAe,EAAsB,EAAE;IAC5D,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,oBAAoB;QAAE,OAAO,SAAS,CAAA;IAClE,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,EAAE,YAAoB,EAA4B,EAAE;IAC3F,MAAM,UAAU,GAAG,wBAAwB,CAAC,YAAY,CAAC,CAAA;IACzD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,kBAAkB,CAAC,EAAE,kBAAkB,EAAE,YAAY,EAAE,CAAC,CAAA;IACpE,CAAC;IAED,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC7C,qBAAqB,CAAC,UAAU,CAAC,OAAO,CAAC;QACzC,uBAAuB,CAAC,UAAU,CAAC,OAAO,CAAC;KAC5C,CAAC,CAAA;IAEF,qBAAqB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;IAExC,4EAA4E;IAC5E,6EAA6E;IAC7E,6DAA6D;IAC7D,MAAM,mBAAmB,GAAG,mCAAmC,CAAC,KAAK,CAAC,gBAAgB,EAAE,UAAU,CAAC,aAAa,CAAC,CAAA;IACjH,IAAI,CAAC,mBAAmB;QAAE,MAAM,SAAS,CAAC,kBAAkB,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAA;IACrF,MAAM,UAAU,GAAG,uBAAuB,CAAC,mBAAmB,CAAC,CAAA;IAC/D,IAAI,CAAC,0BAA0B,CAAC,mBAAmB,CAAC,IAAI,CAAC,0BAA0B,CAAC,UAAU,CAAC,EAAE,CAAC;QAChG,MAAM,SAAS,CAAC,kBAAkB,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAA;IAC7D,CAAC;IAED,4EAA4E;IAC5E,wEAAwE;IACxE,6DAA6D;IAC7D,MAAM,oBAAoB,GAAG,mCAAmC,CAAC,KAAK,CAAC,iBAAiB,EAAE,UAAU,CAAC,aAAa,CAAC,CAAA;IACnH,IAAI,CAAC,oBAAoB;QAAE,MAAM,SAAS,CAAC,mBAAmB,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAA;IAExF,MAAM,MAAM,GAAG,yBAAyB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IACxD,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;IACnE,MAAM,aAAa,GAAG,yBAAyB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IACnE,IAAI,aAAa,KAAK,SAAS;QAAE,MAAM,SAAS,CAAC,YAAY,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;IAElF,wEAAwE;IACxE,wDAAwD;IACxD,MAAM,cAAc,GAAG,eAAe,CAAC,OAAO,CAAC,cAAc,CAAC,CAAA;IAC9D,IAAI,CAAC,cAAc,IAAI,CAAC,oBAAoB,CAAC,cAAc,CAAC,EAAE,CAAC;QAC7D,MAAM,SAAS,CAAC,gBAAgB,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;IAC3D,CAAC;IAED,2EAA2E;IAC3E,uEAAuE;IACvE,iEAAiE;IACjE,2EAA2E;IAC3E,MAAM,WAAW,GAAG,iCAAiC,CAAC;QACpD,MAAM,EAAE,iBAAiB,CAAC,oBAAoB,CAAC,SAAS,GAAG,uBAAuB,EAAE,oBAAoB,CAAC,QAAQ,CAAC;QAClH,cAAc;QACd,aAAa,EAAE,UAAU,CAAC,cAAc;KACzC,CAAC,CAAA;IACF,IAAI,CAAC,WAAW,IAAI,CAAC,0BAA0B,CAAC,oBAAoB,CAAC,IAAI,CAAC,0BAA0B,CAAC,WAAW,CAAC,EAAE,CAAC;QAClH,MAAM,SAAS,CAAC,mBAAmB,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAA;IAC/D,CAAC;IAED,OAAO;QACL,UAAU;QACV,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,UAAU;QACV,WAAW;QACX,WAAW,EAAE,KAAK,CAAC,gBAAgB;QACnC,MAAM;QACN,cAAc;QACd,aAAa;QACb,0EAA0E;QAC1E,yDAAyD;QACzD,eAAe,EAAE,kCAAkC,CAAC,OAAO,CAAC,eAAe,EAAE,UAAU,CAAC,aAAa,CAAC;KACvG,CAAA;AACH,CAAC,CAAA"}
@@ -3,6 +3,11 @@ type TokenBalance = {
3
3
  sharesChain: string;
4
4
  sizeAmountChain: string;
5
5
  };
6
- export declare const fetchMergeableTokenBalances: (thorAddr: string) => Promise<TokenBalance[]>;
6
+ /**
7
+ * @deprecated The KUJI-to-RUJI merge window closed on 2026-04-05.
8
+ *
9
+ * Kept as an inert compatibility shim for the published package subpath.
10
+ */
11
+ export declare const fetchMergeableTokenBalances: (_thorAddr: string) => Promise<TokenBalance[]>;
7
12
  export {};
8
13
  //# sourceMappingURL=fetchMergeableTokenBalances.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fetchMergeableTokenBalances.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/chains/thorchain/ruji/services/fetchMergeableTokenBalances.ts"],"names":[],"mappings":"AAqBA,KAAK,YAAY,GAAG;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,eAAO,MAAM,2BAA2B,GAAU,UAAU,MAAM,KAAG,OAAO,CAAC,YAAY,EAAE,CAoC1F,CAAA"}
1
+ {"version":3,"file":"fetchMergeableTokenBalances.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/chains/thorchain/ruji/services/fetchMergeableTokenBalances.ts"],"names":[],"mappings":"AAAA,KAAK,YAAY,GAAG;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;CACxB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,GAAU,WAAW,MAAM,KAAG,OAAO,CAAC,YAAY,EAAE,CAAO,CAAA"}
@@ -1,36 +1,7 @@
1
- import { queryUrl } from '@vultisig/lib-utils/query/queryUrl';
2
- import { rujiraGraphQlEndpoint } from '../../../cosmos/thor/rujira/config.js';
3
- export const fetchMergeableTokenBalances = async (thorAddr) => {
4
- const { data, errors } = await queryUrl(rujiraGraphQlEndpoint, {
5
- body: {
6
- query: `
7
- query ($id: ID!) {
8
- node(id: $id) {
9
- ... on Account {
10
- merge {
11
- accounts {
12
- shares
13
- size { amount }
14
- pool {
15
- mergeAsset { metadata { symbol } }
16
- }
17
- }
18
- }
19
- }
20
- }}`,
21
- variables: { id: btoa(`Account:${thorAddr}`) },
22
- },
23
- });
24
- if (errors) {
25
- throw new Error(`GraphQL errors: ${JSON.stringify(errors)}`);
26
- }
27
- const accounts = data?.node?.merge?.accounts ?? [];
28
- return accounts.map(account => {
29
- return {
30
- symbol: account.pool.mergeAsset.metadata.symbol,
31
- sharesChain: account.shares,
32
- sizeAmountChain: account.size.amount,
33
- };
34
- });
35
- };
1
+ /**
2
+ * @deprecated The KUJI-to-RUJI merge window closed on 2026-04-05.
3
+ *
4
+ * Kept as an inert compatibility shim for the published package subpath.
5
+ */
6
+ export const fetchMergeableTokenBalances = async (_thorAddr) => [];
36
7
  //# sourceMappingURL=fetchMergeableTokenBalances.js.map