@0dotxyz/p0-ts-sdk 2.2.0-beta.3 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { PublicKey, SolanaJSONRPCError, ComputeBudgetProgram, SystemProgram, TransactionMessage, VersionedTransaction, Transaction, AddressLookupTableAccount, SYSVAR_RENT_PUBKEY, StakeProgram, TransactionInstruction, LAMPORTS_PER_SOL, SYSVAR_INSTRUCTIONS_PUBKEY } from '@solana/web3.js';
1
+ import { PublicKey, SolanaJSONRPCError, ComputeBudgetProgram, SystemProgram, TransactionMessage, VersionedTransaction, Transaction, AddressLookupTableAccount, SYSVAR_RENT_PUBKEY, StakeProgram, TransactionInstruction, LAMPORTS_PER_SOL, Keypair, StakeAuthorizationLayout, SYSVAR_INSTRUCTIONS_PUBKEY, STAKE_CONFIG_ID as STAKE_CONFIG_ID$1 } from '@solana/web3.js';
2
2
  import { object, string, enums, array, assert } from 'superstruct';
3
3
  import BigNumber3, { BigNumber } from 'bignumber.js';
4
- import BN11 from 'bn.js';
4
+ import BN11, { BN } from 'bn.js';
5
5
  import Decimal3, { Decimal } from 'decimal.js';
6
6
  import { BorshCoder, BorshAccountsCoder, BorshInstructionCoder, AnchorProvider, Program } from '@coral-xyz/anchor';
7
7
  import { struct, u32, u8 } from '@solana/buffer-layout';
@@ -91,10 +91,9 @@ function getConfig(environment = "production", overrides) {
91
91
 
92
92
  // src/errors/transaction-building.errors.ts
93
93
  var TransactionBuildingErrorCode = /* @__PURE__ */ ((TransactionBuildingErrorCode2) => {
94
- TransactionBuildingErrorCode2["JUPITER_SWAP_SIZE_EXCEEDED_REPAY"] = "JUPITER_SWAP_SIZE_EXCEEDED_REPAY";
95
- TransactionBuildingErrorCode2["JUPITER_SWAP_SIZE_EXCEEDED_LOOP"] = "JUPITER_SWAP_SIZE_EXCEEDED_LOOP";
96
94
  TransactionBuildingErrorCode2["SWAP_SIZE_EXCEEDED_LOOP"] = "SWAP_SIZE_EXCEEDED_LOOP";
97
95
  TransactionBuildingErrorCode2["SWAP_SIZE_EXCEEDED_REPAY"] = "SWAP_SIZE_EXCEEDED_REPAY";
96
+ TransactionBuildingErrorCode2["SWAP_SIZE_EXCEEDED_POSITION_SWAP"] = "SWAP_SIZE_EXCEEDED_POSITION_SWAP";
98
97
  TransactionBuildingErrorCode2["ORACLE_CRANK_FAILED"] = "ORACLE_CRANK_FAILED";
99
98
  TransactionBuildingErrorCode2["KAMINO_RESERVE_NOT_FOUND"] = "KAMINO_RESERVE_NOT_FOUND";
100
99
  TransactionBuildingErrorCode2["DRIFT_STATE_NOT_FOUND"] = "DRIFT_STATE_NOT_FOUND";
@@ -115,23 +114,6 @@ var TransactionBuildingError = class _TransactionBuildingError extends Error {
115
114
  Error.captureStackTrace(this, _TransactionBuildingError);
116
115
  }
117
116
  }
118
- /**
119
- * Jupiter swap instruction size exceeds available transaction size
120
- */
121
- static jupiterSwapSizeExceededLoop(bytes, accountKeys) {
122
- return new _TransactionBuildingError(
123
- "JUPITER_SWAP_SIZE_EXCEEDED_LOOP" /* JUPITER_SWAP_SIZE_EXCEEDED_LOOP */,
124
- "Jupiter swap instruction size exceeds available transaction size",
125
- { bytes, accountKeys }
126
- );
127
- }
128
- static jupiterSwapSizeExceededRepay(bytes, accountKeys) {
129
- return new _TransactionBuildingError(
130
- "JUPITER_SWAP_SIZE_EXCEEDED_REPAY" /* JUPITER_SWAP_SIZE_EXCEEDED_REPAY */,
131
- "Jupiter swap instruction size exceeds available transaction size",
132
- { bytes, accountKeys }
133
- );
134
- }
135
117
  static swapSizeExceededLoop(bytes, accountKeys, provider) {
136
118
  return new _TransactionBuildingError(
137
119
  "SWAP_SIZE_EXCEEDED_LOOP" /* SWAP_SIZE_EXCEEDED_LOOP */,
@@ -146,6 +128,13 @@ var TransactionBuildingError = class _TransactionBuildingError extends Error {
146
128
  { bytes, accountKeys, provider }
147
129
  );
148
130
  }
131
+ static swapSizeExceededPositionSwap(bytes, accountKeys, provider) {
132
+ return new _TransactionBuildingError(
133
+ "SWAP_SIZE_EXCEEDED_POSITION_SWAP" /* SWAP_SIZE_EXCEEDED_POSITION_SWAP */,
134
+ `${provider ?? "Swap"} instruction size exceeds available transaction size`,
135
+ { bytes, accountKeys, provider }
136
+ );
137
+ }
149
138
  /**
150
139
  * Failed to crank oracles for one or more banks
151
140
  */
@@ -15136,9 +15125,48 @@ var MintLayout = struct([
15136
15125
  publicKey("freezeAuthority")
15137
15126
  ]);
15138
15127
  MintLayout.span;
15128
+ var approveInstructionData = struct([
15129
+ u8("instruction"),
15130
+ u64("amount")
15131
+ ]);
15132
+ function createApproveInstruction(account, delegate, owner, amount, multiSigners = [], programId = TOKEN_PROGRAM_ID) {
15133
+ const keys = addSigners(
15134
+ [
15135
+ { pubkey: account, isSigner: false, isWritable: true },
15136
+ { pubkey: delegate, isSigner: false, isWritable: false }
15137
+ ],
15138
+ owner,
15139
+ multiSigners
15140
+ );
15141
+ const data = Buffer$1.alloc(approveInstructionData.span);
15142
+ approveInstructionData.encode(
15143
+ {
15144
+ instruction: 4 /* Approve */,
15145
+ amount: BigInt(amount)
15146
+ },
15147
+ data
15148
+ );
15149
+ return new TransactionInstruction({ keys, programId, data });
15150
+ }
15139
15151
  struct([
15140
15152
  u8("instruction")
15141
15153
  ]);
15154
+ function createAssociatedTokenAccountInstruction(payer, associatedToken, owner, mint, programId = TOKEN_PROGRAM_ID, associatedTokenProgramId = ASSOCIATED_TOKEN_PROGRAM_ID) {
15155
+ const keys = [
15156
+ { pubkey: payer, isSigner: true, isWritable: true },
15157
+ { pubkey: associatedToken, isSigner: false, isWritable: true },
15158
+ { pubkey: owner, isSigner: false, isWritable: false },
15159
+ { pubkey: mint, isSigner: false, isWritable: false },
15160
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
15161
+ { pubkey: programId, isSigner: false, isWritable: false },
15162
+ { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }
15163
+ ];
15164
+ return new TransactionInstruction({
15165
+ keys,
15166
+ programId: associatedTokenProgramId,
15167
+ data: Buffer$1.alloc(0)
15168
+ });
15169
+ }
15142
15170
  function createAssociatedTokenAccountIdempotentInstruction(payer, associatedToken, owner, mint, programId = TOKEN_PROGRAM_ID, associatedTokenProgramId = ASSOCIATED_TOKEN_PROGRAM_ID) {
15143
15171
  return buildAssociatedTokenAccountInstruction(
15144
15172
  payer,
@@ -43351,6 +43379,173 @@ new Fraction(new BN11(0));
43351
43379
  function roundNearest(decimal) {
43352
43380
  return decimal.toDecimalPlaces(0, Decimal3.ROUND_HALF_CEIL);
43353
43381
  }
43382
+ var SinglePoolInstruction = {
43383
+ initializePool: (voteAccount) => {
43384
+ const pool = findPoolAddress(voteAccount);
43385
+ const stake = findPoolStakeAddress(pool);
43386
+ const mint = findPoolMintAddress(pool);
43387
+ const stakeAuthority = findPoolStakeAuthorityAddress(pool);
43388
+ const mintAuthority = findPoolMintAuthorityAddress(pool);
43389
+ return createTransactionInstruction(
43390
+ SINGLE_POOL_PROGRAM_ID,
43391
+ [
43392
+ { pubkey: voteAccount, isSigner: false, isWritable: false },
43393
+ { pubkey: pool, isSigner: false, isWritable: true },
43394
+ { pubkey: stake, isSigner: false, isWritable: true },
43395
+ { pubkey: mint, isSigner: false, isWritable: true },
43396
+ { pubkey: stakeAuthority, isSigner: false, isWritable: false },
43397
+ { pubkey: mintAuthority, isSigner: false, isWritable: false },
43398
+ { pubkey: SYSVAR_RENT_ID, isSigner: false, isWritable: false },
43399
+ { pubkey: SYSVAR_CLOCK_ID, isSigner: false, isWritable: false },
43400
+ { pubkey: SYSVAR_STAKE_HISTORY_ID, isSigner: false, isWritable: false },
43401
+ { pubkey: STAKE_CONFIG_ID$1, isSigner: false, isWritable: false },
43402
+ { pubkey: SYSTEM_PROGRAM_ID, isSigner: false, isWritable: false },
43403
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
43404
+ { pubkey: STAKE_PROGRAM_ID, isSigner: false, isWritable: false }
43405
+ ],
43406
+ Buffer.from([0 /* InitializePool */])
43407
+ );
43408
+ },
43409
+ initializeOnRamp: (pool) => {
43410
+ const onRamp = findPoolOnRampAddress(pool);
43411
+ const stakeAuthority = findPoolStakeAuthorityAddress(pool);
43412
+ return createTransactionInstruction(
43413
+ SINGLE_POOL_PROGRAM_ID,
43414
+ [
43415
+ { pubkey: pool, isSigner: false, isWritable: false },
43416
+ { pubkey: onRamp, isSigner: false, isWritable: true },
43417
+ { pubkey: stakeAuthority, isSigner: false, isWritable: false },
43418
+ { pubkey: SYSVAR_RENT_ID, isSigner: false, isWritable: false },
43419
+ { pubkey: SYSTEM_PROGRAM_ID, isSigner: false, isWritable: false },
43420
+ { pubkey: STAKE_PROGRAM_ID, isSigner: false, isWritable: false }
43421
+ ],
43422
+ Buffer.from([6 /* InitializeOnRamp */])
43423
+ );
43424
+ },
43425
+ depositStake: async (pool, userStakeAccount, userTokenAccount, userLamportAccount) => {
43426
+ const stake = findPoolStakeAddress(pool);
43427
+ const onRamp = findPoolOnRampAddress(pool);
43428
+ const mint = findPoolMintAddress(pool);
43429
+ const stakeAuthority = findPoolStakeAuthorityAddress(pool);
43430
+ const mintAuthority = findPoolMintAuthorityAddress(pool);
43431
+ return createTransactionInstruction(
43432
+ SINGLE_POOL_PROGRAM_ID,
43433
+ [
43434
+ { pubkey: pool, isSigner: false, isWritable: false },
43435
+ { pubkey: stake, isSigner: false, isWritable: true },
43436
+ { pubkey: onRamp, isSigner: false, isWritable: false },
43437
+ { pubkey: mint, isSigner: false, isWritable: true },
43438
+ { pubkey: stakeAuthority, isSigner: false, isWritable: false },
43439
+ { pubkey: mintAuthority, isSigner: false, isWritable: false },
43440
+ { pubkey: userStakeAccount, isSigner: false, isWritable: true },
43441
+ { pubkey: userTokenAccount, isSigner: false, isWritable: true },
43442
+ { pubkey: userLamportAccount, isSigner: false, isWritable: true },
43443
+ { pubkey: SYSVAR_CLOCK_ID, isSigner: false, isWritable: false },
43444
+ { pubkey: SYSVAR_STAKE_HISTORY_ID, isSigner: false, isWritable: false },
43445
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
43446
+ { pubkey: STAKE_PROGRAM_ID, isSigner: false, isWritable: false }
43447
+ ],
43448
+ Buffer.from([2 /* DepositStake */])
43449
+ );
43450
+ },
43451
+ withdrawStake: async (pool, userStakeAccount, userStakeAuthority, userTokenAccount, tokenAmount) => {
43452
+ const stake = findPoolStakeAddress(pool);
43453
+ const onRamp = findPoolOnRampAddress(pool);
43454
+ const mint = findPoolMintAddress(pool);
43455
+ const stakeAuthority = findPoolStakeAuthorityAddress(pool);
43456
+ const mintAuthority = findPoolMintAuthorityAddress(pool);
43457
+ const rawAmount = BigInt(tokenAmount.multipliedBy(1e9).toString());
43458
+ const data = Buffer.concat([
43459
+ Buffer.from([3 /* WithdrawStake */]),
43460
+ userStakeAuthority.toBuffer(),
43461
+ Buffer.from(new BN(rawAmount.toString()).toArray("le", 8))
43462
+ ]);
43463
+ return createTransactionInstruction(
43464
+ SINGLE_POOL_PROGRAM_ID,
43465
+ [
43466
+ { pubkey: pool, isSigner: false, isWritable: false },
43467
+ { pubkey: stake, isSigner: false, isWritable: true },
43468
+ { pubkey: onRamp, isSigner: false, isWritable: false },
43469
+ { pubkey: mint, isSigner: false, isWritable: true },
43470
+ { pubkey: stakeAuthority, isSigner: false, isWritable: false },
43471
+ { pubkey: mintAuthority, isSigner: false, isWritable: false },
43472
+ { pubkey: userStakeAccount, isSigner: false, isWritable: true },
43473
+ { pubkey: userTokenAccount, isSigner: false, isWritable: true },
43474
+ { pubkey: SYSVAR_CLOCK_ID, isSigner: false, isWritable: false },
43475
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
43476
+ { pubkey: STAKE_PROGRAM_ID, isSigner: false, isWritable: false }
43477
+ ],
43478
+ data
43479
+ );
43480
+ },
43481
+ createTokenMetadata: async (pool, payer) => {
43482
+ const mint = findPoolMintAddress(pool);
43483
+ const [mintAuthority, mplAuthority, mplMetadata] = await Promise.all([
43484
+ findPoolMintAuthorityAddress(pool),
43485
+ findPoolMplAuthorityAddress(pool),
43486
+ findMplMetadataAddress(mint)
43487
+ ]);
43488
+ return createTransactionInstruction(
43489
+ SINGLE_POOL_PROGRAM_ID,
43490
+ [
43491
+ { pubkey: pool, isSigner: false, isWritable: false },
43492
+ { pubkey: mint, isSigner: false, isWritable: false },
43493
+ { pubkey: mintAuthority, isSigner: false, isWritable: false },
43494
+ { pubkey: mplAuthority, isSigner: false, isWritable: false },
43495
+ { pubkey: payer, isSigner: true, isWritable: true },
43496
+ { pubkey: mplMetadata, isSigner: false, isWritable: true },
43497
+ { pubkey: MPL_METADATA_PROGRAM_ID, isSigner: false, isWritable: false },
43498
+ { pubkey: SYSTEM_PROGRAM_ID, isSigner: false, isWritable: false }
43499
+ ],
43500
+ Buffer.from([4 /* CreateTokenMetadata */])
43501
+ );
43502
+ },
43503
+ updateTokenMetadata: async (voteAccount, authorizedWithdrawer, tokenName, tokenSymbol, tokenUri = "") => {
43504
+ if (tokenName.length > 32) {
43505
+ throw new Error("maximum token name length is 32 characters");
43506
+ }
43507
+ if (tokenSymbol.length > 10) {
43508
+ throw new Error("maximum token symbol length is 10 characters");
43509
+ }
43510
+ if (tokenUri.length > 200) {
43511
+ throw new Error("maximum token uri length is 200 characters");
43512
+ }
43513
+ const pool = findPoolAddress(voteAccount);
43514
+ const [mint, mplAuthority] = await Promise.all([
43515
+ findPoolMintAddress(pool),
43516
+ findPoolMplAuthorityAddress(pool)
43517
+ ]);
43518
+ const mplMetadata = await findMplMetadataAddress(mint);
43519
+ const data = Buffer.concat([
43520
+ Buffer.from([5 /* UpdateTokenMetadata */]),
43521
+ Buffer.from(new Uint32Array([tokenName.length]).buffer),
43522
+ Buffer.from(tokenName),
43523
+ Buffer.from(new Uint32Array([tokenSymbol.length]).buffer),
43524
+ Buffer.from(tokenSymbol),
43525
+ Buffer.from(new Uint32Array([tokenUri.length]).buffer),
43526
+ Buffer.from(tokenUri)
43527
+ ]);
43528
+ return createTransactionInstruction(
43529
+ SINGLE_POOL_PROGRAM_ID,
43530
+ [
43531
+ { pubkey: voteAccount, isSigner: false, isWritable: false },
43532
+ { pubkey: pool, isSigner: false, isWritable: false },
43533
+ { pubkey: mplAuthority, isSigner: false, isWritable: false },
43534
+ { pubkey: authorizedWithdrawer, isSigner: true, isWritable: false },
43535
+ { pubkey: mplMetadata, isSigner: false, isWritable: true },
43536
+ { pubkey: MPL_METADATA_PROGRAM_ID, isSigner: false, isWritable: false }
43537
+ ],
43538
+ data
43539
+ );
43540
+ }
43541
+ };
43542
+ var createTransactionInstruction = (programId, keys, data) => {
43543
+ return {
43544
+ programId,
43545
+ keys,
43546
+ data
43547
+ };
43548
+ };
43354
43549
  var findPda = (baseAddress, prefix, programId = SINGLE_POOL_PROGRAM_ID) => {
43355
43550
  const [pda] = PublicKey.findProgramAddressSync(
43356
43551
  [Buffer.from(prefix), baseAddress.toBuffer()],
@@ -43361,7 +43556,17 @@ var findPda = (baseAddress, prefix, programId = SINGLE_POOL_PROGRAM_ID) => {
43361
43556
  var findPoolAddress = (voteAccountAddress) => findPda(voteAccountAddress, "pool");
43362
43557
  var findPoolMintAddress = (poolAddress) => findPda(poolAddress, "mint");
43363
43558
  var findPoolStakeAddress = (poolAddress) => findPda(poolAddress, "stake");
43559
+ var findPoolStakeAuthorityAddress = (poolAddress) => findPda(poolAddress, "stake_authority");
43560
+ var findPoolMintAuthorityAddress = (poolAddress) => findPda(poolAddress, "mint_authority");
43561
+ var findPoolMplAuthorityAddress = (poolAddress) => findPda(poolAddress, "mpl_authority");
43364
43562
  var findPoolOnRampAddress = (poolAddress) => findPda(poolAddress, "onramp");
43563
+ var findMplMetadataAddress = async (poolMintAddress) => {
43564
+ const [pda] = PublicKey.findProgramAddressSync(
43565
+ [Buffer.from("metadata"), MPL_METADATA_PROGRAM_ID.toBuffer(), poolMintAddress.toBuffer()],
43566
+ MPL_METADATA_PROGRAM_ID
43567
+ );
43568
+ return pda;
43569
+ };
43365
43570
  BigInt(33);
43366
43571
  BigInt(200);
43367
43572
  BigInt(82);
@@ -44142,12 +44347,28 @@ var V1Client = class _V1Client {
44142
44347
  return new Promise((resolve, reject) => {
44143
44348
  const ws = new WebSocket(url, [SUBPROTOCOL]);
44144
44349
  ws.binaryType = "arraybuffer";
44145
- ws.on("open", () => {
44350
+ const onOpen = () => {
44351
+ ws.off("error", onError);
44352
+ ws.off("close", onClose);
44146
44353
  resolve(new _V1Client(ws));
44147
- });
44148
- ws.on("error", (err) => {
44354
+ };
44355
+ const onError = (err) => {
44356
+ ws.off("open", onOpen);
44357
+ ws.off("close", onClose);
44149
44358
  reject(err);
44150
- });
44359
+ };
44360
+ const onClose = (code, reason) => {
44361
+ ws.off("open", onOpen);
44362
+ ws.off("error", onError);
44363
+ reject(
44364
+ new Error(
44365
+ `WebSocket closed before open (code=${code}${reason.length ? `, reason=${reason.toString()}` : ""})`
44366
+ )
44367
+ );
44368
+ };
44369
+ ws.once("open", onOpen);
44370
+ ws.once("error", onError);
44371
+ ws.once("close", onClose);
44151
44372
  });
44152
44373
  }
44153
44374
  // --- Constructor ---
@@ -46148,10 +46369,11 @@ async function makeBorrowIx3({
46148
46369
  );
46149
46370
  borrowIxs.push(createAtaIdempotentIx);
46150
46371
  }
46372
+ const mandatoryBanks = [bank.address, ...opts.additionalHealthCheckBanks ?? []];
46151
46373
  const healthAccounts = computeHealthCheckAccounts(
46152
46374
  marginfiAccount.balances,
46153
46375
  bankMap,
46154
- [bank.address],
46376
+ mandatoryBanks,
46155
46377
  []
46156
46378
  );
46157
46379
  const remainingAccounts = [];
@@ -46686,81 +46908,116 @@ async function makeJuplendDepositTx(params) {
46686
46908
  });
46687
46909
  return solanaTx;
46688
46910
  }
46689
- async function makeRepayIx3({
46690
- program,
46691
- bank,
46692
- tokenProgram,
46693
- amount,
46694
- authority,
46695
- accountAddress,
46696
- repayAll = false,
46697
- isSync = false,
46698
- opts = {}
46699
- }) {
46700
- const wrapAndUnwrapSol = opts.wrapAndUnwrapSol ?? true;
46701
- const wSolBalanceUi = opts.wSolBalanceUi ?? 0;
46702
- const repayIxs = [];
46703
- const userAta = getAssociatedTokenAddressSync(bank.mint, authority, true, tokenProgram);
46704
- const remainingAccounts = tokenProgram.equals(TOKEN_2022_PROGRAM_ID) ? [{ pubkey: bank.mint, isSigner: false, isWritable: false }] : [];
46705
- if (bank.mint.equals(NATIVE_MINT) && wrapAndUnwrapSol) {
46706
- repayIxs.push(...makeWrapSolIxs(authority, new BigNumber(amount).minus(wSolBalanceUi)));
46707
- }
46708
- const repayIx = !isSync || !opts.overrideInferAccounts?.group ? await instructions_default.makeRepayIx(
46911
+ async function makeBeginFlashLoanIx3(program, marginfiAccountPk, endIndex, authority, isSync) {
46912
+ const ix = isSync && authority ? sync_instructions_default.makeBeginFlashLoanIx(
46913
+ program.programId,
46914
+ {
46915
+ marginfiAccount: marginfiAccountPk,
46916
+ authority
46917
+ },
46918
+ { endIndex: new BN11(endIndex) }
46919
+ ) : await instructions_default.makeBeginFlashLoanIx(
46709
46920
  program,
46710
46921
  {
46711
- marginfiAccount: accountAddress,
46712
- signerTokenAccount: userAta,
46713
- bank: bank.address,
46714
- tokenProgram,
46715
- authority: opts.overrideInferAccounts?.authority ?? authority,
46716
- group: opts.overrideInferAccounts?.group,
46717
- liquidityVault: opts.overrideInferAccounts?.liquidityVault
46922
+ marginfiAccount: marginfiAccountPk,
46923
+ authority
46718
46924
  },
46719
- { amount: uiToNative(amount, bank.mintDecimals), repayAll },
46720
- remainingAccounts
46721
- ) : sync_instructions_default.makeRepayIx(
46925
+ { endIndex: new BN11(endIndex) }
46926
+ );
46927
+ return { instructions: [ix], keys: [] };
46928
+ }
46929
+ async function makeEndFlashLoanIx3(program, marginfiAccountPk, projectedActiveBanks, authority, isSync) {
46930
+ const remainingAccounts = computeHealthAccountMetas(projectedActiveBanks);
46931
+ const ix = isSync && authority ? sync_instructions_default.makeEndFlashLoanIx(
46722
46932
  program.programId,
46723
46933
  {
46724
- marginfiAccount: accountAddress,
46725
- signerTokenAccount: userAta,
46726
- bank: bank.address,
46727
- tokenProgram,
46728
- authority: opts.overrideInferAccounts?.authority ?? authority,
46729
- group: opts.overrideInferAccounts?.group
46934
+ marginfiAccount: marginfiAccountPk,
46935
+ authority
46730
46936
  },
46731
- { amount: uiToNative(amount, bank.mintDecimals), repayAll },
46732
- remainingAccounts
46937
+ remainingAccounts.map((account) => ({
46938
+ pubkey: account,
46939
+ isSigner: false,
46940
+ isWritable: false
46941
+ }))
46942
+ ) : await instructions_default.makeEndFlashLoanIx(
46943
+ program,
46944
+ {
46945
+ marginfiAccount: marginfiAccountPk,
46946
+ authority
46947
+ },
46948
+ remainingAccounts.map((account) => ({
46949
+ pubkey: account,
46950
+ isSigner: false,
46951
+ isWritable: false
46952
+ }))
46733
46953
  );
46734
- repayIxs.push(repayIx);
46735
- return {
46736
- instructions: repayIxs,
46737
- keys: []
46738
- };
46954
+ return { instructions: [ix], keys: [] };
46739
46955
  }
46740
- async function makeRepayTx(params) {
46741
- const { luts, ...depositIxParams } = params;
46742
- const ixs = await makeRepayIx3(depositIxParams);
46743
- const tx = new Transaction().add(...ixs.instructions);
46744
- tx.feePayer = params.authority;
46745
- const solanaTx = addTransactionMetadata(tx, {
46746
- type: "REPAY" /* REPAY */,
46747
- signers: ixs.keys,
46748
- addressLookupTables: luts
46956
+ async function makeFlashLoanTx({
46957
+ program,
46958
+ marginfiAccount,
46959
+ ixs,
46960
+ bankMap,
46961
+ blockhash,
46962
+ addressLookupTableAccounts,
46963
+ signers,
46964
+ isSync
46965
+ }) {
46966
+ const endIndex = ixs.length + 1;
46967
+ const projectedActiveBanksKeys = computeProjectedActiveBanksNoCpi(
46968
+ marginfiAccount.balances,
46969
+ ixs,
46970
+ program
46971
+ );
46972
+ const projectedActiveBanks = projectedActiveBanksKeys.map((account) => {
46973
+ const b = bankMap.get(account.toBase58());
46974
+ if (!b) throw Error(`Bank ${account.toBase58()} not found, in makeFlashLoanTx function`);
46975
+ return b;
46749
46976
  });
46750
- return solanaTx;
46977
+ const beginFlashLoanIx = await makeBeginFlashLoanIx3(
46978
+ program,
46979
+ marginfiAccount.address,
46980
+ endIndex,
46981
+ marginfiAccount.authority,
46982
+ isSync
46983
+ );
46984
+ const endFlashLoanIx = await makeEndFlashLoanIx3(
46985
+ program,
46986
+ marginfiAccount.address,
46987
+ projectedActiveBanks,
46988
+ marginfiAccount.authority,
46989
+ isSync
46990
+ );
46991
+ const message = new TransactionMessage({
46992
+ payerKey: marginfiAccount.authority,
46993
+ recentBlockhash: blockhash,
46994
+ instructions: [...beginFlashLoanIx.instructions, ...ixs, ...endFlashLoanIx.instructions]
46995
+ }).compileToV0Message(addressLookupTableAccounts);
46996
+ const tx = addTransactionMetadata(new VersionedTransaction(message), {
46997
+ addressLookupTables: addressLookupTableAccounts,
46998
+ type: "FLASHLOAN" /* FLASHLOAN */,
46999
+ signers
47000
+ });
47001
+ if (signers) {
47002
+ tx.sign(signers);
47003
+ }
47004
+ return tx;
46751
47005
  }
46752
- async function makeRepayWithCollatTx(params) {
47006
+
47007
+ // src/services/account/actions/loop.ts
47008
+ async function makeLoopTx(params) {
46753
47009
  const {
46754
47010
  program,
46755
47011
  marginfiAccount,
46756
47012
  bankMap,
46757
- withdrawOpts,
46758
- repayOpts,
47013
+ depositOpts,
47014
+ borrowOpts,
46759
47015
  bankMetadataMap,
46760
47016
  addressLookupTableAccounts,
46761
47017
  connection,
46762
47018
  oraclePrices,
46763
- crossbarUrl
47019
+ crossbarUrl,
47020
+ additionalIxs = []
46764
47021
  } = params;
46765
47022
  const blockhash = (await connection.getLatestBlockhash("confirmed")).blockhash;
46766
47023
  const setupIxs = await makeSetupIx({
@@ -46768,34 +47025,34 @@ async function makeRepayWithCollatTx(params) {
46768
47025
  authority: marginfiAccount.authority,
46769
47026
  tokens: [
46770
47027
  {
46771
- mint: repayOpts.repayBank.mint,
46772
- tokenProgram: repayOpts.tokenProgram
47028
+ mint: borrowOpts.borrowBank.mint,
47029
+ tokenProgram: borrowOpts.tokenProgram
46773
47030
  },
46774
47031
  {
46775
- mint: withdrawOpts.withdrawBank.mint,
46776
- tokenProgram: withdrawOpts.tokenProgram
47032
+ mint: depositOpts.depositBank.mint,
47033
+ tokenProgram: depositOpts.tokenProgram
46777
47034
  }
46778
47035
  ]
46779
47036
  });
46780
- const updateJuplendMarketIxs = makeUpdateJupLendRateIxs(
46781
- marginfiAccount,
46782
- bankMap,
46783
- [withdrawOpts.withdrawBank.address],
46784
- bankMetadataMap
47037
+ const updateJupLendRateIxs = makeUpdateJupLendRateIxs(
47038
+ params.marginfiAccount,
47039
+ params.bankMap,
47040
+ [depositOpts.depositBank.address],
47041
+ params.bankMetadataMap
46785
47042
  );
46786
47043
  const updateDriftMarketIxs = makeUpdateDriftMarketIxs(
46787
- marginfiAccount,
46788
- bankMap,
46789
- [withdrawOpts.withdrawBank.address],
46790
- bankMetadataMap
47044
+ params.marginfiAccount,
47045
+ params.bankMap,
47046
+ [depositOpts.depositBank.address],
47047
+ params.bankMetadataMap
46791
47048
  );
46792
47049
  const kaminoRefreshIxs = makeRefreshKaminoBanksIxs(
46793
47050
  marginfiAccount,
46794
47051
  bankMap,
46795
- [withdrawOpts.withdrawBank.address, repayOpts.repayBank.address],
47052
+ [borrowOpts.borrowBank.address, depositOpts.depositBank.address],
46796
47053
  bankMetadataMap
46797
47054
  );
46798
- const { flashloanTx, setupInstructions, swapQuote, amountToRepay, withdrawIxs, repayIxs } = await buildRepayWithCollatFlashloanTx({
47055
+ const { flashloanTx, setupInstructions, swapQuote, amountToDeposit, depositIxs, borrowIxs } = await buildLoopFlashloanTx({
46799
47056
  ...params,
46800
47057
  blockhash
46801
47058
  });
@@ -46805,7 +47062,7 @@ async function makeRepayWithCollatTx(params) {
46805
47062
  }
46806
47063
  if (ix.programId.equals(ASSOCIATED_TOKEN_PROGRAM_ID)) {
46807
47064
  const mintKey = ix.keys[3]?.pubkey;
46808
- if (mintKey?.equals(withdrawOpts.withdrawBank.mint) || mintKey?.equals(repayOpts.repayBank.mint)) {
47065
+ if (mintKey?.equals(depositOpts.depositBank.mint) || mintKey?.equals(borrowOpts.borrowBank.mint)) {
46809
47066
  return false;
46810
47067
  }
46811
47068
  }
@@ -46817,18 +47074,24 @@ async function makeRepayWithCollatTx(params) {
46817
47074
  bankMap,
46818
47075
  oraclePrices,
46819
47076
  assetShareValueMultiplierByBank: params.assetShareValueMultiplierByBank,
46820
- instructions: [...withdrawIxs.instructions, ...repayIxs.instructions],
47077
+ instructions: [...borrowIxs.instructions, ...depositIxs.instructions],
46821
47078
  program,
46822
47079
  connection,
46823
47080
  crossbarUrl
46824
47081
  });
46825
47082
  let additionalTxs = [];
46826
- if (setupIxs.length > 0 || kaminoRefreshIxs.instructions.length > 0 || updateDriftMarketIxs.instructions.length > 0 || updateJuplendMarketIxs.instructions.length > 0) {
47083
+ if (depositOpts.depositBank.mint.equals(NATIVE_MINT) && depositOpts.inputDepositAmount) {
47084
+ setupIxs.push(
47085
+ ...makeWrapSolIxs(marginfiAccount.authority, new BigNumber(depositOpts.inputDepositAmount))
47086
+ );
47087
+ }
47088
+ if (setupIxs.length > 0 || additionalIxs.length > 0 || kaminoRefreshIxs.instructions.length > 0 || updateDriftMarketIxs.instructions.length > 0 || updateJupLendRateIxs.instructions.length > 0) {
46827
47089
  const ixs = [
47090
+ ...additionalIxs,
46828
47091
  ...setupIxs,
46829
47092
  ...kaminoRefreshIxs.instructions,
46830
47093
  ...updateDriftMarketIxs.instructions,
46831
- ...updateJuplendMarketIxs.instructions
47094
+ ...updateJupLendRateIxs.instructions
46832
47095
  ];
46833
47096
  const txs = splitInstructionsToFitTransactions([], ixs, {
46834
47097
  blockhash,
@@ -46858,16 +47121,19 @@ async function makeRepayWithCollatTx(params) {
46858
47121
  );
46859
47122
  }
46860
47123
  const transactions = [...additionalTxs, flashloanTx];
46861
- return { transactions, swapQuote, amountToRepay };
47124
+ return {
47125
+ transactions,
47126
+ actionTxIndex: transactions.length - 1,
47127
+ quoteResponse: swapQuote
47128
+ };
46862
47129
  }
46863
- async function buildRepayWithCollatFlashloanTx({
47130
+ async function buildLoopFlashloanTx({
46864
47131
  program,
46865
47132
  marginfiAccount,
46866
47133
  bankMap,
46867
- withdrawOpts,
46868
- repayOpts,
47134
+ borrowOpts,
47135
+ depositOpts,
46869
47136
  bankMetadataMap,
46870
- assetShareValueMultiplierByBank,
46871
47137
  addressLookupTableAccounts,
46872
47138
  connection,
46873
47139
  swapOpts,
@@ -46878,20 +47144,20 @@ async function buildRepayWithCollatFlashloanTx({
46878
47144
  ComputeBudgetProgram.setComputeUnitLimit({ units: 12e5 }),
46879
47145
  ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 })
46880
47146
  ];
46881
- let amountToRepay;
47147
+ let amountToDeposit;
46882
47148
  let swapInstructions = [];
46883
47149
  let setupInstructions = [];
46884
47150
  let swapLookupTables = [];
46885
47151
  let swapQuote;
46886
47152
  let sizeConstraintUsed = 0;
46887
- if (repayOpts.repayBank.mint.equals(withdrawOpts.withdrawBank.mint)) {
46888
- amountToRepay = withdrawOpts.withdrawAmount;
47153
+ if (depositOpts.depositBank.mint.equals(borrowOpts.borrowBank.mint)) {
47154
+ amountToDeposit = borrowOpts.borrowAmount + (depositOpts.loopMode === "DEPOSIT" ? depositOpts.inputDepositAmount : 0);
46889
47155
  } else {
46890
47156
  const destinationTokenAccount = getAssociatedTokenAddressSync(
46891
- new PublicKey(repayOpts.repayBank.mint),
47157
+ new PublicKey(depositOpts.depositBank.mint),
46892
47158
  marginfiAccount.authority,
46893
47159
  true,
46894
- repayOpts.tokenProgram.equals(TOKEN_2022_PROGRAM_ID) ? TOKEN_2022_PROGRAM_ID : void 0
47160
+ depositOpts.tokenProgram.equals(TOKEN_2022_PROGRAM_ID) ? TOKEN_2022_PROGRAM_ID : void 0
46895
47161
  );
46896
47162
  const swapConstraints = await computeFlashloanSwapConstraints({
46897
47163
  program,
@@ -46900,24 +47166,21 @@ async function buildRepayWithCollatFlashloanTx({
46900
47166
  bankMetadataMap,
46901
47167
  addressLookupTableAccounts: addressLookupTableAccounts ?? [],
46902
47168
  primaryIx: {
46903
- type: "withdraw",
46904
- bank: withdrawOpts.withdrawBank,
46905
- tokenProgram: withdrawOpts.tokenProgram
47169
+ type: "borrow",
47170
+ bank: borrowOpts.borrowBank,
47171
+ tokenProgram: borrowOpts.tokenProgram
46906
47172
  },
46907
47173
  secondaryIx: {
46908
- type: "repay",
46909
- bank: repayOpts.repayBank,
46910
- tokenProgram: repayOpts.tokenProgram
47174
+ type: "deposit",
47175
+ bank: depositOpts.depositBank,
47176
+ tokenProgram: depositOpts.tokenProgram
46911
47177
  },
46912
47178
  overrideInferAccounts
46913
47179
  });
46914
47180
  const swapResponse = await getSwapIxsForFlashloan({
46915
- inputMint: withdrawOpts.withdrawBank.mint.toBase58(),
46916
- outputMint: repayOpts.repayBank.mint.toBase58(),
46917
- amount: uiToNative(
46918
- withdrawOpts.withdrawAmount,
46919
- withdrawOpts.withdrawBank.mintDecimals
46920
- ).toNumber(),
47181
+ inputMint: borrowOpts.borrowBank.mint.toBase58(),
47182
+ outputMint: depositOpts.depositBank.mint.toBase58(),
47183
+ amount: uiToNative(borrowOpts.borrowAmount, borrowOpts.borrowBank.mintDecimals).toNumber(),
46921
47184
  swapMode: "ExactIn",
46922
47185
  authority: marginfiAccount.authority,
46923
47186
  connection,
@@ -46927,50 +47190,52 @@ async function buildRepayWithCollatFlashloanTx({
46927
47190
  maxSwapTotalAccounts: swapConstraints.maxSwapTotalAccounts
46928
47191
  });
46929
47192
  sizeConstraintUsed = swapConstraints.sizeConstraint;
46930
- const { quoteResponse } = swapResponse;
46931
- const outAmount = nativeToUi(quoteResponse.outAmount, repayOpts.repayBank.mintDecimals);
46932
47193
  const outAmountThreshold = nativeToUi(
46933
- quoteResponse.otherAmountThreshold,
46934
- repayOpts.repayBank.mintDecimals
47194
+ swapResponse.quoteResponse.otherAmountThreshold,
47195
+ depositOpts.depositBank.mintDecimals
46935
47196
  );
46936
- amountToRepay = outAmount > repayOpts.totalPositionAmount ? repayOpts.totalPositionAmount : outAmountThreshold;
47197
+ amountToDeposit = outAmountThreshold + (depositOpts.loopMode === "DEPOSIT" ? depositOpts.inputDepositAmount : 0);
46937
47198
  swapInstructions = swapResponse.swapInstructions;
47199
+ setupInstructions = swapResponse.setupInstructions;
46938
47200
  swapLookupTables = swapResponse.addressLookupTableAddresses;
46939
- swapQuote = quoteResponse;
47201
+ swapQuote = swapResponse.quoteResponse;
46940
47202
  }
46941
- let withdrawIxs;
46942
- switch (withdrawOpts.withdrawBank.config.assetTag) {
47203
+ const borrowIxs = await makeBorrowIx3({
47204
+ program,
47205
+ bank: borrowOpts.borrowBank,
47206
+ bankMap,
47207
+ tokenProgram: borrowOpts.tokenProgram,
47208
+ amount: borrowOpts.borrowAmount,
47209
+ marginfiAccount,
47210
+ authority: marginfiAccount.authority,
47211
+ isSync: false,
47212
+ opts: {
47213
+ createAtas: false,
47214
+ wrapAndUnwrapSol: false,
47215
+ overrideInferAccounts
47216
+ }
47217
+ });
47218
+ let depositIxs;
47219
+ switch (depositOpts.depositBank.config.assetTag) {
46943
47220
  case 3 /* KAMINO */: {
46944
- const reserve = bankMetadataMap[withdrawOpts.withdrawBank.address.toBase58()]?.kaminoStates?.reserveState;
47221
+ const reserve = bankMetadataMap[depositOpts.depositBank.address.toBase58()]?.kaminoStates?.reserveState;
46945
47222
  if (!reserve) {
46946
47223
  throw TransactionBuildingError.kaminoReserveNotFound(
46947
- withdrawOpts.withdrawBank.address.toBase58(),
46948
- withdrawOpts.withdrawBank.mint.toBase58(),
46949
- withdrawOpts.withdrawBank.tokenSymbol
47224
+ depositOpts.depositBank.address.toBase58(),
47225
+ depositOpts.depositBank.mint.toBase58(),
47226
+ depositOpts.depositBank.tokenSymbol
46950
47227
  );
46951
47228
  }
46952
- const multiplier = assetShareValueMultiplierByBank.get(withdrawOpts.withdrawBank.address.toBase58()) ?? new BigNumber(1);
46953
- const adjustedAmount = new BigNumber(withdrawOpts.withdrawAmount).div(multiplier).times(1.0001).toNumber();
46954
- withdrawIxs = await makeKaminoWithdrawIx3({
47229
+ depositIxs = await makeKaminoDepositIx3({
46955
47230
  program,
46956
- bank: withdrawOpts.withdrawBank,
46957
- bankMap,
46958
- tokenProgram: withdrawOpts.tokenProgram,
46959
- cTokenAmount: adjustedAmount,
46960
- marginfiAccount,
47231
+ bank: depositOpts.depositBank,
47232
+ tokenProgram: depositOpts.tokenProgram,
47233
+ amount: amountToDeposit,
47234
+ accountAddress: marginfiAccount.address,
46961
47235
  authority: marginfiAccount.authority,
47236
+ group: marginfiAccount.group,
46962
47237
  reserve,
46963
- withdrawAll: isWholePosition(
46964
- {
46965
- amount: withdrawOpts.totalPositionAmount,
46966
- isLending: true
46967
- },
46968
- withdrawOpts.withdrawAmount,
46969
- withdrawOpts.withdrawBank.mintDecimals
46970
- ),
46971
- isSync: false,
46972
47238
  opts: {
46973
- createAtas: false,
46974
47239
  wrapAndUnwrapSol: false,
46975
47240
  overrideInferAccounts
46976
47241
  }
@@ -46978,35 +47243,27 @@ async function buildRepayWithCollatFlashloanTx({
46978
47243
  break;
46979
47244
  }
46980
47245
  case 4 /* DRIFT */: {
46981
- const driftState = bankMetadataMap[withdrawOpts.withdrawBank.address.toBase58()]?.driftStates;
47246
+ const driftState = bankMetadataMap[depositOpts.depositBank.address.toBase58()]?.driftStates;
46982
47247
  if (!driftState) {
46983
47248
  throw TransactionBuildingError.driftStateNotFound(
46984
- withdrawOpts.withdrawBank.address.toBase58(),
46985
- withdrawOpts.withdrawBank.mint.toBase58(),
46986
- withdrawOpts.withdrawBank.tokenSymbol
47249
+ depositOpts.depositBank.address.toBase58(),
47250
+ depositOpts.depositBank.mint.toBase58(),
47251
+ depositOpts.depositBank.tokenSymbol
46987
47252
  );
46988
47253
  }
46989
- withdrawIxs = await makeDriftWithdrawIx3({
47254
+ const driftMarketIndex = driftState.spotMarketState.marketIndex;
47255
+ const driftOracle = driftState.spotMarketState.oracle;
47256
+ depositIxs = await makeDriftDepositIx3({
46990
47257
  program,
46991
- bank: withdrawOpts.withdrawBank,
46992
- bankMap,
46993
- tokenProgram: withdrawOpts.tokenProgram,
46994
- amount: withdrawOpts.withdrawAmount,
46995
- marginfiAccount,
47258
+ bank: depositOpts.depositBank,
47259
+ tokenProgram: depositOpts.tokenProgram,
47260
+ amount: amountToDeposit,
47261
+ accountAddress: marginfiAccount.address,
46996
47262
  authority: marginfiAccount.authority,
46997
- driftSpotMarket: driftState.spotMarketState,
46998
- userRewards: driftState.userRewards,
46999
- withdrawAll: isWholePosition(
47000
- {
47001
- amount: withdrawOpts.totalPositionAmount,
47002
- isLending: true
47003
- },
47004
- withdrawOpts.withdrawAmount,
47005
- withdrawOpts.withdrawBank.mintDecimals
47006
- ),
47007
- isSync: false,
47263
+ group: marginfiAccount.group,
47264
+ driftMarketIndex,
47265
+ driftOracle,
47008
47266
  opts: {
47009
- createAtas: false,
47010
47267
  wrapAndUnwrapSol: false,
47011
47268
  overrideInferAccounts
47012
47269
  }
@@ -47014,679 +47271,156 @@ async function buildRepayWithCollatFlashloanTx({
47014
47271
  break;
47015
47272
  }
47016
47273
  case 6 /* JUPLEND */: {
47017
- const jupLendState = bankMetadataMap[withdrawOpts.withdrawBank.address.toBase58()]?.jupLendStates;
47018
- if (!jupLendState) {
47019
- throw TransactionBuildingError.jupLendStateNotFound(
47020
- withdrawOpts.withdrawBank.address.toBase58(),
47021
- withdrawOpts.withdrawBank.mint.toBase58(),
47022
- withdrawOpts.withdrawBank.tokenSymbol
47023
- );
47024
- }
47025
- withdrawIxs = await makeJuplendWithdrawIx2({
47026
- program,
47027
- bank: withdrawOpts.withdrawBank,
47028
- bankMap,
47029
- tokenProgram: withdrawOpts.tokenProgram,
47030
- amount: withdrawOpts.withdrawAmount,
47031
- marginfiAccount,
47032
- authority: marginfiAccount.authority,
47033
- jupLendingState: jupLendState.jupLendingState,
47034
- withdrawAll: isWholePosition(
47035
- {
47036
- amount: withdrawOpts.totalPositionAmount,
47037
- isLending: true
47038
- },
47039
- withdrawOpts.withdrawAmount,
47040
- withdrawOpts.withdrawBank.mintDecimals
47041
- ),
47042
- opts: {
47043
- createAtas: false,
47044
- wrapAndUnwrapSol: false,
47045
- overrideInferAccounts
47046
- }
47047
- });
47048
- break;
47049
- }
47050
- default: {
47051
- withdrawIxs = await makeWithdrawIx3({
47274
+ depositIxs = await makeJuplendDepositIx2({
47052
47275
  program,
47053
- bank: withdrawOpts.withdrawBank,
47054
- bankMap,
47055
- tokenProgram: withdrawOpts.tokenProgram,
47056
- amount: withdrawOpts.withdrawAmount,
47057
- marginfiAccount,
47276
+ bank: depositOpts.depositBank,
47277
+ tokenProgram: depositOpts.tokenProgram,
47278
+ amount: amountToDeposit,
47279
+ accountAddress: marginfiAccount.address,
47058
47280
  authority: marginfiAccount.authority,
47059
- withdrawAll: isWholePosition(
47060
- {
47061
- amount: withdrawOpts.totalPositionAmount,
47062
- isLending: true
47063
- },
47064
- withdrawOpts.withdrawAmount,
47065
- withdrawOpts.withdrawBank.mintDecimals
47066
- ),
47067
- isSync: false,
47281
+ group: marginfiAccount.group,
47068
47282
  opts: {
47069
- createAtas: false,
47070
47283
  wrapAndUnwrapSol: false,
47071
47284
  overrideInferAccounts
47072
47285
  }
47073
47286
  });
47074
47287
  break;
47075
47288
  }
47076
- }
47077
- const repayIxs = await makeRepayIx3({
47078
- program,
47079
- bank: repayOpts.repayBank,
47080
- tokenProgram: repayOpts.tokenProgram,
47081
- amount: amountToRepay,
47082
- accountAddress: marginfiAccount.address,
47083
- authority: marginfiAccount.authority,
47084
- repayAll: isWholePosition(
47085
- {
47086
- amount: repayOpts.totalPositionAmount,
47087
- isLending: true
47088
- },
47089
- amountToRepay,
47090
- repayOpts.repayBank.mintDecimals
47091
- ),
47092
- isSync: false,
47093
- opts: {
47094
- wrapAndUnwrapSol: false,
47095
- overrideInferAccounts
47096
- }
47097
- });
47098
- const luts = [...addressLookupTableAccounts ?? [], ...swapLookupTables];
47099
- const allNonFlIxs = [
47100
- ...cuRequestIxs,
47101
- ...withdrawIxs.instructions,
47102
- ...swapInstructions,
47103
- ...repayIxs.instructions
47104
- ];
47105
- if (swapInstructions.length > 0) {
47106
- compileFlashloanPrecheck({
47107
- allIxs: allNonFlIxs,
47108
- payer: marginfiAccount.authority,
47109
- luts,
47110
- sizeConstraint: sizeConstraintUsed,
47111
- swapIxCount: swapInstructions.length,
47112
- swapLutCount: swapLookupTables.length
47113
- });
47114
- }
47115
- const flashloanTx = await makeFlashLoanTx({
47116
- program,
47117
- marginfiAccount,
47118
- bankMap,
47119
- addressLookupTableAccounts: luts,
47120
- blockhash,
47121
- ixs: allNonFlIxs,
47122
- isSync: true
47123
- });
47124
- const txSize = getTxSize(flashloanTx);
47125
- const totalKeys = getTotalAccountKeys(flashloanTx);
47126
- if (txSize > MAX_TX_SIZE || totalKeys > MAX_ACCOUNT_LOCKS) {
47127
- throw TransactionBuildingError.swapSizeExceededRepay(
47128
- txSize,
47129
- totalKeys,
47130
- swapOpts.swapConfig?.provider
47131
- );
47132
- }
47133
- return {
47134
- flashloanTx,
47135
- setupInstructions,
47136
- swapQuote,
47137
- withdrawIxs,
47138
- repayIxs,
47139
- amountToRepay
47140
- };
47141
- }
47142
-
47143
- // src/services/account/utils/flashloan-size.utils.ts
47144
- var SWAP_MERGE_OVERHEAD = 150;
47145
- var FL_IX_OVERHEAD = 52;
47146
- function compactU16Size(n) {
47147
- return n < 128 ? 1 : n < 16384 ? 2 : 3;
47148
- }
47149
- function computeV0TxSize(ixs, payerKey, luts) {
47150
- const keyMap = /* @__PURE__ */ new Map();
47151
- const payerStr = payerKey.toBase58();
47152
- keyMap.set(payerStr, { isSigner: true, isWritable: true });
47153
- const programIds = /* @__PURE__ */ new Set();
47154
- for (const ix of ixs) {
47155
- const progStr = ix.programId.toBase58();
47156
- programIds.add(progStr);
47157
- if (!keyMap.has(progStr)) {
47158
- keyMap.set(progStr, { isSigner: false, isWritable: false });
47159
- }
47160
- for (const meta of ix.keys) {
47161
- const keyStr = meta.pubkey.toBase58();
47162
- const existing = keyMap.get(keyStr);
47163
- if (existing) {
47164
- existing.isSigner = existing.isSigner || meta.isSigner;
47165
- existing.isWritable = existing.isWritable || meta.isWritable;
47166
- } else {
47167
- keyMap.set(keyStr, { isSigner: meta.isSigner, isWritable: meta.isWritable });
47168
- }
47169
- }
47170
- }
47171
- const lutLookup = /* @__PURE__ */ new Map();
47172
- for (let li = 0; li < luts.length; li++) {
47173
- const addresses = luts[li].state.addresses;
47174
- for (let ai = 0; ai < addresses.length; ai++) {
47175
- const addrStr = addresses[ai].toBase58();
47176
- if (!lutLookup.has(addrStr)) {
47177
- lutLookup.set(addrStr, { lutIdx: li, addrIdx: ai });
47178
- }
47179
- }
47180
- }
47181
- let numStaticKeys = 0;
47182
- let numWritableStaticKeys = 0;
47183
- const lutWritableIdxs = luts.map(() => /* @__PURE__ */ new Set());
47184
- const lutReadonlyIdxs = luts.map(() => /* @__PURE__ */ new Set());
47185
- for (const [keyStr, props] of keyMap) {
47186
- if (props.isSigner || programIds.has(keyStr)) {
47187
- numStaticKeys++;
47188
- if (props.isWritable) numWritableStaticKeys++;
47189
- continue;
47190
- }
47191
- const lutEntry = lutLookup.get(keyStr);
47192
- if (lutEntry) {
47193
- if (props.isWritable) {
47194
- lutWritableIdxs[lutEntry.lutIdx].add(lutEntry.addrIdx);
47195
- } else {
47196
- lutReadonlyIdxs[lutEntry.lutIdx].add(lutEntry.addrIdx);
47197
- }
47198
- } else {
47199
- numStaticKeys++;
47200
- if (props.isWritable) numWritableStaticKeys++;
47201
- }
47202
- }
47203
- const fixedOverhead = 101;
47204
- const staticKeysSection = compactU16Size(numStaticKeys) + numStaticKeys * 32;
47205
- let ixSection = compactU16Size(ixs.length);
47206
- for (const ix of ixs) {
47207
- const numAccounts = ix.keys.length;
47208
- ixSection += 1 + // programId index
47209
- compactU16Size(numAccounts) + numAccounts + // account key indexes
47210
- compactU16Size(ix.data.length) + ix.data.length;
47211
- }
47212
- let numUsedLuts = 0;
47213
- let lutSection = 0;
47214
- for (let li = 0; li < luts.length; li++) {
47215
- const wCount = lutWritableIdxs[li].size;
47216
- const rCount = lutReadonlyIdxs[li].size;
47217
- if (wCount === 0 && rCount === 0) continue;
47218
- numUsedLuts++;
47219
- lutSection += 32 + // LUT address
47220
- compactU16Size(wCount) + wCount + // writable indexes
47221
- compactU16Size(rCount) + rCount;
47222
- }
47223
- lutSection += compactU16Size(numUsedLuts);
47224
- let totalLutKeys = 0;
47225
- for (let li = 0; li < luts.length; li++) {
47226
- totalLutKeys += lutWritableIdxs[li].size + lutReadonlyIdxs[li].size;
47227
- }
47228
- const accountCount = numStaticKeys + totalLutKeys;
47229
- let totalLutWritableKeys = 0;
47230
- for (let li = 0; li < luts.length; li++) {
47231
- totalLutWritableKeys += lutWritableIdxs[li].size;
47232
- }
47233
- const writableAccountCount = numWritableStaticKeys + totalLutWritableKeys;
47234
- const size = fixedOverhead + staticKeysSection + ixSection + lutSection + 1;
47235
- return { size, accountCount, writableAccountCount };
47236
- }
47237
- function computeFlashLoanNonSwapBudget({
47238
- program,
47239
- marginfiAccount,
47240
- ixs,
47241
- bankMap,
47242
- addressLookupTableAccounts
47243
- }) {
47244
- const projectedActiveBanksKeys = computeProjectedActiveBanksNoCpi(
47245
- marginfiAccount.balances,
47246
- ixs,
47247
- program
47248
- );
47249
- const projectedActiveBanks = projectedActiveBanksKeys.map((key) => {
47250
- const b = bankMap.get(key.toBase58());
47251
- if (!b) throw new Error(`Bank ${key.toBase58()} not found in computeFlashLoanNonSwapBudget`);
47252
- return b;
47253
- });
47254
- const endIndex = ixs.length + 1;
47255
- const beginFlIx = sync_instructions_default.makeBeginFlashLoanIx(
47256
- program.programId,
47257
- { marginfiAccount: marginfiAccount.address, authority: marginfiAccount.authority },
47258
- { endIndex: new BN11(endIndex) }
47259
- );
47260
- const endFlRemainingAccounts = computeHealthAccountMetas(projectedActiveBanks);
47261
- const endFlIx = sync_instructions_default.makeEndFlashLoanIx(
47262
- program.programId,
47263
- { marginfiAccount: marginfiAccount.address, authority: marginfiAccount.authority },
47264
- endFlRemainingAccounts.map((pubkey) => ({ pubkey, isSigner: false, isWritable: false }))
47265
- );
47266
- const allNonSwapIxs = [beginFlIx, ...ixs, endFlIx];
47267
- const nonSwapMsg = new TransactionMessage({
47268
- payerKey: marginfiAccount.authority,
47269
- recentBlockhash: PublicKey.default.toBase58(),
47270
- instructions: allNonSwapIxs
47271
- }).compileToV0Message(addressLookupTableAccounts);
47272
- const nonSwapSize = new VersionedTransaction(nonSwapMsg).serialize().length;
47273
- const { header, staticAccountKeys, addressTableLookups } = nonSwapMsg;
47274
- const nonSwapTotal = staticAccountKeys.length + addressTableLookups.reduce(
47275
- (s, l) => s + l.writableIndexes.length + l.readonlyIndexes.length,
47276
- 0
47277
- );
47278
- const sizeConstraint = MAX_TX_SIZE - nonSwapSize - SWAP_MERGE_OVERHEAD;
47279
- const maxSwapTotalAccounts = MAX_ACCOUNT_LOCKS - nonSwapTotal;
47280
- console.log("[flashloan-budget]", {
47281
- method: "compiled",
47282
- nonSwapSize,
47283
- nonSwapTotal,
47284
- sizeConstraint,
47285
- maxSwapTotalAccounts
47286
- });
47287
- return { sizeConstraint, maxSwapTotalAccounts };
47288
- }
47289
- function compileFlashloanPrecheck({
47290
- allIxs,
47291
- payer,
47292
- luts,
47293
- sizeConstraint,
47294
- swapIxCount,
47295
- swapLutCount
47296
- }) {
47297
- const msg = new TransactionMessage({
47298
- payerKey: payer,
47299
- recentBlockhash: PublicKey.default.toBase58(),
47300
- instructions: allIxs
47301
- }).compileToV0Message(luts);
47302
- const rawSize = new VersionedTransaction(msg).serialize().length;
47303
- const fullTxSize = rawSize + FL_IX_OVERHEAD;
47304
- const overshoot = fullTxSize - MAX_TX_SIZE;
47305
- const { header, staticAccountKeys, addressTableLookups } = msg;
47306
- const writableStatic = staticAccountKeys.length - header.numReadonlySignedAccounts - header.numReadonlyUnsignedAccounts;
47307
- const writableLut = addressTableLookups.reduce((s, l) => s + l.writableIndexes.length, 0);
47308
- const writableAccounts = writableStatic + writableLut;
47309
- const totalAccounts = staticAccountKeys.length + addressTableLookups.reduce(
47310
- (s, l) => s + l.writableIndexes.length + l.readonlyIndexes.length,
47311
- 0
47312
- );
47313
- console.log("[flashloan-precheck]", {
47314
- fullTxSize,
47315
- overshoot,
47316
- sizeConstraint,
47317
- writableAccounts,
47318
- totalAccounts,
47319
- staticKeys: staticAccountKeys.length,
47320
- numLuts: addressTableLookups.length,
47321
- swapIxCount,
47322
- swapLutCount
47323
- });
47324
- return { fullTxSize, overshoot, writableAccounts, totalAccounts };
47325
- }
47326
- async function buildBudgetIx(config, program, marginfiAccount, bankMap, bankMetadataMap, overrideInferAccounts) {
47327
- const { bank, tokenProgram } = config;
47328
- switch (config.type) {
47329
- case "borrow":
47330
- return makeBorrowIx3({
47331
- program,
47332
- bank,
47333
- bankMap,
47334
- tokenProgram,
47335
- amount: 1,
47336
- marginfiAccount,
47337
- authority: marginfiAccount.authority,
47338
- isSync: true,
47339
- opts: { createAtas: false, wrapAndUnwrapSol: false, overrideInferAccounts }
47340
- });
47341
- case "repay":
47342
- return makeRepayIx3({
47343
- program,
47344
- bank,
47345
- tokenProgram,
47346
- amount: 1,
47347
- accountAddress: marginfiAccount.address,
47348
- authority: marginfiAccount.authority,
47349
- repayAll: false,
47350
- isSync: true,
47351
- opts: { wrapAndUnwrapSol: false, overrideInferAccounts }
47352
- });
47353
- case "deposit":
47354
- return buildDepositBudgetIx(
47355
- config,
47356
- program,
47357
- marginfiAccount,
47358
- bankMetadataMap,
47359
- overrideInferAccounts
47360
- );
47361
- case "withdraw":
47362
- return buildWithdrawBudgetIx(
47363
- config,
47364
- program,
47365
- marginfiAccount,
47366
- bankMap,
47367
- bankMetadataMap,
47368
- overrideInferAccounts
47369
- );
47370
- }
47371
- }
47372
- async function buildDepositBudgetIx(config, program, marginfiAccount, bankMetadataMap, overrideInferAccounts) {
47373
- const { bank, tokenProgram } = config;
47374
- const opts = { wrapAndUnwrapSol: false, overrideInferAccounts };
47375
- switch (bank.config.assetTag) {
47376
- case 3 /* KAMINO */: {
47377
- const reserve = bankMetadataMap[bank.address.toBase58()]?.kaminoStates?.reserveState;
47378
- if (!reserve) {
47379
- throw TransactionBuildingError.kaminoReserveNotFound(
47380
- bank.address.toBase58(),
47381
- bank.mint.toBase58(),
47382
- bank.tokenSymbol
47383
- );
47384
- }
47385
- return makeKaminoDepositIx3({
47386
- program,
47387
- bank,
47388
- tokenProgram,
47389
- amount: 1,
47390
- accountAddress: marginfiAccount.address,
47391
- authority: marginfiAccount.authority,
47392
- group: marginfiAccount.group,
47393
- reserve,
47394
- isSync: true,
47395
- opts
47396
- });
47397
- }
47398
- case 4 /* DRIFT */: {
47399
- const driftState = bankMetadataMap[bank.address.toBase58()]?.driftStates;
47400
- if (!driftState) {
47401
- throw TransactionBuildingError.driftStateNotFound(
47402
- bank.address.toBase58(),
47403
- bank.mint.toBase58(),
47404
- bank.tokenSymbol
47405
- );
47406
- }
47407
- return makeDriftDepositIx3({
47408
- program,
47409
- bank,
47410
- tokenProgram,
47411
- amount: 1,
47412
- accountAddress: marginfiAccount.address,
47413
- authority: marginfiAccount.authority,
47414
- group: marginfiAccount.group,
47415
- driftMarketIndex: driftState.spotMarketState.marketIndex,
47416
- driftOracle: driftState.spotMarketState.oracle,
47417
- isSync: true,
47418
- opts
47419
- });
47420
- }
47421
- case 6 /* JUPLEND */: {
47422
- return makeJuplendDepositIx2({
47423
- program,
47424
- bank,
47425
- tokenProgram,
47426
- amount: 1,
47427
- accountAddress: marginfiAccount.address,
47428
- authority: marginfiAccount.authority,
47429
- group: marginfiAccount.group,
47430
- isSync: true,
47431
- opts
47432
- });
47433
- }
47434
47289
  default: {
47435
- return makeDepositIx3({
47290
+ depositIxs = await makeDepositIx3({
47436
47291
  program,
47437
- bank,
47438
- tokenProgram,
47439
- amount: 1,
47292
+ bank: depositOpts.depositBank,
47293
+ tokenProgram: depositOpts.tokenProgram,
47294
+ amount: amountToDeposit,
47440
47295
  accountAddress: marginfiAccount.address,
47441
47296
  authority: marginfiAccount.authority,
47442
- group: marginfiAccount.group,
47443
- isSync: true,
47444
- opts
47445
- });
47446
- }
47447
- }
47448
- }
47449
- async function buildWithdrawBudgetIx(config, program, marginfiAccount, bankMap, bankMetadataMap, overrideInferAccounts) {
47450
- const { bank, tokenProgram } = config;
47451
- const opts = { createAtas: false, wrapAndUnwrapSol: false, overrideInferAccounts };
47452
- switch (bank.config.assetTag) {
47453
- case 3 /* KAMINO */: {
47454
- const reserve = bankMetadataMap[bank.address.toBase58()]?.kaminoStates?.reserveState;
47455
- if (!reserve) {
47456
- throw TransactionBuildingError.kaminoReserveNotFound(
47457
- bank.address.toBase58(),
47458
- bank.mint.toBase58(),
47459
- bank.tokenSymbol
47460
- );
47461
- }
47462
- return makeKaminoWithdrawIx3({
47463
- program,
47464
- bank,
47465
- bankMap,
47466
- tokenProgram,
47467
- cTokenAmount: 1,
47468
- marginfiAccount,
47469
- authority: marginfiAccount.authority,
47470
- reserve,
47471
- withdrawAll: false,
47472
- isSync: true,
47473
- opts
47474
- });
47475
- }
47476
- case 4 /* DRIFT */: {
47477
- const driftState = bankMetadataMap[bank.address.toBase58()]?.driftStates;
47478
- if (!driftState) {
47479
- throw TransactionBuildingError.driftStateNotFound(
47480
- bank.address.toBase58(),
47481
- bank.mint.toBase58(),
47482
- bank.tokenSymbol
47483
- );
47484
- }
47485
- return makeDriftWithdrawIx3({
47486
- program,
47487
- bank,
47488
- bankMap,
47489
- tokenProgram,
47490
- amount: 1,
47491
- marginfiAccount,
47492
- authority: marginfiAccount.authority,
47493
- driftSpotMarket: driftState.spotMarketState,
47494
- userRewards: driftState.userRewards,
47495
- withdrawAll: false,
47496
- isSync: true,
47497
- opts
47498
- });
47499
- }
47500
- case 6 /* JUPLEND */: {
47501
- const jupLendState = bankMetadataMap[bank.address.toBase58()]?.jupLendStates;
47502
- if (!jupLendState) {
47503
- throw TransactionBuildingError.jupLendStateNotFound(
47504
- bank.address.toBase58(),
47505
- bank.mint.toBase58(),
47506
- bank.tokenSymbol
47507
- );
47508
- }
47509
- return makeJuplendWithdrawIx2({
47510
- program,
47511
- bank,
47512
- bankMap,
47513
- tokenProgram,
47514
- amount: 1,
47515
- marginfiAccount,
47516
- authority: marginfiAccount.authority,
47517
- jupLendingState: jupLendState.jupLendingState,
47518
- withdrawAll: false,
47519
- opts
47520
- });
47521
- }
47522
- default: {
47523
- return makeWithdrawIx3({
47524
- program,
47525
- bank,
47526
- bankMap,
47527
- tokenProgram,
47528
- amount: 1,
47529
- marginfiAccount,
47530
- authority: marginfiAccount.authority,
47531
- withdrawAll: false,
47532
- isSync: true,
47533
- opts
47297
+ group: marginfiAccount.group,
47298
+ opts: {
47299
+ wrapAndUnwrapSol: false,
47300
+ overrideInferAccounts
47301
+ }
47534
47302
  });
47303
+ break;
47535
47304
  }
47536
47305
  }
47537
- }
47538
- async function computeFlashloanSwapConstraints({
47539
- program,
47540
- marginfiAccount,
47541
- bankMap,
47542
- addressLookupTableAccounts,
47543
- bankMetadataMap,
47544
- primaryIx,
47545
- secondaryIx,
47546
- overrideInferAccounts
47547
- }) {
47548
- const cuRequestIxs = [
47549
- ComputeBudgetProgram.setComputeUnitLimit({ units: 12e5 }),
47550
- ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 })
47306
+ const luts = [...addressLookupTableAccounts ?? [], ...swapLookupTables];
47307
+ const allNonFlIxs = [
47308
+ ...cuRequestIxs,
47309
+ ...borrowIxs.instructions,
47310
+ ...swapInstructions,
47311
+ ...depositIxs.instructions
47551
47312
  ];
47552
- const [primaryResult, secondaryResult] = await Promise.all([
47553
- buildBudgetIx(
47554
- primaryIx,
47555
- program,
47556
- marginfiAccount,
47557
- bankMap,
47558
- bankMetadataMap,
47559
- overrideInferAccounts
47560
- ),
47561
- buildBudgetIx(
47562
- secondaryIx,
47563
- program,
47564
- marginfiAccount,
47565
- bankMap,
47566
- bankMetadataMap,
47567
- overrideInferAccounts
47568
- )
47569
- ]);
47570
- return computeFlashLoanNonSwapBudget({
47313
+ if (swapInstructions.length > 0) {
47314
+ compileFlashloanPrecheck({
47315
+ allIxs: allNonFlIxs,
47316
+ payer: marginfiAccount.authority,
47317
+ luts,
47318
+ sizeConstraint: sizeConstraintUsed,
47319
+ swapIxCount: swapInstructions.length,
47320
+ swapLutCount: swapLookupTables.length
47321
+ });
47322
+ }
47323
+ const flashloanTx = await makeFlashLoanTx({
47571
47324
  program,
47572
47325
  marginfiAccount,
47573
47326
  bankMap,
47574
- addressLookupTableAccounts,
47575
- ixs: [...cuRequestIxs, ...primaryResult.instructions, ...secondaryResult.instructions]
47327
+ addressLookupTableAccounts: luts,
47328
+ blockhash,
47329
+ ixs: allNonFlIxs
47576
47330
  });
47331
+ const txSize = getTxSize(flashloanTx);
47332
+ const totalKeys = getTotalAccountKeys(flashloanTx);
47333
+ if (txSize > MAX_TX_SIZE || totalKeys > MAX_ACCOUNT_LOCKS) {
47334
+ throw TransactionBuildingError.swapSizeExceededLoop(
47335
+ txSize,
47336
+ totalKeys,
47337
+ swapOpts.swapConfig?.provider
47338
+ );
47339
+ }
47340
+ return {
47341
+ flashloanTx,
47342
+ setupInstructions,
47343
+ swapQuote,
47344
+ borrowIxs,
47345
+ depositIxs,
47346
+ amountToDeposit
47347
+ };
47577
47348
  }
47578
-
47579
- // src/services/account/actions/flash-loan.ts
47580
- async function makeBeginFlashLoanIx3(program, marginfiAccountPk, endIndex, authority, isSync) {
47581
- const ix = isSync && authority ? sync_instructions_default.makeBeginFlashLoanIx(
47582
- program.programId,
47583
- {
47584
- marginfiAccount: marginfiAccountPk,
47585
- authority
47586
- },
47587
- { endIndex: new BN11(endIndex) }
47588
- ) : await instructions_default.makeBeginFlashLoanIx(
47349
+ async function makeRepayIx3({
47350
+ program,
47351
+ bank,
47352
+ tokenProgram,
47353
+ amount,
47354
+ authority,
47355
+ accountAddress,
47356
+ repayAll = false,
47357
+ isSync = false,
47358
+ opts = {}
47359
+ }) {
47360
+ const wrapAndUnwrapSol = opts.wrapAndUnwrapSol ?? true;
47361
+ const wSolBalanceUi = opts.wSolBalanceUi ?? 0;
47362
+ const repayIxs = [];
47363
+ const userAta = getAssociatedTokenAddressSync(bank.mint, authority, true, tokenProgram);
47364
+ const remainingAccounts = tokenProgram.equals(TOKEN_2022_PROGRAM_ID) ? [{ pubkey: bank.mint, isSigner: false, isWritable: false }] : [];
47365
+ if (bank.mint.equals(NATIVE_MINT) && wrapAndUnwrapSol) {
47366
+ repayIxs.push(...makeWrapSolIxs(authority, new BigNumber(amount).minus(wSolBalanceUi)));
47367
+ }
47368
+ const repayIx = !isSync || !opts.overrideInferAccounts?.group ? await instructions_default.makeRepayIx(
47589
47369
  program,
47590
47370
  {
47591
- marginfiAccount: marginfiAccountPk,
47592
- authority
47371
+ marginfiAccount: accountAddress,
47372
+ signerTokenAccount: userAta,
47373
+ bank: bank.address,
47374
+ tokenProgram,
47375
+ authority: opts.overrideInferAccounts?.authority ?? authority,
47376
+ group: opts.overrideInferAccounts?.group,
47377
+ liquidityVault: opts.overrideInferAccounts?.liquidityVault
47593
47378
  },
47594
- { endIndex: new BN11(endIndex) }
47595
- );
47596
- return { instructions: [ix], keys: [] };
47597
- }
47598
- async function makeEndFlashLoanIx3(program, marginfiAccountPk, projectedActiveBanks, authority, isSync) {
47599
- const remainingAccounts = computeHealthAccountMetas(projectedActiveBanks);
47600
- const ix = isSync && authority ? sync_instructions_default.makeEndFlashLoanIx(
47379
+ { amount: uiToNative(amount, bank.mintDecimals), repayAll },
47380
+ remainingAccounts
47381
+ ) : sync_instructions_default.makeRepayIx(
47601
47382
  program.programId,
47602
47383
  {
47603
- marginfiAccount: marginfiAccountPk,
47604
- authority
47605
- },
47606
- remainingAccounts.map((account) => ({
47607
- pubkey: account,
47608
- isSigner: false,
47609
- isWritable: false
47610
- }))
47611
- ) : await instructions_default.makeEndFlashLoanIx(
47612
- program,
47613
- {
47614
- marginfiAccount: marginfiAccountPk,
47615
- authority
47384
+ marginfiAccount: accountAddress,
47385
+ signerTokenAccount: userAta,
47386
+ bank: bank.address,
47387
+ tokenProgram,
47388
+ authority: opts.overrideInferAccounts?.authority ?? authority,
47389
+ group: opts.overrideInferAccounts?.group
47616
47390
  },
47617
- remainingAccounts.map((account) => ({
47618
- pubkey: account,
47619
- isSigner: false,
47620
- isWritable: false
47621
- }))
47391
+ { amount: uiToNative(amount, bank.mintDecimals), repayAll },
47392
+ remainingAccounts
47622
47393
  );
47623
- return { instructions: [ix], keys: [] };
47394
+ repayIxs.push(repayIx);
47395
+ return {
47396
+ instructions: repayIxs,
47397
+ keys: []
47398
+ };
47624
47399
  }
47625
- async function makeFlashLoanTx({
47626
- program,
47627
- marginfiAccount,
47628
- ixs,
47629
- bankMap,
47630
- blockhash,
47631
- addressLookupTableAccounts,
47632
- signers,
47633
- isSync
47634
- }) {
47635
- const endIndex = ixs.length + 1;
47636
- const projectedActiveBanksKeys = computeProjectedActiveBanksNoCpi(
47637
- marginfiAccount.balances,
47638
- ixs,
47639
- program
47640
- );
47641
- const projectedActiveBanks = projectedActiveBanksKeys.map((account) => {
47642
- const b = bankMap.get(account.toBase58());
47643
- if (!b) throw Error(`Bank ${account.toBase58()} not found, in makeFlashLoanTx function`);
47644
- return b;
47645
- });
47646
- const beginFlashLoanIx = await makeBeginFlashLoanIx3(
47647
- program,
47648
- marginfiAccount.address,
47649
- endIndex,
47650
- marginfiAccount.authority,
47651
- isSync
47652
- );
47653
- const endFlashLoanIx = await makeEndFlashLoanIx3(
47654
- program,
47655
- marginfiAccount.address,
47656
- projectedActiveBanks,
47657
- marginfiAccount.authority,
47658
- isSync
47659
- );
47660
- const message = new TransactionMessage({
47661
- payerKey: marginfiAccount.authority,
47662
- recentBlockhash: blockhash,
47663
- instructions: [...beginFlashLoanIx.instructions, ...ixs, ...endFlashLoanIx.instructions]
47664
- }).compileToV0Message(addressLookupTableAccounts);
47665
- const tx = addTransactionMetadata(new VersionedTransaction(message), {
47666
- addressLookupTables: addressLookupTableAccounts,
47667
- type: "FLASHLOAN" /* FLASHLOAN */,
47668
- signers
47400
+ async function makeRepayTx(params) {
47401
+ const { luts, ...depositIxParams } = params;
47402
+ const ixs = await makeRepayIx3(depositIxParams);
47403
+ const tx = new Transaction().add(...ixs.instructions);
47404
+ tx.feePayer = params.authority;
47405
+ const solanaTx = addTransactionMetadata(tx, {
47406
+ type: "REPAY" /* REPAY */,
47407
+ signers: ixs.keys,
47408
+ addressLookupTables: luts
47669
47409
  });
47670
- if (signers) {
47671
- tx.sign(signers);
47672
- }
47673
- return tx;
47410
+ return solanaTx;
47674
47411
  }
47675
-
47676
- // src/services/account/actions/loop.ts
47677
- async function makeLoopTx(params) {
47412
+ async function makeRepayWithCollatTx(params) {
47678
47413
  const {
47679
47414
  program,
47680
47415
  marginfiAccount,
47681
47416
  bankMap,
47682
- depositOpts,
47683
- borrowOpts,
47417
+ withdrawOpts,
47418
+ repayOpts,
47684
47419
  bankMetadataMap,
47685
47420
  addressLookupTableAccounts,
47686
47421
  connection,
47687
47422
  oraclePrices,
47688
- crossbarUrl,
47689
- additionalIxs = []
47423
+ crossbarUrl
47690
47424
  } = params;
47691
47425
  const blockhash = (await connection.getLatestBlockhash("confirmed")).blockhash;
47692
47426
  const setupIxs = await makeSetupIx({
@@ -47694,34 +47428,34 @@ async function makeLoopTx(params) {
47694
47428
  authority: marginfiAccount.authority,
47695
47429
  tokens: [
47696
47430
  {
47697
- mint: borrowOpts.borrowBank.mint,
47698
- tokenProgram: borrowOpts.tokenProgram
47431
+ mint: repayOpts.repayBank.mint,
47432
+ tokenProgram: repayOpts.tokenProgram
47699
47433
  },
47700
47434
  {
47701
- mint: depositOpts.depositBank.mint,
47702
- tokenProgram: depositOpts.tokenProgram
47435
+ mint: withdrawOpts.withdrawBank.mint,
47436
+ tokenProgram: withdrawOpts.tokenProgram
47703
47437
  }
47704
47438
  ]
47705
47439
  });
47706
- const updateJupLendRateIxs = makeUpdateJupLendRateIxs(
47707
- params.marginfiAccount,
47708
- params.bankMap,
47709
- [depositOpts.depositBank.address],
47710
- params.bankMetadataMap
47440
+ const updateJuplendMarketIxs = makeUpdateJupLendRateIxs(
47441
+ marginfiAccount,
47442
+ bankMap,
47443
+ [withdrawOpts.withdrawBank.address],
47444
+ bankMetadataMap
47711
47445
  );
47712
47446
  const updateDriftMarketIxs = makeUpdateDriftMarketIxs(
47713
- params.marginfiAccount,
47714
- params.bankMap,
47715
- [depositOpts.depositBank.address],
47716
- params.bankMetadataMap
47447
+ marginfiAccount,
47448
+ bankMap,
47449
+ [withdrawOpts.withdrawBank.address],
47450
+ bankMetadataMap
47717
47451
  );
47718
47452
  const kaminoRefreshIxs = makeRefreshKaminoBanksIxs(
47719
47453
  marginfiAccount,
47720
47454
  bankMap,
47721
- [borrowOpts.borrowBank.address, depositOpts.depositBank.address],
47455
+ [withdrawOpts.withdrawBank.address, repayOpts.repayBank.address],
47722
47456
  bankMetadataMap
47723
47457
  );
47724
- const { flashloanTx, setupInstructions, swapQuote, amountToDeposit, depositIxs, borrowIxs } = await buildLoopFlashloanTx({
47458
+ const { flashloanTx, setupInstructions, swapQuote, amountToRepay, withdrawIxs, repayIxs } = await buildRepayWithCollatFlashloanTx({
47725
47459
  ...params,
47726
47460
  blockhash
47727
47461
  });
@@ -47731,7 +47465,7 @@ async function makeLoopTx(params) {
47731
47465
  }
47732
47466
  if (ix.programId.equals(ASSOCIATED_TOKEN_PROGRAM_ID)) {
47733
47467
  const mintKey = ix.keys[3]?.pubkey;
47734
- if (mintKey?.equals(depositOpts.depositBank.mint) || mintKey?.equals(borrowOpts.borrowBank.mint)) {
47468
+ if (mintKey?.equals(withdrawOpts.withdrawBank.mint) || mintKey?.equals(repayOpts.repayBank.mint)) {
47735
47469
  return false;
47736
47470
  }
47737
47471
  }
@@ -47743,24 +47477,18 @@ async function makeLoopTx(params) {
47743
47477
  bankMap,
47744
47478
  oraclePrices,
47745
47479
  assetShareValueMultiplierByBank: params.assetShareValueMultiplierByBank,
47746
- instructions: [...borrowIxs.instructions, ...depositIxs.instructions],
47480
+ instructions: [...withdrawIxs.instructions, ...repayIxs.instructions],
47747
47481
  program,
47748
47482
  connection,
47749
47483
  crossbarUrl
47750
47484
  });
47751
47485
  let additionalTxs = [];
47752
- if (depositOpts.depositBank.mint.equals(NATIVE_MINT) && depositOpts.inputDepositAmount) {
47753
- setupIxs.push(
47754
- ...makeWrapSolIxs(marginfiAccount.authority, new BigNumber(depositOpts.inputDepositAmount))
47755
- );
47756
- }
47757
- if (setupIxs.length > 0 || additionalIxs.length > 0 || kaminoRefreshIxs.instructions.length > 0 || updateDriftMarketIxs.instructions.length > 0 || updateJupLendRateIxs.instructions.length > 0) {
47486
+ if (setupIxs.length > 0 || kaminoRefreshIxs.instructions.length > 0 || updateDriftMarketIxs.instructions.length > 0 || updateJuplendMarketIxs.instructions.length > 0) {
47758
47487
  const ixs = [
47759
- ...additionalIxs,
47760
47488
  ...setupIxs,
47761
47489
  ...kaminoRefreshIxs.instructions,
47762
47490
  ...updateDriftMarketIxs.instructions,
47763
- ...updateJupLendRateIxs.instructions
47491
+ ...updateJuplendMarketIxs.instructions
47764
47492
  ];
47765
47493
  const txs = splitInstructionsToFitTransactions([], ixs, {
47766
47494
  blockhash,
@@ -47790,19 +47518,16 @@ async function makeLoopTx(params) {
47790
47518
  );
47791
47519
  }
47792
47520
  const transactions = [...additionalTxs, flashloanTx];
47793
- return {
47794
- transactions,
47795
- actionTxIndex: transactions.length - 1,
47796
- quoteResponse: swapQuote
47797
- };
47521
+ return { transactions, swapQuote, amountToRepay };
47798
47522
  }
47799
- async function buildLoopFlashloanTx({
47523
+ async function buildRepayWithCollatFlashloanTx({
47800
47524
  program,
47801
47525
  marginfiAccount,
47802
47526
  bankMap,
47803
- borrowOpts,
47804
- depositOpts,
47527
+ withdrawOpts,
47528
+ repayOpts,
47805
47529
  bankMetadataMap,
47530
+ assetShareValueMultiplierByBank,
47806
47531
  addressLookupTableAccounts,
47807
47532
  connection,
47808
47533
  swapOpts,
@@ -47813,20 +47538,20 @@ async function buildLoopFlashloanTx({
47813
47538
  ComputeBudgetProgram.setComputeUnitLimit({ units: 12e5 }),
47814
47539
  ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 })
47815
47540
  ];
47816
- let amountToDeposit;
47541
+ let amountToRepay;
47817
47542
  let swapInstructions = [];
47818
47543
  let setupInstructions = [];
47819
47544
  let swapLookupTables = [];
47820
47545
  let swapQuote;
47821
47546
  let sizeConstraintUsed = 0;
47822
- if (depositOpts.depositBank.mint.equals(borrowOpts.borrowBank.mint)) {
47823
- amountToDeposit = borrowOpts.borrowAmount + (depositOpts.loopMode === "DEPOSIT" ? depositOpts.inputDepositAmount : 0);
47547
+ if (repayOpts.repayBank.mint.equals(withdrawOpts.withdrawBank.mint)) {
47548
+ amountToRepay = withdrawOpts.withdrawAmount;
47824
47549
  } else {
47825
47550
  const destinationTokenAccount = getAssociatedTokenAddressSync(
47826
- new PublicKey(depositOpts.depositBank.mint),
47551
+ new PublicKey(repayOpts.repayBank.mint),
47827
47552
  marginfiAccount.authority,
47828
47553
  true,
47829
- depositOpts.tokenProgram.equals(TOKEN_2022_PROGRAM_ID) ? TOKEN_2022_PROGRAM_ID : void 0
47554
+ repayOpts.tokenProgram.equals(TOKEN_2022_PROGRAM_ID) ? TOKEN_2022_PROGRAM_ID : void 0
47830
47555
  );
47831
47556
  const swapConstraints = await computeFlashloanSwapConstraints({
47832
47557
  program,
@@ -47835,21 +47560,24 @@ async function buildLoopFlashloanTx({
47835
47560
  bankMetadataMap,
47836
47561
  addressLookupTableAccounts: addressLookupTableAccounts ?? [],
47837
47562
  primaryIx: {
47838
- type: "borrow",
47839
- bank: borrowOpts.borrowBank,
47840
- tokenProgram: borrowOpts.tokenProgram
47563
+ type: "withdraw",
47564
+ bank: withdrawOpts.withdrawBank,
47565
+ tokenProgram: withdrawOpts.tokenProgram
47841
47566
  },
47842
47567
  secondaryIx: {
47843
- type: "deposit",
47844
- bank: depositOpts.depositBank,
47845
- tokenProgram: depositOpts.tokenProgram
47568
+ type: "repay",
47569
+ bank: repayOpts.repayBank,
47570
+ tokenProgram: repayOpts.tokenProgram
47846
47571
  },
47847
47572
  overrideInferAccounts
47848
47573
  });
47849
47574
  const swapResponse = await getSwapIxsForFlashloan({
47850
- inputMint: borrowOpts.borrowBank.mint.toBase58(),
47851
- outputMint: depositOpts.depositBank.mint.toBase58(),
47852
- amount: uiToNative(borrowOpts.borrowAmount, borrowOpts.borrowBank.mintDecimals).toNumber(),
47575
+ inputMint: withdrawOpts.withdrawBank.mint.toBase58(),
47576
+ outputMint: repayOpts.repayBank.mint.toBase58(),
47577
+ amount: uiToNative(
47578
+ withdrawOpts.withdrawAmount,
47579
+ withdrawOpts.withdrawBank.mintDecimals
47580
+ ).toNumber(),
47853
47581
  swapMode: "ExactIn",
47854
47582
  authority: marginfiAccount.authority,
47855
47583
  connection,
@@ -47859,52 +47587,50 @@ async function buildLoopFlashloanTx({
47859
47587
  maxSwapTotalAccounts: swapConstraints.maxSwapTotalAccounts
47860
47588
  });
47861
47589
  sizeConstraintUsed = swapConstraints.sizeConstraint;
47590
+ const { quoteResponse } = swapResponse;
47591
+ const outAmount = nativeToUi(quoteResponse.outAmount, repayOpts.repayBank.mintDecimals);
47862
47592
  const outAmountThreshold = nativeToUi(
47863
- swapResponse.quoteResponse.otherAmountThreshold,
47864
- depositOpts.depositBank.mintDecimals
47593
+ quoteResponse.otherAmountThreshold,
47594
+ repayOpts.repayBank.mintDecimals
47865
47595
  );
47866
- amountToDeposit = outAmountThreshold + (depositOpts.loopMode === "DEPOSIT" ? depositOpts.inputDepositAmount : 0);
47596
+ amountToRepay = outAmount > repayOpts.totalPositionAmount ? repayOpts.totalPositionAmount : outAmountThreshold;
47867
47597
  swapInstructions = swapResponse.swapInstructions;
47868
- setupInstructions = swapResponse.setupInstructions;
47869
47598
  swapLookupTables = swapResponse.addressLookupTableAddresses;
47870
- swapQuote = swapResponse.quoteResponse;
47599
+ swapQuote = quoteResponse;
47871
47600
  }
47872
- const borrowIxs = await makeBorrowIx3({
47873
- program,
47874
- bank: borrowOpts.borrowBank,
47875
- bankMap,
47876
- tokenProgram: borrowOpts.tokenProgram,
47877
- amount: borrowOpts.borrowAmount,
47878
- marginfiAccount,
47879
- authority: marginfiAccount.authority,
47880
- isSync: false,
47881
- opts: {
47882
- createAtas: false,
47883
- wrapAndUnwrapSol: false,
47884
- overrideInferAccounts
47885
- }
47886
- });
47887
- let depositIxs;
47888
- switch (depositOpts.depositBank.config.assetTag) {
47601
+ let withdrawIxs;
47602
+ switch (withdrawOpts.withdrawBank.config.assetTag) {
47889
47603
  case 3 /* KAMINO */: {
47890
- const reserve = bankMetadataMap[depositOpts.depositBank.address.toBase58()]?.kaminoStates?.reserveState;
47604
+ const reserve = bankMetadataMap[withdrawOpts.withdrawBank.address.toBase58()]?.kaminoStates?.reserveState;
47891
47605
  if (!reserve) {
47892
47606
  throw TransactionBuildingError.kaminoReserveNotFound(
47893
- depositOpts.depositBank.address.toBase58(),
47894
- depositOpts.depositBank.mint.toBase58(),
47895
- depositOpts.depositBank.tokenSymbol
47607
+ withdrawOpts.withdrawBank.address.toBase58(),
47608
+ withdrawOpts.withdrawBank.mint.toBase58(),
47609
+ withdrawOpts.withdrawBank.tokenSymbol
47896
47610
  );
47897
47611
  }
47898
- depositIxs = await makeKaminoDepositIx3({
47612
+ const multiplier = assetShareValueMultiplierByBank.get(withdrawOpts.withdrawBank.address.toBase58()) ?? new BigNumber(1);
47613
+ const adjustedAmount = new BigNumber(withdrawOpts.withdrawAmount).div(multiplier).times(1.0001).toNumber();
47614
+ withdrawIxs = await makeKaminoWithdrawIx3({
47899
47615
  program,
47900
- bank: depositOpts.depositBank,
47901
- tokenProgram: depositOpts.tokenProgram,
47902
- amount: amountToDeposit,
47903
- accountAddress: marginfiAccount.address,
47616
+ bank: withdrawOpts.withdrawBank,
47617
+ bankMap,
47618
+ tokenProgram: withdrawOpts.tokenProgram,
47619
+ cTokenAmount: adjustedAmount,
47620
+ marginfiAccount,
47904
47621
  authority: marginfiAccount.authority,
47905
- group: marginfiAccount.group,
47906
47622
  reserve,
47623
+ withdrawAll: isWholePosition(
47624
+ {
47625
+ amount: withdrawOpts.totalPositionAmount,
47626
+ isLending: true
47627
+ },
47628
+ withdrawOpts.withdrawAmount,
47629
+ withdrawOpts.withdrawBank.mintDecimals
47630
+ ),
47631
+ isSync: false,
47907
47632
  opts: {
47633
+ createAtas: false,
47908
47634
  wrapAndUnwrapSol: false,
47909
47635
  overrideInferAccounts
47910
47636
  }
@@ -47912,27 +47638,35 @@ async function buildLoopFlashloanTx({
47912
47638
  break;
47913
47639
  }
47914
47640
  case 4 /* DRIFT */: {
47915
- const driftState = bankMetadataMap[depositOpts.depositBank.address.toBase58()]?.driftStates;
47641
+ const driftState = bankMetadataMap[withdrawOpts.withdrawBank.address.toBase58()]?.driftStates;
47916
47642
  if (!driftState) {
47917
47643
  throw TransactionBuildingError.driftStateNotFound(
47918
- depositOpts.depositBank.address.toBase58(),
47919
- depositOpts.depositBank.mint.toBase58(),
47920
- depositOpts.depositBank.tokenSymbol
47644
+ withdrawOpts.withdrawBank.address.toBase58(),
47645
+ withdrawOpts.withdrawBank.mint.toBase58(),
47646
+ withdrawOpts.withdrawBank.tokenSymbol
47921
47647
  );
47922
47648
  }
47923
- const driftMarketIndex = driftState.spotMarketState.marketIndex;
47924
- const driftOracle = driftState.spotMarketState.oracle;
47925
- depositIxs = await makeDriftDepositIx3({
47649
+ withdrawIxs = await makeDriftWithdrawIx3({
47926
47650
  program,
47927
- bank: depositOpts.depositBank,
47928
- tokenProgram: depositOpts.tokenProgram,
47929
- amount: amountToDeposit,
47930
- accountAddress: marginfiAccount.address,
47651
+ bank: withdrawOpts.withdrawBank,
47652
+ bankMap,
47653
+ tokenProgram: withdrawOpts.tokenProgram,
47654
+ amount: withdrawOpts.withdrawAmount,
47655
+ marginfiAccount,
47931
47656
  authority: marginfiAccount.authority,
47932
- group: marginfiAccount.group,
47933
- driftMarketIndex,
47934
- driftOracle,
47657
+ driftSpotMarket: driftState.spotMarketState,
47658
+ userRewards: driftState.userRewards,
47659
+ withdrawAll: isWholePosition(
47660
+ {
47661
+ amount: withdrawOpts.totalPositionAmount,
47662
+ isLending: true
47663
+ },
47664
+ withdrawOpts.withdrawAmount,
47665
+ withdrawOpts.withdrawBank.mintDecimals
47666
+ ),
47667
+ isSync: false,
47935
47668
  opts: {
47669
+ createAtas: false,
47936
47670
  wrapAndUnwrapSol: false,
47937
47671
  overrideInferAccounts
47938
47672
  }
@@ -47940,15 +47674,33 @@ async function buildLoopFlashloanTx({
47940
47674
  break;
47941
47675
  }
47942
47676
  case 6 /* JUPLEND */: {
47943
- depositIxs = await makeJuplendDepositIx2({
47677
+ const jupLendState = bankMetadataMap[withdrawOpts.withdrawBank.address.toBase58()]?.jupLendStates;
47678
+ if (!jupLendState) {
47679
+ throw TransactionBuildingError.jupLendStateNotFound(
47680
+ withdrawOpts.withdrawBank.address.toBase58(),
47681
+ withdrawOpts.withdrawBank.mint.toBase58(),
47682
+ withdrawOpts.withdrawBank.tokenSymbol
47683
+ );
47684
+ }
47685
+ withdrawIxs = await makeJuplendWithdrawIx2({
47944
47686
  program,
47945
- bank: depositOpts.depositBank,
47946
- tokenProgram: depositOpts.tokenProgram,
47947
- amount: amountToDeposit,
47948
- accountAddress: marginfiAccount.address,
47687
+ bank: withdrawOpts.withdrawBank,
47688
+ bankMap,
47689
+ tokenProgram: withdrawOpts.tokenProgram,
47690
+ amount: withdrawOpts.withdrawAmount,
47691
+ marginfiAccount,
47949
47692
  authority: marginfiAccount.authority,
47950
- group: marginfiAccount.group,
47693
+ jupLendingState: jupLendState.jupLendingState,
47694
+ withdrawAll: isWholePosition(
47695
+ {
47696
+ amount: withdrawOpts.totalPositionAmount,
47697
+ isLending: true
47698
+ },
47699
+ withdrawOpts.withdrawAmount,
47700
+ withdrawOpts.withdrawBank.mintDecimals
47701
+ ),
47951
47702
  opts: {
47703
+ createAtas: false,
47952
47704
  wrapAndUnwrapSol: false,
47953
47705
  overrideInferAccounts
47954
47706
  }
@@ -47956,15 +47708,25 @@ async function buildLoopFlashloanTx({
47956
47708
  break;
47957
47709
  }
47958
47710
  default: {
47959
- depositIxs = await makeDepositIx3({
47711
+ withdrawIxs = await makeWithdrawIx3({
47960
47712
  program,
47961
- bank: depositOpts.depositBank,
47962
- tokenProgram: depositOpts.tokenProgram,
47963
- amount: amountToDeposit,
47964
- accountAddress: marginfiAccount.address,
47713
+ bank: withdrawOpts.withdrawBank,
47714
+ bankMap,
47715
+ tokenProgram: withdrawOpts.tokenProgram,
47716
+ amount: withdrawOpts.withdrawAmount,
47717
+ marginfiAccount,
47965
47718
  authority: marginfiAccount.authority,
47966
- group: marginfiAccount.group,
47719
+ withdrawAll: isWholePosition(
47720
+ {
47721
+ amount: withdrawOpts.totalPositionAmount,
47722
+ isLending: true
47723
+ },
47724
+ withdrawOpts.withdrawAmount,
47725
+ withdrawOpts.withdrawBank.mintDecimals
47726
+ ),
47727
+ isSync: false,
47967
47728
  opts: {
47729
+ createAtas: false,
47968
47730
  wrapAndUnwrapSol: false,
47969
47731
  overrideInferAccounts
47970
47732
  }
@@ -47972,12 +47734,33 @@ async function buildLoopFlashloanTx({
47972
47734
  break;
47973
47735
  }
47974
47736
  }
47737
+ const repayIxs = await makeRepayIx3({
47738
+ program,
47739
+ bank: repayOpts.repayBank,
47740
+ tokenProgram: repayOpts.tokenProgram,
47741
+ amount: amountToRepay,
47742
+ accountAddress: marginfiAccount.address,
47743
+ authority: marginfiAccount.authority,
47744
+ repayAll: isWholePosition(
47745
+ {
47746
+ amount: repayOpts.totalPositionAmount,
47747
+ isLending: true
47748
+ },
47749
+ amountToRepay,
47750
+ repayOpts.repayBank.mintDecimals
47751
+ ),
47752
+ isSync: false,
47753
+ opts: {
47754
+ wrapAndUnwrapSol: false,
47755
+ overrideInferAccounts
47756
+ }
47757
+ });
47975
47758
  const luts = [...addressLookupTableAccounts ?? [], ...swapLookupTables];
47976
47759
  const allNonFlIxs = [
47977
47760
  ...cuRequestIxs,
47978
- ...borrowIxs.instructions,
47761
+ ...withdrawIxs.instructions,
47979
47762
  ...swapInstructions,
47980
- ...depositIxs.instructions
47763
+ ...repayIxs.instructions
47981
47764
  ];
47982
47765
  if (swapInstructions.length > 0) {
47983
47766
  compileFlashloanPrecheck({
@@ -47995,12 +47778,13 @@ async function buildLoopFlashloanTx({
47995
47778
  bankMap,
47996
47779
  addressLookupTableAccounts: luts,
47997
47780
  blockhash,
47998
- ixs: allNonFlIxs
47781
+ ixs: allNonFlIxs,
47782
+ isSync: true
47999
47783
  });
48000
47784
  const txSize = getTxSize(flashloanTx);
48001
47785
  const totalKeys = getTotalAccountKeys(flashloanTx);
48002
47786
  if (txSize > MAX_TX_SIZE || totalKeys > MAX_ACCOUNT_LOCKS) {
48003
- throw TransactionBuildingError.swapSizeExceededLoop(
47787
+ throw TransactionBuildingError.swapSizeExceededRepay(
48004
47788
  txSize,
48005
47789
  totalKeys,
48006
47790
  swapOpts.swapConfig?.provider
@@ -48010,9 +47794,9 @@ async function buildLoopFlashloanTx({
48010
47794
  flashloanTx,
48011
47795
  setupInstructions,
48012
47796
  swapQuote,
48013
- borrowIxs,
48014
- depositIxs,
48015
- amountToDeposit
47797
+ withdrawIxs,
47798
+ repayIxs,
47799
+ amountToRepay
48016
47800
  };
48017
47801
  }
48018
47802
 
@@ -48200,7 +47984,7 @@ async function buildSwapCollateralFlashloanTx({
48200
47984
  authority: marginfiAccount.authority,
48201
47985
  reserve,
48202
47986
  withdrawAll: isFullWithdraw,
48203
- isSync: true,
47987
+ isSync: false,
48204
47988
  opts: {
48205
47989
  createAtas: false,
48206
47990
  wrapAndUnwrapSol: false,
@@ -48275,7 +48059,7 @@ async function buildSwapCollateralFlashloanTx({
48275
48059
  marginfiAccount,
48276
48060
  authority: marginfiAccount.authority,
48277
48061
  withdrawAll: isFullWithdraw,
48278
- isSync: true,
48062
+ isSync: false,
48279
48063
  opts: {
48280
48064
  createAtas: false,
48281
48065
  wrapAndUnwrapSol: false,
@@ -48438,12 +48222,12 @@ async function buildSwapCollateralFlashloanTx({
48438
48222
  addressLookupTableAccounts: luts,
48439
48223
  blockhash,
48440
48224
  ixs: allNonFlIxs,
48441
- isSync: true
48225
+ isSync: false
48442
48226
  });
48443
48227
  const txSize = getTxSize(flashloanTx);
48444
48228
  const totalKeys = getTotalAccountKeys(flashloanTx);
48445
48229
  if (txSize > MAX_TX_SIZE || totalKeys > MAX_ACCOUNT_LOCKS) {
48446
- throw TransactionBuildingError.swapSizeExceededLoop(
48230
+ throw TransactionBuildingError.swapSizeExceededPositionSwap(
48447
48231
  txSize,
48448
48232
  totalKeys,
48449
48233
  swapOpts.swapConfig?.provider
@@ -48704,7 +48488,7 @@ async function buildSwapDebtFlashloanTx({
48704
48488
  const txSize = getTxSize(flashloanTx);
48705
48489
  const totalKeys = getTotalAccountKeys(flashloanTx);
48706
48490
  if (txSize > MAX_TX_SIZE || totalKeys > MAX_ACCOUNT_LOCKS) {
48707
- throw TransactionBuildingError.swapSizeExceededLoop(
48491
+ throw TransactionBuildingError.swapSizeExceededPositionSwap(
48708
48492
  txSize,
48709
48493
  totalKeys,
48710
48494
  swapOpts.swapConfig?.provider
@@ -49374,23 +49158,27 @@ var getTitanSwapIxsForFlashloan = async ({
49374
49158
  quoteParams.swapMode === "ExactIn" ? quoteParams.outputMint : quoteParams.inputMint
49375
49159
  );
49376
49160
  const { feeAccount, hasFeeAccount } = await checkTitanFeeAccount(connection, feeMint);
49161
+ const useFeeAccount = hasFeeAccount && !!quoteParams.platformFeeBps;
49377
49162
  let finalQuoteParams = quoteParams;
49378
- if (!hasFeeAccount) {
49379
- console.warn("Warning: Titan fee account ATA does not exist, disabling platform fee");
49163
+ if (!useFeeAccount) {
49164
+ if (!hasFeeAccount) {
49165
+ console.warn("Warning: Titan fee account ATA does not exist, disabling platform fee");
49166
+ }
49380
49167
  finalQuoteParams = {
49381
49168
  ...quoteParams,
49382
49169
  platformFeeBps: void 0
49383
49170
  };
49384
49171
  }
49172
+ const effectiveFeeAccount = useFeeAccount ? feeAccount : void 0;
49385
49173
  if (basePath.startsWith("wss://") || basePath.startsWith("ws://")) {
49386
49174
  return getTitanSwapIxsViaWebSocket(
49387
49175
  { quoteParams: finalQuoteParams, authority, connection, destinationTokenAccount, apiConfig },
49388
- hasFeeAccount ? feeAccount : void 0
49176
+ effectiveFeeAccount
49389
49177
  );
49390
49178
  } else {
49391
49179
  return getTitanSwapIxsViaHttpProxy(
49392
49180
  { quoteParams: finalQuoteParams, authority, connection, destinationTokenAccount, apiConfig },
49393
- hasFeeAccount ? feeAccount : void 0
49181
+ effectiveFeeAccount
49394
49182
  );
49395
49183
  }
49396
49184
  };
@@ -49566,7 +49354,7 @@ async function getTitanExactOutViaWebSocket(params) {
49566
49354
  inputMint: new PublicKey(inputMint).toBytes(),
49567
49355
  outputMint: new PublicKey(outputMint).toBytes(),
49568
49356
  amount,
49569
- swapMode: "ExactOut",
49357
+ swapMode: "ExactOut" /* ExactOut */,
49570
49358
  slippageBps
49571
49359
  },
49572
49360
  transaction: {
@@ -49786,178 +49574,616 @@ var getSwapIxsForFlashloan = async (params) => {
49786
49574
  lastError = err;
49787
49575
  console.warn(`[swap] ${attemptProvider} failed:`, err instanceof Error ? err.message : err);
49788
49576
  }
49789
- }
49790
- const firstProvider = attempts[0]?.provider ?? "Swap";
49791
- throw TransactionBuildingError.swapQuoteFailed(
49792
- firstProvider,
49793
- inputMint,
49794
- outputMint,
49795
- lastError?.message ?? "No swap route available"
49796
- );
49797
- };
49798
- var getExactOutEstimate = async (params) => {
49799
- const { inputMint, outputMint, amount, swapOpts, connection } = params;
49800
- const provider = swapOpts.swapConfig?.provider ?? "JUPITER" /* JUPITER */;
49801
- const attempts = [
49802
- { provider, apiConfig: swapOpts.swapConfig?.apiConfig },
49803
- ...swapOpts.swapConfig?.fallbackProviders ?? []
49804
- ];
49805
- let lastError;
49806
- for (const { provider: attemptProvider, apiConfig } of attempts) {
49807
- const fn = getExactOutProviderFn({
49808
- attemptProvider,
49809
- inputMint,
49810
- outputMint,
49811
- amount,
49812
- swapOpts,
49813
- apiConfig
49814
- });
49815
- if (!fn) continue;
49816
- try {
49817
- return await fn(apiConfig);
49818
- } catch (err) {
49819
- if (err instanceof TransactionBuildingError) throw err;
49820
- lastError = err;
49821
- console.warn(
49822
- `[exactout] ${attemptProvider} failed:`,
49823
- err instanceof Error ? err.message : err
49824
- );
49577
+ }
49578
+ const firstProvider = attempts[0]?.provider ?? "Swap";
49579
+ throw TransactionBuildingError.swapQuoteFailed(
49580
+ firstProvider,
49581
+ inputMint,
49582
+ outputMint,
49583
+ lastError?.message ?? "No swap route available"
49584
+ );
49585
+ };
49586
+ var getExactOutEstimate = async (params) => {
49587
+ const { inputMint, outputMint, amount, swapOpts, connection } = params;
49588
+ const provider = swapOpts.swapConfig?.provider ?? "JUPITER" /* JUPITER */;
49589
+ const attempts = [
49590
+ { provider, apiConfig: swapOpts.swapConfig?.apiConfig },
49591
+ ...swapOpts.swapConfig?.fallbackProviders ?? []
49592
+ ];
49593
+ let lastError;
49594
+ for (const { provider: attemptProvider, apiConfig } of attempts) {
49595
+ const fn = getExactOutProviderFn({
49596
+ attemptProvider,
49597
+ inputMint,
49598
+ outputMint,
49599
+ amount,
49600
+ swapOpts,
49601
+ apiConfig
49602
+ });
49603
+ if (!fn) continue;
49604
+ try {
49605
+ return await fn(apiConfig);
49606
+ } catch (err) {
49607
+ if (err instanceof TransactionBuildingError) throw err;
49608
+ lastError = err;
49609
+ console.warn(
49610
+ `[exactout] ${attemptProvider} failed:`,
49611
+ err instanceof Error ? err.message : err
49612
+ );
49613
+ }
49614
+ }
49615
+ const firstProvider = attempts[0]?.provider ?? "Swap";
49616
+ throw TransactionBuildingError.swapQuoteFailed(
49617
+ firstProvider,
49618
+ inputMint,
49619
+ outputMint,
49620
+ lastError?.message ?? "No swap route available"
49621
+ );
49622
+ };
49623
+ function mapJupiterQuoteToSwapQuoteResult(quote) {
49624
+ return {
49625
+ inAmount: quote.inAmount,
49626
+ outAmount: quote.outAmount,
49627
+ otherAmountThreshold: quote.otherAmountThreshold,
49628
+ slippageBps: quote.slippageBps,
49629
+ platformFee: quote.platformFee ? {
49630
+ amount: quote.platformFee.amount ?? "0",
49631
+ feeBps: quote.platformFee.feeBps ?? 0
49632
+ } : void 0,
49633
+ priceImpactPct: quote.priceImpactPct,
49634
+ contextSlot: quote.contextSlot,
49635
+ timeTaken: quote.timeTaken,
49636
+ provider: "JUPITER" /* JUPITER */
49637
+ };
49638
+ }
49639
+
49640
+ // src/services/account/utils/jupiter.utils.ts
49641
+ var REFERRAL_PROGRAM_ID = new PublicKey("REFER4ZgmyYx9c6He5XfaTMiGfdLwRnkV4RPp9t9iF3");
49642
+ var REFERRAL_ACCOUNT_PUBKEY = new PublicKey("Mm7HcujSK2JzPW4eX7g4oqTXbWYDuFxapNMHXe8yp1B");
49643
+ var getFeeAccount = (mint) => {
49644
+ const [feeAccount] = PublicKey.findProgramAddressSync(
49645
+ [Buffer.from("referral_ata"), REFERRAL_ACCOUNT_PUBKEY.toBuffer(), mint.toBuffer()],
49646
+ REFERRAL_PROGRAM_ID
49647
+ );
49648
+ return feeAccount.toBase58();
49649
+ };
49650
+ var checkFeeAccount = async (connection, mint) => {
49651
+ const feeAccount = getFeeAccount(mint);
49652
+ const hasFeeAccount = !!await connection.getAccountInfo(new PublicKey(feeAccount));
49653
+ return { feeAccount, hasFeeAccount };
49654
+ };
49655
+ function deserializeJupiterInstruction(instruction) {
49656
+ return new TransactionInstruction({
49657
+ programId: new PublicKey(instruction.programId),
49658
+ keys: instruction.accounts.map((key) => ({
49659
+ pubkey: new PublicKey(key.pubkey),
49660
+ isSigner: key.isSigner,
49661
+ isWritable: key.isWritable
49662
+ })),
49663
+ data: Buffer.from(instruction.data, "base64")
49664
+ });
49665
+ }
49666
+ function toJupiterConfig(apiConfig) {
49667
+ if (!apiConfig) return void 0;
49668
+ return {
49669
+ basePath: apiConfig.basePath,
49670
+ apiKey: apiConfig.apiKey ? () => apiConfig.apiKey : void 0,
49671
+ headers: apiConfig.headers
49672
+ };
49673
+ }
49674
+ var getJupiterSwapIxsForFlashloan = async ({
49675
+ quoteParams,
49676
+ authority,
49677
+ connection,
49678
+ destinationTokenAccount,
49679
+ apiConfig,
49680
+ maxSwapAccounts
49681
+ }) => {
49682
+ const configParams = toJupiterConfig(apiConfig);
49683
+ const jupiterApiClient = configParams?.basePath ? new SwapApi(new Configuration(configParams)) : createJupiterApiClient(configParams);
49684
+ const feeMint = quoteParams.swapMode === "ExactIn" ? quoteParams.outputMint : quoteParams.inputMint;
49685
+ const { feeAccount, hasFeeAccount } = await checkFeeAccount(connection, new PublicKey(feeMint));
49686
+ const project0JupiterLut = (await connection.getAddressLookupTable(ADDRESS_LOOKUP_TABLE_FOR_SWAP))?.value;
49687
+ const useFeeAccount = hasFeeAccount && !!quoteParams.platformFeeBps;
49688
+ let finalQuoteParams = quoteParams;
49689
+ if (!useFeeAccount) {
49690
+ if (!hasFeeAccount) {
49691
+ console.warn("Warning: feeAccountInfo is undefined");
49692
+ }
49693
+ finalQuoteParams = {
49694
+ ...quoteParams,
49695
+ platformFeeBps: void 0
49696
+ };
49697
+ }
49698
+ const JUPITER_MAX_ACCOUNTS_MARGIN = 4;
49699
+ const maxAccounts = maxSwapAccounts !== void 0 ? maxSwapAccounts - JUPITER_MAX_ACCOUNTS_MARGIN : 40;
49700
+ const swapQuote = await jupiterApiClient.quoteGet({
49701
+ ...finalQuoteParams,
49702
+ maxAccounts
49703
+ });
49704
+ const swapInstructionResponse = await jupiterApiClient.swapInstructionsPost({
49705
+ swapRequest: {
49706
+ quoteResponse: swapQuote,
49707
+ userPublicKey: authority.toBase58(),
49708
+ feeAccount: useFeeAccount ? feeAccount : void 0,
49709
+ wrapAndUnwrapSol: false,
49710
+ destinationTokenAccount: destinationTokenAccount.toBase58()
49711
+ }
49712
+ });
49713
+ const lutAddresses = swapInstructionResponse.addressLookupTableAddresses;
49714
+ const lutAccountsRaw = await connection.getMultipleAccountsInfo(
49715
+ lutAddresses.map((address) => new PublicKey(address))
49716
+ );
49717
+ const addressLookupTableAccounts = lutAccountsRaw.map((accountInfo, index) => {
49718
+ const addressLookupTableAddress = lutAddresses[index];
49719
+ if (!accountInfo || !addressLookupTableAddress) {
49720
+ return null;
49721
+ }
49722
+ return new AddressLookupTableAccount({
49723
+ key: new PublicKey(addressLookupTableAddress),
49724
+ state: AddressLookupTableAccount.deserialize(accountInfo.data)
49725
+ });
49726
+ }).filter((account) => account !== null).concat(project0JupiterLut ? [project0JupiterLut] : []);
49727
+ const instruction = deserializeJupiterInstruction(swapInstructionResponse.swapInstruction);
49728
+ const setupInstructions = swapInstructionResponse.setupInstructions.map(
49729
+ deserializeJupiterInstruction
49730
+ );
49731
+ return {
49732
+ swapInstructions: [instruction],
49733
+ setupInstructions,
49734
+ addressLookupTableAddresses: addressLookupTableAccounts,
49735
+ quoteResponse: mapJupiterQuoteToSwapQuoteResult(swapQuote)
49736
+ };
49737
+ };
49738
+
49739
+ // src/services/account/utils/misc.utils.ts
49740
+ function floor(value, decimals) {
49741
+ return Math.floor(value * 10 ** decimals) / 10 ** decimals;
49742
+ }
49743
+ function ceil(value, decimals) {
49744
+ return Math.ceil(value * 10 ** decimals) / 10 ** decimals;
49745
+ }
49746
+ function computeClosePositionTokenAmount(position, mintDecimals) {
49747
+ const closePositionTokenAmount = position.isLending ? floor(position.amount, mintDecimals) : ceil(position.amount, mintDecimals);
49748
+ return closePositionTokenAmount;
49749
+ }
49750
+ function isWholePosition(position, amount, mintDecimals) {
49751
+ const closePositionTokenAmount = computeClosePositionTokenAmount(position, mintDecimals);
49752
+ return amount >= closePositionTokenAmount;
49753
+ }
49754
+ var SWAP_MERGE_OVERHEAD = 150;
49755
+ var FL_IX_OVERHEAD = 52;
49756
+ function compactU16Size(n) {
49757
+ return n < 128 ? 1 : n < 16384 ? 2 : 3;
49758
+ }
49759
+ function computeV0TxSize(ixs, payerKey, luts) {
49760
+ const keyMap = /* @__PURE__ */ new Map();
49761
+ const payerStr = payerKey.toBase58();
49762
+ keyMap.set(payerStr, { isSigner: true, isWritable: true });
49763
+ const programIds = /* @__PURE__ */ new Set();
49764
+ for (const ix of ixs) {
49765
+ const progStr = ix.programId.toBase58();
49766
+ programIds.add(progStr);
49767
+ if (!keyMap.has(progStr)) {
49768
+ keyMap.set(progStr, { isSigner: false, isWritable: false });
49769
+ }
49770
+ for (const meta of ix.keys) {
49771
+ const keyStr = meta.pubkey.toBase58();
49772
+ const existing = keyMap.get(keyStr);
49773
+ if (existing) {
49774
+ existing.isSigner = existing.isSigner || meta.isSigner;
49775
+ existing.isWritable = existing.isWritable || meta.isWritable;
49776
+ } else {
49777
+ keyMap.set(keyStr, { isSigner: meta.isSigner, isWritable: meta.isWritable });
49778
+ }
49779
+ }
49780
+ }
49781
+ const lutLookup = /* @__PURE__ */ new Map();
49782
+ for (let li = 0; li < luts.length; li++) {
49783
+ const addresses = luts[li].state.addresses;
49784
+ for (let ai = 0; ai < addresses.length; ai++) {
49785
+ const addrStr = addresses[ai].toBase58();
49786
+ if (!lutLookup.has(addrStr)) {
49787
+ lutLookup.set(addrStr, { lutIdx: li, addrIdx: ai });
49788
+ }
49789
+ }
49790
+ }
49791
+ let numStaticKeys = 0;
49792
+ let numWritableStaticKeys = 0;
49793
+ const lutWritableIdxs = luts.map(() => /* @__PURE__ */ new Set());
49794
+ const lutReadonlyIdxs = luts.map(() => /* @__PURE__ */ new Set());
49795
+ for (const [keyStr, props] of keyMap) {
49796
+ if (props.isSigner || programIds.has(keyStr)) {
49797
+ numStaticKeys++;
49798
+ if (props.isWritable) numWritableStaticKeys++;
49799
+ continue;
49800
+ }
49801
+ const lutEntry = lutLookup.get(keyStr);
49802
+ if (lutEntry) {
49803
+ if (props.isWritable) {
49804
+ lutWritableIdxs[lutEntry.lutIdx].add(lutEntry.addrIdx);
49805
+ } else {
49806
+ lutReadonlyIdxs[lutEntry.lutIdx].add(lutEntry.addrIdx);
49807
+ }
49808
+ } else {
49809
+ numStaticKeys++;
49810
+ if (props.isWritable) numWritableStaticKeys++;
49811
+ }
49812
+ }
49813
+ const fixedOverhead = 101;
49814
+ const staticKeysSection = compactU16Size(numStaticKeys) + numStaticKeys * 32;
49815
+ let ixSection = compactU16Size(ixs.length);
49816
+ for (const ix of ixs) {
49817
+ const numAccounts = ix.keys.length;
49818
+ ixSection += 1 + // programId index
49819
+ compactU16Size(numAccounts) + numAccounts + // account key indexes
49820
+ compactU16Size(ix.data.length) + ix.data.length;
49821
+ }
49822
+ let numUsedLuts = 0;
49823
+ let lutSection = 0;
49824
+ for (let li = 0; li < luts.length; li++) {
49825
+ const wCount = lutWritableIdxs[li].size;
49826
+ const rCount = lutReadonlyIdxs[li].size;
49827
+ if (wCount === 0 && rCount === 0) continue;
49828
+ numUsedLuts++;
49829
+ lutSection += 32 + // LUT address
49830
+ compactU16Size(wCount) + wCount + // writable indexes
49831
+ compactU16Size(rCount) + rCount;
49832
+ }
49833
+ lutSection += compactU16Size(numUsedLuts);
49834
+ let totalLutKeys = 0;
49835
+ for (let li = 0; li < luts.length; li++) {
49836
+ totalLutKeys += lutWritableIdxs[li].size + lutReadonlyIdxs[li].size;
49837
+ }
49838
+ const accountCount = numStaticKeys + totalLutKeys;
49839
+ let totalLutWritableKeys = 0;
49840
+ for (let li = 0; li < luts.length; li++) {
49841
+ totalLutWritableKeys += lutWritableIdxs[li].size;
49842
+ }
49843
+ const writableAccountCount = numWritableStaticKeys + totalLutWritableKeys;
49844
+ const size = fixedOverhead + staticKeysSection + ixSection + lutSection + 1;
49845
+ return { size, accountCount, writableAccountCount };
49846
+ }
49847
+ function computeFlashLoanNonSwapBudget({
49848
+ program,
49849
+ marginfiAccount,
49850
+ ixs,
49851
+ bankMap,
49852
+ addressLookupTableAccounts
49853
+ }) {
49854
+ const projectedActiveBanksKeys = computeProjectedActiveBanksNoCpi(
49855
+ marginfiAccount.balances,
49856
+ ixs,
49857
+ program
49858
+ );
49859
+ const projectedActiveBanks = projectedActiveBanksKeys.map((key) => {
49860
+ const b = bankMap.get(key.toBase58());
49861
+ if (!b) throw new Error(`Bank ${key.toBase58()} not found in computeFlashLoanNonSwapBudget`);
49862
+ return b;
49863
+ });
49864
+ const endIndex = ixs.length + 1;
49865
+ const beginFlIx = sync_instructions_default.makeBeginFlashLoanIx(
49866
+ program.programId,
49867
+ { marginfiAccount: marginfiAccount.address, authority: marginfiAccount.authority },
49868
+ { endIndex: new BN11(endIndex) }
49869
+ );
49870
+ const endFlRemainingAccounts = computeHealthAccountMetas(projectedActiveBanks);
49871
+ const endFlIx = sync_instructions_default.makeEndFlashLoanIx(
49872
+ program.programId,
49873
+ { marginfiAccount: marginfiAccount.address, authority: marginfiAccount.authority },
49874
+ endFlRemainingAccounts.map((pubkey) => ({ pubkey, isSigner: false, isWritable: false }))
49875
+ );
49876
+ const allNonSwapIxs = [beginFlIx, ...ixs, endFlIx];
49877
+ const nonSwapMsg = new TransactionMessage({
49878
+ payerKey: marginfiAccount.authority,
49879
+ recentBlockhash: PublicKey.default.toBase58(),
49880
+ instructions: allNonSwapIxs
49881
+ }).compileToV0Message(addressLookupTableAccounts);
49882
+ const nonSwapSize = new VersionedTransaction(nonSwapMsg).serialize().length;
49883
+ const { header, staticAccountKeys, addressTableLookups } = nonSwapMsg;
49884
+ const nonSwapTotal = staticAccountKeys.length + addressTableLookups.reduce(
49885
+ (s, l) => s + l.writableIndexes.length + l.readonlyIndexes.length,
49886
+ 0
49887
+ );
49888
+ const sizeConstraint = MAX_TX_SIZE - nonSwapSize - SWAP_MERGE_OVERHEAD;
49889
+ const maxSwapTotalAccounts = MAX_ACCOUNT_LOCKS - nonSwapTotal;
49890
+ console.log("[flashloan-budget]", {
49891
+ method: "compiled",
49892
+ nonSwapSize,
49893
+ nonSwapTotal,
49894
+ sizeConstraint,
49895
+ maxSwapTotalAccounts
49896
+ });
49897
+ return { sizeConstraint, maxSwapTotalAccounts };
49898
+ }
49899
+ function compileFlashloanPrecheck({
49900
+ allIxs,
49901
+ payer,
49902
+ luts,
49903
+ sizeConstraint,
49904
+ swapIxCount,
49905
+ swapLutCount
49906
+ }) {
49907
+ const msg = new TransactionMessage({
49908
+ payerKey: payer,
49909
+ recentBlockhash: PublicKey.default.toBase58(),
49910
+ instructions: allIxs
49911
+ }).compileToV0Message(luts);
49912
+ const rawSize = new VersionedTransaction(msg).serialize().length;
49913
+ const fullTxSize = rawSize + FL_IX_OVERHEAD;
49914
+ const overshoot = fullTxSize - MAX_TX_SIZE;
49915
+ const { header, staticAccountKeys, addressTableLookups } = msg;
49916
+ const writableStatic = staticAccountKeys.length - header.numReadonlySignedAccounts - header.numReadonlyUnsignedAccounts;
49917
+ const writableLut = addressTableLookups.reduce((s, l) => s + l.writableIndexes.length, 0);
49918
+ const writableAccounts = writableStatic + writableLut;
49919
+ const totalAccounts = staticAccountKeys.length + addressTableLookups.reduce(
49920
+ (s, l) => s + l.writableIndexes.length + l.readonlyIndexes.length,
49921
+ 0
49922
+ );
49923
+ console.log("[flashloan-precheck]", {
49924
+ fullTxSize,
49925
+ overshoot,
49926
+ sizeConstraint,
49927
+ writableAccounts,
49928
+ totalAccounts,
49929
+ staticKeys: staticAccountKeys.length,
49930
+ numLuts: addressTableLookups.length,
49931
+ swapIxCount,
49932
+ swapLutCount
49933
+ });
49934
+ return { fullTxSize, overshoot, writableAccounts, totalAccounts };
49935
+ }
49936
+ async function buildBudgetIx(config, program, marginfiAccount, bankMap, bankMetadataMap, overrideInferAccounts) {
49937
+ const { bank, tokenProgram } = config;
49938
+ switch (config.type) {
49939
+ case "borrow":
49940
+ return makeBorrowIx3({
49941
+ program,
49942
+ bank,
49943
+ bankMap,
49944
+ tokenProgram,
49945
+ amount: 1,
49946
+ marginfiAccount,
49947
+ authority: marginfiAccount.authority,
49948
+ isSync: true,
49949
+ opts: { createAtas: false, wrapAndUnwrapSol: false, overrideInferAccounts }
49950
+ });
49951
+ case "repay":
49952
+ return makeRepayIx3({
49953
+ program,
49954
+ bank,
49955
+ tokenProgram,
49956
+ amount: 1,
49957
+ accountAddress: marginfiAccount.address,
49958
+ authority: marginfiAccount.authority,
49959
+ repayAll: false,
49960
+ isSync: true,
49961
+ opts: { wrapAndUnwrapSol: false, overrideInferAccounts }
49962
+ });
49963
+ case "deposit":
49964
+ return buildDepositBudgetIx(
49965
+ config,
49966
+ program,
49967
+ marginfiAccount,
49968
+ bankMetadataMap,
49969
+ overrideInferAccounts
49970
+ );
49971
+ case "withdraw":
49972
+ return buildWithdrawBudgetIx(
49973
+ config,
49974
+ program,
49975
+ marginfiAccount,
49976
+ bankMap,
49977
+ bankMetadataMap,
49978
+ overrideInferAccounts
49979
+ );
49980
+ }
49981
+ }
49982
+ async function buildDepositBudgetIx(config, program, marginfiAccount, bankMetadataMap, overrideInferAccounts) {
49983
+ const { bank, tokenProgram } = config;
49984
+ const opts = { wrapAndUnwrapSol: false, overrideInferAccounts };
49985
+ switch (bank.config.assetTag) {
49986
+ case 3 /* KAMINO */: {
49987
+ const reserve = bankMetadataMap[bank.address.toBase58()]?.kaminoStates?.reserveState;
49988
+ if (!reserve) {
49989
+ throw TransactionBuildingError.kaminoReserveNotFound(
49990
+ bank.address.toBase58(),
49991
+ bank.mint.toBase58(),
49992
+ bank.tokenSymbol
49993
+ );
49994
+ }
49995
+ return makeKaminoDepositIx3({
49996
+ program,
49997
+ bank,
49998
+ tokenProgram,
49999
+ amount: 1,
50000
+ accountAddress: marginfiAccount.address,
50001
+ authority: marginfiAccount.authority,
50002
+ group: marginfiAccount.group,
50003
+ reserve,
50004
+ isSync: true,
50005
+ opts
50006
+ });
50007
+ }
50008
+ case 4 /* DRIFT */: {
50009
+ const driftState = bankMetadataMap[bank.address.toBase58()]?.driftStates;
50010
+ if (!driftState) {
50011
+ throw TransactionBuildingError.driftStateNotFound(
50012
+ bank.address.toBase58(),
50013
+ bank.mint.toBase58(),
50014
+ bank.tokenSymbol
50015
+ );
50016
+ }
50017
+ return makeDriftDepositIx3({
50018
+ program,
50019
+ bank,
50020
+ tokenProgram,
50021
+ amount: 1,
50022
+ accountAddress: marginfiAccount.address,
50023
+ authority: marginfiAccount.authority,
50024
+ group: marginfiAccount.group,
50025
+ driftMarketIndex: driftState.spotMarketState.marketIndex,
50026
+ driftOracle: driftState.spotMarketState.oracle,
50027
+ isSync: true,
50028
+ opts
50029
+ });
50030
+ }
50031
+ case 6 /* JUPLEND */: {
50032
+ return makeJuplendDepositIx2({
50033
+ program,
50034
+ bank,
50035
+ tokenProgram,
50036
+ amount: 1,
50037
+ accountAddress: marginfiAccount.address,
50038
+ authority: marginfiAccount.authority,
50039
+ group: marginfiAccount.group,
50040
+ isSync: true,
50041
+ opts
50042
+ });
50043
+ }
50044
+ default: {
50045
+ return makeDepositIx3({
50046
+ program,
50047
+ bank,
50048
+ tokenProgram,
50049
+ amount: 1,
50050
+ accountAddress: marginfiAccount.address,
50051
+ authority: marginfiAccount.authority,
50052
+ group: marginfiAccount.group,
50053
+ isSync: true,
50054
+ opts
50055
+ });
49825
50056
  }
49826
50057
  }
49827
- const firstProvider = attempts[0]?.provider ?? "Swap";
49828
- throw TransactionBuildingError.swapQuoteFailed(
49829
- firstProvider,
49830
- inputMint,
49831
- outputMint,
49832
- lastError?.message ?? "No swap route available"
49833
- );
49834
- };
49835
- function mapJupiterQuoteToSwapQuoteResult(quote) {
49836
- return {
49837
- inAmount: quote.inAmount,
49838
- outAmount: quote.outAmount,
49839
- otherAmountThreshold: quote.otherAmountThreshold,
49840
- slippageBps: quote.slippageBps,
49841
- platformFee: quote.platformFee ? {
49842
- amount: quote.platformFee.amount ?? "0",
49843
- feeBps: quote.platformFee.feeBps ?? 0
49844
- } : void 0,
49845
- priceImpactPct: quote.priceImpactPct,
49846
- contextSlot: quote.contextSlot,
49847
- timeTaken: quote.timeTaken,
49848
- provider: "JUPITER" /* JUPITER */
49849
- };
49850
- }
49851
-
49852
- // src/services/account/utils/jupiter.utils.ts
49853
- var REFERRAL_PROGRAM_ID = new PublicKey("REFER4ZgmyYx9c6He5XfaTMiGfdLwRnkV4RPp9t9iF3");
49854
- var REFERRAL_ACCOUNT_PUBKEY = new PublicKey("Mm7HcujSK2JzPW4eX7g4oqTXbWYDuFxapNMHXe8yp1B");
49855
- var getFeeAccount = (mint) => {
49856
- const [feeAccount] = PublicKey.findProgramAddressSync(
49857
- [Buffer.from("referral_ata"), REFERRAL_ACCOUNT_PUBKEY.toBuffer(), mint.toBuffer()],
49858
- REFERRAL_PROGRAM_ID
49859
- );
49860
- return feeAccount.toBase58();
49861
- };
49862
- var checkFeeAccount = async (connection, mint) => {
49863
- const feeAccount = getFeeAccount(mint);
49864
- const hasFeeAccount = !!await connection.getAccountInfo(new PublicKey(feeAccount));
49865
- return { feeAccount, hasFeeAccount };
49866
- };
49867
- function deserializeJupiterInstruction(instruction) {
49868
- return new TransactionInstruction({
49869
- programId: new PublicKey(instruction.programId),
49870
- keys: instruction.accounts.map((key) => ({
49871
- pubkey: new PublicKey(key.pubkey),
49872
- isSigner: key.isSigner,
49873
- isWritable: key.isWritable
49874
- })),
49875
- data: Buffer.from(instruction.data, "base64")
49876
- });
49877
- }
49878
- function toJupiterConfig(apiConfig) {
49879
- if (!apiConfig) return void 0;
49880
- return {
49881
- basePath: apiConfig.basePath,
49882
- apiKey: apiConfig.apiKey ? () => apiConfig.apiKey : void 0,
49883
- headers: apiConfig.headers
49884
- };
49885
50058
  }
49886
- var getJupiterSwapIxsForFlashloan = async ({
49887
- quoteParams,
49888
- authority,
49889
- connection,
49890
- destinationTokenAccount,
49891
- apiConfig,
49892
- maxSwapAccounts
49893
- }) => {
49894
- const configParams = toJupiterConfig(apiConfig);
49895
- const jupiterApiClient = configParams?.basePath ? new SwapApi(new Configuration(configParams)) : createJupiterApiClient(configParams);
49896
- const feeMint = quoteParams.swapMode === "ExactIn" ? quoteParams.outputMint : quoteParams.inputMint;
49897
- const { feeAccount, hasFeeAccount } = await checkFeeAccount(connection, new PublicKey(feeMint));
49898
- const project0JupiterLut = (await connection.getAddressLookupTable(ADDRESS_LOOKUP_TABLE_FOR_SWAP))?.value;
49899
- let finalQuoteParams = quoteParams;
49900
- if (!hasFeeAccount) {
49901
- console.warn("Warning: feeAccountInfo is undefined");
49902
- finalQuoteParams = {
49903
- ...quoteParams,
49904
- platformFeeBps: void 0
49905
- };
49906
- }
49907
- const maxAccounts = maxSwapAccounts ?? 40;
49908
- const swapQuote = await jupiterApiClient.quoteGet({
49909
- ...finalQuoteParams,
49910
- maxAccounts
49911
- });
49912
- const swapInstructionResponse = await jupiterApiClient.swapInstructionsPost({
49913
- swapRequest: {
49914
- quoteResponse: swapQuote,
49915
- userPublicKey: authority.toBase58(),
49916
- feeAccount: hasFeeAccount ? feeAccount : void 0,
49917
- wrapAndUnwrapSol: false,
49918
- destinationTokenAccount: destinationTokenAccount.toBase58()
50059
+ async function buildWithdrawBudgetIx(config, program, marginfiAccount, bankMap, bankMetadataMap, overrideInferAccounts) {
50060
+ const { bank, tokenProgram } = config;
50061
+ const opts = { createAtas: false, wrapAndUnwrapSol: false, overrideInferAccounts };
50062
+ switch (bank.config.assetTag) {
50063
+ case 3 /* KAMINO */: {
50064
+ const reserve = bankMetadataMap[bank.address.toBase58()]?.kaminoStates?.reserveState;
50065
+ if (!reserve) {
50066
+ throw TransactionBuildingError.kaminoReserveNotFound(
50067
+ bank.address.toBase58(),
50068
+ bank.mint.toBase58(),
50069
+ bank.tokenSymbol
50070
+ );
50071
+ }
50072
+ return makeKaminoWithdrawIx3({
50073
+ program,
50074
+ bank,
50075
+ bankMap,
50076
+ tokenProgram,
50077
+ cTokenAmount: 1,
50078
+ marginfiAccount,
50079
+ authority: marginfiAccount.authority,
50080
+ reserve,
50081
+ withdrawAll: false,
50082
+ isSync: true,
50083
+ opts
50084
+ });
49919
50085
  }
49920
- });
49921
- const lutAddresses = swapInstructionResponse.addressLookupTableAddresses;
49922
- const lutAccountsRaw = await connection.getMultipleAccountsInfo(
49923
- lutAddresses.map((address) => new PublicKey(address))
49924
- );
49925
- const addressLookupTableAccounts = lutAccountsRaw.map((accountInfo, index) => {
49926
- const addressLookupTableAddress = lutAddresses[index];
49927
- if (!accountInfo || !addressLookupTableAddress) {
49928
- return null;
50086
+ case 4 /* DRIFT */: {
50087
+ const driftState = bankMetadataMap[bank.address.toBase58()]?.driftStates;
50088
+ if (!driftState) {
50089
+ throw TransactionBuildingError.driftStateNotFound(
50090
+ bank.address.toBase58(),
50091
+ bank.mint.toBase58(),
50092
+ bank.tokenSymbol
50093
+ );
50094
+ }
50095
+ return makeDriftWithdrawIx3({
50096
+ program,
50097
+ bank,
50098
+ bankMap,
50099
+ tokenProgram,
50100
+ amount: 1,
50101
+ marginfiAccount,
50102
+ authority: marginfiAccount.authority,
50103
+ driftSpotMarket: driftState.spotMarketState,
50104
+ userRewards: driftState.userRewards,
50105
+ withdrawAll: false,
50106
+ isSync: true,
50107
+ opts
50108
+ });
49929
50109
  }
49930
- return new AddressLookupTableAccount({
49931
- key: new PublicKey(addressLookupTableAddress),
49932
- state: AddressLookupTableAccount.deserialize(accountInfo.data)
49933
- });
49934
- }).filter((account) => account !== null).concat(project0JupiterLut ? [project0JupiterLut] : []);
49935
- const instruction = deserializeJupiterInstruction(swapInstructionResponse.swapInstruction);
49936
- const setupInstructions = swapInstructionResponse.setupInstructions.map(
49937
- deserializeJupiterInstruction
49938
- );
49939
- return {
49940
- swapInstructions: [instruction],
49941
- setupInstructions,
49942
- addressLookupTableAddresses: addressLookupTableAccounts,
49943
- quoteResponse: mapJupiterQuoteToSwapQuoteResult(swapQuote)
49944
- };
49945
- };
49946
-
49947
- // src/services/account/utils/misc.utils.ts
49948
- function floor(value, decimals) {
49949
- return Math.floor(value * 10 ** decimals) / 10 ** decimals;
49950
- }
49951
- function ceil(value, decimals) {
49952
- return Math.ceil(value * 10 ** decimals) / 10 ** decimals;
49953
- }
49954
- function computeClosePositionTokenAmount(position, mintDecimals) {
49955
- const closePositionTokenAmount = position.isLending ? floor(position.amount, mintDecimals) : ceil(position.amount, mintDecimals);
49956
- return closePositionTokenAmount;
50110
+ case 6 /* JUPLEND */: {
50111
+ const jupLendState = bankMetadataMap[bank.address.toBase58()]?.jupLendStates;
50112
+ if (!jupLendState) {
50113
+ throw TransactionBuildingError.jupLendStateNotFound(
50114
+ bank.address.toBase58(),
50115
+ bank.mint.toBase58(),
50116
+ bank.tokenSymbol
50117
+ );
50118
+ }
50119
+ return makeJuplendWithdrawIx2({
50120
+ program,
50121
+ bank,
50122
+ bankMap,
50123
+ tokenProgram,
50124
+ amount: 1,
50125
+ marginfiAccount,
50126
+ authority: marginfiAccount.authority,
50127
+ jupLendingState: jupLendState.jupLendingState,
50128
+ withdrawAll: false,
50129
+ opts
50130
+ });
50131
+ }
50132
+ default: {
50133
+ return makeWithdrawIx3({
50134
+ program,
50135
+ bank,
50136
+ bankMap,
50137
+ tokenProgram,
50138
+ amount: 1,
50139
+ marginfiAccount,
50140
+ authority: marginfiAccount.authority,
50141
+ withdrawAll: false,
50142
+ isSync: true,
50143
+ opts
50144
+ });
50145
+ }
50146
+ }
49957
50147
  }
49958
- function isWholePosition(position, amount, mintDecimals) {
49959
- const closePositionTokenAmount = computeClosePositionTokenAmount(position, mintDecimals);
49960
- return amount >= closePositionTokenAmount;
50148
+ async function computeFlashloanSwapConstraints({
50149
+ program,
50150
+ marginfiAccount,
50151
+ bankMap,
50152
+ addressLookupTableAccounts,
50153
+ bankMetadataMap,
50154
+ primaryIx,
50155
+ secondaryIx,
50156
+ overrideInferAccounts
50157
+ }) {
50158
+ const cuRequestIxs = [
50159
+ ComputeBudgetProgram.setComputeUnitLimit({ units: 12e5 }),
50160
+ ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 })
50161
+ ];
50162
+ const [primaryResult, secondaryResult] = await Promise.all([
50163
+ buildBudgetIx(
50164
+ primaryIx,
50165
+ program,
50166
+ marginfiAccount,
50167
+ bankMap,
50168
+ bankMetadataMap,
50169
+ overrideInferAccounts
50170
+ ),
50171
+ buildBudgetIx(
50172
+ secondaryIx,
50173
+ program,
50174
+ marginfiAccount,
50175
+ bankMap,
50176
+ bankMetadataMap,
50177
+ overrideInferAccounts
50178
+ )
50179
+ ]);
50180
+ return computeFlashLoanNonSwapBudget({
50181
+ program,
50182
+ marginfiAccount,
50183
+ bankMap,
50184
+ addressLookupTableAccounts,
50185
+ ixs: [...cuRequestIxs, ...primaryResult.instructions, ...secondaryResult.instructions]
50186
+ });
49961
50187
  }
49962
50188
 
49963
50189
  // src/services/price/utils/smart-crank.utils.ts
@@ -50625,18 +50851,15 @@ var fetchPythOracleData = async (banks, opts) => {
50625
50851
  bankOraclePriceMap: /* @__PURE__ */ new Map()
50626
50852
  };
50627
50853
  }
50628
- pythStakedCollateralBanks.map((bank) => [
50629
- opts.validatorVoteAccountByBank?.[bank.address.toBase58()] ?? "",
50630
- bank.mint.toBase58()
50631
- ]);
50632
- const priceCoeffByBank = {};
50633
50854
  const combinedPythBanks = [
50634
50855
  ...pythPushBanks,
50856
+ ...pythStakedCollateralBanks,
50635
50857
  ...pythPushKaminosBanks,
50636
50858
  ...driftPythPullBanks,
50637
50859
  ...solendPythPullBanks,
50638
50860
  ...juplendPythPullBanks
50639
50861
  ];
50862
+ const priceCoeffByBank = {};
50640
50863
  const pythOracleKeys = extractPythOracleKeys(combinedPythBanks);
50641
50864
  const uniquePythOracleKeys = Array.from(new Set(pythOracleKeys));
50642
50865
  let oraclePrices;
@@ -51440,6 +51663,78 @@ function computeRemainingCapacity(bank) {
51440
51663
  };
51441
51664
  }
51442
51665
 
51666
+ // src/services/bank/utils/bank-metrics.utils.ts
51667
+ function computeBankTotalDeposits(bank, assetShareValueMultiplier) {
51668
+ const totalAssets = getTotalAssetQuantity(bank).times(
51669
+ assetShareValueMultiplier ?? 1
51670
+ );
51671
+ return nativeToUi(totalAssets, bank.mintDecimals);
51672
+ }
51673
+ function computeBankTotalBorrows(bank) {
51674
+ return nativeToUi(getTotalLiabilityQuantity(bank), bank.mintDecimals);
51675
+ }
51676
+ function computeBankTotalDepositsUsd(bank, oraclePrice, assetShareValueMultiplier) {
51677
+ return computeUsdValue({
51678
+ bank,
51679
+ oraclePrice,
51680
+ quantity: getTotalAssetQuantity(bank),
51681
+ priceBias: 1 /* None */,
51682
+ isWeightedPrice: false,
51683
+ assetShareValueMultiplier
51684
+ }).toNumber();
51685
+ }
51686
+ function computeBankTotalBorrowsUsd(bank, oraclePrice) {
51687
+ return computeUsdValue({
51688
+ bank,
51689
+ oraclePrice,
51690
+ quantity: getTotalLiabilityQuantity(bank),
51691
+ priceBias: 1 /* None */,
51692
+ isWeightedPrice: false
51693
+ }).toNumber();
51694
+ }
51695
+ function computeBankPoolSize(bank, assetShareValueMultiplier) {
51696
+ const totalDeposits = computeBankTotalDeposits(bank, assetShareValueMultiplier);
51697
+ const totalBorrows = computeBankTotalBorrows(bank);
51698
+ const borrowCap = nativeToUi(bank.config.borrowLimit, bank.mintDecimals);
51699
+ return Math.max(0, Math.min(totalDeposits, borrowCap) - totalBorrows);
51700
+ }
51701
+ function computeBankDepositCapRemaining(bank) {
51702
+ const { depositCapacity } = computeRemainingCapacity(bank);
51703
+ return Math.max(0, nativeToUi(depositCapacity, bank.mintDecimals));
51704
+ }
51705
+ function computeBankBorrowCapRemaining(bank) {
51706
+ const { borrowCapacity } = computeRemainingCapacity(bank);
51707
+ return Math.max(0, nativeToUi(borrowCapacity, bank.mintDecimals));
51708
+ }
51709
+ function computeBankSupplyApy(bank) {
51710
+ return aprToApy(computeInterestRates(bank).lendingRate.toNumber());
51711
+ }
51712
+ function computeBankBorrowApy(bank) {
51713
+ return aprToApy(computeInterestRates(bank).borrowingRate.toNumber());
51714
+ }
51715
+ function computeBankMetrics(params) {
51716
+ const { bank, oraclePrice, assetShareValueMultiplier, symbol = "" } = params;
51717
+ return {
51718
+ symbol,
51719
+ totalDeposits: computeBankTotalDeposits(bank, assetShareValueMultiplier),
51720
+ totalBorrows: computeBankTotalBorrows(bank),
51721
+ totalDepositsUsd: computeBankTotalDepositsUsd(
51722
+ bank,
51723
+ oraclePrice,
51724
+ assetShareValueMultiplier
51725
+ ),
51726
+ totalBorrowsUsd: computeBankTotalBorrowsUsd(bank, oraclePrice),
51727
+ utilizationRate: computeUtilizationRate(bank).toNumber(),
51728
+ poolSize: computeBankPoolSize(bank, assetShareValueMultiplier),
51729
+ depositCap: nativeToUi(bank.config.depositLimit, bank.mintDecimals),
51730
+ borrowCap: nativeToUi(bank.config.borrowLimit, bank.mintDecimals),
51731
+ depositCapRemaining: computeBankDepositCapRemaining(bank),
51732
+ borrowCapRemaining: computeBankBorrowCapRemaining(bank),
51733
+ supplyApy: computeBankSupplyApy(bank),
51734
+ borrowApy: computeBankBorrowApy(bank)
51735
+ };
51736
+ }
51737
+
51443
51738
  // src/services/bank/bank.service.ts
51444
51739
  async function freezeBankConfigIx(program, bankAddress, bankConfigOpt) {
51445
51740
  let bankConfigRaw;
@@ -51841,6 +52136,613 @@ function dtoToValidatorStakeGroup(validatorStakeGroupDto) {
51841
52136
  }))
51842
52137
  };
51843
52138
  }
52139
+
52140
+ // src/services/native-stake/utils/metadata.data.ts
52141
+ var STAKED_BANK_METADATA_JSON = [
52142
+ {
52143
+ bankAddress: "8g5qG6PVygcVSXV1cJnjXaD1yhrDwcWAMQCY2wR9VuAf",
52144
+ validatorVoteAccount: "CooLbbZy5Xmdt7DiHPQ3ss2uRXawnTXXVgpMS8E8jDzr",
52145
+ tokenAddress: "BADo3D6nMtGnsAaTv3iEes8mMcq92TuFoBWebFe8kzeA",
52146
+ tokenName: "Cavey Cool",
52147
+ tokenSymbol: "COOL"
52148
+ },
52149
+ {
52150
+ bankAddress: "BuCckNm1djpp3vZVhvh1CrrniirY6sr2hwUmeP5kTcGz",
52151
+ validatorVoteAccount: "mrgn4t2JabSgvGnrCaHXMvz8ocr4F52scsxJnkQMQsQ",
52152
+ tokenAddress: "FUyAyVbYrMfiaN1QEQYFZTuBNzW5EJf3jWzjjymGqKLv",
52153
+ tokenName: "Project 0 Meridian",
52154
+ tokenSymbol: "MERIDIAN"
52155
+ },
52156
+ {
52157
+ bankAddress: "Hco1P3dGRXz3ZGFvMkbDgghZQy47Tp7vp7koSYRvP6nm",
52158
+ validatorVoteAccount: "mrgn6ETrBDM8mjjYN8rbVwFqVwF8z6rtmvGLbdGuVUU",
52159
+ tokenAddress: "A4B5MGQvcZCUqeiUEAB4ckZ2tvH2UmEg31vF7TiERDkH",
52160
+ tokenName: "MRGN 3",
52161
+ tokenSymbol: "MRGN3"
52162
+ },
52163
+ {
52164
+ bankAddress: "EPh2abWP8DusPH8myWnECAAeQUZgAz927aMbmwXt3eRY",
52165
+ validatorVoteAccount: "mrgn2vsZ5EJ8YEfAMNPXmRux7th9cNfBasQ1JJvVwPn",
52166
+ tokenAddress: "6Mt7tBWLUJfDxqCFTsjoRXF9wD55g4Lhs5nAyYp244pX",
52167
+ tokenName: "Project 0 Horizon",
52168
+ tokenSymbol: "HORIZON"
52169
+ },
52170
+ {
52171
+ bankAddress: "6wjAwhnxTMEzHk8NNHVXgkx1jSrb6TX1bC17j3S56FfB",
52172
+ validatorVoteAccount: "3N7s9zXMZ4QqvHQR15t5GNHyqc89KduzMP7423eWiD5g",
52173
+ tokenAddress: "DKPvRV4dxUejjGpr2XwFmzZbbbTD7vx9Jmt1kk43n4d5",
52174
+ tokenName: "Binance",
52175
+ tokenSymbol: "BINANCE"
52176
+ },
52177
+ {
52178
+ bankAddress: "J9tksvZEDSwtNtZ6yxYjWDDkzhPbwDMnihU61NkFG9FE",
52179
+ validatorVoteAccount: "he1iusunGwqrNtafDtLdhsUQDFvo13z9sUa36PauBtk",
52180
+ tokenAddress: "2k79y8CApbU9jAvWhLS2j6uRbaVjpLJTUzstBTho9vGq",
52181
+ tokenName: "Helius",
52182
+ tokenSymbol: "HELIUS"
52183
+ },
52184
+ {
52185
+ bankAddress: "Dfr6Sf44ftecaJaoJMzFQABdkt3CEHfBwut1WyacRzaE",
52186
+ validatorVoteAccount: "SLaYv7tCwetrFGbPCRnqpHswG5qqKino78EYpbGF7xY",
52187
+ tokenAddress: "Vsw4JT33S7bLbhjySMMyrP3JKvTAcNi9WG5Doekrmgg",
52188
+ tokenName: "Solayer",
52189
+ tokenSymbol: "SOLAYER"
52190
+ },
52191
+ {
52192
+ bankAddress: "BZAm4qGscR8gg5bmWrEq6BTofgaZPbg7Fwfa7rFghEXL",
52193
+ validatorVoteAccount: "J1to3PQfXidUUhprQWgdKkQAMWPJAEqSJ7amkBDE9qhF",
52194
+ tokenAddress: "6B8hZSupE5mcACmjzozP6C1DR2uaCCtmrGqcYWC6SBCc",
52195
+ tokenName: "Bonk",
52196
+ tokenSymbol: "BONK"
52197
+ },
52198
+ {
52199
+ bankAddress: "3UrMZ26NRKu2y6c2dPE7gZVHwEmhpwKLcWACg3tjCVEt",
52200
+ validatorVoteAccount: "J2nUHEAgZFRyuJbFjdqPrAa9gyWDuc7hErtDQHPhsYRp",
52201
+ tokenAddress: "9M7oMo4oL6RDPG7WbAX3Zz4dPzbMgpiCzwrQPMwG4Wgq",
52202
+ tokenName: "Phantom",
52203
+ tokenSymbol: "PHANTOM"
52204
+ },
52205
+ {
52206
+ bankAddress: "8c269gkonvATm93nviuYiriCQ829f7ypx3aScYDR1YoQ",
52207
+ validatorVoteAccount: "D3QPJm7BDzzPeRG51YZSEz3LfV7GvFNu9NkcibzURxuj",
52208
+ tokenAddress: "8hXCCQmYFcDhU5Mkuvyixp2Q11sbyQComkceSSh3GY4a",
52209
+ tokenName: "Starke Finance",
52210
+ tokenSymbol: "STARKE"
52211
+ },
52212
+ {
52213
+ bankAddress: "37tiA2NTF6YCt85XzCidPo9ZVpuqkkmfVJCYQ5Yx5Uhs",
52214
+ validatorVoteAccount: "SBLZib4npE7svxFA7AsD3ytdQAfYNb39c8zsU82AA2E",
52215
+ tokenAddress: "96rXgCFy1Er49169XoKHkeLiKC2k4bTy1641q1TVrMm2",
52216
+ tokenName: "SolBlaze Validator",
52217
+ tokenSymbol: "SOLBLAZE"
52218
+ },
52219
+ {
52220
+ bankAddress: "J9trpcrVdFjVNg6VFrdF1XPGgjftQKZhbbWsxertdv9V",
52221
+ validatorVoteAccount: "FACqsS19VScz8oo2YhdMg35EsAy6xsCZ9Y58eJXGv8QJ",
52222
+ tokenAddress: "AH6fxpHS2gtMtJgBy8y8pEAPkqyop2pSugF6REs9NaTp",
52223
+ tokenName: "Lantern",
52224
+ tokenSymbol: "LNTRN"
52225
+ },
52226
+ {
52227
+ bankAddress: "EGTfrYiuWpPPZ4yfY9tCxnK6QMkY7pzVie9DxK772iGe",
52228
+ validatorVoteAccount: "EfnywDKqArxK6N6FS9ctsuzNdxfx3pzfXEQE5EevQ1SV",
52229
+ tokenAddress: "FcXEwHku68ZquqtSj1eSWS1SVWkhAZSyb4usfpiuEJAL",
52230
+ tokenName: "PROJECT SUPER",
52231
+ tokenSymbol: "SUPER"
52232
+ },
52233
+ {
52234
+ bankAddress: "A5e7UTE3g11ZfKgftqRCvxAgcDuFGyeDjMka96zJWSWe",
52235
+ validatorVoteAccount: "3ZUQekqiZoybB57y49eqtvSaoonqDwuNbeqEGwN88JkQ",
52236
+ tokenAddress: "F1XPjtpsEy23Q7po4JkWjp1jkDZcvFYSrqD8TR1YL3EF",
52237
+ tokenName: "Paws",
52238
+ tokenSymbol: "PAWS"
52239
+ },
52240
+ {
52241
+ bankAddress: "91jkdp4cF8vCDhjwude3SGSGrmVWFk5vTAtR6fsGVAfy",
52242
+ validatorVoteAccount: "gangtRyGPTvYWb8K3xS2feJQaCks4iJ7rytFUPtVqSY",
52243
+ tokenAddress: "6ZS7ZVDw91BVAC8gsz3SZBSeVeF2GtXtL2BHK31Kvyjm",
52244
+ tokenName: "Lotus Validator",
52245
+ tokenSymbol: "LOTUS"
52246
+ },
52247
+ {
52248
+ bankAddress: "72BS34HkCgq8RWQR7kuVVmiJMtKqSxG4CHX6ZXpSCwg7",
52249
+ validatorVoteAccount: "oRAnGeU5h8h2UkvbfnE5cjXnnAa4rBoaxmS4kbFymSe",
52250
+ tokenAddress: "9yF8pXctzicum2P73uuk4Dhqf2MVz6tzRAe8THGXCJcp",
52251
+ tokenName: "Orangefin Ventures",
52252
+ tokenSymbol: "ORANGEFIN"
52253
+ },
52254
+ {
52255
+ bankAddress: "8F4DsU3NMFunUxBZkWrpYR8zwhAfoAt7QuiEPMtyhWvX",
52256
+ validatorVoteAccount: "3xjfK9C9YNcta8MvK1US4sQ3bc6DEjoJoR3qLExGf9xE",
52257
+ tokenAddress: "Akib1NYJzzh9HkiDH41S2LUefUmR1bKsk65xgqUcW5C5",
52258
+ tokenName: "pico\u{1F644}.sol",
52259
+ tokenSymbol: "PICO"
52260
+ },
52261
+ {
52262
+ bankAddress: "GdtggomQth6cxuYPdiVhBbcX7VC9rnDDwLMfxipxE2Po",
52263
+ validatorVoteAccount: "oPaLTmyvoUhW26QCMwLA5JNUeBYy72PDpFoXQF8SeX4",
52264
+ tokenAddress: "C71A3W7g5XALUNwTDWTwHX3qhfypaYZ41aNZjBpcaC9D",
52265
+ tokenName: "Temporal Opal",
52266
+ tokenSymbol: "OPAL"
52267
+ },
52268
+ {
52269
+ bankAddress: "5sJCKePwAhyD3mzrzLRDM2PkFMc85nnvvarxHLsvWvpg",
52270
+ validatorVoteAccount: "9jYFwBfbjYmvasFbJyES9apLJDTkwtbgSDRWanHEvcRw",
52271
+ tokenAddress: "Hj69K1WbnfZFipLbrzdxgGhDqCR47q48bN5nUHt6xQZo",
52272
+ tokenName: "WATCHTOWER",
52273
+ tokenSymbol: "WATCHTOWER"
52274
+ },
52275
+ {
52276
+ bankAddress: "3F3QXT3BtkegaBfFjn2odKLurFYLHJHJ99xKV2TRTvrk",
52277
+ validatorVoteAccount: "6JfBwvcz5QUKQJ37BMKTLrf968DDJBtwoZLw19aHwFtQ",
52278
+ tokenAddress: "8FqX86cQofBHReetZgxrxxvzN4iqMVsj2hbiv7pj2h73",
52279
+ tokenName: "Spectrum Staking",
52280
+ tokenSymbol: "SPECTRUM"
52281
+ },
52282
+ {
52283
+ bankAddress: "CFmvdtEPQJPVqS1QRkeRcdQm2itAPk6k8hSJbmt88Sjc",
52284
+ validatorVoteAccount: "Haz7b47sZBpxh9SwggGndN3fAyNQ1S949BPdxWXS3ab6",
52285
+ tokenAddress: "38ZUTefZnKSUJU3wxpUe3xpiw2j5WQPnmzSTNbS1JqLA",
52286
+ tokenName: "Temporal Emerald",
52287
+ tokenSymbol: "EMERALD"
52288
+ },
52289
+ {
52290
+ bankAddress: "CmBDHSVuodmUnanbBVFvY9cauLeosbdFQn9bJANMVYUG",
52291
+ validatorVoteAccount: "mintrNtxN3PhAB45Pt41XqyKghTTpqcoBkQTZqh96iR",
52292
+ tokenAddress: "GxGmv7s7s2co3pLZukns946fr5zmR8c5buWRD9prGd6v",
52293
+ tokenName: "Hanabi Staking",
52294
+ tokenSymbol: "haSOLmrgn"
52295
+ },
52296
+ {
52297
+ bankAddress: "7bLfrb4fWVYkVpZ9rg7dBUwKRAqLyiivCW4ahMMGcKyS",
52298
+ validatorVoteAccount: "76DafWkJ6pGK2hoD41HjrM4xTBhfKqrDYDazv13n5ir1",
52299
+ tokenAddress: "GT7n9uZbYzHv52YqDBowtZ5ZVW91umaBQTNPFQNeLUpR",
52300
+ tokenName: "Solana Japan Validator",
52301
+ tokenSymbol: "SolJAPAn"
52302
+ },
52303
+ {
52304
+ bankAddress: "6q5DB86DhCBQt5bqzZwgopV8EA96aCnngu5ebR1ooDFq",
52305
+ validatorVoteAccount: "Cue647T8jgwpRSDUb8ttTYx7NiEfJCRZNiiw1qmchXsG",
52306
+ tokenAddress: "EAR6LenhNstHxR9289rWakm82WgLJYvHD7NawfXtuyUx",
52307
+ tokenName: "KIWAMI",
52308
+ tokenSymbol: "KIWAMI"
52309
+ },
52310
+ {
52311
+ bankAddress: "GLSCJ39N82Xo21621jMheinvjQLrBrkG7gzo2C5L1y6y",
52312
+ validatorVoteAccount: "7emL18Bnve7wbYE9Az7vYJjikxN6YPU81igf6rVU5FN8",
52313
+ tokenAddress: "EQuMUgLZArKwWUk6uGPmTGYUgNbfgJrbBaNR7CQyZ5uf",
52314
+ tokenName: "Temporal Topaz",
52315
+ tokenSymbol: "TOPAZ"
52316
+ },
52317
+ {
52318
+ bankAddress: "4irzCCsU53ffh9XB7NxGzbbHjvSR7FTfPbn6KoXkt7kX",
52319
+ validatorVoteAccount: "2iWXwF2Q5W6o7yntV2mkbxncB4rYHnX61y3NU8a8EFMJ",
52320
+ tokenAddress: "14Pets6QpE9iXKkXg8Ri4GcDazRMfWR3guM6LZXnFChc",
52321
+ tokenName: "Bull Moose SOL",
52322
+ tokenSymbol: "bmsSOL"
52323
+ },
52324
+ {
52325
+ bankAddress: "C96do7nkEaaFjHq8jHzPpyPTdJSea5xEGwxDzDSepCzf",
52326
+ validatorVoteAccount: "voteRnv6PBzmiGP8NicWtQiqEJTwKKq2SxtqtdLUJjd",
52327
+ tokenAddress: "3YEDiJ4r4xRGNhq6nudRnkwrdKHG7PAtDim24CjTMtBH",
52328
+ tokenName: "diman",
52329
+ tokenSymbol: "DIMAN"
52330
+ },
52331
+ {
52332
+ bankAddress: "9dZiyG51FBR4BWpAs69XbDpr7GfVAEB1ZB89v38maV36",
52333
+ validatorVoteAccount: "Simpj3KyRQmpRkXuBvCQFS7DBBG6vqw93SkZb9UD1hp",
52334
+ tokenAddress: "77YLpVLQXr2KU66GM2JykbT9g5du7LarWgehbWD3CJaB",
52335
+ tokenName: "SIMPDIGIT",
52336
+ tokenSymbol: "SIMPDIGIT"
52337
+ },
52338
+ {
52339
+ bankAddress: "2foqT8wWzWRduyV37uRdj81DijkNMKzYD3D6JPfir7La",
52340
+ validatorVoteAccount: "48oxpSHQkM4sdXUY9NQ8KnEtebzZbyk8uUT7JRdVQNuf",
52341
+ tokenAddress: "42m7Ygk5VxREdKfcFrsH1HnuoqCke8BcVcxNeywMCfp2",
52342
+ tokenName: "Infinite Lux",
52343
+ tokenSymbol: "LUX"
52344
+ },
52345
+ {
52346
+ bankAddress: "FsdWEJzHXkUXejWnb7c1p9UJtF69hVWQNNoakjoXyRCJ",
52347
+ validatorVoteAccount: "4AUED4uj6nSTuANzaAUnGBPJQRmhpDYDwoWJNkoUUBBW",
52348
+ tokenAddress: "CiyQTfHJ9PbTwC7TGf4pXZk8szcWGJ8TeFhhCuUwybqi",
52349
+ tokenName: "Anagram",
52350
+ tokenSymbol: "ANAGRAM"
52351
+ },
52352
+ {
52353
+ bankAddress: "2hs1pHAzDWGqnn1d8VQkc8bZRfQ45grYvzfau8dnWFUk",
52354
+ validatorVoteAccount: "2NxEEbhqqj1Qptq5LXLbDTP5tLa9f7PqkU8zNgxbGU9P",
52355
+ tokenAddress: "9yQLxEzusZ7QiZNafDNdzbEaTCPuJToGjMhLRJtZbgsd",
52356
+ tokenName: "NANSEN",
52357
+ tokenSymbol: "NANSEN"
52358
+ },
52359
+ {
52360
+ bankAddress: "FCi8unSVCwJd3QkrhTtv6LTTjw1c4zV65D5cG5N1rAG6",
52361
+ validatorVoteAccount: "Va1idkzkB6LEmVFmxWbWU8Ao9qehC62Tjmf68L3uYKj",
52362
+ tokenAddress: "AExKb8oJ6mGPYJUyfiX49DMMi226h2AnWeG1G6neQBEz",
52363
+ tokenName: "VALIDATOR",
52364
+ tokenSymbol: "VALID"
52365
+ },
52366
+ {
52367
+ bankAddress: "HzS8RqaQ5syk6EHbVi7h9rFYN48PpxykUXEs6w9wNfNP",
52368
+ validatorVoteAccount: "sTach38ebT8jnGH8i2D1g8NDAS6An19whVMnSSWPXt4",
52369
+ tokenAddress: "AFDVYBqxADagPfN9DdbrNrf9zZqugub7CV4kUJEUrK6J",
52370
+ tokenName: "Stache Node",
52371
+ tokenSymbol: "STACHE"
52372
+ },
52373
+ {
52374
+ bankAddress: "9Hs4E6ACNw6Hmwjvm1duXzbaWmvXxSxN11agw4updEn1",
52375
+ validatorVoteAccount: "EtMSc3MvcDXUr6ChK5GxyFVwTxYA3zqP5XzjE9jwKvSV",
52376
+ tokenAddress: "ENKFyZQZHzNNSxcKYoaVsNLi2xoGPoStZH4A9xxezjbC",
52377
+ tokenName: "Mad Lads CN",
52378
+ tokenSymbol: "MadLadsCN"
52379
+ },
52380
+ {
52381
+ bankAddress: "4watsWcjTBAwsrZpArwQbnNX4bQ1yeHBxgdbrGT4eMu9",
52382
+ validatorVoteAccount: "EARNynHRWg6GfyJCmrrizcZxARB3HVzcaasvNa8kBS72",
52383
+ tokenAddress: "8fhkWcm2n28JuadzY7mRR8FFDZZfnaPfWgw7pLNVZCbE",
52384
+ tokenName: "Solana Compass Stake",
52385
+ tokenSymbol: "compaStake"
52386
+ },
52387
+ {
52388
+ bankAddress: "9d7MTvcz1VMB1rK6H73quMxkR26dLPz5HDaac2eGRjQx",
52389
+ validatorVoteAccount: "nymsndUdAZyUPpWYz5VEg8Ghj9cFvwTRgciLogpmYaQ",
52390
+ tokenAddress: "FWFeaqpkgDr3ejVSY3HjiUmUg3u9fcr5d66HvimnDLWE",
52391
+ tokenName: "Hypo Nyms",
52392
+ tokenSymbol: "NYMS"
52393
+ },
52394
+ {
52395
+ bankAddress: "6V4vCK3n3JVncfpS16mW8ceLoNPatvu61pKxFmWx8adi",
52396
+ validatorVoteAccount: "BT8LZUvQVwFHRGw2Dwv7UeqDUq7btfjegLpuz5bwgziD",
52397
+ tokenAddress: "9YRS7Stf9dVibTT1M4uVEAuRMcoS4MH1QxqXy9Lssrab",
52398
+ tokenName: "private",
52399
+ tokenSymbol: "private"
52400
+ },
52401
+ {
52402
+ bankAddress: "CK8qRAcmvkDXaqX2S5GkgTCZT5pCz34me1neQhpJYe1Z",
52403
+ validatorVoteAccount: "Ac1beBKixfNdrTAac7GRaTsJTxLyvgGvJjvy4qQfvyfc",
52404
+ tokenAddress: "DLTAbTL5NXhbqX6LX3ie3tf52pdtGpxe2DrZUr1RhgY6",
52405
+ tokenName: "Stronghold",
52406
+ tokenSymbol: "Stronghold"
52407
+ },
52408
+ {
52409
+ bankAddress: "H6CT1aiCgSNw9S6aq38npEhdoN2UPhSKe8Lj9fQqqjuu",
52410
+ validatorVoteAccount: "FREEL1BCzmPpNneC7FHCtBqzeWYrHRbtisFvi4N8XUP9",
52411
+ tokenAddress: "AKFuMoM5rjSpQSL4p6TBoc7D4dmEem9QrHhuSDCBYyZ8",
52412
+ tokenName: "Ross",
52413
+ tokenSymbol: "Ross"
52414
+ },
52415
+ {
52416
+ bankAddress: "G46aHuakgStymbE2WsLbja61mH5UXBPdSdpwf6Ci3saG",
52417
+ validatorVoteAccount: "mnvkHm47ZmRKoSWuQZAfXLRiDPiKCq8PWkMWrp1Wwqe",
52418
+ tokenAddress: "Cq9S5UB9BviPn5yoGkEDk3m7neQag4KJnhPWGyuev9W8",
52419
+ tokenName: "gripto staked sol",
52420
+ tokenSymbol: "GRIPTO"
52421
+ },
52422
+ {
52423
+ bankAddress: "75UmeEMdqVnGn3JHx8yVZEn7viybJ73XYSjhYCYfyhp2",
52424
+ validatorVoteAccount: "4m1PbxzwLdUnEwog3T9UKxgjktgriHgE1CfAhMqDw7Xx",
52425
+ tokenAddress: "432SogPNunjZMneDV6goZ8ZcCQz282GxoSJ4rwqx95pT",
52426
+ tokenName: "kumasol",
52427
+ tokenSymbol: "kumasol"
52428
+ },
52429
+ {
52430
+ bankAddress: "3zk6EmXANYQK12bwy9dySRAM4cT2vT5cDcAB79j8G33B",
52431
+ validatorVoteAccount: "HvsD9L5t62MGv3QBD2K7xjkipGYr9UZN7BtsW8NuSPpg",
52432
+ tokenAddress: "5vmwd6JHDCmX9W2XT1n2QpvYGA2kk4Xf7qWSayDU6caT",
52433
+ tokenName: "ArgenTerraSOL",
52434
+ tokenSymbol: "atSOL"
52435
+ },
52436
+ {
52437
+ bankAddress: "4C2vPweGNpiE6kTEbYvcbUBHNWxrn4ErQYaqWm5zDexx",
52438
+ validatorVoteAccount: "FnAPJkzf19s87sm24Qhv6bHZMZvZ43gjNUBRgjwXpD4v",
52439
+ tokenAddress: "6q4kVnwUpkE3i7W32dqaX6V12pbsrCnMqZ7TWz9yp1m5",
52440
+ tokenName: "BLOCKPORT",
52441
+ tokenSymbol: "BPT"
52442
+ },
52443
+ {
52444
+ bankAddress: "E5hZu5QQ1pRmGvyS4JHGXVQwzdUPaYM4yEiNKr64YzyG",
52445
+ validatorVoteAccount: "nfGcSJkP35SkPa5475iBChmq1UNcj7JE1uQHrrasymm",
52446
+ tokenAddress: "AQpQoJ3tJKGH9Yn8GSzoUsVcHPJjj3xYfQFp9XVr74F6",
52447
+ tokenName: "Test01",
52448
+ tokenSymbol: "TEST01"
52449
+ },
52450
+ {
52451
+ bankAddress: "3VCkXWAmE5DSwYRpqGFnkUz7vvD2RKbhFvrhzLuE8msu",
52452
+ validatorVoteAccount: "abc1zP7ihWsgQW8z5YmfQNqMckJE5Dfx8fwUNMNVNkY",
52453
+ tokenAddress: "BNisp3omkr6Rg5nHESWafjUbeCpGPy6MYq1iRJRgSAsh",
52454
+ tokenName: "ALGO STAKE",
52455
+ tokenSymbol: "ALGO"
52456
+ },
52457
+ {
52458
+ bankAddress: "7BHHMWw3P1AyebLhX9A8wnDeeGy8jgFXqqHuEZt7BVmW",
52459
+ validatorVoteAccount: "8Pep3GmYiijRALqrMKpez92cxvF4YPTzoZg83uXh14pW",
52460
+ tokenAddress: "zBH13AzXYCqHZKS8NGa4KR8zQhWiyvFdDY15nmfrHgS",
52461
+ tokenName: "8Pep",
52462
+ tokenSymbol: "8Pep"
52463
+ },
52464
+ {
52465
+ bankAddress: "9QWUatjtJtc98yts4ufWnmNeaWQRmaaLjFwbK3iMdS47",
52466
+ validatorVoteAccount: "CatzoSMUkTRidT5DwBxAC2pEtnwMBTpkCepHkFgZDiqb",
52467
+ tokenAddress: "98B1NMLYaNJQNxiQGr53vbjNFMNTYFmDqoCgj7qD9Vhm",
52468
+ tokenName: "JUPITER ",
52469
+ tokenSymbol: "JUPITER"
52470
+ },
52471
+ {
52472
+ bankAddress: "5q1wJkGqqRh6mSBtjG8sfjBsgJSGdA2QoXTWv4UQbHGk",
52473
+ validatorVoteAccount: "shft7Fry1js37Hm9wq4dfwcZSp2DyKszeWMvEpjYCQ1",
52474
+ tokenAddress: "C1KwBJZNwUaodUcP5kXqD52NCuZzThNAG2cw3vt5H6iE",
52475
+ tokenName: "BLUESHIFT",
52476
+ tokenSymbol: "SHIFT"
52477
+ },
52478
+ {
52479
+ bankAddress: "FZaHyfg9hmNMKpfUJ474wNKPaPdXMpnJouasKnndECiZ",
52480
+ validatorVoteAccount: "DdCNGDpP7qMgoAy6paFzhhak2EeyCZcgjH7ak5u5v28m",
52481
+ tokenAddress: "PhxXAYTkFZS23ZWvFcz6H6Uq4VnVBMa6hniiAyudjaW",
52482
+ tokenName: "KILN1",
52483
+ tokenSymbol: "KILN1"
52484
+ },
52485
+ {
52486
+ bankAddress: "5CBocarwfJeWGNozGemWktRYSz6kPikRPdfH8ZHSFrsg",
52487
+ validatorVoteAccount: "8zuMRTXThoPTTPLLvaiKiJshLLCqGMt9BdRjjCL19xBc",
52488
+ tokenAddress: "BDsEuxFWznAP5cUCannnfjyjDtTwqN57CkGfDbjx2nNZ",
52489
+ tokenName: "DawnLabs",
52490
+ tokenSymbol: "DawnLabs"
52491
+ },
52492
+ {
52493
+ bankAddress: "9ivswG37QpCUmkPkLMpRZT7PMyP64V9dDpZdteM254ec",
52494
+ validatorVoteAccount: "gaToR246dheK1DGAMEqxMdBJZwU4qFyt7DzhSwAHFWF",
52495
+ tokenAddress: "TjA2rtxoUFzyPVAw35VQGEQnNXiwcmNjKSk29nmkq1P",
52496
+ tokenName: "Valigator Open",
52497
+ tokenSymbol: "Valigator"
52498
+ }
52499
+ ];
52500
+
52501
+ // src/services/native-stake/utils/metadata.utils.ts
52502
+ var _metadataMap = null;
52503
+ var _voteAccountByBank = null;
52504
+ function getStakedBankMetadataMap() {
52505
+ if (!_metadataMap) {
52506
+ _metadataMap = /* @__PURE__ */ new Map();
52507
+ for (const entry of STAKED_BANK_METADATA_JSON) {
52508
+ _metadataMap.set(entry.bankAddress, entry);
52509
+ }
52510
+ }
52511
+ return _metadataMap;
52512
+ }
52513
+ function getValidatorVoteAccountByBank() {
52514
+ if (!_voteAccountByBank) {
52515
+ _voteAccountByBank = {};
52516
+ for (const entry of STAKED_BANK_METADATA_JSON) {
52517
+ _voteAccountByBank[entry.bankAddress] = entry.validatorVoteAccount;
52518
+ }
52519
+ }
52520
+ return _voteAccountByBank;
52521
+ }
52522
+ async function computeStakedBankMultipliers(stakedBanks, connection) {
52523
+ const multiplierByBank = /* @__PURE__ */ new Map();
52524
+ if (stakedBanks.length === 0) {
52525
+ return multiplierByBank;
52526
+ }
52527
+ const metadataMap = getStakedBankMetadataMap();
52528
+ const stakedBankAddresses = [];
52529
+ const poolStakeAddresses = [];
52530
+ const lstMintAddresses = [];
52531
+ for (const bank of stakedBanks) {
52532
+ const metadata = metadataMap.get(bank.address.toBase58());
52533
+ if (!metadata) {
52534
+ multiplierByBank.set(bank.address.toBase58(), new BigNumber3(1));
52535
+ continue;
52536
+ }
52537
+ const pool = findPoolAddress(new PublicKey(metadata.validatorVoteAccount));
52538
+ stakedBankAddresses.push(bank.address.toBase58());
52539
+ poolStakeAddresses.push(findPoolStakeAddress(pool));
52540
+ lstMintAddresses.push(findPoolMintAddress(pool));
52541
+ }
52542
+ if (stakedBankAddresses.length === 0) {
52543
+ return multiplierByBank;
52544
+ }
52545
+ const allAddresses = [
52546
+ ...poolStakeAddresses.map((a) => a.toBase58()),
52547
+ ...lstMintAddresses.map((a) => a.toBase58())
52548
+ ];
52549
+ const accountInfos = await chunkedGetRawMultipleAccountInfoOrdered(connection, allAddresses);
52550
+ const poolStakeInfos = accountInfos.slice(0, poolStakeAddresses.length);
52551
+ const lstMintInfos = accountInfos.slice(poolStakeAddresses.length);
52552
+ for (let i = 0; i < stakedBankAddresses.length; i++) {
52553
+ const bankAddr = stakedBankAddresses[i];
52554
+ const poolStakeInfo = poolStakeInfos[i];
52555
+ const lstMintInfo = lstMintInfos[i];
52556
+ if (!poolStakeInfo || !lstMintInfo) {
52557
+ multiplierByBank.set(bankAddr, new BigNumber3(1));
52558
+ continue;
52559
+ }
52560
+ const stakeLamports = poolStakeInfo.lamports;
52561
+ const supplyBuffer = lstMintInfo.data.slice(36, 44);
52562
+ const lstMintSupply = Number(Buffer.from(supplyBuffer).readBigUInt64LE(0));
52563
+ if (lstMintSupply === 0) {
52564
+ multiplierByBank.set(bankAddr, new BigNumber3(1));
52565
+ continue;
52566
+ }
52567
+ const adjustedStake = Math.max(stakeLamports - LAMPORTS_PER_SOL, 0);
52568
+ const multiplier = new BigNumber3(adjustedStake).dividedBy(lstMintSupply);
52569
+ multiplierByBank.set(bankAddr, multiplier);
52570
+ }
52571
+ return multiplierByBank;
52572
+ }
52573
+ var SYSVAR_CLOCK_ID2 = new PublicKey("SysvarC1ock11111111111111111111111111111111");
52574
+ async function makeMintStakedLstIx(params) {
52575
+ const { amount, authority, stakeAccountPk, validator, connection } = params;
52576
+ const pool = findPoolAddress(validator);
52577
+ const lstMint = findPoolMintAddress(pool);
52578
+ const poolStakeAuth = findPoolStakeAuthorityAddress(pool);
52579
+ const lstAta = getAssociatedTokenAddressSync(lstMint, authority);
52580
+ const [lstAccInfo, stakeAccInfoParsed, rentExemptReserve] = await Promise.all([
52581
+ connection.getAccountInfo(lstAta),
52582
+ connection.getParsedAccountInfo(stakeAccountPk),
52583
+ connection.getMinimumBalanceForRentExemption(StakeProgram.space)
52584
+ ]);
52585
+ const stakeAccParsed = stakeAccInfoParsed?.value?.data;
52586
+ const amountLamports = Math.round(Number(amount) * LAMPORTS_PER_SOL);
52587
+ const stakeAccLamports = Number(stakeAccParsed?.parsed?.info?.stake?.delegation?.stake ?? 0);
52588
+ const isFullStake = amountLamports >= stakeAccLamports;
52589
+ const instructions2 = [];
52590
+ const signers = [];
52591
+ if (!lstAccInfo) {
52592
+ instructions2.push(
52593
+ createAssociatedTokenAccountInstruction(authority, lstAta, authority, lstMint)
52594
+ );
52595
+ }
52596
+ let targetStakePubkey;
52597
+ if (!isFullStake) {
52598
+ const splitStakeAccount = Keypair.generate();
52599
+ signers.push(splitStakeAccount);
52600
+ targetStakePubkey = splitStakeAccount.publicKey;
52601
+ instructions2.push(
52602
+ ...StakeProgram.split(
52603
+ {
52604
+ stakePubkey: stakeAccountPk,
52605
+ authorizedPubkey: authority,
52606
+ splitStakePubkey: splitStakeAccount.publicKey,
52607
+ lamports: amountLamports
52608
+ },
52609
+ rentExemptReserve
52610
+ ).instructions
52611
+ );
52612
+ } else {
52613
+ targetStakePubkey = stakeAccountPk;
52614
+ }
52615
+ const [authorizeStakerIx, authorizeWithdrawIx] = await Promise.all([
52616
+ StakeProgram.authorize({
52617
+ stakePubkey: targetStakePubkey,
52618
+ authorizedPubkey: authority,
52619
+ newAuthorizedPubkey: poolStakeAuth,
52620
+ stakeAuthorizationType: StakeAuthorizationLayout.Staker
52621
+ }).instructions,
52622
+ StakeProgram.authorize({
52623
+ stakePubkey: targetStakePubkey,
52624
+ authorizedPubkey: authority,
52625
+ newAuthorizedPubkey: poolStakeAuth,
52626
+ stakeAuthorizationType: StakeAuthorizationLayout.Withdrawer
52627
+ }).instructions
52628
+ ]);
52629
+ [authorizeStakerIx[0], authorizeWithdrawIx[0]].forEach((ix) => {
52630
+ if (ix) {
52631
+ ix.keys = ix.keys.map((key) => ({
52632
+ ...key,
52633
+ isWritable: key.pubkey.equals(SYSVAR_CLOCK_ID2) ? false : key.isWritable
52634
+ }));
52635
+ }
52636
+ });
52637
+ instructions2.push(...authorizeStakerIx, ...authorizeWithdrawIx);
52638
+ const depositStakeIx = await SinglePoolInstruction.depositStake(
52639
+ pool,
52640
+ targetStakePubkey,
52641
+ lstAta,
52642
+ authority
52643
+ );
52644
+ instructions2.push(depositStakeIx);
52645
+ return { instructions: instructions2, keys: signers };
52646
+ }
52647
+ async function makeMintStakedLstTx(params) {
52648
+ const { connection, luts, blockhash: providedBlockhash } = params;
52649
+ const { instructions: instructions2, keys } = await makeMintStakedLstIx(params);
52650
+ const blockhash = providedBlockhash ?? (await connection.getLatestBlockhash("confirmed")).blockhash;
52651
+ const message = new TransactionMessage({
52652
+ payerKey: params.authority,
52653
+ recentBlockhash: blockhash,
52654
+ instructions: instructions2
52655
+ }).compileToV0Message(luts);
52656
+ const tx = new VersionedTransaction(message);
52657
+ return addTransactionMetadata(tx, {
52658
+ signers: keys,
52659
+ addressLookupTables: luts,
52660
+ type: "DEPOSIT_STAKE" /* DEPOSIT_STAKE */
52661
+ });
52662
+ }
52663
+ async function makeRedeemStakedLstIx(params) {
52664
+ const { amount, authority, validator, connection } = params;
52665
+ const pool = findPoolAddress(validator);
52666
+ const lstMint = findPoolMintAddress(pool);
52667
+ const mintAuthority = findPoolMintAuthorityAddress(pool);
52668
+ const lstAta = getAssociatedTokenAddressSync(lstMint, authority);
52669
+ const rentExemption = await connection.getMinimumBalanceForRentExemption(
52670
+ StakeProgram.space
52671
+ );
52672
+ const stakeAmount = new BigNumber3(new BigNumber3(amount).toString());
52673
+ const instructions2 = [];
52674
+ const signers = [];
52675
+ const stakeAccount = Keypair.generate();
52676
+ signers.push(stakeAccount);
52677
+ instructions2.push(
52678
+ SystemProgram.createAccount({
52679
+ fromPubkey: authority,
52680
+ newAccountPubkey: stakeAccount.publicKey,
52681
+ lamports: rentExemption,
52682
+ space: StakeProgram.space,
52683
+ programId: StakeProgram.programId
52684
+ })
52685
+ );
52686
+ instructions2.push(
52687
+ createApproveInstruction(
52688
+ lstAta,
52689
+ mintAuthority,
52690
+ authority,
52691
+ BigInt(stakeAmount.multipliedBy(1e9).toFixed(0))
52692
+ )
52693
+ );
52694
+ const withdrawStakeIx = await SinglePoolInstruction.withdrawStake(
52695
+ pool,
52696
+ stakeAccount.publicKey,
52697
+ authority,
52698
+ lstAta,
52699
+ stakeAmount
52700
+ );
52701
+ instructions2.push(withdrawStakeIx);
52702
+ return { instructions: instructions2, keys: signers };
52703
+ }
52704
+ async function makeRedeemStakedLstTx(params) {
52705
+ const { connection, luts, blockhash: providedBlockhash } = params;
52706
+ const { instructions: instructions2, keys } = await makeRedeemStakedLstIx(params);
52707
+ const blockhash = providedBlockhash ?? (await connection.getLatestBlockhash("confirmed")).blockhash;
52708
+ const message = new TransactionMessage({
52709
+ payerKey: params.authority,
52710
+ recentBlockhash: blockhash,
52711
+ instructions: instructions2
52712
+ }).compileToV0Message(luts);
52713
+ const tx = new VersionedTransaction(message);
52714
+ return addTransactionMetadata(tx, {
52715
+ signers: keys,
52716
+ addressLookupTables: luts,
52717
+ type: "WITHDRAW_STAKE" /* WITHDRAW_STAKE */
52718
+ });
52719
+ }
52720
+ async function makeMergeStakeAccountsTx(params) {
52721
+ const {
52722
+ authority,
52723
+ sourceStakeAccount,
52724
+ destinationStakeAccount,
52725
+ connection,
52726
+ luts,
52727
+ blockhash: providedBlockhash
52728
+ } = params;
52729
+ const mergeIx = StakeProgram.merge({
52730
+ stakePubkey: destinationStakeAccount,
52731
+ sourceStakePubKey: sourceStakeAccount,
52732
+ authorizedPubkey: authority
52733
+ }).instructions;
52734
+ const blockhash = providedBlockhash ?? (await connection.getLatestBlockhash("confirmed")).blockhash;
52735
+ const message = new TransactionMessage({
52736
+ payerKey: authority,
52737
+ recentBlockhash: blockhash,
52738
+ instructions: mergeIx
52739
+ }).compileToV0Message(luts);
52740
+ const tx = new VersionedTransaction(message);
52741
+ return addTransactionMetadata(tx, {
52742
+ addressLookupTables: luts,
52743
+ type: "MERGE_STAKE_ACCOUNTS" /* MERGE_STAKE_ACCOUNTS */
52744
+ });
52745
+ }
51844
52746
  async function getKaminoMetadata(options) {
51845
52747
  const kaminoBanks = options.banks.filter((b) => b.config.assetTag === 3 /* KAMINO */);
51846
52748
  const DEFAULT_PUBKEY = PublicKey.default;
@@ -54538,7 +55440,6 @@ var Project0Client = class _Project0Client {
54538
55440
  assetShareMultiplierByBank.set(bank.address.toBase58(), new BigNumber3(1));
54539
55441
  break;
54540
55442
  case 2 /* STAKED */:
54541
- assetShareMultiplierByBank.set(bank.address.toBase58(), new BigNumber3(1));
54542
55443
  break;
54543
55444
  case 0 /* DEFAULT */:
54544
55445
  case 1 /* SOL */:
@@ -54547,6 +55448,11 @@ var Project0Client = class _Project0Client {
54547
55448
  break;
54548
55449
  }
54549
55450
  });
55451
+ const stakedMultipliers = await computeStakedBankMultipliers(
55452
+ banksArray.filter((b) => b.config.assetTag === 2 /* STAKED */),
55453
+ connection
55454
+ );
55455
+ stakedMultipliers.forEach((v, k) => assetShareMultiplierByBank.set(k, v));
54550
55456
  const emodePairs = getEmodePairs(banksArray);
54551
55457
  return new _Project0Client(
54552
55458
  program,
@@ -54588,6 +55494,6 @@ var EmodeSettings = class _EmodeSettings {
54588
55494
  }
54589
55495
  };
54590
55496
 
54591
- export { ADDRESS_LOOKUP_TABLE_FOR_GROUP, ADDRESS_LOOKUP_TABLE_FOR_SWAP, AccountFlags, AccountType, AssetTag, BUNDLE_TX_SIZE, Balance, Bank, BankConfig, BankConfigFlag, BankVaultType, DEFAULT_ORACLE_MAX_AGE, DISABLED_FLAG, EMPTY_HEALTH_CACHE, EmodeEntryFlags, EmodeFlags, EmodeImpactStatus, EmodeSettings, EmodeTag, FLASHLOAN_ENABLED_FLAG, HOURS_PER_YEAR, HealthCache, HealthCacheFlags, HealthCacheSimulationError, HealthCacheStatus, JUPITER_V6_PROGRAM, JUP_SWAP_LUT_PROGRAM_AUTHORITY_INDEX, LST_MINT, MARGINFI_IDL, MARGINFI_PROGRAM, MARGINFI_PROGRAM_STAGING, MARGINFI_PROGRAM_STAGING_ALT, MARGINFI_SPONSORED_SHARD_ID, MAX_ACCOUNT_LOCKS, MAX_CONFIDENCE_INTERVAL_RATIO, MAX_TX_SIZE, MAX_U64, MPL_METADATA_PROGRAM_ID, MarginRequirementType, MarginfiAccount, MarginfiAccountWrapper, MarginfiGroup, OperationalState, OracleSetup, PDA_BANK_EMISSIONS_AUTH_SEED, PDA_BANK_EMISSIONS_VAULT_SEED, PDA_BANK_FEE_STATE_SEED, PDA_BANK_FEE_VAULT_AUTH_SEED, PDA_BANK_FEE_VAULT_SEED, PDA_BANK_INSURANCE_VAULT_AUTH_SEED, PDA_BANK_INSURANCE_VAULT_SEED, PDA_BANK_LIQUIDITY_VAULT_AUTH_SEED, PDA_BANK_LIQUIDITY_VAULT_SEED, PDA_MARGINFI_ACCOUNT_SEED, PRIORITY_TX_SIZE, PYTH_PRICE_CONF_INTERVALS, PYTH_PUSH_ORACLE_ID, PYTH_SPONSORED_SHARD_ID, PriceBias, Project0Client, RiskTier, SINGLE_POOL_PROGRAM_ID, STAKE_CONFIG_ID, STAKE_PROGRAM_ID, SWB_PRICE_CONF_INTERVALS, SYSTEM_PROGRAM_ID, SYSVAR_CLOCK_ID, SYSVAR_RENT_ID, SYSVAR_STAKE_HISTORY_ID, SwapProvider, TRANSFER_ACCOUNT_AUTHORITY_FLAG, TransactionArenaKeyMap, TransactionBuildingError, TransactionBuildingErrorCode, TransactionConfigMap, TransactionType, USDC_DECIMALS, USDC_MINT, WSOL_MINT, ZERO_ORACLE_KEY, accountFlagToBN, addOracleToBanksIx, addTransactionMetadata, adjustPriceComponent, aprToApy, apyToApr, balanceToDto, bankConfigRawToDto, bankConfigToBankConfigRaw, bankMetadataMapToDto, bankMetadataToDto, bankRawToDto, bigNumberToWrappedI80F48, bpsToPercentile, calculateApyFromInterest, calculateInterestFromApy, capConfidenceInterval, categorizePythBanks, checkBatchOracleCrankability, checkMultipleOraclesCrankability, chunkedGetRawMultipleAccountInfoOrdered, chunkedGetRawMultipleAccountInfoOrderedWithNulls, chunkedGetRawMultipleAccountInfos, compileFlashloanPrecheck, composeRemainingAccounts, computeAccountValue, computeActiveEmodePairs, computeAssetHealthComponent, computeAssetUsdValue, computeBalanceUsdValue, computeBaseInterestRate, computeClaimedEmissions, computeClosePositionTokenAmount, computeEmodeImpacts, computeFlashLoanNonSwapBudget, computeFlashloanSwapConstraints, computeFreeCollateralFromBalances, computeFreeCollateralFromCache, computeHealthAccountMetas, computeHealthCacheStatus, computeHealthCheckAccounts, computeHealthComponentsFromBalances, computeHealthComponentsFromCache, computeHealthComponentsWithoutBiasFromBalances, computeInterestRates, computeLiabilityHealthComponent, computeLiabilityUsdValue, computeLiquidationPriceForBank, computeLoopingParams, computeLowestEmodeWeights, computeMaxBorrowForBank, computeMaxLeverage, computeMaxWithdrawForBank, computeNetApy, computeProjectedActiveBalancesNoCpi, computeProjectedActiveBanksNoCpi, computeQuantity, computeQuantityUi, computeRemainingCapacity, computeSmartCrank, computeTotalOutstandingEmissions, computeTvl, computeUsdValue, computeUtilizationRate, computeV0TxSize, convertVoteAccCoeffsToBankCoeffs, createActiveEmodePairFromPairs, createEmptyBalance, decodeAccountRaw, decodeBankRaw, decodeInstruction, decompileV0Transaction, deriveBankEmissionsAuth, deriveBankEmissionsVault, deriveBankFeeVault, deriveBankFeeVaultAuthority, deriveBankInsuranceVault, deriveBankInsuranceVaultAuthority, deriveBankLiquidityVault, deriveBankLiquidityVaultAuthority, deriveFeeState, deriveMarginfiAccount, dtoToBalance, dtoToBank, dtoToBankConfig, dtoToBankConfigRaw, dtoToBankMetadata, dtoToBankMetadataMap, dtoToBankRaw, dtoToEmodeSettings, dtoToEmodeSettingsRaw, dtoToGroup, dtoToHealthCache, dtoToInterestRateConfig, dtoToMarginfiAccount, dtoToOraclePrice, dtoToValidatorStakeGroup, emodeSettingsRawToDto, extractPythOracleKeys, fetchBank, fetchBankIntegrationMetadata, fetchMarginfiAccountAddresses, fetchMarginfiAccountData, fetchMultipleBanks, fetchNativeStakeAccounts, fetchOracleData, fetchProgramForMints, fetchPythOracleData, fetchPythOraclePricesFromAPI, fetchPythOraclePricesFromChain, fetchStakeAccount, fetchStakePoolActiveStates, fetchStakePoolMev, fetchSwbOracleAccountsFromAPI, fetchSwbOracleAccountsFromChain, fetchSwbOracleData, fetchSwbOraclePricesFromAPI, fetchSwbOraclePricesFromCrossbar, findRandomAvailableAccountIndex, freezeBankConfigIx, getAccountKeys, getActiveAccountFlags, getActiveBalances, getActiveEmodeEntryFlags, getActiveEmodeFlags, getActiveHealthCacheFlags, getAssetQuantity, getAssetShares, getAssetWeight, getBalance, getBalanceUsdValueWithPriceBias, getBankVaultAuthority, getBankVaultSeeds, getBirdeyeFallbackPricesByFeedId, getBirdeyePricesForMints, getConfig, getDriftCTokenMultiplier, getDriftMetadata, getDriftStatesDto, getEmodePairs, getExactOutEstimate, getHealthCacheStatusDescription, getHealthSimulationTransactions, getJupLendFTokenMultiplier, getJupLendMetadata, getJupLendStatesDto, getJupiterSwapIxsForFlashloan, getKaminoCTokenMultiplier, getKaminoMetadata, getKaminoStatesDto, getLiabilityQuantity, getLiabilityShares, getLiabilityWeight, getOracleSourceFromBank, getOracleSourceFromOracleSetup, getOracleSourceNameFromKey, getPrice, getPriceWithConfidence, getSwapIxsForFlashloan, getTitanExactOutEstimate, getTitanSwapIxsForFlashloan, getTotalAccountKeys, getTotalAssetQuantity, getTotalLiabilityQuantity, getTxSize, getWritableAccountKeys, groupToDto, hasAccountFlag, hasEmodeEntryFlag, hasEmodeFlag, hasHealthCacheFlag, healthCacheToDto, isFlashloan, isV0Tx, isWeightedPrice, isWholePosition, makeAddPermissionlessStakedBankIx, makeBeginFlashLoanIx3 as makeBeginFlashLoanIx, makeBorrowIx3 as makeBorrowIx, makeBorrowTx, makeBundleTipIx, makeClearEmissionsIx, makeCloseMarginfiAccountIx, makeCloseMarginfiAccountTx, makeCrankSwbFeedIx, makeCreateAccountIxWithProjection, makeCreateAccountTxWithProjection, makeCreateMarginfiAccountIx, makeCreateMarginfiAccountTx, makeDepositIx3 as makeDepositIx, makeDepositTx, makeDriftDepositIx3 as makeDriftDepositIx, makeDriftDepositTx, makeDriftWithdrawIx3 as makeDriftWithdrawIx, makeDriftWithdrawTx, makeEndFlashLoanIx3 as makeEndFlashLoanIx, makeFlashLoanTx, makeJuplendDepositIx2 as makeJuplendDepositIx, makeJuplendDepositTx, makeJuplendWithdrawIx2 as makeJuplendWithdrawIx, makeJuplendWithdrawTx, makeKaminoDepositIx3 as makeKaminoDepositIx, makeKaminoDepositTx, makeKaminoWithdrawIx3 as makeKaminoWithdrawIx, makeKaminoWithdrawTx, makeLoopTx, makePoolAddBankIx3 as makePoolAddBankIx, makePoolConfigureBankIx3 as makePoolConfigureBankIx, makePriorityFeeIx, makePriorityFeeMicroIx, makePulseHealthIx2 as makePulseHealthIx, makeRefreshKaminoBanksIxs, makeRepayIx3 as makeRepayIx, makeRepayTx, makeRepayWithCollatTx, makeSetupIx, makeSmartCrankSwbFeedIx, makeSwapCollateralTx, makeSwapDebtTx, makeTxPriorityIx, makeUnwrapSolIx, makeUpdateDriftMarketIxs, makeUpdateJupLendRateIxs, makeUpdateSwbFeedIx, makeVersionedTransaction, makeWithdrawIx3 as makeWithdrawIx, makeWithdrawTx, makeWrapSolIxs, mapBrokenFeedsToOraclePrices, mapJupiterQuoteToSwapQuoteResult, mapPythBanksToOraclePrices, mapSwbBanksToOraclePrices, marginfiAccountToDto, nativeToUi, oraclePriceToDto, parseBalanceRaw, parseBankConfigRaw, parseBankRaw, parseEmodeSettingsRaw, parseEmodeTag, parseHealthCacheRaw, parseMarginfiAccountRaw, parseOperationalState, parseOracleSetup, parseOraclePriceData as parsePriceInfo, parseRiskTier, parseRpcPythPriceData, parseSwbOraclePriceData, partitionBanksByCrankability, resolveAmount, serializeBankConfigOpt, serializeInterestRateConfig, serializeOperationalState, serializeOracleSetup, serializeOracleSetupToIndex, serializeRiskTier, shortenAddress, simulateAccountHealthCache, simulateAccountHealthCacheWithFallback, simulateBundle, splitInstructionsToFitTransactions, toBankConfigDto, toBankDto, toBigNumber, toEmodeSettingsDto, toInterestRateConfigDto, toJupiterConfig, toNumber, uiToNative, uiToNativeBigNumber, validatorStakeGroupToDto, wrappedI80F48toBigNumber };
55497
+ export { ADDRESS_LOOKUP_TABLE_FOR_GROUP, ADDRESS_LOOKUP_TABLE_FOR_SWAP, AccountFlags, AccountType, AssetTag, BUNDLE_TX_SIZE, Balance, Bank, BankConfig, BankConfigFlag, BankVaultType, DEFAULT_ORACLE_MAX_AGE, DISABLED_FLAG, EMPTY_HEALTH_CACHE, EmodeEntryFlags, EmodeFlags, EmodeImpactStatus, EmodeSettings, EmodeTag, FLASHLOAN_ENABLED_FLAG, HOURS_PER_YEAR, HealthCache, HealthCacheFlags, HealthCacheSimulationError, HealthCacheStatus, JUPITER_V6_PROGRAM, JUP_SWAP_LUT_PROGRAM_AUTHORITY_INDEX, LST_MINT, MARGINFI_IDL, MARGINFI_PROGRAM, MARGINFI_PROGRAM_STAGING, MARGINFI_PROGRAM_STAGING_ALT, MARGINFI_SPONSORED_SHARD_ID, MAX_ACCOUNT_LOCKS, MAX_CONFIDENCE_INTERVAL_RATIO, MAX_TX_SIZE, MAX_U64, MPL_METADATA_PROGRAM_ID, MarginRequirementType, MarginfiAccount, MarginfiAccountWrapper, MarginfiGroup, OperationalState, OracleSetup, PDA_BANK_EMISSIONS_AUTH_SEED, PDA_BANK_EMISSIONS_VAULT_SEED, PDA_BANK_FEE_STATE_SEED, PDA_BANK_FEE_VAULT_AUTH_SEED, PDA_BANK_FEE_VAULT_SEED, PDA_BANK_INSURANCE_VAULT_AUTH_SEED, PDA_BANK_INSURANCE_VAULT_SEED, PDA_BANK_LIQUIDITY_VAULT_AUTH_SEED, PDA_BANK_LIQUIDITY_VAULT_SEED, PDA_MARGINFI_ACCOUNT_SEED, PRIORITY_TX_SIZE, PYTH_PRICE_CONF_INTERVALS, PYTH_PUSH_ORACLE_ID, PYTH_SPONSORED_SHARD_ID, PriceBias, Project0Client, RiskTier, SINGLE_POOL_PROGRAM_ID, STAKE_CONFIG_ID, STAKE_PROGRAM_ID, SWB_PRICE_CONF_INTERVALS, SYSTEM_PROGRAM_ID, SYSVAR_CLOCK_ID, SYSVAR_RENT_ID, SYSVAR_STAKE_HISTORY_ID, SwapProvider, TRANSFER_ACCOUNT_AUTHORITY_FLAG, TransactionArenaKeyMap, TransactionBuildingError, TransactionBuildingErrorCode, TransactionConfigMap, TransactionType, USDC_DECIMALS, USDC_MINT, WSOL_MINT, ZERO_ORACLE_KEY, accountFlagToBN, addOracleToBanksIx, addTransactionMetadata, adjustPriceComponent, aprToApy, apyToApr, balanceToDto, bankConfigRawToDto, bankConfigToBankConfigRaw, bankMetadataMapToDto, bankMetadataToDto, bankRawToDto, bigNumberToWrappedI80F48, bpsToPercentile, calculateApyFromInterest, calculateInterestFromApy, capConfidenceInterval, categorizePythBanks, checkBatchOracleCrankability, checkMultipleOraclesCrankability, chunkedGetRawMultipleAccountInfoOrdered, chunkedGetRawMultipleAccountInfoOrderedWithNulls, chunkedGetRawMultipleAccountInfos, compileFlashloanPrecheck, composeRemainingAccounts, computeAccountValue, computeActiveEmodePairs, computeAssetHealthComponent, computeAssetUsdValue, computeBalanceUsdValue, computeBankBorrowApy, computeBankBorrowCapRemaining, computeBankDepositCapRemaining, computeBankMetrics, computeBankPoolSize, computeBankSupplyApy, computeBankTotalBorrows, computeBankTotalBorrowsUsd, computeBankTotalDeposits, computeBankTotalDepositsUsd, computeBaseInterestRate, computeClaimedEmissions, computeClosePositionTokenAmount, computeEmodeImpacts, computeFlashLoanNonSwapBudget, computeFlashloanSwapConstraints, computeFreeCollateralFromBalances, computeFreeCollateralFromCache, computeHealthAccountMetas, computeHealthCacheStatus, computeHealthCheckAccounts, computeHealthComponentsFromBalances, computeHealthComponentsFromCache, computeHealthComponentsWithoutBiasFromBalances, computeInterestRates, computeLiabilityHealthComponent, computeLiabilityUsdValue, computeLiquidationPriceForBank, computeLoopingParams, computeLowestEmodeWeights, computeMaxBorrowForBank, computeMaxLeverage, computeMaxWithdrawForBank, computeNetApy, computeProjectedActiveBalancesNoCpi, computeProjectedActiveBanksNoCpi, computeQuantity, computeQuantityUi, computeRemainingCapacity, computeSmartCrank, computeStakedBankMultipliers, computeTotalOutstandingEmissions, computeTvl, computeUsdValue, computeUtilizationRate, computeV0TxSize, convertVoteAccCoeffsToBankCoeffs, createActiveEmodePairFromPairs, createEmptyBalance, decodeAccountRaw, decodeBankRaw, decodeInstruction, decompileV0Transaction, deriveBankEmissionsAuth, deriveBankEmissionsVault, deriveBankFeeVault, deriveBankFeeVaultAuthority, deriveBankInsuranceVault, deriveBankInsuranceVaultAuthority, deriveBankLiquidityVault, deriveBankLiquidityVaultAuthority, deriveFeeState, deriveMarginfiAccount, dtoToBalance, dtoToBank, dtoToBankConfig, dtoToBankConfigRaw, dtoToBankMetadata, dtoToBankMetadataMap, dtoToBankRaw, dtoToEmodeSettings, dtoToEmodeSettingsRaw, dtoToGroup, dtoToHealthCache, dtoToInterestRateConfig, dtoToMarginfiAccount, dtoToOraclePrice, dtoToValidatorStakeGroup, emodeSettingsRawToDto, extractPythOracleKeys, fetchBank, fetchBankIntegrationMetadata, fetchMarginfiAccountAddresses, fetchMarginfiAccountData, fetchMultipleBanks, fetchNativeStakeAccounts, fetchOracleData, fetchProgramForMints, fetchPythOracleData, fetchPythOraclePricesFromAPI, fetchPythOraclePricesFromChain, fetchStakeAccount, fetchStakePoolActiveStates, fetchStakePoolMev, fetchSwbOracleAccountsFromAPI, fetchSwbOracleAccountsFromChain, fetchSwbOracleData, fetchSwbOraclePricesFromAPI, fetchSwbOraclePricesFromCrossbar, findRandomAvailableAccountIndex, freezeBankConfigIx, generateDummyAccount, getAccountKeys, getActiveAccountFlags, getActiveBalances, getActiveEmodeEntryFlags, getActiveEmodeFlags, getActiveHealthCacheFlags, getAssetQuantity, getAssetShares, getAssetWeight, getBalance, getBalanceUsdValueWithPriceBias, getBankVaultAuthority, getBankVaultSeeds, getBirdeyeFallbackPricesByFeedId, getBirdeyePricesForMints, getConfig, getDriftCTokenMultiplier, getDriftMetadata, getDriftStatesDto, getEmodePairs, getExactOutEstimate, getHealthCacheStatusDescription, getHealthSimulationTransactions, getJupLendFTokenMultiplier, getJupLendMetadata, getJupLendStatesDto, getJupiterSwapIxsForFlashloan, getKaminoCTokenMultiplier, getKaminoMetadata, getKaminoStatesDto, getLiabilityQuantity, getLiabilityShares, getLiabilityWeight, getOracleSourceFromBank, getOracleSourceFromOracleSetup, getOracleSourceNameFromKey, getPrice, getPriceWithConfidence, getStakedBankMetadataMap, getSwapIxsForFlashloan, getTitanExactOutEstimate, getTitanSwapIxsForFlashloan, getTotalAccountKeys, getTotalAssetQuantity, getTotalLiabilityQuantity, getTxSize, getValidatorVoteAccountByBank, getWritableAccountKeys, groupToDto, hasAccountFlag, hasEmodeEntryFlag, hasEmodeFlag, hasHealthCacheFlag, healthCacheToDto, isFlashloan, isV0Tx, isWeightedPrice, isWholePosition, makeAddPermissionlessStakedBankIx, makeBeginFlashLoanIx3 as makeBeginFlashLoanIx, makeBorrowIx3 as makeBorrowIx, makeBorrowTx, makeBundleTipIx, makeClearEmissionsIx, makeCloseMarginfiAccountIx, makeCloseMarginfiAccountTx, makeCrankSwbFeedIx, makeCreateAccountIxWithProjection, makeCreateAccountTxWithProjection, makeCreateMarginfiAccountIx, makeCreateMarginfiAccountTx, makeDepositIx3 as makeDepositIx, makeDepositTx, makeDriftDepositIx3 as makeDriftDepositIx, makeDriftDepositTx, makeDriftWithdrawIx3 as makeDriftWithdrawIx, makeDriftWithdrawTx, makeEndFlashLoanIx3 as makeEndFlashLoanIx, makeFlashLoanTx, makeJuplendDepositIx2 as makeJuplendDepositIx, makeJuplendDepositTx, makeJuplendWithdrawIx2 as makeJuplendWithdrawIx, makeJuplendWithdrawTx, makeKaminoDepositIx3 as makeKaminoDepositIx, makeKaminoDepositTx, makeKaminoWithdrawIx3 as makeKaminoWithdrawIx, makeKaminoWithdrawTx, makeLoopTx, makeMergeStakeAccountsTx, makeMintStakedLstIx, makeMintStakedLstTx, makePoolAddBankIx3 as makePoolAddBankIx, makePoolConfigureBankIx3 as makePoolConfigureBankIx, makePriorityFeeIx, makePriorityFeeMicroIx, makePulseHealthIx2 as makePulseHealthIx, makeRedeemStakedLstIx, makeRedeemStakedLstTx, makeRefreshKaminoBanksIxs, makeRepayIx3 as makeRepayIx, makeRepayTx, makeRepayWithCollatTx, makeSetupIx, makeSmartCrankSwbFeedIx, makeSwapCollateralTx, makeSwapDebtTx, makeTxPriorityIx, makeUnwrapSolIx, makeUpdateDriftMarketIxs, makeUpdateJupLendRateIxs, makeUpdateSwbFeedIx, makeVersionedTransaction, makeWithdrawIx3 as makeWithdrawIx, makeWithdrawTx, makeWrapSolIxs, mapBrokenFeedsToOraclePrices, mapJupiterQuoteToSwapQuoteResult, mapPythBanksToOraclePrices, mapSwbBanksToOraclePrices, marginfiAccountToDto, nativeToUi, oraclePriceToDto, parseBalanceRaw, parseBankConfigRaw, parseBankRaw, parseEmodeSettingsRaw, parseEmodeTag, parseHealthCacheRaw, parseMarginfiAccountRaw, parseOperationalState, parseOracleSetup, parseOraclePriceData as parsePriceInfo, parseRiskTier, parseRpcPythPriceData, parseSwbOraclePriceData, partitionBanksByCrankability, resolveAmount, serializeBankConfigOpt, serializeInterestRateConfig, serializeOperationalState, serializeOracleSetup, serializeOracleSetupToIndex, serializeRiskTier, shortenAddress, simulateAccountHealthCache, simulateAccountHealthCacheWithFallback, simulateBundle, splitInstructionsToFitTransactions, toBankConfigDto, toBankDto, toBigNumber, toEmodeSettingsDto, toInterestRateConfigDto, toJupiterConfig, toNumber, uiToNative, uiToNativeBigNumber, validatorStakeGroupToDto, wrappedI80F48toBigNumber };
54592
55498
  //# sourceMappingURL=index.js.map
54593
55499
  //# sourceMappingURL=index.js.map