@hobba-io/core 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/LICENSE +15 -0
- package/README.md +87 -0
- package/dist/amountUtils.d.ts +15 -0
- package/dist/amountUtils.d.ts.map +1 -0
- package/dist/amountUtils.js +59 -0
- package/dist/amountUtils.js.map +1 -0
- package/dist/constants.d.ts +148 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +231 -0
- package/dist/constants.js.map +1 -0
- package/dist/errors.d.ts +7 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +29 -0
- package/dist/errors.js.map +1 -0
- package/dist/executeAction.d.ts +36 -0
- package/dist/executeAction.d.ts.map +1 -0
- package/dist/executeAction.js +606 -0
- package/dist/executeAction.js.map +1 -0
- package/dist/executeDepositBorrow.d.ts +49 -0
- package/dist/executeDepositBorrow.d.ts.map +1 -0
- package/dist/executeDepositBorrow.js +444 -0
- package/dist/executeDepositBorrow.js.map +1 -0
- package/dist/idl/hobba.json +5072 -0
- package/dist/idl.d.ts +783 -0
- package/dist/idl.d.ts.map +1 -0
- package/dist/idl.js +7 -0
- package/dist/idl.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/juplend/accountResolvers.d.ts +106 -0
- package/dist/juplend/accountResolvers.d.ts.map +1 -0
- package/dist/juplend/accountResolvers.js +148 -0
- package/dist/juplend/accountResolvers.js.map +1 -0
- package/dist/juplend/operateRemaining.d.ts +11 -0
- package/dist/juplend/operateRemaining.d.ts.map +1 -0
- package/dist/juplend/operateRemaining.js +46 -0
- package/dist/juplend/operateRemaining.js.map +1 -0
- package/dist/juplend/positionInit.d.ts +34 -0
- package/dist/juplend/positionInit.d.ts.map +1 -0
- package/dist/juplend/positionInit.js +56 -0
- package/dist/juplend/positionInit.js.map +1 -0
- package/dist/juplend/positionParser.d.ts +8 -0
- package/dist/juplend/positionParser.d.ts.map +1 -0
- package/dist/juplend/positionParser.js +30 -0
- package/dist/juplend/positionParser.js.map +1 -0
- package/dist/juplend/sdkApi.d.ts +39 -0
- package/dist/juplend/sdkApi.d.ts.map +1 -0
- package/dist/juplend/sdkApi.js +68 -0
- package/dist/juplend/sdkApi.js.map +1 -0
- package/dist/juplend/tickMath.d.ts +19 -0
- package/dist/juplend/tickMath.d.ts.map +1 -0
- package/dist/juplend/tickMath.js +91 -0
- package/dist/juplend/tickMath.js.map +1 -0
- package/dist/juplend/tickUtils.d.ts +20 -0
- package/dist/juplend/tickUtils.d.ts.map +1 -0
- package/dist/juplend/tickUtils.js +115 -0
- package/dist/juplend/tickUtils.js.map +1 -0
- package/dist/juplend/vaultConfigParser.d.ts +25 -0
- package/dist/juplend/vaultConfigParser.d.ts.map +1 -0
- package/dist/juplend/vaultConfigParser.js +38 -0
- package/dist/juplend/vaultConfigParser.js.map +1 -0
- package/dist/kamino/accountResolvers.d.ts +110 -0
- package/dist/kamino/accountResolvers.d.ts.map +1 -0
- package/dist/kamino/accountResolvers.js +220 -0
- package/dist/kamino/accountResolvers.js.map +1 -0
- package/dist/kamino/obligationParser.d.ts +13 -0
- package/dist/kamino/obligationParser.d.ts.map +1 -0
- package/dist/kamino/obligationParser.js +92 -0
- package/dist/kamino/obligationParser.js.map +1 -0
- package/dist/kamino/refreshInstructions.d.ts +4 -0
- package/dist/kamino/refreshInstructions.d.ts.map +1 -0
- package/dist/kamino/refreshInstructions.js +32 -0
- package/dist/kamino/refreshInstructions.js.map +1 -0
- package/dist/limits.d.ts +87 -0
- package/dist/limits.d.ts.map +1 -0
- package/dist/limits.js +174 -0
- package/dist/limits.js.map +1 -0
- package/dist/marketConfig.d.ts +35 -0
- package/dist/marketConfig.d.ts.map +1 -0
- package/dist/marketConfig.js +85 -0
- package/dist/marketConfig.js.map +1 -0
- package/dist/oracle/scopePrice.d.ts +7 -0
- package/dist/oracle/scopePrice.d.ts.map +1 -0
- package/dist/oracle/scopePrice.js +31 -0
- package/dist/oracle/scopePrice.js.map +1 -0
- package/dist/pdas.d.ts +33 -0
- package/dist/pdas.d.ts.map +1 -0
- package/dist/pdas.js +116 -0
- package/dist/pdas.js.map +1 -0
- package/dist/position.d.ts +45 -0
- package/dist/position.d.ts.map +1 -0
- package/dist/position.js +68 -0
- package/dist/position.js.map +1 -0
- package/dist/positionMetrics.d.ts +108 -0
- package/dist/positionMetrics.d.ts.map +1 -0
- package/dist/positionMetrics.js +238 -0
- package/dist/positionMetrics.js.map +1 -0
- package/dist/program.d.ts +12 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +24 -0
- package/dist/program.js.map +1 -0
- package/dist/quote.d.ts +90 -0
- package/dist/quote.d.ts.map +1 -0
- package/dist/quote.js +198 -0
- package/dist/quote.js.map +1 -0
- package/dist/rates/borrowRates.d.ts +44 -0
- package/dist/rates/borrowRates.d.ts.map +1 -0
- package/dist/rates/borrowRates.js +229 -0
- package/dist/rates/borrowRates.js.map +1 -0
- package/dist/rates/collateralInfo.d.ts +21 -0
- package/dist/rates/collateralInfo.d.ts.map +1 -0
- package/dist/rates/collateralInfo.js +104 -0
- package/dist/rates/collateralInfo.js.map +1 -0
- package/dist/rates/constants.d.ts +22 -0
- package/dist/rates/constants.d.ts.map +1 -0
- package/dist/rates/constants.js +70 -0
- package/dist/rates/constants.js.map +1 -0
- package/dist/rates/index.d.ts +11 -0
- package/dist/rates/index.d.ts.map +1 -0
- package/dist/rates/index.js +11 -0
- package/dist/rates/index.js.map +1 -0
- package/dist/rates/kaminoApi.d.ts +24 -0
- package/dist/rates/kaminoApi.d.ts.map +1 -0
- package/dist/rates/kaminoApi.js +98 -0
- package/dist/rates/kaminoApi.js.map +1 -0
- package/dist/rates/supplyRates.d.ts +23 -0
- package/dist/rates/supplyRates.d.ts.map +1 -0
- package/dist/rates/supplyRates.js +67 -0
- package/dist/rates/supplyRates.js.map +1 -0
- package/dist/transactionBuilder.d.ts +5 -0
- package/dist/transactionBuilder.d.ts.map +1 -0
- package/dist/transactionBuilder.js +287 -0
- package/dist/transactionBuilder.js.map +1 -0
- package/dist/txHelpers.d.ts +16 -0
- package/dist/txHelpers.d.ts.map +1 -0
- package/dist/txHelpers.js +82 -0
- package/dist/txHelpers.js.map +1 -0
- package/dist/userState.d.ts +21 -0
- package/dist/userState.d.ts.map +1 -0
- package/dist/userState.js +60 -0
- package/dist/userState.js.map +1 -0
- package/dist/vault/vaultAccounts.d.ts +82 -0
- package/dist/vault/vaultAccounts.d.ts.map +1 -0
- package/dist/vault/vaultAccounts.js +275 -0
- package/dist/vault/vaultAccounts.js.map +1 -0
- package/dist/wallet.d.ts +12 -0
- package/dist/wallet.d.ts.map +1 -0
- package/dist/wallet.js +2 -0
- package/dist/wallet.js.map +1 -0
- package/package.json +63 -0
- package/src/amountUtils.ts +69 -0
- package/src/constants.ts +263 -0
- package/src/errors.ts +33 -0
- package/src/executeAction.ts +884 -0
- package/src/executeDepositBorrow.ts +677 -0
- package/src/idl/hobba.json +5072 -0
- package/src/idl.ts +7 -0
- package/src/index.ts +21 -0
- package/src/juplend/accountResolvers.ts +207 -0
- package/src/juplend/operateRemaining.ts +81 -0
- package/src/juplend/positionInit.ts +86 -0
- package/src/juplend/positionParser.ts +41 -0
- package/src/juplend/sdkApi.ts +112 -0
- package/src/juplend/tickMath.ts +82 -0
- package/src/juplend/tickUtils.ts +163 -0
- package/src/juplend/vaultConfigParser.ts +45 -0
- package/src/kamino/accountResolvers.ts +299 -0
- package/src/kamino/obligationParser.ts +123 -0
- package/src/kamino/refreshInstructions.ts +45 -0
- package/src/limits.ts +222 -0
- package/src/marketConfig.ts +139 -0
- package/src/oracle/scopePrice.ts +31 -0
- package/src/pdas.ts +226 -0
- package/src/position.ts +131 -0
- package/src/positionMetrics.ts +387 -0
- package/src/program.ts +30 -0
- package/src/quote.ts +310 -0
- package/src/rates/borrowRates.ts +270 -0
- package/src/rates/collateralInfo.ts +136 -0
- package/src/rates/constants.ts +87 -0
- package/src/rates/index.ts +38 -0
- package/src/rates/kaminoApi.ts +134 -0
- package/src/rates/supplyRates.ts +102 -0
- package/src/transactionBuilder.ts +324 -0
- package/src/txHelpers.ts +107 -0
- package/src/userState.ts +91 -0
- package/src/vault/vaultAccounts.ts +365 -0
- package/src/wallet.ts +12 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { Transaction, TransactionMessage, VersionedTransaction, ComputeBudgetProgram, } from "@solana/web3.js";
|
|
2
|
+
import { isTickError } from "./juplend/tickUtils";
|
|
3
|
+
/** Poll-based confirmation — avoids WebSocket dependency */
|
|
4
|
+
async function pollConfirmation(connection, signature, lastValidBlockHeight, timeoutMs = 60000) {
|
|
5
|
+
const start = Date.now();
|
|
6
|
+
while (Date.now() - start < timeoutMs) {
|
|
7
|
+
try {
|
|
8
|
+
const { value } = await connection.getSignatureStatuses([signature]);
|
|
9
|
+
const status = value[0];
|
|
10
|
+
if (status) {
|
|
11
|
+
if (status.err)
|
|
12
|
+
throw new Error(`Transaction failed: ${JSON.stringify(status.err)}`);
|
|
13
|
+
if (status.confirmationStatus === "confirmed" || status.confirmationStatus === "finalized")
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
// Ignore RPC errors (429 etc.) and keep polling
|
|
19
|
+
console.warn("[pollConfirmation] RPC error, retrying:", e.message?.slice(0, 80));
|
|
20
|
+
}
|
|
21
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
22
|
+
}
|
|
23
|
+
throw new Error(`Transaction not confirmed within ${timeoutMs / 1000}s. Check: https://solscan.io/tx/${signature}`);
|
|
24
|
+
}
|
|
25
|
+
export async function sendLegacyTx(connection, instructions, wallet, computeUnits) {
|
|
26
|
+
if (!wallet.publicKey || !wallet.signTransaction) {
|
|
27
|
+
throw new Error("Wallet not connected");
|
|
28
|
+
}
|
|
29
|
+
const tx = new Transaction();
|
|
30
|
+
if (computeUnits) {
|
|
31
|
+
tx.add(ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnits }));
|
|
32
|
+
}
|
|
33
|
+
tx.add(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 100000 }));
|
|
34
|
+
for (const ix of instructions) {
|
|
35
|
+
tx.add(ix);
|
|
36
|
+
}
|
|
37
|
+
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
|
|
38
|
+
tx.recentBlockhash = blockhash;
|
|
39
|
+
tx.feePayer = wallet.publicKey;
|
|
40
|
+
const signed = await wallet.signTransaction(tx);
|
|
41
|
+
const sig = await connection.sendRawTransaction(signed.serialize(), {
|
|
42
|
+
skipPreflight: false,
|
|
43
|
+
});
|
|
44
|
+
await pollConfirmation(connection, sig, lastValidBlockHeight);
|
|
45
|
+
return sig;
|
|
46
|
+
}
|
|
47
|
+
export async function sendVersionedTx(connection, instructions, wallet, lutAddresses, computeUnits, skipSimulation,
|
|
48
|
+
// If supplied, called when pre-sign simulation fails with a JupLend tick error
|
|
49
|
+
// (VaultInvalidTick / VaultTickMismatch / VaultTickHasDebtNotFound). Should return
|
|
50
|
+
// a fresh instruction list (typically by re-fetching the SDK operate context) or
|
|
51
|
+
// null to surface the original error.
|
|
52
|
+
rebuildOnTickError) {
|
|
53
|
+
if (!wallet.publicKey || !wallet.signTransaction) {
|
|
54
|
+
throw new Error("Wallet not connected");
|
|
55
|
+
}
|
|
56
|
+
const budgetIxs = [
|
|
57
|
+
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 100000 }),
|
|
58
|
+
...(computeUnits ? [ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnits })] : []),
|
|
59
|
+
];
|
|
60
|
+
const allInstructions = [...budgetIxs, ...instructions];
|
|
61
|
+
// Load lookup tables
|
|
62
|
+
const lookupTables = [];
|
|
63
|
+
for (const lutAddress of lutAddresses) {
|
|
64
|
+
try {
|
|
65
|
+
const lutAccount = await connection.getAddressLookupTable(lutAddress);
|
|
66
|
+
if (lutAccount.value) {
|
|
67
|
+
lookupTables.push(lutAccount.value);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
console.warn(`[tx] LUT ${lutAddress.toBase58()} returned null (not found on RPC)`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
console.warn(`[tx] LUT ${lutAddress.toBase58()} fetch failed: ${e?.message || e}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (lookupTables.length === 0 && lutAddresses.length > 0) {
|
|
78
|
+
throw new Error("LUT not found or not yet activated");
|
|
79
|
+
}
|
|
80
|
+
const INIT_TICK_DISC = "160d3e8d4959b21d";
|
|
81
|
+
const INIT_TICK_ID_LIQ_DISC = "386e79a998f156b7";
|
|
82
|
+
const JUPLEND_PROGRAM = "jupr81YtYssSyPt8jbnGuiWon5f6x9TcDEFxYe3Bdzi";
|
|
83
|
+
const MAX_TX_SIZE = 1232;
|
|
84
|
+
const isInitTickIx = (ix) => {
|
|
85
|
+
if (ix.programId.toBase58() !== JUPLEND_PROGRAM)
|
|
86
|
+
return false;
|
|
87
|
+
const disc = Buffer.from(ix.data).subarray(0, 8).toString("hex");
|
|
88
|
+
return disc === INIT_TICK_DISC || disc === INIT_TICK_ID_LIQ_DISC;
|
|
89
|
+
};
|
|
90
|
+
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
|
|
91
|
+
let finalInstructions = allInstructions;
|
|
92
|
+
const tryBuild = (ixs) => {
|
|
93
|
+
try {
|
|
94
|
+
const msg = new TransactionMessage({
|
|
95
|
+
payerKey: wallet.publicKey,
|
|
96
|
+
recentBlockhash: blockhash,
|
|
97
|
+
instructions: ixs,
|
|
98
|
+
}).compileToV0Message(lookupTables);
|
|
99
|
+
const tx = new VersionedTransaction(msg);
|
|
100
|
+
const size = tx.serialize().length;
|
|
101
|
+
return { tx, size };
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
if (String(e?.message || e).includes("overruns Uint8Array"))
|
|
105
|
+
return null;
|
|
106
|
+
throw e;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
let built = tryBuild(finalInstructions);
|
|
110
|
+
// If TX doesn't fit (build threw or over MAX_TX_SIZE), strip InitTick/InitTickIdLiq (retry path re-adds if simulation says missing)
|
|
111
|
+
if (!built || built.size > MAX_TX_SIZE) {
|
|
112
|
+
const stripped = finalInstructions.filter(ix => !isInitTickIx(ix));
|
|
113
|
+
if (stripped.length < finalInstructions.length) {
|
|
114
|
+
console.log(`[tx] TX too large (${built?.size ?? "overflow"}), stripping ${finalInstructions.length - stripped.length} InitTick instructions`);
|
|
115
|
+
finalInstructions = stripped;
|
|
116
|
+
built = tryBuild(finalInstructions);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (!built) {
|
|
120
|
+
throw new Error(`Transaction too large even after stripping InitTick. Try splitting deposit/borrow or contact support.`);
|
|
121
|
+
}
|
|
122
|
+
const versionedTx = built.tx;
|
|
123
|
+
// Pre-simulate to catch errors before opening wallet popup
|
|
124
|
+
let txToSign = versionedTx;
|
|
125
|
+
if (skipSimulation) {
|
|
126
|
+
const signed = await wallet.signTransaction(versionedTx);
|
|
127
|
+
const sig = await connection.sendRawTransaction(signed.serialize(), { skipPreflight: true });
|
|
128
|
+
await pollConfirmation(connection, sig, lastValidBlockHeight);
|
|
129
|
+
return sig;
|
|
130
|
+
}
|
|
131
|
+
const simResult = await connection.simulateTransaction(versionedTx, {
|
|
132
|
+
sigVerify: false,
|
|
133
|
+
replaceRecentBlockhash: true,
|
|
134
|
+
});
|
|
135
|
+
if (simResult.value.err) {
|
|
136
|
+
if (simResult.value.logs) {
|
|
137
|
+
console.log("[simulation] Full logs:");
|
|
138
|
+
simResult.value.logs.forEach((l, i) => console.log(` ${i}: ${l}`));
|
|
139
|
+
}
|
|
140
|
+
const logs = simResult.value.logs || [];
|
|
141
|
+
const logBlob = logs.join("\n");
|
|
142
|
+
// JupLend tick race: SDK-computed tick PDAs no longer match on-chain state.
|
|
143
|
+
// Recover by re-fetching the SDK operate context and rebuilding the ix list,
|
|
144
|
+
// then re-simulating with fresh ticks. Single wallet popup at the end.
|
|
145
|
+
// Retry up to 3 times — vault state can shift again between SDK refetch and
|
|
146
|
+
// the rebuilt simulation, especially for withdraw paths that touch tick_has_debt arrays.
|
|
147
|
+
let tickRebuildSucceeded = false;
|
|
148
|
+
if (rebuildOnTickError && isTickError(logBlob)) {
|
|
149
|
+
const MAX_REBUILD_ATTEMPTS = 3;
|
|
150
|
+
let lastErrJson = "";
|
|
151
|
+
let lastLogs = "";
|
|
152
|
+
for (let attempt = 0; attempt < MAX_REBUILD_ATTEMPTS && !tickRebuildSucceeded; attempt++) {
|
|
153
|
+
console.log(`[simulation] JupLend tick error — rebuilding from fresh SDK context (attempt ${attempt + 1}/${MAX_REBUILD_ATTEMPTS})`);
|
|
154
|
+
const rebuilt = await rebuildOnTickError();
|
|
155
|
+
if (!rebuilt)
|
|
156
|
+
break;
|
|
157
|
+
let rebuiltIxs = [...budgetIxs, ...rebuilt];
|
|
158
|
+
// Strip any init-tick ixs that won't fit; the SDK already filters missing ones
|
|
159
|
+
let candidate = tryBuild(rebuiltIxs);
|
|
160
|
+
if (!candidate || candidate.size > MAX_TX_SIZE) {
|
|
161
|
+
const stripped = rebuiltIxs.filter(ix => !isInitTickIx(ix));
|
|
162
|
+
candidate = tryBuild(stripped);
|
|
163
|
+
if (candidate)
|
|
164
|
+
rebuiltIxs = stripped;
|
|
165
|
+
}
|
|
166
|
+
if (!candidate)
|
|
167
|
+
break;
|
|
168
|
+
const retrySim = await connection.simulateTransaction(candidate.tx, {
|
|
169
|
+
sigVerify: false,
|
|
170
|
+
replaceRecentBlockhash: true,
|
|
171
|
+
});
|
|
172
|
+
if (!retrySim.value.err) {
|
|
173
|
+
finalInstructions = rebuiltIxs;
|
|
174
|
+
txToSign = candidate.tx;
|
|
175
|
+
tickRebuildSucceeded = true;
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
lastErrJson = JSON.stringify(retrySim.value.err);
|
|
179
|
+
lastLogs = retrySim.value.logs?.slice(-10).join("\n") || "";
|
|
180
|
+
const retryBlob = (retrySim.value.logs || []).join("\n");
|
|
181
|
+
// If the new error isn't a tick error, no point retrying
|
|
182
|
+
if (!isTickError(retryBlob)) {
|
|
183
|
+
throw new Error(`Simulation failed after tick rebuild: ${lastErrJson}\n${lastLogs}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (!tickRebuildSucceeded) {
|
|
187
|
+
throw new Error(`Simulation failed after ${MAX_REBUILD_ATTEMPTS} tick rebuild attempts: ${lastErrJson}\n${lastLogs}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (tickRebuildSucceeded) {
|
|
191
|
+
// fall through to signing below with the rebuilt instructions
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
// If an InitTick/InitTickIdLiquidation failed (already exists, or unrecognized discriminator),
|
|
195
|
+
// strip those instructions and retry the simulation.
|
|
196
|
+
const hasAlreadyInUse = logs.some(l => l.includes("already in use"));
|
|
197
|
+
const hasFallbackNotFound = logs.some(l => l.includes("InstructionFallbackNotFound") || l.includes("custom program error: 0x65"));
|
|
198
|
+
if (hasAlreadyInUse || hasFallbackNotFound) {
|
|
199
|
+
// Strip problematic JupLend instructions:
|
|
200
|
+
// - "already in use": InitTick accounts already exist
|
|
201
|
+
// - "FallbackNotFound": SDK generated an instruction the program doesn't recognize
|
|
202
|
+
const filtered = finalInstructions.filter(ix => {
|
|
203
|
+
if (ix.programId.toBase58() !== JUPLEND_PROGRAM)
|
|
204
|
+
return true;
|
|
205
|
+
// Keep known-good InitTick instructions, strip everything else from JupLend
|
|
206
|
+
if (isInitTickIx(ix)) {
|
|
207
|
+
// Strip InitTick only if accounts already exist
|
|
208
|
+
return !hasAlreadyInUse;
|
|
209
|
+
}
|
|
210
|
+
// Strip unrecognized JupLend instructions (causes FallbackNotFound)
|
|
211
|
+
return !hasFallbackNotFound;
|
|
212
|
+
});
|
|
213
|
+
if (filtered.length < finalInstructions.length) {
|
|
214
|
+
console.log("[simulation] Retrying without initTick instructions");
|
|
215
|
+
finalInstructions = filtered;
|
|
216
|
+
const retryMsg = new TransactionMessage({
|
|
217
|
+
payerKey: wallet.publicKey,
|
|
218
|
+
recentBlockhash: blockhash,
|
|
219
|
+
instructions: finalInstructions,
|
|
220
|
+
}).compileToV0Message(lookupTables);
|
|
221
|
+
txToSign = new VersionedTransaction(retryMsg);
|
|
222
|
+
const retryResult = await connection.simulateTransaction(txToSign, {
|
|
223
|
+
sigVerify: false,
|
|
224
|
+
replaceRecentBlockhash: true,
|
|
225
|
+
});
|
|
226
|
+
if (retryResult.value.err) {
|
|
227
|
+
const retryLogs = retryResult.value.logs?.slice(-10).join("\n") || "";
|
|
228
|
+
throw new Error(`Simulation failed: ${JSON.stringify(retryResult.value.err)}\n${retryLogs}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
const logStr = logs.slice(-10).join("\n");
|
|
233
|
+
throw new Error(`Simulation failed: ${JSON.stringify(simResult.value.err)}\n${logStr}`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
const logStr = logs.slice(-10).join("\n");
|
|
238
|
+
throw new Error(`Simulation failed: ${JSON.stringify(simResult.value.err)}\n${logStr}`);
|
|
239
|
+
}
|
|
240
|
+
} // close tickRebuildSucceeded else
|
|
241
|
+
}
|
|
242
|
+
// Rebuild with fresh blockhash — the original may be stale after simulation + wallet delay.
|
|
243
|
+
// Extract instructions from the compiled message and recompile with fresh blockhash.
|
|
244
|
+
const { blockhash: freshHash } = await connection.getLatestBlockhash();
|
|
245
|
+
const freshMsg = new TransactionMessage({
|
|
246
|
+
payerKey: wallet.publicKey,
|
|
247
|
+
recentBlockhash: freshHash,
|
|
248
|
+
instructions: txToSign === versionedTx ? finalInstructions : finalInstructions,
|
|
249
|
+
}).compileToV0Message(lookupTables);
|
|
250
|
+
const freshTx = new VersionedTransaction(freshMsg);
|
|
251
|
+
const signed = await wallet.signTransaction(freshTx);
|
|
252
|
+
const rawTx = signed.serialize();
|
|
253
|
+
const sig = await connection.sendRawTransaction(rawTx, {
|
|
254
|
+
skipPreflight: true,
|
|
255
|
+
});
|
|
256
|
+
// Poll for confirmation, re-sending periodically in case the TX was dropped
|
|
257
|
+
const start = Date.now();
|
|
258
|
+
const TIMEOUT_MS = 60000;
|
|
259
|
+
const RESEND_INTERVAL_MS = 4000;
|
|
260
|
+
let lastResend = Date.now();
|
|
261
|
+
while (Date.now() - start < TIMEOUT_MS) {
|
|
262
|
+
try {
|
|
263
|
+
const { value } = await connection.getSignatureStatuses([sig]);
|
|
264
|
+
const status = value[0];
|
|
265
|
+
if (status) {
|
|
266
|
+
if (status.err)
|
|
267
|
+
throw new Error(`Transaction failed: ${JSON.stringify(status.err)}`);
|
|
268
|
+
if (status.confirmationStatus === "confirmed" || status.confirmationStatus === "finalized")
|
|
269
|
+
return sig;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
catch (e) {
|
|
273
|
+
console.warn("[confirm] RPC error, retrying:", e.message?.slice(0, 80));
|
|
274
|
+
}
|
|
275
|
+
// Re-send TX periodically in case it was dropped
|
|
276
|
+
if (Date.now() - lastResend > RESEND_INTERVAL_MS) {
|
|
277
|
+
try {
|
|
278
|
+
await connection.sendRawTransaction(rawTx, { skipPreflight: true });
|
|
279
|
+
lastResend = Date.now();
|
|
280
|
+
}
|
|
281
|
+
catch { }
|
|
282
|
+
}
|
|
283
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
284
|
+
}
|
|
285
|
+
throw new Error(`Transaction not confirmed within ${TIMEOUT_MS / 1000}s. Check: https://solscan.io/tx/${sig}`);
|
|
286
|
+
}
|
|
287
|
+
//# sourceMappingURL=transactionBuilder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transactionBuilder.js","sourceRoot":"","sources":["../src/transactionBuilder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Connection, PublicKey, TransactionInstruction } from "@solana/web3.js";
|
|
2
|
+
import BN from "bn.js";
|
|
3
|
+
import type { deriveUserTokenAccounts } from "./pdas";
|
|
4
|
+
import type { VaultInfo } from "./vault/vaultAccounts";
|
|
5
|
+
export type UserTokenAccounts = Awaited<ReturnType<typeof deriveUserTokenAccounts>>;
|
|
6
|
+
export type SafeGetAccountInfo = (addr: PublicKey) => Promise<Awaited<ReturnType<Connection["getAccountInfo"]>>>;
|
|
7
|
+
export declare function makeSafeGetAccountInfo(connection: Connection): SafeGetAccountInfo;
|
|
8
|
+
/** Build wSOL wrapping instructions (create ATA if missing → transfer → sync). */
|
|
9
|
+
export declare function buildWrapSolIxs(owner: PublicKey, wsolAta: PublicKey, lamports: BN, safeGetAccountInfo: SafeGetAccountInfo): Promise<TransactionInstruction[]>;
|
|
10
|
+
/** Shares ATA (owned by the UserState PDA) for the given yield vault. */
|
|
11
|
+
export declare function getSharesAtaForVault(vaultType: string, tokens: UserTokenAccounts): PublicKey;
|
|
12
|
+
/** Fetch a LUT address from the Hobba backend; null when not configured. */
|
|
13
|
+
export declare function fetchMarketLut(apiBaseUrl: string, market: string): Promise<PublicKey | null>;
|
|
14
|
+
/** Resolve LUTs for a vault, fetching from the backend + per-vault constant. */
|
|
15
|
+
export declare function resolveVaultLuts(apiBaseUrl: string, vi: VaultInfo, extraLuts?: PublicKey[]): Promise<PublicKey[]>;
|
|
16
|
+
//# sourceMappingURL=txHelpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"txHelpers.d.ts","sourceRoot":"","sources":["../src/txHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAiB,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAM/F,OAAO,EAAE,MAAM,OAAO,CAAC;AACvB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,QAAQ,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC,CAAC;AAEpF,MAAM,MAAM,kBAAkB,GAAG,CAC/B,IAAI,EAAE,SAAS,KACZ,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;AAEhE,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,UAAU,GAAG,kBAAkB,CAQjF;AAED,kFAAkF;AAClF,wBAAsB,eAAe,CACnC,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,SAAS,EAClB,QAAQ,EAAE,EAAE,EACZ,kBAAkB,EAAE,kBAAkB,GACrC,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAenC;AAED,yEAAyE;AACzE,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,SAAS,CAW5F;AAED,4EAA4E;AAC5E,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAQ3B;AAED,gFAAgF;AAChF,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,SAAS,EACb,SAAS,CAAC,EAAE,SAAS,EAAE,GACtB,OAAO,CAAC,SAAS,EAAE,CAAC,CAwBtB"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { PublicKey, SystemProgram } from "@solana/web3.js";
|
|
2
|
+
import { createAssociatedTokenAccountInstruction, createSyncNativeInstruction, NATIVE_MINT, } from "@solana/spl-token";
|
|
3
|
+
export function makeSafeGetAccountInfo(connection) {
|
|
4
|
+
return async (addr) => {
|
|
5
|
+
try {
|
|
6
|
+
return await connection.getAccountInfo(addr);
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/** Build wSOL wrapping instructions (create ATA if missing → transfer → sync). */
|
|
14
|
+
export async function buildWrapSolIxs(owner, wsolAta, lamports, safeGetAccountInfo) {
|
|
15
|
+
const ixs = [];
|
|
16
|
+
const ataInfo = await safeGetAccountInfo(wsolAta);
|
|
17
|
+
if (!ataInfo) {
|
|
18
|
+
ixs.push(createAssociatedTokenAccountInstruction(owner, wsolAta, owner, NATIVE_MINT));
|
|
19
|
+
}
|
|
20
|
+
ixs.push(SystemProgram.transfer({
|
|
21
|
+
fromPubkey: owner,
|
|
22
|
+
toPubkey: wsolAta,
|
|
23
|
+
lamports: BigInt(lamports.toString()),
|
|
24
|
+
}), createSyncNativeInstruction(wsolAta));
|
|
25
|
+
return ixs;
|
|
26
|
+
}
|
|
27
|
+
/** Shares ATA (owned by the UserState PDA) for the given yield vault. */
|
|
28
|
+
export function getSharesAtaForVault(vaultType, tokens) {
|
|
29
|
+
switch (vaultType) {
|
|
30
|
+
case "prime":
|
|
31
|
+
return tokens.pdaPrimeSharesAta;
|
|
32
|
+
case "rockawayRWA":
|
|
33
|
+
return tokens.pdaRockawaySharesAta;
|
|
34
|
+
case "perena":
|
|
35
|
+
return tokens.pdaPerenaSharesAta;
|
|
36
|
+
default:
|
|
37
|
+
return tokens.pdaSharesAta; // allez
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Fetch a LUT address from the Hobba backend; null when not configured. */
|
|
41
|
+
export async function fetchMarketLut(apiBaseUrl, market) {
|
|
42
|
+
try {
|
|
43
|
+
const resp = await fetch(`${apiBaseUrl}/api/lut?market=${market}`);
|
|
44
|
+
const data = await resp.json();
|
|
45
|
+
return data.address ? new PublicKey(data.address) : null;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** Resolve LUTs for a vault, fetching from the backend + per-vault constant. */
|
|
52
|
+
export async function resolveVaultLuts(apiBaseUrl, vi, extraLuts) {
|
|
53
|
+
const luts = [];
|
|
54
|
+
const seen = new Set();
|
|
55
|
+
const addLut = (pk) => {
|
|
56
|
+
const key = pk.toBase58();
|
|
57
|
+
if (!seen.has(key) && !pk.equals(PublicKey.default)) {
|
|
58
|
+
seen.add(key);
|
|
59
|
+
luts.push(pk);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
if (vi.provider === "perena") {
|
|
63
|
+
const lut = await fetchMarketLut(apiBaseUrl, "perena");
|
|
64
|
+
if (lut)
|
|
65
|
+
addLut(lut);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// Vault LUT from the backend (batch accounts for the kvault CPI) …
|
|
69
|
+
const lut = await fetchMarketLut(apiBaseUrl, "vault");
|
|
70
|
+
if (lut)
|
|
71
|
+
addLut(lut);
|
|
72
|
+
// … plus the per-vault constant LUT as fallback.
|
|
73
|
+
if (!vi.lookupTable.equals(PublicKey.default))
|
|
74
|
+
addLut(vi.lookupTable);
|
|
75
|
+
}
|
|
76
|
+
if (extraLuts) {
|
|
77
|
+
for (const l of extraLuts)
|
|
78
|
+
addLut(l);
|
|
79
|
+
}
|
|
80
|
+
return luts;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=txHelpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"txHelpers.js","sourceRoot":"","sources":["../src/txHelpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Connection, PublicKey } from "@solana/web3.js";
|
|
2
|
+
export type CurrentVaultType = "allez" | "prime" | "rockawayRWA" | "perena" | "none";
|
|
3
|
+
export interface UserStateData {
|
|
4
|
+
owner: PublicKey;
|
|
5
|
+
obligation: PublicKey;
|
|
6
|
+
lendingMarket: PublicKey;
|
|
7
|
+
lendingProvider: number;
|
|
8
|
+
depositedToVault: number;
|
|
9
|
+
currentVault: PublicKey;
|
|
10
|
+
currentVaultType: CurrentVaultType;
|
|
11
|
+
collateralMint: PublicKey;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Parse a Hobba UserState account buffer. Lifted verbatim from the app's
|
|
15
|
+
* useUserState hook so the app, the widget, and headless integrators share one
|
|
16
|
+
* layout definition.
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseUserStateData(data: Buffer): UserStateData;
|
|
19
|
+
/** Fetch + parse the UserState for (owner, collateral mint). Null when none exists. */
|
|
20
|
+
export declare function fetchUserState(connection: Connection, owner: PublicKey, collateralMint: PublicKey): Promise<UserStateData | null>;
|
|
21
|
+
//# sourceMappingURL=userState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userState.d.ts","sourceRoot":"","sources":["../src/userState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAcxD,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,OAAO,GAAG,aAAa,GAAG,QAAQ,GAAG,MAAM,CAAC;AAErF,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,SAAS,CAAC;IACtB,aAAa,EAAE,SAAS,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,SAAS,CAAC;IACxB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,cAAc,EAAE,SAAS,CAAC;CAC3B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CA8C9D;AAED,uFAAuF;AACvF,wBAAsB,cAAc,CAClC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,SAAS,EAChB,cAAc,EAAE,SAAS,GACxB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAK/B"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
import BN from "bn.js";
|
|
3
|
+
import { CBBTC_MINT, DEPOSITED_TO_VAULT_OFFSET, CURRENT_VAULT_OFFSET, COLLATERAL_MINT_OFFSET, ALLEZ_USDC_VAULT, USDC_PRIME_VAULT, ROCKAWAY_RWA_VAULT, PERENA_VAULT_STATE, } from "./constants";
|
|
4
|
+
import { deriveUserStatePda } from "./pdas";
|
|
5
|
+
/**
|
|
6
|
+
* Parse a Hobba UserState account buffer. Lifted verbatim from the app's
|
|
7
|
+
* useUserState hook so the app, the widget, and headless integrators share one
|
|
8
|
+
* layout definition.
|
|
9
|
+
*/
|
|
10
|
+
export function parseUserStateData(data) {
|
|
11
|
+
const owner = new PublicKey(data.slice(9, 41));
|
|
12
|
+
const obligation = new PublicKey(data.slice(41, 73));
|
|
13
|
+
const lendingMarket = new PublicKey(data.slice(73, 105));
|
|
14
|
+
const lendingProvider = data[105];
|
|
15
|
+
let depositedToVault = 0;
|
|
16
|
+
if (data.length >= DEPOSITED_TO_VAULT_OFFSET + 8) {
|
|
17
|
+
depositedToVault = new BN(data.slice(DEPOSITED_TO_VAULT_OFFSET, DEPOSITED_TO_VAULT_OFFSET + 8), "le").toNumber();
|
|
18
|
+
}
|
|
19
|
+
let currentVault = PublicKey.default;
|
|
20
|
+
let currentVaultType = "none";
|
|
21
|
+
if (data.length >= CURRENT_VAULT_OFFSET + 32) {
|
|
22
|
+
currentVault = new PublicKey(data.slice(CURRENT_VAULT_OFFSET, CURRENT_VAULT_OFFSET + 32));
|
|
23
|
+
if (!currentVault.equals(PublicKey.default)) {
|
|
24
|
+
if (currentVault.equals(ALLEZ_USDC_VAULT))
|
|
25
|
+
currentVaultType = "allez";
|
|
26
|
+
else if (currentVault.equals(USDC_PRIME_VAULT))
|
|
27
|
+
currentVaultType = "prime";
|
|
28
|
+
else if (currentVault.equals(ROCKAWAY_RWA_VAULT))
|
|
29
|
+
currentVaultType = "rockawayRWA";
|
|
30
|
+
else if (currentVault.equals(PERENA_VAULT_STATE))
|
|
31
|
+
currentVaultType = "perena";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
let collateralMint = CBBTC_MINT; // default for older accounts
|
|
35
|
+
if (data.length >= COLLATERAL_MINT_OFFSET + 32) {
|
|
36
|
+
collateralMint = new PublicKey(data.slice(COLLATERAL_MINT_OFFSET, COLLATERAL_MINT_OFFSET + 32));
|
|
37
|
+
if (collateralMint.equals(PublicKey.default)) {
|
|
38
|
+
collateralMint = CBBTC_MINT;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
owner,
|
|
43
|
+
obligation,
|
|
44
|
+
lendingMarket,
|
|
45
|
+
lendingProvider,
|
|
46
|
+
depositedToVault,
|
|
47
|
+
currentVault,
|
|
48
|
+
currentVaultType,
|
|
49
|
+
collateralMint,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/** Fetch + parse the UserState for (owner, collateral mint). Null when none exists. */
|
|
53
|
+
export async function fetchUserState(connection, owner, collateralMint) {
|
|
54
|
+
const [pda] = deriveUserStatePda(owner, collateralMint);
|
|
55
|
+
const info = await connection.getAccountInfo(pda);
|
|
56
|
+
if (!info)
|
|
57
|
+
return null;
|
|
58
|
+
return parseUserStateData(info.data);
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=userState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userState.js","sourceRoot":"","sources":["../src/userState.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Connection, PublicKey } from "@solana/web3.js";
|
|
2
|
+
export type VaultType = "allez" | "prime" | "rockawayRWA" | "perena";
|
|
3
|
+
export type VaultProvider = "kvault" | "perena";
|
|
4
|
+
export interface VaultInfo {
|
|
5
|
+
vault: PublicKey;
|
|
6
|
+
tokenVault: PublicKey;
|
|
7
|
+
authority: PublicKey;
|
|
8
|
+
sharesMint: PublicKey;
|
|
9
|
+
lookupTable: PublicKey;
|
|
10
|
+
provider: VaultProvider;
|
|
11
|
+
batchAccounts: {
|
|
12
|
+
pubkey: PublicKey;
|
|
13
|
+
isSigner: boolean;
|
|
14
|
+
isWritable: boolean;
|
|
15
|
+
}[];
|
|
16
|
+
withdrawFixed: {
|
|
17
|
+
pubkey: PublicKey;
|
|
18
|
+
isSigner: boolean;
|
|
19
|
+
isWritable: boolean;
|
|
20
|
+
}[];
|
|
21
|
+
}
|
|
22
|
+
export declare function vaultProviderToU8(provider: VaultProvider): number;
|
|
23
|
+
/**
|
|
24
|
+
* Build KVault deposit vault_remaining:
|
|
25
|
+
* [token_vault, base_vault_authority, event_authority, kamino_program, kvault_program, ...batchAccounts]
|
|
26
|
+
*/
|
|
27
|
+
export declare function getKvaultDepositRemaining(vaultInfo: VaultInfo): AccountMeta[];
|
|
28
|
+
/**
|
|
29
|
+
* Build KVault withdraw vault_remaining:
|
|
30
|
+
* [kvault_global_config, token_vault, base_vault_authority, event_authority, kamino_program, kvault_program, ...withdrawFixed, ...batchAccounts]
|
|
31
|
+
*/
|
|
32
|
+
export declare function getKvaultWithdrawRemaining(vaultInfo: VaultInfo, withdrawFixed: AccountMeta[]): AccountMeta[];
|
|
33
|
+
export declare function getVaultInfo(vaultType: VaultType): VaultInfo;
|
|
34
|
+
type AccountMeta = {
|
|
35
|
+
pubkey: PublicKey;
|
|
36
|
+
isSigner: boolean;
|
|
37
|
+
isWritable: boolean;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Reads vault state on-chain, finds the allocation with the highest ctokenAllocation,
|
|
41
|
+
* reads that reserve to get lending_market / liquidity.supplyVault / collateral.mintPubkey,
|
|
42
|
+
* and returns the 11-account withdrawFixed array.
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveWithdrawFixed(connection: Connection, vaultPubkey: PublicKey): Promise<AccountMeta[]>;
|
|
45
|
+
export declare function identifyVaultType(vaultKey: PublicKey): VaultType | null;
|
|
46
|
+
export declare function identifyVaultProvider(vaultKey: PublicKey): VaultProvider;
|
|
47
|
+
/**
|
|
48
|
+
* Build the 16-account list for Perena deposit (mint_w_yielding_gen).
|
|
49
|
+
* These go into remaining_accounts when vault_provider = 1 (Perena).
|
|
50
|
+
* 15 instruction accounts + Perena program for CPI resolution.
|
|
51
|
+
* MarginFi accounts are omitted — Perena's crank will deploy capital later.
|
|
52
|
+
* This matches the Perena frontend behavior and avoids MarginFi ProtocolPaused errors.
|
|
53
|
+
*/
|
|
54
|
+
export declare function getPerenaDepositAccounts(pdaKey: PublicKey, pdaUsdcAta: PublicKey, pdaStarAta: PublicKey): AccountMeta[];
|
|
55
|
+
/**
|
|
56
|
+
* Build the 16-account list for Perena withdraw (burn_for_yielding_gen) WITHOUT
|
|
57
|
+
* MarginFi. Use this only as a fallback when MarginFi is paused — otherwise
|
|
58
|
+
* Perena can only pay out from its small USDC transit buffer and will fail
|
|
59
|
+
* with `insufficient funds` when that buffer is drained between crank runs.
|
|
60
|
+
*
|
|
61
|
+
* Prefer `getPerenaWithdrawAccountsWithMarginfi` for normal operation.
|
|
62
|
+
*
|
|
63
|
+
* 15 instruction accounts + Perena program for CPI resolution.
|
|
64
|
+
*/
|
|
65
|
+
export declare function getPerenaWithdrawAccounts(pdaKey: PublicKey, pdaUsdcAta: PublicKey, pdaStarAta: PublicKey): AccountMeta[];
|
|
66
|
+
/**
|
|
67
|
+
* Build the 24-account list for Perena withdraw (burn_for_yielding_gen) WITH
|
|
68
|
+
* MarginFi. This is the **default** for our flows: when the Perena USDC transit
|
|
69
|
+
* buffer is insufficient to cover the requested amount, Perena uses the
|
|
70
|
+
* MarginFi accounts to pull deployed capital back, so withdrawals don't fail.
|
|
71
|
+
*
|
|
72
|
+
* If MarginFi is paused (Perena's internal ProtocolPaused error), fall back to
|
|
73
|
+
* `getPerenaWithdrawAccounts` and retry after the next crank.
|
|
74
|
+
*
|
|
75
|
+
* 15 instruction accounts + 8 MarginFi (incl. oracle) + Perena program.
|
|
76
|
+
* MarginFi's LendingAccountWithdraw needs 1 oracle per active balance slot in
|
|
77
|
+
* Perena's marginfi account; Perena holds 2 balance slots, both USDC, so we
|
|
78
|
+
* pass the USDC oracle (position 22) and MarginFi reads it twice.
|
|
79
|
+
*/
|
|
80
|
+
export declare function getPerenaWithdrawAccountsWithMarginfi(pdaKey: PublicKey, pdaUsdcAta: PublicKey, pdaStarAta: PublicKey): AccountMeta[];
|
|
81
|
+
export {};
|
|
82
|
+
//# sourceMappingURL=vaultAccounts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vaultAccounts.d.ts","sourceRoot":"","sources":["../../src/vault/vaultAccounts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAA6C,MAAM,iBAAiB,CAAC;AA+CnG,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,aAAa,GAAG,QAAQ,CAAC;AAErE,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEhD,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,SAAS,CAAC;IACtB,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,SAAS,CAAC;IACtB,WAAW,EAAE,SAAS,CAAC;IACvB,QAAQ,EAAE,aAAa,CAAC;IACxB,aAAa,EAAE;QAAE,MAAM,EAAE,SAAS,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAC/E,aAAa,EAAE;QAAE,MAAM,EAAE,SAAS,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;CAChF;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,CAEjE;AAQD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,SAAS,GAAG,WAAW,EAAE,CAS7E;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAW5G;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,CA+C5D;AASD,KAAK,WAAW,GAAG;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CAAC;AAEjF;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,SAAS,GACrB,OAAO,CAAC,WAAW,EAAE,CAAC,CAkExB;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI,CAMvE;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,SAAS,GAAG,aAAa,CAGxE;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,SAAS,EACrB,UAAU,EAAE,SAAS,GACpB,WAAW,EAAE,CAmBf;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,SAAS,EACrB,UAAU,EAAE,SAAS,GACpB,WAAW,EAAE,CAmBf;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qCAAqC,CACnD,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,SAAS,EACrB,UAAU,EAAE,SAAS,GACpB,WAAW,EAAE,CA4Bf"}
|