@vultisig/core-chain 2.37.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 (74) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/chains/solana/kamino/KaminoServiceError.d.ts +63 -0
  3. package/dist/chains/solana/kamino/KaminoServiceError.d.ts.map +1 -0
  4. package/dist/chains/solana/kamino/KaminoServiceError.js +29 -0
  5. package/dist/chains/solana/kamino/KaminoServiceError.js.map +1 -0
  6. package/dist/chains/solana/kamino/amount.d.ts +141 -0
  7. package/dist/chains/solana/kamino/amount.d.ts.map +1 -0
  8. package/dist/chains/solana/kamino/amount.js +156 -0
  9. package/dist/chains/solana/kamino/amount.js.map +1 -0
  10. package/dist/chains/solana/kamino/api.d.ts +20 -0
  11. package/dist/chains/solana/kamino/api.d.ts.map +1 -0
  12. package/dist/chains/solana/kamino/api.js +59 -0
  13. package/dist/chains/solana/kamino/api.js.map +1 -0
  14. package/dist/chains/solana/kamino/baseUnits.d.ts +23 -0
  15. package/dist/chains/solana/kamino/baseUnits.d.ts.map +1 -0
  16. package/dist/chains/solana/kamino/baseUnits.js +30 -0
  17. package/dist/chains/solana/kamino/baseUnits.js.map +1 -0
  18. package/dist/chains/solana/kamino/config.d.ts +27 -0
  19. package/dist/chains/solana/kamino/config.d.ts.map +1 -0
  20. package/dist/chains/solana/kamino/config.js +27 -0
  21. package/dist/chains/solana/kamino/config.js.map +1 -0
  22. package/dist/chains/solana/kamino/decimal.d.ts +24 -0
  23. package/dist/chains/solana/kamino/decimal.d.ts.map +1 -0
  24. package/dist/chains/solana/kamino/decimal.js +52 -0
  25. package/dist/chains/solana/kamino/decimal.js.map +1 -0
  26. package/dist/chains/solana/kamino/models.d.ts +148 -0
  27. package/dist/chains/solana/kamino/models.d.ts.map +1 -0
  28. package/dist/chains/solana/kamino/models.js +2 -0
  29. package/dist/chains/solana/kamino/models.js.map +1 -0
  30. package/dist/chains/solana/kamino/position.d.ts +79 -0
  31. package/dist/chains/solana/kamino/position.d.ts.map +1 -0
  32. package/dist/chains/solana/kamino/position.js +52 -0
  33. package/dist/chains/solana/kamino/position.js.map +1 -0
  34. package/dist/chains/solana/kamino/rate.d.ts +57 -0
  35. package/dist/chains/solana/kamino/rate.d.ts.map +1 -0
  36. package/dist/chains/solana/kamino/rate.js +88 -0
  37. package/dist/chains/solana/kamino/rate.js.map +1 -0
  38. package/dist/chains/solana/kamino/registry.d.ts +70 -0
  39. package/dist/chains/solana/kamino/registry.d.ts.map +1 -0
  40. package/dist/chains/solana/kamino/registry.js +67 -0
  41. package/dist/chains/solana/kamino/registry.js.map +1 -0
  42. package/dist/chains/solana/kamino/tx/actions.d.ts +22 -0
  43. package/dist/chains/solana/kamino/tx/actions.d.ts.map +1 -0
  44. package/dist/chains/solana/kamino/tx/actions.js +85 -0
  45. package/dist/chains/solana/kamino/tx/actions.js.map +1 -0
  46. package/dist/chains/solana/kamino/tx/computeBudget.d.ts +66 -0
  47. package/dist/chains/solana/kamino/tx/computeBudget.d.ts.map +1 -0
  48. package/dist/chains/solana/kamino/tx/computeBudget.js +73 -0
  49. package/dist/chains/solana/kamino/tx/computeBudget.js.map +1 -0
  50. package/dist/chains/solana/kamino/tx/decode.d.ts +121 -0
  51. package/dist/chains/solana/kamino/tx/decode.d.ts.map +1 -0
  52. package/dist/chains/solana/kamino/tx/decode.js +458 -0
  53. package/dist/chains/solana/kamino/tx/decode.js.map +1 -0
  54. package/dist/chains/solana/kamino/tx/instructions.d.ts +260 -0
  55. package/dist/chains/solana/kamino/tx/instructions.d.ts.map +1 -0
  56. package/dist/chains/solana/kamino/tx/instructions.js +256 -0
  57. package/dist/chains/solana/kamino/tx/instructions.js.map +1 -0
  58. package/dist/chains/solana/kamino/tx/sequence.d.ts +123 -0
  59. package/dist/chains/solana/kamino/tx/sequence.d.ts.map +1 -0
  60. package/dist/chains/solana/kamino/tx/sequence.js +235 -0
  61. package/dist/chains/solana/kamino/tx/sequence.js.map +1 -0
  62. package/dist/chains/solana/kamino/tx/validate.d.ts +138 -0
  63. package/dist/chains/solana/kamino/tx/validate.d.ts.map +1 -0
  64. package/dist/chains/solana/kamino/tx/validate.js +542 -0
  65. package/dist/chains/solana/kamino/tx/validate.js.map +1 -0
  66. package/dist/chains/solana/kamino/tx/wire.d.ts +107 -0
  67. package/dist/chains/solana/kamino/tx/wire.d.ts.map +1 -0
  68. package/dist/chains/solana/kamino/tx/wire.js +274 -0
  69. package/dist/chains/solana/kamino/tx/wire.js.map +1 -0
  70. package/dist/chains/solana/kamino/vaultInfo.d.ts +17 -0
  71. package/dist/chains/solana/kamino/vaultInfo.d.ts.map +1 -0
  72. package/dist/chains/solana/kamino/vaultInfo.js +150 -0
  73. package/dist/chains/solana/kamino/vaultInfo.js.map +1 -0
  74. package/package.json +91 -1
@@ -0,0 +1,260 @@
1
+ /**
2
+ * Every program a Kamino Earn transaction is allowed to invoke.
3
+ *
4
+ * This is an allow-list, not a catalogue: an instruction whose program is not
5
+ * one of these is a refusal. That matters because the transaction is built by
6
+ * Kamino and signed verbatim, so the program set is the outer boundary on what
7
+ * the user's single signature can authorise. Anything outside it is code we
8
+ * never agreed to run.
9
+ */
10
+ export declare const kaminoAllowedPrograms: {
11
+ readonly system: "11111111111111111111111111111111";
12
+ readonly token: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
13
+ readonly token2022: "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb";
14
+ readonly associatedToken: "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
15
+ readonly computeBudget: "ComputeBudget111111111111111111111111111111";
16
+ readonly kvault: "KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd";
17
+ readonly farms: "FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr";
18
+ /**
19
+ * SPL Memo v3, carrying this app's attribution tag. Never present in what
20
+ * Kamino builds — the app appends it, which is why a memo arriving from the
21
+ * API is a refusal rather than something to pass through.
22
+ */
23
+ readonly memo: "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr";
24
+ };
25
+ /** One of the allow-listed programs, named. */
26
+ export type KaminoAllowedProgram = keyof typeof kaminoAllowedPrograms;
27
+ /** Resolves a program id to its allow-list name, `undefined` when foreign. */
28
+ export declare const kaminoAllowedProgram: (programId: string) => KaminoAllowedProgram | undefined;
29
+ /**
30
+ * Programs whose instructions Kamino's builder composes itself, rather than
31
+ * reaching them through a CPI from its own programs.
32
+ *
33
+ * The distinction is the crux of the writable-account check. What `kvault` and
34
+ * `farms` do with the accounts they are handed is the protocol we chose to
35
+ * trust; what appears at the *top level* of the transaction is whatever the
36
+ * builder decided to put there, so every account those instructions can write
37
+ * to has to be one we can name.
38
+ */
39
+ export declare const isBuilderComposedProgram: (program: KaminoAllowedProgram) => boolean;
40
+ /**
41
+ * The attribution tag this app writes into every Kamino transaction it builds.
42
+ *
43
+ * Kamino's kvault API takes no referrer or partner parameter, so attribution
44
+ * is client-side: one SPL Memo instruction carrying this literal, appended
45
+ * after the API has built the transaction and before it is validated and
46
+ * signed.
47
+ *
48
+ * The bytes are the whole point. This tag is the filter every downstream
49
+ * measurement of Vultisig-originated deposits keys on, and it has to be
50
+ * byte-identical on every platform. So it is written once, and the injector,
51
+ * the validator and the verify-screen decoder all read it from here rather
52
+ * than each spelling it out. It is matched whole and compared as bytes, so it
53
+ * is case-sensitive: `8K2MZ` is a different memo.
54
+ */
55
+ export declare const kaminoAttributionMemoTag = "8k2mz";
56
+ /** The tag's exact bytes — what the injector writes and the checks compare. */
57
+ export declare const kaminoAttributionMemoTagBytes: Uint8Array;
58
+ /**
59
+ * Instruction discriminators for the programs a Kamino Earn transaction uses.
60
+ *
61
+ * The Anchor ones are `sha256("global:<name>")[0..8]`, and each was also read
62
+ * back out of a mainnet-simulated transaction built by the Kamino API, so the
63
+ * constant and the observation agree. That agreement is the point: a constant
64
+ * copied out of a captured transaction matches the shape it was copied from
65
+ * and asserts nothing; one derived from the instruction's name and *then*
66
+ * found in the bytes says the bytes are that instruction.
67
+ */
68
+ export declare const kaminoDiscriminators: {
69
+ /** `kvault::deposit(u64 tokenAmount)`. */
70
+ readonly kvaultDeposit: Uint8Array<ArrayBuffer>;
71
+ /**
72
+ * `kvault::withdraw(u64 shareAmount)` — the argument is in SHARES, the
73
+ * inverse of deposit's unit. One of TWO instructions a withdraw arrives as;
74
+ * this is the one the builder emits when the request does not fit the
75
+ * vault's liquid buffer, because only this one carries the accounts needed
76
+ * to pull the shortfall out of a lending reserve.
77
+ */
78
+ readonly kvaultWithdraw: Uint8Array<ArrayBuffer>;
79
+ /**
80
+ * `kvault::withdraw_from_available(u64 shareAmount)` — the same withdraw,
81
+ * served entirely out of the vault's liquid buffer. Which of the two arrives
82
+ * is a fact about the VAULT's liquidity at build time, not about the user's
83
+ * request, and both are in live use — so both are accepted, and both mean
84
+ * the same thing to the person signing.
85
+ */
86
+ readonly kvaultWithdrawFromAvailable: Uint8Array<ArrayBuffer>;
87
+ /** `farms::initialize_user` — creates the user's farm state. Absent when it already exists. */
88
+ readonly farmsInitializeUser: Uint8Array<ArrayBuffer>;
89
+ /** `farms::stake(u64 amount)`. Kamino always passes `u64::MAX`, meaning "stake the whole share balance". */
90
+ readonly farmsStake: Uint8Array<ArrayBuffer>;
91
+ /**
92
+ * `farms::unstake(u128 stakeSharesScaled)` — releases shares from the farm
93
+ * into the user's pending-withdrawal balance. Its argument is the only
94
+ * `u128` in this feature, and it is scaled: the farms program holds stake at
95
+ * `WAD`, so the value is share base units multiplied by `10^18`. Reading
96
+ * those 16 bytes as a `u64` truncates silently.
97
+ */
98
+ readonly farmsUnstake: Uint8Array<ArrayBuffer>;
99
+ /**
100
+ * `farms::withdraw_unstaked_deposits` — moves what `unstake` released into
101
+ * the user's share account, where the vault withdraw can then burn it.
102
+ * Takes no argument: it always moves the whole pending balance.
103
+ */
104
+ readonly farmsWithdrawUnstakedDeposits: Uint8Array<ArrayBuffer>;
105
+ };
106
+ /**
107
+ * The fixed-point scale the farms program holds stake at: `10^18`. Everything
108
+ * else in this feature is an integer count of base units; this one is not, so
109
+ * the conversion is written out rather than inferred at each call site.
110
+ */
111
+ export declare const kaminoFarmsStakeScale: bigint;
112
+ /** Associated Token Program `CreateIdempotent`. */
113
+ export declare const createIdempotentAtaDiscriminator = 1;
114
+ /** SPL Token `SyncNative` — reconciles a wSOL account's balance with its lamports. */
115
+ export declare const tokenSyncNativeDiscriminator = 17;
116
+ /** SPL Token `CloseAccount` — unwraps wSOL back to native SOL, or reclaims rent. */
117
+ export declare const tokenCloseAccountDiscriminator = 9;
118
+ /** System Program `Transfer`: a 4-byte little-endian enum index. */
119
+ export declare const systemTransferDiscriminator: Uint8Array<ArrayBuffer>;
120
+ /** ComputeBudget `SetComputeUnitLimit` / `SetComputeUnitPrice` one-byte tags. */
121
+ export declare const computeBudgetDiscriminators: {
122
+ readonly setUnitLimit: 2;
123
+ readonly setUnitPrice: 3;
124
+ };
125
+ /** Whether `data` starts with the 8-byte Anchor discriminator `prefix`. */
126
+ export declare const hasAnchorDiscriminator: (data: Uint8Array, prefix: Uint8Array) => boolean;
127
+ /** Whether `data` is exactly the attribution tag — matched whole, as bytes. */
128
+ export declare const isAttributionMemoData: (data: Uint8Array) => boolean;
129
+ /**
130
+ * An Anchor instruction's `u64` argument: the 8 bytes after the
131
+ * discriminator, little-endian. `undefined` unless the payload is exactly
132
+ * discriminator + argument.
133
+ */
134
+ export declare const anchorU64Argument: (data: Uint8Array) => bigint | undefined;
135
+ /**
136
+ * An Anchor instruction's `u128` argument: the 16 bytes after the
137
+ * discriminator, little-endian, exact.
138
+ *
139
+ * Separate from `anchorU64Argument` and never a fallback for it. A `u128`
140
+ * argument read through the `u64` reader would take the low 8 bytes of a
141
+ * 16-byte field and report a plausible-looking number that is not the one on
142
+ * the wire — so the two readers are keyed on the exact payload length and
143
+ * neither accepts the other's.
144
+ */
145
+ export declare const anchorU128Argument: (data: Uint8Array) => bigint | undefined;
146
+ /**
147
+ * An Anchor instruction that carries no argument at all: exactly the
148
+ * discriminator and nothing after it. Checked rather than assumed — the
149
+ * sequence matches on the first eight bytes, so trailing bytes would
150
+ * otherwise ride along unread.
151
+ */
152
+ export declare const hasNoAnchorArgument: (data: Uint8Array) => boolean;
153
+ /** `Transfer` payload: the 4-byte discriminant plus a `u64` lamport amount. */
154
+ export declare const systemTransferLamports: (data: Uint8Array) => bigint | undefined;
155
+ /** `SetComputeUnitLimit`'s `u32` argument. */
156
+ export declare const computeUnitLimitArgument: (data: Uint8Array) => number | undefined;
157
+ /**
158
+ * `SetComputeUnitPrice`'s `u64` argument, in micro-lamports per compute unit.
159
+ * The fee it produces is `price × limit`, so this is a spend.
160
+ */
161
+ export declare const computeUnitPriceArgument: (data: Uint8Array) => bigint | undefined;
162
+ /**
163
+ * The farms program's per-user account, derived rather than trusted.
164
+ *
165
+ * `farms::unstake` and `farms::withdraw_unstaked_deposits` both take it, and
166
+ * it is the account that decides WHICH stake they move. Its address is a
167
+ * program address over the farm and the owner, so recomputing it locally
168
+ * binds both instructions to one farm and one user at once — and it does so
169
+ * offline, which the farm slot itself cannot: the farm is an
170
+ * address-lookup-table entry in every captured transaction, and the verify
171
+ * screen has no way to resolve one.
172
+ */
173
+ export declare const deriveKaminoFarmsUserState: ({ farm, owner }: {
174
+ farm: string;
175
+ owner: string;
176
+ }) => string | undefined;
177
+ /**
178
+ * Positions of the accounts each instruction is checked and decoded on.
179
+ *
180
+ * An Anchor instruction's account list is fixed by its IDL — only the
181
+ * trailing `remaining_accounts` vary, which is why the observed lists differ
182
+ * in length between vaults while these prefixes do not. Each index was read
183
+ * out of transactions the Kamino API built for all three launch vaults.
184
+ *
185
+ * Shared rather than duplicated: the validator checks against these before
186
+ * signing and the decoder reads the same slots back out of the signed bytes.
187
+ * Two copies that drifted would let the verify screen describe a different
188
+ * instruction from the one that was validated.
189
+ *
190
+ * The two withdraw instructions share one map rather than merely agreeing:
191
+ * the program's IDL declares `withdraw`'s account list as
192
+ * `withdraw_from_available`'s fourteen accounts followed by the reserve-exit
193
+ * group, so the first fourteen slots of the longer instruction ARE the
194
+ * shorter one's, and every pinned index lies inside that shared prefix.
195
+ */
196
+ export declare const kaminoInstructionAccounts: {
197
+ readonly kvaultDeposit: {
198
+ readonly user: 0;
199
+ readonly vault: 1;
200
+ readonly tokenMint: 3;
201
+ readonly sharesMint: 5;
202
+ readonly userTokenAccount: 6;
203
+ readonly userShareAccount: 7;
204
+ readonly minimumCount: 8;
205
+ };
206
+ readonly kvaultWithdraw: {
207
+ readonly user: 0;
208
+ readonly vault: 1;
209
+ readonly userTokenAccount: 5;
210
+ readonly tokenMint: 6;
211
+ readonly userShareAccount: 7;
212
+ readonly sharesMint: 8;
213
+ readonly minimumCount: 9;
214
+ };
215
+ readonly farmsInitializeUser: {
216
+ readonly authority: 0;
217
+ readonly farm: 5;
218
+ readonly minimumCount: 6;
219
+ };
220
+ readonly farmsStake: {
221
+ readonly owner: 0;
222
+ readonly farm: 2;
223
+ readonly userShareAccount: 4;
224
+ readonly sharesMint: 5;
225
+ readonly minimumCount: 6;
226
+ };
227
+ readonly farmsUnstake: {
228
+ readonly owner: 0;
229
+ readonly userState: 1;
230
+ readonly farm: 2;
231
+ readonly minimumCount: 3;
232
+ };
233
+ readonly farmsWithdrawUnstakedDeposits: {
234
+ readonly owner: 0;
235
+ readonly userState: 1;
236
+ readonly farm: 2;
237
+ readonly userShareAccount: 3;
238
+ readonly minimumCount: 4;
239
+ };
240
+ readonly associatedToken: {
241
+ readonly payer: 0;
242
+ readonly account: 1;
243
+ readonly wallet: 2;
244
+ readonly mint: 3;
245
+ readonly tokenProgram: 5;
246
+ readonly count: 6;
247
+ };
248
+ readonly systemTransfer: {
249
+ readonly source: 0;
250
+ readonly destination: 1;
251
+ readonly count: 2;
252
+ };
253
+ readonly closeAccount: {
254
+ readonly account: 0;
255
+ readonly destination: 1;
256
+ readonly authority: 2;
257
+ readonly count: 3;
258
+ };
259
+ };
260
+ //# sourceMappingURL=instructions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/chains/solana/kamino/tx/instructions.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;IAQhC;;;;OAIG;;CAEK,CAAA;AAEV,+CAA+C;AAC/C,MAAM,MAAM,oBAAoB,GAAG,MAAM,OAAO,qBAAqB,CAAA;AAMrE,8EAA8E;AAC9E,eAAO,MAAM,oBAAoB,GAAI,WAAW,MAAM,KAAG,oBAAoB,GAAG,SAC/C,CAAA;AAEjC;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB,GAAI,SAAS,oBAAoB,KAAG,OACgC,CAAA;AAEzG;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,wBAAwB,UAAU,CAAA;AAE/C,+EAA+E;AAC/E,eAAO,MAAM,6BAA6B,EAAE,UAA+D,CAAA;AAE3G;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB;IAC/B,0CAA0C;;IAE1C;;;;;;OAMG;;IAEH;;;;;;OAMG;;IAEH,+FAA+F;;IAE/F,4GAA4G;;IAE5G;;;;;;OAMG;;IAEH;;;;OAIG;;CAEK,CAAA;AAEV;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,QAAa,CAAA;AAE/C,mDAAmD;AACnD,eAAO,MAAM,gCAAgC,IAAI,CAAA;AAEjD,sFAAsF;AACtF,eAAO,MAAM,4BAA4B,KAAK,CAAA;AAE9C,oFAAoF;AACpF,eAAO,MAAM,8BAA8B,IAAI,CAAA;AAE/C,oEAAoE;AACpE,eAAO,MAAM,2BAA2B,yBAAgC,CAAA;AAExE,iFAAiF;AACjF,eAAO,MAAM,2BAA2B;;;CAAgD,CAAA;AAKxF,2EAA2E;AAC3E,eAAO,MAAM,sBAAsB,GAAI,MAAM,UAAU,EAAE,QAAQ,UAAU,KAAG,OACpB,CAAA;AAE1D,+EAA+E;AAC/E,eAAO,MAAM,qBAAqB,GAAI,MAAM,UAAU,KAAG,OAA0D,CAAA;AAUnH;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,UAAU,KAAG,MAAM,GAAG,SAG7D,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,GAAI,MAAM,UAAU,KAAG,MAAM,GAAG,SAG9D,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,UAAU,KAAG,OAA4B,CAAA;AAEnF,+EAA+E;AAC/E,eAAO,MAAM,sBAAsB,GAAI,MAAM,UAAU,KAAG,MAAM,GAAG,SAIlE,CAAA;AAED,8CAA8C;AAC9C,eAAO,MAAM,wBAAwB,GAAI,MAAM,UAAU,KAAG,MAAM,GAAG,SAGpE,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GAAI,MAAM,UAAU,KAAG,MAAM,GAAG,SAGpE,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,0BAA0B,GAAI,iBAAiB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,KAAG,MAAM,GAAG,SAUtG,CAAA;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0B5B,CAAA"}
@@ -0,0 +1,256 @@
1
+ import { PublicKey } from '@solana/web3.js';
2
+ import { kaminoConfig } from '../config.js';
3
+ /**
4
+ * Every program a Kamino Earn transaction is allowed to invoke.
5
+ *
6
+ * This is an allow-list, not a catalogue: an instruction whose program is not
7
+ * one of these is a refusal. That matters because the transaction is built by
8
+ * Kamino and signed verbatim, so the program set is the outer boundary on what
9
+ * the user's single signature can authorise. Anything outside it is code we
10
+ * never agreed to run.
11
+ */
12
+ export const kaminoAllowedPrograms = {
13
+ system: '11111111111111111111111111111111',
14
+ token: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
15
+ token2022: 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb',
16
+ associatedToken: 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL',
17
+ computeBudget: 'ComputeBudget111111111111111111111111111111',
18
+ kvault: kaminoConfig.programId,
19
+ farms: kaminoConfig.farmsProgramId,
20
+ /**
21
+ * SPL Memo v3, carrying this app's attribution tag. Never present in what
22
+ * Kamino builds — the app appends it, which is why a memo arriving from the
23
+ * API is a refusal rather than something to pass through.
24
+ */
25
+ memo: 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr',
26
+ };
27
+ const programByAddress = new Map(Object.entries(kaminoAllowedPrograms).map(([name, address]) => [address, name]));
28
+ /** Resolves a program id to its allow-list name, `undefined` when foreign. */
29
+ export const kaminoAllowedProgram = (programId) => programByAddress.get(programId);
30
+ /**
31
+ * Programs whose instructions Kamino's builder composes itself, rather than
32
+ * reaching them through a CPI from its own programs.
33
+ *
34
+ * The distinction is the crux of the writable-account check. What `kvault` and
35
+ * `farms` do with the accounts they are handed is the protocol we chose to
36
+ * trust; what appears at the *top level* of the transaction is whatever the
37
+ * builder decided to put there, so every account those instructions can write
38
+ * to has to be one we can name.
39
+ */
40
+ export const isBuilderComposedProgram = (program) => program === 'system' || program === 'token' || program === 'token2022' || program === 'associatedToken';
41
+ /**
42
+ * The attribution tag this app writes into every Kamino transaction it builds.
43
+ *
44
+ * Kamino's kvault API takes no referrer or partner parameter, so attribution
45
+ * is client-side: one SPL Memo instruction carrying this literal, appended
46
+ * after the API has built the transaction and before it is validated and
47
+ * signed.
48
+ *
49
+ * The bytes are the whole point. This tag is the filter every downstream
50
+ * measurement of Vultisig-originated deposits keys on, and it has to be
51
+ * byte-identical on every platform. So it is written once, and the injector,
52
+ * the validator and the verify-screen decoder all read it from here rather
53
+ * than each spelling it out. It is matched whole and compared as bytes, so it
54
+ * is case-sensitive: `8K2MZ` is a different memo.
55
+ */
56
+ export const kaminoAttributionMemoTag = '8k2mz';
57
+ /** The tag's exact bytes — what the injector writes and the checks compare. */
58
+ export const kaminoAttributionMemoTagBytes = new TextEncoder().encode(kaminoAttributionMemoTag);
59
+ /**
60
+ * Instruction discriminators for the programs a Kamino Earn transaction uses.
61
+ *
62
+ * The Anchor ones are `sha256("global:<name>")[0..8]`, and each was also read
63
+ * back out of a mainnet-simulated transaction built by the Kamino API, so the
64
+ * constant and the observation agree. That agreement is the point: a constant
65
+ * copied out of a captured transaction matches the shape it was copied from
66
+ * and asserts nothing; one derived from the instruction's name and *then*
67
+ * found in the bytes says the bytes are that instruction.
68
+ */
69
+ export const kaminoDiscriminators = {
70
+ /** `kvault::deposit(u64 tokenAmount)`. */
71
+ kvaultDeposit: Uint8Array.from([0xf2, 0x23, 0xc6, 0x89, 0x52, 0xe1, 0xf2, 0xb6]),
72
+ /**
73
+ * `kvault::withdraw(u64 shareAmount)` — the argument is in SHARES, the
74
+ * inverse of deposit's unit. One of TWO instructions a withdraw arrives as;
75
+ * this is the one the builder emits when the request does not fit the
76
+ * vault's liquid buffer, because only this one carries the accounts needed
77
+ * to pull the shortfall out of a lending reserve.
78
+ */
79
+ kvaultWithdraw: Uint8Array.from([0xb7, 0x12, 0x46, 0x9c, 0x94, 0x6d, 0xa1, 0x22]),
80
+ /**
81
+ * `kvault::withdraw_from_available(u64 shareAmount)` — the same withdraw,
82
+ * served entirely out of the vault's liquid buffer. Which of the two arrives
83
+ * is a fact about the VAULT's liquidity at build time, not about the user's
84
+ * request, and both are in live use — so both are accepted, and both mean
85
+ * the same thing to the person signing.
86
+ */
87
+ kvaultWithdrawFromAvailable: Uint8Array.from([0x13, 0x83, 0x70, 0x9b, 0xaa, 0xdc, 0x22, 0x39]),
88
+ /** `farms::initialize_user` — creates the user's farm state. Absent when it already exists. */
89
+ farmsInitializeUser: Uint8Array.from([0x6f, 0x11, 0xb9, 0xfa, 0x3c, 0x7a, 0x26, 0xfe]),
90
+ /** `farms::stake(u64 amount)`. Kamino always passes `u64::MAX`, meaning "stake the whole share balance". */
91
+ farmsStake: Uint8Array.from([0xce, 0xb0, 0xca, 0x12, 0xc8, 0xd1, 0xb3, 0x6c]),
92
+ /**
93
+ * `farms::unstake(u128 stakeSharesScaled)` — releases shares from the farm
94
+ * into the user's pending-withdrawal balance. Its argument is the only
95
+ * `u128` in this feature, and it is scaled: the farms program holds stake at
96
+ * `WAD`, so the value is share base units multiplied by `10^18`. Reading
97
+ * those 16 bytes as a `u64` truncates silently.
98
+ */
99
+ farmsUnstake: Uint8Array.from([0x5a, 0x5f, 0x6b, 0x2a, 0xcd, 0x7c, 0x32, 0xe1]),
100
+ /**
101
+ * `farms::withdraw_unstaked_deposits` — moves what `unstake` released into
102
+ * the user's share account, where the vault withdraw can then burn it.
103
+ * Takes no argument: it always moves the whole pending balance.
104
+ */
105
+ farmsWithdrawUnstakedDeposits: Uint8Array.from([0x24, 0x66, 0xbb, 0x31, 0xdc, 0x24, 0x84, 0x43]),
106
+ };
107
+ /**
108
+ * The fixed-point scale the farms program holds stake at: `10^18`. Everything
109
+ * else in this feature is an integer count of base units; this one is not, so
110
+ * the conversion is written out rather than inferred at each call site.
111
+ */
112
+ export const kaminoFarmsStakeScale = 10n ** 18n;
113
+ /** Associated Token Program `CreateIdempotent`. */
114
+ export const createIdempotentAtaDiscriminator = 1;
115
+ /** SPL Token `SyncNative` — reconciles a wSOL account's balance with its lamports. */
116
+ export const tokenSyncNativeDiscriminator = 17;
117
+ /** SPL Token `CloseAccount` — unwraps wSOL back to native SOL, or reclaims rent. */
118
+ export const tokenCloseAccountDiscriminator = 9;
119
+ /** System Program `Transfer`: a 4-byte little-endian enum index. */
120
+ export const systemTransferDiscriminator = Uint8Array.from([2, 0, 0, 0]);
121
+ /** ComputeBudget `SetComputeUnitLimit` / `SetComputeUnitPrice` one-byte tags. */
122
+ export const computeBudgetDiscriminators = { setUnitLimit: 2, setUnitPrice: 3 };
123
+ const bytesEqual = (a, b) => a.length === b.length && a.every((byte, index) => byte === b[index]);
124
+ /** Whether `data` starts with the 8-byte Anchor discriminator `prefix`. */
125
+ export const hasAnchorDiscriminator = (data, prefix) => data.length >= 8 && bytesEqual(data.slice(0, 8), prefix);
126
+ /** Whether `data` is exactly the attribution tag — matched whole, as bytes. */
127
+ export const isAttributionMemoData = (data) => bytesEqual(data, kaminoAttributionMemoTagBytes);
128
+ const littleEndianBigInt = (bytes) => {
129
+ let value = 0n;
130
+ for (let index = bytes.length - 1; index >= 0; index--) {
131
+ value = (value << 8n) | BigInt(bytes[index]);
132
+ }
133
+ return value;
134
+ };
135
+ /**
136
+ * An Anchor instruction's `u64` argument: the 8 bytes after the
137
+ * discriminator, little-endian. `undefined` unless the payload is exactly
138
+ * discriminator + argument.
139
+ */
140
+ export const anchorU64Argument = (data) => {
141
+ if (data.length !== 16)
142
+ return undefined;
143
+ return littleEndianBigInt(data.slice(8, 16));
144
+ };
145
+ /**
146
+ * An Anchor instruction's `u128` argument: the 16 bytes after the
147
+ * discriminator, little-endian, exact.
148
+ *
149
+ * Separate from `anchorU64Argument` and never a fallback for it. A `u128`
150
+ * argument read through the `u64` reader would take the low 8 bytes of a
151
+ * 16-byte field and report a plausible-looking number that is not the one on
152
+ * the wire — so the two readers are keyed on the exact payload length and
153
+ * neither accepts the other's.
154
+ */
155
+ export const anchorU128Argument = (data) => {
156
+ if (data.length !== 24)
157
+ return undefined;
158
+ return littleEndianBigInt(data.slice(8, 24));
159
+ };
160
+ /**
161
+ * An Anchor instruction that carries no argument at all: exactly the
162
+ * discriminator and nothing after it. Checked rather than assumed — the
163
+ * sequence matches on the first eight bytes, so trailing bytes would
164
+ * otherwise ride along unread.
165
+ */
166
+ export const hasNoAnchorArgument = (data) => data.length === 8;
167
+ /** `Transfer` payload: the 4-byte discriminant plus a `u64` lamport amount. */
168
+ export const systemTransferLamports = (data) => {
169
+ if (data.length !== 12)
170
+ return undefined;
171
+ if (!bytesEqual(data.slice(0, 4), systemTransferDiscriminator))
172
+ return undefined;
173
+ return littleEndianBigInt(data.slice(4, 12));
174
+ };
175
+ /** `SetComputeUnitLimit`'s `u32` argument. */
176
+ export const computeUnitLimitArgument = (data) => {
177
+ if (data.length !== 5 || data[0] !== computeBudgetDiscriminators.setUnitLimit)
178
+ return undefined;
179
+ return Number(littleEndianBigInt(data.slice(1, 5)));
180
+ };
181
+ /**
182
+ * `SetComputeUnitPrice`'s `u64` argument, in micro-lamports per compute unit.
183
+ * The fee it produces is `price × limit`, so this is a spend.
184
+ */
185
+ export const computeUnitPriceArgument = (data) => {
186
+ if (data.length !== 9 || data[0] !== computeBudgetDiscriminators.setUnitPrice)
187
+ return undefined;
188
+ return littleEndianBigInt(data.slice(1, 9));
189
+ };
190
+ /**
191
+ * The farms program's per-user account, derived rather than trusted.
192
+ *
193
+ * `farms::unstake` and `farms::withdraw_unstaked_deposits` both take it, and
194
+ * it is the account that decides WHICH stake they move. Its address is a
195
+ * program address over the farm and the owner, so recomputing it locally
196
+ * binds both instructions to one farm and one user at once — and it does so
197
+ * offline, which the farm slot itself cannot: the farm is an
198
+ * address-lookup-table entry in every captured transaction, and the verify
199
+ * screen has no way to resolve one.
200
+ */
201
+ export const deriveKaminoFarmsUserState = ({ farm, owner }) => {
202
+ try {
203
+ const [address] = PublicKey.findProgramAddressSync([new TextEncoder().encode('user'), new PublicKey(farm).toBytes(), new PublicKey(owner).toBytes()], new PublicKey(kaminoAllowedPrograms.farms));
204
+ return address.toBase58();
205
+ }
206
+ catch {
207
+ return undefined;
208
+ }
209
+ };
210
+ /**
211
+ * Positions of the accounts each instruction is checked and decoded on.
212
+ *
213
+ * An Anchor instruction's account list is fixed by its IDL — only the
214
+ * trailing `remaining_accounts` vary, which is why the observed lists differ
215
+ * in length between vaults while these prefixes do not. Each index was read
216
+ * out of transactions the Kamino API built for all three launch vaults.
217
+ *
218
+ * Shared rather than duplicated: the validator checks against these before
219
+ * signing and the decoder reads the same slots back out of the signed bytes.
220
+ * Two copies that drifted would let the verify screen describe a different
221
+ * instruction from the one that was validated.
222
+ *
223
+ * The two withdraw instructions share one map rather than merely agreeing:
224
+ * the program's IDL declares `withdraw`'s account list as
225
+ * `withdraw_from_available`'s fourteen accounts followed by the reserve-exit
226
+ * group, so the first fourteen slots of the longer instruction ARE the
227
+ * shorter one's, and every pinned index lies inside that shared prefix.
228
+ */
229
+ export const kaminoInstructionAccounts = {
230
+ kvaultDeposit: {
231
+ user: 0,
232
+ vault: 1,
233
+ tokenMint: 3,
234
+ sharesMint: 5,
235
+ userTokenAccount: 6,
236
+ userShareAccount: 7,
237
+ minimumCount: 8,
238
+ },
239
+ kvaultWithdraw: {
240
+ user: 0,
241
+ vault: 1,
242
+ userTokenAccount: 5,
243
+ tokenMint: 6,
244
+ userShareAccount: 7,
245
+ sharesMint: 8,
246
+ minimumCount: 9,
247
+ },
248
+ farmsInitializeUser: { authority: 0, farm: 5, minimumCount: 6 },
249
+ farmsStake: { owner: 0, farm: 2, userShareAccount: 4, sharesMint: 5, minimumCount: 6 },
250
+ farmsUnstake: { owner: 0, userState: 1, farm: 2, minimumCount: 3 },
251
+ farmsWithdrawUnstakedDeposits: { owner: 0, userState: 1, farm: 2, userShareAccount: 3, minimumCount: 4 },
252
+ associatedToken: { payer: 0, account: 1, wallet: 2, mint: 3, tokenProgram: 5, count: 6 },
253
+ systemTransfer: { source: 0, destination: 1, count: 2 },
254
+ closeAccount: { account: 0, destination: 1, authority: 2, count: 3 },
255
+ };
256
+ //# sourceMappingURL=instructions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instructions.js","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/chains/solana/kamino/tx/instructions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ import { KaminoAllowedProgram } from './instructions.js';
2
+ /**
3
+ * The instruction shapes each Kamino operation produces, and the walk that
4
+ * matches a transaction against them.
5
+ *
6
+ * Shared by the two places that need it, because they must agree on what a
7
+ * Kamino transaction is *allowed to contain*: the validator runs it on the
8
+ * initiating device before signing, followed by account-identity checks that
9
+ * need the lookup tables resolved; the decoder runs it on ANY device, offline,
10
+ * before claiming to describe a transaction. Without it the decode would read
11
+ * one recognised instruction and say nothing about the rest — so a transfer
12
+ * riding alongside a plausible deposit would be summarised as "Deposit
13
+ * 1 USDC", which is worse than showing nothing at all.
14
+ *
15
+ * A step matches on the program and the instruction discriminator only. Both
16
+ * are readable without a lookup table (a v0 message's program ids are always
17
+ * static keys), which is what lets the offline decode use the same template
18
+ * as the online validator. Everything else about an instruction is checked
19
+ * after it has been matched, so a wrong ACCOUNT is a refusal rather than a
20
+ * silent failure to match.
21
+ */
22
+ export declare const kaminoInstructionKinds: readonly ["computeUnitLimit", "computeUnitPrice", "createTokenAccount", "wrapSolTransfer", "syncNative", "closeTokenAccount", "kvaultDeposit", "kvaultWithdraw", "farmsInitializeUser", "farmsStake", "farmsUnstake", "farmsWithdrawUnstakedDeposits", "attributionMemo"];
23
+ /** One recognised instruction shape. */
24
+ export type KaminoInstructionKind = (typeof kaminoInstructionKinds)[number];
25
+ /** Human-readable step names, used in refusal messages. */
26
+ export declare const kaminoInstructionKindName: Record<KaminoInstructionKind, string>;
27
+ /**
28
+ * One template step. `pairedWith` names a step this one may only appear
29
+ * alongside: either both are matched or neither is. Optionality is per-step,
30
+ * and for two instructions that are halves of ONE operation that is not
31
+ * enough — `farms::unstake` releases shares into a pending-withdrawal balance
32
+ * and `farms::withdraw_unstaked_deposits` is what moves them out of it, so an
33
+ * unstake on its own strands shares somewhere neither the position read nor
34
+ * the verify screen describes.
35
+ */
36
+ export type KaminoSequenceStep = {
37
+ kind: KaminoInstructionKind;
38
+ isRequired: boolean;
39
+ isRepeatable: boolean;
40
+ pairedWith?: KaminoInstructionKind;
41
+ };
42
+ /**
43
+ * Whether a withdraw is supposed to release shares from the vault's farm.
44
+ *
45
+ * The API decides this from the user's position: a request that fits inside
46
+ * the shares already sitting in their share account is built as a plain
47
+ * withdraw, and anything above it is built with the farms pair in front. The
48
+ * three cases are three different claims:
49
+ *
50
+ * - `required` — the initiating device, which read the position and sized the
51
+ * request against it. A transaction missing the unstake is refused.
52
+ * - `forbidden` — the same device, for a request that fits the unstaked
53
+ * balance. A transaction CARRYING an unstake is refused.
54
+ * - `unknown` — the offline decode on a co-signing device, which holds no
55
+ * position to compare against. Either shape is accepted, and what bounds it
56
+ * there is the argument check: the unstake amount may not exceed the shares
57
+ * the withdraw itself burns.
58
+ */
59
+ export type KaminoFarmUnstakeExpectation = 'required' | 'forbidden' | 'unknown';
60
+ /** Why a transaction does not fit the template. */
61
+ export type KaminoSequenceMismatch = {
62
+ unexpectedInstruction: {
63
+ index: number;
64
+ };
65
+ } | {
66
+ missingInstruction: string;
67
+ } | {
68
+ incompleteInstructionPair: string;
69
+ };
70
+ type ExpectedSequenceInput = {
71
+ operation: 'deposit' | 'withdraw';
72
+ isWrappedSolVault: boolean;
73
+ hasFarm: boolean;
74
+ /**
75
+ * Whether the app's ComputeBudget pair has been injected. The API emits
76
+ * none, so before injection their presence is a refusal and after it their
77
+ * absence is.
78
+ */
79
+ hasPriorityFee: boolean;
80
+ /**
81
+ * Whether the app's attribution memo has been appended. Same contract as
82
+ * the fee, for the same reason: the API emits no memo, so one arriving
83
+ * before injection came from somewhere else, and one missing after
84
+ * injection means the tag this app claims to write is not in the bytes it
85
+ * is about to sign.
86
+ */
87
+ hasAttributionMemo: boolean;
88
+ /** Ignored for a deposit. */
89
+ farmUnstake: KaminoFarmUnstakeExpectation;
90
+ };
91
+ /**
92
+ * The shape `operation` produces against a vault with these properties,
93
+ * verified by decoding transactions the Kamino API built and simulating them
94
+ * on mainnet.
95
+ *
96
+ * Optional steps are the ones whose absence cannot cost the user anything —
97
+ * an idempotent account creation that was already done, a farm user that
98
+ * already exists, a token account that stays open. Everything that decides
99
+ * where money moves is required, and anything not listed at all is refused.
100
+ */
101
+ export declare const expectedKaminoSequence: ({ operation, isWrappedSolVault, hasFarm, hasPriorityFee, hasAttributionMemo, farmUnstake, }: ExpectedSequenceInput) => KaminoSequenceStep[];
102
+ /**
103
+ * The kind of instruction this program and payload are, or `undefined` when
104
+ * it is none the template knows. Program and discriminator only — see the
105
+ * module doc for why.
106
+ */
107
+ export declare const kaminoInstructionKind: (program: KaminoAllowedProgram | undefined, data: Uint8Array) => KaminoInstructionKind | undefined;
108
+ /**
109
+ * Walks `steps` and `kinds` together. A step that does not match is skipped
110
+ * only when it is optional; an instruction left over at the end has no place
111
+ * in this operation at all.
112
+ *
113
+ * `kinds` holds one entry per instruction, in order, `undefined` for an
114
+ * instruction whose program is not allow-listed or whose discriminator is not
115
+ * one the template names.
116
+ */
117
+ export declare const matchKaminoSequence: (kinds: (KaminoInstructionKind | undefined)[], steps: KaminoSequenceStep[]) => {
118
+ matched: KaminoInstructionKind[];
119
+ } | {
120
+ mismatch: KaminoSequenceMismatch;
121
+ };
122
+ export {};
123
+ //# sourceMappingURL=sequence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequence.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/chains/solana/kamino/tx/sequence.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,oBAAoB,EAKrB,MAAM,gBAAgB,CAAA;AAEvB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,sBAAsB,2QAczB,CAAA;AAEV,wCAAwC;AACxC,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE3E,2DAA2D;AAC3D,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAc3E,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,qBAAqB,CAAA;IAC3B,UAAU,EAAE,OAAO,CAAA;IACnB,YAAY,EAAE,OAAO,CAAA;IACrB,UAAU,CAAC,EAAE,qBAAqB,CAAA;CACnC,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,4BAA4B,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,CAAA;AAE/E,mDAAmD;AACnD,MAAM,MAAM,sBAAsB,GAC9B;IAAE,qBAAqB,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAC5C;IAAE,kBAAkB,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,yBAAyB,EAAE,MAAM,CAAA;CAAE,CAAA;AAEzC,KAAK,qBAAqB,GAAG;IAC3B,SAAS,EAAE,SAAS,GAAG,UAAU,CAAA;IACjC,iBAAiB,EAAE,OAAO,CAAA;IAC1B,OAAO,EAAE,OAAO,CAAA;IAChB;;;;OAIG;IACH,cAAc,EAAE,OAAO,CAAA;IACvB;;;;;;OAMG;IACH,kBAAkB,EAAE,OAAO,CAAA;IAC3B,6BAA6B;IAC7B,WAAW,EAAE,4BAA4B,CAAA;CAC1C,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,GAAI,6FAOpC,qBAAqB,KAAG,kBAAkB,EA8D5C,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAChC,SAAS,oBAAoB,GAAG,SAAS,EACzC,MAAM,UAAU,KACf,qBAAqB,GAAG,SAkD1B,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,GAC9B,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,EAAE,EAC5C,OAAO,kBAAkB,EAAE,KAC1B;IAAE,OAAO,EAAE,qBAAqB,EAAE,CAAA;CAAE,GAAG;IAAE,QAAQ,EAAE,sBAAsB,CAAA;CAgD3E,CAAA"}