@0dotxyz/p0-ts-sdk 2.3.0-alpha.3 → 2.3.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -36191,7 +36191,7 @@ async function makeSetupIx({ connection, authority, tokens }) {
36191
36191
  let ixs = [];
36192
36192
  const userAtaAis = await connection.getMultipleAccountsInfo(userAtas);
36193
36193
  for (const [i, userAta] of userAtaAis.entries()) {
36194
- const token = tokens[i];
36194
+ const token = uniqueTokens[i];
36195
36195
  const userAtaAddress = userAtas[i];
36196
36196
  if (userAta === null && token && userAtaAddress) {
36197
36197
  ixs.push(
@@ -44608,11 +44608,13 @@ function selectBestRoute(quotes, swapMode) {
44608
44608
  }
44609
44609
  function buildSwapQuoteResult(route, swapMode) {
44610
44610
  const slippageBps = route.slippageBps;
44611
+ const outAmount = Number(route.outAmount);
44612
+ const inAmount = Number(route.inAmount);
44611
44613
  let otherAmountThreshold;
44612
44614
  if (swapMode === "ExactIn") {
44613
- otherAmountThreshold = String(Math.floor(route.outAmount * (1 - slippageBps / 1e4)));
44615
+ otherAmountThreshold = String(Math.floor(outAmount * (1 - slippageBps / 1e4)));
44614
44616
  } else {
44615
- otherAmountThreshold = String(Math.ceil(route.inAmount * (1 + slippageBps / 1e4)));
44617
+ otherAmountThreshold = String(Math.ceil(inAmount * (1 + slippageBps / 1e4)));
44616
44618
  }
44617
44619
  return {
44618
44620
  inAmount: String(route.inAmount),
@@ -52005,6 +52007,59 @@ function deriveExponentEventAuthority() {
52005
52007
  EXPONENT_CORE_PROGRAM_ID
52006
52008
  )[0];
52007
52009
  }
52010
+ Buffer.from([5]);
52011
+ Buffer.from([17]);
52012
+ Buffer.from([4]);
52013
+ var WRAPPER_MERGE_DISCRIMINATOR = Buffer.from([39]);
52014
+ function makeExponentWrapperMergeIx(accounts, args) {
52015
+ const tokenProgram = accounts.tokenProgram ?? TOKEN_PROGRAM_ID;
52016
+ const eventAuthority = deriveExponentEventAuthority();
52017
+ const data = Buffer.alloc(WRAPPER_MERGE_DISCRIMINATOR.length + 9);
52018
+ WRAPPER_MERGE_DISCRIMINATOR.copy(data, 0);
52019
+ data.writeBigUInt64LE(args.amountPyNative, WRAPPER_MERGE_DISCRIMINATOR.length);
52020
+ data.writeUInt8(args.redeemSyAccountsUntil, WRAPPER_MERGE_DISCRIMINATOR.length + 8);
52021
+ const keys = [
52022
+ { pubkey: accounts.owner, isSigner: true, isWritable: true },
52023
+ { pubkey: accounts.syAta, isSigner: false, isWritable: true },
52024
+ { pubkey: accounts.vault, isSigner: false, isWritable: true },
52025
+ { pubkey: accounts.escrowSy, isSigner: false, isWritable: true },
52026
+ { pubkey: accounts.ytAta, isSigner: false, isWritable: true },
52027
+ { pubkey: accounts.ptAta, isSigner: false, isWritable: true },
52028
+ { pubkey: accounts.mintYt, isSigner: false, isWritable: true },
52029
+ { pubkey: accounts.mintPt, isSigner: false, isWritable: true },
52030
+ { pubkey: accounts.authority, isSigner: false, isWritable: true },
52031
+ { pubkey: accounts.addressLookupTable, isSigner: false, isWritable: false },
52032
+ { pubkey: tokenProgram, isSigner: false, isWritable: false },
52033
+ { pubkey: accounts.yieldPosition, isSigner: false, isWritable: true },
52034
+ { pubkey: accounts.syProgram, isSigner: false, isWritable: false },
52035
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
52036
+ { pubkey: eventAuthority, isSigner: false, isWritable: false },
52037
+ { pubkey: EXPONENT_CORE_PROGRAM_ID, isSigner: false, isWritable: false },
52038
+ // [...redeem (flavor SY-redeem accounts), ...cpi (withdraw_sy ++ get_sy_state)]
52039
+ ...accounts.remainingAccounts
52040
+ ];
52041
+ return new TransactionInstruction({ keys, programId: EXPONENT_CORE_PROGRAM_ID, data });
52042
+ }
52043
+ var SPL_STAKE_POOL_UPDATE_BALANCE_TAG = Buffer.from([7]);
52044
+ function makeSplStakePoolUpdateBalanceIx(accounts) {
52045
+ const tokenProgram = accounts.tokenProgram ?? TOKEN_PROGRAM_ID;
52046
+ const keys = [
52047
+ { pubkey: accounts.stakePool, isSigner: false, isWritable: true },
52048
+ { pubkey: accounts.withdrawAuthority, isSigner: false, isWritable: false },
52049
+ { pubkey: accounts.validatorList, isSigner: false, isWritable: true },
52050
+ { pubkey: accounts.reserveStake, isSigner: false, isWritable: false },
52051
+ { pubkey: accounts.managerFeeAccount, isSigner: false, isWritable: true },
52052
+ { pubkey: accounts.poolMint, isSigner: false, isWritable: true },
52053
+ { pubkey: tokenProgram, isSigner: false, isWritable: false }
52054
+ ];
52055
+ return new TransactionInstruction({
52056
+ keys,
52057
+ programId: accounts.stakePoolProgram,
52058
+ data: Buffer.from(SPL_STAKE_POOL_UPDATE_BALANCE_TAG)
52059
+ });
52060
+ }
52061
+
52062
+ // src/vendor/exponent/utils/resolve.utils.ts
52008
52063
  function resolveCpiMetas(contexts, altAddresses, altKey) {
52009
52064
  return contexts.map((ctx) => {
52010
52065
  const pubkey = altAddresses[ctx.altIndex];
@@ -52016,10 +52071,46 @@ function resolveCpiMetas(contexts, altAddresses, altKey) {
52016
52071
  return { pubkey, isSigner: false, isWritable: ctx.isWritable };
52017
52072
  });
52018
52073
  }
52019
- async function resolveExponentMergeContext(params) {
52020
- const { connection, owner } = params;
52074
+ function uniqueRemainingAccounts(metas) {
52075
+ const seen = /* @__PURE__ */ new Map();
52076
+ for (const m of metas) {
52077
+ const key = m.pubkey.toBase58();
52078
+ const prev = seen.get(key);
52079
+ if (prev) prev.isWritable = prev.isWritable || m.isWritable;
52080
+ else seen.set(key, { ...m });
52081
+ }
52082
+ return [...seen.values()];
52083
+ }
52084
+ var STAKE_POOL_OFFSETS = {
52085
+ validatorList: 98,
52086
+ reserveStake: 130,
52087
+ poolMint: 162,
52088
+ managerFeeAccount: 194
52089
+ };
52090
+ async function resolveSplStakePoolRefreshIx(connection, stakePool) {
52091
+ const info = await connection.getAccountInfo(stakePool);
52092
+ if (!info) throw new Error(`SPL stake pool account not found: ${stakePool.toBase58()}`);
52093
+ const stakePoolProgram = info.owner;
52094
+ const at = (off) => new PublicKey(info.data.subarray(off, off + 32));
52095
+ const [withdrawAuthority] = PublicKey.findProgramAddressSync(
52096
+ [stakePool.toBuffer(), Buffer.from("withdraw")],
52097
+ stakePoolProgram
52098
+ );
52099
+ return makeSplStakePoolUpdateBalanceIx({
52100
+ stakePoolProgram,
52101
+ stakePool,
52102
+ withdrawAuthority,
52103
+ validatorList: at(STAKE_POOL_OFFSETS.validatorList),
52104
+ reserveStake: at(STAKE_POOL_OFFSETS.reserveStake),
52105
+ managerFeeAccount: at(STAKE_POOL_OFFSETS.managerFeeAccount),
52106
+ poolMint: at(STAKE_POOL_OFFSETS.poolMint)
52107
+ });
52108
+ }
52109
+ async function resolveExponentWrapperMergeContext(params) {
52110
+ const { connection, owner, baseMint } = params;
52021
52111
  const ptYtTokenProgram = params.ptYtTokenProgram ?? TOKEN_PROGRAM_ID;
52022
52112
  const syTokenProgram = params.syTokenProgram ?? TOKEN_PROGRAM_ID;
52113
+ const baseTokenProgram = params.baseTokenProgram ?? TOKEN_PROGRAM_ID;
52023
52114
  let vaultAddress;
52024
52115
  let vault;
52025
52116
  if (params.vault) {
@@ -52030,11 +52121,8 @@ async function resolveExponentMergeContext(params) {
52030
52121
  vaultAddress = res.vault;
52031
52122
  vault = res.account;
52032
52123
  } else {
52033
- throw new Error("resolveExponentMergeContext: one of `vault` or `market` is required");
52124
+ throw new Error("resolveExponentWrapperMergeContext: one of `vault` or `market` is required");
52034
52125
  }
52035
- const ptSrcAta = getAssociatedTokenAddressSync(vault.mintPt, owner, true, ptYtTokenProgram);
52036
- const ytSrcAta = getAssociatedTokenAddressSync(vault.mintYt, owner, true, ptYtTokenProgram);
52037
- const sySrcDstAta = getAssociatedTokenAddressSync(vault.mintSy, owner, true, syTokenProgram);
52038
52126
  const altResult = await connection.getAddressLookupTable(vault.addressLookupTable);
52039
52127
  const alt = altResult.value;
52040
52128
  if (!alt) {
@@ -52042,169 +52130,75 @@ async function resolveExponentMergeContext(params) {
52042
52130
  `Exponent vault address lookup table not found: ${vault.addressLookupTable.toBase58()}`
52043
52131
  );
52044
52132
  }
52045
- const remainingAccounts = [
52046
- ...resolveCpiMetas(vault.cpiAccounts.getSyState, alt.state.addresses, vault.addressLookupTable),
52047
- ...resolveCpiMetas(vault.cpiAccounts.withdrawSy, alt.state.addresses, vault.addressLookupTable)
52048
- ];
52049
- const mergeAccounts = {
52050
- owner,
52051
- authority: vault.authority,
52052
- vault: vaultAddress,
52053
- sySrcDstAta,
52054
- escrowSy: vault.escrowSy,
52055
- ytSrcAta,
52056
- ptSrcAta,
52057
- mintYt: vault.mintYt,
52058
- mintPt: vault.mintPt,
52059
- syProgram: vault.syProgram,
52060
- addressLookupTable: vault.addressLookupTable,
52061
- yieldPosition: vault.yieldPosition,
52062
- tokenProgram: ptYtTokenProgram,
52063
- remainingAccounts
52064
- };
52065
- const decimals = await getMintDecimals(connection, vault.mintSy);
52066
- return {
52067
- vaultAddress,
52068
- vault,
52069
- mergeAccounts,
52070
- addressLookupTable: alt,
52071
- underlying: { mint: vault.mintSy, decimals, tokenProgram: syTokenProgram },
52072
- computeRedeemedAmountNative(ptAmountNative) {
52073
- if (vault.ptSupply === 0n) return 0n;
52074
- const sy = new BigNumber(ptAmountNative.toString()).times(vault.syForPt.toString()).div(vault.ptSupply.toString()).integerValue(BigNumber.ROUND_FLOOR);
52075
- return BigInt(sy.toFixed(0));
52076
- }
52077
- };
52078
- }
52079
- async function resolveExponentStripContext(params) {
52080
- const { connection, owner } = params;
52081
- const ptYtTokenProgram = params.ptYtTokenProgram ?? TOKEN_PROGRAM_ID;
52082
- const syTokenProgram = params.syTokenProgram ?? TOKEN_PROGRAM_ID;
52083
- let vaultAddress;
52084
- let vault;
52085
- if (params.vault) {
52086
- vaultAddress = params.vault;
52087
- vault = await fetchExponentVault(connection, vaultAddress);
52088
- } else if (params.market) {
52089
- const res = await fetchExponentVaultFromMarket(connection, params.market);
52090
- vaultAddress = res.vault;
52091
- vault = res.account;
52092
- } else {
52093
- throw new Error("resolveExponentStripContext: one of `vault` or `market` is required");
52094
- }
52095
- const altResult = await connection.getAddressLookupTable(vault.addressLookupTable);
52096
- const alt = altResult.value;
52097
- if (!alt) {
52133
+ const altKey = vault.addressLookupTable;
52134
+ const getSyState = resolveCpiMetas(vault.cpiAccounts.getSyState, alt.state.addresses, altKey);
52135
+ const withdrawSy = resolveCpiMetas(vault.cpiAccounts.withdrawSy, alt.state.addresses, altKey);
52136
+ if (getSyState.length < 4) {
52098
52137
  throw new Error(
52099
- `Exponent vault address lookup table not found: ${vault.addressLookupTable.toBase58()}`
52138
+ "resolveExponentWrapperMergeContext: unexpected get_sy_state shape (expected the generic SPL-stake-pool flavor: [syState, mintSy, tokenSyEscrow, stakePool])"
52100
52139
  );
52101
52140
  }
52102
- const remainingAccounts = resolveCpiMetas(
52103
- vault.cpiAccounts.depositSy,
52104
- alt.state.addresses,
52105
- vault.addressLookupTable
52106
- );
52107
- const sySrc = getAssociatedTokenAddressSync(vault.mintSy, owner, true, syTokenProgram);
52108
- const ptDst = getAssociatedTokenAddressSync(vault.mintPt, owner, true, ptYtTokenProgram);
52109
- const ytDst = getAssociatedTokenAddressSync(vault.mintYt, owner, true, ptYtTokenProgram);
52110
- const stripAccounts = {
52111
- depositor: owner,
52112
- authority: vault.authority,
52141
+ const syState = getSyState[0].pubkey;
52142
+ const stakePool = getSyState[3].pubkey;
52143
+ const syAta = getAssociatedTokenAddressSync(vault.mintSy, owner, true, syTokenProgram);
52144
+ const ptAta = getAssociatedTokenAddressSync(vault.mintPt, owner, true, ptYtTokenProgram);
52145
+ const ytAta = getAssociatedTokenAddressSync(vault.mintYt, owner, true, ptYtTokenProgram);
52146
+ const baseAta = getAssociatedTokenAddressSync(baseMint, owner, true, baseTokenProgram);
52147
+ const baseEscrow = getAssociatedTokenAddressSync(baseMint, syState, true, baseTokenProgram);
52148
+ const redeem = [
52149
+ { pubkey: owner, isSigner: true, isWritable: true },
52150
+ { pubkey: syState, isSigner: false, isWritable: true },
52151
+ { pubkey: baseAta, isSigner: false, isWritable: true },
52152
+ { pubkey: baseEscrow, isSigner: false, isWritable: true },
52153
+ { pubkey: syAta, isSigner: false, isWritable: true },
52154
+ { pubkey: vault.mintSy, isSigner: false, isWritable: true },
52155
+ { pubkey: baseMint, isSigner: false, isWritable: false },
52156
+ { pubkey: syTokenProgram, isSigner: false, isWritable: false },
52157
+ { pubkey: baseTokenProgram, isSigner: false, isWritable: false },
52158
+ { pubkey: stakePool, isSigner: false, isWritable: true }
52159
+ ];
52160
+ const cpi = uniqueRemainingAccounts([...withdrawSy, ...getSyState]);
52161
+ const wrapperMergeAccounts = {
52162
+ owner,
52163
+ syAta,
52113
52164
  vault: vaultAddress,
52114
- sySrc,
52115
52165
  escrowSy: vault.escrowSy,
52116
- ytDst,
52117
- ptDst,
52166
+ ytAta,
52167
+ ptAta,
52118
52168
  mintYt: vault.mintYt,
52119
52169
  mintPt: vault.mintPt,
52120
- syProgram: vault.syProgram,
52170
+ authority: vault.authority,
52121
52171
  addressLookupTable: vault.addressLookupTable,
52122
52172
  yieldPosition: vault.yieldPosition,
52173
+ syProgram: vault.syProgram,
52123
52174
  tokenProgram: ptYtTokenProgram,
52124
- remainingAccounts
52175
+ remainingAccounts: [...redeem, ...cpi],
52176
+ redeemSyAccountsUntil: redeem.length
52125
52177
  };
52126
- const [syDecimals, ptDecimals] = await Promise.all([
52127
- getMintDecimals(connection, vault.mintSy),
52128
- getMintDecimals(connection, vault.mintPt)
52178
+ const [baseDecimals, stakePoolRefreshIx] = await Promise.all([
52179
+ getMintDecimals(connection, baseMint),
52180
+ resolveSplStakePoolRefreshIx(connection, stakePool)
52129
52181
  ]);
52130
- const syExchangeRate = vault.lastSeenSyExchangeRate.toNumber();
52131
52182
  return {
52132
52183
  vaultAddress,
52133
52184
  vault,
52134
- stripAccounts,
52185
+ wrapperMergeAccounts,
52186
+ preInstructions: [stakePoolRefreshIx],
52135
52187
  addressLookupTable: alt,
52136
- sy: { mint: vault.mintSy, decimals: syDecimals, tokenProgram: syTokenProgram },
52137
- pt: { mint: vault.mintPt, decimals: ptDecimals, tokenProgram: ptYtTokenProgram },
52138
- yt: { mint: vault.mintYt, tokenProgram: ptYtTokenProgram },
52139
- syExchangeRate,
52140
- computeStrippedPtNative(syInNative) {
52141
- const pt = vault.lastSeenSyExchangeRate.times(syInNative.toString()).integerValue(BigNumber.ROUND_FLOOR);
52142
- return BigInt(pt.toFixed(0));
52188
+ baseToken: { mint: baseMint, decimals: baseDecimals, tokenProgram: baseTokenProgram },
52189
+ setupMints: [
52190
+ { mint: baseMint, tokenProgram: baseTokenProgram },
52191
+ { mint: vault.mintSy, tokenProgram: syTokenProgram },
52192
+ { mint: vault.mintPt, tokenProgram: ptYtTokenProgram },
52193
+ { mint: vault.mintYt, tokenProgram: ptYtTokenProgram }
52194
+ ],
52195
+ computeRedeemedBaseNative(ptAmountNative) {
52196
+ if (vault.ptSupply === 0n) return 0n;
52197
+ const base = new BigNumber(ptAmountNative.toString()).times(vault.syForPt.toString()).div(vault.ptSupply.toString()).integerValue(BigNumber.ROUND_FLOOR);
52198
+ return BigInt(base.toFixed(0));
52143
52199
  }
52144
52200
  };
52145
52201
  }
52146
- var MERGE_DISCRIMINATOR = Buffer.from([5]);
52147
- function makeExponentMergeIx(accounts, amountNative) {
52148
- const tokenProgram = accounts.tokenProgram ?? TOKEN_PROGRAM_ID;
52149
- const eventAuthority = deriveExponentEventAuthority();
52150
- const data = Buffer.alloc(MERGE_DISCRIMINATOR.length + 8);
52151
- MERGE_DISCRIMINATOR.copy(data, 0);
52152
- data.writeBigUInt64LE(amountNative, MERGE_DISCRIMINATOR.length);
52153
- const keys = [
52154
- { pubkey: accounts.owner, isSigner: true, isWritable: true },
52155
- { pubkey: accounts.authority, isSigner: false, isWritable: true },
52156
- { pubkey: accounts.vault, isSigner: false, isWritable: true },
52157
- { pubkey: accounts.sySrcDstAta, isSigner: false, isWritable: true },
52158
- { pubkey: accounts.escrowSy, isSigner: false, isWritable: true },
52159
- { pubkey: accounts.ytSrcAta, isSigner: false, isWritable: true },
52160
- { pubkey: accounts.ptSrcAta, isSigner: false, isWritable: true },
52161
- { pubkey: accounts.mintYt, isSigner: false, isWritable: true },
52162
- { pubkey: accounts.mintPt, isSigner: false, isWritable: true },
52163
- { pubkey: tokenProgram, isSigner: false, isWritable: false },
52164
- { pubkey: accounts.syProgram, isSigner: false, isWritable: false },
52165
- { pubkey: accounts.addressLookupTable, isSigner: false, isWritable: false },
52166
- { pubkey: accounts.yieldPosition, isSigner: false, isWritable: true },
52167
- { pubkey: eventAuthority, isSigner: false, isWritable: false },
52168
- { pubkey: EXPONENT_CORE_PROGRAM_ID, isSigner: false, isWritable: false },
52169
- // SY-program CPI accounts (getSyState ++ withdrawSy), ALT-resolved (post-maturity merge
52170
- // still CPIs into the SY program to move SY out of escrow).
52171
- ...accounts.remainingAccounts ?? []
52172
- ];
52173
- return new TransactionInstruction({
52174
- keys,
52175
- programId: EXPONENT_CORE_PROGRAM_ID,
52176
- data
52177
- });
52178
- }
52179
- Buffer.from([17]);
52180
- var STRIP_DISCRIMINATOR = Buffer.from([4]);
52181
- function makeExponentStripIx(accounts, amountNative) {
52182
- const tokenProgram = accounts.tokenProgram ?? TOKEN_PROGRAM_ID;
52183
- const eventAuthority = deriveExponentEventAuthority();
52184
- const data = Buffer.alloc(STRIP_DISCRIMINATOR.length + 8);
52185
- STRIP_DISCRIMINATOR.copy(data, 0);
52186
- data.writeBigUInt64LE(amountNative, STRIP_DISCRIMINATOR.length);
52187
- const keys = [
52188
- { pubkey: accounts.depositor, isSigner: true, isWritable: true },
52189
- { pubkey: accounts.authority, isSigner: false, isWritable: true },
52190
- { pubkey: accounts.vault, isSigner: false, isWritable: true },
52191
- { pubkey: accounts.sySrc, isSigner: false, isWritable: true },
52192
- { pubkey: accounts.escrowSy, isSigner: false, isWritable: true },
52193
- { pubkey: accounts.ytDst, isSigner: false, isWritable: true },
52194
- { pubkey: accounts.ptDst, isSigner: false, isWritable: true },
52195
- { pubkey: accounts.mintYt, isSigner: false, isWritable: true },
52196
- { pubkey: accounts.mintPt, isSigner: false, isWritable: true },
52197
- { pubkey: tokenProgram, isSigner: false, isWritable: false },
52198
- { pubkey: accounts.addressLookupTable, isSigner: false, isWritable: false },
52199
- { pubkey: accounts.syProgram, isSigner: false, isWritable: false },
52200
- { pubkey: accounts.yieldPosition, isSigner: false, isWritable: true },
52201
- { pubkey: eventAuthority, isSigner: false, isWritable: false },
52202
- { pubkey: EXPONENT_CORE_PROGRAM_ID, isSigner: false, isWritable: false },
52203
- // SY-program CPI accounts (depositSy), ALT-resolved.
52204
- ...accounts.remainingAccounts ?? []
52205
- ];
52206
- return new TransactionInstruction({ keys, programId: EXPONENT_CORE_PROGRAM_ID, data });
52207
- }
52208
52202
 
52209
52203
  // src/vendor/klend/utils/klend/interest-rate.utils.ts
52210
52204
  function getKaminoTotalSupply(reserve) {
@@ -57834,93 +57828,6 @@ async function buildSwapDebtFlashloanTx({
57834
57828
  repayIxs
57835
57829
  };
57836
57830
  }
57837
- var DEFAULT_ROLL_SLIPPAGE_BPS = 10;
57838
- async function resolveRoll(params) {
57839
- const { connection, marginfiAccount, withdrawOpts, rollOpts } = params;
57840
- const owner = marginfiAccount.authority;
57841
- const slippageBps = rollOpts.slippageBps ?? DEFAULT_ROLL_SLIPPAGE_BPS;
57842
- const keepBps = BigInt(1e4 - slippageBps);
57843
- if (withdrawOpts.withdrawAmount !== void 0 && withdrawOpts.withdrawAmount <= 0) {
57844
- throw new Error("withdrawAmount must be greater than 0");
57845
- }
57846
- const actualWithdrawAmount = Math.min(
57847
- withdrawOpts.withdrawAmount ?? withdrawOpts.totalPositionAmount,
57848
- withdrawOpts.totalPositionAmount
57849
- );
57850
- const isFullWithdraw = isWholePosition(
57851
- { amount: withdrawOpts.totalPositionAmount, isLending: true },
57852
- actualWithdrawAmount,
57853
- withdrawOpts.withdrawBank.mintDecimals
57854
- );
57855
- if (!rollOpts.maturedMarket && !rollOpts.maturedVault) {
57856
- throw new Error("roll-pt: rollOpts.maturedMarket or maturedVault is required");
57857
- }
57858
- const merge = await resolveExponentMergeContext({
57859
- connection,
57860
- owner,
57861
- market: rollOpts.maturedMarket,
57862
- vault: rollOpts.maturedVault
57863
- });
57864
- const withdrawNative = BigInt(
57865
- uiToNative(actualWithdrawAmount, withdrawOpts.withdrawBank.mintDecimals).toString()
57866
- );
57867
- const redeemedSy = merge.computeRedeemedAmountNative(withdrawNative);
57868
- const syToken = { mint: merge.underlying.mint, tokenProgram: merge.underlying.tokenProgram };
57869
- let buyInstructions;
57870
- let buySetupInstructions;
57871
- let buyLuts;
57872
- let ptOutNative;
57873
- if (rollOpts.buy) {
57874
- buyInstructions = rollOpts.buy.instructions;
57875
- buySetupInstructions = rollOpts.buy.setupInstructions ?? [];
57876
- buyLuts = rollOpts.buy.lookupTables ?? [];
57877
- ptOutNative = rollOpts.buy.ptOutNative;
57878
- } else {
57879
- if (!rollOpts.successorVault && !rollOpts.successorMarket) {
57880
- throw new Error(
57881
- "roll-pt: rollOpts.successorVault or successorMarket is required (or pass rollOpts.buy)"
57882
- );
57883
- }
57884
- const strip = await resolveExponentStripContext({
57885
- connection,
57886
- owner,
57887
- vault: rollOpts.successorVault,
57888
- market: rollOpts.successorMarket
57889
- });
57890
- const syIn = redeemedSy * keepBps / 10000n;
57891
- buyInstructions = [makeExponentStripIx(strip.stripAccounts, syIn)];
57892
- const ytAta = getAssociatedTokenAddressSync(strip.yt.mint, owner, true, strip.yt.tokenProgram);
57893
- buySetupInstructions = [
57894
- createAssociatedTokenAccountIdempotentInstruction(
57895
- owner,
57896
- ytAta,
57897
- owner,
57898
- strip.yt.mint,
57899
- strip.yt.tokenProgram
57900
- )
57901
- ];
57902
- buyLuts = [strip.addressLookupTable];
57903
- ptOutNative = strip.computeStrippedPtNative(syIn) * keepBps / 10000n;
57904
- }
57905
- const rollLuts = [merge.addressLookupTable, ...buyLuts];
57906
- if (rollOpts.lookupTable) {
57907
- const fetched = (await connection.getAddressLookupTable(rollOpts.lookupTable)).value;
57908
- if (!fetched) {
57909
- throw new Error(`roll-pt: PT-roll lookup table not found: ${rollOpts.lookupTable.toBase58()}`);
57910
- }
57911
- rollLuts.push(fetched);
57912
- }
57913
- return {
57914
- actualWithdrawAmount,
57915
- isFullWithdraw,
57916
- mergeAccounts: merge.mergeAccounts,
57917
- syToken,
57918
- buyInstructions,
57919
- buySetupInstructions,
57920
- ptOutNative,
57921
- rollLuts
57922
- };
57923
- }
57924
57831
  async function makeRollPtTx(params) {
57925
57832
  const {
57926
57833
  program,
@@ -57930,30 +57837,46 @@ async function makeRollPtTx(params) {
57930
57837
  oraclePrices,
57931
57838
  withdrawOpts,
57932
57839
  depositOpts,
57840
+ rollOpts,
57933
57841
  assetShareValueMultiplierByBank,
57934
57842
  addressLookupTableAccounts,
57935
57843
  crossbarUrl
57936
57844
  } = params;
57937
- const resolved = await resolveRoll(params);
57845
+ if (!rollOpts.maturedMarket && !rollOpts.maturedVault) {
57846
+ throw new Error("roll-pt: rollOpts.maturedMarket or maturedVault is required");
57847
+ }
57848
+ const wrapper = await resolveExponentWrapperMergeContext({
57849
+ connection,
57850
+ owner: marginfiAccount.authority,
57851
+ market: rollOpts.maturedMarket,
57852
+ vault: rollOpts.maturedVault,
57853
+ baseMint: rollOpts.baseMint,
57854
+ baseTokenProgram: rollOpts.baseTokenProgram,
57855
+ ptYtTokenProgram: withdrawOpts.tokenProgram
57856
+ });
57938
57857
  const blockhash = (await connection.getLatestBlockhash("confirmed")).blockhash;
57939
57858
  const setupIxs = await makeSetupIx({
57940
57859
  connection,
57941
57860
  authority: marginfiAccount.authority,
57942
57861
  tokens: [
57943
57862
  { mint: withdrawOpts.withdrawBank.mint, tokenProgram: withdrawOpts.tokenProgram },
57944
- { mint: resolved.syToken.mint, tokenProgram: resolved.syToken.tokenProgram },
57945
- { mint: resolved.mergeAccounts.mintYt, tokenProgram: TOKEN_PROGRAM_ID },
57863
+ ...wrapper.setupMints,
57946
57864
  { mint: depositOpts.depositBank.mint, tokenProgram: depositOpts.tokenProgram }
57947
57865
  ]
57948
57866
  });
57949
- if (resolved.buySetupInstructions.length) {
57950
- setupIxs.push(...resolved.buySetupInstructions);
57951
- }
57952
- const { flashloanTx, withdrawIxs, depositIxs } = await buildRollPtFlashloanTx({
57953
- params,
57954
- resolved,
57955
- blockhash
57867
+ setupIxs.push(...wrapper.preInstructions);
57868
+ const { flashloanTx, setupInstructions, swapQuote, withdrawIxs, depositIxs } = await buildRollPtFlashloanTx({ params, wrapper, blockhash });
57869
+ const swapSetupInstructions = setupInstructions.filter((ix) => {
57870
+ if (ix.programId.equals(ComputeBudgetProgram.programId)) return false;
57871
+ if (ix.programId.equals(ASSOCIATED_TOKEN_PROGRAM_ID)) {
57872
+ const mintKey = ix.keys[3]?.pubkey;
57873
+ if (mintKey?.equals(withdrawOpts.withdrawBank.mint) || mintKey?.equals(depositOpts.depositBank.mint)) {
57874
+ return false;
57875
+ }
57876
+ }
57877
+ return true;
57956
57878
  });
57879
+ setupIxs.push(...swapSetupInstructions);
57957
57880
  const { instructions: updateFeedIxs, luts: feedLuts } = await makeSmartCrankSwbFeedIx({
57958
57881
  marginfiAccount,
57959
57882
  bankMap,
@@ -57997,12 +57920,12 @@ async function makeRollPtTx(params) {
57997
57920
  return {
57998
57921
  transactions,
57999
57922
  actionTxIndex: transactions.length - 1,
58000
- quoteResponse: void 0
57923
+ quoteResponse: swapQuote
58001
57924
  };
58002
57925
  }
58003
57926
  async function buildRollPtFlashloanTx({
58004
57927
  params,
58005
- resolved,
57928
+ wrapper,
58006
57929
  blockhash
58007
57930
  }) {
58008
57931
  const {
@@ -58011,27 +57934,29 @@ async function buildRollPtFlashloanTx({
58011
57934
  bankMap,
58012
57935
  withdrawOpts,
58013
57936
  depositOpts,
57937
+ swapOpts,
58014
57938
  bankMetadataMap,
57939
+ connection,
58015
57940
  addressLookupTableAccounts,
58016
- overrideInferAccounts
57941
+ overrideInferAccounts,
57942
+ rollOpts,
57943
+ swapEngineRunner
58017
57944
  } = params;
58018
- const {
58019
- actualWithdrawAmount,
58020
- isFullWithdraw,
58021
- mergeAccounts,
58022
- buyInstructions,
58023
- ptOutNative,
58024
- rollLuts
58025
- } = resolved;
58026
- const { withdrawBank, tokenProgram: withdrawTokenProgram } = withdrawOpts;
57945
+ const { withdrawBank, tokenProgram: withdrawTokenProgram, totalPositionAmount, withdrawAmount } = withdrawOpts;
58027
57946
  const { depositBank, tokenProgram: depositTokenProgram } = depositOpts;
58028
57947
  const authority = marginfiAccount.authority;
58029
- if (ptOutNative <= 0n) {
58030
- throw new Error("roll-pt: ptOutNative (PT to buy) must be greater than 0");
58031
- }
58032
- if (buyInstructions.length === 0) {
58033
- throw new Error("roll-pt: buy leg (SY \u2192 PT_new) must not be empty");
57948
+ if (withdrawAmount !== void 0 && withdrawAmount <= 0) {
57949
+ throw new Error("withdrawAmount must be greater than 0");
58034
57950
  }
57951
+ const actualWithdrawAmount = Math.min(withdrawAmount ?? totalPositionAmount, totalPositionAmount);
57952
+ const isFullWithdraw = isWholePosition(
57953
+ { amount: totalPositionAmount, isLending: true },
57954
+ actualWithdrawAmount,
57955
+ withdrawBank.mintDecimals
57956
+ );
57957
+ const withdrawNative = BigInt(
57958
+ uiToNative(actualWithdrawAmount, withdrawBank.mintDecimals).toString()
57959
+ );
58035
57960
  const cuRequestIxs = [
58036
57961
  ComputeBudgetProgram.setComputeUnitLimit({ units: 12e5 }),
58037
57962
  ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 })
@@ -58048,10 +57973,11 @@ async function buildRollPtFlashloanTx({
58048
57973
  isSync: false,
58049
57974
  opts: { createAtas: false, wrapAndUnwrapSol: false, overrideInferAccounts }
58050
57975
  });
58051
- const mergeIx = makeExponentMergeIx(
58052
- mergeAccounts,
58053
- BigInt(uiToNative(actualWithdrawAmount, withdrawBank.mintDecimals).toString())
58054
- );
57976
+ const wrapperMergeIx = makeExponentWrapperMergeIx(wrapper.wrapperMergeAccounts, {
57977
+ amountPyNative: withdrawNative,
57978
+ redeemSyAccountsUntil: wrapper.wrapperMergeAccounts.redeemSyAccountsUntil
57979
+ });
57980
+ const redeemIxs = [wrapperMergeIx];
58055
57981
  const depositIxs = await makeDepositIx3({
58056
57982
  program,
58057
57983
  bank: depositBank,
@@ -58062,19 +57988,77 @@ async function buildRollPtFlashloanTx({
58062
57988
  group: marginfiAccount.group,
58063
57989
  opts: { wrapAndUnwrapSol: false, overrideInferAccounts }
58064
57990
  });
57991
+ let baseLuts;
57992
+ if (rollOpts.lookupTable) {
57993
+ const fetched = (await connection.getAddressLookupTable(rollOpts.lookupTable)).value;
57994
+ if (!fetched) {
57995
+ throw new Error(`roll-pt: PT-roll lookup table not found: ${rollOpts.lookupTable.toBase58()}`);
57996
+ }
57997
+ baseLuts = [fetched];
57998
+ } else {
57999
+ baseLuts = [...addressLookupTableAccounts ?? [], wrapper.addressLookupTable];
58000
+ }
58001
+ const nonSwapFootprint = [
58002
+ ...cuRequestIxs,
58003
+ ...withdrawIxs.instructions,
58004
+ ...redeemIxs,
58005
+ ...depositIxs.instructions
58006
+ ];
58007
+ const { sizeConstraint, maxSwapTotalAccounts } = computeFlashLoanNonSwapBudget({
58008
+ program,
58009
+ marginfiAccount,
58010
+ bankMap,
58011
+ addressLookupTableAccounts: baseLuts,
58012
+ ixs: nonSwapFootprint
58013
+ });
58014
+ const destinationTokenAccount = getAssociatedTokenAddressSync(
58015
+ depositBank.mint,
58016
+ authority,
58017
+ true,
58018
+ depositTokenProgram.equals(TOKEN_2022_PROGRAM_ID) ? TOKEN_2022_PROGRAM_ID : void 0
58019
+ );
58020
+ const baseAmountNative = wrapper.computeRedeemedBaseNative(withdrawNative);
58021
+ const runEngine = swapEngineRunner ?? runSwapEngine;
58022
+ const engineResult = await runEngine({
58023
+ inputMint: wrapper.baseToken.mint.toBase58(),
58024
+ outputMint: depositBank.mint.toBase58(),
58025
+ amountNative: Number(baseAmountNative),
58026
+ inputDecimals: wrapper.baseToken.decimals,
58027
+ outputDecimals: depositBank.mintDecimals,
58028
+ ...swapEngineQuoteFieldsFromOpts(swapOpts),
58029
+ taker: authority,
58030
+ destinationTokenAccount,
58031
+ connection,
58032
+ footprint: {
58033
+ instructions: nonSwapFootprint,
58034
+ luts: baseLuts,
58035
+ payer: authority,
58036
+ sizeConstraint,
58037
+ maxSwapTotalAccounts
58038
+ },
58039
+ providers: swapEngineProvidersFromOpts(swapOpts)
58040
+ });
58065
58041
  const depositIxToPatch = depositIxs.instructions.find(isDepositIx);
58066
58042
  if (!depositIxToPatch) {
58067
58043
  throw new Error("roll-pt: could not locate deposit instruction for amount patching");
58068
58044
  }
58069
- patchDepositAmount(depositIxToPatch, new BN11(ptOutNative.toString()));
58070
- const luts = [...addressLookupTableAccounts ?? [], ...rollLuts];
58045
+ patchDepositAmount(depositIxToPatch, engineResult.outputAmountNative);
58046
+ const luts = [...baseLuts, ...engineResult.swapLuts];
58071
58047
  const allNonFlIxs = [
58072
58048
  ...cuRequestIxs,
58073
58049
  ...withdrawIxs.instructions,
58074
- mergeIx,
58075
- ...buyInstructions,
58050
+ ...redeemIxs,
58051
+ ...engineResult.swapInstructions,
58076
58052
  ...depositIxs.instructions
58077
58053
  ];
58054
+ compileFlashloanPrecheck({
58055
+ allIxs: allNonFlIxs,
58056
+ payer: authority,
58057
+ luts,
58058
+ sizeConstraint,
58059
+ swapIxCount: engineResult.swapInstructions.length,
58060
+ swapLutCount: engineResult.swapLuts.length
58061
+ });
58078
58062
  const flashloanTx = await makeFlashLoanTx({
58079
58063
  program,
58080
58064
  marginfiAccount,
@@ -58087,10 +58071,16 @@ async function buildRollPtFlashloanTx({
58087
58071
  const txSize = getTxSize(flashloanTx);
58088
58072
  const totalKeys = getTotalAccountKeys(flashloanTx);
58089
58073
  if (txSize > MAX_TX_SIZE || totalKeys > MAX_ACCOUNT_LOCKS) {
58090
- throw TransactionBuildingError.swapSizeExceededPositionSwap(txSize, totalKeys);
58074
+ throw TransactionBuildingError.swapSizeExceededPositionSwap(
58075
+ txSize,
58076
+ totalKeys,
58077
+ swapOpts.swapConfig?.provider
58078
+ );
58091
58079
  }
58092
58080
  return {
58093
58081
  flashloanTx,
58082
+ setupInstructions: engineResult.setupInstructions,
58083
+ swapQuote: engineResult.quoteResponse,
58094
58084
  withdrawIxs,
58095
58085
  depositIxs
58096
58086
  };
@@ -62881,9 +62871,10 @@ var MarginfiAccount = class _MarginfiAccount {
62881
62871
  /**
62882
62872
  * Creates a transaction to roll a matured Exponent PT collateral position into its
62883
62873
  * next-maturity PT, in one flash-loan-wrapped bundle
62884
- * (withdraw PT_old → merge → buy PT_new → deposit). See {@link makeRollPtTx}.
62874
+ * (withdraw PT_old → `wrapper_merge` to base swap-engine buy PT_new → deposit).
62875
+ * See {@link makeRollPtTx}.
62885
62876
  *
62886
- * @param params - Roll-PT parameters (`withdrawOpts`/`depositOpts`/`rollOpts`).
62877
+ * @param params - Roll-PT parameters (`withdrawOpts`/`depositOpts`/`swapOpts`/`rollOpts`).
62887
62878
  */
62888
62879
  async makeRollPtTx(params) {
62889
62880
  return makeRollPtTx({
@@ -63415,12 +63406,12 @@ var MarginfiAccountWrapper = class {
63415
63406
  }
63416
63407
  /**
63417
63408
  * Rolls a matured Exponent PT collateral position into its next-maturity PT, with
63418
- * auto-injected client data (withdraw PT_old → merge buy PT_new deposit, flash-loan
63419
- * wrapped). The buy leg is venue-agnostic supplied via `rollOpts.buyInstructions`.
63409
+ * auto-injected client data (withdraw PT_old → `wrapper_merge` to baseswap-engine buy
63410
+ * PT_new → deposit, flash-loan wrapped). The full deposit ends up as new PT.
63420
63411
  *
63421
63412
  * Auto-injects: program, marginfiAccount, bankMap, oraclePrices, bankMetadataMap, addressLookupTables
63422
63413
  *
63423
- * @param params - Roll-PT parameters (user provides: connection, withdrawOpts, depositOpts, rollOpts, etc.)
63414
+ * @param params - Roll-PT parameters (user provides: connection, withdrawOpts, depositOpts, swapOpts, rollOpts, etc.)
63424
63415
  */
63425
63416
  async makeRollPtTx(params) {
63426
63417
  const fullParams = {