@elmntl/jlpd-sdk 0.1.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/dist/index.js ADDED
@@ -0,0 +1,1843 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AdminContext: () => AdminContext,
24
+ EXCHANGE_RATE_PRECISION: () => EXCHANGE_RATE_PRECISION,
25
+ FLAG_DEPOSITS_DISABLED: () => FLAG_DEPOSITS_DISABLED,
26
+ FLAG_JLP_DISABLED: () => FLAG_JLP_DISABLED,
27
+ FLAG_PAUSED: () => FLAG_PAUSED,
28
+ FLAG_REBALANCE_DISABLED: () => FLAG_REBALANCE_DISABLED,
29
+ FLAG_WITHDRAWALS_DISABLED: () => FLAG_WITHDRAWALS_DISABLED,
30
+ JLPD_PROGRAM_ID: () => JLPD_PROGRAM_ID,
31
+ JLP_VAULT_ACCOUNT_SIZE: () => JLP_VAULT_ACCOUNT_SIZE,
32
+ JLP_VAULT_DATA_SIZE: () => JLP_VAULT_DATA_SIZE,
33
+ JLP_VAULT_DISCRIMINATOR: () => JLP_VAULT_DISCRIMINATOR,
34
+ JUPITER_LEND_PROGRAM_ID: () => JUPITER_LEND_PROGRAM_ID,
35
+ JUPITER_SWAP_PROGRAM_ID: () => JUPITER_SWAP_PROGRAM_ID,
36
+ JUPUSD_POOL: () => JUPUSD_POOL,
37
+ JUP_LEND_PROGRAM_ID: () => JUPITER_LEND_PROGRAM_ID2,
38
+ JlpdClient: () => JlpdClient,
39
+ JlpdClientError: () => JlpdClientError,
40
+ LENDING_ADMIN: () => LENDING_ADMIN,
41
+ LIQUIDITY_PROGRAM_ID: () => LIQUIDITY_PROGRAM_ID,
42
+ LIQUIDITY_SINGLETON: () => LIQUIDITY_SINGLETON,
43
+ MINTS: () => MINTS,
44
+ ORACLES: () => ORACLES,
45
+ POOLS: () => POOLS,
46
+ PPS_DECIMALS: () => PPS_DECIMALS,
47
+ PoolContext: () => PoolContext,
48
+ SEED_JLP_VAULT: () => SEED_JLP_VAULT,
49
+ SEED_STV: () => SEED_STV,
50
+ STV_ACCOUNT_SIZE: () => STV_ACCOUNT_SIZE,
51
+ STV_DATA_SIZE: () => STV_DATA_SIZE,
52
+ STV_DISCRIMINATOR: () => STV_DISCRIMINATOR,
53
+ STV_INDEX: () => STV_INDEX,
54
+ SwapContext: () => SwapContext,
55
+ USDC_POOL: () => USDC_POOL,
56
+ WBTC_POOL: () => WBTC_POOL,
57
+ WETH_POOL: () => WETH_POOL,
58
+ WSOL_POOL: () => WSOL_POOL,
59
+ baseToJlx: () => baseToJlx,
60
+ baseToShares: () => baseToShares,
61
+ buildExchangeRateAccounts: () => buildExchangeRateAccounts,
62
+ buildJupEarnDepositAccounts: () => buildJupEarnDepositAccounts,
63
+ buildJupEarnWithdrawAccounts: () => buildJupEarnWithdrawAccounts,
64
+ buildSwapData: () => buildSwapData,
65
+ calculateExchangeRate: () => calculateExchangeRate,
66
+ calculateNav: () => calculateNav,
67
+ calculatePps: () => calculatePps,
68
+ clearAtaCache: () => clearAtaCache,
69
+ clearPdaCache: () => clearPdaCache,
70
+ createClaimFeesInstruction: () => createClaimFeesInstruction,
71
+ createDepositInstruction: () => createDepositInstruction,
72
+ createInitOrUpdateVaultInstruction: () => createInitOrUpdateVaultInstruction,
73
+ createInitializeStvInstruction: () => createInitializeStvInstruction,
74
+ createJupEarnInstruction: () => createJupEarnInstruction,
75
+ createMoveJlxInstruction: () => createMoveJlxInstruction,
76
+ createSettleYieldInstruction: () => createSettleYieldInstruction,
77
+ createSwapJlxJlpInstruction: () => createSwapJlxJlpInstruction,
78
+ createSwapJlxJlxInstruction: () => createSwapJlxJlxInstruction,
79
+ createUpdateStvInstruction: () => createUpdateStvInstruction,
80
+ createWithdrawInstruction: () => createWithdrawInstruction,
81
+ deriveAta: () => deriveAta,
82
+ deriveStvAtas: () => deriveStvAtas,
83
+ deriveStvPda: () => deriveStvPda,
84
+ deriveUserAtas: () => deriveUserAtas,
85
+ deriveVaultAtas: () => deriveVaultAtas,
86
+ deriveVaultPda: () => deriveVaultPda,
87
+ fetchAddressLookupTables: () => fetchAddressLookupTables,
88
+ fetchJlpRate: () => fetchJlpRate,
89
+ fetchJupiterPriceUsd: () => fetchJupiterPriceUsd,
90
+ getJupiterQuote: () => getJupiterQuote,
91
+ getJupiterSwapInstructions: () => getJupiterSwapInstructions,
92
+ getPoolByMint: () => getPoolByMint,
93
+ getPoolByName: () => getPoolByName,
94
+ jlxToBase: () => jlxToBase,
95
+ parseLendingAccount: () => parseLendingAccount,
96
+ parseRewardsRateModel: () => parseRewardsRateModel,
97
+ parseStv: () => parseStv,
98
+ parseSwapRemainingAccounts: () => parseSwapRemainingAccounts,
99
+ parseVault: () => parseVault,
100
+ sharesToBase: () => sharesToBase
101
+ });
102
+ module.exports = __toCommonJS(index_exports);
103
+
104
+ // src/client.ts
105
+ var import_web312 = require("@solana/web3.js");
106
+ var import_anchor5 = require("@coral-xyz/anchor");
107
+ var import_spl_token5 = require("@solana/spl-token");
108
+
109
+ // src/constants.ts
110
+ var import_web3 = require("@solana/web3.js");
111
+ var import_spl_token = require("@solana/spl-token");
112
+ var JLPD_PROGRAM_ID = new import_web3.PublicKey(
113
+ "ELEM2bAobpZNuysfhyF28XGVjA1aTUwm6rPYyv1JX3oq"
114
+ );
115
+ var JUPITER_LEND_PROGRAM_ID = new import_web3.PublicKey(
116
+ "jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9"
117
+ );
118
+ var JUPITER_SWAP_PROGRAM_ID = new import_web3.PublicKey(
119
+ "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"
120
+ );
121
+ var SEED_JLP_VAULT = "jlp_vault";
122
+ var SEED_STV = "stv";
123
+ var FLAG_PAUSED = 1;
124
+ var FLAG_DEPOSITS_DISABLED = 2;
125
+ var FLAG_WITHDRAWALS_DISABLED = 4;
126
+ var FLAG_JLP_DISABLED = 8;
127
+ var FLAG_REBALANCE_DISABLED = 16;
128
+ var PPS_DECIMALS = 1e9;
129
+ var EXCHANGE_RATE_PRECISION = 1e12;
130
+ var MINTS = {
131
+ JLP: new import_web3.PublicKey("27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4"),
132
+ WSOL: import_spl_token.NATIVE_MINT,
133
+ USDC: new import_web3.PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"),
134
+ WBTC: new import_web3.PublicKey("3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh"),
135
+ WETH: new import_web3.PublicKey("7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs"),
136
+ JupUSD: new import_web3.PublicKey("JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD")
137
+ };
138
+ var STV_INDEX = /* @__PURE__ */ ((STV_INDEX2) => {
139
+ STV_INDEX2[STV_INDEX2["BTC"] = 0] = "BTC";
140
+ STV_INDEX2[STV_INDEX2["ETH"] = 1] = "ETH";
141
+ STV_INDEX2[STV_INDEX2["SOL"] = 2] = "SOL";
142
+ STV_INDEX2[STV_INDEX2["USDC"] = 3] = "USDC";
143
+ STV_INDEX2[STV_INDEX2["JupUSD"] = 4] = "JupUSD";
144
+ return STV_INDEX2;
145
+ })(STV_INDEX || {});
146
+ var ORACLES = {
147
+ // Doves oracles (Jupiter Perps oracle system)
148
+ DOVES_BTC_USD: new import_web3.PublicKey("4HBbPx9QJdjJ7GUe6bsiJjGybvfpDhQMMPXP1UEa7VT5"),
149
+ DOVES_ETH_USD: new import_web3.PublicKey("5URYohbPy32nxK1t3jAHVNfdWY2xTubHiFvLrE3VhXEp"),
150
+ DOVES_SOL_USD: new import_web3.PublicKey("39cWjvHrpHNz2SbXv6ME4NPhqBDBd4KsjUYv5JkHEAJU"),
151
+ // Pyth oracle for JLP price
152
+ PYTH_JLP_USD: new import_web3.PublicKey("2TTGSRSezqFzeLUH8JwRUbtN66XLLaymfYsWRTMjfiMw")
153
+ };
154
+
155
+ // src/accounts/pdas.ts
156
+ var import_web32 = require("@solana/web3.js");
157
+ var SEED_JLP_VAULT_BUFFER = Buffer.from(SEED_JLP_VAULT);
158
+ var SEED_STV_BUFFER = Buffer.from(SEED_STV);
159
+ var pdaCache = /* @__PURE__ */ new Map();
160
+ function deriveVaultPda(programId) {
161
+ const key = `vault:${programId.toBase58()}`;
162
+ let cached = pdaCache.get(key);
163
+ if (!cached) {
164
+ cached = import_web32.PublicKey.findProgramAddressSync(
165
+ [SEED_JLP_VAULT_BUFFER],
166
+ programId
167
+ );
168
+ pdaCache.set(key, cached);
169
+ }
170
+ return cached;
171
+ }
172
+ function deriveStvPda(baseMint, programId) {
173
+ const key = `stv:${baseMint.toBase58()}:${programId.toBase58()}`;
174
+ let cached = pdaCache.get(key);
175
+ if (!cached) {
176
+ cached = import_web32.PublicKey.findProgramAddressSync(
177
+ [SEED_STV_BUFFER, baseMint.toBuffer()],
178
+ programId
179
+ );
180
+ pdaCache.set(key, cached);
181
+ }
182
+ return cached;
183
+ }
184
+ function clearPdaCache() {
185
+ pdaCache.clear();
186
+ }
187
+
188
+ // src/accounts/vault.ts
189
+ var import_web33 = require("@solana/web3.js");
190
+ var import_anchor = require("@coral-xyz/anchor");
191
+ var JLP_VAULT_DATA_SIZE = 464;
192
+ var JLP_VAULT_ACCOUNT_SIZE = 8 + JLP_VAULT_DATA_SIZE;
193
+ var JLP_VAULT_DISCRIMINATOR = Buffer.from([
194
+ 41,
195
+ 108,
196
+ 189,
197
+ 168,
198
+ 199,
199
+ 152,
200
+ 221,
201
+ 119
202
+ ]);
203
+ function parseVault(data) {
204
+ if (data.length < JLP_VAULT_ACCOUNT_SIZE) {
205
+ throw new Error(
206
+ `Invalid JLPVault data size: expected ${JLP_VAULT_ACCOUNT_SIZE}, got ${data.length}`
207
+ );
208
+ }
209
+ const discriminator = data.subarray(0, 8);
210
+ if (!discriminator.equals(JLP_VAULT_DISCRIMINATOR)) {
211
+ throw new Error(
212
+ `Invalid JLPVault discriminator: expected ${JLP_VAULT_DISCRIMINATOR.toString("hex")}, got ${discriminator.toString("hex")}`
213
+ );
214
+ }
215
+ let offset = 8;
216
+ const admin = new import_web33.PublicKey(data.subarray(offset, offset + 32));
217
+ offset += 32;
218
+ const manager = new import_web33.PublicKey(data.subarray(offset, offset + 32));
219
+ offset += 32;
220
+ const feeReceiver = new import_web33.PublicKey(data.subarray(offset, offset + 32));
221
+ offset += 32;
222
+ const jlpMint = new import_web33.PublicKey(data.subarray(offset, offset + 32));
223
+ offset += 32;
224
+ const baseAssetMints = [];
225
+ for (let i = 0; i < 5; i++) {
226
+ baseAssetMints.push(new import_web33.PublicKey(data.subarray(offset, offset + 32)));
227
+ offset += 32;
228
+ }
229
+ const jlxAssetMints = [];
230
+ for (let i = 0; i < 5; i++) {
231
+ jlxAssetMints.push(new import_web33.PublicKey(data.subarray(offset, offset + 32)));
232
+ offset += 32;
233
+ }
234
+ const oracleStalenessThreshold = new import_anchor.BN(data.subarray(offset, offset + 8), "le");
235
+ offset += 8;
236
+ const flags = data.readUInt16LE(offset);
237
+ offset += 2;
238
+ const jlpSlippageBps = data.readUInt16LE(offset);
239
+ offset += 2;
240
+ const version = data.readUInt8(offset);
241
+ offset += 1;
242
+ const bump = data.readUInt8(offset);
243
+ offset += 1;
244
+ return {
245
+ admin,
246
+ manager,
247
+ feeReceiver,
248
+ jlpMint,
249
+ baseAssetMints,
250
+ jlxAssetMints,
251
+ oracleStalenessThreshold,
252
+ flags,
253
+ jlpSlippageBps,
254
+ version,
255
+ bump
256
+ };
257
+ }
258
+
259
+ // src/accounts/stv.ts
260
+ var import_web34 = require("@solana/web3.js");
261
+ var import_anchor2 = require("@coral-xyz/anchor");
262
+ var STV_DATA_SIZE = 160;
263
+ var STV_ACCOUNT_SIZE = 8 + STV_DATA_SIZE;
264
+ var STV_DISCRIMINATOR = Buffer.from([
265
+ 214,
266
+ 2,
267
+ 96,
268
+ 41,
269
+ 85,
270
+ 163,
271
+ 17,
272
+ 230
273
+ ]);
274
+ function parseStv(data) {
275
+ if (data.length < STV_ACCOUNT_SIZE) {
276
+ throw new Error(
277
+ `Invalid STV data size: expected ${STV_ACCOUNT_SIZE}, got ${data.length}`
278
+ );
279
+ }
280
+ const discriminator = data.subarray(0, 8);
281
+ if (!discriminator.equals(STV_DISCRIMINATOR)) {
282
+ throw new Error(
283
+ `Invalid STV discriminator: expected ${STV_DISCRIMINATOR.toString("hex")}, got ${discriminator.toString("hex")}`
284
+ );
285
+ }
286
+ let offset = 8;
287
+ const baseMint = new import_web34.PublicKey(data.subarray(offset, offset + 32));
288
+ offset += 32;
289
+ const jlMint = new import_web34.PublicKey(data.subarray(offset, offset + 32));
290
+ offset += 32;
291
+ const jvMint = new import_web34.PublicKey(data.subarray(offset, offset + 32));
292
+ offset += 32;
293
+ const pps = new import_anchor2.BN(data.subarray(offset, offset + 8), "le");
294
+ offset += 8;
295
+ const hwm = new import_anchor2.BN(data.subarray(offset, offset + 8), "le");
296
+ offset += 8;
297
+ const lastMgmtFeeTs = new import_anchor2.BN(data.subarray(offset, offset + 8), "le");
298
+ offset += 8;
299
+ const baseLoaned = new import_anchor2.BN(data.subarray(offset, offset + 8), "le");
300
+ offset += 8;
301
+ const accruedFeesJlx = new import_anchor2.BN(data.subarray(offset, offset + 8), "le");
302
+ offset += 8;
303
+ const maxDeposit = new import_anchor2.BN(data.subarray(offset, offset + 8), "le");
304
+ offset += 8;
305
+ const minDeposit = new import_anchor2.BN(data.subarray(offset, offset + 8), "le");
306
+ offset += 8;
307
+ const mgmtFeeBps = data.readUInt16LE(offset);
308
+ offset += 2;
309
+ const perfFeeBps = data.readUInt16LE(offset);
310
+ offset += 2;
311
+ const flags = data.readUInt16LE(offset);
312
+ offset += 2;
313
+ const version = data.readUInt8(offset);
314
+ offset += 1;
315
+ const bump = data.readUInt8(offset);
316
+ offset += 1;
317
+ return {
318
+ baseMint,
319
+ jlMint,
320
+ jvMint,
321
+ pps,
322
+ hwm,
323
+ lastMgmtFeeTs,
324
+ baseLoaned,
325
+ accruedFeesJlx,
326
+ maxDeposit,
327
+ minDeposit,
328
+ mgmtFeeBps,
329
+ perfFeeBps,
330
+ flags,
331
+ version,
332
+ bump
333
+ };
334
+ }
335
+
336
+ // src/utils/ata.ts
337
+ var import_spl_token2 = require("@solana/spl-token");
338
+ var ataCache = /* @__PURE__ */ new Map();
339
+ function deriveAta(mint, owner, allowPda = false) {
340
+ const key = `${mint.toBase58()}:${owner.toBase58()}:${allowPda}`;
341
+ let cached = ataCache.get(key);
342
+ if (!cached) {
343
+ cached = (0, import_spl_token2.getAssociatedTokenAddressSync)(mint, owner, allowPda);
344
+ ataCache.set(key, cached);
345
+ }
346
+ return cached;
347
+ }
348
+ function deriveUserAtas(baseMint, jvMint, userWallet) {
349
+ return {
350
+ baseAta: deriveAta(baseMint, userWallet, false),
351
+ jvxAta: deriveAta(jvMint, userWallet, false)
352
+ };
353
+ }
354
+ function deriveStvAtas(baseMint, jlxMint, stvPda) {
355
+ return {
356
+ baseAta: deriveAta(baseMint, stvPda, true),
357
+ jlxAta: deriveAta(jlxMint, stvPda, true)
358
+ };
359
+ }
360
+ function deriveVaultAtas(jlxMint, jlpMint, vaultPda) {
361
+ return {
362
+ stagingAta: deriveAta(jlxMint, vaultPda, true),
363
+ jlpAta: deriveAta(jlpMint, vaultPda, true)
364
+ };
365
+ }
366
+ function clearAtaCache() {
367
+ ataCache.clear();
368
+ }
369
+
370
+ // src/utils/math.ts
371
+ var import_anchor3 = require("@coral-xyz/anchor");
372
+ var PPS_DECIMALS_BN = new import_anchor3.BN(PPS_DECIMALS);
373
+ var EXCHANGE_RATE_PRECISION_BN = new import_anchor3.BN(EXCHANGE_RATE_PRECISION);
374
+ var EXCHANGE_RATE_PRECISION_BI = BigInt(EXCHANGE_RATE_PRECISION);
375
+ var RETURN_PERCENT_PRECISION = EXCHANGE_RATE_PRECISION_BI * 100n;
376
+ var SECONDS_PER_YEAR = BigInt(365 * 24 * 60 * 60);
377
+ var MAX_REWARDS_RATE = 50n * EXCHANGE_RATE_PRECISION_BI;
378
+ function calculateNav(stvBaseBalance, stvJlxBalance, exchangeRate, baseLoaned) {
379
+ const jlxValue = stvJlxBalance.mul(new import_anchor3.BN(exchangeRate.toString())).div(EXCHANGE_RATE_PRECISION_BN);
380
+ return stvBaseBalance.add(jlxValue).add(baseLoaned);
381
+ }
382
+ function calculatePps(nav, jvSupply) {
383
+ if (jvSupply.isZero()) {
384
+ return new import_anchor3.BN(PPS_DECIMALS);
385
+ }
386
+ return nav.mul(PPS_DECIMALS_BN).div(jvSupply);
387
+ }
388
+ function sharesToBase(shares, pps) {
389
+ if (pps.isZero()) {
390
+ throw new Error("Price per share cannot be zero");
391
+ }
392
+ return shares.mul(pps).div(PPS_DECIMALS_BN);
393
+ }
394
+ function baseToShares(base, pps) {
395
+ if (pps.isZero()) {
396
+ throw new Error("Price per share cannot be zero");
397
+ }
398
+ return base.mul(PPS_DECIMALS_BN).div(pps);
399
+ }
400
+ function jlxToBase(jlxAmount, exchangeRate) {
401
+ if (exchangeRate.isZero()) {
402
+ throw new Error("Exchange rate cannot be zero");
403
+ }
404
+ return jlxAmount.mul(exchangeRate).div(EXCHANGE_RATE_PRECISION_BN);
405
+ }
406
+ function baseToJlx(baseAmount, exchangeRate) {
407
+ if (exchangeRate.isZero()) {
408
+ throw new Error("Exchange rate cannot be zero");
409
+ }
410
+ return baseAmount.mul(EXCHANGE_RATE_PRECISION_BN).div(exchangeRate);
411
+ }
412
+ function calculateExchangeRate(storedRate, rewardsRate, currentTimestamp, lastUpdateTimestamp, fTokenTotalSupply) {
413
+ if (fTokenTotalSupply === 0n) {
414
+ return storedRate;
415
+ }
416
+ const totalAssets = storedRate * fTokenTotalSupply / EXCHANGE_RATE_PRECISION_BI;
417
+ if (totalAssets === 0n || rewardsRate === 0n) {
418
+ return storedRate;
419
+ }
420
+ const timeDiff = currentTimestamp - lastUpdateTimestamp;
421
+ if (timeDiff <= 0n) {
422
+ return storedRate;
423
+ }
424
+ const rate = rewardsRate * RETURN_PERCENT_PRECISION / totalAssets;
425
+ const cappedRate = rate > MAX_REWARDS_RATE ? MAX_REWARDS_RATE : rate;
426
+ const priceIncrease = storedRate * cappedRate * timeDiff / RETURN_PERCENT_PRECISION / SECONDS_PER_YEAR;
427
+ return storedRate + priceIncrease;
428
+ }
429
+
430
+ // src/jupiter/pools.ts
431
+ var import_web35 = require("@solana/web3.js");
432
+ var import_spl_token3 = require("@solana/spl-token");
433
+ var LENDING_ADMIN = new import_web35.PublicKey("5nmGjA4s7ATzpBQXC5RNceRpaJ7pYw2wKsNBWyuSAZV6");
434
+ var LIQUIDITY_PROGRAM_ID = new import_web35.PublicKey("jupeiUmn818Jg1ekPURTpr4mFo29p46vygyykFJ3wZC");
435
+ var LIQUIDITY_SINGLETON = new import_web35.PublicKey("7s1da8DduuBFqGra5bJBjpnvL5E9mGzCuMk1Qkh4or2Z");
436
+ var WSOL_POOL = {
437
+ mint: import_spl_token3.NATIVE_MINT,
438
+ name: "SOL",
439
+ lending: new import_web35.PublicKey("BeAqbxfrcXmzEYT2Ra62oW2MqkuFDHaCtps47Mzg6Zj3"),
440
+ fTokenMint: new import_web35.PublicKey("2uQsyo1fXXQkDtcpXnLofWy88PxcvnfH2L8FPSE62FVU"),
441
+ tokenReservesLiquidity: new import_web35.PublicKey("4Y66HtUEqbbbpZdENGtFdVhUMS3tnagffn3M4do59Nfy"),
442
+ supplyPositionOnLiquidity: new import_web35.PublicKey("4SkEYxmiRgQ4VYyvh9VB4k39M49BpqazyzDUFDzJhXQm"),
443
+ rewardsRateModel: new import_web35.PublicKey("CkeQGDRsgMZcCaU8cZEdC2aFAohia4jLzL36RaLcUDsR"),
444
+ vault: new import_web35.PublicKey("BWeWnEbVmYKLmUpcrAXGrvDYxVA7VBS6TEnNc74jTerw"),
445
+ rateModel: new import_web35.PublicKey("Acvyi9HBGmqh3Exe1N4PjBVyY8fokq2AdC6fSLqV6KSo"),
446
+ claimAccount: new import_web35.PublicKey("6AQGR8zK4KTVZfZ9UZaRzyEL5ynvwVaF5ywVdmtJT24N"),
447
+ decimals: 9,
448
+ stvIndex: 2 /* SOL */,
449
+ hasJupiterLend: true
450
+ };
451
+ var USDC_POOL = {
452
+ mint: MINTS.USDC,
453
+ name: "USDC",
454
+ lending: new import_web35.PublicKey("2vVYHYM8VYnvZqQWpTJSj8o8DBf1wM8pVs3bsTgYZiqJ"),
455
+ fTokenMint: new import_web35.PublicKey("9BEcn9aPEmhSPbPQeFGjidRiEKki46fVQDyPpSQXPA2D"),
456
+ tokenReservesLiquidity: new import_web35.PublicKey("94vK29npVbyRHXH63rRcTiSr26SFhrQTzbpNJuhQEDu"),
457
+ supplyPositionOnLiquidity: new import_web35.PublicKey("Hf9gtkM4dpVBahVSzEXSVCAPpKzBsBcns3s8As3z77oF"),
458
+ rewardsRateModel: new import_web35.PublicKey("5xSPBiD3TibamAnwHDhZABdB4z4F9dcj5PnbteroBTTd"),
459
+ vault: new import_web35.PublicKey("BmkUoKMFYBxNSzWXyUjyMJjMAaVz4d8ZnxwwmhDCUXFB"),
460
+ rateModel: new import_web35.PublicKey("5pjzT5dFTsXcwixoab1QDLvZQvpYJxJeBphkyfHGn688"),
461
+ claimAccount: new import_web35.PublicKey("HN1r4VfkDn53xQQfeGDYrNuDKFdemAhZsHYRwBrFhsW"),
462
+ decimals: 6,
463
+ stvIndex: 3 /* USDC */,
464
+ hasJupiterLend: true
465
+ };
466
+ var JUPUSD_POOL = {
467
+ mint: MINTS.JupUSD,
468
+ name: "JupUSD",
469
+ lending: new import_web35.PublicKey("papYEgeG5uPE4niUWZhihUUzVVotJn1mAWbYo2UBSHi"),
470
+ fTokenMint: new import_web35.PublicKey("7GxATsNMnaC88vdwd2t3mwrFuQwwGvmYPrUQ4D6FotXk"),
471
+ tokenReservesLiquidity: new import_web35.PublicKey("2tQE8jVR5ezDw3PDa21BNzfyQ14Ug5cTf6n3swJNjkod"),
472
+ supplyPositionOnLiquidity: new import_web35.PublicKey("DXFoJruECdEch2KpzLQ2cSpxoBSsyg4bpYPnHYofsbD4"),
473
+ rewardsRateModel: new import_web35.PublicKey("E3U32h49TL9Qof3NeLja9qJxTrGYpY1o1NQPtrSLJjcc"),
474
+ vault: new import_web35.PublicKey("9kGqd5zsQGaFfFPdUuEgbRM4V7x72Jdt7WTS4uRouAQ7"),
475
+ rateModel: new import_web35.PublicKey("2hT44GA9r5PiqsbbmqN5CuF7ymtquoEdokRncAs9CVej"),
476
+ claimAccount: new import_web35.PublicKey("6q9vTzAsTMEPUCwuhEdJSJdpRNXnubwKZbi2go1B8nvg"),
477
+ decimals: 6,
478
+ stvIndex: 4 /* JupUSD */,
479
+ hasJupiterLend: true
480
+ };
481
+ var WBTC_POOL = {
482
+ mint: MINTS.WBTC,
483
+ name: "BTC",
484
+ lending: import_web35.PublicKey.default,
485
+ fTokenMint: MINTS.WBTC,
486
+ // jlBTC = WBTC (base-only)
487
+ tokenReservesLiquidity: import_web35.PublicKey.default,
488
+ supplyPositionOnLiquidity: import_web35.PublicKey.default,
489
+ rewardsRateModel: import_web35.PublicKey.default,
490
+ vault: import_web35.PublicKey.default,
491
+ rateModel: import_web35.PublicKey.default,
492
+ claimAccount: import_web35.PublicKey.default,
493
+ decimals: 8,
494
+ stvIndex: 0 /* BTC */,
495
+ hasJupiterLend: false
496
+ };
497
+ var WETH_POOL = {
498
+ mint: MINTS.WETH,
499
+ name: "ETH",
500
+ lending: import_web35.PublicKey.default,
501
+ fTokenMint: MINTS.WETH,
502
+ // jlETH = WETH (base-only)
503
+ tokenReservesLiquidity: import_web35.PublicKey.default,
504
+ supplyPositionOnLiquidity: import_web35.PublicKey.default,
505
+ rewardsRateModel: import_web35.PublicKey.default,
506
+ vault: import_web35.PublicKey.default,
507
+ rateModel: import_web35.PublicKey.default,
508
+ claimAccount: import_web35.PublicKey.default,
509
+ decimals: 8,
510
+ stvIndex: 1 /* ETH */,
511
+ hasJupiterLend: false
512
+ };
513
+ var POOLS = {
514
+ SOL: WSOL_POOL,
515
+ USDC: USDC_POOL,
516
+ JupUSD: JUPUSD_POOL,
517
+ BTC: WBTC_POOL,
518
+ ETH: WETH_POOL
519
+ };
520
+ var POOLS_BY_MINT = new Map(
521
+ Object.values(POOLS).map((p) => [p.mint.toBase58(), p])
522
+ );
523
+ function getPoolByName(name) {
524
+ return POOLS[name];
525
+ }
526
+ function getPoolByMint(mint) {
527
+ return POOLS_BY_MINT.get(mint.toBase58());
528
+ }
529
+
530
+ // src/jupiter/lend.ts
531
+ var import_web36 = require("@solana/web3.js");
532
+ var import_spl_token4 = require("@solana/spl-token");
533
+ var JUPITER_LEND_PROGRAM_ID2 = new import_web36.PublicKey(
534
+ "jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9"
535
+ );
536
+ function buildExchangeRateAccounts(pool) {
537
+ if (!pool.hasJupiterLend) {
538
+ return null;
539
+ }
540
+ return {
541
+ lending: pool.lending,
542
+ rewardsRateModel: pool.rewardsRateModel
543
+ };
544
+ }
545
+ function buildJupEarnDepositAccounts(pool, stvPda, stvBaseAta, stvJlxAta) {
546
+ if (!pool.hasJupiterLend) {
547
+ throw new Error(`Pool ${pool.name} does not support Jupiter Lend`);
548
+ }
549
+ return [
550
+ { pubkey: stvPda, isSigner: false, isWritable: true },
551
+ { pubkey: stvBaseAta, isSigner: false, isWritable: true },
552
+ { pubkey: stvJlxAta, isSigner: false, isWritable: true },
553
+ { pubkey: pool.mint, isSigner: false, isWritable: false },
554
+ { pubkey: LENDING_ADMIN, isSigner: false, isWritable: false },
555
+ { pubkey: pool.lending, isSigner: false, isWritable: true },
556
+ { pubkey: pool.fTokenMint, isSigner: false, isWritable: true },
557
+ { pubkey: pool.tokenReservesLiquidity, isSigner: false, isWritable: true },
558
+ { pubkey: pool.supplyPositionOnLiquidity, isSigner: false, isWritable: true },
559
+ { pubkey: pool.rateModel, isSigner: false, isWritable: false },
560
+ { pubkey: pool.vault, isSigner: false, isWritable: true },
561
+ { pubkey: LIQUIDITY_SINGLETON, isSigner: false, isWritable: true },
562
+ { pubkey: LIQUIDITY_PROGRAM_ID, isSigner: false, isWritable: true },
563
+ { pubkey: pool.rewardsRateModel, isSigner: false, isWritable: false },
564
+ { pubkey: import_spl_token4.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
565
+ { pubkey: import_spl_token4.ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
566
+ { pubkey: import_web36.SystemProgram.programId, isSigner: false, isWritable: false },
567
+ { pubkey: JUPITER_LEND_PROGRAM_ID2, isSigner: false, isWritable: false }
568
+ ];
569
+ }
570
+ function buildJupEarnWithdrawAccounts(pool, stvPda, stvJlxAta, stvBaseAta) {
571
+ if (!pool.hasJupiterLend) {
572
+ throw new Error(`Pool ${pool.name} does not support Jupiter Lend`);
573
+ }
574
+ return [
575
+ { pubkey: stvPda, isSigner: false, isWritable: true },
576
+ { pubkey: stvJlxAta, isSigner: false, isWritable: true },
577
+ { pubkey: stvBaseAta, isSigner: false, isWritable: true },
578
+ { pubkey: LENDING_ADMIN, isSigner: false, isWritable: false },
579
+ { pubkey: pool.lending, isSigner: false, isWritable: true },
580
+ { pubkey: pool.mint, isSigner: false, isWritable: false },
581
+ { pubkey: pool.fTokenMint, isSigner: false, isWritable: true },
582
+ { pubkey: pool.tokenReservesLiquidity, isSigner: false, isWritable: true },
583
+ { pubkey: pool.supplyPositionOnLiquidity, isSigner: false, isWritable: true },
584
+ { pubkey: pool.rateModel, isSigner: false, isWritable: false },
585
+ { pubkey: pool.vault, isSigner: false, isWritable: true },
586
+ { pubkey: pool.claimAccount, isSigner: false, isWritable: true },
587
+ { pubkey: LIQUIDITY_SINGLETON, isSigner: false, isWritable: true },
588
+ { pubkey: LIQUIDITY_PROGRAM_ID, isSigner: false, isWritable: true },
589
+ { pubkey: pool.rewardsRateModel, isSigner: false, isWritable: false },
590
+ { pubkey: import_spl_token4.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
591
+ { pubkey: import_spl_token4.ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
592
+ { pubkey: import_web36.SystemProgram.programId, isSigner: false, isWritable: false },
593
+ { pubkey: JUPITER_LEND_PROGRAM_ID2, isSigner: false, isWritable: false }
594
+ ];
595
+ }
596
+ function parseLendingAccount(data) {
597
+ return {
598
+ mint: new import_web36.PublicKey(data.slice(8, 40)),
599
+ fTokenMint: new import_web36.PublicKey(data.slice(40, 72)),
600
+ lendingId: data.readUInt16LE(72),
601
+ decimals: data[74],
602
+ rewardsRateModel: new import_web36.PublicKey(data.slice(75, 107)),
603
+ liquidityExchangePrice: data.readBigUInt64LE(107),
604
+ tokenExchangePrice: data.readBigUInt64LE(115),
605
+ lastUpdateTimestamp: data.readBigUInt64LE(123),
606
+ tokenReservesLiquidity: new import_web36.PublicKey(data.slice(131, 163)),
607
+ supplyPositionOnLiquidity: new import_web36.PublicKey(data.slice(163, 195)),
608
+ bump: data[195]
609
+ };
610
+ }
611
+ function parseRewardsRateModel(data) {
612
+ return {
613
+ mint: new import_web36.PublicKey(data.slice(8, 40)),
614
+ startTvl: data.readBigUInt64LE(40),
615
+ duration: data.readBigUInt64LE(48),
616
+ startTime: data.readBigUInt64LE(56),
617
+ yearlyReward: data.readBigUInt64LE(64),
618
+ nextDuration: data.readBigUInt64LE(72),
619
+ nextRewardAmount: data.readBigUInt64LE(80),
620
+ bump: data[88]
621
+ };
622
+ }
623
+
624
+ // src/jupiter/swap.ts
625
+ var import_web37 = require("@solana/web3.js");
626
+ var JUPITER_API_BASE = "https://lite-api.jup.ag/swap/v1";
627
+ var DEFAULT_TIMEOUT_MS = 3e4;
628
+ var MAX_RETRIES = 3;
629
+ var RETRY_DELAY_MS = 1e3;
630
+ function sleep(ms) {
631
+ return new Promise((resolve) => setTimeout(resolve, ms));
632
+ }
633
+ async function fetchWithRetry(url, options = {}, timeoutMs = DEFAULT_TIMEOUT_MS, retries = MAX_RETRIES) {
634
+ let lastError = null;
635
+ for (let attempt = 0; attempt < retries; attempt++) {
636
+ try {
637
+ const controller = new AbortController();
638
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
639
+ const response = await fetch(url, {
640
+ ...options,
641
+ signal: controller.signal
642
+ });
643
+ clearTimeout(timeoutId);
644
+ if (response.ok) {
645
+ return response;
646
+ }
647
+ if (response.status >= 400 && response.status < 500) {
648
+ const errorText = await response.text();
649
+ throw new Error(`Jupiter API error (${response.status}): ${errorText}`);
650
+ }
651
+ lastError = new Error(`Jupiter API returned ${response.status}`);
652
+ } catch (error) {
653
+ if (error instanceof Error) {
654
+ if (error.name === "AbortError") {
655
+ lastError = new Error(`Request timed out after ${timeoutMs}ms`);
656
+ } else {
657
+ lastError = error;
658
+ }
659
+ }
660
+ }
661
+ if (attempt < retries - 1) {
662
+ await sleep(RETRY_DELAY_MS * (attempt + 1));
663
+ }
664
+ }
665
+ throw lastError ?? new Error("Unknown error during fetch");
666
+ }
667
+ async function getJupiterQuote(inputMint, outputMint, amount, slippageBps = 50, maxAccounts = 40) {
668
+ const params = new URLSearchParams({
669
+ inputMint: inputMint.toBase58(),
670
+ outputMint: outputMint.toBase58(),
671
+ amount: amount.toString(),
672
+ slippageBps: slippageBps.toString(),
673
+ maxAccounts: maxAccounts.toString()
674
+ });
675
+ const url = `${JUPITER_API_BASE}/quote?${params.toString()}`;
676
+ const response = await fetchWithRetry(url);
677
+ const data = await response.json();
678
+ if (data.error) {
679
+ throw new Error(`Jupiter quote error: ${data.error}`);
680
+ }
681
+ return data;
682
+ }
683
+ async function getJupiterSwapInstructions(quote, userPubkey) {
684
+ const url = `${JUPITER_API_BASE}/swap-instructions`;
685
+ const body = {
686
+ quoteResponse: quote,
687
+ userPublicKey: userPubkey.toBase58(),
688
+ wrapAndUnwrapSol: true,
689
+ useSharedAccounts: true,
690
+ dynamicComputeUnitLimit: true,
691
+ skipUserAccountsRpcCalls: false
692
+ };
693
+ const response = await fetchWithRetry(url, {
694
+ method: "POST",
695
+ headers: { "Content-Type": "application/json" },
696
+ body: JSON.stringify(body)
697
+ });
698
+ const data = await response.json();
699
+ if (data.error) {
700
+ throw new Error(`Jupiter swap instructions error: ${data.error}`);
701
+ }
702
+ return data;
703
+ }
704
+ function parseSwapRemainingAccounts(swapInstruction) {
705
+ return swapInstruction.accounts.map((acc) => ({
706
+ pubkey: new import_web37.PublicKey(acc.pubkey),
707
+ isSigner: acc.isSigner,
708
+ isWritable: acc.isWritable
709
+ }));
710
+ }
711
+ async function fetchAddressLookupTables(connection, addresses) {
712
+ if (addresses.length === 0) {
713
+ return [];
714
+ }
715
+ const pubkeys = addresses.map((addr) => new import_web37.PublicKey(addr));
716
+ const accountInfos = await connection.getMultipleAccountsInfo(pubkeys);
717
+ const tables = [];
718
+ for (let i = 0; i < accountInfos.length; i++) {
719
+ const info = accountInfos[i];
720
+ if (info === null) {
721
+ console.warn(`ALT not found: ${addresses[i]}`);
722
+ continue;
723
+ }
724
+ const table = new import_web37.AddressLookupTableAccount({
725
+ key: pubkeys[i],
726
+ state: import_web37.AddressLookupTableAccount.deserialize(info.data)
727
+ });
728
+ tables.push(table);
729
+ }
730
+ return tables;
731
+ }
732
+ async function buildSwapData(connection, inputMint, outputMint, amount, userPubkey, slippageBps = 50, maxAccounts = 40) {
733
+ const quote = await getJupiterQuote(
734
+ inputMint,
735
+ outputMint,
736
+ amount,
737
+ slippageBps,
738
+ maxAccounts
739
+ );
740
+ const instructions = await getJupiterSwapInstructions(quote, userPubkey);
741
+ const remainingAccounts = parseSwapRemainingAccounts(instructions.swapInstruction);
742
+ const addressLookupTables = await fetchAddressLookupTables(
743
+ connection,
744
+ instructions.addressLookupTableAddresses
745
+ );
746
+ return {
747
+ quote,
748
+ instructions,
749
+ remainingAccounts,
750
+ addressLookupTables
751
+ };
752
+ }
753
+
754
+ // src/jupiter/price.ts
755
+ var import_anchor4 = require("@coral-xyz/anchor");
756
+ var DEFAULT_API_KEY = "9edc77aa-0be8-41cf-9264-907603c44150";
757
+ async function fetchJupiterPriceUsd(mint, apiKey = DEFAULT_API_KEY) {
758
+ const url = `https://api.jup.ag/price/v3?ids=${mint}`;
759
+ try {
760
+ const response = await fetch(url, {
761
+ headers: {
762
+ "x-api-key": apiKey
763
+ }
764
+ });
765
+ if (!response.ok) {
766
+ console.warn(`Jupiter Price API error: ${response.status}`);
767
+ return null;
768
+ }
769
+ const data = await response.json();
770
+ const priceData = data[mint];
771
+ if (!priceData?.usdPrice) {
772
+ console.warn(`No price data for ${mint}`);
773
+ return null;
774
+ }
775
+ return priceData.usdPrice;
776
+ } catch (error) {
777
+ console.warn(`Failed to fetch Jupiter price: ${error.message}`);
778
+ return null;
779
+ }
780
+ }
781
+ async function fetchJlpRate(jlpMint, fallbackPrice = 4.6, apiKey = DEFAULT_API_KEY) {
782
+ const priceUsd = await fetchJupiterPriceUsd(jlpMint, apiKey);
783
+ if (priceUsd === null) {
784
+ console.warn(`Using fallback JLP price: $${fallbackPrice}`);
785
+ return new import_anchor4.BN(Math.round(fallbackPrice * 1e8));
786
+ }
787
+ console.log(`JLP price: $${priceUsd.toFixed(4)} -> ${Math.round(priceUsd * 1e8)} (8 decimals)`);
788
+ return new import_anchor4.BN(Math.round(priceUsd * 1e8));
789
+ }
790
+
791
+ // src/instructions/admin.ts
792
+ var import_web38 = require("@solana/web3.js");
793
+ var INIT_OR_UPDATE_VAULT_DISCRIMINATOR = Buffer.from([
794
+ 91,
795
+ 101,
796
+ 110,
797
+ 100,
798
+ 105,
799
+ 110,
800
+ 103,
801
+ 93
802
+ ]);
803
+ var INITIALIZE_STV_DISCRIMINATOR = Buffer.from([
804
+ 105,
805
+ 110,
806
+ 105,
807
+ 116,
808
+ 95,
809
+ 115,
810
+ 116,
811
+ 118
812
+ ]);
813
+ var UPDATE_STV_DISCRIMINATOR = Buffer.from([
814
+ 117,
815
+ 112,
816
+ 100,
817
+ 95,
818
+ 115,
819
+ 116,
820
+ 118,
821
+ 0
822
+ ]);
823
+ function serializeOptionPubkey(value) {
824
+ if (value === null) {
825
+ return Buffer.from([0]);
826
+ }
827
+ return Buffer.concat([Buffer.from([1]), value.toBuffer()]);
828
+ }
829
+ function serializeOptionU64(value) {
830
+ if (value === null) {
831
+ return Buffer.from([0]);
832
+ }
833
+ const buf = Buffer.alloc(9);
834
+ buf.writeUInt8(1, 0);
835
+ buf.writeBigUInt64LE(BigInt(value.toString()), 1);
836
+ return buf;
837
+ }
838
+ function serializeU16(value) {
839
+ const buf = Buffer.alloc(2);
840
+ buf.writeUInt16LE(value, 0);
841
+ return buf;
842
+ }
843
+ function serializeU64(value) {
844
+ const buf = Buffer.alloc(8);
845
+ buf.writeBigUInt64LE(BigInt(value.toString()), 0);
846
+ return buf;
847
+ }
848
+ function createInitOrUpdateVaultInstruction(params, accounts, programId = JLPD_PROGRAM_ID) {
849
+ const data = Buffer.concat([
850
+ INIT_OR_UPDATE_VAULT_DISCRIMINATOR,
851
+ serializeOptionPubkey(params.jlpMint),
852
+ // baseAssetMints - Option<[Pubkey; 5]>
853
+ params.baseAssetMints ? Buffer.concat([Buffer.from([1]), ...params.baseAssetMints.map((p) => p.toBuffer())]) : Buffer.from([0]),
854
+ // jlxAssetMints - Option<[Pubkey; 5]>
855
+ params.jlxAssetMints ? Buffer.concat([Buffer.from([1]), ...params.jlxAssetMints.map((p) => p.toBuffer())]) : Buffer.from([0]),
856
+ serializeOptionPubkey(params.newAdmin),
857
+ serializeOptionPubkey(params.manager ?? null),
858
+ serializeOptionPubkey(params.feeReceiver ?? null),
859
+ params.flags !== void 0 ? Buffer.concat([Buffer.from([1]), serializeU16(params.flags)]) : Buffer.from([0]),
860
+ params.jlpSlippageBps !== void 0 ? Buffer.concat([Buffer.from([1]), serializeU16(params.jlpSlippageBps)]) : Buffer.from([0]),
861
+ serializeOptionU64(params.oracleStalenessThreshold)
862
+ ]);
863
+ const keys = [
864
+ { pubkey: accounts.admin, isSigner: true, isWritable: true },
865
+ { pubkey: accounts.jlpVault, isSigner: false, isWritable: true },
866
+ { pubkey: accounts.systemProgram, isSigner: false, isWritable: false }
867
+ ];
868
+ return new import_web38.TransactionInstruction({ keys, programId, data });
869
+ }
870
+ function createInitializeStvInstruction(params, accounts, programId = JLPD_PROGRAM_ID) {
871
+ const data = Buffer.concat([
872
+ INITIALIZE_STV_DISCRIMINATOR,
873
+ serializeU16(params.mgmtFeeBps),
874
+ serializeU16(params.perfFeeBps),
875
+ serializeU64(params.maxDeposit),
876
+ serializeU64(params.minDeposit)
877
+ ]);
878
+ const keys = [
879
+ { pubkey: accounts.admin, isSigner: true, isWritable: true },
880
+ { pubkey: accounts.jlpVault, isSigner: false, isWritable: false },
881
+ { pubkey: accounts.stv, isSigner: false, isWritable: true },
882
+ { pubkey: accounts.baseMint, isSigner: false, isWritable: false },
883
+ { pubkey: accounts.jlMint, isSigner: false, isWritable: false },
884
+ { pubkey: accounts.jvMint, isSigner: true, isWritable: true },
885
+ { pubkey: accounts.stvJlxAta, isSigner: false, isWritable: true },
886
+ { pubkey: accounts.systemProgram, isSigner: false, isWritable: false },
887
+ { pubkey: accounts.tokenProgram, isSigner: false, isWritable: false },
888
+ { pubkey: accounts.associatedTokenProgram, isSigner: false, isWritable: false },
889
+ { pubkey: accounts.rent, isSigner: false, isWritable: false }
890
+ ];
891
+ return new import_web38.TransactionInstruction({ keys, programId, data });
892
+ }
893
+ function createUpdateStvInstruction(params, accounts, programId = JLPD_PROGRAM_ID) {
894
+ const data = Buffer.concat([
895
+ UPDATE_STV_DISCRIMINATOR,
896
+ params.mgmtFeeBps !== void 0 ? Buffer.concat([Buffer.from([1]), serializeU16(params.mgmtFeeBps)]) : Buffer.from([0]),
897
+ params.perfFeeBps !== void 0 ? Buffer.concat([Buffer.from([1]), serializeU16(params.perfFeeBps)]) : Buffer.from([0]),
898
+ params.flags !== void 0 ? Buffer.concat([Buffer.from([1]), serializeU16(params.flags)]) : Buffer.from([0]),
899
+ params.maxDeposit !== void 0 ? Buffer.concat([Buffer.from([1]), serializeU64(params.maxDeposit)]) : Buffer.from([0]),
900
+ params.minDeposit !== void 0 ? Buffer.concat([Buffer.from([1]), serializeU64(params.minDeposit)]) : Buffer.from([0])
901
+ ]);
902
+ const keys = [
903
+ { pubkey: accounts.admin, isSigner: true, isWritable: false },
904
+ { pubkey: accounts.jlpVault, isSigner: false, isWritable: false },
905
+ { pubkey: accounts.stv, isSigner: false, isWritable: true }
906
+ ];
907
+ return new import_web38.TransactionInstruction({ keys, programId, data });
908
+ }
909
+
910
+ // src/instructions/user.ts
911
+ var import_web39 = require("@solana/web3.js");
912
+ var DEPOSIT_DISCRIMINATOR = Buffer.from([
913
+ 248,
914
+ 198,
915
+ 158,
916
+ 145,
917
+ 225,
918
+ 117,
919
+ 135,
920
+ 200
921
+ ]);
922
+ var WITHDRAW_DISCRIMINATOR = Buffer.from([
923
+ 183,
924
+ 18,
925
+ 70,
926
+ 156,
927
+ 148,
928
+ 109,
929
+ 161,
930
+ 34
931
+ ]);
932
+ function serializeU642(value) {
933
+ const buf = Buffer.alloc(8);
934
+ buf.writeBigUInt64LE(BigInt(value.toString()), 0);
935
+ return buf;
936
+ }
937
+ function createDepositInstruction(amount, accounts, remainingAccounts = [], programId = JLPD_PROGRAM_ID) {
938
+ const data = Buffer.concat([DEPOSIT_DISCRIMINATOR, serializeU642(amount)]);
939
+ const keys = [
940
+ { pubkey: accounts.user, isSigner: true, isWritable: true },
941
+ { pubkey: accounts.jlpVault, isSigner: false, isWritable: false },
942
+ { pubkey: accounts.stv, isSigner: false, isWritable: true },
943
+ { pubkey: accounts.baseMint, isSigner: false, isWritable: false },
944
+ { pubkey: accounts.jlMint, isSigner: false, isWritable: false },
945
+ { pubkey: accounts.jvMint, isSigner: false, isWritable: true },
946
+ { pubkey: accounts.userBaseAta, isSigner: false, isWritable: true },
947
+ { pubkey: accounts.userJvxAta, isSigner: false, isWritable: true },
948
+ { pubkey: accounts.stvBaseAta, isSigner: false, isWritable: true },
949
+ { pubkey: accounts.stvJlxAta, isSigner: false, isWritable: false },
950
+ { pubkey: accounts.tokenProgram, isSigner: false, isWritable: false },
951
+ ...remainingAccounts
952
+ ];
953
+ return new import_web39.TransactionInstruction({ keys, programId, data });
954
+ }
955
+ function createWithdrawInstruction(sharesToBurn, accounts, remainingAccounts = [], programId = JLPD_PROGRAM_ID) {
956
+ const data = Buffer.concat([WITHDRAW_DISCRIMINATOR, serializeU642(sharesToBurn)]);
957
+ const keys = [
958
+ { pubkey: accounts.user, isSigner: true, isWritable: true },
959
+ { pubkey: accounts.jlpVault, isSigner: false, isWritable: false },
960
+ { pubkey: accounts.stv, isSigner: false, isWritable: true },
961
+ { pubkey: accounts.baseMint, isSigner: false, isWritable: false },
962
+ { pubkey: accounts.jlMint, isSigner: false, isWritable: false },
963
+ { pubkey: accounts.jvMint, isSigner: false, isWritable: true },
964
+ { pubkey: accounts.userBaseAta, isSigner: false, isWritable: true },
965
+ { pubkey: accounts.userJvxAta, isSigner: false, isWritable: true },
966
+ { pubkey: accounts.stvBaseAta, isSigner: false, isWritable: true },
967
+ { pubkey: accounts.stvJlxAta, isSigner: false, isWritable: false },
968
+ { pubkey: accounts.tokenProgram, isSigner: false, isWritable: false },
969
+ ...remainingAccounts
970
+ ];
971
+ return new import_web39.TransactionInstruction({ keys, programId, data });
972
+ }
973
+
974
+ // src/instructions/manager.ts
975
+ var import_web310 = require("@solana/web3.js");
976
+ var JUP_EARN_DISCRIMINATOR = Buffer.from([
977
+ 161,
978
+ 178,
979
+ 195,
980
+ 212,
981
+ 229,
982
+ 246,
983
+ 7,
984
+ 24
985
+ ]);
986
+ var MOVE_STV_DISCRIMINATOR = Buffer.from([
987
+ 41,
988
+ 58,
989
+ 75,
990
+ 92,
991
+ 109,
992
+ 126,
993
+ 143,
994
+ 144
995
+ ]);
996
+ var SWAP_JLX_JLX_DISCRIMINATOR = Buffer.from([
997
+ 65,
998
+ 82,
999
+ 99,
1000
+ 116,
1001
+ 133,
1002
+ 150,
1003
+ 167,
1004
+ 184
1005
+ ]);
1006
+ var SWAP_JLX_JLP_DISCRIMINATOR = Buffer.from([
1007
+ 201,
1008
+ 218,
1009
+ 235,
1010
+ 252,
1011
+ 13,
1012
+ 30,
1013
+ 47,
1014
+ 48
1015
+ ]);
1016
+ var SETTLE_YIELD_DISCRIMINATOR = Buffer.from([
1017
+ 81,
1018
+ 98,
1019
+ 115,
1020
+ 132,
1021
+ 149,
1022
+ 166,
1023
+ 183,
1024
+ 200
1025
+ ]);
1026
+ function serializeU8(value) {
1027
+ const buf = Buffer.alloc(1);
1028
+ buf.writeUInt8(value, 0);
1029
+ return buf;
1030
+ }
1031
+ function serializeU643(value) {
1032
+ const buf = Buffer.alloc(8);
1033
+ buf.writeBigUInt64LE(BigInt(value.toString()), 0);
1034
+ return buf;
1035
+ }
1036
+ function createJupEarnInstruction(params, accounts, remainingAccounts = [], programId = JLPD_PROGRAM_ID) {
1037
+ const directionByte = params.direction === "Deposit" ? 0 : 1;
1038
+ const data = Buffer.concat([
1039
+ JUP_EARN_DISCRIMINATOR,
1040
+ serializeU8(directionByte),
1041
+ serializeU643(params.amount)
1042
+ ]);
1043
+ const keys = [
1044
+ { pubkey: accounts.manager, isSigner: true, isWritable: false },
1045
+ { pubkey: accounts.jlpVault, isSigner: false, isWritable: false },
1046
+ { pubkey: accounts.stv, isSigner: false, isWritable: false },
1047
+ { pubkey: accounts.baseMint, isSigner: false, isWritable: false },
1048
+ { pubkey: accounts.jlMint, isSigner: false, isWritable: true },
1049
+ { pubkey: accounts.stvBaseAta, isSigner: false, isWritable: true },
1050
+ { pubkey: accounts.stvJlxAta, isSigner: false, isWritable: true },
1051
+ { pubkey: accounts.tokenProgram, isSigner: false, isWritable: false },
1052
+ ...remainingAccounts
1053
+ ];
1054
+ return new import_web310.TransactionInstruction({ keys, programId, data });
1055
+ }
1056
+ function createMoveJlxInstruction(params, accounts, remainingAccounts = [], programId = JLPD_PROGRAM_ID) {
1057
+ const directionByte = params.direction === "ToVault" ? 0 : 1;
1058
+ const data = Buffer.concat([
1059
+ MOVE_STV_DISCRIMINATOR,
1060
+ serializeU643(params.amountJlx),
1061
+ serializeU8(directionByte)
1062
+ ]);
1063
+ const keys = [
1064
+ { pubkey: accounts.manager, isSigner: true, isWritable: false },
1065
+ { pubkey: accounts.jlpVault, isSigner: false, isWritable: false },
1066
+ { pubkey: accounts.stv, isSigner: false, isWritable: true },
1067
+ { pubkey: accounts.baseMint, isSigner: false, isWritable: false },
1068
+ { pubkey: accounts.jlMint, isSigner: false, isWritable: false },
1069
+ { pubkey: accounts.stvJlxAta, isSigner: false, isWritable: true },
1070
+ { pubkey: accounts.vaultStagingAta, isSigner: false, isWritable: true },
1071
+ { pubkey: accounts.tokenProgram, isSigner: false, isWritable: false },
1072
+ ...remainingAccounts
1073
+ ];
1074
+ return new import_web310.TransactionInstruction({ keys, programId, data });
1075
+ }
1076
+ function createSwapJlxJlxInstruction(params, accounts, remainingAccounts = [], programId = JLPD_PROGRAM_ID) {
1077
+ const lenBuf = Buffer.alloc(4);
1078
+ lenBuf.writeUInt32LE(params.jupiterData.length, 0);
1079
+ const data = Buffer.concat([
1080
+ SWAP_JLX_JLX_DISCRIMINATOR,
1081
+ serializeU8(params.fromIndex),
1082
+ serializeU8(params.toIndex),
1083
+ serializeU643(params.amountIn),
1084
+ serializeU643(params.minOut),
1085
+ lenBuf,
1086
+ params.jupiterData
1087
+ ]);
1088
+ const keys = [
1089
+ { pubkey: accounts.manager, isSigner: true, isWritable: false },
1090
+ { pubkey: accounts.jlpVault, isSigner: false, isWritable: false },
1091
+ { pubkey: accounts.fromJlxMint, isSigner: false, isWritable: false },
1092
+ { pubkey: accounts.toJlxMint, isSigner: false, isWritable: false },
1093
+ { pubkey: accounts.fromJlxAta, isSigner: false, isWritable: true },
1094
+ { pubkey: accounts.toJlxAta, isSigner: false, isWritable: true },
1095
+ { pubkey: accounts.tokenProgram, isSigner: false, isWritable: false },
1096
+ { pubkey: accounts.jupiterProgram, isSigner: false, isWritable: false },
1097
+ ...remainingAccounts
1098
+ ];
1099
+ return new import_web310.TransactionInstruction({ keys, programId, data });
1100
+ }
1101
+ function createSwapJlxJlpInstruction(params, accounts, remainingAccounts = [], programId = JLPD_PROGRAM_ID) {
1102
+ const directionByte = params.direction === "JlxToJlp" ? 0 : 1;
1103
+ const lenBuf = Buffer.alloc(4);
1104
+ lenBuf.writeUInt32LE(params.jupiterData.length, 0);
1105
+ const data = Buffer.concat([
1106
+ SWAP_JLX_JLP_DISCRIMINATOR,
1107
+ serializeU8(params.stvIndex),
1108
+ serializeU8(directionByte),
1109
+ serializeU643(params.amountIn),
1110
+ serializeU643(params.expectedAmountOut),
1111
+ lenBuf,
1112
+ params.jupiterData
1113
+ ]);
1114
+ const keys = [
1115
+ { pubkey: accounts.manager, isSigner: true, isWritable: false },
1116
+ { pubkey: accounts.jlpVault, isSigner: false, isWritable: false },
1117
+ { pubkey: accounts.vaultJlxAta, isSigner: false, isWritable: true },
1118
+ { pubkey: accounts.vaultJlpAta, isSigner: false, isWritable: true },
1119
+ { pubkey: accounts.jlpMint, isSigner: false, isWritable: false },
1120
+ { pubkey: accounts.tokenProgram, isSigner: false, isWritable: false },
1121
+ { pubkey: accounts.jupiterProgram, isSigner: false, isWritable: false },
1122
+ ...remainingAccounts
1123
+ ];
1124
+ return new import_web310.TransactionInstruction({ keys, programId, data });
1125
+ }
1126
+ function createSettleYieldInstruction(params, accounts, remainingAccounts = [], programId = JLPD_PROGRAM_ID) {
1127
+ const data = Buffer.concat([
1128
+ SETTLE_YIELD_DISCRIMINATOR,
1129
+ serializeU643(params.jlpRate)
1130
+ ]);
1131
+ const keys = [
1132
+ { pubkey: accounts.manager, isSigner: true, isWritable: false },
1133
+ { pubkey: accounts.jlpVault, isSigner: false, isWritable: true },
1134
+ { pubkey: accounts.vaultJlpAta, isSigner: false, isWritable: false },
1135
+ { pubkey: accounts.jlpMint, isSigner: false, isWritable: false },
1136
+ { pubkey: accounts.stvBtc, isSigner: false, isWritable: true },
1137
+ { pubkey: accounts.stvEth, isSigner: false, isWritable: true },
1138
+ { pubkey: accounts.stvSol, isSigner: false, isWritable: true },
1139
+ { pubkey: accounts.stvUsdc, isSigner: false, isWritable: true },
1140
+ { pubkey: accounts.stvJupusd, isSigner: false, isWritable: true },
1141
+ { pubkey: accounts.stagingBtc, isSigner: false, isWritable: false },
1142
+ { pubkey: accounts.stagingEth, isSigner: false, isWritable: false },
1143
+ { pubkey: accounts.stagingSol, isSigner: false, isWritable: false },
1144
+ { pubkey: accounts.stagingUsdc, isSigner: false, isWritable: false },
1145
+ { pubkey: accounts.stagingJupusd, isSigner: false, isWritable: false },
1146
+ { pubkey: accounts.oracleBtc, isSigner: false, isWritable: false },
1147
+ { pubkey: accounts.oracleEth, isSigner: false, isWritable: false },
1148
+ { pubkey: accounts.oracleSol, isSigner: false, isWritable: false },
1149
+ { pubkey: accounts.oracleJlp, isSigner: false, isWritable: false },
1150
+ ...remainingAccounts
1151
+ ];
1152
+ return new import_web310.TransactionInstruction({ keys, programId, data });
1153
+ }
1154
+
1155
+ // src/instructions/fees.ts
1156
+ var import_web311 = require("@solana/web3.js");
1157
+ var CLAIM_FEES_DISCRIMINATOR = Buffer.from([
1158
+ 209,
1159
+ 226,
1160
+ 243,
1161
+ 4,
1162
+ 21,
1163
+ 38,
1164
+ 55,
1165
+ 72
1166
+ ]);
1167
+ function createClaimFeesInstruction(accounts, remainingAccounts = [], programId = JLPD_PROGRAM_ID) {
1168
+ const data = CLAIM_FEES_DISCRIMINATOR;
1169
+ const keys = [
1170
+ { pubkey: accounts.manager, isSigner: true, isWritable: false },
1171
+ { pubkey: accounts.jlpVault, isSigner: false, isWritable: false },
1172
+ { pubkey: accounts.stv, isSigner: false, isWritable: true },
1173
+ { pubkey: accounts.baseMint, isSigner: false, isWritable: false },
1174
+ { pubkey: accounts.jlMint, isSigner: false, isWritable: false },
1175
+ { pubkey: accounts.jvMint, isSigner: false, isWritable: false },
1176
+ { pubkey: accounts.stvBaseAta, isSigner: false, isWritable: false },
1177
+ { pubkey: accounts.stvJlxAta, isSigner: false, isWritable: true },
1178
+ { pubkey: accounts.feeReceiverJlxAta, isSigner: false, isWritable: true },
1179
+ { pubkey: accounts.tokenProgram, isSigner: false, isWritable: false },
1180
+ ...remainingAccounts
1181
+ ];
1182
+ return new import_web311.TransactionInstruction({ keys, programId, data });
1183
+ }
1184
+
1185
+ // src/client.ts
1186
+ var JlpdClientError = class extends Error {
1187
+ constructor(message) {
1188
+ super(message);
1189
+ this.name = "JlpdClientError";
1190
+ }
1191
+ };
1192
+ var JlpdClient = class _JlpdClient {
1193
+ constructor(connection, programId = JLPD_PROGRAM_ID) {
1194
+ // Cache for PoolContext instances (avoids re-deriving PDAs/ATAs)
1195
+ this.poolContextCache = /* @__PURE__ */ new Map();
1196
+ this.connection = connection;
1197
+ this.programId = programId;
1198
+ const [vaultPda, vaultBump] = deriveVaultPda(programId);
1199
+ this.vaultPda = vaultPda;
1200
+ this.vaultBump = vaultBump;
1201
+ }
1202
+ static mainnet(connection) {
1203
+ return new _JlpdClient(connection, JLPD_PROGRAM_ID);
1204
+ }
1205
+ static devnet(connection) {
1206
+ const devnetProgramId = new import_web312.PublicKey(
1207
+ "AcVcAihjB9Z3Lg3ZiboWxni2sTzXUrrsF3unGX4ntn6p"
1208
+ );
1209
+ return new _JlpdClient(connection, devnetProgramId);
1210
+ }
1211
+ // Fetch vault account
1212
+ async fetchVault() {
1213
+ const accountInfo = await this.connection.getAccountInfo(this.vaultPda);
1214
+ if (!accountInfo) return null;
1215
+ return parseVault(accountInfo.data);
1216
+ }
1217
+ // Fetch STV by base mint
1218
+ async fetchStv(baseMint) {
1219
+ const [stvPda] = deriveStvPda(baseMint, this.programId);
1220
+ const accountInfo = await this.connection.getAccountInfo(stvPda);
1221
+ if (!accountInfo) return null;
1222
+ return parseStv(accountInfo.data);
1223
+ }
1224
+ // Fetch exchange rate for a pool
1225
+ async fetchExchangeRate(poolName) {
1226
+ const pool = getPoolByName(poolName);
1227
+ if (!pool) throw new JlpdClientError(`Unknown pool: ${poolName}`);
1228
+ if (!pool.hasJupiterLend) {
1229
+ return {
1230
+ rate: 1,
1231
+ rawRate: BigInt(EXCHANGE_RATE_PRECISION),
1232
+ storedRate: 1,
1233
+ staleness: 0,
1234
+ isFresh: true
1235
+ };
1236
+ }
1237
+ const accounts = await this.connection.getMultipleAccountsInfo([
1238
+ pool.lending,
1239
+ pool.rewardsRateModel,
1240
+ pool.fTokenMint
1241
+ ]);
1242
+ const [lendingInfo, rewardsInfo, mintInfo] = accounts;
1243
+ if (!lendingInfo || !rewardsInfo || !mintInfo) {
1244
+ throw new JlpdClientError("Failed to fetch Jupiter Lend accounts");
1245
+ }
1246
+ const lendingData = parseLendingAccount(lendingInfo.data);
1247
+ const rewardsData = parseRewardsRateModel(rewardsInfo.data);
1248
+ const slot = await this.connection.getSlot();
1249
+ const timestamp = await this.connection.getBlockTime(slot);
1250
+ if (!timestamp) throw new JlpdClientError("Failed to get block time");
1251
+ const supply = mintInfo.data.readBigUInt64LE(36);
1252
+ const rawRate = calculateExchangeRate(
1253
+ lendingData.tokenExchangePrice,
1254
+ rewardsData.yearlyReward,
1255
+ BigInt(timestamp),
1256
+ lendingData.lastUpdateTimestamp,
1257
+ supply
1258
+ );
1259
+ const rate = Number(rawRate) / EXCHANGE_RATE_PRECISION;
1260
+ const storedRate = Number(lendingData.tokenExchangePrice) / EXCHANGE_RATE_PRECISION;
1261
+ const staleness = timestamp - Number(lendingData.lastUpdateTimestamp);
1262
+ return {
1263
+ rate,
1264
+ rawRate,
1265
+ storedRate,
1266
+ staleness,
1267
+ isFresh: staleness < 300
1268
+ };
1269
+ }
1270
+ // Get pool context for pool-specific operations (cached)
1271
+ pool(poolNameOrMint) {
1272
+ const key = typeof poolNameOrMint === "string" ? poolNameOrMint : poolNameOrMint.toBase58();
1273
+ let ctx = this.poolContextCache.get(key);
1274
+ if (!ctx) {
1275
+ const pool = typeof poolNameOrMint === "string" ? getPoolByName(poolNameOrMint) : getPoolByMint(poolNameOrMint);
1276
+ if (!pool) throw new JlpdClientError(`Unknown pool: ${key}`);
1277
+ ctx = new PoolContext(this, pool);
1278
+ this.poolContextCache.set(key, ctx);
1279
+ if (typeof poolNameOrMint === "string") {
1280
+ this.poolContextCache.set(pool.mint.toBase58(), ctx);
1281
+ } else {
1282
+ this.poolContextCache.set(pool.name, ctx);
1283
+ }
1284
+ }
1285
+ return ctx;
1286
+ }
1287
+ // Get swap context for swap operations
1288
+ swap() {
1289
+ return new SwapContext(this);
1290
+ }
1291
+ // Get admin context for admin operations
1292
+ admin() {
1293
+ return new AdminContext(this);
1294
+ }
1295
+ // Build a versioned transaction
1296
+ async buildTransaction(payer, ixs, alts = []) {
1297
+ const { blockhash } = await this.connection.getLatestBlockhash("confirmed");
1298
+ const message = new import_web312.TransactionMessage({
1299
+ payerKey: payer,
1300
+ recentBlockhash: blockhash,
1301
+ instructions: ixs
1302
+ }).compileToV0Message(alts);
1303
+ return new import_web312.VersionedTransaction(message);
1304
+ }
1305
+ };
1306
+ var PoolContext = class {
1307
+ constructor(client, pool) {
1308
+ this.client = client;
1309
+ this.pool = pool;
1310
+ const [pda, bump] = deriveStvPda(pool.mint, client.programId);
1311
+ this.stvPda = pda;
1312
+ this.stvBump = bump;
1313
+ const vaultAtas = deriveVaultAtas(pool.fTokenMint, MINTS.JLP, client.vaultPda);
1314
+ this.vaultStagingAta = vaultAtas.stagingAta;
1315
+ this.vaultJlpAta = vaultAtas.jlpAta;
1316
+ const stvAtas = deriveStvAtas(pool.mint, pool.fTokenMint, this.stvPda);
1317
+ this.stvBaseAta = stvAtas.baseAta;
1318
+ this.stvJlxAta = stvAtas.jlxAta;
1319
+ }
1320
+ // Deposit base asset and receive jvX shares
1321
+ async deposit(params) {
1322
+ if (params.amount.isZero() || params.amount.isNeg()) {
1323
+ throw new JlpdClientError("Deposit amount must be positive");
1324
+ }
1325
+ const [stv, { blockhash }] = await Promise.all([
1326
+ this.client.fetchStv(this.pool.mint),
1327
+ this.client.connection.getLatestBlockhash("confirmed")
1328
+ ]);
1329
+ if (!stv) throw new JlpdClientError("STV not found");
1330
+ const userAtas = deriveUserAtas(this.pool.mint, stv.jvMint, params.user);
1331
+ const erAccounts = this.pool.hasJupiterLend ? buildExchangeRateAccounts(this.pool) : null;
1332
+ const ix = createDepositInstruction(
1333
+ params.amount,
1334
+ {
1335
+ user: params.user,
1336
+ jlpVault: this.client.vaultPda,
1337
+ stv: this.stvPda,
1338
+ baseMint: this.pool.mint,
1339
+ jlMint: this.pool.fTokenMint,
1340
+ jvMint: stv.jvMint,
1341
+ userBaseAta: userAtas.baseAta,
1342
+ userJvxAta: userAtas.jvxAta,
1343
+ stvBaseAta: this.stvBaseAta,
1344
+ stvJlxAta: this.stvJlxAta,
1345
+ tokenProgram: import_spl_token5.TOKEN_PROGRAM_ID
1346
+ },
1347
+ erAccounts ? [
1348
+ { pubkey: erAccounts.lending, isSigner: false, isWritable: false },
1349
+ { pubkey: erAccounts.rewardsRateModel, isSigner: false, isWritable: false }
1350
+ ] : [],
1351
+ this.client.programId
1352
+ );
1353
+ const message = new import_web312.TransactionMessage({
1354
+ payerKey: params.user,
1355
+ recentBlockhash: blockhash,
1356
+ instructions: [ix]
1357
+ }).compileToV0Message();
1358
+ return new import_web312.VersionedTransaction(message);
1359
+ }
1360
+ // Burn jvX shares and withdraw base asset
1361
+ async withdraw(params) {
1362
+ if (params.shares.isZero() || params.shares.isNeg()) {
1363
+ throw new JlpdClientError("Withdraw shares must be positive");
1364
+ }
1365
+ const [stv, { blockhash }] = await Promise.all([
1366
+ this.client.fetchStv(this.pool.mint),
1367
+ this.client.connection.getLatestBlockhash("confirmed")
1368
+ ]);
1369
+ if (!stv) throw new JlpdClientError("STV not found");
1370
+ const userAtas = deriveUserAtas(this.pool.mint, stv.jvMint, params.user);
1371
+ const erAccounts = this.pool.hasJupiterLend ? buildExchangeRateAccounts(this.pool) : null;
1372
+ const ix = createWithdrawInstruction(
1373
+ params.shares,
1374
+ {
1375
+ user: params.user,
1376
+ jlpVault: this.client.vaultPda,
1377
+ stv: this.stvPda,
1378
+ baseMint: this.pool.mint,
1379
+ jlMint: this.pool.fTokenMint,
1380
+ jvMint: stv.jvMint,
1381
+ userBaseAta: userAtas.baseAta,
1382
+ userJvxAta: userAtas.jvxAta,
1383
+ stvBaseAta: this.stvBaseAta,
1384
+ stvJlxAta: this.stvJlxAta,
1385
+ tokenProgram: import_spl_token5.TOKEN_PROGRAM_ID
1386
+ },
1387
+ erAccounts ? [
1388
+ { pubkey: erAccounts.lending, isSigner: false, isWritable: false },
1389
+ { pubkey: erAccounts.rewardsRateModel, isSigner: false, isWritable: false }
1390
+ ] : [],
1391
+ this.client.programId
1392
+ );
1393
+ const message = new import_web312.TransactionMessage({
1394
+ payerKey: params.user,
1395
+ recentBlockhash: blockhash,
1396
+ instructions: [ix]
1397
+ }).compileToV0Message();
1398
+ return new import_web312.VersionedTransaction(message);
1399
+ }
1400
+ // Jupiter Earn deposit/withdraw
1401
+ async jupEarn(params) {
1402
+ if (!this.pool.hasJupiterLend) {
1403
+ throw new JlpdClientError(`Pool ${this.pool.name} does not support Jupiter Earn`);
1404
+ }
1405
+ const remainingAccounts = params.direction === "Deposit" ? buildJupEarnDepositAccounts(this.pool, this.stvPda, this.stvBaseAta, this.stvJlxAta) : buildJupEarnWithdrawAccounts(this.pool, this.stvPda, this.stvJlxAta, this.stvBaseAta);
1406
+ const ix = createJupEarnInstruction(
1407
+ { direction: params.direction, amount: params.amount },
1408
+ {
1409
+ manager: params.manager,
1410
+ jlpVault: this.client.vaultPda,
1411
+ stv: this.stvPda,
1412
+ baseMint: this.pool.mint,
1413
+ jlMint: this.pool.fTokenMint,
1414
+ stvBaseAta: this.stvBaseAta,
1415
+ stvJlxAta: this.stvJlxAta,
1416
+ tokenProgram: import_spl_token5.TOKEN_PROGRAM_ID
1417
+ },
1418
+ remainingAccounts,
1419
+ this.client.programId
1420
+ );
1421
+ return this.client.buildTransaction(params.manager, [ix]);
1422
+ }
1423
+ // Move jlX between STV and vault
1424
+ async moveJlx(params) {
1425
+ const erAccounts = this.pool.hasJupiterLend ? buildExchangeRateAccounts(this.pool) : null;
1426
+ const ix = createMoveJlxInstruction(
1427
+ { amountJlx: params.jlxAmount, direction: params.direction },
1428
+ {
1429
+ manager: params.manager,
1430
+ jlpVault: this.client.vaultPda,
1431
+ stv: this.stvPda,
1432
+ baseMint: this.pool.mint,
1433
+ jlMint: this.pool.fTokenMint,
1434
+ stvJlxAta: this.stvJlxAta,
1435
+ vaultStagingAta: this.vaultStagingAta,
1436
+ tokenProgram: import_spl_token5.TOKEN_PROGRAM_ID
1437
+ },
1438
+ erAccounts ? [
1439
+ { pubkey: erAccounts.lending, isSigner: false, isWritable: false },
1440
+ { pubkey: erAccounts.rewardsRateModel, isSigner: false, isWritable: false }
1441
+ ] : [],
1442
+ this.client.programId
1443
+ );
1444
+ return this.client.buildTransaction(params.manager, [ix]);
1445
+ }
1446
+ // Claim fees
1447
+ async claimFees(params) {
1448
+ const [vault, stv] = await Promise.all([
1449
+ this.client.fetchVault(),
1450
+ this.client.fetchStv(this.pool.mint)
1451
+ ]);
1452
+ if (!vault) throw new JlpdClientError("Vault not found");
1453
+ if (!stv) throw new JlpdClientError("STV not found");
1454
+ const feeReceiverJlxAta = (0, import_spl_token5.getAssociatedTokenAddressSync)(
1455
+ this.pool.fTokenMint,
1456
+ vault.feeReceiver,
1457
+ true
1458
+ );
1459
+ const erAccounts = this.pool.hasJupiterLend ? buildExchangeRateAccounts(this.pool) : null;
1460
+ const ix = createClaimFeesInstruction(
1461
+ {
1462
+ manager: params.manager,
1463
+ jlpVault: this.client.vaultPda,
1464
+ stv: this.stvPda,
1465
+ baseMint: this.pool.mint,
1466
+ jlMint: this.pool.fTokenMint,
1467
+ jvMint: stv.jvMint,
1468
+ stvBaseAta: this.stvBaseAta,
1469
+ stvJlxAta: this.stvJlxAta,
1470
+ feeReceiverJlxAta,
1471
+ tokenProgram: import_spl_token5.TOKEN_PROGRAM_ID
1472
+ },
1473
+ erAccounts ? [
1474
+ { pubkey: erAccounts.lending, isSigner: false, isWritable: false },
1475
+ { pubkey: erAccounts.rewardsRateModel, isSigner: false, isWritable: false }
1476
+ ] : [],
1477
+ this.client.programId
1478
+ );
1479
+ return this.client.buildTransaction(params.manager, [ix]);
1480
+ }
1481
+ // Update STV parameters (admin only)
1482
+ async updateStv(params) {
1483
+ const ix = createUpdateStvInstruction(
1484
+ {
1485
+ mgmtFeeBps: params.mgmtFeeBps,
1486
+ perfFeeBps: params.perfFeeBps,
1487
+ flags: params.flags,
1488
+ maxDeposit: params.maxDeposit,
1489
+ minDeposit: params.minDeposit
1490
+ },
1491
+ {
1492
+ admin: params.admin,
1493
+ jlpVault: this.client.vaultPda,
1494
+ stv: this.stvPda
1495
+ },
1496
+ this.client.programId
1497
+ );
1498
+ return this.client.buildTransaction(params.admin, [ix]);
1499
+ }
1500
+ };
1501
+ var SwapContext = class {
1502
+ constructor(client) {
1503
+ this.client = client;
1504
+ }
1505
+ // Get a quote for jlX <-> JLP swap
1506
+ async quoteJlxJlp(params) {
1507
+ const poolConfig = getPoolByName(params.pool);
1508
+ if (!poolConfig) throw new JlpdClientError(`Unknown pool: ${params.pool}`);
1509
+ const inputMint = params.direction === "JlxToJlp" ? poolConfig.fTokenMint : MINTS.JLP;
1510
+ const outputMint = params.direction === "JlxToJlp" ? MINTS.JLP : poolConfig.fTokenMint;
1511
+ const quote = await getJupiterQuote(
1512
+ inputMint,
1513
+ outputMint,
1514
+ BigInt(params.amountIn.toString()),
1515
+ params.slippageBps ?? 30
1516
+ );
1517
+ const swapIxs = await getJupiterSwapInstructions(quote, this.client.vaultPda);
1518
+ const remainingAccounts = parseSwapRemainingAccounts(swapIxs.swapInstruction);
1519
+ const alts = await fetchAddressLookupTables(
1520
+ this.client.connection,
1521
+ swapIxs.addressLookupTableAddresses
1522
+ );
1523
+ return {
1524
+ inputMint,
1525
+ outputMint,
1526
+ inAmount: new import_anchor5.BN(quote.inAmount),
1527
+ outAmount: new import_anchor5.BN(quote.outAmount),
1528
+ minOutAmount: new import_anchor5.BN(quote.otherAmountThreshold),
1529
+ priceImpactPct: parseFloat(quote.priceImpactPct),
1530
+ route: quote.routePlan.map((r) => r.swapInfo.label || "unknown"),
1531
+ jupiterData: Buffer.from(swapIxs.swapInstruction.data, "base64"),
1532
+ remainingAccounts,
1533
+ addressLookupTables: alts,
1534
+ computeUnitLimit: swapIxs.computeUnitLimit ?? 6e5
1535
+ };
1536
+ }
1537
+ // Build jlX <-> JLP swap transaction
1538
+ async swapJlxJlp(params) {
1539
+ const poolConfig = getPoolByName(params.pool);
1540
+ if (!poolConfig) throw new JlpdClientError(`Unknown pool: ${params.pool}`);
1541
+ const poolCtx = this.client.pool(params.pool);
1542
+ const computeIx = import_web312.ComputeBudgetProgram.setComputeUnitLimit({
1543
+ units: params.quote.computeUnitLimit
1544
+ });
1545
+ const jupiterProgram = params.quote.remainingAccounts[0]?.pubkey ?? import_web312.PublicKey.default;
1546
+ const swapIx = createSwapJlxJlpInstruction(
1547
+ {
1548
+ stvIndex: poolConfig.stvIndex,
1549
+ direction: params.direction,
1550
+ amountIn: params.amountIn,
1551
+ expectedAmountOut: params.expectedOut,
1552
+ jupiterData: params.quote.jupiterData
1553
+ },
1554
+ {
1555
+ manager: params.manager,
1556
+ jlpVault: this.client.vaultPda,
1557
+ vaultJlxAta: poolCtx.vaultStagingAta,
1558
+ vaultJlpAta: poolCtx.vaultJlpAta,
1559
+ jlpMint: MINTS.JLP,
1560
+ tokenProgram: import_spl_token5.TOKEN_PROGRAM_ID,
1561
+ jupiterProgram
1562
+ },
1563
+ params.quote.remainingAccounts,
1564
+ this.client.programId
1565
+ );
1566
+ const { blockhash } = await this.client.connection.getLatestBlockhash("confirmed");
1567
+ const message = new import_web312.TransactionMessage({
1568
+ payerKey: params.manager,
1569
+ recentBlockhash: blockhash,
1570
+ instructions: [computeIx, swapIx]
1571
+ }).compileToV0Message(params.quote.addressLookupTables);
1572
+ return new import_web312.VersionedTransaction(message);
1573
+ }
1574
+ // Get a quote for jlX <-> jlX swap
1575
+ async quoteJlxJlx(params) {
1576
+ const fromPoolConfig = getPoolByName(params.fromPool);
1577
+ const toPoolConfig = getPoolByName(params.toPool);
1578
+ if (!fromPoolConfig) throw new JlpdClientError(`Unknown pool: ${params.fromPool}`);
1579
+ if (!toPoolConfig) throw new JlpdClientError(`Unknown pool: ${params.toPool}`);
1580
+ const inputMint = fromPoolConfig.fTokenMint;
1581
+ const outputMint = toPoolConfig.fTokenMint;
1582
+ const quote = await getJupiterQuote(
1583
+ inputMint,
1584
+ outputMint,
1585
+ BigInt(params.amountIn.toString()),
1586
+ params.slippageBps ?? 30
1587
+ );
1588
+ const swapIxs = await getJupiterSwapInstructions(quote, this.client.vaultPda);
1589
+ const remainingAccounts = parseSwapRemainingAccounts(swapIxs.swapInstruction);
1590
+ const alts = await fetchAddressLookupTables(
1591
+ this.client.connection,
1592
+ swapIxs.addressLookupTableAddresses
1593
+ );
1594
+ return {
1595
+ inputMint,
1596
+ outputMint,
1597
+ inAmount: new import_anchor5.BN(quote.inAmount),
1598
+ outAmount: new import_anchor5.BN(quote.outAmount),
1599
+ minOutAmount: new import_anchor5.BN(quote.otherAmountThreshold),
1600
+ priceImpactPct: parseFloat(quote.priceImpactPct),
1601
+ route: quote.routePlan.map((r) => r.swapInfo.label || "unknown"),
1602
+ jupiterData: Buffer.from(swapIxs.swapInstruction.data, "base64"),
1603
+ remainingAccounts,
1604
+ addressLookupTables: alts,
1605
+ computeUnitLimit: swapIxs.computeUnitLimit ?? 6e5
1606
+ };
1607
+ }
1608
+ // Build jlX <-> jlX swap transaction
1609
+ async swapJlxJlx(params) {
1610
+ const fromPoolConfig = getPoolByName(params.fromPool);
1611
+ const toPoolConfig = getPoolByName(params.toPool);
1612
+ if (!fromPoolConfig) throw new JlpdClientError(`Unknown pool: ${params.fromPool}`);
1613
+ if (!toPoolConfig) throw new JlpdClientError(`Unknown pool: ${params.toPool}`);
1614
+ const fromPoolCtx = this.client.pool(params.fromPool);
1615
+ const toPoolCtx = this.client.pool(params.toPool);
1616
+ const computeIx = import_web312.ComputeBudgetProgram.setComputeUnitLimit({
1617
+ units: params.quote.computeUnitLimit
1618
+ });
1619
+ const jupiterProgram = params.quote.remainingAccounts[0]?.pubkey ?? import_web312.PublicKey.default;
1620
+ const swapIx = createSwapJlxJlxInstruction(
1621
+ {
1622
+ fromIndex: fromPoolConfig.stvIndex,
1623
+ toIndex: toPoolConfig.stvIndex,
1624
+ amountIn: params.amountIn,
1625
+ minOut: params.minOut,
1626
+ jupiterData: params.quote.jupiterData
1627
+ },
1628
+ {
1629
+ manager: params.manager,
1630
+ jlpVault: this.client.vaultPda,
1631
+ fromJlxMint: fromPoolConfig.fTokenMint,
1632
+ toJlxMint: toPoolConfig.fTokenMint,
1633
+ fromJlxAta: fromPoolCtx.vaultStagingAta,
1634
+ toJlxAta: toPoolCtx.vaultStagingAta,
1635
+ tokenProgram: import_spl_token5.TOKEN_PROGRAM_ID,
1636
+ jupiterProgram
1637
+ },
1638
+ params.quote.remainingAccounts,
1639
+ this.client.programId
1640
+ );
1641
+ const { blockhash } = await this.client.connection.getLatestBlockhash("confirmed");
1642
+ const message = new import_web312.TransactionMessage({
1643
+ payerKey: params.manager,
1644
+ recentBlockhash: blockhash,
1645
+ instructions: [computeIx, swapIx]
1646
+ }).compileToV0Message(params.quote.addressLookupTables);
1647
+ return new import_web312.VersionedTransaction(message);
1648
+ }
1649
+ };
1650
+ var AdminContext = class {
1651
+ constructor(client) {
1652
+ this.client = client;
1653
+ }
1654
+ // Initialize or update vault
1655
+ async initOrUpdateVault(params) {
1656
+ const ix = createInitOrUpdateVaultInstruction(
1657
+ {
1658
+ jlpMint: params.jlpMint ?? null,
1659
+ baseAssetMints: params.baseAssetMints ?? null,
1660
+ jlxAssetMints: params.jlxAssetMints ?? null,
1661
+ newAdmin: params.newAdmin ?? null,
1662
+ manager: params.manager,
1663
+ feeReceiver: params.feeReceiver,
1664
+ flags: params.flags,
1665
+ jlpSlippageBps: params.jlpSlippageBps,
1666
+ oracleStalenessThreshold: params.oracleStalenessThreshold ?? null
1667
+ },
1668
+ {
1669
+ admin: params.admin,
1670
+ jlpVault: this.client.vaultPda,
1671
+ systemProgram: import_web312.SystemProgram.programId
1672
+ },
1673
+ this.client.programId
1674
+ );
1675
+ return this.client.buildTransaction(params.admin, [ix]);
1676
+ }
1677
+ // Initialize STV
1678
+ async initializeStv(params, jvMintKeypair) {
1679
+ const pool = getPoolByName(params.poolName);
1680
+ if (!pool) throw new JlpdClientError(`Unknown pool: ${params.poolName}`);
1681
+ const [stvPda] = deriveStvPda(pool.mint, this.client.programId);
1682
+ const stvJlxAta = (0, import_spl_token5.getAssociatedTokenAddressSync)(pool.fTokenMint, stvPda, true);
1683
+ const ix = createInitializeStvInstruction(
1684
+ {
1685
+ mgmtFeeBps: params.mgmtFeeBps,
1686
+ perfFeeBps: params.perfFeeBps,
1687
+ maxDeposit: params.maxDeposit,
1688
+ minDeposit: params.minDeposit
1689
+ },
1690
+ {
1691
+ admin: params.admin,
1692
+ jlpVault: this.client.vaultPda,
1693
+ stv: stvPda,
1694
+ baseMint: pool.mint,
1695
+ jlMint: pool.fTokenMint,
1696
+ jvMint: jvMintKeypair,
1697
+ stvJlxAta,
1698
+ systemProgram: import_web312.SystemProgram.programId,
1699
+ tokenProgram: import_spl_token5.TOKEN_PROGRAM_ID,
1700
+ associatedTokenProgram: import_spl_token5.ASSOCIATED_TOKEN_PROGRAM_ID,
1701
+ rent: import_web312.SYSVAR_RENT_PUBKEY
1702
+ },
1703
+ this.client.programId
1704
+ );
1705
+ return this.client.buildTransaction(params.admin, [ix]);
1706
+ }
1707
+ // Settle yield across all STVs
1708
+ async settleYield(params) {
1709
+ const poolNames = ["BTC", "ETH", "SOL", "USDC", "JupUSD"];
1710
+ const pools = poolNames.map((name) => {
1711
+ const pool = getPoolByName(name);
1712
+ if (!pool) throw new JlpdClientError(`Unknown pool: ${name}`);
1713
+ return pool;
1714
+ });
1715
+ const stvPdas = pools.map((p) => deriveStvPda(p.mint, this.client.programId)[0]);
1716
+ const stagingAtas = pools.map(
1717
+ (p) => (0, import_spl_token5.getAssociatedTokenAddressSync)(p.fTokenMint, this.client.vaultPda, true)
1718
+ );
1719
+ const lendingAccounts = pools.map((p) => ({
1720
+ pubkey: p.hasJupiterLend ? p.lending : import_web312.PublicKey.default,
1721
+ isSigner: false,
1722
+ isWritable: false
1723
+ }));
1724
+ const rewardsAccounts = pools.map((p) => ({
1725
+ pubkey: p.hasJupiterLend ? p.rewardsRateModel : import_web312.PublicKey.default,
1726
+ isSigner: false,
1727
+ isWritable: false
1728
+ }));
1729
+ const mintAccounts = pools.map((p) => ({
1730
+ pubkey: p.fTokenMint,
1731
+ isSigner: false,
1732
+ isWritable: false
1733
+ }));
1734
+ const remainingAccounts = [...lendingAccounts, ...rewardsAccounts, ...mintAccounts];
1735
+ const ix = createSettleYieldInstruction(
1736
+ { jlpRate: params.jlpRate },
1737
+ {
1738
+ manager: params.manager,
1739
+ jlpVault: this.client.vaultPda,
1740
+ vaultJlpAta: (0, import_spl_token5.getAssociatedTokenAddressSync)(MINTS.JLP, this.client.vaultPda, true),
1741
+ jlpMint: MINTS.JLP,
1742
+ stvBtc: stvPdas[0],
1743
+ stvEth: stvPdas[1],
1744
+ stvSol: stvPdas[2],
1745
+ stvUsdc: stvPdas[3],
1746
+ stvJupusd: stvPdas[4],
1747
+ stagingBtc: stagingAtas[0],
1748
+ stagingEth: stagingAtas[1],
1749
+ stagingSol: stagingAtas[2],
1750
+ stagingUsdc: stagingAtas[3],
1751
+ stagingJupusd: stagingAtas[4],
1752
+ oracleBtc: ORACLES.DOVES_BTC_USD,
1753
+ oracleEth: ORACLES.DOVES_ETH_USD,
1754
+ oracleSol: ORACLES.DOVES_SOL_USD,
1755
+ oracleJlp: ORACLES.PYTH_JLP_USD
1756
+ },
1757
+ remainingAccounts,
1758
+ this.client.programId
1759
+ );
1760
+ return this.client.buildTransaction(params.manager, [ix]);
1761
+ }
1762
+ };
1763
+ // Annotate the CommonJS export names for ESM import in node:
1764
+ 0 && (module.exports = {
1765
+ AdminContext,
1766
+ EXCHANGE_RATE_PRECISION,
1767
+ FLAG_DEPOSITS_DISABLED,
1768
+ FLAG_JLP_DISABLED,
1769
+ FLAG_PAUSED,
1770
+ FLAG_REBALANCE_DISABLED,
1771
+ FLAG_WITHDRAWALS_DISABLED,
1772
+ JLPD_PROGRAM_ID,
1773
+ JLP_VAULT_ACCOUNT_SIZE,
1774
+ JLP_VAULT_DATA_SIZE,
1775
+ JLP_VAULT_DISCRIMINATOR,
1776
+ JUPITER_LEND_PROGRAM_ID,
1777
+ JUPITER_SWAP_PROGRAM_ID,
1778
+ JUPUSD_POOL,
1779
+ JUP_LEND_PROGRAM_ID,
1780
+ JlpdClient,
1781
+ JlpdClientError,
1782
+ LENDING_ADMIN,
1783
+ LIQUIDITY_PROGRAM_ID,
1784
+ LIQUIDITY_SINGLETON,
1785
+ MINTS,
1786
+ ORACLES,
1787
+ POOLS,
1788
+ PPS_DECIMALS,
1789
+ PoolContext,
1790
+ SEED_JLP_VAULT,
1791
+ SEED_STV,
1792
+ STV_ACCOUNT_SIZE,
1793
+ STV_DATA_SIZE,
1794
+ STV_DISCRIMINATOR,
1795
+ STV_INDEX,
1796
+ SwapContext,
1797
+ USDC_POOL,
1798
+ WBTC_POOL,
1799
+ WETH_POOL,
1800
+ WSOL_POOL,
1801
+ baseToJlx,
1802
+ baseToShares,
1803
+ buildExchangeRateAccounts,
1804
+ buildJupEarnDepositAccounts,
1805
+ buildJupEarnWithdrawAccounts,
1806
+ buildSwapData,
1807
+ calculateExchangeRate,
1808
+ calculateNav,
1809
+ calculatePps,
1810
+ clearAtaCache,
1811
+ clearPdaCache,
1812
+ createClaimFeesInstruction,
1813
+ createDepositInstruction,
1814
+ createInitOrUpdateVaultInstruction,
1815
+ createInitializeStvInstruction,
1816
+ createJupEarnInstruction,
1817
+ createMoveJlxInstruction,
1818
+ createSettleYieldInstruction,
1819
+ createSwapJlxJlpInstruction,
1820
+ createSwapJlxJlxInstruction,
1821
+ createUpdateStvInstruction,
1822
+ createWithdrawInstruction,
1823
+ deriveAta,
1824
+ deriveStvAtas,
1825
+ deriveStvPda,
1826
+ deriveUserAtas,
1827
+ deriveVaultAtas,
1828
+ deriveVaultPda,
1829
+ fetchAddressLookupTables,
1830
+ fetchJlpRate,
1831
+ fetchJupiterPriceUsd,
1832
+ getJupiterQuote,
1833
+ getJupiterSwapInstructions,
1834
+ getPoolByMint,
1835
+ getPoolByName,
1836
+ jlxToBase,
1837
+ parseLendingAccount,
1838
+ parseRewardsRateModel,
1839
+ parseStv,
1840
+ parseSwapRemainingAccounts,
1841
+ parseVault,
1842
+ sharesToBase
1843
+ });