@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.
- package/CHANGELOG.md +29 -0
- package/dist/chains/cosmos/cosmosGasLimitRecord.d.ts.map +1 -1
- package/dist/chains/cosmos/cosmosGasLimitRecord.js +13 -14
- package/dist/chains/cosmos/cosmosGasLimitRecord.js.map +1 -1
- package/dist/chains/cosmos/gas.d.ts +16 -0
- package/dist/chains/cosmos/gas.d.ts.map +1 -1
- package/dist/chains/cosmos/gas.js +17 -1
- package/dist/chains/cosmos/gas.js.map +1 -1
- package/dist/chains/solana/kamino/KaminoServiceError.d.ts +63 -0
- package/dist/chains/solana/kamino/KaminoServiceError.d.ts.map +1 -0
- package/dist/chains/solana/kamino/KaminoServiceError.js +29 -0
- package/dist/chains/solana/kamino/KaminoServiceError.js.map +1 -0
- package/dist/chains/solana/kamino/amount.d.ts +141 -0
- package/dist/chains/solana/kamino/amount.d.ts.map +1 -0
- package/dist/chains/solana/kamino/amount.js +156 -0
- package/dist/chains/solana/kamino/amount.js.map +1 -0
- package/dist/chains/solana/kamino/api.d.ts +20 -0
- package/dist/chains/solana/kamino/api.d.ts.map +1 -0
- package/dist/chains/solana/kamino/api.js +59 -0
- package/dist/chains/solana/kamino/api.js.map +1 -0
- package/dist/chains/solana/kamino/baseUnits.d.ts +23 -0
- package/dist/chains/solana/kamino/baseUnits.d.ts.map +1 -0
- package/dist/chains/solana/kamino/baseUnits.js +30 -0
- package/dist/chains/solana/kamino/baseUnits.js.map +1 -0
- package/dist/chains/solana/kamino/config.d.ts +27 -0
- package/dist/chains/solana/kamino/config.d.ts.map +1 -0
- package/dist/chains/solana/kamino/config.js +27 -0
- package/dist/chains/solana/kamino/config.js.map +1 -0
- package/dist/chains/solana/kamino/decimal.d.ts +24 -0
- package/dist/chains/solana/kamino/decimal.d.ts.map +1 -0
- package/dist/chains/solana/kamino/decimal.js +52 -0
- package/dist/chains/solana/kamino/decimal.js.map +1 -0
- package/dist/chains/solana/kamino/models.d.ts +148 -0
- package/dist/chains/solana/kamino/models.d.ts.map +1 -0
- package/dist/chains/solana/kamino/models.js +2 -0
- package/dist/chains/solana/kamino/models.js.map +1 -0
- package/dist/chains/solana/kamino/position.d.ts +79 -0
- package/dist/chains/solana/kamino/position.d.ts.map +1 -0
- package/dist/chains/solana/kamino/position.js +52 -0
- package/dist/chains/solana/kamino/position.js.map +1 -0
- package/dist/chains/solana/kamino/rate.d.ts +57 -0
- package/dist/chains/solana/kamino/rate.d.ts.map +1 -0
- package/dist/chains/solana/kamino/rate.js +88 -0
- package/dist/chains/solana/kamino/rate.js.map +1 -0
- package/dist/chains/solana/kamino/registry.d.ts +70 -0
- package/dist/chains/solana/kamino/registry.d.ts.map +1 -0
- package/dist/chains/solana/kamino/registry.js +67 -0
- package/dist/chains/solana/kamino/registry.js.map +1 -0
- package/dist/chains/solana/kamino/tx/actions.d.ts +22 -0
- package/dist/chains/solana/kamino/tx/actions.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/actions.js +85 -0
- package/dist/chains/solana/kamino/tx/actions.js.map +1 -0
- package/dist/chains/solana/kamino/tx/computeBudget.d.ts +66 -0
- package/dist/chains/solana/kamino/tx/computeBudget.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/computeBudget.js +73 -0
- package/dist/chains/solana/kamino/tx/computeBudget.js.map +1 -0
- package/dist/chains/solana/kamino/tx/decode.d.ts +121 -0
- package/dist/chains/solana/kamino/tx/decode.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/decode.js +458 -0
- package/dist/chains/solana/kamino/tx/decode.js.map +1 -0
- package/dist/chains/solana/kamino/tx/instructions.d.ts +260 -0
- package/dist/chains/solana/kamino/tx/instructions.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/instructions.js +256 -0
- package/dist/chains/solana/kamino/tx/instructions.js.map +1 -0
- package/dist/chains/solana/kamino/tx/sequence.d.ts +123 -0
- package/dist/chains/solana/kamino/tx/sequence.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/sequence.js +235 -0
- package/dist/chains/solana/kamino/tx/sequence.js.map +1 -0
- package/dist/chains/solana/kamino/tx/validate.d.ts +138 -0
- package/dist/chains/solana/kamino/tx/validate.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/validate.js +542 -0
- package/dist/chains/solana/kamino/tx/validate.js.map +1 -0
- package/dist/chains/solana/kamino/tx/wire.d.ts +107 -0
- package/dist/chains/solana/kamino/tx/wire.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/wire.js +274 -0
- package/dist/chains/solana/kamino/tx/wire.js.map +1 -0
- package/dist/chains/solana/kamino/vaultInfo.d.ts +17 -0
- package/dist/chains/solana/kamino/vaultInfo.d.ts.map +1 -0
- package/dist/chains/solana/kamino/vaultInfo.js +150 -0
- package/dist/chains/solana/kamino/vaultInfo.js.map +1 -0
- package/dist/chains/thorchain/ruji/services/fetchMergeableTokenBalances.d.ts +6 -1
- package/dist/chains/thorchain/ruji/services/fetchMergeableTokenBalances.d.ts.map +1 -1
- package/dist/chains/thorchain/ruji/services/fetchMergeableTokenBalances.js +6 -35
- package/dist/chains/thorchain/ruji/services/fetchMergeableTokenBalances.js.map +1 -1
- package/dist/swap/quote/findSwapQuote.d.ts +39 -0
- package/dist/swap/quote/findSwapQuote.d.ts.map +1 -1
- package/dist/swap/quote/findSwapQuote.js +33 -2
- package/dist/swap/quote/findSwapQuote.js.map +1 -1
- package/dist/tx/broadcast/cosmosSequenceMismatch.d.ts +26 -0
- package/dist/tx/broadcast/cosmosSequenceMismatch.d.ts.map +1 -0
- package/dist/tx/broadcast/cosmosSequenceMismatch.js +79 -0
- package/dist/tx/broadcast/cosmosSequenceMismatch.js.map +1 -0
- package/dist/tx/broadcast/resolvers/cosmos.d.ts +1 -0
- package/dist/tx/broadcast/resolvers/cosmos.d.ts.map +1 -1
- package/dist/tx/broadcast/resolvers/cosmos.js +7 -1
- package/dist/tx/broadcast/resolvers/cosmos.js.map +1 -1
- package/dist/tx/broadcast/transientRetry.d.ts.map +1 -1
- package/dist/tx/broadcast/transientRetry.js +6 -0
- package/dist/tx/broadcast/transientRetry.js.map +1 -1
- package/dist/utils/isValidTokenId.d.ts +6 -3
- package/dist/utils/isValidTokenId.d.ts.map +1 -1
- package/dist/utils/isValidTokenId.js +10 -3
- package/dist/utils/isValidTokenId.js.map +1 -1
- package/package.json +97 -2
|
@@ -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"}
|