@0dotxyz/p0-ts-sdk 2.2.0-alpha.5 → 2.2.0-alpha.6
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.cjs +1264 -1315
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +96 -110
- package/dist/index.d.ts +96 -110
- package/dist/index.js +1265 -1317
- package/dist/index.js.map +1 -1
- package/dist/vendor.cjs +20 -4
- package/dist/vendor.cjs.map +1 -1
- package/dist/vendor.js +20 -4
- package/dist/vendor.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -118,10 +118,9 @@ function getConfig(environment = "production", overrides) {
|
|
|
118
118
|
|
|
119
119
|
// src/errors/transaction-building.errors.ts
|
|
120
120
|
var TransactionBuildingErrorCode = /* @__PURE__ */ ((TransactionBuildingErrorCode2) => {
|
|
121
|
-
TransactionBuildingErrorCode2["JUPITER_SWAP_SIZE_EXCEEDED_REPAY"] = "JUPITER_SWAP_SIZE_EXCEEDED_REPAY";
|
|
122
|
-
TransactionBuildingErrorCode2["JUPITER_SWAP_SIZE_EXCEEDED_LOOP"] = "JUPITER_SWAP_SIZE_EXCEEDED_LOOP";
|
|
123
121
|
TransactionBuildingErrorCode2["SWAP_SIZE_EXCEEDED_LOOP"] = "SWAP_SIZE_EXCEEDED_LOOP";
|
|
124
122
|
TransactionBuildingErrorCode2["SWAP_SIZE_EXCEEDED_REPAY"] = "SWAP_SIZE_EXCEEDED_REPAY";
|
|
123
|
+
TransactionBuildingErrorCode2["SWAP_SIZE_EXCEEDED_POSITION_SWAP"] = "SWAP_SIZE_EXCEEDED_POSITION_SWAP";
|
|
125
124
|
TransactionBuildingErrorCode2["ORACLE_CRANK_FAILED"] = "ORACLE_CRANK_FAILED";
|
|
126
125
|
TransactionBuildingErrorCode2["KAMINO_RESERVE_NOT_FOUND"] = "KAMINO_RESERVE_NOT_FOUND";
|
|
127
126
|
TransactionBuildingErrorCode2["DRIFT_STATE_NOT_FOUND"] = "DRIFT_STATE_NOT_FOUND";
|
|
@@ -142,23 +141,6 @@ var TransactionBuildingError = class _TransactionBuildingError extends Error {
|
|
|
142
141
|
Error.captureStackTrace(this, _TransactionBuildingError);
|
|
143
142
|
}
|
|
144
143
|
}
|
|
145
|
-
/**
|
|
146
|
-
* Jupiter swap instruction size exceeds available transaction size
|
|
147
|
-
*/
|
|
148
|
-
static jupiterSwapSizeExceededLoop(bytes, accountKeys) {
|
|
149
|
-
return new _TransactionBuildingError(
|
|
150
|
-
"JUPITER_SWAP_SIZE_EXCEEDED_LOOP" /* JUPITER_SWAP_SIZE_EXCEEDED_LOOP */,
|
|
151
|
-
"Jupiter swap instruction size exceeds available transaction size",
|
|
152
|
-
{ bytes, accountKeys }
|
|
153
|
-
);
|
|
154
|
-
}
|
|
155
|
-
static jupiterSwapSizeExceededRepay(bytes, accountKeys) {
|
|
156
|
-
return new _TransactionBuildingError(
|
|
157
|
-
"JUPITER_SWAP_SIZE_EXCEEDED_REPAY" /* JUPITER_SWAP_SIZE_EXCEEDED_REPAY */,
|
|
158
|
-
"Jupiter swap instruction size exceeds available transaction size",
|
|
159
|
-
{ bytes, accountKeys }
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
144
|
static swapSizeExceededLoop(bytes, accountKeys, provider) {
|
|
163
145
|
return new _TransactionBuildingError(
|
|
164
146
|
"SWAP_SIZE_EXCEEDED_LOOP" /* SWAP_SIZE_EXCEEDED_LOOP */,
|
|
@@ -173,6 +155,13 @@ var TransactionBuildingError = class _TransactionBuildingError extends Error {
|
|
|
173
155
|
{ bytes, accountKeys, provider }
|
|
174
156
|
);
|
|
175
157
|
}
|
|
158
|
+
static swapSizeExceededPositionSwap(bytes, accountKeys, provider) {
|
|
159
|
+
return new _TransactionBuildingError(
|
|
160
|
+
"SWAP_SIZE_EXCEEDED_POSITION_SWAP" /* SWAP_SIZE_EXCEEDED_POSITION_SWAP */,
|
|
161
|
+
`${provider ?? "Swap"} instruction size exceeds available transaction size`,
|
|
162
|
+
{ bytes, accountKeys, provider }
|
|
163
|
+
);
|
|
164
|
+
}
|
|
176
165
|
/**
|
|
177
166
|
* Failed to crank oracles for one or more banks
|
|
178
167
|
*/
|
|
@@ -44385,12 +44374,28 @@ var V1Client = class _V1Client {
|
|
|
44385
44374
|
return new Promise((resolve, reject) => {
|
|
44386
44375
|
const ws = new WebSocket__default.default(url, [SUBPROTOCOL]);
|
|
44387
44376
|
ws.binaryType = "arraybuffer";
|
|
44388
|
-
|
|
44377
|
+
const onOpen = () => {
|
|
44378
|
+
ws.off("error", onError);
|
|
44379
|
+
ws.off("close", onClose);
|
|
44389
44380
|
resolve(new _V1Client(ws));
|
|
44390
|
-
}
|
|
44391
|
-
|
|
44381
|
+
};
|
|
44382
|
+
const onError = (err) => {
|
|
44383
|
+
ws.off("open", onOpen);
|
|
44384
|
+
ws.off("close", onClose);
|
|
44392
44385
|
reject(err);
|
|
44393
|
-
}
|
|
44386
|
+
};
|
|
44387
|
+
const onClose = (code, reason) => {
|
|
44388
|
+
ws.off("open", onOpen);
|
|
44389
|
+
ws.off("error", onError);
|
|
44390
|
+
reject(
|
|
44391
|
+
new Error(
|
|
44392
|
+
`WebSocket closed before open (code=${code}${reason.length ? `, reason=${reason.toString()}` : ""})`
|
|
44393
|
+
)
|
|
44394
|
+
);
|
|
44395
|
+
};
|
|
44396
|
+
ws.once("open", onOpen);
|
|
44397
|
+
ws.once("error", onError);
|
|
44398
|
+
ws.once("close", onClose);
|
|
44394
44399
|
});
|
|
44395
44400
|
}
|
|
44396
44401
|
// --- Constructor ---
|
|
@@ -46930,6 +46935,444 @@ async function makeJuplendDepositTx(params) {
|
|
|
46930
46935
|
});
|
|
46931
46936
|
return solanaTx;
|
|
46932
46937
|
}
|
|
46938
|
+
async function makeBeginFlashLoanIx3(program, marginfiAccountPk, endIndex, authority, isSync) {
|
|
46939
|
+
const ix = isSync && authority ? sync_instructions_default.makeBeginFlashLoanIx(
|
|
46940
|
+
program.programId,
|
|
46941
|
+
{
|
|
46942
|
+
marginfiAccount: marginfiAccountPk,
|
|
46943
|
+
authority
|
|
46944
|
+
},
|
|
46945
|
+
{ endIndex: new BN11__default.default(endIndex) }
|
|
46946
|
+
) : await instructions_default.makeBeginFlashLoanIx(
|
|
46947
|
+
program,
|
|
46948
|
+
{
|
|
46949
|
+
marginfiAccount: marginfiAccountPk,
|
|
46950
|
+
authority
|
|
46951
|
+
},
|
|
46952
|
+
{ endIndex: new BN11__default.default(endIndex) }
|
|
46953
|
+
);
|
|
46954
|
+
return { instructions: [ix], keys: [] };
|
|
46955
|
+
}
|
|
46956
|
+
async function makeEndFlashLoanIx3(program, marginfiAccountPk, projectedActiveBanks, authority, isSync) {
|
|
46957
|
+
const remainingAccounts = computeHealthAccountMetas(projectedActiveBanks);
|
|
46958
|
+
const ix = isSync && authority ? sync_instructions_default.makeEndFlashLoanIx(
|
|
46959
|
+
program.programId,
|
|
46960
|
+
{
|
|
46961
|
+
marginfiAccount: marginfiAccountPk,
|
|
46962
|
+
authority
|
|
46963
|
+
},
|
|
46964
|
+
remainingAccounts.map((account) => ({
|
|
46965
|
+
pubkey: account,
|
|
46966
|
+
isSigner: false,
|
|
46967
|
+
isWritable: false
|
|
46968
|
+
}))
|
|
46969
|
+
) : await instructions_default.makeEndFlashLoanIx(
|
|
46970
|
+
program,
|
|
46971
|
+
{
|
|
46972
|
+
marginfiAccount: marginfiAccountPk,
|
|
46973
|
+
authority
|
|
46974
|
+
},
|
|
46975
|
+
remainingAccounts.map((account) => ({
|
|
46976
|
+
pubkey: account,
|
|
46977
|
+
isSigner: false,
|
|
46978
|
+
isWritable: false
|
|
46979
|
+
}))
|
|
46980
|
+
);
|
|
46981
|
+
return { instructions: [ix], keys: [] };
|
|
46982
|
+
}
|
|
46983
|
+
async function makeFlashLoanTx({
|
|
46984
|
+
program,
|
|
46985
|
+
marginfiAccount,
|
|
46986
|
+
ixs,
|
|
46987
|
+
bankMap,
|
|
46988
|
+
blockhash,
|
|
46989
|
+
addressLookupTableAccounts,
|
|
46990
|
+
signers,
|
|
46991
|
+
isSync
|
|
46992
|
+
}) {
|
|
46993
|
+
const endIndex = ixs.length + 1;
|
|
46994
|
+
const projectedActiveBanksKeys = computeProjectedActiveBanksNoCpi(
|
|
46995
|
+
marginfiAccount.balances,
|
|
46996
|
+
ixs,
|
|
46997
|
+
program
|
|
46998
|
+
);
|
|
46999
|
+
const projectedActiveBanks = projectedActiveBanksKeys.map((account) => {
|
|
47000
|
+
const b = bankMap.get(account.toBase58());
|
|
47001
|
+
if (!b) throw Error(`Bank ${account.toBase58()} not found, in makeFlashLoanTx function`);
|
|
47002
|
+
return b;
|
|
47003
|
+
});
|
|
47004
|
+
const beginFlashLoanIx = await makeBeginFlashLoanIx3(
|
|
47005
|
+
program,
|
|
47006
|
+
marginfiAccount.address,
|
|
47007
|
+
endIndex,
|
|
47008
|
+
marginfiAccount.authority,
|
|
47009
|
+
isSync
|
|
47010
|
+
);
|
|
47011
|
+
const endFlashLoanIx = await makeEndFlashLoanIx3(
|
|
47012
|
+
program,
|
|
47013
|
+
marginfiAccount.address,
|
|
47014
|
+
projectedActiveBanks,
|
|
47015
|
+
marginfiAccount.authority,
|
|
47016
|
+
isSync
|
|
47017
|
+
);
|
|
47018
|
+
const message = new web3_js.TransactionMessage({
|
|
47019
|
+
payerKey: marginfiAccount.authority,
|
|
47020
|
+
recentBlockhash: blockhash,
|
|
47021
|
+
instructions: [...beginFlashLoanIx.instructions, ...ixs, ...endFlashLoanIx.instructions]
|
|
47022
|
+
}).compileToV0Message(addressLookupTableAccounts);
|
|
47023
|
+
const tx = addTransactionMetadata(new web3_js.VersionedTransaction(message), {
|
|
47024
|
+
addressLookupTables: addressLookupTableAccounts,
|
|
47025
|
+
type: "FLASHLOAN" /* FLASHLOAN */,
|
|
47026
|
+
signers
|
|
47027
|
+
});
|
|
47028
|
+
if (signers) {
|
|
47029
|
+
tx.sign(signers);
|
|
47030
|
+
}
|
|
47031
|
+
return tx;
|
|
47032
|
+
}
|
|
47033
|
+
|
|
47034
|
+
// src/services/account/actions/loop.ts
|
|
47035
|
+
async function makeLoopTx(params) {
|
|
47036
|
+
const {
|
|
47037
|
+
program,
|
|
47038
|
+
marginfiAccount,
|
|
47039
|
+
bankMap,
|
|
47040
|
+
depositOpts,
|
|
47041
|
+
borrowOpts,
|
|
47042
|
+
bankMetadataMap,
|
|
47043
|
+
addressLookupTableAccounts,
|
|
47044
|
+
connection,
|
|
47045
|
+
oraclePrices,
|
|
47046
|
+
crossbarUrl,
|
|
47047
|
+
additionalIxs = []
|
|
47048
|
+
} = params;
|
|
47049
|
+
const blockhash = (await connection.getLatestBlockhash("confirmed")).blockhash;
|
|
47050
|
+
const setupIxs = await makeSetupIx({
|
|
47051
|
+
connection,
|
|
47052
|
+
authority: marginfiAccount.authority,
|
|
47053
|
+
tokens: [
|
|
47054
|
+
{
|
|
47055
|
+
mint: borrowOpts.borrowBank.mint,
|
|
47056
|
+
tokenProgram: borrowOpts.tokenProgram
|
|
47057
|
+
},
|
|
47058
|
+
{
|
|
47059
|
+
mint: depositOpts.depositBank.mint,
|
|
47060
|
+
tokenProgram: depositOpts.tokenProgram
|
|
47061
|
+
}
|
|
47062
|
+
]
|
|
47063
|
+
});
|
|
47064
|
+
const updateJupLendRateIxs = makeUpdateJupLendRateIxs(
|
|
47065
|
+
params.marginfiAccount,
|
|
47066
|
+
params.bankMap,
|
|
47067
|
+
[depositOpts.depositBank.address],
|
|
47068
|
+
params.bankMetadataMap
|
|
47069
|
+
);
|
|
47070
|
+
const updateDriftMarketIxs = makeUpdateDriftMarketIxs(
|
|
47071
|
+
params.marginfiAccount,
|
|
47072
|
+
params.bankMap,
|
|
47073
|
+
[depositOpts.depositBank.address],
|
|
47074
|
+
params.bankMetadataMap
|
|
47075
|
+
);
|
|
47076
|
+
const kaminoRefreshIxs = makeRefreshKaminoBanksIxs(
|
|
47077
|
+
marginfiAccount,
|
|
47078
|
+
bankMap,
|
|
47079
|
+
[borrowOpts.borrowBank.address, depositOpts.depositBank.address],
|
|
47080
|
+
bankMetadataMap
|
|
47081
|
+
);
|
|
47082
|
+
const { flashloanTx, setupInstructions, swapQuote, amountToDeposit, depositIxs, borrowIxs } = await buildLoopFlashloanTx({
|
|
47083
|
+
...params,
|
|
47084
|
+
blockhash
|
|
47085
|
+
});
|
|
47086
|
+
const jupiterSetupInstructions = setupInstructions.filter((ix) => {
|
|
47087
|
+
if (ix.programId.equals(web3_js.ComputeBudgetProgram.programId)) {
|
|
47088
|
+
return false;
|
|
47089
|
+
}
|
|
47090
|
+
if (ix.programId.equals(ASSOCIATED_TOKEN_PROGRAM_ID)) {
|
|
47091
|
+
const mintKey = ix.keys[3]?.pubkey;
|
|
47092
|
+
if (mintKey?.equals(depositOpts.depositBank.mint) || mintKey?.equals(borrowOpts.borrowBank.mint)) {
|
|
47093
|
+
return false;
|
|
47094
|
+
}
|
|
47095
|
+
}
|
|
47096
|
+
return true;
|
|
47097
|
+
});
|
|
47098
|
+
setupIxs.push(...jupiterSetupInstructions);
|
|
47099
|
+
const { instructions: updateFeedIxs, luts: feedLuts } = await makeSmartCrankSwbFeedIx({
|
|
47100
|
+
marginfiAccount,
|
|
47101
|
+
bankMap,
|
|
47102
|
+
oraclePrices,
|
|
47103
|
+
assetShareValueMultiplierByBank: params.assetShareValueMultiplierByBank,
|
|
47104
|
+
instructions: [...borrowIxs.instructions, ...depositIxs.instructions],
|
|
47105
|
+
program,
|
|
47106
|
+
connection,
|
|
47107
|
+
crossbarUrl
|
|
47108
|
+
});
|
|
47109
|
+
let additionalTxs = [];
|
|
47110
|
+
if (depositOpts.depositBank.mint.equals(NATIVE_MINT) && depositOpts.inputDepositAmount) {
|
|
47111
|
+
setupIxs.push(
|
|
47112
|
+
...makeWrapSolIxs(marginfiAccount.authority, new BigNumber3.BigNumber(depositOpts.inputDepositAmount))
|
|
47113
|
+
);
|
|
47114
|
+
}
|
|
47115
|
+
if (setupIxs.length > 0 || additionalIxs.length > 0 || kaminoRefreshIxs.instructions.length > 0 || updateDriftMarketIxs.instructions.length > 0 || updateJupLendRateIxs.instructions.length > 0) {
|
|
47116
|
+
const ixs = [
|
|
47117
|
+
...additionalIxs,
|
|
47118
|
+
...setupIxs,
|
|
47119
|
+
...kaminoRefreshIxs.instructions,
|
|
47120
|
+
...updateDriftMarketIxs.instructions,
|
|
47121
|
+
...updateJupLendRateIxs.instructions
|
|
47122
|
+
];
|
|
47123
|
+
const txs = splitInstructionsToFitTransactions([], ixs, {
|
|
47124
|
+
blockhash,
|
|
47125
|
+
payerKey: marginfiAccount.authority,
|
|
47126
|
+
luts: addressLookupTableAccounts ?? []
|
|
47127
|
+
});
|
|
47128
|
+
additionalTxs.push(
|
|
47129
|
+
...txs.map(
|
|
47130
|
+
(tx) => addTransactionMetadata(tx, {
|
|
47131
|
+
type: "CREATE_ATA" /* CREATE_ATA */,
|
|
47132
|
+
addressLookupTables: addressLookupTableAccounts
|
|
47133
|
+
})
|
|
47134
|
+
)
|
|
47135
|
+
);
|
|
47136
|
+
}
|
|
47137
|
+
if (updateFeedIxs.length > 0) {
|
|
47138
|
+
const message = new web3_js.TransactionMessage({
|
|
47139
|
+
payerKey: marginfiAccount.authority,
|
|
47140
|
+
recentBlockhash: blockhash,
|
|
47141
|
+
instructions: updateFeedIxs
|
|
47142
|
+
}).compileToV0Message(feedLuts);
|
|
47143
|
+
additionalTxs.push(
|
|
47144
|
+
addTransactionMetadata(new web3_js.VersionedTransaction(message), {
|
|
47145
|
+
addressLookupTables: feedLuts,
|
|
47146
|
+
type: "CRANK" /* CRANK */
|
|
47147
|
+
})
|
|
47148
|
+
);
|
|
47149
|
+
}
|
|
47150
|
+
const transactions = [...additionalTxs, flashloanTx];
|
|
47151
|
+
return {
|
|
47152
|
+
transactions,
|
|
47153
|
+
actionTxIndex: transactions.length - 1,
|
|
47154
|
+
quoteResponse: swapQuote
|
|
47155
|
+
};
|
|
47156
|
+
}
|
|
47157
|
+
async function buildLoopFlashloanTx({
|
|
47158
|
+
program,
|
|
47159
|
+
marginfiAccount,
|
|
47160
|
+
bankMap,
|
|
47161
|
+
borrowOpts,
|
|
47162
|
+
depositOpts,
|
|
47163
|
+
bankMetadataMap,
|
|
47164
|
+
addressLookupTableAccounts,
|
|
47165
|
+
connection,
|
|
47166
|
+
swapOpts,
|
|
47167
|
+
overrideInferAccounts,
|
|
47168
|
+
blockhash
|
|
47169
|
+
}) {
|
|
47170
|
+
const cuRequestIxs = [
|
|
47171
|
+
web3_js.ComputeBudgetProgram.setComputeUnitLimit({ units: 12e5 }),
|
|
47172
|
+
web3_js.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 })
|
|
47173
|
+
];
|
|
47174
|
+
let amountToDeposit;
|
|
47175
|
+
let swapInstructions = [];
|
|
47176
|
+
let setupInstructions = [];
|
|
47177
|
+
let swapLookupTables = [];
|
|
47178
|
+
let swapQuote;
|
|
47179
|
+
let sizeConstraintUsed = 0;
|
|
47180
|
+
if (depositOpts.depositBank.mint.equals(borrowOpts.borrowBank.mint)) {
|
|
47181
|
+
amountToDeposit = borrowOpts.borrowAmount + (depositOpts.loopMode === "DEPOSIT" ? depositOpts.inputDepositAmount : 0);
|
|
47182
|
+
} else {
|
|
47183
|
+
const destinationTokenAccount = getAssociatedTokenAddressSync(
|
|
47184
|
+
new web3_js.PublicKey(depositOpts.depositBank.mint),
|
|
47185
|
+
marginfiAccount.authority,
|
|
47186
|
+
true,
|
|
47187
|
+
depositOpts.tokenProgram.equals(TOKEN_2022_PROGRAM_ID) ? TOKEN_2022_PROGRAM_ID : void 0
|
|
47188
|
+
);
|
|
47189
|
+
const swapConstraints = await computeFlashloanSwapConstraints({
|
|
47190
|
+
program,
|
|
47191
|
+
marginfiAccount,
|
|
47192
|
+
bankMap,
|
|
47193
|
+
bankMetadataMap,
|
|
47194
|
+
addressLookupTableAccounts: addressLookupTableAccounts ?? [],
|
|
47195
|
+
primaryIx: {
|
|
47196
|
+
type: "borrow",
|
|
47197
|
+
bank: borrowOpts.borrowBank,
|
|
47198
|
+
tokenProgram: borrowOpts.tokenProgram
|
|
47199
|
+
},
|
|
47200
|
+
secondaryIx: {
|
|
47201
|
+
type: "deposit",
|
|
47202
|
+
bank: depositOpts.depositBank,
|
|
47203
|
+
tokenProgram: depositOpts.tokenProgram
|
|
47204
|
+
},
|
|
47205
|
+
overrideInferAccounts
|
|
47206
|
+
});
|
|
47207
|
+
const swapResponse = await getSwapIxsForFlashloan({
|
|
47208
|
+
inputMint: borrowOpts.borrowBank.mint.toBase58(),
|
|
47209
|
+
outputMint: depositOpts.depositBank.mint.toBase58(),
|
|
47210
|
+
amount: uiToNative(borrowOpts.borrowAmount, borrowOpts.borrowBank.mintDecimals).toNumber(),
|
|
47211
|
+
swapMode: "ExactIn",
|
|
47212
|
+
authority: marginfiAccount.authority,
|
|
47213
|
+
connection,
|
|
47214
|
+
destinationTokenAccount,
|
|
47215
|
+
swapOpts,
|
|
47216
|
+
sizeConstraint: swapConstraints.sizeConstraint,
|
|
47217
|
+
maxSwapTotalAccounts: swapConstraints.maxSwapTotalAccounts
|
|
47218
|
+
});
|
|
47219
|
+
sizeConstraintUsed = swapConstraints.sizeConstraint;
|
|
47220
|
+
const outAmountThreshold = nativeToUi(
|
|
47221
|
+
swapResponse.quoteResponse.otherAmountThreshold,
|
|
47222
|
+
depositOpts.depositBank.mintDecimals
|
|
47223
|
+
);
|
|
47224
|
+
amountToDeposit = outAmountThreshold + (depositOpts.loopMode === "DEPOSIT" ? depositOpts.inputDepositAmount : 0);
|
|
47225
|
+
swapInstructions = swapResponse.swapInstructions;
|
|
47226
|
+
setupInstructions = swapResponse.setupInstructions;
|
|
47227
|
+
swapLookupTables = swapResponse.addressLookupTableAddresses;
|
|
47228
|
+
swapQuote = swapResponse.quoteResponse;
|
|
47229
|
+
}
|
|
47230
|
+
const borrowIxs = await makeBorrowIx3({
|
|
47231
|
+
program,
|
|
47232
|
+
bank: borrowOpts.borrowBank,
|
|
47233
|
+
bankMap,
|
|
47234
|
+
tokenProgram: borrowOpts.tokenProgram,
|
|
47235
|
+
amount: borrowOpts.borrowAmount,
|
|
47236
|
+
marginfiAccount,
|
|
47237
|
+
authority: marginfiAccount.authority,
|
|
47238
|
+
isSync: false,
|
|
47239
|
+
opts: {
|
|
47240
|
+
createAtas: false,
|
|
47241
|
+
wrapAndUnwrapSol: false,
|
|
47242
|
+
overrideInferAccounts
|
|
47243
|
+
}
|
|
47244
|
+
});
|
|
47245
|
+
let depositIxs;
|
|
47246
|
+
switch (depositOpts.depositBank.config.assetTag) {
|
|
47247
|
+
case 3 /* KAMINO */: {
|
|
47248
|
+
const reserve = bankMetadataMap[depositOpts.depositBank.address.toBase58()]?.kaminoStates?.reserveState;
|
|
47249
|
+
if (!reserve) {
|
|
47250
|
+
throw TransactionBuildingError.kaminoReserveNotFound(
|
|
47251
|
+
depositOpts.depositBank.address.toBase58(),
|
|
47252
|
+
depositOpts.depositBank.mint.toBase58(),
|
|
47253
|
+
depositOpts.depositBank.tokenSymbol
|
|
47254
|
+
);
|
|
47255
|
+
}
|
|
47256
|
+
depositIxs = await makeKaminoDepositIx3({
|
|
47257
|
+
program,
|
|
47258
|
+
bank: depositOpts.depositBank,
|
|
47259
|
+
tokenProgram: depositOpts.tokenProgram,
|
|
47260
|
+
amount: amountToDeposit,
|
|
47261
|
+
accountAddress: marginfiAccount.address,
|
|
47262
|
+
authority: marginfiAccount.authority,
|
|
47263
|
+
group: marginfiAccount.group,
|
|
47264
|
+
reserve,
|
|
47265
|
+
opts: {
|
|
47266
|
+
wrapAndUnwrapSol: false,
|
|
47267
|
+
overrideInferAccounts
|
|
47268
|
+
}
|
|
47269
|
+
});
|
|
47270
|
+
break;
|
|
47271
|
+
}
|
|
47272
|
+
case 4 /* DRIFT */: {
|
|
47273
|
+
const driftState = bankMetadataMap[depositOpts.depositBank.address.toBase58()]?.driftStates;
|
|
47274
|
+
if (!driftState) {
|
|
47275
|
+
throw TransactionBuildingError.driftStateNotFound(
|
|
47276
|
+
depositOpts.depositBank.address.toBase58(),
|
|
47277
|
+
depositOpts.depositBank.mint.toBase58(),
|
|
47278
|
+
depositOpts.depositBank.tokenSymbol
|
|
47279
|
+
);
|
|
47280
|
+
}
|
|
47281
|
+
const driftMarketIndex = driftState.spotMarketState.marketIndex;
|
|
47282
|
+
const driftOracle = driftState.spotMarketState.oracle;
|
|
47283
|
+
depositIxs = await makeDriftDepositIx3({
|
|
47284
|
+
program,
|
|
47285
|
+
bank: depositOpts.depositBank,
|
|
47286
|
+
tokenProgram: depositOpts.tokenProgram,
|
|
47287
|
+
amount: amountToDeposit,
|
|
47288
|
+
accountAddress: marginfiAccount.address,
|
|
47289
|
+
authority: marginfiAccount.authority,
|
|
47290
|
+
group: marginfiAccount.group,
|
|
47291
|
+
driftMarketIndex,
|
|
47292
|
+
driftOracle,
|
|
47293
|
+
opts: {
|
|
47294
|
+
wrapAndUnwrapSol: false,
|
|
47295
|
+
overrideInferAccounts
|
|
47296
|
+
}
|
|
47297
|
+
});
|
|
47298
|
+
break;
|
|
47299
|
+
}
|
|
47300
|
+
case 6 /* JUPLEND */: {
|
|
47301
|
+
depositIxs = await makeJuplendDepositIx2({
|
|
47302
|
+
program,
|
|
47303
|
+
bank: depositOpts.depositBank,
|
|
47304
|
+
tokenProgram: depositOpts.tokenProgram,
|
|
47305
|
+
amount: amountToDeposit,
|
|
47306
|
+
accountAddress: marginfiAccount.address,
|
|
47307
|
+
authority: marginfiAccount.authority,
|
|
47308
|
+
group: marginfiAccount.group,
|
|
47309
|
+
opts: {
|
|
47310
|
+
wrapAndUnwrapSol: false,
|
|
47311
|
+
overrideInferAccounts
|
|
47312
|
+
}
|
|
47313
|
+
});
|
|
47314
|
+
break;
|
|
47315
|
+
}
|
|
47316
|
+
default: {
|
|
47317
|
+
depositIxs = await makeDepositIx3({
|
|
47318
|
+
program,
|
|
47319
|
+
bank: depositOpts.depositBank,
|
|
47320
|
+
tokenProgram: depositOpts.tokenProgram,
|
|
47321
|
+
amount: amountToDeposit,
|
|
47322
|
+
accountAddress: marginfiAccount.address,
|
|
47323
|
+
authority: marginfiAccount.authority,
|
|
47324
|
+
group: marginfiAccount.group,
|
|
47325
|
+
opts: {
|
|
47326
|
+
wrapAndUnwrapSol: false,
|
|
47327
|
+
overrideInferAccounts
|
|
47328
|
+
}
|
|
47329
|
+
});
|
|
47330
|
+
break;
|
|
47331
|
+
}
|
|
47332
|
+
}
|
|
47333
|
+
const luts = [...addressLookupTableAccounts ?? [], ...swapLookupTables];
|
|
47334
|
+
const allNonFlIxs = [
|
|
47335
|
+
...cuRequestIxs,
|
|
47336
|
+
...borrowIxs.instructions,
|
|
47337
|
+
...swapInstructions,
|
|
47338
|
+
...depositIxs.instructions
|
|
47339
|
+
];
|
|
47340
|
+
if (swapInstructions.length > 0) {
|
|
47341
|
+
compileFlashloanPrecheck({
|
|
47342
|
+
allIxs: allNonFlIxs,
|
|
47343
|
+
payer: marginfiAccount.authority,
|
|
47344
|
+
luts,
|
|
47345
|
+
sizeConstraint: sizeConstraintUsed,
|
|
47346
|
+
swapIxCount: swapInstructions.length,
|
|
47347
|
+
swapLutCount: swapLookupTables.length
|
|
47348
|
+
});
|
|
47349
|
+
}
|
|
47350
|
+
const flashloanTx = await makeFlashLoanTx({
|
|
47351
|
+
program,
|
|
47352
|
+
marginfiAccount,
|
|
47353
|
+
bankMap,
|
|
47354
|
+
addressLookupTableAccounts: luts,
|
|
47355
|
+
blockhash,
|
|
47356
|
+
ixs: allNonFlIxs
|
|
47357
|
+
});
|
|
47358
|
+
const txSize = getTxSize(flashloanTx);
|
|
47359
|
+
const totalKeys = getTotalAccountKeys(flashloanTx);
|
|
47360
|
+
if (txSize > MAX_TX_SIZE || totalKeys > MAX_ACCOUNT_LOCKS) {
|
|
47361
|
+
throw TransactionBuildingError.swapSizeExceededLoop(
|
|
47362
|
+
txSize,
|
|
47363
|
+
totalKeys,
|
|
47364
|
+
swapOpts.swapConfig?.provider
|
|
47365
|
+
);
|
|
47366
|
+
}
|
|
47367
|
+
return {
|
|
47368
|
+
flashloanTx,
|
|
47369
|
+
setupInstructions,
|
|
47370
|
+
swapQuote,
|
|
47371
|
+
borrowIxs,
|
|
47372
|
+
depositIxs,
|
|
47373
|
+
amountToDeposit
|
|
47374
|
+
};
|
|
47375
|
+
}
|
|
46933
47376
|
async function makeRepayIx3({
|
|
46934
47377
|
program,
|
|
46935
47378
|
bank,
|
|
@@ -47384,882 +47827,6 @@ async function buildRepayWithCollatFlashloanTx({
|
|
|
47384
47827
|
};
|
|
47385
47828
|
}
|
|
47386
47829
|
|
|
47387
|
-
// src/services/account/utils/flashloan-size.utils.ts
|
|
47388
|
-
var SWAP_MERGE_OVERHEAD = 150;
|
|
47389
|
-
var FL_IX_OVERHEAD = 52;
|
|
47390
|
-
function compactU16Size(n) {
|
|
47391
|
-
return n < 128 ? 1 : n < 16384 ? 2 : 3;
|
|
47392
|
-
}
|
|
47393
|
-
function computeV0TxSize(ixs, payerKey, luts) {
|
|
47394
|
-
const keyMap = /* @__PURE__ */ new Map();
|
|
47395
|
-
const payerStr = payerKey.toBase58();
|
|
47396
|
-
keyMap.set(payerStr, { isSigner: true, isWritable: true });
|
|
47397
|
-
const programIds = /* @__PURE__ */ new Set();
|
|
47398
|
-
for (const ix of ixs) {
|
|
47399
|
-
const progStr = ix.programId.toBase58();
|
|
47400
|
-
programIds.add(progStr);
|
|
47401
|
-
if (!keyMap.has(progStr)) {
|
|
47402
|
-
keyMap.set(progStr, { isSigner: false, isWritable: false });
|
|
47403
|
-
}
|
|
47404
|
-
for (const meta of ix.keys) {
|
|
47405
|
-
const keyStr = meta.pubkey.toBase58();
|
|
47406
|
-
const existing = keyMap.get(keyStr);
|
|
47407
|
-
if (existing) {
|
|
47408
|
-
existing.isSigner = existing.isSigner || meta.isSigner;
|
|
47409
|
-
existing.isWritable = existing.isWritable || meta.isWritable;
|
|
47410
|
-
} else {
|
|
47411
|
-
keyMap.set(keyStr, { isSigner: meta.isSigner, isWritable: meta.isWritable });
|
|
47412
|
-
}
|
|
47413
|
-
}
|
|
47414
|
-
}
|
|
47415
|
-
const lutLookup = /* @__PURE__ */ new Map();
|
|
47416
|
-
for (let li = 0; li < luts.length; li++) {
|
|
47417
|
-
const addresses = luts[li].state.addresses;
|
|
47418
|
-
for (let ai = 0; ai < addresses.length; ai++) {
|
|
47419
|
-
const addrStr = addresses[ai].toBase58();
|
|
47420
|
-
if (!lutLookup.has(addrStr)) {
|
|
47421
|
-
lutLookup.set(addrStr, { lutIdx: li, addrIdx: ai });
|
|
47422
|
-
}
|
|
47423
|
-
}
|
|
47424
|
-
}
|
|
47425
|
-
let numStaticKeys = 0;
|
|
47426
|
-
let numWritableStaticKeys = 0;
|
|
47427
|
-
const lutWritableIdxs = luts.map(() => /* @__PURE__ */ new Set());
|
|
47428
|
-
const lutReadonlyIdxs = luts.map(() => /* @__PURE__ */ new Set());
|
|
47429
|
-
for (const [keyStr, props] of keyMap) {
|
|
47430
|
-
if (props.isSigner || programIds.has(keyStr)) {
|
|
47431
|
-
numStaticKeys++;
|
|
47432
|
-
if (props.isWritable) numWritableStaticKeys++;
|
|
47433
|
-
continue;
|
|
47434
|
-
}
|
|
47435
|
-
const lutEntry = lutLookup.get(keyStr);
|
|
47436
|
-
if (lutEntry) {
|
|
47437
|
-
if (props.isWritable) {
|
|
47438
|
-
lutWritableIdxs[lutEntry.lutIdx].add(lutEntry.addrIdx);
|
|
47439
|
-
} else {
|
|
47440
|
-
lutReadonlyIdxs[lutEntry.lutIdx].add(lutEntry.addrIdx);
|
|
47441
|
-
}
|
|
47442
|
-
} else {
|
|
47443
|
-
numStaticKeys++;
|
|
47444
|
-
if (props.isWritable) numWritableStaticKeys++;
|
|
47445
|
-
}
|
|
47446
|
-
}
|
|
47447
|
-
const fixedOverhead = 101;
|
|
47448
|
-
const staticKeysSection = compactU16Size(numStaticKeys) + numStaticKeys * 32;
|
|
47449
|
-
let ixSection = compactU16Size(ixs.length);
|
|
47450
|
-
for (const ix of ixs) {
|
|
47451
|
-
const numAccounts = ix.keys.length;
|
|
47452
|
-
ixSection += 1 + // programId index
|
|
47453
|
-
compactU16Size(numAccounts) + numAccounts + // account key indexes
|
|
47454
|
-
compactU16Size(ix.data.length) + ix.data.length;
|
|
47455
|
-
}
|
|
47456
|
-
let numUsedLuts = 0;
|
|
47457
|
-
let lutSection = 0;
|
|
47458
|
-
for (let li = 0; li < luts.length; li++) {
|
|
47459
|
-
const wCount = lutWritableIdxs[li].size;
|
|
47460
|
-
const rCount = lutReadonlyIdxs[li].size;
|
|
47461
|
-
if (wCount === 0 && rCount === 0) continue;
|
|
47462
|
-
numUsedLuts++;
|
|
47463
|
-
lutSection += 32 + // LUT address
|
|
47464
|
-
compactU16Size(wCount) + wCount + // writable indexes
|
|
47465
|
-
compactU16Size(rCount) + rCount;
|
|
47466
|
-
}
|
|
47467
|
-
lutSection += compactU16Size(numUsedLuts);
|
|
47468
|
-
let totalLutKeys = 0;
|
|
47469
|
-
for (let li = 0; li < luts.length; li++) {
|
|
47470
|
-
totalLutKeys += lutWritableIdxs[li].size + lutReadonlyIdxs[li].size;
|
|
47471
|
-
}
|
|
47472
|
-
const accountCount = numStaticKeys + totalLutKeys;
|
|
47473
|
-
let totalLutWritableKeys = 0;
|
|
47474
|
-
for (let li = 0; li < luts.length; li++) {
|
|
47475
|
-
totalLutWritableKeys += lutWritableIdxs[li].size;
|
|
47476
|
-
}
|
|
47477
|
-
const writableAccountCount = numWritableStaticKeys + totalLutWritableKeys;
|
|
47478
|
-
const size = fixedOverhead + staticKeysSection + ixSection + lutSection + 1;
|
|
47479
|
-
return { size, accountCount, writableAccountCount };
|
|
47480
|
-
}
|
|
47481
|
-
function computeFlashLoanNonSwapBudget({
|
|
47482
|
-
program,
|
|
47483
|
-
marginfiAccount,
|
|
47484
|
-
ixs,
|
|
47485
|
-
bankMap,
|
|
47486
|
-
addressLookupTableAccounts
|
|
47487
|
-
}) {
|
|
47488
|
-
const projectedActiveBanksKeys = computeProjectedActiveBanksNoCpi(
|
|
47489
|
-
marginfiAccount.balances,
|
|
47490
|
-
ixs,
|
|
47491
|
-
program
|
|
47492
|
-
);
|
|
47493
|
-
const projectedActiveBanks = projectedActiveBanksKeys.map((key) => {
|
|
47494
|
-
const b = bankMap.get(key.toBase58());
|
|
47495
|
-
if (!b) throw new Error(`Bank ${key.toBase58()} not found in computeFlashLoanNonSwapBudget`);
|
|
47496
|
-
return b;
|
|
47497
|
-
});
|
|
47498
|
-
const endIndex = ixs.length + 1;
|
|
47499
|
-
const beginFlIx = sync_instructions_default.makeBeginFlashLoanIx(
|
|
47500
|
-
program.programId,
|
|
47501
|
-
{ marginfiAccount: marginfiAccount.address, authority: marginfiAccount.authority },
|
|
47502
|
-
{ endIndex: new BN11__default.default(endIndex) }
|
|
47503
|
-
);
|
|
47504
|
-
const endFlRemainingAccounts = computeHealthAccountMetas(projectedActiveBanks);
|
|
47505
|
-
const endFlIx = sync_instructions_default.makeEndFlashLoanIx(
|
|
47506
|
-
program.programId,
|
|
47507
|
-
{ marginfiAccount: marginfiAccount.address, authority: marginfiAccount.authority },
|
|
47508
|
-
endFlRemainingAccounts.map((pubkey) => ({ pubkey, isSigner: false, isWritable: false }))
|
|
47509
|
-
);
|
|
47510
|
-
const allNonSwapIxs = [beginFlIx, ...ixs, endFlIx];
|
|
47511
|
-
const nonSwapMsg = new web3_js.TransactionMessage({
|
|
47512
|
-
payerKey: marginfiAccount.authority,
|
|
47513
|
-
recentBlockhash: web3_js.PublicKey.default.toBase58(),
|
|
47514
|
-
instructions: allNonSwapIxs
|
|
47515
|
-
}).compileToV0Message(addressLookupTableAccounts);
|
|
47516
|
-
const nonSwapSize = new web3_js.VersionedTransaction(nonSwapMsg).serialize().length;
|
|
47517
|
-
const { header, staticAccountKeys, addressTableLookups } = nonSwapMsg;
|
|
47518
|
-
const nonSwapTotal = staticAccountKeys.length + addressTableLookups.reduce(
|
|
47519
|
-
(s, l) => s + l.writableIndexes.length + l.readonlyIndexes.length,
|
|
47520
|
-
0
|
|
47521
|
-
);
|
|
47522
|
-
const sizeConstraint = MAX_TX_SIZE - nonSwapSize - SWAP_MERGE_OVERHEAD;
|
|
47523
|
-
const maxSwapTotalAccounts = MAX_ACCOUNT_LOCKS - nonSwapTotal;
|
|
47524
|
-
console.log("[flashloan-budget]", {
|
|
47525
|
-
method: "compiled",
|
|
47526
|
-
nonSwapSize,
|
|
47527
|
-
nonSwapTotal,
|
|
47528
|
-
sizeConstraint,
|
|
47529
|
-
maxSwapTotalAccounts
|
|
47530
|
-
});
|
|
47531
|
-
return { sizeConstraint, maxSwapTotalAccounts };
|
|
47532
|
-
}
|
|
47533
|
-
function compileFlashloanPrecheck({
|
|
47534
|
-
allIxs,
|
|
47535
|
-
payer,
|
|
47536
|
-
luts,
|
|
47537
|
-
sizeConstraint,
|
|
47538
|
-
swapIxCount,
|
|
47539
|
-
swapLutCount
|
|
47540
|
-
}) {
|
|
47541
|
-
const msg = new web3_js.TransactionMessage({
|
|
47542
|
-
payerKey: payer,
|
|
47543
|
-
recentBlockhash: web3_js.PublicKey.default.toBase58(),
|
|
47544
|
-
instructions: allIxs
|
|
47545
|
-
}).compileToV0Message(luts);
|
|
47546
|
-
const rawSize = new web3_js.VersionedTransaction(msg).serialize().length;
|
|
47547
|
-
const fullTxSize = rawSize + FL_IX_OVERHEAD;
|
|
47548
|
-
const overshoot = fullTxSize - MAX_TX_SIZE;
|
|
47549
|
-
const { header, staticAccountKeys, addressTableLookups } = msg;
|
|
47550
|
-
const writableStatic = staticAccountKeys.length - header.numReadonlySignedAccounts - header.numReadonlyUnsignedAccounts;
|
|
47551
|
-
const writableLut = addressTableLookups.reduce((s, l) => s + l.writableIndexes.length, 0);
|
|
47552
|
-
const writableAccounts = writableStatic + writableLut;
|
|
47553
|
-
const totalAccounts = staticAccountKeys.length + addressTableLookups.reduce(
|
|
47554
|
-
(s, l) => s + l.writableIndexes.length + l.readonlyIndexes.length,
|
|
47555
|
-
0
|
|
47556
|
-
);
|
|
47557
|
-
console.log("[flashloan-precheck]", {
|
|
47558
|
-
fullTxSize,
|
|
47559
|
-
overshoot,
|
|
47560
|
-
sizeConstraint,
|
|
47561
|
-
writableAccounts,
|
|
47562
|
-
totalAccounts,
|
|
47563
|
-
staticKeys: staticAccountKeys.length,
|
|
47564
|
-
numLuts: addressTableLookups.length,
|
|
47565
|
-
swapIxCount,
|
|
47566
|
-
swapLutCount
|
|
47567
|
-
});
|
|
47568
|
-
return { fullTxSize, overshoot, writableAccounts, totalAccounts };
|
|
47569
|
-
}
|
|
47570
|
-
async function buildBudgetIx(config, program, marginfiAccount, bankMap, bankMetadataMap, overrideInferAccounts) {
|
|
47571
|
-
const { bank, tokenProgram } = config;
|
|
47572
|
-
switch (config.type) {
|
|
47573
|
-
case "borrow":
|
|
47574
|
-
return makeBorrowIx3({
|
|
47575
|
-
program,
|
|
47576
|
-
bank,
|
|
47577
|
-
bankMap,
|
|
47578
|
-
tokenProgram,
|
|
47579
|
-
amount: 1,
|
|
47580
|
-
marginfiAccount,
|
|
47581
|
-
authority: marginfiAccount.authority,
|
|
47582
|
-
isSync: true,
|
|
47583
|
-
opts: { createAtas: false, wrapAndUnwrapSol: false, overrideInferAccounts }
|
|
47584
|
-
});
|
|
47585
|
-
case "repay":
|
|
47586
|
-
return makeRepayIx3({
|
|
47587
|
-
program,
|
|
47588
|
-
bank,
|
|
47589
|
-
tokenProgram,
|
|
47590
|
-
amount: 1,
|
|
47591
|
-
accountAddress: marginfiAccount.address,
|
|
47592
|
-
authority: marginfiAccount.authority,
|
|
47593
|
-
repayAll: false,
|
|
47594
|
-
isSync: true,
|
|
47595
|
-
opts: { wrapAndUnwrapSol: false, overrideInferAccounts }
|
|
47596
|
-
});
|
|
47597
|
-
case "deposit":
|
|
47598
|
-
return buildDepositBudgetIx(
|
|
47599
|
-
config,
|
|
47600
|
-
program,
|
|
47601
|
-
marginfiAccount,
|
|
47602
|
-
bankMetadataMap,
|
|
47603
|
-
overrideInferAccounts
|
|
47604
|
-
);
|
|
47605
|
-
case "withdraw":
|
|
47606
|
-
return buildWithdrawBudgetIx(
|
|
47607
|
-
config,
|
|
47608
|
-
program,
|
|
47609
|
-
marginfiAccount,
|
|
47610
|
-
bankMap,
|
|
47611
|
-
bankMetadataMap,
|
|
47612
|
-
overrideInferAccounts
|
|
47613
|
-
);
|
|
47614
|
-
}
|
|
47615
|
-
}
|
|
47616
|
-
async function buildDepositBudgetIx(config, program, marginfiAccount, bankMetadataMap, overrideInferAccounts) {
|
|
47617
|
-
const { bank, tokenProgram } = config;
|
|
47618
|
-
const opts = { wrapAndUnwrapSol: false, overrideInferAccounts };
|
|
47619
|
-
switch (bank.config.assetTag) {
|
|
47620
|
-
case 3 /* KAMINO */: {
|
|
47621
|
-
const reserve = bankMetadataMap[bank.address.toBase58()]?.kaminoStates?.reserveState;
|
|
47622
|
-
if (!reserve) {
|
|
47623
|
-
throw TransactionBuildingError.kaminoReserveNotFound(
|
|
47624
|
-
bank.address.toBase58(),
|
|
47625
|
-
bank.mint.toBase58(),
|
|
47626
|
-
bank.tokenSymbol
|
|
47627
|
-
);
|
|
47628
|
-
}
|
|
47629
|
-
return makeKaminoDepositIx3({
|
|
47630
|
-
program,
|
|
47631
|
-
bank,
|
|
47632
|
-
tokenProgram,
|
|
47633
|
-
amount: 1,
|
|
47634
|
-
accountAddress: marginfiAccount.address,
|
|
47635
|
-
authority: marginfiAccount.authority,
|
|
47636
|
-
group: marginfiAccount.group,
|
|
47637
|
-
reserve,
|
|
47638
|
-
isSync: true,
|
|
47639
|
-
opts
|
|
47640
|
-
});
|
|
47641
|
-
}
|
|
47642
|
-
case 4 /* DRIFT */: {
|
|
47643
|
-
const driftState = bankMetadataMap[bank.address.toBase58()]?.driftStates;
|
|
47644
|
-
if (!driftState) {
|
|
47645
|
-
throw TransactionBuildingError.driftStateNotFound(
|
|
47646
|
-
bank.address.toBase58(),
|
|
47647
|
-
bank.mint.toBase58(),
|
|
47648
|
-
bank.tokenSymbol
|
|
47649
|
-
);
|
|
47650
|
-
}
|
|
47651
|
-
return makeDriftDepositIx3({
|
|
47652
|
-
program,
|
|
47653
|
-
bank,
|
|
47654
|
-
tokenProgram,
|
|
47655
|
-
amount: 1,
|
|
47656
|
-
accountAddress: marginfiAccount.address,
|
|
47657
|
-
authority: marginfiAccount.authority,
|
|
47658
|
-
group: marginfiAccount.group,
|
|
47659
|
-
driftMarketIndex: driftState.spotMarketState.marketIndex,
|
|
47660
|
-
driftOracle: driftState.spotMarketState.oracle,
|
|
47661
|
-
isSync: true,
|
|
47662
|
-
opts
|
|
47663
|
-
});
|
|
47664
|
-
}
|
|
47665
|
-
case 6 /* JUPLEND */: {
|
|
47666
|
-
return makeJuplendDepositIx2({
|
|
47667
|
-
program,
|
|
47668
|
-
bank,
|
|
47669
|
-
tokenProgram,
|
|
47670
|
-
amount: 1,
|
|
47671
|
-
accountAddress: marginfiAccount.address,
|
|
47672
|
-
authority: marginfiAccount.authority,
|
|
47673
|
-
group: marginfiAccount.group,
|
|
47674
|
-
isSync: true,
|
|
47675
|
-
opts
|
|
47676
|
-
});
|
|
47677
|
-
}
|
|
47678
|
-
default: {
|
|
47679
|
-
return makeDepositIx3({
|
|
47680
|
-
program,
|
|
47681
|
-
bank,
|
|
47682
|
-
tokenProgram,
|
|
47683
|
-
amount: 1,
|
|
47684
|
-
accountAddress: marginfiAccount.address,
|
|
47685
|
-
authority: marginfiAccount.authority,
|
|
47686
|
-
group: marginfiAccount.group,
|
|
47687
|
-
isSync: true,
|
|
47688
|
-
opts
|
|
47689
|
-
});
|
|
47690
|
-
}
|
|
47691
|
-
}
|
|
47692
|
-
}
|
|
47693
|
-
async function buildWithdrawBudgetIx(config, program, marginfiAccount, bankMap, bankMetadataMap, overrideInferAccounts) {
|
|
47694
|
-
const { bank, tokenProgram } = config;
|
|
47695
|
-
const opts = { createAtas: false, wrapAndUnwrapSol: false, overrideInferAccounts };
|
|
47696
|
-
switch (bank.config.assetTag) {
|
|
47697
|
-
case 3 /* KAMINO */: {
|
|
47698
|
-
const reserve = bankMetadataMap[bank.address.toBase58()]?.kaminoStates?.reserveState;
|
|
47699
|
-
if (!reserve) {
|
|
47700
|
-
throw TransactionBuildingError.kaminoReserveNotFound(
|
|
47701
|
-
bank.address.toBase58(),
|
|
47702
|
-
bank.mint.toBase58(),
|
|
47703
|
-
bank.tokenSymbol
|
|
47704
|
-
);
|
|
47705
|
-
}
|
|
47706
|
-
return makeKaminoWithdrawIx3({
|
|
47707
|
-
program,
|
|
47708
|
-
bank,
|
|
47709
|
-
bankMap,
|
|
47710
|
-
tokenProgram,
|
|
47711
|
-
cTokenAmount: 1,
|
|
47712
|
-
marginfiAccount,
|
|
47713
|
-
authority: marginfiAccount.authority,
|
|
47714
|
-
reserve,
|
|
47715
|
-
withdrawAll: false,
|
|
47716
|
-
isSync: true,
|
|
47717
|
-
opts
|
|
47718
|
-
});
|
|
47719
|
-
}
|
|
47720
|
-
case 4 /* DRIFT */: {
|
|
47721
|
-
const driftState = bankMetadataMap[bank.address.toBase58()]?.driftStates;
|
|
47722
|
-
if (!driftState) {
|
|
47723
|
-
throw TransactionBuildingError.driftStateNotFound(
|
|
47724
|
-
bank.address.toBase58(),
|
|
47725
|
-
bank.mint.toBase58(),
|
|
47726
|
-
bank.tokenSymbol
|
|
47727
|
-
);
|
|
47728
|
-
}
|
|
47729
|
-
return makeDriftWithdrawIx3({
|
|
47730
|
-
program,
|
|
47731
|
-
bank,
|
|
47732
|
-
bankMap,
|
|
47733
|
-
tokenProgram,
|
|
47734
|
-
amount: 1,
|
|
47735
|
-
marginfiAccount,
|
|
47736
|
-
authority: marginfiAccount.authority,
|
|
47737
|
-
driftSpotMarket: driftState.spotMarketState,
|
|
47738
|
-
userRewards: driftState.userRewards,
|
|
47739
|
-
withdrawAll: false,
|
|
47740
|
-
isSync: true,
|
|
47741
|
-
opts
|
|
47742
|
-
});
|
|
47743
|
-
}
|
|
47744
|
-
case 6 /* JUPLEND */: {
|
|
47745
|
-
const jupLendState = bankMetadataMap[bank.address.toBase58()]?.jupLendStates;
|
|
47746
|
-
if (!jupLendState) {
|
|
47747
|
-
throw TransactionBuildingError.jupLendStateNotFound(
|
|
47748
|
-
bank.address.toBase58(),
|
|
47749
|
-
bank.mint.toBase58(),
|
|
47750
|
-
bank.tokenSymbol
|
|
47751
|
-
);
|
|
47752
|
-
}
|
|
47753
|
-
return makeJuplendWithdrawIx2({
|
|
47754
|
-
program,
|
|
47755
|
-
bank,
|
|
47756
|
-
bankMap,
|
|
47757
|
-
tokenProgram,
|
|
47758
|
-
amount: 1,
|
|
47759
|
-
marginfiAccount,
|
|
47760
|
-
authority: marginfiAccount.authority,
|
|
47761
|
-
jupLendingState: jupLendState.jupLendingState,
|
|
47762
|
-
withdrawAll: false,
|
|
47763
|
-
opts
|
|
47764
|
-
});
|
|
47765
|
-
}
|
|
47766
|
-
default: {
|
|
47767
|
-
return makeWithdrawIx3({
|
|
47768
|
-
program,
|
|
47769
|
-
bank,
|
|
47770
|
-
bankMap,
|
|
47771
|
-
tokenProgram,
|
|
47772
|
-
amount: 1,
|
|
47773
|
-
marginfiAccount,
|
|
47774
|
-
authority: marginfiAccount.authority,
|
|
47775
|
-
withdrawAll: false,
|
|
47776
|
-
isSync: true,
|
|
47777
|
-
opts
|
|
47778
|
-
});
|
|
47779
|
-
}
|
|
47780
|
-
}
|
|
47781
|
-
}
|
|
47782
|
-
async function computeFlashloanSwapConstraints({
|
|
47783
|
-
program,
|
|
47784
|
-
marginfiAccount,
|
|
47785
|
-
bankMap,
|
|
47786
|
-
addressLookupTableAccounts,
|
|
47787
|
-
bankMetadataMap,
|
|
47788
|
-
primaryIx,
|
|
47789
|
-
secondaryIx,
|
|
47790
|
-
overrideInferAccounts
|
|
47791
|
-
}) {
|
|
47792
|
-
const cuRequestIxs = [
|
|
47793
|
-
web3_js.ComputeBudgetProgram.setComputeUnitLimit({ units: 12e5 }),
|
|
47794
|
-
web3_js.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 })
|
|
47795
|
-
];
|
|
47796
|
-
const [primaryResult, secondaryResult] = await Promise.all([
|
|
47797
|
-
buildBudgetIx(
|
|
47798
|
-
primaryIx,
|
|
47799
|
-
program,
|
|
47800
|
-
marginfiAccount,
|
|
47801
|
-
bankMap,
|
|
47802
|
-
bankMetadataMap,
|
|
47803
|
-
overrideInferAccounts
|
|
47804
|
-
),
|
|
47805
|
-
buildBudgetIx(
|
|
47806
|
-
secondaryIx,
|
|
47807
|
-
program,
|
|
47808
|
-
marginfiAccount,
|
|
47809
|
-
bankMap,
|
|
47810
|
-
bankMetadataMap,
|
|
47811
|
-
overrideInferAccounts
|
|
47812
|
-
)
|
|
47813
|
-
]);
|
|
47814
|
-
return computeFlashLoanNonSwapBudget({
|
|
47815
|
-
program,
|
|
47816
|
-
marginfiAccount,
|
|
47817
|
-
bankMap,
|
|
47818
|
-
addressLookupTableAccounts,
|
|
47819
|
-
ixs: [...cuRequestIxs, ...primaryResult.instructions, ...secondaryResult.instructions]
|
|
47820
|
-
});
|
|
47821
|
-
}
|
|
47822
|
-
|
|
47823
|
-
// src/services/account/actions/flash-loan.ts
|
|
47824
|
-
async function makeBeginFlashLoanIx3(program, marginfiAccountPk, endIndex, authority, isSync) {
|
|
47825
|
-
const ix = isSync && authority ? sync_instructions_default.makeBeginFlashLoanIx(
|
|
47826
|
-
program.programId,
|
|
47827
|
-
{
|
|
47828
|
-
marginfiAccount: marginfiAccountPk,
|
|
47829
|
-
authority
|
|
47830
|
-
},
|
|
47831
|
-
{ endIndex: new BN11__default.default(endIndex) }
|
|
47832
|
-
) : await instructions_default.makeBeginFlashLoanIx(
|
|
47833
|
-
program,
|
|
47834
|
-
{
|
|
47835
|
-
marginfiAccount: marginfiAccountPk,
|
|
47836
|
-
authority
|
|
47837
|
-
},
|
|
47838
|
-
{ endIndex: new BN11__default.default(endIndex) }
|
|
47839
|
-
);
|
|
47840
|
-
return { instructions: [ix], keys: [] };
|
|
47841
|
-
}
|
|
47842
|
-
async function makeEndFlashLoanIx3(program, marginfiAccountPk, projectedActiveBanks, authority, isSync) {
|
|
47843
|
-
const remainingAccounts = computeHealthAccountMetas(projectedActiveBanks);
|
|
47844
|
-
const ix = isSync && authority ? sync_instructions_default.makeEndFlashLoanIx(
|
|
47845
|
-
program.programId,
|
|
47846
|
-
{
|
|
47847
|
-
marginfiAccount: marginfiAccountPk,
|
|
47848
|
-
authority
|
|
47849
|
-
},
|
|
47850
|
-
remainingAccounts.map((account) => ({
|
|
47851
|
-
pubkey: account,
|
|
47852
|
-
isSigner: false,
|
|
47853
|
-
isWritable: false
|
|
47854
|
-
}))
|
|
47855
|
-
) : await instructions_default.makeEndFlashLoanIx(
|
|
47856
|
-
program,
|
|
47857
|
-
{
|
|
47858
|
-
marginfiAccount: marginfiAccountPk,
|
|
47859
|
-
authority
|
|
47860
|
-
},
|
|
47861
|
-
remainingAccounts.map((account) => ({
|
|
47862
|
-
pubkey: account,
|
|
47863
|
-
isSigner: false,
|
|
47864
|
-
isWritable: false
|
|
47865
|
-
}))
|
|
47866
|
-
);
|
|
47867
|
-
return { instructions: [ix], keys: [] };
|
|
47868
|
-
}
|
|
47869
|
-
async function makeFlashLoanTx({
|
|
47870
|
-
program,
|
|
47871
|
-
marginfiAccount,
|
|
47872
|
-
ixs,
|
|
47873
|
-
bankMap,
|
|
47874
|
-
blockhash,
|
|
47875
|
-
addressLookupTableAccounts,
|
|
47876
|
-
signers,
|
|
47877
|
-
isSync
|
|
47878
|
-
}) {
|
|
47879
|
-
const endIndex = ixs.length + 1;
|
|
47880
|
-
const projectedActiveBanksKeys = computeProjectedActiveBanksNoCpi(
|
|
47881
|
-
marginfiAccount.balances,
|
|
47882
|
-
ixs,
|
|
47883
|
-
program
|
|
47884
|
-
);
|
|
47885
|
-
const projectedActiveBanks = projectedActiveBanksKeys.map((account) => {
|
|
47886
|
-
const b = bankMap.get(account.toBase58());
|
|
47887
|
-
if (!b) throw Error(`Bank ${account.toBase58()} not found, in makeFlashLoanTx function`);
|
|
47888
|
-
return b;
|
|
47889
|
-
});
|
|
47890
|
-
const beginFlashLoanIx = await makeBeginFlashLoanIx3(
|
|
47891
|
-
program,
|
|
47892
|
-
marginfiAccount.address,
|
|
47893
|
-
endIndex,
|
|
47894
|
-
marginfiAccount.authority,
|
|
47895
|
-
isSync
|
|
47896
|
-
);
|
|
47897
|
-
const endFlashLoanIx = await makeEndFlashLoanIx3(
|
|
47898
|
-
program,
|
|
47899
|
-
marginfiAccount.address,
|
|
47900
|
-
projectedActiveBanks,
|
|
47901
|
-
marginfiAccount.authority,
|
|
47902
|
-
isSync
|
|
47903
|
-
);
|
|
47904
|
-
const message = new web3_js.TransactionMessage({
|
|
47905
|
-
payerKey: marginfiAccount.authority,
|
|
47906
|
-
recentBlockhash: blockhash,
|
|
47907
|
-
instructions: [...beginFlashLoanIx.instructions, ...ixs, ...endFlashLoanIx.instructions]
|
|
47908
|
-
}).compileToV0Message(addressLookupTableAccounts);
|
|
47909
|
-
const tx = addTransactionMetadata(new web3_js.VersionedTransaction(message), {
|
|
47910
|
-
addressLookupTables: addressLookupTableAccounts,
|
|
47911
|
-
type: "FLASHLOAN" /* FLASHLOAN */,
|
|
47912
|
-
signers
|
|
47913
|
-
});
|
|
47914
|
-
if (signers) {
|
|
47915
|
-
tx.sign(signers);
|
|
47916
|
-
}
|
|
47917
|
-
return tx;
|
|
47918
|
-
}
|
|
47919
|
-
|
|
47920
|
-
// src/services/account/actions/loop.ts
|
|
47921
|
-
async function makeLoopTx(params) {
|
|
47922
|
-
const {
|
|
47923
|
-
program,
|
|
47924
|
-
marginfiAccount,
|
|
47925
|
-
bankMap,
|
|
47926
|
-
depositOpts,
|
|
47927
|
-
borrowOpts,
|
|
47928
|
-
bankMetadataMap,
|
|
47929
|
-
addressLookupTableAccounts,
|
|
47930
|
-
connection,
|
|
47931
|
-
oraclePrices,
|
|
47932
|
-
crossbarUrl,
|
|
47933
|
-
additionalIxs = []
|
|
47934
|
-
} = params;
|
|
47935
|
-
const blockhash = (await connection.getLatestBlockhash("confirmed")).blockhash;
|
|
47936
|
-
const setupIxs = await makeSetupIx({
|
|
47937
|
-
connection,
|
|
47938
|
-
authority: marginfiAccount.authority,
|
|
47939
|
-
tokens: [
|
|
47940
|
-
{
|
|
47941
|
-
mint: borrowOpts.borrowBank.mint,
|
|
47942
|
-
tokenProgram: borrowOpts.tokenProgram
|
|
47943
|
-
},
|
|
47944
|
-
{
|
|
47945
|
-
mint: depositOpts.depositBank.mint,
|
|
47946
|
-
tokenProgram: depositOpts.tokenProgram
|
|
47947
|
-
}
|
|
47948
|
-
]
|
|
47949
|
-
});
|
|
47950
|
-
const updateJupLendRateIxs = makeUpdateJupLendRateIxs(
|
|
47951
|
-
params.marginfiAccount,
|
|
47952
|
-
params.bankMap,
|
|
47953
|
-
[depositOpts.depositBank.address],
|
|
47954
|
-
params.bankMetadataMap
|
|
47955
|
-
);
|
|
47956
|
-
const updateDriftMarketIxs = makeUpdateDriftMarketIxs(
|
|
47957
|
-
params.marginfiAccount,
|
|
47958
|
-
params.bankMap,
|
|
47959
|
-
[depositOpts.depositBank.address],
|
|
47960
|
-
params.bankMetadataMap
|
|
47961
|
-
);
|
|
47962
|
-
const kaminoRefreshIxs = makeRefreshKaminoBanksIxs(
|
|
47963
|
-
marginfiAccount,
|
|
47964
|
-
bankMap,
|
|
47965
|
-
[borrowOpts.borrowBank.address, depositOpts.depositBank.address],
|
|
47966
|
-
bankMetadataMap
|
|
47967
|
-
);
|
|
47968
|
-
const { flashloanTx, setupInstructions, swapQuote, amountToDeposit, depositIxs, borrowIxs } = await buildLoopFlashloanTx({
|
|
47969
|
-
...params,
|
|
47970
|
-
blockhash
|
|
47971
|
-
});
|
|
47972
|
-
const jupiterSetupInstructions = setupInstructions.filter((ix) => {
|
|
47973
|
-
if (ix.programId.equals(web3_js.ComputeBudgetProgram.programId)) {
|
|
47974
|
-
return false;
|
|
47975
|
-
}
|
|
47976
|
-
if (ix.programId.equals(ASSOCIATED_TOKEN_PROGRAM_ID)) {
|
|
47977
|
-
const mintKey = ix.keys[3]?.pubkey;
|
|
47978
|
-
if (mintKey?.equals(depositOpts.depositBank.mint) || mintKey?.equals(borrowOpts.borrowBank.mint)) {
|
|
47979
|
-
return false;
|
|
47980
|
-
}
|
|
47981
|
-
}
|
|
47982
|
-
return true;
|
|
47983
|
-
});
|
|
47984
|
-
setupIxs.push(...jupiterSetupInstructions);
|
|
47985
|
-
const { instructions: updateFeedIxs, luts: feedLuts } = await makeSmartCrankSwbFeedIx({
|
|
47986
|
-
marginfiAccount,
|
|
47987
|
-
bankMap,
|
|
47988
|
-
oraclePrices,
|
|
47989
|
-
assetShareValueMultiplierByBank: params.assetShareValueMultiplierByBank,
|
|
47990
|
-
instructions: [...borrowIxs.instructions, ...depositIxs.instructions],
|
|
47991
|
-
program,
|
|
47992
|
-
connection,
|
|
47993
|
-
crossbarUrl
|
|
47994
|
-
});
|
|
47995
|
-
let additionalTxs = [];
|
|
47996
|
-
if (depositOpts.depositBank.mint.equals(NATIVE_MINT) && depositOpts.inputDepositAmount) {
|
|
47997
|
-
setupIxs.push(
|
|
47998
|
-
...makeWrapSolIxs(marginfiAccount.authority, new BigNumber3.BigNumber(depositOpts.inputDepositAmount))
|
|
47999
|
-
);
|
|
48000
|
-
}
|
|
48001
|
-
if (setupIxs.length > 0 || additionalIxs.length > 0 || kaminoRefreshIxs.instructions.length > 0 || updateDriftMarketIxs.instructions.length > 0 || updateJupLendRateIxs.instructions.length > 0) {
|
|
48002
|
-
const ixs = [
|
|
48003
|
-
...additionalIxs,
|
|
48004
|
-
...setupIxs,
|
|
48005
|
-
...kaminoRefreshIxs.instructions,
|
|
48006
|
-
...updateDriftMarketIxs.instructions,
|
|
48007
|
-
...updateJupLendRateIxs.instructions
|
|
48008
|
-
];
|
|
48009
|
-
const txs = splitInstructionsToFitTransactions([], ixs, {
|
|
48010
|
-
blockhash,
|
|
48011
|
-
payerKey: marginfiAccount.authority,
|
|
48012
|
-
luts: addressLookupTableAccounts ?? []
|
|
48013
|
-
});
|
|
48014
|
-
additionalTxs.push(
|
|
48015
|
-
...txs.map(
|
|
48016
|
-
(tx) => addTransactionMetadata(tx, {
|
|
48017
|
-
type: "CREATE_ATA" /* CREATE_ATA */,
|
|
48018
|
-
addressLookupTables: addressLookupTableAccounts
|
|
48019
|
-
})
|
|
48020
|
-
)
|
|
48021
|
-
);
|
|
48022
|
-
}
|
|
48023
|
-
if (updateFeedIxs.length > 0) {
|
|
48024
|
-
const message = new web3_js.TransactionMessage({
|
|
48025
|
-
payerKey: marginfiAccount.authority,
|
|
48026
|
-
recentBlockhash: blockhash,
|
|
48027
|
-
instructions: updateFeedIxs
|
|
48028
|
-
}).compileToV0Message(feedLuts);
|
|
48029
|
-
additionalTxs.push(
|
|
48030
|
-
addTransactionMetadata(new web3_js.VersionedTransaction(message), {
|
|
48031
|
-
addressLookupTables: feedLuts,
|
|
48032
|
-
type: "CRANK" /* CRANK */
|
|
48033
|
-
})
|
|
48034
|
-
);
|
|
48035
|
-
}
|
|
48036
|
-
const transactions = [...additionalTxs, flashloanTx];
|
|
48037
|
-
return {
|
|
48038
|
-
transactions,
|
|
48039
|
-
actionTxIndex: transactions.length - 1,
|
|
48040
|
-
quoteResponse: swapQuote
|
|
48041
|
-
};
|
|
48042
|
-
}
|
|
48043
|
-
async function buildLoopFlashloanTx({
|
|
48044
|
-
program,
|
|
48045
|
-
marginfiAccount,
|
|
48046
|
-
bankMap,
|
|
48047
|
-
borrowOpts,
|
|
48048
|
-
depositOpts,
|
|
48049
|
-
bankMetadataMap,
|
|
48050
|
-
addressLookupTableAccounts,
|
|
48051
|
-
connection,
|
|
48052
|
-
swapOpts,
|
|
48053
|
-
overrideInferAccounts,
|
|
48054
|
-
blockhash
|
|
48055
|
-
}) {
|
|
48056
|
-
const cuRequestIxs = [
|
|
48057
|
-
web3_js.ComputeBudgetProgram.setComputeUnitLimit({ units: 12e5 }),
|
|
48058
|
-
web3_js.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 })
|
|
48059
|
-
];
|
|
48060
|
-
let amountToDeposit;
|
|
48061
|
-
let swapInstructions = [];
|
|
48062
|
-
let setupInstructions = [];
|
|
48063
|
-
let swapLookupTables = [];
|
|
48064
|
-
let swapQuote;
|
|
48065
|
-
let sizeConstraintUsed = 0;
|
|
48066
|
-
if (depositOpts.depositBank.mint.equals(borrowOpts.borrowBank.mint)) {
|
|
48067
|
-
amountToDeposit = borrowOpts.borrowAmount + (depositOpts.loopMode === "DEPOSIT" ? depositOpts.inputDepositAmount : 0);
|
|
48068
|
-
} else {
|
|
48069
|
-
const destinationTokenAccount = getAssociatedTokenAddressSync(
|
|
48070
|
-
new web3_js.PublicKey(depositOpts.depositBank.mint),
|
|
48071
|
-
marginfiAccount.authority,
|
|
48072
|
-
true,
|
|
48073
|
-
depositOpts.tokenProgram.equals(TOKEN_2022_PROGRAM_ID) ? TOKEN_2022_PROGRAM_ID : void 0
|
|
48074
|
-
);
|
|
48075
|
-
const swapConstraints = await computeFlashloanSwapConstraints({
|
|
48076
|
-
program,
|
|
48077
|
-
marginfiAccount,
|
|
48078
|
-
bankMap,
|
|
48079
|
-
bankMetadataMap,
|
|
48080
|
-
addressLookupTableAccounts: addressLookupTableAccounts ?? [],
|
|
48081
|
-
primaryIx: {
|
|
48082
|
-
type: "borrow",
|
|
48083
|
-
bank: borrowOpts.borrowBank,
|
|
48084
|
-
tokenProgram: borrowOpts.tokenProgram
|
|
48085
|
-
},
|
|
48086
|
-
secondaryIx: {
|
|
48087
|
-
type: "deposit",
|
|
48088
|
-
bank: depositOpts.depositBank,
|
|
48089
|
-
tokenProgram: depositOpts.tokenProgram
|
|
48090
|
-
},
|
|
48091
|
-
overrideInferAccounts
|
|
48092
|
-
});
|
|
48093
|
-
const swapResponse = await getSwapIxsForFlashloan({
|
|
48094
|
-
inputMint: borrowOpts.borrowBank.mint.toBase58(),
|
|
48095
|
-
outputMint: depositOpts.depositBank.mint.toBase58(),
|
|
48096
|
-
amount: uiToNative(borrowOpts.borrowAmount, borrowOpts.borrowBank.mintDecimals).toNumber(),
|
|
48097
|
-
swapMode: "ExactIn",
|
|
48098
|
-
authority: marginfiAccount.authority,
|
|
48099
|
-
connection,
|
|
48100
|
-
destinationTokenAccount,
|
|
48101
|
-
swapOpts,
|
|
48102
|
-
sizeConstraint: swapConstraints.sizeConstraint,
|
|
48103
|
-
maxSwapTotalAccounts: swapConstraints.maxSwapTotalAccounts
|
|
48104
|
-
});
|
|
48105
|
-
sizeConstraintUsed = swapConstraints.sizeConstraint;
|
|
48106
|
-
const outAmountThreshold = nativeToUi(
|
|
48107
|
-
swapResponse.quoteResponse.otherAmountThreshold,
|
|
48108
|
-
depositOpts.depositBank.mintDecimals
|
|
48109
|
-
);
|
|
48110
|
-
amountToDeposit = outAmountThreshold + (depositOpts.loopMode === "DEPOSIT" ? depositOpts.inputDepositAmount : 0);
|
|
48111
|
-
swapInstructions = swapResponse.swapInstructions;
|
|
48112
|
-
setupInstructions = swapResponse.setupInstructions;
|
|
48113
|
-
swapLookupTables = swapResponse.addressLookupTableAddresses;
|
|
48114
|
-
swapQuote = swapResponse.quoteResponse;
|
|
48115
|
-
}
|
|
48116
|
-
const borrowIxs = await makeBorrowIx3({
|
|
48117
|
-
program,
|
|
48118
|
-
bank: borrowOpts.borrowBank,
|
|
48119
|
-
bankMap,
|
|
48120
|
-
tokenProgram: borrowOpts.tokenProgram,
|
|
48121
|
-
amount: borrowOpts.borrowAmount,
|
|
48122
|
-
marginfiAccount,
|
|
48123
|
-
authority: marginfiAccount.authority,
|
|
48124
|
-
isSync: false,
|
|
48125
|
-
opts: {
|
|
48126
|
-
createAtas: false,
|
|
48127
|
-
wrapAndUnwrapSol: false,
|
|
48128
|
-
overrideInferAccounts
|
|
48129
|
-
}
|
|
48130
|
-
});
|
|
48131
|
-
let depositIxs;
|
|
48132
|
-
switch (depositOpts.depositBank.config.assetTag) {
|
|
48133
|
-
case 3 /* KAMINO */: {
|
|
48134
|
-
const reserve = bankMetadataMap[depositOpts.depositBank.address.toBase58()]?.kaminoStates?.reserveState;
|
|
48135
|
-
if (!reserve) {
|
|
48136
|
-
throw TransactionBuildingError.kaminoReserveNotFound(
|
|
48137
|
-
depositOpts.depositBank.address.toBase58(),
|
|
48138
|
-
depositOpts.depositBank.mint.toBase58(),
|
|
48139
|
-
depositOpts.depositBank.tokenSymbol
|
|
48140
|
-
);
|
|
48141
|
-
}
|
|
48142
|
-
depositIxs = await makeKaminoDepositIx3({
|
|
48143
|
-
program,
|
|
48144
|
-
bank: depositOpts.depositBank,
|
|
48145
|
-
tokenProgram: depositOpts.tokenProgram,
|
|
48146
|
-
amount: amountToDeposit,
|
|
48147
|
-
accountAddress: marginfiAccount.address,
|
|
48148
|
-
authority: marginfiAccount.authority,
|
|
48149
|
-
group: marginfiAccount.group,
|
|
48150
|
-
reserve,
|
|
48151
|
-
opts: {
|
|
48152
|
-
wrapAndUnwrapSol: false,
|
|
48153
|
-
overrideInferAccounts
|
|
48154
|
-
}
|
|
48155
|
-
});
|
|
48156
|
-
break;
|
|
48157
|
-
}
|
|
48158
|
-
case 4 /* DRIFT */: {
|
|
48159
|
-
const driftState = bankMetadataMap[depositOpts.depositBank.address.toBase58()]?.driftStates;
|
|
48160
|
-
if (!driftState) {
|
|
48161
|
-
throw TransactionBuildingError.driftStateNotFound(
|
|
48162
|
-
depositOpts.depositBank.address.toBase58(),
|
|
48163
|
-
depositOpts.depositBank.mint.toBase58(),
|
|
48164
|
-
depositOpts.depositBank.tokenSymbol
|
|
48165
|
-
);
|
|
48166
|
-
}
|
|
48167
|
-
const driftMarketIndex = driftState.spotMarketState.marketIndex;
|
|
48168
|
-
const driftOracle = driftState.spotMarketState.oracle;
|
|
48169
|
-
depositIxs = await makeDriftDepositIx3({
|
|
48170
|
-
program,
|
|
48171
|
-
bank: depositOpts.depositBank,
|
|
48172
|
-
tokenProgram: depositOpts.tokenProgram,
|
|
48173
|
-
amount: amountToDeposit,
|
|
48174
|
-
accountAddress: marginfiAccount.address,
|
|
48175
|
-
authority: marginfiAccount.authority,
|
|
48176
|
-
group: marginfiAccount.group,
|
|
48177
|
-
driftMarketIndex,
|
|
48178
|
-
driftOracle,
|
|
48179
|
-
opts: {
|
|
48180
|
-
wrapAndUnwrapSol: false,
|
|
48181
|
-
overrideInferAccounts
|
|
48182
|
-
}
|
|
48183
|
-
});
|
|
48184
|
-
break;
|
|
48185
|
-
}
|
|
48186
|
-
case 6 /* JUPLEND */: {
|
|
48187
|
-
depositIxs = await makeJuplendDepositIx2({
|
|
48188
|
-
program,
|
|
48189
|
-
bank: depositOpts.depositBank,
|
|
48190
|
-
tokenProgram: depositOpts.tokenProgram,
|
|
48191
|
-
amount: amountToDeposit,
|
|
48192
|
-
accountAddress: marginfiAccount.address,
|
|
48193
|
-
authority: marginfiAccount.authority,
|
|
48194
|
-
group: marginfiAccount.group,
|
|
48195
|
-
opts: {
|
|
48196
|
-
wrapAndUnwrapSol: false,
|
|
48197
|
-
overrideInferAccounts
|
|
48198
|
-
}
|
|
48199
|
-
});
|
|
48200
|
-
break;
|
|
48201
|
-
}
|
|
48202
|
-
default: {
|
|
48203
|
-
depositIxs = await makeDepositIx3({
|
|
48204
|
-
program,
|
|
48205
|
-
bank: depositOpts.depositBank,
|
|
48206
|
-
tokenProgram: depositOpts.tokenProgram,
|
|
48207
|
-
amount: amountToDeposit,
|
|
48208
|
-
accountAddress: marginfiAccount.address,
|
|
48209
|
-
authority: marginfiAccount.authority,
|
|
48210
|
-
group: marginfiAccount.group,
|
|
48211
|
-
opts: {
|
|
48212
|
-
wrapAndUnwrapSol: false,
|
|
48213
|
-
overrideInferAccounts
|
|
48214
|
-
}
|
|
48215
|
-
});
|
|
48216
|
-
break;
|
|
48217
|
-
}
|
|
48218
|
-
}
|
|
48219
|
-
const luts = [...addressLookupTableAccounts ?? [], ...swapLookupTables];
|
|
48220
|
-
const allNonFlIxs = [
|
|
48221
|
-
...cuRequestIxs,
|
|
48222
|
-
...borrowIxs.instructions,
|
|
48223
|
-
...swapInstructions,
|
|
48224
|
-
...depositIxs.instructions
|
|
48225
|
-
];
|
|
48226
|
-
if (swapInstructions.length > 0) {
|
|
48227
|
-
compileFlashloanPrecheck({
|
|
48228
|
-
allIxs: allNonFlIxs,
|
|
48229
|
-
payer: marginfiAccount.authority,
|
|
48230
|
-
luts,
|
|
48231
|
-
sizeConstraint: sizeConstraintUsed,
|
|
48232
|
-
swapIxCount: swapInstructions.length,
|
|
48233
|
-
swapLutCount: swapLookupTables.length
|
|
48234
|
-
});
|
|
48235
|
-
}
|
|
48236
|
-
const flashloanTx = await makeFlashLoanTx({
|
|
48237
|
-
program,
|
|
48238
|
-
marginfiAccount,
|
|
48239
|
-
bankMap,
|
|
48240
|
-
addressLookupTableAccounts: luts,
|
|
48241
|
-
blockhash,
|
|
48242
|
-
ixs: allNonFlIxs
|
|
48243
|
-
});
|
|
48244
|
-
const txSize = getTxSize(flashloanTx);
|
|
48245
|
-
const totalKeys = getTotalAccountKeys(flashloanTx);
|
|
48246
|
-
if (txSize > MAX_TX_SIZE || totalKeys > MAX_ACCOUNT_LOCKS) {
|
|
48247
|
-
throw TransactionBuildingError.swapSizeExceededLoop(
|
|
48248
|
-
txSize,
|
|
48249
|
-
totalKeys,
|
|
48250
|
-
swapOpts.swapConfig?.provider
|
|
48251
|
-
);
|
|
48252
|
-
}
|
|
48253
|
-
return {
|
|
48254
|
-
flashloanTx,
|
|
48255
|
-
setupInstructions,
|
|
48256
|
-
swapQuote,
|
|
48257
|
-
borrowIxs,
|
|
48258
|
-
depositIxs,
|
|
48259
|
-
amountToDeposit
|
|
48260
|
-
};
|
|
48261
|
-
}
|
|
48262
|
-
|
|
48263
47830
|
// src/services/account/actions/emissions.ts
|
|
48264
47831
|
async function makeClearEmissionsIx(program, marginfiAccount, banks, bankAddress) {
|
|
48265
47832
|
const bank = banks.get(bankAddress.toBase58());
|
|
@@ -48687,7 +48254,7 @@ async function buildSwapCollateralFlashloanTx({
|
|
|
48687
48254
|
const txSize = getTxSize(flashloanTx);
|
|
48688
48255
|
const totalKeys = getTotalAccountKeys(flashloanTx);
|
|
48689
48256
|
if (txSize > MAX_TX_SIZE || totalKeys > MAX_ACCOUNT_LOCKS) {
|
|
48690
|
-
throw TransactionBuildingError.
|
|
48257
|
+
throw TransactionBuildingError.swapSizeExceededPositionSwap(
|
|
48691
48258
|
txSize,
|
|
48692
48259
|
totalKeys,
|
|
48693
48260
|
swapOpts.swapConfig?.provider
|
|
@@ -48948,7 +48515,7 @@ async function buildSwapDebtFlashloanTx({
|
|
|
48948
48515
|
const txSize = getTxSize(flashloanTx);
|
|
48949
48516
|
const totalKeys = getTotalAccountKeys(flashloanTx);
|
|
48950
48517
|
if (txSize > MAX_TX_SIZE || totalKeys > MAX_ACCOUNT_LOCKS) {
|
|
48951
|
-
throw TransactionBuildingError.
|
|
48518
|
+
throw TransactionBuildingError.swapSizeExceededPositionSwap(
|
|
48952
48519
|
txSize,
|
|
48953
48520
|
totalKeys,
|
|
48954
48521
|
swapOpts.swapConfig?.provider
|
|
@@ -48962,179 +48529,6 @@ async function buildSwapDebtFlashloanTx({
|
|
|
48962
48529
|
repayIxs
|
|
48963
48530
|
};
|
|
48964
48531
|
}
|
|
48965
|
-
var SYSVAR_CLOCK_ID2 = new web3_js.PublicKey("SysvarC1ock11111111111111111111111111111111");
|
|
48966
|
-
async function makeMintStakedLstIx(params) {
|
|
48967
|
-
const { amount, authority, stakeAccountPk, validator, connection } = params;
|
|
48968
|
-
const pool = findPoolAddress(validator);
|
|
48969
|
-
const lstMint = findPoolMintAddress(pool);
|
|
48970
|
-
const poolStakeAuth = findPoolStakeAuthorityAddress(pool);
|
|
48971
|
-
const lstAta = getAssociatedTokenAddressSync(lstMint, authority);
|
|
48972
|
-
const [lstAccInfo, stakeAccInfoParsed, rentExemptReserve] = await Promise.all([
|
|
48973
|
-
connection.getAccountInfo(lstAta),
|
|
48974
|
-
connection.getParsedAccountInfo(stakeAccountPk),
|
|
48975
|
-
connection.getMinimumBalanceForRentExemption(web3_js.StakeProgram.space)
|
|
48976
|
-
]);
|
|
48977
|
-
const stakeAccParsed = stakeAccInfoParsed?.value?.data;
|
|
48978
|
-
const amountLamports = Math.round(Number(amount) * web3_js.LAMPORTS_PER_SOL);
|
|
48979
|
-
const stakeAccLamports = Number(stakeAccParsed?.parsed?.info?.stake?.delegation?.stake ?? 0);
|
|
48980
|
-
const isFullStake = amountLamports >= stakeAccLamports;
|
|
48981
|
-
const instructions2 = [];
|
|
48982
|
-
const signers = [];
|
|
48983
|
-
if (!lstAccInfo) {
|
|
48984
|
-
instructions2.push(
|
|
48985
|
-
createAssociatedTokenAccountInstruction(authority, lstAta, authority, lstMint)
|
|
48986
|
-
);
|
|
48987
|
-
}
|
|
48988
|
-
let targetStakePubkey;
|
|
48989
|
-
if (!isFullStake) {
|
|
48990
|
-
const splitStakeAccount = web3_js.Keypair.generate();
|
|
48991
|
-
signers.push(splitStakeAccount);
|
|
48992
|
-
targetStakePubkey = splitStakeAccount.publicKey;
|
|
48993
|
-
instructions2.push(
|
|
48994
|
-
...web3_js.StakeProgram.split(
|
|
48995
|
-
{
|
|
48996
|
-
stakePubkey: stakeAccountPk,
|
|
48997
|
-
authorizedPubkey: authority,
|
|
48998
|
-
splitStakePubkey: splitStakeAccount.publicKey,
|
|
48999
|
-
lamports: amountLamports
|
|
49000
|
-
},
|
|
49001
|
-
rentExemptReserve
|
|
49002
|
-
).instructions
|
|
49003
|
-
);
|
|
49004
|
-
} else {
|
|
49005
|
-
targetStakePubkey = stakeAccountPk;
|
|
49006
|
-
}
|
|
49007
|
-
const [authorizeStakerIx, authorizeWithdrawIx] = await Promise.all([
|
|
49008
|
-
web3_js.StakeProgram.authorize({
|
|
49009
|
-
stakePubkey: targetStakePubkey,
|
|
49010
|
-
authorizedPubkey: authority,
|
|
49011
|
-
newAuthorizedPubkey: poolStakeAuth,
|
|
49012
|
-
stakeAuthorizationType: web3_js.StakeAuthorizationLayout.Staker
|
|
49013
|
-
}).instructions,
|
|
49014
|
-
web3_js.StakeProgram.authorize({
|
|
49015
|
-
stakePubkey: targetStakePubkey,
|
|
49016
|
-
authorizedPubkey: authority,
|
|
49017
|
-
newAuthorizedPubkey: poolStakeAuth,
|
|
49018
|
-
stakeAuthorizationType: web3_js.StakeAuthorizationLayout.Withdrawer
|
|
49019
|
-
}).instructions
|
|
49020
|
-
]);
|
|
49021
|
-
[authorizeStakerIx[0], authorizeWithdrawIx[0]].forEach((ix) => {
|
|
49022
|
-
if (ix) {
|
|
49023
|
-
ix.keys = ix.keys.map((key) => ({
|
|
49024
|
-
...key,
|
|
49025
|
-
isWritable: key.pubkey.equals(SYSVAR_CLOCK_ID2) ? false : key.isWritable
|
|
49026
|
-
}));
|
|
49027
|
-
}
|
|
49028
|
-
});
|
|
49029
|
-
instructions2.push(...authorizeStakerIx, ...authorizeWithdrawIx);
|
|
49030
|
-
const depositStakeIx = await SinglePoolInstruction.depositStake(
|
|
49031
|
-
pool,
|
|
49032
|
-
targetStakePubkey,
|
|
49033
|
-
lstAta,
|
|
49034
|
-
authority
|
|
49035
|
-
);
|
|
49036
|
-
instructions2.push(depositStakeIx);
|
|
49037
|
-
return { instructions: instructions2, keys: signers };
|
|
49038
|
-
}
|
|
49039
|
-
async function makeMintStakedLstTx(params) {
|
|
49040
|
-
const { connection, luts, blockhash: providedBlockhash } = params;
|
|
49041
|
-
const { instructions: instructions2, keys } = await makeMintStakedLstIx(params);
|
|
49042
|
-
const blockhash = providedBlockhash ?? (await connection.getLatestBlockhash("confirmed")).blockhash;
|
|
49043
|
-
const message = new web3_js.TransactionMessage({
|
|
49044
|
-
payerKey: params.authority,
|
|
49045
|
-
recentBlockhash: blockhash,
|
|
49046
|
-
instructions: instructions2
|
|
49047
|
-
}).compileToV0Message(luts);
|
|
49048
|
-
const tx = new web3_js.VersionedTransaction(message);
|
|
49049
|
-
return addTransactionMetadata(tx, {
|
|
49050
|
-
signers: keys,
|
|
49051
|
-
addressLookupTables: luts,
|
|
49052
|
-
type: "DEPOSIT_STAKE" /* DEPOSIT_STAKE */
|
|
49053
|
-
});
|
|
49054
|
-
}
|
|
49055
|
-
async function makeRedeemStakedLstIx(params) {
|
|
49056
|
-
const { amount, authority, validator, connection } = params;
|
|
49057
|
-
const pool = findPoolAddress(validator);
|
|
49058
|
-
const lstMint = findPoolMintAddress(pool);
|
|
49059
|
-
const mintAuthority = findPoolMintAuthorityAddress(pool);
|
|
49060
|
-
const lstAta = getAssociatedTokenAddressSync(lstMint, authority);
|
|
49061
|
-
const rentExemption = await connection.getMinimumBalanceForRentExemption(
|
|
49062
|
-
web3_js.StakeProgram.space
|
|
49063
|
-
);
|
|
49064
|
-
const stakeAmount = new BigNumber3__default.default(new BigNumber3__default.default(amount).toString());
|
|
49065
|
-
const instructions2 = [];
|
|
49066
|
-
const signers = [];
|
|
49067
|
-
const stakeAccount = web3_js.Keypair.generate();
|
|
49068
|
-
signers.push(stakeAccount);
|
|
49069
|
-
instructions2.push(
|
|
49070
|
-
web3_js.SystemProgram.createAccount({
|
|
49071
|
-
fromPubkey: authority,
|
|
49072
|
-
newAccountPubkey: stakeAccount.publicKey,
|
|
49073
|
-
lamports: rentExemption,
|
|
49074
|
-
space: web3_js.StakeProgram.space,
|
|
49075
|
-
programId: web3_js.StakeProgram.programId
|
|
49076
|
-
})
|
|
49077
|
-
);
|
|
49078
|
-
instructions2.push(
|
|
49079
|
-
createApproveInstruction(
|
|
49080
|
-
lstAta,
|
|
49081
|
-
mintAuthority,
|
|
49082
|
-
authority,
|
|
49083
|
-
BigInt(stakeAmount.multipliedBy(1e9).toFixed(0))
|
|
49084
|
-
)
|
|
49085
|
-
);
|
|
49086
|
-
const withdrawStakeIx = await SinglePoolInstruction.withdrawStake(
|
|
49087
|
-
pool,
|
|
49088
|
-
stakeAccount.publicKey,
|
|
49089
|
-
authority,
|
|
49090
|
-
lstAta,
|
|
49091
|
-
stakeAmount
|
|
49092
|
-
);
|
|
49093
|
-
instructions2.push(withdrawStakeIx);
|
|
49094
|
-
return { instructions: instructions2, keys: signers };
|
|
49095
|
-
}
|
|
49096
|
-
async function makeRedeemStakedLstTx(params) {
|
|
49097
|
-
const { connection, luts, blockhash: providedBlockhash } = params;
|
|
49098
|
-
const { instructions: instructions2, keys } = await makeRedeemStakedLstIx(params);
|
|
49099
|
-
const blockhash = providedBlockhash ?? (await connection.getLatestBlockhash("confirmed")).blockhash;
|
|
49100
|
-
const message = new web3_js.TransactionMessage({
|
|
49101
|
-
payerKey: params.authority,
|
|
49102
|
-
recentBlockhash: blockhash,
|
|
49103
|
-
instructions: instructions2
|
|
49104
|
-
}).compileToV0Message(luts);
|
|
49105
|
-
const tx = new web3_js.VersionedTransaction(message);
|
|
49106
|
-
return addTransactionMetadata(tx, {
|
|
49107
|
-
signers: keys,
|
|
49108
|
-
addressLookupTables: luts,
|
|
49109
|
-
type: "WITHDRAW_STAKE" /* WITHDRAW_STAKE */
|
|
49110
|
-
});
|
|
49111
|
-
}
|
|
49112
|
-
async function makeMergeStakeAccountsTx(params) {
|
|
49113
|
-
const {
|
|
49114
|
-
authority,
|
|
49115
|
-
sourceStakeAccount,
|
|
49116
|
-
destinationStakeAccount,
|
|
49117
|
-
connection,
|
|
49118
|
-
luts,
|
|
49119
|
-
blockhash: providedBlockhash
|
|
49120
|
-
} = params;
|
|
49121
|
-
const mergeIx = web3_js.StakeProgram.merge({
|
|
49122
|
-
stakePubkey: destinationStakeAccount,
|
|
49123
|
-
sourceStakePubKey: sourceStakeAccount,
|
|
49124
|
-
authorizedPubkey: authority
|
|
49125
|
-
}).instructions;
|
|
49126
|
-
const blockhash = providedBlockhash ?? (await connection.getLatestBlockhash("confirmed")).blockhash;
|
|
49127
|
-
const message = new web3_js.TransactionMessage({
|
|
49128
|
-
payerKey: authority,
|
|
49129
|
-
recentBlockhash: blockhash,
|
|
49130
|
-
instructions: mergeIx
|
|
49131
|
-
}).compileToV0Message(luts);
|
|
49132
|
-
const tx = new web3_js.VersionedTransaction(message);
|
|
49133
|
-
return addTransactionMetadata(tx, {
|
|
49134
|
-
addressLookupTables: luts,
|
|
49135
|
-
type: "MERGE_STAKE_ACCOUNTS" /* MERGE_STAKE_ACCOUNTS */
|
|
49136
|
-
});
|
|
49137
|
-
}
|
|
49138
48532
|
|
|
49139
48533
|
// src/services/account/services/account-simulation.service.ts
|
|
49140
48534
|
async function simulateAccountHealthCacheWithFallback(params) {
|
|
@@ -49983,7 +49377,7 @@ async function getTitanExactOutViaWebSocket(params) {
|
|
|
49983
49377
|
inputMint: new web3_js.PublicKey(inputMint).toBytes(),
|
|
49984
49378
|
outputMint: new web3_js.PublicKey(outputMint).toBytes(),
|
|
49985
49379
|
amount,
|
|
49986
|
-
swapMode: "ExactOut"
|
|
49380
|
+
swapMode: "ExactOut" /* ExactOut */,
|
|
49987
49381
|
slippageBps
|
|
49988
49382
|
},
|
|
49989
49383
|
transaction: {
|
|
@@ -50241,140 +49635,575 @@ var getExactOutEstimate = async (params) => {
|
|
|
50241
49635
|
);
|
|
50242
49636
|
}
|
|
50243
49637
|
}
|
|
50244
|
-
const firstProvider = attempts[0]?.provider ?? "Swap";
|
|
50245
|
-
throw TransactionBuildingError.swapQuoteFailed(
|
|
50246
|
-
firstProvider,
|
|
50247
|
-
inputMint,
|
|
50248
|
-
outputMint,
|
|
50249
|
-
lastError?.message ?? "No swap route available"
|
|
50250
|
-
);
|
|
50251
|
-
};
|
|
50252
|
-
function mapJupiterQuoteToSwapQuoteResult(quote) {
|
|
50253
|
-
return {
|
|
50254
|
-
inAmount: quote.inAmount,
|
|
50255
|
-
outAmount: quote.outAmount,
|
|
50256
|
-
otherAmountThreshold: quote.otherAmountThreshold,
|
|
50257
|
-
slippageBps: quote.slippageBps,
|
|
50258
|
-
platformFee: quote.platformFee ? {
|
|
50259
|
-
amount: quote.platformFee.amount ?? "0",
|
|
50260
|
-
feeBps: quote.platformFee.feeBps ?? 0
|
|
50261
|
-
} : void 0,
|
|
50262
|
-
priceImpactPct: quote.priceImpactPct,
|
|
50263
|
-
contextSlot: quote.contextSlot,
|
|
50264
|
-
timeTaken: quote.timeTaken,
|
|
50265
|
-
provider: "JUPITER" /* JUPITER */
|
|
50266
|
-
};
|
|
50267
|
-
}
|
|
50268
|
-
|
|
50269
|
-
// src/services/account/utils/jupiter.utils.ts
|
|
50270
|
-
var REFERRAL_PROGRAM_ID = new web3_js.PublicKey("REFER4ZgmyYx9c6He5XfaTMiGfdLwRnkV4RPp9t9iF3");
|
|
50271
|
-
var REFERRAL_ACCOUNT_PUBKEY = new web3_js.PublicKey("Mm7HcujSK2JzPW4eX7g4oqTXbWYDuFxapNMHXe8yp1B");
|
|
50272
|
-
var getFeeAccount = (mint) => {
|
|
50273
|
-
const [feeAccount] = web3_js.PublicKey.findProgramAddressSync(
|
|
50274
|
-
[Buffer.from("referral_ata"), REFERRAL_ACCOUNT_PUBKEY.toBuffer(), mint.toBuffer()],
|
|
50275
|
-
REFERRAL_PROGRAM_ID
|
|
50276
|
-
);
|
|
50277
|
-
return feeAccount.toBase58();
|
|
50278
|
-
};
|
|
50279
|
-
var checkFeeAccount = async (connection, mint) => {
|
|
50280
|
-
const feeAccount = getFeeAccount(mint);
|
|
50281
|
-
const hasFeeAccount = !!await connection.getAccountInfo(new web3_js.PublicKey(feeAccount));
|
|
50282
|
-
return { feeAccount, hasFeeAccount };
|
|
50283
|
-
};
|
|
50284
|
-
function deserializeJupiterInstruction(instruction) {
|
|
50285
|
-
return new web3_js.TransactionInstruction({
|
|
50286
|
-
programId: new web3_js.PublicKey(instruction.programId),
|
|
50287
|
-
keys: instruction.accounts.map((key) => ({
|
|
50288
|
-
pubkey: new web3_js.PublicKey(key.pubkey),
|
|
50289
|
-
isSigner: key.isSigner,
|
|
50290
|
-
isWritable: key.isWritable
|
|
50291
|
-
})),
|
|
50292
|
-
data: Buffer.from(instruction.data, "base64")
|
|
50293
|
-
});
|
|
50294
|
-
}
|
|
50295
|
-
function toJupiterConfig(apiConfig) {
|
|
50296
|
-
if (!apiConfig) return void 0;
|
|
50297
|
-
return {
|
|
50298
|
-
basePath: apiConfig.basePath,
|
|
50299
|
-
apiKey: apiConfig.apiKey ? () => apiConfig.apiKey : void 0,
|
|
50300
|
-
headers: apiConfig.headers
|
|
50301
|
-
};
|
|
49638
|
+
const firstProvider = attempts[0]?.provider ?? "Swap";
|
|
49639
|
+
throw TransactionBuildingError.swapQuoteFailed(
|
|
49640
|
+
firstProvider,
|
|
49641
|
+
inputMint,
|
|
49642
|
+
outputMint,
|
|
49643
|
+
lastError?.message ?? "No swap route available"
|
|
49644
|
+
);
|
|
49645
|
+
};
|
|
49646
|
+
function mapJupiterQuoteToSwapQuoteResult(quote) {
|
|
49647
|
+
return {
|
|
49648
|
+
inAmount: quote.inAmount,
|
|
49649
|
+
outAmount: quote.outAmount,
|
|
49650
|
+
otherAmountThreshold: quote.otherAmountThreshold,
|
|
49651
|
+
slippageBps: quote.slippageBps,
|
|
49652
|
+
platformFee: quote.platformFee ? {
|
|
49653
|
+
amount: quote.platformFee.amount ?? "0",
|
|
49654
|
+
feeBps: quote.platformFee.feeBps ?? 0
|
|
49655
|
+
} : void 0,
|
|
49656
|
+
priceImpactPct: quote.priceImpactPct,
|
|
49657
|
+
contextSlot: quote.contextSlot,
|
|
49658
|
+
timeTaken: quote.timeTaken,
|
|
49659
|
+
provider: "JUPITER" /* JUPITER */
|
|
49660
|
+
};
|
|
49661
|
+
}
|
|
49662
|
+
|
|
49663
|
+
// src/services/account/utils/jupiter.utils.ts
|
|
49664
|
+
var REFERRAL_PROGRAM_ID = new web3_js.PublicKey("REFER4ZgmyYx9c6He5XfaTMiGfdLwRnkV4RPp9t9iF3");
|
|
49665
|
+
var REFERRAL_ACCOUNT_PUBKEY = new web3_js.PublicKey("Mm7HcujSK2JzPW4eX7g4oqTXbWYDuFxapNMHXe8yp1B");
|
|
49666
|
+
var getFeeAccount = (mint) => {
|
|
49667
|
+
const [feeAccount] = web3_js.PublicKey.findProgramAddressSync(
|
|
49668
|
+
[Buffer.from("referral_ata"), REFERRAL_ACCOUNT_PUBKEY.toBuffer(), mint.toBuffer()],
|
|
49669
|
+
REFERRAL_PROGRAM_ID
|
|
49670
|
+
);
|
|
49671
|
+
return feeAccount.toBase58();
|
|
49672
|
+
};
|
|
49673
|
+
var checkFeeAccount = async (connection, mint) => {
|
|
49674
|
+
const feeAccount = getFeeAccount(mint);
|
|
49675
|
+
const hasFeeAccount = !!await connection.getAccountInfo(new web3_js.PublicKey(feeAccount));
|
|
49676
|
+
return { feeAccount, hasFeeAccount };
|
|
49677
|
+
};
|
|
49678
|
+
function deserializeJupiterInstruction(instruction) {
|
|
49679
|
+
return new web3_js.TransactionInstruction({
|
|
49680
|
+
programId: new web3_js.PublicKey(instruction.programId),
|
|
49681
|
+
keys: instruction.accounts.map((key) => ({
|
|
49682
|
+
pubkey: new web3_js.PublicKey(key.pubkey),
|
|
49683
|
+
isSigner: key.isSigner,
|
|
49684
|
+
isWritable: key.isWritable
|
|
49685
|
+
})),
|
|
49686
|
+
data: Buffer.from(instruction.data, "base64")
|
|
49687
|
+
});
|
|
49688
|
+
}
|
|
49689
|
+
function toJupiterConfig(apiConfig) {
|
|
49690
|
+
if (!apiConfig) return void 0;
|
|
49691
|
+
return {
|
|
49692
|
+
basePath: apiConfig.basePath,
|
|
49693
|
+
apiKey: apiConfig.apiKey ? () => apiConfig.apiKey : void 0,
|
|
49694
|
+
headers: apiConfig.headers
|
|
49695
|
+
};
|
|
49696
|
+
}
|
|
49697
|
+
var getJupiterSwapIxsForFlashloan = async ({
|
|
49698
|
+
quoteParams,
|
|
49699
|
+
authority,
|
|
49700
|
+
connection,
|
|
49701
|
+
destinationTokenAccount,
|
|
49702
|
+
apiConfig,
|
|
49703
|
+
maxSwapAccounts
|
|
49704
|
+
}) => {
|
|
49705
|
+
const configParams = toJupiterConfig(apiConfig);
|
|
49706
|
+
const jupiterApiClient = configParams?.basePath ? new api.SwapApi(new api.Configuration(configParams)) : api.createJupiterApiClient(configParams);
|
|
49707
|
+
const feeMint = quoteParams.swapMode === "ExactIn" ? quoteParams.outputMint : quoteParams.inputMint;
|
|
49708
|
+
const { feeAccount, hasFeeAccount } = await checkFeeAccount(connection, new web3_js.PublicKey(feeMint));
|
|
49709
|
+
const project0JupiterLut = (await connection.getAddressLookupTable(ADDRESS_LOOKUP_TABLE_FOR_SWAP))?.value;
|
|
49710
|
+
let finalQuoteParams = quoteParams;
|
|
49711
|
+
if (!hasFeeAccount) {
|
|
49712
|
+
console.warn("Warning: feeAccountInfo is undefined");
|
|
49713
|
+
finalQuoteParams = {
|
|
49714
|
+
...quoteParams,
|
|
49715
|
+
platformFeeBps: void 0
|
|
49716
|
+
};
|
|
49717
|
+
}
|
|
49718
|
+
const JUPITER_MAX_ACCOUNTS_MARGIN = 4;
|
|
49719
|
+
const maxAccounts = maxSwapAccounts !== void 0 ? maxSwapAccounts - JUPITER_MAX_ACCOUNTS_MARGIN : 40;
|
|
49720
|
+
const swapQuote = await jupiterApiClient.quoteGet({
|
|
49721
|
+
...finalQuoteParams,
|
|
49722
|
+
maxAccounts
|
|
49723
|
+
});
|
|
49724
|
+
const swapInstructionResponse = await jupiterApiClient.swapInstructionsPost({
|
|
49725
|
+
swapRequest: {
|
|
49726
|
+
quoteResponse: swapQuote,
|
|
49727
|
+
userPublicKey: authority.toBase58(),
|
|
49728
|
+
feeAccount: hasFeeAccount ? feeAccount : void 0,
|
|
49729
|
+
wrapAndUnwrapSol: false,
|
|
49730
|
+
destinationTokenAccount: destinationTokenAccount.toBase58()
|
|
49731
|
+
}
|
|
49732
|
+
});
|
|
49733
|
+
const lutAddresses = swapInstructionResponse.addressLookupTableAddresses;
|
|
49734
|
+
const lutAccountsRaw = await connection.getMultipleAccountsInfo(
|
|
49735
|
+
lutAddresses.map((address) => new web3_js.PublicKey(address))
|
|
49736
|
+
);
|
|
49737
|
+
const addressLookupTableAccounts = lutAccountsRaw.map((accountInfo, index) => {
|
|
49738
|
+
const addressLookupTableAddress = lutAddresses[index];
|
|
49739
|
+
if (!accountInfo || !addressLookupTableAddress) {
|
|
49740
|
+
return null;
|
|
49741
|
+
}
|
|
49742
|
+
return new web3_js.AddressLookupTableAccount({
|
|
49743
|
+
key: new web3_js.PublicKey(addressLookupTableAddress),
|
|
49744
|
+
state: web3_js.AddressLookupTableAccount.deserialize(accountInfo.data)
|
|
49745
|
+
});
|
|
49746
|
+
}).filter((account) => account !== null).concat(project0JupiterLut ? [project0JupiterLut] : []);
|
|
49747
|
+
const instruction = deserializeJupiterInstruction(swapInstructionResponse.swapInstruction);
|
|
49748
|
+
const setupInstructions = swapInstructionResponse.setupInstructions.map(
|
|
49749
|
+
deserializeJupiterInstruction
|
|
49750
|
+
);
|
|
49751
|
+
return {
|
|
49752
|
+
swapInstructions: [instruction],
|
|
49753
|
+
setupInstructions,
|
|
49754
|
+
addressLookupTableAddresses: addressLookupTableAccounts,
|
|
49755
|
+
quoteResponse: mapJupiterQuoteToSwapQuoteResult(swapQuote)
|
|
49756
|
+
};
|
|
49757
|
+
};
|
|
49758
|
+
|
|
49759
|
+
// src/services/account/utils/misc.utils.ts
|
|
49760
|
+
function floor(value, decimals) {
|
|
49761
|
+
return Math.floor(value * 10 ** decimals) / 10 ** decimals;
|
|
49762
|
+
}
|
|
49763
|
+
function ceil(value, decimals) {
|
|
49764
|
+
return Math.ceil(value * 10 ** decimals) / 10 ** decimals;
|
|
49765
|
+
}
|
|
49766
|
+
function computeClosePositionTokenAmount(position, mintDecimals) {
|
|
49767
|
+
const closePositionTokenAmount = position.isLending ? floor(position.amount, mintDecimals) : ceil(position.amount, mintDecimals);
|
|
49768
|
+
return closePositionTokenAmount;
|
|
49769
|
+
}
|
|
49770
|
+
function isWholePosition(position, amount, mintDecimals) {
|
|
49771
|
+
const closePositionTokenAmount = computeClosePositionTokenAmount(position, mintDecimals);
|
|
49772
|
+
return amount >= closePositionTokenAmount;
|
|
49773
|
+
}
|
|
49774
|
+
var SWAP_MERGE_OVERHEAD = 150;
|
|
49775
|
+
var FL_IX_OVERHEAD = 52;
|
|
49776
|
+
function compactU16Size(n) {
|
|
49777
|
+
return n < 128 ? 1 : n < 16384 ? 2 : 3;
|
|
49778
|
+
}
|
|
49779
|
+
function computeV0TxSize(ixs, payerKey, luts) {
|
|
49780
|
+
const keyMap = /* @__PURE__ */ new Map();
|
|
49781
|
+
const payerStr = payerKey.toBase58();
|
|
49782
|
+
keyMap.set(payerStr, { isSigner: true, isWritable: true });
|
|
49783
|
+
const programIds = /* @__PURE__ */ new Set();
|
|
49784
|
+
for (const ix of ixs) {
|
|
49785
|
+
const progStr = ix.programId.toBase58();
|
|
49786
|
+
programIds.add(progStr);
|
|
49787
|
+
if (!keyMap.has(progStr)) {
|
|
49788
|
+
keyMap.set(progStr, { isSigner: false, isWritable: false });
|
|
49789
|
+
}
|
|
49790
|
+
for (const meta of ix.keys) {
|
|
49791
|
+
const keyStr = meta.pubkey.toBase58();
|
|
49792
|
+
const existing = keyMap.get(keyStr);
|
|
49793
|
+
if (existing) {
|
|
49794
|
+
existing.isSigner = existing.isSigner || meta.isSigner;
|
|
49795
|
+
existing.isWritable = existing.isWritable || meta.isWritable;
|
|
49796
|
+
} else {
|
|
49797
|
+
keyMap.set(keyStr, { isSigner: meta.isSigner, isWritable: meta.isWritable });
|
|
49798
|
+
}
|
|
49799
|
+
}
|
|
49800
|
+
}
|
|
49801
|
+
const lutLookup = /* @__PURE__ */ new Map();
|
|
49802
|
+
for (let li = 0; li < luts.length; li++) {
|
|
49803
|
+
const addresses = luts[li].state.addresses;
|
|
49804
|
+
for (let ai = 0; ai < addresses.length; ai++) {
|
|
49805
|
+
const addrStr = addresses[ai].toBase58();
|
|
49806
|
+
if (!lutLookup.has(addrStr)) {
|
|
49807
|
+
lutLookup.set(addrStr, { lutIdx: li, addrIdx: ai });
|
|
49808
|
+
}
|
|
49809
|
+
}
|
|
49810
|
+
}
|
|
49811
|
+
let numStaticKeys = 0;
|
|
49812
|
+
let numWritableStaticKeys = 0;
|
|
49813
|
+
const lutWritableIdxs = luts.map(() => /* @__PURE__ */ new Set());
|
|
49814
|
+
const lutReadonlyIdxs = luts.map(() => /* @__PURE__ */ new Set());
|
|
49815
|
+
for (const [keyStr, props] of keyMap) {
|
|
49816
|
+
if (props.isSigner || programIds.has(keyStr)) {
|
|
49817
|
+
numStaticKeys++;
|
|
49818
|
+
if (props.isWritable) numWritableStaticKeys++;
|
|
49819
|
+
continue;
|
|
49820
|
+
}
|
|
49821
|
+
const lutEntry = lutLookup.get(keyStr);
|
|
49822
|
+
if (lutEntry) {
|
|
49823
|
+
if (props.isWritable) {
|
|
49824
|
+
lutWritableIdxs[lutEntry.lutIdx].add(lutEntry.addrIdx);
|
|
49825
|
+
} else {
|
|
49826
|
+
lutReadonlyIdxs[lutEntry.lutIdx].add(lutEntry.addrIdx);
|
|
49827
|
+
}
|
|
49828
|
+
} else {
|
|
49829
|
+
numStaticKeys++;
|
|
49830
|
+
if (props.isWritable) numWritableStaticKeys++;
|
|
49831
|
+
}
|
|
49832
|
+
}
|
|
49833
|
+
const fixedOverhead = 101;
|
|
49834
|
+
const staticKeysSection = compactU16Size(numStaticKeys) + numStaticKeys * 32;
|
|
49835
|
+
let ixSection = compactU16Size(ixs.length);
|
|
49836
|
+
for (const ix of ixs) {
|
|
49837
|
+
const numAccounts = ix.keys.length;
|
|
49838
|
+
ixSection += 1 + // programId index
|
|
49839
|
+
compactU16Size(numAccounts) + numAccounts + // account key indexes
|
|
49840
|
+
compactU16Size(ix.data.length) + ix.data.length;
|
|
49841
|
+
}
|
|
49842
|
+
let numUsedLuts = 0;
|
|
49843
|
+
let lutSection = 0;
|
|
49844
|
+
for (let li = 0; li < luts.length; li++) {
|
|
49845
|
+
const wCount = lutWritableIdxs[li].size;
|
|
49846
|
+
const rCount = lutReadonlyIdxs[li].size;
|
|
49847
|
+
if (wCount === 0 && rCount === 0) continue;
|
|
49848
|
+
numUsedLuts++;
|
|
49849
|
+
lutSection += 32 + // LUT address
|
|
49850
|
+
compactU16Size(wCount) + wCount + // writable indexes
|
|
49851
|
+
compactU16Size(rCount) + rCount;
|
|
49852
|
+
}
|
|
49853
|
+
lutSection += compactU16Size(numUsedLuts);
|
|
49854
|
+
let totalLutKeys = 0;
|
|
49855
|
+
for (let li = 0; li < luts.length; li++) {
|
|
49856
|
+
totalLutKeys += lutWritableIdxs[li].size + lutReadonlyIdxs[li].size;
|
|
49857
|
+
}
|
|
49858
|
+
const accountCount = numStaticKeys + totalLutKeys;
|
|
49859
|
+
let totalLutWritableKeys = 0;
|
|
49860
|
+
for (let li = 0; li < luts.length; li++) {
|
|
49861
|
+
totalLutWritableKeys += lutWritableIdxs[li].size;
|
|
49862
|
+
}
|
|
49863
|
+
const writableAccountCount = numWritableStaticKeys + totalLutWritableKeys;
|
|
49864
|
+
const size = fixedOverhead + staticKeysSection + ixSection + lutSection + 1;
|
|
49865
|
+
return { size, accountCount, writableAccountCount };
|
|
49866
|
+
}
|
|
49867
|
+
function computeFlashLoanNonSwapBudget({
|
|
49868
|
+
program,
|
|
49869
|
+
marginfiAccount,
|
|
49870
|
+
ixs,
|
|
49871
|
+
bankMap,
|
|
49872
|
+
addressLookupTableAccounts
|
|
49873
|
+
}) {
|
|
49874
|
+
const projectedActiveBanksKeys = computeProjectedActiveBanksNoCpi(
|
|
49875
|
+
marginfiAccount.balances,
|
|
49876
|
+
ixs,
|
|
49877
|
+
program
|
|
49878
|
+
);
|
|
49879
|
+
const projectedActiveBanks = projectedActiveBanksKeys.map((key) => {
|
|
49880
|
+
const b = bankMap.get(key.toBase58());
|
|
49881
|
+
if (!b) throw new Error(`Bank ${key.toBase58()} not found in computeFlashLoanNonSwapBudget`);
|
|
49882
|
+
return b;
|
|
49883
|
+
});
|
|
49884
|
+
const endIndex = ixs.length + 1;
|
|
49885
|
+
const beginFlIx = sync_instructions_default.makeBeginFlashLoanIx(
|
|
49886
|
+
program.programId,
|
|
49887
|
+
{ marginfiAccount: marginfiAccount.address, authority: marginfiAccount.authority },
|
|
49888
|
+
{ endIndex: new BN11__default.default(endIndex) }
|
|
49889
|
+
);
|
|
49890
|
+
const endFlRemainingAccounts = computeHealthAccountMetas(projectedActiveBanks);
|
|
49891
|
+
const endFlIx = sync_instructions_default.makeEndFlashLoanIx(
|
|
49892
|
+
program.programId,
|
|
49893
|
+
{ marginfiAccount: marginfiAccount.address, authority: marginfiAccount.authority },
|
|
49894
|
+
endFlRemainingAccounts.map((pubkey) => ({ pubkey, isSigner: false, isWritable: false }))
|
|
49895
|
+
);
|
|
49896
|
+
const allNonSwapIxs = [beginFlIx, ...ixs, endFlIx];
|
|
49897
|
+
const nonSwapMsg = new web3_js.TransactionMessage({
|
|
49898
|
+
payerKey: marginfiAccount.authority,
|
|
49899
|
+
recentBlockhash: web3_js.PublicKey.default.toBase58(),
|
|
49900
|
+
instructions: allNonSwapIxs
|
|
49901
|
+
}).compileToV0Message(addressLookupTableAccounts);
|
|
49902
|
+
const nonSwapSize = new web3_js.VersionedTransaction(nonSwapMsg).serialize().length;
|
|
49903
|
+
const { header, staticAccountKeys, addressTableLookups } = nonSwapMsg;
|
|
49904
|
+
const nonSwapTotal = staticAccountKeys.length + addressTableLookups.reduce(
|
|
49905
|
+
(s, l) => s + l.writableIndexes.length + l.readonlyIndexes.length,
|
|
49906
|
+
0
|
|
49907
|
+
);
|
|
49908
|
+
const sizeConstraint = MAX_TX_SIZE - nonSwapSize - SWAP_MERGE_OVERHEAD;
|
|
49909
|
+
const maxSwapTotalAccounts = MAX_ACCOUNT_LOCKS - nonSwapTotal;
|
|
49910
|
+
console.log("[flashloan-budget]", {
|
|
49911
|
+
method: "compiled",
|
|
49912
|
+
nonSwapSize,
|
|
49913
|
+
nonSwapTotal,
|
|
49914
|
+
sizeConstraint,
|
|
49915
|
+
maxSwapTotalAccounts
|
|
49916
|
+
});
|
|
49917
|
+
return { sizeConstraint, maxSwapTotalAccounts };
|
|
49918
|
+
}
|
|
49919
|
+
function compileFlashloanPrecheck({
|
|
49920
|
+
allIxs,
|
|
49921
|
+
payer,
|
|
49922
|
+
luts,
|
|
49923
|
+
sizeConstraint,
|
|
49924
|
+
swapIxCount,
|
|
49925
|
+
swapLutCount
|
|
49926
|
+
}) {
|
|
49927
|
+
const msg = new web3_js.TransactionMessage({
|
|
49928
|
+
payerKey: payer,
|
|
49929
|
+
recentBlockhash: web3_js.PublicKey.default.toBase58(),
|
|
49930
|
+
instructions: allIxs
|
|
49931
|
+
}).compileToV0Message(luts);
|
|
49932
|
+
const rawSize = new web3_js.VersionedTransaction(msg).serialize().length;
|
|
49933
|
+
const fullTxSize = rawSize + FL_IX_OVERHEAD;
|
|
49934
|
+
const overshoot = fullTxSize - MAX_TX_SIZE;
|
|
49935
|
+
const { header, staticAccountKeys, addressTableLookups } = msg;
|
|
49936
|
+
const writableStatic = staticAccountKeys.length - header.numReadonlySignedAccounts - header.numReadonlyUnsignedAccounts;
|
|
49937
|
+
const writableLut = addressTableLookups.reduce((s, l) => s + l.writableIndexes.length, 0);
|
|
49938
|
+
const writableAccounts = writableStatic + writableLut;
|
|
49939
|
+
const totalAccounts = staticAccountKeys.length + addressTableLookups.reduce(
|
|
49940
|
+
(s, l) => s + l.writableIndexes.length + l.readonlyIndexes.length,
|
|
49941
|
+
0
|
|
49942
|
+
);
|
|
49943
|
+
console.log("[flashloan-precheck]", {
|
|
49944
|
+
fullTxSize,
|
|
49945
|
+
overshoot,
|
|
49946
|
+
sizeConstraint,
|
|
49947
|
+
writableAccounts,
|
|
49948
|
+
totalAccounts,
|
|
49949
|
+
staticKeys: staticAccountKeys.length,
|
|
49950
|
+
numLuts: addressTableLookups.length,
|
|
49951
|
+
swapIxCount,
|
|
49952
|
+
swapLutCount
|
|
49953
|
+
});
|
|
49954
|
+
return { fullTxSize, overshoot, writableAccounts, totalAccounts };
|
|
49955
|
+
}
|
|
49956
|
+
async function buildBudgetIx(config, program, marginfiAccount, bankMap, bankMetadataMap, overrideInferAccounts) {
|
|
49957
|
+
const { bank, tokenProgram } = config;
|
|
49958
|
+
switch (config.type) {
|
|
49959
|
+
case "borrow":
|
|
49960
|
+
return makeBorrowIx3({
|
|
49961
|
+
program,
|
|
49962
|
+
bank,
|
|
49963
|
+
bankMap,
|
|
49964
|
+
tokenProgram,
|
|
49965
|
+
amount: 1,
|
|
49966
|
+
marginfiAccount,
|
|
49967
|
+
authority: marginfiAccount.authority,
|
|
49968
|
+
isSync: true,
|
|
49969
|
+
opts: { createAtas: false, wrapAndUnwrapSol: false, overrideInferAccounts }
|
|
49970
|
+
});
|
|
49971
|
+
case "repay":
|
|
49972
|
+
return makeRepayIx3({
|
|
49973
|
+
program,
|
|
49974
|
+
bank,
|
|
49975
|
+
tokenProgram,
|
|
49976
|
+
amount: 1,
|
|
49977
|
+
accountAddress: marginfiAccount.address,
|
|
49978
|
+
authority: marginfiAccount.authority,
|
|
49979
|
+
repayAll: false,
|
|
49980
|
+
isSync: true,
|
|
49981
|
+
opts: { wrapAndUnwrapSol: false, overrideInferAccounts }
|
|
49982
|
+
});
|
|
49983
|
+
case "deposit":
|
|
49984
|
+
return buildDepositBudgetIx(
|
|
49985
|
+
config,
|
|
49986
|
+
program,
|
|
49987
|
+
marginfiAccount,
|
|
49988
|
+
bankMetadataMap,
|
|
49989
|
+
overrideInferAccounts
|
|
49990
|
+
);
|
|
49991
|
+
case "withdraw":
|
|
49992
|
+
return buildWithdrawBudgetIx(
|
|
49993
|
+
config,
|
|
49994
|
+
program,
|
|
49995
|
+
marginfiAccount,
|
|
49996
|
+
bankMap,
|
|
49997
|
+
bankMetadataMap,
|
|
49998
|
+
overrideInferAccounts
|
|
49999
|
+
);
|
|
50000
|
+
}
|
|
50001
|
+
}
|
|
50002
|
+
async function buildDepositBudgetIx(config, program, marginfiAccount, bankMetadataMap, overrideInferAccounts) {
|
|
50003
|
+
const { bank, tokenProgram } = config;
|
|
50004
|
+
const opts = { wrapAndUnwrapSol: false, overrideInferAccounts };
|
|
50005
|
+
switch (bank.config.assetTag) {
|
|
50006
|
+
case 3 /* KAMINO */: {
|
|
50007
|
+
const reserve = bankMetadataMap[bank.address.toBase58()]?.kaminoStates?.reserveState;
|
|
50008
|
+
if (!reserve) {
|
|
50009
|
+
throw TransactionBuildingError.kaminoReserveNotFound(
|
|
50010
|
+
bank.address.toBase58(),
|
|
50011
|
+
bank.mint.toBase58(),
|
|
50012
|
+
bank.tokenSymbol
|
|
50013
|
+
);
|
|
50014
|
+
}
|
|
50015
|
+
return makeKaminoDepositIx3({
|
|
50016
|
+
program,
|
|
50017
|
+
bank,
|
|
50018
|
+
tokenProgram,
|
|
50019
|
+
amount: 1,
|
|
50020
|
+
accountAddress: marginfiAccount.address,
|
|
50021
|
+
authority: marginfiAccount.authority,
|
|
50022
|
+
group: marginfiAccount.group,
|
|
50023
|
+
reserve,
|
|
50024
|
+
isSync: true,
|
|
50025
|
+
opts
|
|
50026
|
+
});
|
|
50027
|
+
}
|
|
50028
|
+
case 4 /* DRIFT */: {
|
|
50029
|
+
const driftState = bankMetadataMap[bank.address.toBase58()]?.driftStates;
|
|
50030
|
+
if (!driftState) {
|
|
50031
|
+
throw TransactionBuildingError.driftStateNotFound(
|
|
50032
|
+
bank.address.toBase58(),
|
|
50033
|
+
bank.mint.toBase58(),
|
|
50034
|
+
bank.tokenSymbol
|
|
50035
|
+
);
|
|
50036
|
+
}
|
|
50037
|
+
return makeDriftDepositIx3({
|
|
50038
|
+
program,
|
|
50039
|
+
bank,
|
|
50040
|
+
tokenProgram,
|
|
50041
|
+
amount: 1,
|
|
50042
|
+
accountAddress: marginfiAccount.address,
|
|
50043
|
+
authority: marginfiAccount.authority,
|
|
50044
|
+
group: marginfiAccount.group,
|
|
50045
|
+
driftMarketIndex: driftState.spotMarketState.marketIndex,
|
|
50046
|
+
driftOracle: driftState.spotMarketState.oracle,
|
|
50047
|
+
isSync: true,
|
|
50048
|
+
opts
|
|
50049
|
+
});
|
|
50050
|
+
}
|
|
50051
|
+
case 6 /* JUPLEND */: {
|
|
50052
|
+
return makeJuplendDepositIx2({
|
|
50053
|
+
program,
|
|
50054
|
+
bank,
|
|
50055
|
+
tokenProgram,
|
|
50056
|
+
amount: 1,
|
|
50057
|
+
accountAddress: marginfiAccount.address,
|
|
50058
|
+
authority: marginfiAccount.authority,
|
|
50059
|
+
group: marginfiAccount.group,
|
|
50060
|
+
isSync: true,
|
|
50061
|
+
opts
|
|
50062
|
+
});
|
|
50063
|
+
}
|
|
50064
|
+
default: {
|
|
50065
|
+
return makeDepositIx3({
|
|
50066
|
+
program,
|
|
50067
|
+
bank,
|
|
50068
|
+
tokenProgram,
|
|
50069
|
+
amount: 1,
|
|
50070
|
+
accountAddress: marginfiAccount.address,
|
|
50071
|
+
authority: marginfiAccount.authority,
|
|
50072
|
+
group: marginfiAccount.group,
|
|
50073
|
+
isSync: true,
|
|
50074
|
+
opts
|
|
50075
|
+
});
|
|
50076
|
+
}
|
|
50077
|
+
}
|
|
50302
50078
|
}
|
|
50303
|
-
|
|
50304
|
-
|
|
50305
|
-
|
|
50306
|
-
|
|
50307
|
-
|
|
50308
|
-
|
|
50309
|
-
|
|
50310
|
-
|
|
50311
|
-
|
|
50312
|
-
|
|
50313
|
-
|
|
50314
|
-
|
|
50315
|
-
|
|
50316
|
-
|
|
50317
|
-
|
|
50318
|
-
|
|
50319
|
-
|
|
50320
|
-
|
|
50321
|
-
|
|
50322
|
-
|
|
50323
|
-
|
|
50324
|
-
|
|
50325
|
-
|
|
50326
|
-
|
|
50327
|
-
|
|
50328
|
-
|
|
50329
|
-
const swapInstructionResponse = await jupiterApiClient.swapInstructionsPost({
|
|
50330
|
-
swapRequest: {
|
|
50331
|
-
quoteResponse: swapQuote,
|
|
50332
|
-
userPublicKey: authority.toBase58(),
|
|
50333
|
-
feeAccount: hasFeeAccount ? feeAccount : void 0,
|
|
50334
|
-
wrapAndUnwrapSol: false,
|
|
50335
|
-
destinationTokenAccount: destinationTokenAccount.toBase58()
|
|
50079
|
+
async function buildWithdrawBudgetIx(config, program, marginfiAccount, bankMap, bankMetadataMap, overrideInferAccounts) {
|
|
50080
|
+
const { bank, tokenProgram } = config;
|
|
50081
|
+
const opts = { createAtas: false, wrapAndUnwrapSol: false, overrideInferAccounts };
|
|
50082
|
+
switch (bank.config.assetTag) {
|
|
50083
|
+
case 3 /* KAMINO */: {
|
|
50084
|
+
const reserve = bankMetadataMap[bank.address.toBase58()]?.kaminoStates?.reserveState;
|
|
50085
|
+
if (!reserve) {
|
|
50086
|
+
throw TransactionBuildingError.kaminoReserveNotFound(
|
|
50087
|
+
bank.address.toBase58(),
|
|
50088
|
+
bank.mint.toBase58(),
|
|
50089
|
+
bank.tokenSymbol
|
|
50090
|
+
);
|
|
50091
|
+
}
|
|
50092
|
+
return makeKaminoWithdrawIx3({
|
|
50093
|
+
program,
|
|
50094
|
+
bank,
|
|
50095
|
+
bankMap,
|
|
50096
|
+
tokenProgram,
|
|
50097
|
+
cTokenAmount: 1,
|
|
50098
|
+
marginfiAccount,
|
|
50099
|
+
authority: marginfiAccount.authority,
|
|
50100
|
+
reserve,
|
|
50101
|
+
withdrawAll: false,
|
|
50102
|
+
isSync: true,
|
|
50103
|
+
opts
|
|
50104
|
+
});
|
|
50336
50105
|
}
|
|
50337
|
-
|
|
50338
|
-
|
|
50339
|
-
|
|
50340
|
-
|
|
50341
|
-
|
|
50342
|
-
|
|
50343
|
-
|
|
50344
|
-
|
|
50345
|
-
|
|
50106
|
+
case 4 /* DRIFT */: {
|
|
50107
|
+
const driftState = bankMetadataMap[bank.address.toBase58()]?.driftStates;
|
|
50108
|
+
if (!driftState) {
|
|
50109
|
+
throw TransactionBuildingError.driftStateNotFound(
|
|
50110
|
+
bank.address.toBase58(),
|
|
50111
|
+
bank.mint.toBase58(),
|
|
50112
|
+
bank.tokenSymbol
|
|
50113
|
+
);
|
|
50114
|
+
}
|
|
50115
|
+
return makeDriftWithdrawIx3({
|
|
50116
|
+
program,
|
|
50117
|
+
bank,
|
|
50118
|
+
bankMap,
|
|
50119
|
+
tokenProgram,
|
|
50120
|
+
amount: 1,
|
|
50121
|
+
marginfiAccount,
|
|
50122
|
+
authority: marginfiAccount.authority,
|
|
50123
|
+
driftSpotMarket: driftState.spotMarketState,
|
|
50124
|
+
userRewards: driftState.userRewards,
|
|
50125
|
+
withdrawAll: false,
|
|
50126
|
+
isSync: true,
|
|
50127
|
+
opts
|
|
50128
|
+
});
|
|
50346
50129
|
}
|
|
50347
|
-
|
|
50348
|
-
|
|
50349
|
-
|
|
50350
|
-
|
|
50351
|
-
|
|
50352
|
-
|
|
50353
|
-
|
|
50354
|
-
|
|
50355
|
-
|
|
50356
|
-
|
|
50357
|
-
|
|
50358
|
-
|
|
50359
|
-
|
|
50360
|
-
|
|
50361
|
-
|
|
50362
|
-
|
|
50363
|
-
|
|
50364
|
-
|
|
50365
|
-
|
|
50366
|
-
|
|
50367
|
-
}
|
|
50368
|
-
|
|
50369
|
-
|
|
50370
|
-
|
|
50371
|
-
|
|
50372
|
-
|
|
50373
|
-
|
|
50130
|
+
case 6 /* JUPLEND */: {
|
|
50131
|
+
const jupLendState = bankMetadataMap[bank.address.toBase58()]?.jupLendStates;
|
|
50132
|
+
if (!jupLendState) {
|
|
50133
|
+
throw TransactionBuildingError.jupLendStateNotFound(
|
|
50134
|
+
bank.address.toBase58(),
|
|
50135
|
+
bank.mint.toBase58(),
|
|
50136
|
+
bank.tokenSymbol
|
|
50137
|
+
);
|
|
50138
|
+
}
|
|
50139
|
+
return makeJuplendWithdrawIx2({
|
|
50140
|
+
program,
|
|
50141
|
+
bank,
|
|
50142
|
+
bankMap,
|
|
50143
|
+
tokenProgram,
|
|
50144
|
+
amount: 1,
|
|
50145
|
+
marginfiAccount,
|
|
50146
|
+
authority: marginfiAccount.authority,
|
|
50147
|
+
jupLendingState: jupLendState.jupLendingState,
|
|
50148
|
+
withdrawAll: false,
|
|
50149
|
+
opts
|
|
50150
|
+
});
|
|
50151
|
+
}
|
|
50152
|
+
default: {
|
|
50153
|
+
return makeWithdrawIx3({
|
|
50154
|
+
program,
|
|
50155
|
+
bank,
|
|
50156
|
+
bankMap,
|
|
50157
|
+
tokenProgram,
|
|
50158
|
+
amount: 1,
|
|
50159
|
+
marginfiAccount,
|
|
50160
|
+
authority: marginfiAccount.authority,
|
|
50161
|
+
withdrawAll: false,
|
|
50162
|
+
isSync: true,
|
|
50163
|
+
opts
|
|
50164
|
+
});
|
|
50165
|
+
}
|
|
50166
|
+
}
|
|
50374
50167
|
}
|
|
50375
|
-
function
|
|
50376
|
-
|
|
50377
|
-
|
|
50168
|
+
async function computeFlashloanSwapConstraints({
|
|
50169
|
+
program,
|
|
50170
|
+
marginfiAccount,
|
|
50171
|
+
bankMap,
|
|
50172
|
+
addressLookupTableAccounts,
|
|
50173
|
+
bankMetadataMap,
|
|
50174
|
+
primaryIx,
|
|
50175
|
+
secondaryIx,
|
|
50176
|
+
overrideInferAccounts
|
|
50177
|
+
}) {
|
|
50178
|
+
const cuRequestIxs = [
|
|
50179
|
+
web3_js.ComputeBudgetProgram.setComputeUnitLimit({ units: 12e5 }),
|
|
50180
|
+
web3_js.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 })
|
|
50181
|
+
];
|
|
50182
|
+
const [primaryResult, secondaryResult] = await Promise.all([
|
|
50183
|
+
buildBudgetIx(
|
|
50184
|
+
primaryIx,
|
|
50185
|
+
program,
|
|
50186
|
+
marginfiAccount,
|
|
50187
|
+
bankMap,
|
|
50188
|
+
bankMetadataMap,
|
|
50189
|
+
overrideInferAccounts
|
|
50190
|
+
),
|
|
50191
|
+
buildBudgetIx(
|
|
50192
|
+
secondaryIx,
|
|
50193
|
+
program,
|
|
50194
|
+
marginfiAccount,
|
|
50195
|
+
bankMap,
|
|
50196
|
+
bankMetadataMap,
|
|
50197
|
+
overrideInferAccounts
|
|
50198
|
+
)
|
|
50199
|
+
]);
|
|
50200
|
+
return computeFlashLoanNonSwapBudget({
|
|
50201
|
+
program,
|
|
50202
|
+
marginfiAccount,
|
|
50203
|
+
bankMap,
|
|
50204
|
+
addressLookupTableAccounts,
|
|
50205
|
+
ixs: [...cuRequestIxs, ...primaryResult.instructions, ...secondaryResult.instructions]
|
|
50206
|
+
});
|
|
50378
50207
|
}
|
|
50379
50208
|
|
|
50380
50209
|
// src/services/price/utils/smart-crank.utils.ts
|
|
@@ -52638,6 +52467,230 @@ function getValidatorVoteAccountByBank() {
|
|
|
52638
52467
|
}
|
|
52639
52468
|
return _voteAccountByBank;
|
|
52640
52469
|
}
|
|
52470
|
+
async function computeStakedBankMultipliers(stakedBanks, connection) {
|
|
52471
|
+
const multiplierByBank = /* @__PURE__ */ new Map();
|
|
52472
|
+
if (stakedBanks.length === 0) {
|
|
52473
|
+
return multiplierByBank;
|
|
52474
|
+
}
|
|
52475
|
+
const metadataMap = getStakedBankMetadataMap();
|
|
52476
|
+
const stakedBankAddresses = [];
|
|
52477
|
+
const poolStakeAddresses = [];
|
|
52478
|
+
const lstMintAddresses = [];
|
|
52479
|
+
for (const bank of stakedBanks) {
|
|
52480
|
+
const metadata = metadataMap.get(bank.address.toBase58());
|
|
52481
|
+
if (!metadata) {
|
|
52482
|
+
multiplierByBank.set(bank.address.toBase58(), new BigNumber3__default.default(1));
|
|
52483
|
+
continue;
|
|
52484
|
+
}
|
|
52485
|
+
const pool = findPoolAddress(new web3_js.PublicKey(metadata.validatorVoteAccount));
|
|
52486
|
+
stakedBankAddresses.push(bank.address.toBase58());
|
|
52487
|
+
poolStakeAddresses.push(findPoolStakeAddress(pool));
|
|
52488
|
+
lstMintAddresses.push(findPoolMintAddress(pool));
|
|
52489
|
+
}
|
|
52490
|
+
if (stakedBankAddresses.length === 0) {
|
|
52491
|
+
return multiplierByBank;
|
|
52492
|
+
}
|
|
52493
|
+
const allAddresses = [
|
|
52494
|
+
...poolStakeAddresses.map((a) => a.toBase58()),
|
|
52495
|
+
...lstMintAddresses.map((a) => a.toBase58())
|
|
52496
|
+
];
|
|
52497
|
+
const accountInfos = await chunkedGetRawMultipleAccountInfoOrdered(connection, allAddresses);
|
|
52498
|
+
const poolStakeInfos = accountInfos.slice(0, poolStakeAddresses.length);
|
|
52499
|
+
const lstMintInfos = accountInfos.slice(poolStakeAddresses.length);
|
|
52500
|
+
for (let i = 0; i < stakedBankAddresses.length; i++) {
|
|
52501
|
+
const bankAddr = stakedBankAddresses[i];
|
|
52502
|
+
const poolStakeInfo = poolStakeInfos[i];
|
|
52503
|
+
const lstMintInfo = lstMintInfos[i];
|
|
52504
|
+
if (!poolStakeInfo || !lstMintInfo) {
|
|
52505
|
+
multiplierByBank.set(bankAddr, new BigNumber3__default.default(1));
|
|
52506
|
+
continue;
|
|
52507
|
+
}
|
|
52508
|
+
const stakeLamports = poolStakeInfo.lamports;
|
|
52509
|
+
const supplyBuffer = lstMintInfo.data.slice(36, 44);
|
|
52510
|
+
const lstMintSupply = Number(Buffer.from(supplyBuffer).readBigUInt64LE(0));
|
|
52511
|
+
if (lstMintSupply === 0) {
|
|
52512
|
+
multiplierByBank.set(bankAddr, new BigNumber3__default.default(1));
|
|
52513
|
+
continue;
|
|
52514
|
+
}
|
|
52515
|
+
const adjustedStake = Math.max(stakeLamports - web3_js.LAMPORTS_PER_SOL, 0);
|
|
52516
|
+
const multiplier = new BigNumber3__default.default(adjustedStake).dividedBy(lstMintSupply);
|
|
52517
|
+
multiplierByBank.set(bankAddr, multiplier);
|
|
52518
|
+
}
|
|
52519
|
+
return multiplierByBank;
|
|
52520
|
+
}
|
|
52521
|
+
var SYSVAR_CLOCK_ID2 = new web3_js.PublicKey("SysvarC1ock11111111111111111111111111111111");
|
|
52522
|
+
async function makeMintStakedLstIx(params) {
|
|
52523
|
+
const { amount, authority, stakeAccountPk, validator, connection } = params;
|
|
52524
|
+
const pool = findPoolAddress(validator);
|
|
52525
|
+
const lstMint = findPoolMintAddress(pool);
|
|
52526
|
+
const poolStakeAuth = findPoolStakeAuthorityAddress(pool);
|
|
52527
|
+
const lstAta = getAssociatedTokenAddressSync(lstMint, authority);
|
|
52528
|
+
const [lstAccInfo, stakeAccInfoParsed, rentExemptReserve] = await Promise.all([
|
|
52529
|
+
connection.getAccountInfo(lstAta),
|
|
52530
|
+
connection.getParsedAccountInfo(stakeAccountPk),
|
|
52531
|
+
connection.getMinimumBalanceForRentExemption(web3_js.StakeProgram.space)
|
|
52532
|
+
]);
|
|
52533
|
+
const stakeAccParsed = stakeAccInfoParsed?.value?.data;
|
|
52534
|
+
const amountLamports = Math.round(Number(amount) * web3_js.LAMPORTS_PER_SOL);
|
|
52535
|
+
const stakeAccLamports = Number(stakeAccParsed?.parsed?.info?.stake?.delegation?.stake ?? 0);
|
|
52536
|
+
const isFullStake = amountLamports >= stakeAccLamports;
|
|
52537
|
+
const instructions2 = [];
|
|
52538
|
+
const signers = [];
|
|
52539
|
+
if (!lstAccInfo) {
|
|
52540
|
+
instructions2.push(
|
|
52541
|
+
createAssociatedTokenAccountInstruction(authority, lstAta, authority, lstMint)
|
|
52542
|
+
);
|
|
52543
|
+
}
|
|
52544
|
+
let targetStakePubkey;
|
|
52545
|
+
if (!isFullStake) {
|
|
52546
|
+
const splitStakeAccount = web3_js.Keypair.generate();
|
|
52547
|
+
signers.push(splitStakeAccount);
|
|
52548
|
+
targetStakePubkey = splitStakeAccount.publicKey;
|
|
52549
|
+
instructions2.push(
|
|
52550
|
+
...web3_js.StakeProgram.split(
|
|
52551
|
+
{
|
|
52552
|
+
stakePubkey: stakeAccountPk,
|
|
52553
|
+
authorizedPubkey: authority,
|
|
52554
|
+
splitStakePubkey: splitStakeAccount.publicKey,
|
|
52555
|
+
lamports: amountLamports
|
|
52556
|
+
},
|
|
52557
|
+
rentExemptReserve
|
|
52558
|
+
).instructions
|
|
52559
|
+
);
|
|
52560
|
+
} else {
|
|
52561
|
+
targetStakePubkey = stakeAccountPk;
|
|
52562
|
+
}
|
|
52563
|
+
const [authorizeStakerIx, authorizeWithdrawIx] = await Promise.all([
|
|
52564
|
+
web3_js.StakeProgram.authorize({
|
|
52565
|
+
stakePubkey: targetStakePubkey,
|
|
52566
|
+
authorizedPubkey: authority,
|
|
52567
|
+
newAuthorizedPubkey: poolStakeAuth,
|
|
52568
|
+
stakeAuthorizationType: web3_js.StakeAuthorizationLayout.Staker
|
|
52569
|
+
}).instructions,
|
|
52570
|
+
web3_js.StakeProgram.authorize({
|
|
52571
|
+
stakePubkey: targetStakePubkey,
|
|
52572
|
+
authorizedPubkey: authority,
|
|
52573
|
+
newAuthorizedPubkey: poolStakeAuth,
|
|
52574
|
+
stakeAuthorizationType: web3_js.StakeAuthorizationLayout.Withdrawer
|
|
52575
|
+
}).instructions
|
|
52576
|
+
]);
|
|
52577
|
+
[authorizeStakerIx[0], authorizeWithdrawIx[0]].forEach((ix) => {
|
|
52578
|
+
if (ix) {
|
|
52579
|
+
ix.keys = ix.keys.map((key) => ({
|
|
52580
|
+
...key,
|
|
52581
|
+
isWritable: key.pubkey.equals(SYSVAR_CLOCK_ID2) ? false : key.isWritable
|
|
52582
|
+
}));
|
|
52583
|
+
}
|
|
52584
|
+
});
|
|
52585
|
+
instructions2.push(...authorizeStakerIx, ...authorizeWithdrawIx);
|
|
52586
|
+
const depositStakeIx = await SinglePoolInstruction.depositStake(
|
|
52587
|
+
pool,
|
|
52588
|
+
targetStakePubkey,
|
|
52589
|
+
lstAta,
|
|
52590
|
+
authority
|
|
52591
|
+
);
|
|
52592
|
+
instructions2.push(depositStakeIx);
|
|
52593
|
+
return { instructions: instructions2, keys: signers };
|
|
52594
|
+
}
|
|
52595
|
+
async function makeMintStakedLstTx(params) {
|
|
52596
|
+
const { connection, luts, blockhash: providedBlockhash } = params;
|
|
52597
|
+
const { instructions: instructions2, keys } = await makeMintStakedLstIx(params);
|
|
52598
|
+
const blockhash = providedBlockhash ?? (await connection.getLatestBlockhash("confirmed")).blockhash;
|
|
52599
|
+
const message = new web3_js.TransactionMessage({
|
|
52600
|
+
payerKey: params.authority,
|
|
52601
|
+
recentBlockhash: blockhash,
|
|
52602
|
+
instructions: instructions2
|
|
52603
|
+
}).compileToV0Message(luts);
|
|
52604
|
+
const tx = new web3_js.VersionedTransaction(message);
|
|
52605
|
+
return addTransactionMetadata(tx, {
|
|
52606
|
+
signers: keys,
|
|
52607
|
+
addressLookupTables: luts,
|
|
52608
|
+
type: "DEPOSIT_STAKE" /* DEPOSIT_STAKE */
|
|
52609
|
+
});
|
|
52610
|
+
}
|
|
52611
|
+
async function makeRedeemStakedLstIx(params) {
|
|
52612
|
+
const { amount, authority, validator, connection } = params;
|
|
52613
|
+
const pool = findPoolAddress(validator);
|
|
52614
|
+
const lstMint = findPoolMintAddress(pool);
|
|
52615
|
+
const mintAuthority = findPoolMintAuthorityAddress(pool);
|
|
52616
|
+
const lstAta = getAssociatedTokenAddressSync(lstMint, authority);
|
|
52617
|
+
const rentExemption = await connection.getMinimumBalanceForRentExemption(
|
|
52618
|
+
web3_js.StakeProgram.space
|
|
52619
|
+
);
|
|
52620
|
+
const stakeAmount = new BigNumber3__default.default(new BigNumber3__default.default(amount).toString());
|
|
52621
|
+
const instructions2 = [];
|
|
52622
|
+
const signers = [];
|
|
52623
|
+
const stakeAccount = web3_js.Keypair.generate();
|
|
52624
|
+
signers.push(stakeAccount);
|
|
52625
|
+
instructions2.push(
|
|
52626
|
+
web3_js.SystemProgram.createAccount({
|
|
52627
|
+
fromPubkey: authority,
|
|
52628
|
+
newAccountPubkey: stakeAccount.publicKey,
|
|
52629
|
+
lamports: rentExemption,
|
|
52630
|
+
space: web3_js.StakeProgram.space,
|
|
52631
|
+
programId: web3_js.StakeProgram.programId
|
|
52632
|
+
})
|
|
52633
|
+
);
|
|
52634
|
+
instructions2.push(
|
|
52635
|
+
createApproveInstruction(
|
|
52636
|
+
lstAta,
|
|
52637
|
+
mintAuthority,
|
|
52638
|
+
authority,
|
|
52639
|
+
BigInt(stakeAmount.multipliedBy(1e9).toFixed(0))
|
|
52640
|
+
)
|
|
52641
|
+
);
|
|
52642
|
+
const withdrawStakeIx = await SinglePoolInstruction.withdrawStake(
|
|
52643
|
+
pool,
|
|
52644
|
+
stakeAccount.publicKey,
|
|
52645
|
+
authority,
|
|
52646
|
+
lstAta,
|
|
52647
|
+
stakeAmount
|
|
52648
|
+
);
|
|
52649
|
+
instructions2.push(withdrawStakeIx);
|
|
52650
|
+
return { instructions: instructions2, keys: signers };
|
|
52651
|
+
}
|
|
52652
|
+
async function makeRedeemStakedLstTx(params) {
|
|
52653
|
+
const { connection, luts, blockhash: providedBlockhash } = params;
|
|
52654
|
+
const { instructions: instructions2, keys } = await makeRedeemStakedLstIx(params);
|
|
52655
|
+
const blockhash = providedBlockhash ?? (await connection.getLatestBlockhash("confirmed")).blockhash;
|
|
52656
|
+
const message = new web3_js.TransactionMessage({
|
|
52657
|
+
payerKey: params.authority,
|
|
52658
|
+
recentBlockhash: blockhash,
|
|
52659
|
+
instructions: instructions2
|
|
52660
|
+
}).compileToV0Message(luts);
|
|
52661
|
+
const tx = new web3_js.VersionedTransaction(message);
|
|
52662
|
+
return addTransactionMetadata(tx, {
|
|
52663
|
+
signers: keys,
|
|
52664
|
+
addressLookupTables: luts,
|
|
52665
|
+
type: "WITHDRAW_STAKE" /* WITHDRAW_STAKE */
|
|
52666
|
+
});
|
|
52667
|
+
}
|
|
52668
|
+
async function makeMergeStakeAccountsTx(params) {
|
|
52669
|
+
const {
|
|
52670
|
+
authority,
|
|
52671
|
+
sourceStakeAccount,
|
|
52672
|
+
destinationStakeAccount,
|
|
52673
|
+
connection,
|
|
52674
|
+
luts,
|
|
52675
|
+
blockhash: providedBlockhash
|
|
52676
|
+
} = params;
|
|
52677
|
+
const mergeIx = web3_js.StakeProgram.merge({
|
|
52678
|
+
stakePubkey: destinationStakeAccount,
|
|
52679
|
+
sourceStakePubKey: sourceStakeAccount,
|
|
52680
|
+
authorizedPubkey: authority
|
|
52681
|
+
}).instructions;
|
|
52682
|
+
const blockhash = providedBlockhash ?? (await connection.getLatestBlockhash("confirmed")).blockhash;
|
|
52683
|
+
const message = new web3_js.TransactionMessage({
|
|
52684
|
+
payerKey: authority,
|
|
52685
|
+
recentBlockhash: blockhash,
|
|
52686
|
+
instructions: mergeIx
|
|
52687
|
+
}).compileToV0Message(luts);
|
|
52688
|
+
const tx = new web3_js.VersionedTransaction(message);
|
|
52689
|
+
return addTransactionMetadata(tx, {
|
|
52690
|
+
addressLookupTables: luts,
|
|
52691
|
+
type: "MERGE_STAKE_ACCOUNTS" /* MERGE_STAKE_ACCOUNTS */
|
|
52692
|
+
});
|
|
52693
|
+
}
|
|
52641
52694
|
async function getKaminoMetadata(options) {
|
|
52642
52695
|
const kaminoBanks = options.banks.filter((b) => b.config.assetTag === 3 /* KAMINO */);
|
|
52643
52696
|
const DEFAULT_PUBKEY = web3_js.PublicKey.default;
|
|
@@ -55074,66 +55127,6 @@ var MarginfiAccountWrapper = class {
|
|
|
55074
55127
|
return this.account.getHealthCheckAccounts(this.client.bankMap, mandatoryBanks, excludedBanks);
|
|
55075
55128
|
}
|
|
55076
55129
|
// ----------------------------------------------------------------------------
|
|
55077
|
-
// Native stake actions
|
|
55078
|
-
// Note: These call standalone action functions directly rather than routing
|
|
55079
|
-
// through this.account because they interact with the SPL stake pool program,
|
|
55080
|
-
// not the marginfi program. No MarginfiAccount state is needed.
|
|
55081
|
-
// ----------------------------------------------------------------------------
|
|
55082
|
-
/**
|
|
55083
|
-
* Creates a transaction to mint LST from a native stake account.
|
|
55084
|
-
*
|
|
55085
|
-
* Converts a native stake account (or a portion of it) into LST tokens
|
|
55086
|
-
* by depositing the stake into the single-validator pool.
|
|
55087
|
-
*
|
|
55088
|
-
* @param amount - SOL amount to convert (in UI units)
|
|
55089
|
-
* @param stakeAccountPk - The stake account to convert
|
|
55090
|
-
* @param validator - The validator vote account
|
|
55091
|
-
*/
|
|
55092
|
-
async makeMintStakedLstTx(amount, stakeAccountPk, validator) {
|
|
55093
|
-
return makeMintStakedLstTx({
|
|
55094
|
-
amount,
|
|
55095
|
-
authority: this.authority,
|
|
55096
|
-
stakeAccountPk,
|
|
55097
|
-
validator,
|
|
55098
|
-
connection: this.client.program.provider.connection,
|
|
55099
|
-
luts: this.client.addressLookupTables
|
|
55100
|
-
});
|
|
55101
|
-
}
|
|
55102
|
-
/**
|
|
55103
|
-
* Creates a transaction to redeem LST tokens back to a native stake account.
|
|
55104
|
-
*
|
|
55105
|
-
* Burns LST tokens and withdraws the underlying stake into a new stake account.
|
|
55106
|
-
*
|
|
55107
|
-
* @param amount - LST amount to redeem (in UI units)
|
|
55108
|
-
* @param validator - The validator vote account
|
|
55109
|
-
*/
|
|
55110
|
-
async makeRedeemStakedLstTx(amount, validator) {
|
|
55111
|
-
return makeRedeemStakedLstTx({
|
|
55112
|
-
amount,
|
|
55113
|
-
authority: this.authority,
|
|
55114
|
-
validator,
|
|
55115
|
-
connection: this.client.program.provider.connection,
|
|
55116
|
-
luts: this.client.addressLookupTables
|
|
55117
|
-
});
|
|
55118
|
-
}
|
|
55119
|
-
/**
|
|
55120
|
-
* Creates a transaction to merge two stake accounts.
|
|
55121
|
-
*
|
|
55122
|
-
* Both accounts must share the same authorized staker/withdrawer and vote account.
|
|
55123
|
-
*
|
|
55124
|
-
* @param sourceStakeAccount - The stake account to merge from (will be consumed)
|
|
55125
|
-
* @param destinationStakeAccount - The stake account to merge into
|
|
55126
|
-
*/
|
|
55127
|
-
async makeMergeStakeAccountsTx(sourceStakeAccount, destinationStakeAccount) {
|
|
55128
|
-
return makeMergeStakeAccountsTx({
|
|
55129
|
-
authority: this.authority,
|
|
55130
|
-
sourceStakeAccount,
|
|
55131
|
-
destinationStakeAccount,
|
|
55132
|
-
connection: this.client.program.provider.connection,
|
|
55133
|
-
luts: this.client.addressLookupTables
|
|
55134
|
-
});
|
|
55135
|
-
}
|
|
55136
|
-
// ----------------------------------------------------------------------------
|
|
55137
55130
|
// Helper methods
|
|
55138
55131
|
// ----------------------------------------------------------------------------
|
|
55139
55132
|
/**
|
|
@@ -55403,56 +55396,11 @@ var Project0Client = class _Project0Client {
|
|
|
55403
55396
|
break;
|
|
55404
55397
|
}
|
|
55405
55398
|
});
|
|
55406
|
-
const
|
|
55407
|
-
|
|
55408
|
-
|
|
55409
|
-
|
|
55410
|
-
|
|
55411
|
-
const lstMintAddresses = [];
|
|
55412
|
-
for (const bank of stakedBanks) {
|
|
55413
|
-
const metadata = metadataMap.get(bank.address.toBase58());
|
|
55414
|
-
if (!metadata) {
|
|
55415
|
-
assetShareMultiplierByBank.set(bank.address.toBase58(), new BigNumber3__default.default(1));
|
|
55416
|
-
continue;
|
|
55417
|
-
}
|
|
55418
|
-
const pool = findPoolAddress(new web3_js.PublicKey(metadata.validatorVoteAccount));
|
|
55419
|
-
stakedBankAddresses.push(bank.address.toBase58());
|
|
55420
|
-
poolStakeAddresses.push(findPoolStakeAddress(pool));
|
|
55421
|
-
lstMintAddresses.push(findPoolMintAddress(pool));
|
|
55422
|
-
}
|
|
55423
|
-
if (stakedBankAddresses.length > 0) {
|
|
55424
|
-
const allAddresses = [
|
|
55425
|
-
...poolStakeAddresses.map((a) => a.toBase58()),
|
|
55426
|
-
...lstMintAddresses.map((a) => a.toBase58())
|
|
55427
|
-
];
|
|
55428
|
-
const accountInfos = await chunkedGetRawMultipleAccountInfoOrdered(
|
|
55429
|
-
connection,
|
|
55430
|
-
allAddresses
|
|
55431
|
-
);
|
|
55432
|
-
const poolStakeInfos = accountInfos.slice(0, poolStakeAddresses.length);
|
|
55433
|
-
const lstMintInfos = accountInfos.slice(poolStakeAddresses.length);
|
|
55434
|
-
for (let i = 0; i < stakedBankAddresses.length; i++) {
|
|
55435
|
-
const bankAddr = stakedBankAddresses[i];
|
|
55436
|
-
const poolStakeInfo = poolStakeInfos[i];
|
|
55437
|
-
const lstMintInfo = lstMintInfos[i];
|
|
55438
|
-
if (!poolStakeInfo || !lstMintInfo) {
|
|
55439
|
-
assetShareMultiplierByBank.set(bankAddr, new BigNumber3__default.default(1));
|
|
55440
|
-
continue;
|
|
55441
|
-
}
|
|
55442
|
-
const stakeLamports = poolStakeInfo.lamports;
|
|
55443
|
-
const supplyBuffer = lstMintInfo.data.slice(36, 44);
|
|
55444
|
-
const lstMintSupply = Number(Buffer.from(supplyBuffer).readBigUInt64LE(0));
|
|
55445
|
-
if (lstMintSupply === 0) {
|
|
55446
|
-
assetShareMultiplierByBank.set(bankAddr, new BigNumber3__default.default(1));
|
|
55447
|
-
continue;
|
|
55448
|
-
}
|
|
55449
|
-
const LAMPORTS_PER_SOL5 = 1e9;
|
|
55450
|
-
const adjustedStake = Math.max(stakeLamports - LAMPORTS_PER_SOL5, 0);
|
|
55451
|
-
const multiplier = new BigNumber3__default.default(adjustedStake).dividedBy(lstMintSupply);
|
|
55452
|
-
assetShareMultiplierByBank.set(bankAddr, multiplier);
|
|
55453
|
-
}
|
|
55454
|
-
}
|
|
55455
|
-
}
|
|
55399
|
+
const stakedMultipliers = await computeStakedBankMultipliers(
|
|
55400
|
+
banksArray.filter((b) => b.config.assetTag === 2 /* STAKED */),
|
|
55401
|
+
connection
|
|
55402
|
+
);
|
|
55403
|
+
stakedMultipliers.forEach((v, k) => assetShareMultiplierByBank.set(k, v));
|
|
55456
55404
|
const emodePairs = getEmodePairs(banksArray);
|
|
55457
55405
|
return new _Project0Client(
|
|
55458
55406
|
program,
|
|
@@ -55634,6 +55582,7 @@ exports.computeQuantity = computeQuantity;
|
|
|
55634
55582
|
exports.computeQuantityUi = computeQuantityUi;
|
|
55635
55583
|
exports.computeRemainingCapacity = computeRemainingCapacity;
|
|
55636
55584
|
exports.computeSmartCrank = computeSmartCrank;
|
|
55585
|
+
exports.computeStakedBankMultipliers = computeStakedBankMultipliers;
|
|
55637
55586
|
exports.computeTotalOutstandingEmissions = computeTotalOutstandingEmissions;
|
|
55638
55587
|
exports.computeTvl = computeTvl;
|
|
55639
55588
|
exports.computeUsdValue = computeUsdValue;
|