@elmntl/jlpd-sdk 0.2.0 → 0.13.4

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 (115) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +185 -404
  3. package/dist/common/ata.d.ts +26 -0
  4. package/dist/common/ata.js +48 -0
  5. package/dist/common/buffer.d.ts +15 -0
  6. package/dist/common/buffer.js +118 -0
  7. package/dist/common/connection.d.ts +13 -0
  8. package/dist/common/connection.js +2 -0
  9. package/dist/common/constants.d.ts +14 -0
  10. package/dist/common/constants.js +31 -0
  11. package/dist/common/index.d.ts +6 -0
  12. package/dist/common/index.js +28 -0
  13. package/dist/common/strategy-interface.d.ts +59 -0
  14. package/dist/common/strategy-interface.js +42 -0
  15. package/dist/elemental-lend/accounts.d.ts +103 -0
  16. package/dist/elemental-lend/accounts.js +354 -0
  17. package/dist/elemental-lend/constants.d.ts +25 -0
  18. package/dist/elemental-lend/constants.js +48 -0
  19. package/dist/elemental-lend/index.d.ts +8 -0
  20. package/dist/elemental-lend/index.js +24 -0
  21. package/dist/elemental-lend/instructions.d.ts +104 -0
  22. package/dist/elemental-lend/instructions.js +266 -0
  23. package/dist/elemental-lend/jupiter-lend.d.ts +91 -0
  24. package/dist/elemental-lend/jupiter-lend.js +189 -0
  25. package/dist/elemental-lend/kamino-vault.d.ts +173 -0
  26. package/dist/elemental-lend/kamino-vault.js +483 -0
  27. package/dist/elemental-lend/pda.d.ts +12 -0
  28. package/dist/elemental-lend/pda.js +24 -0
  29. package/dist/elemental-lend/protocol-actions.d.ts +56 -0
  30. package/dist/elemental-lend/protocol-actions.js +244 -0
  31. package/dist/elemental-lend/types.d.ts +113 -0
  32. package/dist/elemental-lend/types.js +2 -0
  33. package/dist/elemental-lend-v2/accounts.d.ts +14 -0
  34. package/dist/elemental-lend-v2/accounts.js +136 -0
  35. package/dist/elemental-lend-v2/adapters.d.ts +22 -0
  36. package/dist/elemental-lend-v2/adapters.js +50 -0
  37. package/dist/elemental-lend-v2/constants.d.ts +48 -0
  38. package/dist/elemental-lend-v2/constants.js +104 -0
  39. package/dist/elemental-lend-v2/index.d.ts +8 -0
  40. package/dist/elemental-lend-v2/index.js +24 -0
  41. package/dist/elemental-lend-v2/instructions.d.ts +96 -0
  42. package/dist/elemental-lend-v2/instructions.js +190 -0
  43. package/dist/elemental-lend-v2/lut.d.ts +20 -0
  44. package/dist/elemental-lend-v2/lut.js +65 -0
  45. package/dist/elemental-lend-v2/pda.d.ts +9 -0
  46. package/dist/elemental-lend-v2/pda.js +27 -0
  47. package/dist/elemental-lend-v2/types.d.ts +105 -0
  48. package/dist/elemental-lend-v2/types.js +2 -0
  49. package/dist/elemental-lend-v2/update-aum.d.ts +29 -0
  50. package/dist/elemental-lend-v2/update-aum.js +82 -0
  51. package/dist/index.d.ts +5 -4199
  52. package/dist/index.js +37 -5187
  53. package/dist/jlpd-strategy/accounts.d.ts +83 -0
  54. package/dist/jlpd-strategy/accounts.js +216 -0
  55. package/dist/jlpd-strategy/adapter.d.ts +81 -0
  56. package/dist/jlpd-strategy/adapter.js +118 -0
  57. package/dist/jlpd-strategy/base-to-base-swap.d.ts +74 -0
  58. package/dist/jlpd-strategy/base-to-base-swap.js +205 -0
  59. package/dist/jlpd-strategy/constants.d.ts +127 -0
  60. package/dist/jlpd-strategy/constants.js +174 -0
  61. package/dist/jlpd-strategy/fluid-view.d.ts +199 -0
  62. package/dist/jlpd-strategy/fluid-view.js +799 -0
  63. package/dist/jlpd-strategy/hedge-derived.d.ts +135 -0
  64. package/dist/jlpd-strategy/hedge-derived.js +231 -0
  65. package/dist/jlpd-strategy/hedge-instructions.d.ts +210 -0
  66. package/dist/jlpd-strategy/hedge-instructions.js +300 -0
  67. package/dist/jlpd-strategy/hedge-state.d.ts +88 -0
  68. package/dist/jlpd-strategy/hedge-state.js +110 -0
  69. package/dist/jlpd-strategy/index.d.ts +17 -0
  70. package/dist/jlpd-strategy/index.js +33 -0
  71. package/dist/jlpd-strategy/instructions.d.ts +159 -0
  72. package/dist/jlpd-strategy/instructions.js +234 -0
  73. package/dist/jlpd-strategy/jlp-borrow.d.ts +63 -0
  74. package/dist/jlpd-strategy/jlp-borrow.js +87 -0
  75. package/dist/jlpd-strategy/jlp-data.d.ts +166 -0
  76. package/dist/jlpd-strategy/jlp-data.js +611 -0
  77. package/dist/jlpd-strategy/jupusd-earn.d.ts +90 -0
  78. package/dist/jlpd-strategy/jupusd-earn.js +166 -0
  79. package/dist/jlpd-strategy/live-jlp-price.d.ts +46 -0
  80. package/dist/jlpd-strategy/live-jlp-price.js +267 -0
  81. package/dist/jlpd-strategy/pda.d.ts +13 -0
  82. package/dist/jlpd-strategy/pda.js +28 -0
  83. package/dist/jlpd-strategy/settle-yield.d.ts +45 -0
  84. package/dist/jlpd-strategy/settle-yield.js +113 -0
  85. package/dist/jlpd-strategy/swap-jlp.d.ts +198 -0
  86. package/dist/jlpd-strategy/swap-jlp.js +586 -0
  87. package/dist/jlpd-strategy/types.d.ts +101 -0
  88. package/dist/jlpd-strategy/types.js +29 -0
  89. package/dist/p-stv-core/accounts.d.ts +152 -0
  90. package/dist/p-stv-core/accounts.js +407 -0
  91. package/dist/p-stv-core/constants.d.ts +138 -0
  92. package/dist/p-stv-core/constants.js +181 -0
  93. package/dist/p-stv-core/events.d.ts +7 -0
  94. package/dist/p-stv-core/events.js +246 -0
  95. package/dist/p-stv-core/index.d.ts +11 -0
  96. package/dist/p-stv-core/index.js +27 -0
  97. package/dist/p-stv-core/instructions.d.ts +637 -0
  98. package/dist/p-stv-core/instructions.js +670 -0
  99. package/dist/p-stv-core/lut.d.ts +41 -0
  100. package/dist/p-stv-core/lut.js +81 -0
  101. package/dist/p-stv-core/pda.d.ts +30 -0
  102. package/dist/p-stv-core/pda.js +65 -0
  103. package/dist/p-stv-core/prices.d.ts +20 -0
  104. package/dist/p-stv-core/prices.js +77 -0
  105. package/dist/p-stv-core/remaining-accounts.d.ts +107 -0
  106. package/dist/p-stv-core/remaining-accounts.js +326 -0
  107. package/dist/p-stv-core/send-tx.d.ts +72 -0
  108. package/dist/p-stv-core/send-tx.js +290 -0
  109. package/dist/p-stv-core/sol-wrap.d.ts +34 -0
  110. package/dist/p-stv-core/sol-wrap.js +74 -0
  111. package/dist/p-stv-core/types.d.ts +361 -0
  112. package/dist/p-stv-core/types.js +2 -0
  113. package/package.json +56 -15
  114. package/dist/index.d.mts +0 -4199
  115. package/dist/index.mjs +0 -5090
@@ -0,0 +1,354 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deserializeLendStrategyState = deserializeLendStrategyState;
4
+ exports.deserializeLendStvPosition = deserializeLendStvPosition;
5
+ exports.deserializeManagerRole = deserializeManagerRole;
6
+ exports.fetchLendStrategyState = fetchLendStrategyState;
7
+ exports.fetchLendStrategyStateByAddress = fetchLendStrategyStateByAddress;
8
+ exports.fetchLendStvPosition = fetchLendStvPosition;
9
+ exports.fetchManagerRole = fetchManagerRole;
10
+ exports.fetchAllLendStrategyStates = fetchAllLendStrategyStates;
11
+ exports.fetchManagersForStrategy = fetchManagersForStrategy;
12
+ exports.buildProtocolAccountsForAum = buildProtocolAccountsForAum;
13
+ const web3_js_1 = require("@solana/web3.js");
14
+ const buffer_1 = require("../common/buffer");
15
+ const strategy_interface_1 = require("../common/strategy-interface");
16
+ const constants_1 = require("./constants");
17
+ const pda_1 = require("./pda");
18
+ // ---------------------------------------------------------------------------
19
+ // Deserialization
20
+ //
21
+ // All offsets below INCLUDE the 8-byte Anchor account discriminator. Layout
22
+ // blocks above each parser show the field map; the helpers in
23
+ // `common/buffer.ts` validate that `offset + width <= data.length` so a
24
+ // drift between this file and the on-chain layout fails loudly with a
25
+ // `RangeError` rather than returning garbage.
26
+ // ---------------------------------------------------------------------------
27
+ /**
28
+ * LendStrategyState — Elemental Lend's per-base-mint strategy account. Total 536 bytes.
29
+ *
30
+ * Layout (offsets include the 8-byte discriminator):
31
+ * [ 0.. 8] discriminator (sha256("account:StrategyState")[..8] —
32
+ * shared with jlpd-strategy)
33
+ * --- StrategyStateHeader (104 bytes, identical across all strategy programs) ---
34
+ * [ 8.. 40] baseMint Pubkey
35
+ * [ 40.. 72] authority Pubkey (p-stv-core program)
36
+ * [ 72.. 80] pps u64 (scaled by PPS_DECIMALS = 10^9)
37
+ * [ 80.. 88] totalAum u64
38
+ * [ 88.. 96] totalShares u64
39
+ * [ 96..104] lastUpdated u64 (unix seconds)
40
+ * [104..106] flags u16 (FLAG_PAUSED, …)
41
+ * [106..107] version u8
42
+ * [107..108] bump u8
43
+ * [108..112] _headerPadding [u8; 4]
44
+ * --- Custom Elemental Lend fields (424 bytes) ---
45
+ * [112..144] admin Pubkey
46
+ * [144..464] protocols[10] [Pubkey; 10] (registered protocol accounts)
47
+ * [464..465] protocolCount u8
48
+ * [465..466] managerCount u8
49
+ * [466..472] _padding [u8; 6]
50
+ * [472..536] _reserved [u8; 64]
51
+ */
52
+ function deserializeLendStrategyState(data) {
53
+ if (data.length < constants_1.STRATEGY_STATE_SIZE) {
54
+ throw new Error(`LendStrategyState data too short: ${data.length} < ${constants_1.STRATEGY_STATE_SIZE}`);
55
+ }
56
+ const disc = data.subarray(0, 8);
57
+ if (!disc.equals(constants_1.DISC_STRATEGY_STATE)) {
58
+ throw new Error(`Invalid LendStrategyState discriminator`);
59
+ }
60
+ const protocolCount = (0, buffer_1.readU8)(data, 464);
61
+ const managerCount = (0, buffer_1.readU8)(data, 465);
62
+ const protocols = [];
63
+ for (let i = 0; i < protocolCount; i++) {
64
+ protocols.push((0, buffer_1.readPubkey)(data, 144 + i * 32));
65
+ }
66
+ return {
67
+ // Header
68
+ baseMint: (0, buffer_1.readPubkey)(data, 8),
69
+ authority: (0, buffer_1.readPubkey)(data, 40),
70
+ pps: (0, buffer_1.readU64)(data, 72),
71
+ totalAum: (0, buffer_1.readU64)(data, 80),
72
+ totalShares: (0, buffer_1.readU64)(data, 88),
73
+ lastUpdated: (0, buffer_1.readU64)(data, 96),
74
+ flags: (0, buffer_1.readU16)(data, 104),
75
+ version: (0, buffer_1.readU8)(data, 106),
76
+ bump: (0, buffer_1.readU8)(data, 107),
77
+ // Custom
78
+ admin: (0, buffer_1.readPubkey)(data, 112),
79
+ protocols,
80
+ protocolCount,
81
+ managerCount,
82
+ };
83
+ }
84
+ /**
85
+ * StvPosition — per-STV virtual share record. Total 120 bytes.
86
+ *
87
+ * The on-disk layout is identical across elemental-lend and jlpd-strategy
88
+ * (`StvPosition` from `common/strategy-interface.ts`). The 8-byte
89
+ * discriminator validation here distinguishes the two so a `JlpdStvPosition`
90
+ * can't be parsed as a lend position by mistake. See
91
+ * `common/strategy-interface.ts` for the field-by-field layout.
92
+ */
93
+ function deserializeLendStvPosition(data) {
94
+ if (data.length < constants_1.STV_POSITION_SIZE) {
95
+ throw new Error(`StvPosition data too short: ${data.length} < ${constants_1.STV_POSITION_SIZE}`);
96
+ }
97
+ const disc = data.subarray(0, 8);
98
+ if (!disc.equals(constants_1.DISC_STV_POSITION)) {
99
+ throw new Error(`Invalid StvPosition discriminator`);
100
+ }
101
+ return (0, strategy_interface_1.deserializeStvPosition)(data);
102
+ }
103
+ /**
104
+ * ManagerRole — per-(strategy_state, manager) authorization. Total 80 bytes.
105
+ *
106
+ * Layout (offsets include the 8-byte discriminator):
107
+ * [ 0.. 8] discriminator (sha256("account:ManagerRole")[..8] —
108
+ * shared with p-stv-core + jlpd-strategy)
109
+ * [ 8.. 40] strategyState Pubkey
110
+ * [ 40.. 72] manager Pubkey
111
+ * [ 72.. 73] bump u8
112
+ * [ 73.. 80] _padding [u8; 7]
113
+ */
114
+ function deserializeManagerRole(data) {
115
+ if (data.length < constants_1.MANAGER_ROLE_SIZE) {
116
+ throw new Error(`ManagerRole data too short: ${data.length} < ${constants_1.MANAGER_ROLE_SIZE}`);
117
+ }
118
+ const disc = data.subarray(0, 8);
119
+ if (!disc.equals(constants_1.DISC_MANAGER_ROLE)) {
120
+ throw new Error(`Invalid ManagerRole discriminator`);
121
+ }
122
+ return {
123
+ strategyState: (0, buffer_1.readPubkey)(data, 8),
124
+ manager: (0, buffer_1.readPubkey)(data, 40),
125
+ bump: (0, buffer_1.readU8)(data, 72),
126
+ };
127
+ }
128
+ // ---------------------------------------------------------------------------
129
+ // Fetch Helpers
130
+ // ---------------------------------------------------------------------------
131
+ async function fetchLendStrategyState(connection, baseMint, programId = constants_1.PROGRAM_ID) {
132
+ const [pda] = (0, pda_1.findStrategyStatePda)(baseMint, programId);
133
+ const info = await connection.getAccountInfo(pda);
134
+ if (!info)
135
+ throw new Error(`LendStrategyState not found for mint ${baseMint.toBase58()}`);
136
+ return deserializeLendStrategyState(info.data);
137
+ }
138
+ async function fetchLendStrategyStateByAddress(connection, address) {
139
+ const info = await connection.getAccountInfo(address);
140
+ if (!info)
141
+ throw new Error(`LendStrategyState not found at ${address.toBase58()}`);
142
+ return deserializeLendStrategyState(info.data);
143
+ }
144
+ async function fetchLendStvPosition(connection, stv, programId = constants_1.PROGRAM_ID) {
145
+ const [pda] = (0, pda_1.findStvPositionPda)(stv, programId);
146
+ const info = await connection.getAccountInfo(pda);
147
+ if (!info)
148
+ throw new Error(`StvPosition not found for stv ${stv.toBase58()}`);
149
+ return deserializeLendStvPosition(info.data);
150
+ }
151
+ async function fetchManagerRole(connection, strategyState, manager, programId = constants_1.PROGRAM_ID) {
152
+ const [pda] = (0, pda_1.findLendManagerRolePda)(strategyState, manager, programId);
153
+ const info = await connection.getAccountInfo(pda);
154
+ if (!info)
155
+ return null;
156
+ return deserializeManagerRole(info.data);
157
+ }
158
+ // ---------------------------------------------------------------------------
159
+ // GPA Helpers
160
+ // ---------------------------------------------------------------------------
161
+ async function fetchAllLendStrategyStates(connection, programId = constants_1.PROGRAM_ID) {
162
+ const accounts = await connection.getProgramAccounts(programId, {
163
+ filters: [
164
+ { dataSize: constants_1.STRATEGY_STATE_SIZE },
165
+ { memcmp: { offset: 0, bytes: constants_1.DISC_STRATEGY_STATE.toString("base64"), encoding: "base64" } },
166
+ ],
167
+ });
168
+ return accounts.map((a) => [a.pubkey, deserializeLendStrategyState(a.account.data)]);
169
+ }
170
+ async function fetchManagersForStrategy(connection, strategyState, programId = constants_1.PROGRAM_ID) {
171
+ const accounts = await connection.getProgramAccounts(programId, {
172
+ filters: [
173
+ { dataSize: constants_1.MANAGER_ROLE_SIZE },
174
+ { memcmp: { offset: 0, bytes: constants_1.DISC_MANAGER_ROLE.toString("base64"), encoding: "base64" } },
175
+ { memcmp: { offset: 8, bytes: strategyState.toBuffer().toString("base64"), encoding: "base64" } },
176
+ ],
177
+ });
178
+ return accounts.map((a) => [a.pubkey, deserializeManagerRole(a.account.data)]);
179
+ }
180
+ // ---------------------------------------------------------------------------
181
+ // Protocol Account Builders
182
+ // ---------------------------------------------------------------------------
183
+ /**
184
+ * Build remaining_accounts for the update_aum CPI on elemental-lend.
185
+ *
186
+ * COMPLETENESS REQUIREMENT: Every registered protocol MUST be present in the
187
+ * returned array. The on-chain update_aum.rs validates a completeness bitmap
188
+ * (seen == expected) and rejects with `IncompleteProtocolAccounts` if any
189
+ * registered protocol is missing (update_aum.rs:265). An uninitialized share
190
+ * ATA is NOT an error — the on-chain `read_protocol_share_ata` checks the
191
+ * canonical ATA key and returns 0 for uninitialised accounts (update_aum.rs:314).
192
+ *
193
+ * Canonical ATA addresses are DERIVED (not fetched from token account lists) so
194
+ * that uninitialized ATAs are included. The on-chain `is_canonical_ata`
195
+ * (update_aum.rs:30-37) pins the SINGLE SPL-Token ATA derivation — all Elemental
196
+ * Lend receipt mints (Kamino kvTokens, Jupiter fTokens) are SPL-Token mints. Share
197
+ * ATAs are ALWAYS derived under the SPL Token program id regardless of the caller's
198
+ * `tokenProgramId`; passing a Token-2022 id would yield a different ATA address that
199
+ * the on-chain handler rejects.
200
+ *
201
+ * - kVault (KvauG...): [kvtoken_ata, vault_state] (2 accounts)
202
+ * - Jupiter Lend (jup3Y...): [ftoken_ata, lending_account, rewards_rate_model] (3 accounts)
203
+ *
204
+ * @param connection - Solana connection (needed to fetch protocol account data)
205
+ * @param strategy - Deserialized LendStrategyState (with protocols list)
206
+ * @param strategyStatePda - The strategy state PDA (owns the share-token ATAs)
207
+ * @param tokenProgramId - Token program for the BASE mint ATA derivation. Share-mint ATAs
208
+ * (kvToken, fToken) are always derived under SPL Token regardless of this value.
209
+ * @param protocolCache - Optional pre-resolved cache of protocol specs keyed by protocol
210
+ * pubkey base-58. On a cache hit the `getMultipleAccountsInfo` fetch is skipped for
211
+ * that protocol. On a miss the protocol is fetched and the result is stored in the
212
+ * cache for future calls. Pass a shared `Map` across repeated calls (e.g. in a keeper
213
+ * loop) to avoid refetching mostly-static protocol metadata every iteration.
214
+ *
215
+ * **Cache contract (FIX 4 — staleness):** The cache is caller-owned and intentionally
216
+ * short-lived / slot-scoped. Callers are responsible for invalidation. For Jupiter Lend
217
+ * protocols the cached `data` includes the `fTokenMint` and `rewardsRateModel` fields;
218
+ * if a Jupiter Lend pool's `rewardsRateModel` account changes (rare, governance-gated)
219
+ * the cache entry becomes stale. Always construct a fresh `Map` (or clear the existing
220
+ * one) at the start of each slot/epoch boundary or after any on-chain governance change
221
+ * to the protocol accounts. Do NOT hold the same cache instance across multiple slots in
222
+ * latency-sensitive paths — create a new `Map()` per transaction-building pass instead.
223
+ */
224
+ async function buildProtocolAccountsForAum(connection, strategy, strategyStatePda,
225
+ // Retained for signature stability + positional `protocolCache`; share-mint ATAs are
226
+ // pinned to SPL Token (the program's is_canonical_ata is SPL-only), so the caller's
227
+ // token program is no longer used for any derivation in this builder.
228
+ _tokenProgramId, protocolCache) {
229
+ const accounts = [];
230
+ if (strategy.protocolCount === 0)
231
+ return accounts;
232
+ // Only fetch the active slice — strategy.protocols is a fixed-size array but only
233
+ // the first protocolCount entries are registered; the rest are default pubkeys.
234
+ const activeProtocols = strategy.protocols.slice(0, strategy.protocolCount);
235
+ // Determine which protocols need an RPC fetch (cache miss or no cache).
236
+ const needFetch = [];
237
+ const needFetchIdx = [];
238
+ for (let i = 0; i < activeProtocols.length; i++) {
239
+ const key = activeProtocols[i].toBase58();
240
+ if (!protocolCache || !protocolCache.has(key)) {
241
+ needFetch.push(activeProtocols[i]);
242
+ needFetchIdx.push(i);
243
+ }
244
+ }
245
+ // Batch-fetch all cache-miss protocols in one RPC call.
246
+ let fetchedInfos = [];
247
+ if (needFetch.length > 0) {
248
+ fetchedInfos = await connection.getMultipleAccountsInfo(needFetch);
249
+ }
250
+ // FIX 3: Build a direct map from active-protocol index → resolved {owner, data}.
251
+ // Resolve each protocol's result BEFORE writing anything into the cache, so the
252
+ // build loop selects fetch results by the protocol's position in needFetchIdx
253
+ // rather than by post-mutation cache.has() — which would desync fetchIdx when
254
+ // some fetched protocols return null (null results are not written to the cache,
255
+ // so a later null-result protocol would have its cache.has() == false in the build
256
+ // loop, but fetchIdx would be pointing to the wrong slot because prior successful
257
+ // fetches were already consumed from fetchedInfos via cache hits).
258
+ const resolved = new Array(activeProtocols.length);
259
+ for (let j = 0; j < needFetchIdx.length; j++) {
260
+ const i = needFetchIdx[j];
261
+ const info = fetchedInfos[j];
262
+ const keyStr = activeProtocols[i].toBase58();
263
+ if (!info) {
264
+ throw new Error(`buildProtocolAccountsForAum: protocol account not found: ${keyStr} (index ${i})`);
265
+ }
266
+ resolved[i] = { owner: info.owner, data: info.data };
267
+ }
268
+ // Fill cached protocols into resolved[], then populate the cache from fresh fetches.
269
+ // Separating these two steps ensures the cache is only written AFTER all results are
270
+ // resolved — so the build loop below always drives selection from `resolved[]` (index-
271
+ // based), never from a post-mutation cache.has() check.
272
+ for (let i = 0; i < activeProtocols.length; i++) {
273
+ if (resolved[i] === undefined) {
274
+ // Must be a cache hit (was excluded from needFetch).
275
+ const cached = protocolCache.get(activeProtocols[i].toBase58());
276
+ resolved[i] = cached;
277
+ }
278
+ }
279
+ // Populate cache for future calls (only for successfully fetched entries).
280
+ if (protocolCache) {
281
+ for (let j = 0; j < needFetchIdx.length; j++) {
282
+ const i = needFetchIdx[j];
283
+ protocolCache.set(activeProtocols[i].toBase58(), resolved[i]);
284
+ }
285
+ }
286
+ // Build protocol account groups — drive selection from resolved[] by index.
287
+ // The emitted AccountMeta[] order and flags are identical whether the protocol
288
+ // was cached or freshly fetched (both paths produce the same resolved[i]).
289
+ for (let i = 0; i < activeProtocols.length; i++) {
290
+ const protocolKey = activeProtocols[i];
291
+ const keyStr = protocolKey.toBase58();
292
+ const { owner, data } = resolved[i];
293
+ if (owner.equals(constants_1.KAMINO_VAULT_PROGRAM)) {
294
+ // kVault: AUM accounts = [kvtoken_ata, vault_state]
295
+ //
296
+ // Derive the shares_mint PDA: ["shares", vault_state] under KAMINO_VAULT_PROGRAM.
297
+ // Derive the canonical kvToken ATA for strategyStatePda — even if uninitialized,
298
+ // the on-chain handler accepts it (returns 0 for data.len() < 72).
299
+ // Share ATAs are always SPL-Token (is_canonical_ata pins spl_token derivation).
300
+ const [sharesMint] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("shares"), protocolKey.toBuffer()], constants_1.KAMINO_VAULT_PROGRAM);
301
+ const kvTokenAta = findAtaAddress(sharesMint, strategyStatePda, SPL_TOKEN_PROGRAM_ID);
302
+ accounts.push({ pubkey: kvTokenAta, isSigner: false, isWritable: false }, { pubkey: protocolKey, isSigner: false, isWritable: false });
303
+ }
304
+ else if (owner.equals(constants_1.JUP_LEND_EARN_PROGRAM)) {
305
+ // Jupiter Lend Earn: AUM accounts = [ftoken_ata, lending_account, rewards_rate_model]
306
+ //
307
+ // Lending account layout (Jupiter Lend Earn — Anchor 8-byte disc):
308
+ // [ 0.. 8] discriminator
309
+ // [ 8.. 40] authority Pubkey
310
+ // [ 40.. 72] fTokenMint Pubkey
311
+ // [ 72.. 75] _padding [u8; 3]
312
+ // [ 75..107] rewardsRateModel Pubkey
313
+ // [107..] remaining fields …
314
+ if (data.length < 107) {
315
+ throw new Error(`buildProtocolAccountsForAum: Jupiter Lend account data too short at ${keyStr}`);
316
+ }
317
+ const fTokenMint = new web3_js_1.PublicKey(data.subarray(40, 72));
318
+ const rewardsRateModel = new web3_js_1.PublicKey(data.subarray(75, 107));
319
+ // Share ATAs are always SPL-Token — is_canonical_ata (update_aum.rs:30-37) pins
320
+ // the spl_token derivation. Jupiter fTokens are SPL-Token mints; a Token-2022
321
+ // derivation would produce a different key the on-chain handler rejects.
322
+ const fTokenAta = findAtaAddress(fTokenMint, strategyStatePda, SPL_TOKEN_PROGRAM_ID);
323
+ accounts.push({ pubkey: fTokenAta, isSigner: false, isWritable: false }, { pubkey: protocolKey, isSigner: false, isWritable: false }, { pubkey: rewardsRateModel, isSigner: false, isWritable: false });
324
+ }
325
+ else {
326
+ // Unknown protocol owner — reject loudly rather than silently skipping.
327
+ // An unknown protocol would make the on-chain completeness check fail anyway.
328
+ throw new Error(`buildProtocolAccountsForAum: unknown protocol owner ${owner.toBase58()} at ${keyStr}`);
329
+ }
330
+ }
331
+ return accounts;
332
+ }
333
+ /** Associated Token Program ID (constant; same across SPL Token and Token-2022 namespaces). */
334
+ const ASSOCIATED_TOKEN_PROGRAM_ID_KEY = new web3_js_1.PublicKey("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL");
335
+ /**
336
+ * SPL Token program ID. Used to pin ATA derivations for lend receipt/share mints.
337
+ *
338
+ * The on-chain `is_canonical_ata` (update_aum.rs:30-37) pins the SINGLE SPL-Token ATA
339
+ * derivation — all Elemental Lend receipt mints (Kamino kvTokens, Jupiter fTokens) are
340
+ * SPL-Token mints, verified on-chain 2026-06-13. Deriving under Token-2022 would yield
341
+ * a different address that the on-chain handler rejects.
342
+ */
343
+ const SPL_TOKEN_PROGRAM_ID = new web3_js_1.PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
344
+ /**
345
+ * Derive an Associated Token Account address.
346
+ *
347
+ * PDA([owner, tokenProgram, mint], ASSOCIATED_TOKEN_PROGRAM_ID).
348
+ * Inline helper scoped to this module so elemental-lend/accounts.ts has no
349
+ * cross-module dependency on common/ata.ts.
350
+ */
351
+ function findAtaAddress(mint, owner, tokenProgram) {
352
+ const [ata] = web3_js_1.PublicKey.findProgramAddressSync([owner.toBuffer(), tokenProgram.toBuffer(), mint.toBuffer()], ASSOCIATED_TOKEN_PROGRAM_ID_KEY);
353
+ return ata;
354
+ }
@@ -0,0 +1,25 @@
1
+ import { PublicKey } from "@solana/web3.js";
2
+ export declare const PROGRAM_ID: PublicKey;
3
+ export declare const STRATEGY_STATE_SEED: Buffer<ArrayBuffer>;
4
+ export declare const POSITION_SEED: Buffer<ArrayBuffer>;
5
+ export declare const MANAGER_SEED: Buffer<ArrayBuffer>;
6
+ export { DISC_STRATEGY_STATE, DISC_STV_POSITION, DISC_MANAGER_ROLE, } from "../common/constants";
7
+ export declare const IX_INIT_OR_UPDATE_STRATEGY: Buffer<ArrayBuffer>;
8
+ export declare const IX_CLOSE_STRATEGY: Buffer<ArrayBuffer>;
9
+ export declare const IX_RESET_STRATEGY: Buffer<ArrayBuffer>;
10
+ export declare const IX_ADD_MANAGER: Buffer<ArrayBuffer>;
11
+ export declare const IX_REMOVE_MANAGER: Buffer<ArrayBuffer>;
12
+ export declare const IX_KVAULT_DEPOSIT: Buffer<ArrayBuffer>;
13
+ export declare const IX_KVAULT_WITHDRAW: Buffer<ArrayBuffer>;
14
+ export declare const IX_JUP_LEND_DEPOSIT: Buffer<ArrayBuffer>;
15
+ export declare const IX_JUP_LEND_WITHDRAW: Buffer<ArrayBuffer>;
16
+ export declare const STRATEGY_STATE_SIZE = 536;
17
+ export declare const STV_POSITION_SIZE = 120;
18
+ export declare const MANAGER_ROLE_SIZE = 80;
19
+ export declare const FLAG_PAUSED = 1;
20
+ export declare const MAX_PROTOCOLS = 10;
21
+ export declare const KAMINO_VAULT_PROGRAM: PublicKey;
22
+ export declare const KLEND_PROGRAM: PublicKey;
23
+ /** Jupiter Lend Earn program (the supply-side product). */
24
+ export declare const JUP_LEND_EARN_PROGRAM: PublicKey;
25
+ export { PPS_DECIMALS } from "../common/constants";
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PPS_DECIMALS = exports.JUP_LEND_EARN_PROGRAM = exports.KLEND_PROGRAM = exports.KAMINO_VAULT_PROGRAM = exports.MAX_PROTOCOLS = exports.FLAG_PAUSED = exports.MANAGER_ROLE_SIZE = exports.STV_POSITION_SIZE = exports.STRATEGY_STATE_SIZE = exports.IX_JUP_LEND_WITHDRAW = exports.IX_JUP_LEND_DEPOSIT = exports.IX_KVAULT_WITHDRAW = exports.IX_KVAULT_DEPOSIT = exports.IX_REMOVE_MANAGER = exports.IX_ADD_MANAGER = exports.IX_RESET_STRATEGY = exports.IX_CLOSE_STRATEGY = exports.IX_INIT_OR_UPDATE_STRATEGY = exports.DISC_MANAGER_ROLE = exports.DISC_STV_POSITION = exports.DISC_STRATEGY_STATE = exports.MANAGER_SEED = exports.POSITION_SEED = exports.STRATEGY_STATE_SEED = exports.PROGRAM_ID = void 0;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ exports.PROGRAM_ID = new web3_js_1.PublicKey("EHaGVh7p6xSxZsq4CcEEZhnV5adDvWg1gS1Rc5rLiBpC");
6
+ // PDA Seeds
7
+ exports.STRATEGY_STATE_SEED = Buffer.from("strategy_state");
8
+ exports.POSITION_SEED = Buffer.from("position");
9
+ exports.MANAGER_SEED = Buffer.from("manager");
10
+ // Account discriminators (Anchor 8-byte) — defined once in common/, re-exported here
11
+ var constants_1 = require("../common/constants");
12
+ Object.defineProperty(exports, "DISC_STRATEGY_STATE", { enumerable: true, get: function () { return constants_1.DISC_STRATEGY_STATE; } });
13
+ Object.defineProperty(exports, "DISC_STV_POSITION", { enumerable: true, get: function () { return constants_1.DISC_STV_POSITION; } });
14
+ Object.defineProperty(exports, "DISC_MANAGER_ROLE", { enumerable: true, get: function () { return constants_1.DISC_MANAGER_ROLE; } });
15
+ // Instruction discriminators (Anchor 8-byte)
16
+ // --- Admin instructions ---
17
+ exports.IX_INIT_OR_UPDATE_STRATEGY = Buffer.from([221, 4, 60, 139, 83, 148, 116, 247]);
18
+ // sha256("global:close_strategy")[..8] — verified against elemental_lend.json IDL
19
+ exports.IX_CLOSE_STRATEGY = Buffer.from([56, 247, 170, 246, 89, 221, 134, 200]);
20
+ // sha256("global:reset_strategy")[..8] — verified against elemental_lend.json IDL
21
+ exports.IX_RESET_STRATEGY = Buffer.from([127, 28, 155, 41, 137, 170, 16, 39]);
22
+ // sha256("global:add_manager")[..8]
23
+ exports.IX_ADD_MANAGER = Buffer.from([0x7d, 0x26, 0xc0, 0xd4, 0x65, 0x5b, 0xb3, 0x10]);
24
+ // sha256("global:remove_manager")[..8]
25
+ exports.IX_REMOVE_MANAGER = Buffer.from([0x96, 0x37, 0x9d, 0x4d, 0x80, 0x94, 0x07, 0x0f]);
26
+ // --- Protocol instructions (manager-only via ManagerRole PDA) ---
27
+ exports.IX_KVAULT_DEPOSIT = Buffer.from([240, 233, 97, 12, 52, 70, 230, 243]);
28
+ exports.IX_KVAULT_WITHDRAW = Buffer.from([186, 254, 50, 47, 123, 146, 242, 216]);
29
+ exports.IX_JUP_LEND_DEPOSIT = Buffer.from([87, 129, 182, 64, 170, 11, 223, 59]);
30
+ exports.IX_JUP_LEND_WITHDRAW = Buffer.from([46, 152, 191, 164, 24, 135, 89, 64]);
31
+ // NOTE: The CPI-facing discriminators (init_position, deposit, withdraw, update_aum)
32
+ // are invoked by p-stv-core directly via remaining_accounts; clients do not call them
33
+ // standalone and they are not exported from this SDK module.
34
+ // Account sizes
35
+ exports.STRATEGY_STATE_SIZE = 536;
36
+ exports.STV_POSITION_SIZE = 120;
37
+ exports.MANAGER_ROLE_SIZE = 80;
38
+ // Flags
39
+ exports.FLAG_PAUSED = 0x0001;
40
+ // Limits
41
+ exports.MAX_PROTOCOLS = 10;
42
+ // External protocol programs
43
+ exports.KAMINO_VAULT_PROGRAM = new web3_js_1.PublicKey("KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd");
44
+ exports.KLEND_PROGRAM = new web3_js_1.PublicKey("KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD");
45
+ /** Jupiter Lend Earn program (the supply-side product). */
46
+ exports.JUP_LEND_EARN_PROGRAM = new web3_js_1.PublicKey("jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9");
47
+ var constants_2 = require("../common/constants");
48
+ Object.defineProperty(exports, "PPS_DECIMALS", { enumerable: true, get: function () { return constants_2.PPS_DECIMALS; } });
@@ -0,0 +1,8 @@
1
+ export * from "./constants";
2
+ export * from "./types";
3
+ export * from "./pda";
4
+ export * from "./accounts";
5
+ export * from "./instructions";
6
+ export * from "./jupiter-lend";
7
+ export * from "./kamino-vault";
8
+ export * from "./protocol-actions";
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./constants"), exports);
18
+ __exportStar(require("./types"), exports);
19
+ __exportStar(require("./pda"), exports);
20
+ __exportStar(require("./accounts"), exports);
21
+ __exportStar(require("./instructions"), exports);
22
+ __exportStar(require("./jupiter-lend"), exports);
23
+ __exportStar(require("./kamino-vault"), exports);
24
+ __exportStar(require("./protocol-actions"), exports);
@@ -0,0 +1,104 @@
1
+ import { PublicKey, TransactionInstruction, AccountMeta } from "@solana/web3.js";
2
+ import BN from "bn.js";
3
+ export interface InitOrUpdateStrategyArgs {
4
+ admin: PublicKey;
5
+ strategyState: PublicKey;
6
+ baseMint: PublicKey;
7
+ strategyBaseAta: PublicKey;
8
+ tokenProgram: PublicKey;
9
+ systemProgram?: PublicKey;
10
+ associatedTokenProgram?: PublicKey;
11
+ authority?: PublicKey | null;
12
+ flags?: number | null;
13
+ addProtocol?: PublicKey | null;
14
+ removeProtocol?: PublicKey | null;
15
+ newAdmin?: PublicKey | null;
16
+ /**
17
+ * One-shot legacy backfill of `manager_count` (update path only) — set to the true
18
+ * live ManagerRole count on a strategy that predates the counter, so the
19
+ * close_strategy `manager_count == 0` gate is effective. Omit on normal calls.
20
+ */
21
+ managerCount?: number | null;
22
+ remainingAccounts?: AccountMeta[];
23
+ }
24
+ export declare function createInitOrUpdateStrategyIx(args: InitOrUpdateStrategyArgs, programId?: PublicKey): TransactionInstruction;
25
+ export interface CloseStrategyArgs {
26
+ admin: PublicKey;
27
+ payer: PublicKey;
28
+ strategyState: PublicKey;
29
+ strategyBaseAta: PublicKey;
30
+ baseMint: PublicKey;
31
+ tokenProgram: PublicKey;
32
+ /** Optional: required when strategy_base_ata has residual balance to drain. */
33
+ remainingAccounts?: AccountMeta[];
34
+ }
35
+ export declare function createCloseStrategyIx(args: CloseStrategyArgs, programId?: PublicKey): TransactionInstruction;
36
+ export interface ResetStrategyArgs {
37
+ admin: PublicKey;
38
+ strategyState: PublicKey;
39
+ }
40
+ export declare function createResetStrategyIx(args: ResetStrategyArgs, programId?: PublicKey): TransactionInstruction;
41
+ export interface KvaultDepositArgs {
42
+ manager: PublicKey;
43
+ strategyState: PublicKey;
44
+ managerRole: PublicKey;
45
+ depositorBaseAta: PublicKey;
46
+ depositorSharesAta: PublicKey;
47
+ amount: BN | number;
48
+ /** Minimum protocol-receipt out (deposit: shares/fTokens; withdraw: base). 0 = non-zero only. */
49
+ minOut?: BN | number;
50
+ remainingAccounts: AccountMeta[];
51
+ }
52
+ export declare function createKvaultDepositIx(args: KvaultDepositArgs, programId?: PublicKey): TransactionInstruction;
53
+ export interface KvaultWithdrawArgs {
54
+ manager: PublicKey;
55
+ strategyState: PublicKey;
56
+ managerRole: PublicKey;
57
+ depositorBaseAta: PublicKey;
58
+ depositorSharesAta: PublicKey;
59
+ shares: BN | number;
60
+ /** Minimum protocol-receipt out (deposit: shares/fTokens; withdraw: base). 0 = non-zero only. */
61
+ minOut?: BN | number;
62
+ remainingAccounts: AccountMeta[];
63
+ }
64
+ export declare function createKvaultWithdrawIx(args: KvaultWithdrawArgs, programId?: PublicKey): TransactionInstruction;
65
+ export interface JupLendDepositArgs {
66
+ manager: PublicKey;
67
+ strategyState: PublicKey;
68
+ managerRole: PublicKey;
69
+ depositorBaseAta: PublicKey;
70
+ depositorFtokenAta: PublicKey;
71
+ amount: BN | number;
72
+ /** Minimum protocol-receipt out (deposit: shares/fTokens; withdraw: base). 0 = non-zero only. */
73
+ minOut?: BN | number;
74
+ remainingAccounts: AccountMeta[];
75
+ }
76
+ export declare function createJupLendDepositIx(args: JupLendDepositArgs, programId?: PublicKey): TransactionInstruction;
77
+ export interface JupLendWithdrawArgs {
78
+ manager: PublicKey;
79
+ strategyState: PublicKey;
80
+ managerRole: PublicKey;
81
+ depositorBaseAta: PublicKey;
82
+ depositorFtokenAta: PublicKey;
83
+ amount: BN | number;
84
+ /** Minimum protocol-receipt out (deposit: shares/fTokens; withdraw: base). 0 = non-zero only. */
85
+ minOut?: BN | number;
86
+ remainingAccounts: AccountMeta[];
87
+ }
88
+ export declare function createJupLendWithdrawIx(args: JupLendWithdrawArgs, programId?: PublicKey): TransactionInstruction;
89
+ export interface AddManagerArgs {
90
+ admin: PublicKey;
91
+ payer: PublicKey;
92
+ strategyState: PublicKey;
93
+ managerRole: PublicKey;
94
+ manager: PublicKey;
95
+ systemProgram?: PublicKey;
96
+ }
97
+ export declare function createAddManagerIx(args: AddManagerArgs, programId?: PublicKey): TransactionInstruction;
98
+ export interface RemoveManagerArgs {
99
+ admin: PublicKey;
100
+ payer: PublicKey;
101
+ strategyState: PublicKey;
102
+ managerRole: PublicKey;
103
+ }
104
+ export declare function createRemoveManagerIx(args: RemoveManagerArgs, programId?: PublicKey): TransactionInstruction;