@elmntl/jlpd-sdk 0.1.11 → 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.
- package/LICENSE +201 -0
- package/README.md +185 -404
- package/dist/common/ata.d.ts +26 -0
- package/dist/common/ata.js +48 -0
- package/dist/common/buffer.d.ts +15 -0
- package/dist/common/buffer.js +118 -0
- package/dist/common/connection.d.ts +13 -0
- package/dist/common/connection.js +2 -0
- package/dist/common/constants.d.ts +14 -0
- package/dist/common/constants.js +31 -0
- package/dist/common/index.d.ts +6 -0
- package/dist/common/index.js +28 -0
- package/dist/common/strategy-interface.d.ts +59 -0
- package/dist/common/strategy-interface.js +42 -0
- package/dist/elemental-lend/accounts.d.ts +103 -0
- package/dist/elemental-lend/accounts.js +354 -0
- package/dist/elemental-lend/constants.d.ts +25 -0
- package/dist/elemental-lend/constants.js +48 -0
- package/dist/elemental-lend/index.d.ts +8 -0
- package/dist/elemental-lend/index.js +24 -0
- package/dist/elemental-lend/instructions.d.ts +104 -0
- package/dist/elemental-lend/instructions.js +266 -0
- package/dist/elemental-lend/jupiter-lend.d.ts +91 -0
- package/dist/elemental-lend/jupiter-lend.js +189 -0
- package/dist/elemental-lend/kamino-vault.d.ts +173 -0
- package/dist/elemental-lend/kamino-vault.js +483 -0
- package/dist/elemental-lend/pda.d.ts +12 -0
- package/dist/elemental-lend/pda.js +24 -0
- package/dist/elemental-lend/protocol-actions.d.ts +56 -0
- package/dist/elemental-lend/protocol-actions.js +244 -0
- package/dist/elemental-lend/types.d.ts +113 -0
- package/dist/elemental-lend/types.js +2 -0
- package/dist/elemental-lend-v2/accounts.d.ts +14 -0
- package/dist/elemental-lend-v2/accounts.js +136 -0
- package/dist/elemental-lend-v2/adapters.d.ts +22 -0
- package/dist/elemental-lend-v2/adapters.js +50 -0
- package/dist/elemental-lend-v2/constants.d.ts +48 -0
- package/dist/elemental-lend-v2/constants.js +104 -0
- package/dist/elemental-lend-v2/index.d.ts +8 -0
- package/dist/elemental-lend-v2/index.js +24 -0
- package/dist/elemental-lend-v2/instructions.d.ts +96 -0
- package/dist/elemental-lend-v2/instructions.js +190 -0
- package/dist/elemental-lend-v2/lut.d.ts +20 -0
- package/dist/elemental-lend-v2/lut.js +65 -0
- package/dist/elemental-lend-v2/pda.d.ts +9 -0
- package/dist/elemental-lend-v2/pda.js +27 -0
- package/dist/elemental-lend-v2/types.d.ts +105 -0
- package/dist/elemental-lend-v2/types.js +2 -0
- package/dist/elemental-lend-v2/update-aum.d.ts +29 -0
- package/dist/elemental-lend-v2/update-aum.js +82 -0
- package/dist/index.d.ts +5 -3552
- package/dist/index.js +37 -4454
- package/dist/jlpd-strategy/accounts.d.ts +83 -0
- package/dist/jlpd-strategy/accounts.js +216 -0
- package/dist/jlpd-strategy/adapter.d.ts +81 -0
- package/dist/jlpd-strategy/adapter.js +118 -0
- package/dist/jlpd-strategy/base-to-base-swap.d.ts +74 -0
- package/dist/jlpd-strategy/base-to-base-swap.js +205 -0
- package/dist/jlpd-strategy/constants.d.ts +127 -0
- package/dist/jlpd-strategy/constants.js +174 -0
- package/dist/jlpd-strategy/fluid-view.d.ts +199 -0
- package/dist/jlpd-strategy/fluid-view.js +799 -0
- package/dist/jlpd-strategy/hedge-derived.d.ts +135 -0
- package/dist/jlpd-strategy/hedge-derived.js +231 -0
- package/dist/jlpd-strategy/hedge-instructions.d.ts +210 -0
- package/dist/jlpd-strategy/hedge-instructions.js +300 -0
- package/dist/jlpd-strategy/hedge-state.d.ts +88 -0
- package/dist/jlpd-strategy/hedge-state.js +110 -0
- package/dist/jlpd-strategy/index.d.ts +17 -0
- package/dist/jlpd-strategy/index.js +33 -0
- package/dist/jlpd-strategy/instructions.d.ts +159 -0
- package/dist/jlpd-strategy/instructions.js +234 -0
- package/dist/jlpd-strategy/jlp-borrow.d.ts +63 -0
- package/dist/jlpd-strategy/jlp-borrow.js +87 -0
- package/dist/jlpd-strategy/jlp-data.d.ts +166 -0
- package/dist/jlpd-strategy/jlp-data.js +611 -0
- package/dist/jlpd-strategy/jupusd-earn.d.ts +90 -0
- package/dist/jlpd-strategy/jupusd-earn.js +166 -0
- package/dist/jlpd-strategy/live-jlp-price.d.ts +46 -0
- package/dist/jlpd-strategy/live-jlp-price.js +267 -0
- package/dist/jlpd-strategy/pda.d.ts +13 -0
- package/dist/jlpd-strategy/pda.js +28 -0
- package/dist/jlpd-strategy/settle-yield.d.ts +45 -0
- package/dist/jlpd-strategy/settle-yield.js +113 -0
- package/dist/jlpd-strategy/swap-jlp.d.ts +198 -0
- package/dist/jlpd-strategy/swap-jlp.js +586 -0
- package/dist/jlpd-strategy/types.d.ts +101 -0
- package/dist/jlpd-strategy/types.js +29 -0
- package/dist/p-stv-core/accounts.d.ts +152 -0
- package/dist/p-stv-core/accounts.js +407 -0
- package/dist/p-stv-core/constants.d.ts +138 -0
- package/dist/p-stv-core/constants.js +181 -0
- package/dist/p-stv-core/events.d.ts +7 -0
- package/dist/p-stv-core/events.js +246 -0
- package/dist/p-stv-core/index.d.ts +11 -0
- package/dist/p-stv-core/index.js +27 -0
- package/dist/p-stv-core/instructions.d.ts +637 -0
- package/dist/p-stv-core/instructions.js +670 -0
- package/dist/p-stv-core/lut.d.ts +41 -0
- package/dist/p-stv-core/lut.js +81 -0
- package/dist/p-stv-core/pda.d.ts +30 -0
- package/dist/p-stv-core/pda.js +65 -0
- package/dist/p-stv-core/prices.d.ts +20 -0
- package/dist/p-stv-core/prices.js +77 -0
- package/dist/p-stv-core/remaining-accounts.d.ts +107 -0
- package/dist/p-stv-core/remaining-accounts.js +326 -0
- package/dist/p-stv-core/send-tx.d.ts +72 -0
- package/dist/p-stv-core/send-tx.js +290 -0
- package/dist/p-stv-core/sol-wrap.d.ts +34 -0
- package/dist/p-stv-core/sol-wrap.js +74 -0
- package/dist/p-stv-core/types.d.ts +361 -0
- package/dist/p-stv-core/types.js +2 -0
- package/package.json +56 -15
- package/dist/index.d.mts +0 -3552
- package/dist/index.mjs +0 -4363
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createSwapJlpIx = createSwapJlpIx;
|
|
7
|
+
exports.getJupiterSwapQuote = getJupiterSwapQuote;
|
|
8
|
+
exports.getJupiterSwapInstructions = getJupiterSwapInstructions;
|
|
9
|
+
exports.buildSwapJlpTransaction = buildSwapJlpTransaction;
|
|
10
|
+
exports.buildRebalanceTransaction = buildRebalanceTransaction;
|
|
11
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
12
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
13
|
+
const ata_1 = require("../common/ata");
|
|
14
|
+
const bn_js_1 = __importDefault(require("bn.js"));
|
|
15
|
+
const constants_1 = require("./constants");
|
|
16
|
+
const pda_1 = require("./pda");
|
|
17
|
+
const accounts_1 = require("./accounts");
|
|
18
|
+
const pda_2 = require("../p-stv-core/pda");
|
|
19
|
+
const instructions_1 = require("../p-stv-core/instructions");
|
|
20
|
+
const remaining_accounts_1 = require("../p-stv-core/remaining-accounts");
|
|
21
|
+
const accounts_2 = require("../p-stv-core/accounts");
|
|
22
|
+
const constants_2 = require("../p-stv-core/constants");
|
|
23
|
+
const pda_3 = require("../elemental-lend/pda");
|
|
24
|
+
const jupiter_lend_1 = require("../elemental-lend/jupiter-lend");
|
|
25
|
+
const instructions_2 = require("../elemental-lend/instructions");
|
|
26
|
+
const accounts_3 = require("../elemental-lend/accounts");
|
|
27
|
+
/** Decode a Jupiter `JupiterSwapInstruction` into a `TransactionInstruction`. */
|
|
28
|
+
function decodeJupiterInstruction(raw) {
|
|
29
|
+
return new web3_js_1.TransactionInstruction({
|
|
30
|
+
programId: new web3_js_1.PublicKey(raw.programId),
|
|
31
|
+
keys: raw.accounts.map((acc) => ({
|
|
32
|
+
pubkey: new web3_js_1.PublicKey(acc.pubkey),
|
|
33
|
+
isSigner: acc.isSigner,
|
|
34
|
+
isWritable: acc.isWritable,
|
|
35
|
+
})),
|
|
36
|
+
data: Buffer.from(raw.data, "base64"),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Helpers
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
const JUPITER_API_BASE = "https://api.jup.ag/swap/v1";
|
|
43
|
+
/**
|
|
44
|
+
* Optional Jupiter API key, read once at module load time. When set,
|
|
45
|
+
* outbound Jupiter requests include an `x-api-key` header for higher rate
|
|
46
|
+
* limits. Read once instead of per-call so the env var is consistent across
|
|
47
|
+
* the lifetime of the process.
|
|
48
|
+
*/
|
|
49
|
+
const JUPITER_API_KEY = process.env.NEXT_PUBLIC_JUPITER_API_KEY ?? process.env.JUPITER_API_KEY;
|
|
50
|
+
function toBigInt(v) {
|
|
51
|
+
if (typeof v === "bigint")
|
|
52
|
+
return v;
|
|
53
|
+
const bn = v;
|
|
54
|
+
if (typeof bn.toBigInt === "function")
|
|
55
|
+
return bn.toBigInt();
|
|
56
|
+
return BigInt(bn.toString());
|
|
57
|
+
}
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
// Low-level instruction builder
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
/**
|
|
62
|
+
* Build the on-chain `swap_jlp` instruction.
|
|
63
|
+
*
|
|
64
|
+
* Instruction data layout (Anchor Borsh):
|
|
65
|
+
* [8-byte disc, 1-byte direction, 8-byte amount (LE), 8-byte min_out (LE),
|
|
66
|
+
* 4-byte jupiter_data_len (LE), ...jupiter_data_bytes]
|
|
67
|
+
*/
|
|
68
|
+
function createSwapJlpIx(args, programId = constants_1.PROGRAM_ID) {
|
|
69
|
+
const { manager, config, managerRole, strategyState, strategyBaseAta, strategyJlpAta, vaultJlpAta, baseMint, jlpMint, tokenProgram, jupiterProgram, priceOracle, jlpPool, jlpMintAccount, direction, amount, minOut, jupiterData, remainingAccounts = [], } = args;
|
|
70
|
+
const amountBi = toBigInt(amount);
|
|
71
|
+
const minOutBi = toBigInt(minOut);
|
|
72
|
+
// Serialize instruction data
|
|
73
|
+
const jupBytes = Buffer.from(jupiterData);
|
|
74
|
+
const dataLen = 8 + 1 + 8 + 8 + 4 + jupBytes.length;
|
|
75
|
+
const data = Buffer.alloc(dataLen);
|
|
76
|
+
// Discriminator
|
|
77
|
+
constants_1.IX_SWAP_JLP.copy(data, 0);
|
|
78
|
+
// Direction (1 byte)
|
|
79
|
+
data.writeUInt8(direction === "BaseToJlp" ? 0 : 1, 8);
|
|
80
|
+
// Amount (u64 LE)
|
|
81
|
+
data.writeBigUInt64LE(amountBi, 9);
|
|
82
|
+
// MinOut (u64 LE)
|
|
83
|
+
data.writeBigUInt64LE(minOutBi, 17);
|
|
84
|
+
// Jupiter data length (u32 LE) + bytes
|
|
85
|
+
data.writeUInt32LE(jupBytes.length, 25);
|
|
86
|
+
jupBytes.copy(data, 29);
|
|
87
|
+
const keys = [
|
|
88
|
+
{ pubkey: manager, isSigner: true, isWritable: false },
|
|
89
|
+
{ pubkey: config, isSigner: false, isWritable: false },
|
|
90
|
+
{ pubkey: managerRole, isSigner: false, isWritable: false },
|
|
91
|
+
{ pubkey: strategyState, isSigner: false, isWritable: true },
|
|
92
|
+
{ pubkey: strategyBaseAta, isSigner: false, isWritable: true },
|
|
93
|
+
{ pubkey: strategyJlpAta, isSigner: false, isWritable: true },
|
|
94
|
+
{ pubkey: vaultJlpAta, isSigner: false, isWritable: true },
|
|
95
|
+
{ pubkey: baseMint, isSigner: false, isWritable: false },
|
|
96
|
+
{ pubkey: jlpMint, isSigner: false, isWritable: false },
|
|
97
|
+
{ pubkey: tokenProgram, isSigner: false, isWritable: false },
|
|
98
|
+
{ pubkey: jupiterProgram, isSigner: false, isWritable: false },
|
|
99
|
+
{ pubkey: priceOracle, isSigner: false, isWritable: false },
|
|
100
|
+
{ pubkey: jlpPool, isSigner: false, isWritable: false },
|
|
101
|
+
{ pubkey: jlpMintAccount, isSigner: false, isWritable: false },
|
|
102
|
+
...remainingAccounts,
|
|
103
|
+
];
|
|
104
|
+
return new web3_js_1.TransactionInstruction({ keys, programId, data });
|
|
105
|
+
}
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// Stable-asset detection
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
/** Mints that use a hardcoded $1 price on-chain (oracle account ignored). */
|
|
110
|
+
const STABLE_MINTS = new Set(constants_1.JLPD_POOLS.filter((p) => p.name === "USDC" || p.name === "JupUSD").map((p) => p.mint));
|
|
111
|
+
function isStableMint(mint) {
|
|
112
|
+
return STABLE_MINTS.has(mint.toBase58());
|
|
113
|
+
}
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// Jupiter API helpers
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
/**
|
|
118
|
+
* Fetch a swap quote from Jupiter's v1 quote API.
|
|
119
|
+
*/
|
|
120
|
+
async function getJupiterSwapQuote(args) {
|
|
121
|
+
const { inputMint, outputMint, amount, slippageBps = 50, maxAccounts = 40 } = args;
|
|
122
|
+
const params = new URLSearchParams({
|
|
123
|
+
inputMint: inputMint.toBase58(),
|
|
124
|
+
outputMint: outputMint.toBase58(),
|
|
125
|
+
amount: amount.toString(),
|
|
126
|
+
slippageBps: slippageBps.toString(),
|
|
127
|
+
maxAccounts: maxAccounts.toString(),
|
|
128
|
+
});
|
|
129
|
+
const url = `${JUPITER_API_BASE}/quote?${params.toString()}`;
|
|
130
|
+
const headers = {};
|
|
131
|
+
if (JUPITER_API_KEY) {
|
|
132
|
+
headers["x-api-key"] = JUPITER_API_KEY;
|
|
133
|
+
}
|
|
134
|
+
const response = await fetch(url, { headers });
|
|
135
|
+
if (!response.ok) {
|
|
136
|
+
const text = await response.text();
|
|
137
|
+
throw new Error(`Jupiter quote API error (${response.status}): ${text}`);
|
|
138
|
+
}
|
|
139
|
+
const data = (await response.json());
|
|
140
|
+
if (data.error) {
|
|
141
|
+
throw new Error(`Jupiter quote error: ${data.error}`);
|
|
142
|
+
}
|
|
143
|
+
return data;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Fetch swap instructions from Jupiter's v1 swap-instructions API.
|
|
147
|
+
*
|
|
148
|
+
* @param quoteResponse The quote from getJupiterSwapQuote
|
|
149
|
+
* @param userPublicKey The account that signs the swap -- for JLPD this is the strategy_state PDA
|
|
150
|
+
* @param destinationTokenAccount Optional override for the destination token account.
|
|
151
|
+
* For base_to_base_swap: must be base_out_ata (ATA owned by strategy_state_OUT) so
|
|
152
|
+
* Jupiter routes output tokens there instead of to userPublicKey's default ATA.
|
|
153
|
+
* For swap_jlp: omit — Jupiter defaults destination to userPublicKey's ATA which is correct.
|
|
154
|
+
*/
|
|
155
|
+
async function getJupiterSwapInstructions(args) {
|
|
156
|
+
const { quoteResponse, userPublicKey, destinationTokenAccount } = args;
|
|
157
|
+
const url = `${JUPITER_API_BASE}/swap-instructions`;
|
|
158
|
+
const body = {
|
|
159
|
+
quoteResponse,
|
|
160
|
+
userPublicKey: userPublicKey.toBase58(),
|
|
161
|
+
wrapAndUnwrapSol: false,
|
|
162
|
+
dynamicComputeUnitLimit: true,
|
|
163
|
+
skipUserAccountsRpcCalls: true,
|
|
164
|
+
};
|
|
165
|
+
if (destinationTokenAccount !== undefined) {
|
|
166
|
+
body["destinationTokenAccount"] = destinationTokenAccount.toBase58();
|
|
167
|
+
}
|
|
168
|
+
const headers = {
|
|
169
|
+
"Content-Type": "application/json",
|
|
170
|
+
};
|
|
171
|
+
if (JUPITER_API_KEY) {
|
|
172
|
+
headers["x-api-key"] = JUPITER_API_KEY;
|
|
173
|
+
}
|
|
174
|
+
const response = await fetch(url, {
|
|
175
|
+
method: "POST",
|
|
176
|
+
headers,
|
|
177
|
+
body: JSON.stringify(body),
|
|
178
|
+
});
|
|
179
|
+
if (!response.ok) {
|
|
180
|
+
const text = await response.text();
|
|
181
|
+
throw new Error(`Jupiter swap-instructions API error (${response.status}): ${text}`);
|
|
182
|
+
}
|
|
183
|
+
const data = (await response.json());
|
|
184
|
+
if (data.error) {
|
|
185
|
+
throw new Error(`Jupiter swap-instructions error: ${data.error}`);
|
|
186
|
+
}
|
|
187
|
+
// Extract the raw instruction data (base64 encoded) from the swap instruction
|
|
188
|
+
const swapIx = data.swapInstruction;
|
|
189
|
+
const swapInstructionData = Buffer.from(swapIx.data, "base64");
|
|
190
|
+
// Build remaining accounts from the swap instruction's accounts
|
|
191
|
+
// All signers become non-signers for CPI (the strategy PDA signs via seeds)
|
|
192
|
+
const remainingAccounts = swapIx.accounts.map((acc) => ({
|
|
193
|
+
pubkey: new web3_js_1.PublicKey(acc.pubkey),
|
|
194
|
+
isSigner: false,
|
|
195
|
+
isWritable: acc.isWritable,
|
|
196
|
+
}));
|
|
197
|
+
// Decode Jupiter's compute-budget instructions so callers can prepend them.
|
|
198
|
+
// Dropping these silently would leave the tx with the wrong CU budget and
|
|
199
|
+
// risk simulation/execution failure on complex routes.
|
|
200
|
+
const computeBudgetInstructions = (data.computeBudgetInstructions ?? []).map(decodeJupiterInstruction);
|
|
201
|
+
return {
|
|
202
|
+
swapInstructionData,
|
|
203
|
+
remainingAccounts,
|
|
204
|
+
addressLookupTableAddresses: data.addressLookupTableAddresses,
|
|
205
|
+
computeBudgetInstructions,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Fetch Address Lookup Tables from the chain.
|
|
210
|
+
*/
|
|
211
|
+
async function fetchAddressLookupTables(connection, addresses) {
|
|
212
|
+
if (addresses.length === 0)
|
|
213
|
+
return [];
|
|
214
|
+
const pubkeys = addresses.map((addr) => new web3_js_1.PublicKey(addr));
|
|
215
|
+
const accountInfos = await connection.getMultipleAccountsInfo(pubkeys);
|
|
216
|
+
const tables = [];
|
|
217
|
+
for (let i = 0; i < accountInfos.length; i++) {
|
|
218
|
+
const info = accountInfos[i];
|
|
219
|
+
if (!info) {
|
|
220
|
+
console.warn(`ALT not found: ${addresses[i]}`);
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
tables.push(new web3_js_1.AddressLookupTableAccount({
|
|
224
|
+
key: pubkeys[i],
|
|
225
|
+
state: web3_js_1.AddressLookupTableAccount.deserialize(info.data),
|
|
226
|
+
}));
|
|
227
|
+
}
|
|
228
|
+
return tables;
|
|
229
|
+
}
|
|
230
|
+
// ---------------------------------------------------------------------------
|
|
231
|
+
// High-level builder
|
|
232
|
+
// ---------------------------------------------------------------------------
|
|
233
|
+
/**
|
|
234
|
+
* Build a complete swap_jlp transaction with Jupiter quote + instructions + ALTs.
|
|
235
|
+
*
|
|
236
|
+
* This is the main function the frontend calls. It:
|
|
237
|
+
* 1. Derives all PDAs (config, manager_role, strategy_state, ATAs)
|
|
238
|
+
* 2. Gets Jupiter quote
|
|
239
|
+
* 3. Gets Jupiter swap instructions
|
|
240
|
+
* 4. Builds the swap_jlp instruction with remaining accounts
|
|
241
|
+
* 5. Returns instructions + ALTs for a versioned transaction
|
|
242
|
+
*/
|
|
243
|
+
async function buildSwapJlpTransaction(args) {
|
|
244
|
+
const { connection, manager, baseMint, direction, amount, slippageBps = 50, jlpMint = constants_1.JLP_MINT, tokenProgram = spl_token_1.TOKEN_PROGRAM_ID, programId = constants_1.PROGRAM_ID, } = args;
|
|
245
|
+
// 1. Derive PDAs
|
|
246
|
+
const [config] = (0, pda_1.findJlpdConfigPda)(programId);
|
|
247
|
+
const [managerRole] = (0, pda_1.findJlpdManagerRolePda)(config, manager, programId);
|
|
248
|
+
const [strategyState] = (0, pda_1.findStrategyStatePda)(baseMint, programId);
|
|
249
|
+
// Derive ATAs
|
|
250
|
+
const strategyBaseAta = (0, ata_1.findAta)(baseMint, strategyState, tokenProgram);
|
|
251
|
+
const strategyJlpAta = (0, ata_1.findAta)(jlpMint, strategyState, tokenProgram);
|
|
252
|
+
const vaultJlpAta = (0, ata_1.findAta)(jlpMint, config, tokenProgram);
|
|
253
|
+
// 2. Resolve oracle + pending swap_arb. Use pre-fetched state when available;
|
|
254
|
+
// otherwise fetch once if needed (volatile asset without oracle override, or BaseToJlp).
|
|
255
|
+
const needOracleFetch = !isStableMint(baseMint) && args.priceOracle === undefined;
|
|
256
|
+
const needArb = direction === "BaseToJlp";
|
|
257
|
+
const state = args.prefetchedStrategyState !== undefined
|
|
258
|
+
? args.prefetchedStrategyState
|
|
259
|
+
: needOracleFetch || needArb
|
|
260
|
+
? await (0, accounts_1.fetchJlpStrategyState)(connection, baseMint, programId)
|
|
261
|
+
: null;
|
|
262
|
+
let priceOracle;
|
|
263
|
+
if (isStableMint(baseMint)) {
|
|
264
|
+
priceOracle = web3_js_1.PublicKey.default;
|
|
265
|
+
}
|
|
266
|
+
else if (args.priceOracle !== undefined) {
|
|
267
|
+
priceOracle = args.priceOracle;
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
priceOracle = state.priceOracle;
|
|
271
|
+
}
|
|
272
|
+
// 3. BaseToJlp folds pending swap_arb into the Jupiter input:
|
|
273
|
+
// total_in = amount + swap_arb (signed; an unfavorable b2b banked a negative
|
|
274
|
+
// deficit that reduces it). The on-chain handler pins base-spent == total_in,
|
|
275
|
+
// so the Jupiter route MUST be quoted for total_in. The instruction `amount`
|
|
276
|
+
// stays = principal (the program credits base_loaned with principal only).
|
|
277
|
+
let quoteAmount = amount;
|
|
278
|
+
if (direction === "BaseToJlp" && state) {
|
|
279
|
+
const arb = BigInt(state.swapArb.toString()); // signed i64
|
|
280
|
+
const totalIn = amount + arb;
|
|
281
|
+
if (totalIn <= 0n) {
|
|
282
|
+
throw new Error(`swap_arb deficit (${arb}) cancels principal (${amount}); cannot Base->JLP — wait for a settle or larger amount.`);
|
|
283
|
+
}
|
|
284
|
+
quoteAmount = totalIn;
|
|
285
|
+
}
|
|
286
|
+
// 4. Determine input/output mints for the Jupiter quote
|
|
287
|
+
const inputMint = direction === "BaseToJlp" ? baseMint : jlpMint;
|
|
288
|
+
const outputMint = direction === "BaseToJlp" ? jlpMint : baseMint;
|
|
289
|
+
// 5. Get Jupiter quote (for total_in on BaseToJlp; principal otherwise)
|
|
290
|
+
const quote = await getJupiterSwapQuote({
|
|
291
|
+
inputMint,
|
|
292
|
+
outputMint,
|
|
293
|
+
amount: quoteAmount,
|
|
294
|
+
slippageBps,
|
|
295
|
+
});
|
|
296
|
+
// 5. Get Jupiter swap instructions (strategy_state PDA signs via CPI)
|
|
297
|
+
const jupSwap = await getJupiterSwapInstructions({
|
|
298
|
+
quoteResponse: quote,
|
|
299
|
+
userPublicKey: strategyState,
|
|
300
|
+
});
|
|
301
|
+
// 6. Build the swap_jlp instruction
|
|
302
|
+
const minOut = BigInt(quote.otherAmountThreshold);
|
|
303
|
+
const swapJlpIx = createSwapJlpIx({
|
|
304
|
+
manager,
|
|
305
|
+
config,
|
|
306
|
+
managerRole,
|
|
307
|
+
strategyState,
|
|
308
|
+
strategyBaseAta,
|
|
309
|
+
strategyJlpAta,
|
|
310
|
+
vaultJlpAta,
|
|
311
|
+
baseMint,
|
|
312
|
+
jlpMint,
|
|
313
|
+
tokenProgram,
|
|
314
|
+
jupiterProgram: constants_1.JUPITER_PROGRAM,
|
|
315
|
+
priceOracle,
|
|
316
|
+
jlpPool: constants_1.JLP_POOL_ACCOUNT,
|
|
317
|
+
jlpMintAccount: jlpMint,
|
|
318
|
+
direction,
|
|
319
|
+
amount,
|
|
320
|
+
minOut,
|
|
321
|
+
jupiterData: jupSwap.swapInstructionData,
|
|
322
|
+
remainingAccounts: jupSwap.remainingAccounts,
|
|
323
|
+
}, programId);
|
|
324
|
+
// 7. Fetch ALTs
|
|
325
|
+
const addressLookupTables = await fetchAddressLookupTables(connection, jupSwap.addressLookupTableAddresses);
|
|
326
|
+
// Prepend compute-budget instructions from Jupiter so the tx carries the
|
|
327
|
+
// correct CU budget for complex routes. Dropping them risks simulation/exec failure.
|
|
328
|
+
const instructions = [
|
|
329
|
+
...jupSwap.computeBudgetInstructions,
|
|
330
|
+
swapJlpIx,
|
|
331
|
+
];
|
|
332
|
+
return {
|
|
333
|
+
instructions,
|
|
334
|
+
addressLookupTables,
|
|
335
|
+
quoteInAmount: BigInt(quote.inAmount),
|
|
336
|
+
minOut,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Build a complete rebalance transaction set for JLPD strategy.
|
|
341
|
+
*
|
|
342
|
+
* For BaseToJlp: auto-detects liquidity location and builds
|
|
343
|
+
* deposit_to_strategy + swap_jlp (tries 1 tx, falls back to 2 if needed).
|
|
344
|
+
*
|
|
345
|
+
* For JlpToBase: builds swap_jlp + withdraw_from_strategy in 1 tx.
|
|
346
|
+
*/
|
|
347
|
+
async function buildRebalanceTransaction(args) {
|
|
348
|
+
const { connection, manager, baseMint, vaultId, direction, amount, slippageBps = 50, jlpMint = constants_1.JLP_MINT, tokenProgram = spl_token_1.TOKEN_PROGRAM_ID, programId = constants_1.PROGRAM_ID, pStvProgramId = constants_2.PROGRAM_ID, } = args;
|
|
349
|
+
if (direction === "BaseToJlp") {
|
|
350
|
+
return buildBaseToJlpRebalance({
|
|
351
|
+
connection, manager, baseMint, vaultId, amount, slippageBps,
|
|
352
|
+
jlpMint, tokenProgram, programId, pStvProgramId,
|
|
353
|
+
liquidity: args.liquidity,
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
return buildJlpToBaseRebalance({
|
|
358
|
+
connection, manager, baseMint, vaultId, amount, slippageBps,
|
|
359
|
+
jlpMint, tokenProgram, programId, pStvProgramId,
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// ---------------------------------------------------------------------------
|
|
364
|
+
// BaseToJlp: deposit_to_strategy (if needed) + swap_jlp
|
|
365
|
+
// ---------------------------------------------------------------------------
|
|
366
|
+
async function buildBaseToJlpRebalance(args) {
|
|
367
|
+
const { connection, manager, baseMint, vaultId, amount, slippageBps, jlpMint, tokenProgram, programId, pStvProgramId, liquidity, } = args;
|
|
368
|
+
// Derive JLPD PDAs
|
|
369
|
+
const [strategyState] = (0, pda_1.findStrategyStatePda)(baseMint, programId);
|
|
370
|
+
const strategyBaseAta = (0, ata_1.findAta)(baseMint, strategyState, tokenProgram);
|
|
371
|
+
// Check if strategy_base_ata already has enough.
|
|
372
|
+
// Fix 4(c): when balance is not pre-supplied, batch the strategyBaseAta RPC fetch
|
|
373
|
+
// with the strategy-state fetch (which buildSwapJlpTransaction would make anyway
|
|
374
|
+
// for non-stable assets). This collapses two sequential RPC calls into one parallel batch.
|
|
375
|
+
let strategyBalance = liquidity?.strategyAtaBalance ?? 0n;
|
|
376
|
+
let prefetchedStrategyState;
|
|
377
|
+
if (!liquidity) {
|
|
378
|
+
const needStateFetch = !isStableMint(baseMint);
|
|
379
|
+
const [ataInfo, stateResult] = await Promise.all([
|
|
380
|
+
connection.getAccountInfo(strategyBaseAta).catch(() => null),
|
|
381
|
+
needStateFetch
|
|
382
|
+
? (0, accounts_1.fetchJlpStrategyState)(connection, baseMint, programId)
|
|
383
|
+
: Promise.resolve(undefined),
|
|
384
|
+
]);
|
|
385
|
+
if (ataInfo && ataInfo.data.length >= 72 && ataInfo.owner.equals(tokenProgram)) {
|
|
386
|
+
// PERF-LOW: read via subarray to avoid a full Buffer copy just to read 8 bytes.
|
|
387
|
+
strategyBalance = Buffer.from(ataInfo.data).subarray(64, 72).readBigUInt64LE(0);
|
|
388
|
+
}
|
|
389
|
+
if (stateResult !== undefined) {
|
|
390
|
+
prefetchedStrategyState = stateResult;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
// Build the swap_jlp instruction (Jupiter quotes the exact inAmount).
|
|
394
|
+
// Thread pre-fetched strategy state when available to skip its internal fetch.
|
|
395
|
+
const { instructions: swapIxs, addressLookupTables, quoteInAmount } = await buildSwapJlpTransaction({
|
|
396
|
+
connection, manager, baseMint, direction: "BaseToJlp",
|
|
397
|
+
amount, slippageBps, jlpMint, tokenProgram, programId,
|
|
398
|
+
prefetchedStrategyState,
|
|
399
|
+
});
|
|
400
|
+
if (strategyBalance >= quoteInAmount) {
|
|
401
|
+
// Path 1: strategy_base_ata has enough — just swap
|
|
402
|
+
return {
|
|
403
|
+
preInstructions: [],
|
|
404
|
+
instructions: swapIxs,
|
|
405
|
+
postInstructions: [],
|
|
406
|
+
addressLookupTables,
|
|
407
|
+
routeDescription: "Direct swap (strategy has funds)",
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
// Path 2/3: Need to deposit_to_strategy first (auto-unsweep from lend)
|
|
411
|
+
// Use quoteInAmount (what Jupiter will actually consume) instead of the
|
|
412
|
+
// user's requested amount, to avoid leaving dust in the strategy ATA.
|
|
413
|
+
const deficit = quoteInAmount - strategyBalance;
|
|
414
|
+
// Fetch STV on-chain for lend info
|
|
415
|
+
const stv = await (0, accounts_2.fetchStv)(connection, vaultId, pStvProgramId);
|
|
416
|
+
const [stvAddress] = (0, pda_2.findStvPda)(vaultId, pStvProgramId);
|
|
417
|
+
const [stvManagerRole] = (0, pda_2.findStvManagerRolePda)(stvAddress, manager, pStvProgramId);
|
|
418
|
+
// Build deposit_to_strategy remaining accounts (lend + auto-unroute)
|
|
419
|
+
const vaultInfo = {
|
|
420
|
+
address: stvAddress,
|
|
421
|
+
baseMint,
|
|
422
|
+
lendProgram: stv.lendProgram,
|
|
423
|
+
strategy: stv.strategy,
|
|
424
|
+
};
|
|
425
|
+
const depositCtx = await (0, remaining_accounts_1.buildDepositToStrategyContext)(connection, vaultInfo);
|
|
426
|
+
// Derive the JLPD strategy's position PDA in p-STV Core
|
|
427
|
+
const [jlpdStvPosition] = (0, pda_1.findStvPositionPda)(stvAddress, programId);
|
|
428
|
+
const vaultAta = (0, ata_1.findAta)(baseMint, stvAddress, tokenProgram);
|
|
429
|
+
const [configPda] = (0, pda_2.findConfigPda)(pStvProgramId);
|
|
430
|
+
const depositIx = (0, instructions_1.createDepositToStrategyIx)({
|
|
431
|
+
manager,
|
|
432
|
+
managerRole: stvManagerRole,
|
|
433
|
+
config: configPda,
|
|
434
|
+
stv: stvAddress,
|
|
435
|
+
vaultAta,
|
|
436
|
+
baseMint,
|
|
437
|
+
strategyProgram: programId,
|
|
438
|
+
strategyState,
|
|
439
|
+
stvPosition: jlpdStvPosition,
|
|
440
|
+
strategyBaseAta,
|
|
441
|
+
tokenProgram,
|
|
442
|
+
amount: new bn_js_1.default(deficit.toString()),
|
|
443
|
+
minShares: new bn_js_1.default(0),
|
|
444
|
+
protocolAumCount: depositCtx.protocolAumCount,
|
|
445
|
+
autoUnrouteCount: depositCtx.autoUnrouteCount,
|
|
446
|
+
remainingAccounts: depositCtx.remainingAccounts,
|
|
447
|
+
}, pStvProgramId);
|
|
448
|
+
const allPreIxs = [...depositCtx.preInstructions, depositIx];
|
|
449
|
+
return {
|
|
450
|
+
preInstructions: allPreIxs,
|
|
451
|
+
instructions: swapIxs,
|
|
452
|
+
postInstructions: [],
|
|
453
|
+
addressLookupTables,
|
|
454
|
+
routeDescription: depositCtx.autoUnrouteCount > 0
|
|
455
|
+
? "Unsweep from lend → deposit to strategy → swap"
|
|
456
|
+
: "Deposit to strategy → swap",
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
// ---------------------------------------------------------------------------
|
|
460
|
+
// JlpToBase: swap_jlp + withdraw_from_strategy
|
|
461
|
+
// ---------------------------------------------------------------------------
|
|
462
|
+
async function buildJlpToBaseRebalance(args) {
|
|
463
|
+
const { connection, manager, baseMint, vaultId, amount, slippageBps, jlpMint, tokenProgram, programId, pStvProgramId, } = args;
|
|
464
|
+
const [strategyState] = (0, pda_1.findStrategyStatePda)(baseMint, programId);
|
|
465
|
+
const [stvAddress] = (0, pda_2.findStvPda)(vaultId, pStvProgramId);
|
|
466
|
+
// FIX 2: Fetch strategy state first (for oracle/prefetch perf win on non-stables),
|
|
467
|
+
// then build the Jupiter swap concurrently with the independent stv fetch.
|
|
468
|
+
// The position fetch is deferred until AFTER the swap result is known so that
|
|
469
|
+
// sharesToWithdraw is computed from a position read taken after the Jupiter
|
|
470
|
+
// quote/minOut is resolved — preserving the freshness semantics of the old code.
|
|
471
|
+
const stratState = await (0, accounts_1.fetchJlpStrategyState)(connection, baseMint, programId);
|
|
472
|
+
// Run Jupiter build (uses pre-fetched stratState for oracle) concurrently with
|
|
473
|
+
// the stv fetch (which does not depend on the quote outcome).
|
|
474
|
+
const [swapResult, stv] = await Promise.all([
|
|
475
|
+
buildSwapJlpTransaction({
|
|
476
|
+
connection, manager, baseMint, direction: "JlpToBase",
|
|
477
|
+
amount, slippageBps, jlpMint, tokenProgram, programId,
|
|
478
|
+
prefetchedStrategyState: stratState,
|
|
479
|
+
}),
|
|
480
|
+
(0, accounts_2.fetchStv)(connection, vaultId, pStvProgramId),
|
|
481
|
+
]);
|
|
482
|
+
const { instructions: swapIxs, addressLookupTables, minOut: minBaseOut } = swapResult;
|
|
483
|
+
// FIX 1: minOut is returned explicitly by buildSwapJlpTransaction — no need to
|
|
484
|
+
// locate and parse the swap_jlp ix inside swapIxs by index. The instruction
|
|
485
|
+
// array can start with compute-budget ixs (prepended by buildSwapJlpTransaction),
|
|
486
|
+
// so swapIxs[0] is not guaranteed to be the swap_jlp instruction.
|
|
487
|
+
// FIX 2 (continued): Fetch position AFTER the quote is resolved so sharesToWithdraw
|
|
488
|
+
// is computed from the freshest on-chain data, matching the pre-refactor behavior
|
|
489
|
+
// where the position read happened after the Jupiter network round-trip.
|
|
490
|
+
const position = await (0, accounts_1.fetchJlpStvPosition)(connection, stvAddress, programId);
|
|
491
|
+
// shares = ceil(minBaseOut * PPS_DECIMALS / pps), capped at position balance
|
|
492
|
+
// Use the fresh pps from stratState (fetched above) — acceptable here because pps
|
|
493
|
+
// changes only on settle_yield (infrequent) and stratState is fetched at the top
|
|
494
|
+
// of this function before the Jupiter quote begins.
|
|
495
|
+
const pps = BigInt(stratState.pps.toString());
|
|
496
|
+
const ppsDecimals = BigInt(constants_1.PPS_DECIMALS);
|
|
497
|
+
let sharesToWithdraw = (minBaseOut * ppsDecimals + pps - 1n) / pps;
|
|
498
|
+
const positionShares = BigInt(position.shares.toString());
|
|
499
|
+
if (sharesToWithdraw > positionShares) {
|
|
500
|
+
sharesToWithdraw = positionShares;
|
|
501
|
+
}
|
|
502
|
+
// Build withdraw_from_strategy
|
|
503
|
+
const [stvManagerRole] = (0, pda_2.findStvManagerRolePda)(stvAddress, manager, pStvProgramId);
|
|
504
|
+
const [jlpdStvPosition] = (0, pda_1.findStvPositionPda)(stvAddress, programId);
|
|
505
|
+
const strategyBaseAta = (0, ata_1.findAta)(baseMint, strategyState, tokenProgram);
|
|
506
|
+
const vaultAta = (0, ata_1.findAta)(baseMint, stvAddress, tokenProgram);
|
|
507
|
+
// Build lend remaining_accounts for auto-sweep after withdraw:
|
|
508
|
+
// [4 fixed lend, protocolAumCount protocol-AUM accounts]
|
|
509
|
+
// The protocol-AUM accounts feed the pre-sweep update_aum refresh; on-chain lend
|
|
510
|
+
// rejects an incomplete tail, so we must cover the strategy's full protocol set.
|
|
511
|
+
const lendAccounts = [];
|
|
512
|
+
let lendProtocolAumCount = 0;
|
|
513
|
+
const DEFAULT_PUBKEY = web3_js_1.PublicKey.default;
|
|
514
|
+
if (!stv.lendProgram.equals(DEFAULT_PUBKEY)) {
|
|
515
|
+
const [lendStrategyState] = (0, pda_3.findStrategyStatePda)(baseMint, stv.lendProgram);
|
|
516
|
+
const [lendPosition] = (0, pda_3.findStvPositionPda)(stvAddress, stv.lendProgram);
|
|
517
|
+
const lendBaseAta = (0, ata_1.findAta)(baseMint, lendStrategyState, tokenProgram);
|
|
518
|
+
lendAccounts.push(...(0, instructions_1.buildLendRemainingAccounts)({
|
|
519
|
+
lendProgram: stv.lendProgram,
|
|
520
|
+
lendStrategyState,
|
|
521
|
+
lendStvPosition: lendPosition,
|
|
522
|
+
lendBaseAta,
|
|
523
|
+
}));
|
|
524
|
+
const lendState = await (0, accounts_3.fetchLendStrategyState)(connection, baseMint, stv.lendProgram).catch(() => null);
|
|
525
|
+
if (lendState) {
|
|
526
|
+
const protocolAumAccounts = await (0, accounts_3.buildProtocolAccountsForAum)(connection, lendState, lendStrategyState, tokenProgram);
|
|
527
|
+
lendProtocolAumCount = protocolAumAccounts.length;
|
|
528
|
+
lendAccounts.push(...protocolAumAccounts);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
const [configPda] = (0, pda_2.findConfigPda)(pStvProgramId);
|
|
532
|
+
const withdrawIx = (0, instructions_1.createWithdrawFromStrategyIx)({
|
|
533
|
+
manager,
|
|
534
|
+
managerRole: stvManagerRole,
|
|
535
|
+
config: configPda,
|
|
536
|
+
stv: stvAddress,
|
|
537
|
+
vaultAta,
|
|
538
|
+
baseMint,
|
|
539
|
+
strategyProgram: programId,
|
|
540
|
+
strategyState,
|
|
541
|
+
stvPosition: jlpdStvPosition,
|
|
542
|
+
strategyBaseAta,
|
|
543
|
+
tokenProgram,
|
|
544
|
+
shares: new bn_js_1.default(sharesToWithdraw.toString()),
|
|
545
|
+
protocolAumCount: lendProtocolAumCount,
|
|
546
|
+
remainingAccounts: lendAccounts,
|
|
547
|
+
}, pStvProgramId);
|
|
548
|
+
// Build Jupiter Lend deposit instruction to route funds from Elemental Lend → Jupiter Lend.
|
|
549
|
+
// After withdraw_from_strategy, funds are swept to Elemental Lend's base ATA.
|
|
550
|
+
// This instruction routes them into the Jupiter Lend pool for yield.
|
|
551
|
+
const postInstructions = [];
|
|
552
|
+
const jupPool = jupiter_lend_1.JUP_LEND_POOLS[baseMint.toBase58()];
|
|
553
|
+
if (!stv.lendProgram.equals(DEFAULT_PUBKEY) && jupPool) {
|
|
554
|
+
const lendProgramId = stv.lendProgram;
|
|
555
|
+
const [lendStrategyState] = (0, pda_3.findStrategyStatePda)(baseMint, lendProgramId);
|
|
556
|
+
const [lendManagerRole] = (0, pda_3.findLendManagerRolePda)(lendStrategyState, manager, lendProgramId);
|
|
557
|
+
const lendBaseAta = (0, ata_1.findAta)(baseMint, lendStrategyState, tokenProgram);
|
|
558
|
+
const lendFtokenAta = (0, ata_1.findAta)(jupPool.fTokenMint, lendStrategyState, tokenProgram);
|
|
559
|
+
const JUP_LEND_PROG = new web3_js_1.PublicKey("jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9");
|
|
560
|
+
const jupLendAccounts = [
|
|
561
|
+
...(0, jupiter_lend_1.buildJupLendDepositAccounts)(jupPool, lendStrategyState, lendBaseAta, lendFtokenAta).map((a) => ({ ...a, isSigner: false })),
|
|
562
|
+
{ pubkey: JUP_LEND_PROG, isSigner: false, isWritable: false },
|
|
563
|
+
];
|
|
564
|
+
// Use minBaseOut as the deposit amount — this is the minimum base tokens
|
|
565
|
+
// that will arrive in the lend base ATA after swap → withdraw → sweep.
|
|
566
|
+
// The actual amount may be slightly higher due to favorable slippage.
|
|
567
|
+
postInstructions.push((0, instructions_2.createJupLendDepositIx)({
|
|
568
|
+
manager,
|
|
569
|
+
strategyState: lendStrategyState,
|
|
570
|
+
managerRole: lendManagerRole,
|
|
571
|
+
depositorBaseAta: lendBaseAta,
|
|
572
|
+
depositorFtokenAta: lendFtokenAta,
|
|
573
|
+
amount: new bn_js_1.default(minBaseOut.toString()),
|
|
574
|
+
remainingAccounts: jupLendAccounts,
|
|
575
|
+
}, lendProgramId));
|
|
576
|
+
}
|
|
577
|
+
return {
|
|
578
|
+
preInstructions: [],
|
|
579
|
+
instructions: [...swapIxs, withdrawIx],
|
|
580
|
+
postInstructions,
|
|
581
|
+
addressLookupTables,
|
|
582
|
+
routeDescription: jupPool
|
|
583
|
+
? "Swap JLP → base → withdraw to vault → route to Jupiter Lend"
|
|
584
|
+
: "Swap JLP → base → withdraw to vault",
|
|
585
|
+
};
|
|
586
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
import BN from "bn.js";
|
|
3
|
+
import type { StrategyStateHeader } from "../common/strategy-interface";
|
|
4
|
+
/**
|
|
5
|
+
* JlpdConfig global config (392 bytes total, 384 data bytes after the 8-byte
|
|
6
|
+
* discriminator). Layout mirrors `jlpd_config.rs`'s CURRENT `JlpdConfig`
|
|
7
|
+
* struct — the retired adapter-era fields (`jlp_earn_amount`,
|
|
8
|
+
* `jlp_adapter_program`) are GONE; that byte range is now split between the
|
|
9
|
+
* divergence-breaker fields and `_reserved`.
|
|
10
|
+
*/
|
|
11
|
+
export interface JlpdConfig {
|
|
12
|
+
admin: PublicKey;
|
|
13
|
+
jlpMint: PublicKey;
|
|
14
|
+
baseAssetMints: PublicKey[];
|
|
15
|
+
oracleStalenessTh: BN;
|
|
16
|
+
flags: number;
|
|
17
|
+
jlpSlippageBps: number;
|
|
18
|
+
version: number;
|
|
19
|
+
bump: number;
|
|
20
|
+
/**
|
|
21
|
+
* Divergence-breaker SOFT band (bps): settle emits `LiveAumDivergence`
|
|
22
|
+
* (no revert) above this. `0` (an existing pre-upgrade account, or an
|
|
23
|
+
* admin who never tuned it) resolves to the 1% default — see
|
|
24
|
+
* `softBreakerTolBpsResolved`.
|
|
25
|
+
*/
|
|
26
|
+
softBreakerTolBps: number;
|
|
27
|
+
/**
|
|
28
|
+
* Divergence-breaker HARD band (bps): settle reverts `AumDivergenceExceeded`
|
|
29
|
+
* above this. `0` resolves to the 3% default — see `aumHardBreakerBpsResolved`.
|
|
30
|
+
*/
|
|
31
|
+
aumHardBreakerBps: number;
|
|
32
|
+
/**
|
|
33
|
+
* Canonical vault JLP ATA = ATA(config, jlp_mint, token_program); write-once
|
|
34
|
+
* at init, pinned immutable.
|
|
35
|
+
*/
|
|
36
|
+
vaultJlpAta: PublicKey;
|
|
37
|
+
/**
|
|
38
|
+
* Per-`StrategyState` cap on banked `swap_arb` (USD 6-dec); `0` ⇒ fail-closed
|
|
39
|
+
* (no positive arb) until the admin sets it.
|
|
40
|
+
*/
|
|
41
|
+
maxSwapArbUsdPerAsset: BN;
|
|
42
|
+
}
|
|
43
|
+
/** Upper bound for either divergence-breaker band (100%). Only bounds an admin typo. */
|
|
44
|
+
export declare const MAX_BREAKER_BPS = 10000;
|
|
45
|
+
/** Default soft-breaker band (1%), applied when the stored field reads `0` or `> MAX_BREAKER_BPS`. */
|
|
46
|
+
export declare const DEFAULT_SOFT_BREAKER_TOL_BPS = 100;
|
|
47
|
+
/** Default hard-breaker band (3%), applied when the stored field reads `0` or `> MAX_BREAKER_BPS`. */
|
|
48
|
+
export declare const DEFAULT_AUM_HARD_BREAKER_BPS = 300;
|
|
49
|
+
/**
|
|
50
|
+
* Resolved soft-breaker band: the stored value, or `DEFAULT_SOFT_BREAKER_TOL_BPS`
|
|
51
|
+
* when the stored value is `0` or exceeds `MAX_BREAKER_BPS` — mirrors
|
|
52
|
+
* `JlpdConfig::soft_breaker_tol_bps_resolved` exactly.
|
|
53
|
+
*/
|
|
54
|
+
export declare function softBreakerTolBpsResolved(config: Pick<JlpdConfig, "softBreakerTolBps">): number;
|
|
55
|
+
/**
|
|
56
|
+
* Resolved hard-breaker band: the stored value, or `DEFAULT_AUM_HARD_BREAKER_BPS`
|
|
57
|
+
* when the stored value is `0` or exceeds `MAX_BREAKER_BPS` — mirrors
|
|
58
|
+
* `JlpdConfig::aum_hard_breaker_bps_resolved` exactly.
|
|
59
|
+
*/
|
|
60
|
+
export declare function aumHardBreakerBpsResolved(config: Pick<JlpdConfig, "aumHardBreakerBps">): number;
|
|
61
|
+
/** ManagerRole PDA (80 bytes) — grants manager access to rebalance operations */
|
|
62
|
+
export interface ManagerRole {
|
|
63
|
+
config: PublicKey;
|
|
64
|
+
manager: PublicKey;
|
|
65
|
+
bump: number;
|
|
66
|
+
}
|
|
67
|
+
/** JLP StrategyState (224 bytes) — extends standard 104-byte header */
|
|
68
|
+
export interface JlpStrategyState extends StrategyStateHeader {
|
|
69
|
+
baseLoaned: BN;
|
|
70
|
+
swapArb: BN;
|
|
71
|
+
priceOracle: PublicKey;
|
|
72
|
+
}
|
|
73
|
+
export type { StvPosition } from "../common/strategy-interface";
|
|
74
|
+
export interface ConfigInitializedEvent {
|
|
75
|
+
name: "ConfigInitialized";
|
|
76
|
+
config: PublicKey;
|
|
77
|
+
admin: PublicKey;
|
|
78
|
+
jlpMint: PublicKey;
|
|
79
|
+
}
|
|
80
|
+
export interface ConfigUpdatedEvent {
|
|
81
|
+
name: "ConfigUpdated";
|
|
82
|
+
config: PublicKey;
|
|
83
|
+
oldAdmin: PublicKey;
|
|
84
|
+
newAdmin: PublicKey;
|
|
85
|
+
oldFlags: number;
|
|
86
|
+
newFlags: number;
|
|
87
|
+
oldJlpSlippageBps: number;
|
|
88
|
+
newJlpSlippageBps: number;
|
|
89
|
+
oldOracleStalenessTh: BN;
|
|
90
|
+
newOracleStalenessTh: BN;
|
|
91
|
+
}
|
|
92
|
+
export interface ManagerAddedEvent {
|
|
93
|
+
name: "ManagerAdded";
|
|
94
|
+
config: PublicKey;
|
|
95
|
+
manager: PublicKey;
|
|
96
|
+
}
|
|
97
|
+
export interface ManagerRemovedEvent {
|
|
98
|
+
name: "ManagerRemoved";
|
|
99
|
+
config: PublicKey;
|
|
100
|
+
manager: PublicKey;
|
|
101
|
+
}
|