@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.cjs CHANGED
@@ -36218,7 +36218,7 @@ async function makeSetupIx({ connection, authority, tokens }) {
36218
36218
  let ixs = [];
36219
36219
  const userAtaAis = await connection.getMultipleAccountsInfo(userAtas);
36220
36220
  for (const [i, userAta] of userAtaAis.entries()) {
36221
- const token = tokens[i];
36221
+ const token = uniqueTokens[i];
36222
36222
  const userAtaAddress = userAtas[i];
36223
36223
  if (userAta === null && token && userAtaAddress) {
36224
36224
  ixs.push(
@@ -44635,11 +44635,13 @@ function selectBestRoute(quotes, swapMode) {
44635
44635
  }
44636
44636
  function buildSwapQuoteResult(route, swapMode) {
44637
44637
  const slippageBps = route.slippageBps;
44638
+ const outAmount = Number(route.outAmount);
44639
+ const inAmount = Number(route.inAmount);
44638
44640
  let otherAmountThreshold;
44639
44641
  if (swapMode === "ExactIn") {
44640
- otherAmountThreshold = String(Math.floor(route.outAmount * (1 - slippageBps / 1e4)));
44642
+ otherAmountThreshold = String(Math.floor(outAmount * (1 - slippageBps / 1e4)));
44641
44643
  } else {
44642
- otherAmountThreshold = String(Math.ceil(route.inAmount * (1 + slippageBps / 1e4)));
44644
+ otherAmountThreshold = String(Math.ceil(inAmount * (1 + slippageBps / 1e4)));
44643
44645
  }
44644
44646
  return {
44645
44647
  inAmount: String(route.inAmount),
@@ -52032,6 +52034,59 @@ function deriveExponentEventAuthority() {
52032
52034
  EXPONENT_CORE_PROGRAM_ID
52033
52035
  )[0];
52034
52036
  }
52037
+ Buffer.from([5]);
52038
+ Buffer.from([17]);
52039
+ Buffer.from([4]);
52040
+ var WRAPPER_MERGE_DISCRIMINATOR = Buffer.from([39]);
52041
+ function makeExponentWrapperMergeIx(accounts, args) {
52042
+ const tokenProgram = accounts.tokenProgram ?? TOKEN_PROGRAM_ID;
52043
+ const eventAuthority = deriveExponentEventAuthority();
52044
+ const data = Buffer.alloc(WRAPPER_MERGE_DISCRIMINATOR.length + 9);
52045
+ WRAPPER_MERGE_DISCRIMINATOR.copy(data, 0);
52046
+ data.writeBigUInt64LE(args.amountPyNative, WRAPPER_MERGE_DISCRIMINATOR.length);
52047
+ data.writeUInt8(args.redeemSyAccountsUntil, WRAPPER_MERGE_DISCRIMINATOR.length + 8);
52048
+ const keys = [
52049
+ { pubkey: accounts.owner, isSigner: true, isWritable: true },
52050
+ { pubkey: accounts.syAta, isSigner: false, isWritable: true },
52051
+ { pubkey: accounts.vault, isSigner: false, isWritable: true },
52052
+ { pubkey: accounts.escrowSy, isSigner: false, isWritable: true },
52053
+ { pubkey: accounts.ytAta, isSigner: false, isWritable: true },
52054
+ { pubkey: accounts.ptAta, isSigner: false, isWritable: true },
52055
+ { pubkey: accounts.mintYt, isSigner: false, isWritable: true },
52056
+ { pubkey: accounts.mintPt, isSigner: false, isWritable: true },
52057
+ { pubkey: accounts.authority, isSigner: false, isWritable: true },
52058
+ { pubkey: accounts.addressLookupTable, isSigner: false, isWritable: false },
52059
+ { pubkey: tokenProgram, isSigner: false, isWritable: false },
52060
+ { pubkey: accounts.yieldPosition, isSigner: false, isWritable: true },
52061
+ { pubkey: accounts.syProgram, isSigner: false, isWritable: false },
52062
+ { pubkey: web3_js.SystemProgram.programId, isSigner: false, isWritable: false },
52063
+ { pubkey: eventAuthority, isSigner: false, isWritable: false },
52064
+ { pubkey: EXPONENT_CORE_PROGRAM_ID, isSigner: false, isWritable: false },
52065
+ // [...redeem (flavor SY-redeem accounts), ...cpi (withdraw_sy ++ get_sy_state)]
52066
+ ...accounts.remainingAccounts
52067
+ ];
52068
+ return new web3_js.TransactionInstruction({ keys, programId: EXPONENT_CORE_PROGRAM_ID, data });
52069
+ }
52070
+ var SPL_STAKE_POOL_UPDATE_BALANCE_TAG = Buffer.from([7]);
52071
+ function makeSplStakePoolUpdateBalanceIx(accounts) {
52072
+ const tokenProgram = accounts.tokenProgram ?? TOKEN_PROGRAM_ID;
52073
+ const keys = [
52074
+ { pubkey: accounts.stakePool, isSigner: false, isWritable: true },
52075
+ { pubkey: accounts.withdrawAuthority, isSigner: false, isWritable: false },
52076
+ { pubkey: accounts.validatorList, isSigner: false, isWritable: true },
52077
+ { pubkey: accounts.reserveStake, isSigner: false, isWritable: false },
52078
+ { pubkey: accounts.managerFeeAccount, isSigner: false, isWritable: true },
52079
+ { pubkey: accounts.poolMint, isSigner: false, isWritable: true },
52080
+ { pubkey: tokenProgram, isSigner: false, isWritable: false }
52081
+ ];
52082
+ return new web3_js.TransactionInstruction({
52083
+ keys,
52084
+ programId: accounts.stakePoolProgram,
52085
+ data: Buffer.from(SPL_STAKE_POOL_UPDATE_BALANCE_TAG)
52086
+ });
52087
+ }
52088
+
52089
+ // src/vendor/exponent/utils/resolve.utils.ts
52035
52090
  function resolveCpiMetas(contexts, altAddresses, altKey) {
52036
52091
  return contexts.map((ctx) => {
52037
52092
  const pubkey = altAddresses[ctx.altIndex];
@@ -52043,10 +52098,46 @@ function resolveCpiMetas(contexts, altAddresses, altKey) {
52043
52098
  return { pubkey, isSigner: false, isWritable: ctx.isWritable };
52044
52099
  });
52045
52100
  }
52046
- async function resolveExponentMergeContext(params) {
52047
- const { connection, owner } = params;
52101
+ function uniqueRemainingAccounts(metas) {
52102
+ const seen = /* @__PURE__ */ new Map();
52103
+ for (const m of metas) {
52104
+ const key = m.pubkey.toBase58();
52105
+ const prev = seen.get(key);
52106
+ if (prev) prev.isWritable = prev.isWritable || m.isWritable;
52107
+ else seen.set(key, { ...m });
52108
+ }
52109
+ return [...seen.values()];
52110
+ }
52111
+ var STAKE_POOL_OFFSETS = {
52112
+ validatorList: 98,
52113
+ reserveStake: 130,
52114
+ poolMint: 162,
52115
+ managerFeeAccount: 194
52116
+ };
52117
+ async function resolveSplStakePoolRefreshIx(connection, stakePool) {
52118
+ const info = await connection.getAccountInfo(stakePool);
52119
+ if (!info) throw new Error(`SPL stake pool account not found: ${stakePool.toBase58()}`);
52120
+ const stakePoolProgram = info.owner;
52121
+ const at = (off) => new web3_js.PublicKey(info.data.subarray(off, off + 32));
52122
+ const [withdrawAuthority] = web3_js.PublicKey.findProgramAddressSync(
52123
+ [stakePool.toBuffer(), Buffer.from("withdraw")],
52124
+ stakePoolProgram
52125
+ );
52126
+ return makeSplStakePoolUpdateBalanceIx({
52127
+ stakePoolProgram,
52128
+ stakePool,
52129
+ withdrawAuthority,
52130
+ validatorList: at(STAKE_POOL_OFFSETS.validatorList),
52131
+ reserveStake: at(STAKE_POOL_OFFSETS.reserveStake),
52132
+ managerFeeAccount: at(STAKE_POOL_OFFSETS.managerFeeAccount),
52133
+ poolMint: at(STAKE_POOL_OFFSETS.poolMint)
52134
+ });
52135
+ }
52136
+ async function resolveExponentWrapperMergeContext(params) {
52137
+ const { connection, owner, baseMint } = params;
52048
52138
  const ptYtTokenProgram = params.ptYtTokenProgram ?? TOKEN_PROGRAM_ID;
52049
52139
  const syTokenProgram = params.syTokenProgram ?? TOKEN_PROGRAM_ID;
52140
+ const baseTokenProgram = params.baseTokenProgram ?? TOKEN_PROGRAM_ID;
52050
52141
  let vaultAddress;
52051
52142
  let vault;
52052
52143
  if (params.vault) {
@@ -52057,11 +52148,8 @@ async function resolveExponentMergeContext(params) {
52057
52148
  vaultAddress = res.vault;
52058
52149
  vault = res.account;
52059
52150
  } else {
52060
- throw new Error("resolveExponentMergeContext: one of `vault` or `market` is required");
52151
+ throw new Error("resolveExponentWrapperMergeContext: one of `vault` or `market` is required");
52061
52152
  }
52062
- const ptSrcAta = getAssociatedTokenAddressSync(vault.mintPt, owner, true, ptYtTokenProgram);
52063
- const ytSrcAta = getAssociatedTokenAddressSync(vault.mintYt, owner, true, ptYtTokenProgram);
52064
- const sySrcDstAta = getAssociatedTokenAddressSync(vault.mintSy, owner, true, syTokenProgram);
52065
52153
  const altResult = await connection.getAddressLookupTable(vault.addressLookupTable);
52066
52154
  const alt = altResult.value;
52067
52155
  if (!alt) {
@@ -52069,169 +52157,75 @@ async function resolveExponentMergeContext(params) {
52069
52157
  `Exponent vault address lookup table not found: ${vault.addressLookupTable.toBase58()}`
52070
52158
  );
52071
52159
  }
52072
- const remainingAccounts = [
52073
- ...resolveCpiMetas(vault.cpiAccounts.getSyState, alt.state.addresses, vault.addressLookupTable),
52074
- ...resolveCpiMetas(vault.cpiAccounts.withdrawSy, alt.state.addresses, vault.addressLookupTable)
52075
- ];
52076
- const mergeAccounts = {
52077
- owner,
52078
- authority: vault.authority,
52079
- vault: vaultAddress,
52080
- sySrcDstAta,
52081
- escrowSy: vault.escrowSy,
52082
- ytSrcAta,
52083
- ptSrcAta,
52084
- mintYt: vault.mintYt,
52085
- mintPt: vault.mintPt,
52086
- syProgram: vault.syProgram,
52087
- addressLookupTable: vault.addressLookupTable,
52088
- yieldPosition: vault.yieldPosition,
52089
- tokenProgram: ptYtTokenProgram,
52090
- remainingAccounts
52091
- };
52092
- const decimals = await getMintDecimals(connection, vault.mintSy);
52093
- return {
52094
- vaultAddress,
52095
- vault,
52096
- mergeAccounts,
52097
- addressLookupTable: alt,
52098
- underlying: { mint: vault.mintSy, decimals, tokenProgram: syTokenProgram },
52099
- computeRedeemedAmountNative(ptAmountNative) {
52100
- if (vault.ptSupply === 0n) return 0n;
52101
- const sy = new BigNumber3.BigNumber(ptAmountNative.toString()).times(vault.syForPt.toString()).div(vault.ptSupply.toString()).integerValue(BigNumber3.BigNumber.ROUND_FLOOR);
52102
- return BigInt(sy.toFixed(0));
52103
- }
52104
- };
52105
- }
52106
- async function resolveExponentStripContext(params) {
52107
- const { connection, owner } = params;
52108
- const ptYtTokenProgram = params.ptYtTokenProgram ?? TOKEN_PROGRAM_ID;
52109
- const syTokenProgram = params.syTokenProgram ?? TOKEN_PROGRAM_ID;
52110
- let vaultAddress;
52111
- let vault;
52112
- if (params.vault) {
52113
- vaultAddress = params.vault;
52114
- vault = await fetchExponentVault(connection, vaultAddress);
52115
- } else if (params.market) {
52116
- const res = await fetchExponentVaultFromMarket(connection, params.market);
52117
- vaultAddress = res.vault;
52118
- vault = res.account;
52119
- } else {
52120
- throw new Error("resolveExponentStripContext: one of `vault` or `market` is required");
52121
- }
52122
- const altResult = await connection.getAddressLookupTable(vault.addressLookupTable);
52123
- const alt = altResult.value;
52124
- if (!alt) {
52160
+ const altKey = vault.addressLookupTable;
52161
+ const getSyState = resolveCpiMetas(vault.cpiAccounts.getSyState, alt.state.addresses, altKey);
52162
+ const withdrawSy = resolveCpiMetas(vault.cpiAccounts.withdrawSy, alt.state.addresses, altKey);
52163
+ if (getSyState.length < 4) {
52125
52164
  throw new Error(
52126
- `Exponent vault address lookup table not found: ${vault.addressLookupTable.toBase58()}`
52165
+ "resolveExponentWrapperMergeContext: unexpected get_sy_state shape (expected the generic SPL-stake-pool flavor: [syState, mintSy, tokenSyEscrow, stakePool])"
52127
52166
  );
52128
52167
  }
52129
- const remainingAccounts = resolveCpiMetas(
52130
- vault.cpiAccounts.depositSy,
52131
- alt.state.addresses,
52132
- vault.addressLookupTable
52133
- );
52134
- const sySrc = getAssociatedTokenAddressSync(vault.mintSy, owner, true, syTokenProgram);
52135
- const ptDst = getAssociatedTokenAddressSync(vault.mintPt, owner, true, ptYtTokenProgram);
52136
- const ytDst = getAssociatedTokenAddressSync(vault.mintYt, owner, true, ptYtTokenProgram);
52137
- const stripAccounts = {
52138
- depositor: owner,
52139
- authority: vault.authority,
52168
+ const syState = getSyState[0].pubkey;
52169
+ const stakePool = getSyState[3].pubkey;
52170
+ const syAta = getAssociatedTokenAddressSync(vault.mintSy, owner, true, syTokenProgram);
52171
+ const ptAta = getAssociatedTokenAddressSync(vault.mintPt, owner, true, ptYtTokenProgram);
52172
+ const ytAta = getAssociatedTokenAddressSync(vault.mintYt, owner, true, ptYtTokenProgram);
52173
+ const baseAta = getAssociatedTokenAddressSync(baseMint, owner, true, baseTokenProgram);
52174
+ const baseEscrow = getAssociatedTokenAddressSync(baseMint, syState, true, baseTokenProgram);
52175
+ const redeem = [
52176
+ { pubkey: owner, isSigner: true, isWritable: true },
52177
+ { pubkey: syState, isSigner: false, isWritable: true },
52178
+ { pubkey: baseAta, isSigner: false, isWritable: true },
52179
+ { pubkey: baseEscrow, isSigner: false, isWritable: true },
52180
+ { pubkey: syAta, isSigner: false, isWritable: true },
52181
+ { pubkey: vault.mintSy, isSigner: false, isWritable: true },
52182
+ { pubkey: baseMint, isSigner: false, isWritable: false },
52183
+ { pubkey: syTokenProgram, isSigner: false, isWritable: false },
52184
+ { pubkey: baseTokenProgram, isSigner: false, isWritable: false },
52185
+ { pubkey: stakePool, isSigner: false, isWritable: true }
52186
+ ];
52187
+ const cpi = uniqueRemainingAccounts([...withdrawSy, ...getSyState]);
52188
+ const wrapperMergeAccounts = {
52189
+ owner,
52190
+ syAta,
52140
52191
  vault: vaultAddress,
52141
- sySrc,
52142
52192
  escrowSy: vault.escrowSy,
52143
- ytDst,
52144
- ptDst,
52193
+ ytAta,
52194
+ ptAta,
52145
52195
  mintYt: vault.mintYt,
52146
52196
  mintPt: vault.mintPt,
52147
- syProgram: vault.syProgram,
52197
+ authority: vault.authority,
52148
52198
  addressLookupTable: vault.addressLookupTable,
52149
52199
  yieldPosition: vault.yieldPosition,
52200
+ syProgram: vault.syProgram,
52150
52201
  tokenProgram: ptYtTokenProgram,
52151
- remainingAccounts
52202
+ remainingAccounts: [...redeem, ...cpi],
52203
+ redeemSyAccountsUntil: redeem.length
52152
52204
  };
52153
- const [syDecimals, ptDecimals] = await Promise.all([
52154
- getMintDecimals(connection, vault.mintSy),
52155
- getMintDecimals(connection, vault.mintPt)
52205
+ const [baseDecimals, stakePoolRefreshIx] = await Promise.all([
52206
+ getMintDecimals(connection, baseMint),
52207
+ resolveSplStakePoolRefreshIx(connection, stakePool)
52156
52208
  ]);
52157
- const syExchangeRate = vault.lastSeenSyExchangeRate.toNumber();
52158
52209
  return {
52159
52210
  vaultAddress,
52160
52211
  vault,
52161
- stripAccounts,
52212
+ wrapperMergeAccounts,
52213
+ preInstructions: [stakePoolRefreshIx],
52162
52214
  addressLookupTable: alt,
52163
- sy: { mint: vault.mintSy, decimals: syDecimals, tokenProgram: syTokenProgram },
52164
- pt: { mint: vault.mintPt, decimals: ptDecimals, tokenProgram: ptYtTokenProgram },
52165
- yt: { mint: vault.mintYt, tokenProgram: ptYtTokenProgram },
52166
- syExchangeRate,
52167
- computeStrippedPtNative(syInNative) {
52168
- const pt = vault.lastSeenSyExchangeRate.times(syInNative.toString()).integerValue(BigNumber3.BigNumber.ROUND_FLOOR);
52169
- return BigInt(pt.toFixed(0));
52215
+ baseToken: { mint: baseMint, decimals: baseDecimals, tokenProgram: baseTokenProgram },
52216
+ setupMints: [
52217
+ { mint: baseMint, tokenProgram: baseTokenProgram },
52218
+ { mint: vault.mintSy, tokenProgram: syTokenProgram },
52219
+ { mint: vault.mintPt, tokenProgram: ptYtTokenProgram },
52220
+ { mint: vault.mintYt, tokenProgram: ptYtTokenProgram }
52221
+ ],
52222
+ computeRedeemedBaseNative(ptAmountNative) {
52223
+ if (vault.ptSupply === 0n) return 0n;
52224
+ const base = new BigNumber3.BigNumber(ptAmountNative.toString()).times(vault.syForPt.toString()).div(vault.ptSupply.toString()).integerValue(BigNumber3.BigNumber.ROUND_FLOOR);
52225
+ return BigInt(base.toFixed(0));
52170
52226
  }
52171
52227
  };
52172
52228
  }
52173
- var MERGE_DISCRIMINATOR = Buffer.from([5]);
52174
- function makeExponentMergeIx(accounts, amountNative) {
52175
- const tokenProgram = accounts.tokenProgram ?? TOKEN_PROGRAM_ID;
52176
- const eventAuthority = deriveExponentEventAuthority();
52177
- const data = Buffer.alloc(MERGE_DISCRIMINATOR.length + 8);
52178
- MERGE_DISCRIMINATOR.copy(data, 0);
52179
- data.writeBigUInt64LE(amountNative, MERGE_DISCRIMINATOR.length);
52180
- const keys = [
52181
- { pubkey: accounts.owner, isSigner: true, isWritable: true },
52182
- { pubkey: accounts.authority, isSigner: false, isWritable: true },
52183
- { pubkey: accounts.vault, isSigner: false, isWritable: true },
52184
- { pubkey: accounts.sySrcDstAta, isSigner: false, isWritable: true },
52185
- { pubkey: accounts.escrowSy, isSigner: false, isWritable: true },
52186
- { pubkey: accounts.ytSrcAta, isSigner: false, isWritable: true },
52187
- { pubkey: accounts.ptSrcAta, isSigner: false, isWritable: true },
52188
- { pubkey: accounts.mintYt, isSigner: false, isWritable: true },
52189
- { pubkey: accounts.mintPt, isSigner: false, isWritable: true },
52190
- { pubkey: tokenProgram, isSigner: false, isWritable: false },
52191
- { pubkey: accounts.syProgram, isSigner: false, isWritable: false },
52192
- { pubkey: accounts.addressLookupTable, isSigner: false, isWritable: false },
52193
- { pubkey: accounts.yieldPosition, isSigner: false, isWritable: true },
52194
- { pubkey: eventAuthority, isSigner: false, isWritable: false },
52195
- { pubkey: EXPONENT_CORE_PROGRAM_ID, isSigner: false, isWritable: false },
52196
- // SY-program CPI accounts (getSyState ++ withdrawSy), ALT-resolved (post-maturity merge
52197
- // still CPIs into the SY program to move SY out of escrow).
52198
- ...accounts.remainingAccounts ?? []
52199
- ];
52200
- return new web3_js.TransactionInstruction({
52201
- keys,
52202
- programId: EXPONENT_CORE_PROGRAM_ID,
52203
- data
52204
- });
52205
- }
52206
- Buffer.from([17]);
52207
- var STRIP_DISCRIMINATOR = Buffer.from([4]);
52208
- function makeExponentStripIx(accounts, amountNative) {
52209
- const tokenProgram = accounts.tokenProgram ?? TOKEN_PROGRAM_ID;
52210
- const eventAuthority = deriveExponentEventAuthority();
52211
- const data = Buffer.alloc(STRIP_DISCRIMINATOR.length + 8);
52212
- STRIP_DISCRIMINATOR.copy(data, 0);
52213
- data.writeBigUInt64LE(amountNative, STRIP_DISCRIMINATOR.length);
52214
- const keys = [
52215
- { pubkey: accounts.depositor, isSigner: true, isWritable: true },
52216
- { pubkey: accounts.authority, isSigner: false, isWritable: true },
52217
- { pubkey: accounts.vault, isSigner: false, isWritable: true },
52218
- { pubkey: accounts.sySrc, isSigner: false, isWritable: true },
52219
- { pubkey: accounts.escrowSy, isSigner: false, isWritable: true },
52220
- { pubkey: accounts.ytDst, isSigner: false, isWritable: true },
52221
- { pubkey: accounts.ptDst, isSigner: false, isWritable: true },
52222
- { pubkey: accounts.mintYt, isSigner: false, isWritable: true },
52223
- { pubkey: accounts.mintPt, isSigner: false, isWritable: true },
52224
- { pubkey: tokenProgram, isSigner: false, isWritable: false },
52225
- { pubkey: accounts.addressLookupTable, isSigner: false, isWritable: false },
52226
- { pubkey: accounts.syProgram, isSigner: false, isWritable: false },
52227
- { pubkey: accounts.yieldPosition, isSigner: false, isWritable: true },
52228
- { pubkey: eventAuthority, isSigner: false, isWritable: false },
52229
- { pubkey: EXPONENT_CORE_PROGRAM_ID, isSigner: false, isWritable: false },
52230
- // SY-program CPI accounts (depositSy), ALT-resolved.
52231
- ...accounts.remainingAccounts ?? []
52232
- ];
52233
- return new web3_js.TransactionInstruction({ keys, programId: EXPONENT_CORE_PROGRAM_ID, data });
52234
- }
52235
52229
 
52236
52230
  // src/vendor/klend/utils/klend/interest-rate.utils.ts
52237
52231
  function getKaminoTotalSupply(reserve) {
@@ -57861,93 +57855,6 @@ async function buildSwapDebtFlashloanTx({
57861
57855
  repayIxs
57862
57856
  };
57863
57857
  }
57864
- var DEFAULT_ROLL_SLIPPAGE_BPS = 10;
57865
- async function resolveRoll(params) {
57866
- const { connection, marginfiAccount, withdrawOpts, rollOpts } = params;
57867
- const owner = marginfiAccount.authority;
57868
- const slippageBps = rollOpts.slippageBps ?? DEFAULT_ROLL_SLIPPAGE_BPS;
57869
- const keepBps = BigInt(1e4 - slippageBps);
57870
- if (withdrawOpts.withdrawAmount !== void 0 && withdrawOpts.withdrawAmount <= 0) {
57871
- throw new Error("withdrawAmount must be greater than 0");
57872
- }
57873
- const actualWithdrawAmount = Math.min(
57874
- withdrawOpts.withdrawAmount ?? withdrawOpts.totalPositionAmount,
57875
- withdrawOpts.totalPositionAmount
57876
- );
57877
- const isFullWithdraw = isWholePosition(
57878
- { amount: withdrawOpts.totalPositionAmount, isLending: true },
57879
- actualWithdrawAmount,
57880
- withdrawOpts.withdrawBank.mintDecimals
57881
- );
57882
- if (!rollOpts.maturedMarket && !rollOpts.maturedVault) {
57883
- throw new Error("roll-pt: rollOpts.maturedMarket or maturedVault is required");
57884
- }
57885
- const merge = await resolveExponentMergeContext({
57886
- connection,
57887
- owner,
57888
- market: rollOpts.maturedMarket,
57889
- vault: rollOpts.maturedVault
57890
- });
57891
- const withdrawNative = BigInt(
57892
- uiToNative(actualWithdrawAmount, withdrawOpts.withdrawBank.mintDecimals).toString()
57893
- );
57894
- const redeemedSy = merge.computeRedeemedAmountNative(withdrawNative);
57895
- const syToken = { mint: merge.underlying.mint, tokenProgram: merge.underlying.tokenProgram };
57896
- let buyInstructions;
57897
- let buySetupInstructions;
57898
- let buyLuts;
57899
- let ptOutNative;
57900
- if (rollOpts.buy) {
57901
- buyInstructions = rollOpts.buy.instructions;
57902
- buySetupInstructions = rollOpts.buy.setupInstructions ?? [];
57903
- buyLuts = rollOpts.buy.lookupTables ?? [];
57904
- ptOutNative = rollOpts.buy.ptOutNative;
57905
- } else {
57906
- if (!rollOpts.successorVault && !rollOpts.successorMarket) {
57907
- throw new Error(
57908
- "roll-pt: rollOpts.successorVault or successorMarket is required (or pass rollOpts.buy)"
57909
- );
57910
- }
57911
- const strip = await resolveExponentStripContext({
57912
- connection,
57913
- owner,
57914
- vault: rollOpts.successorVault,
57915
- market: rollOpts.successorMarket
57916
- });
57917
- const syIn = redeemedSy * keepBps / 10000n;
57918
- buyInstructions = [makeExponentStripIx(strip.stripAccounts, syIn)];
57919
- const ytAta = getAssociatedTokenAddressSync(strip.yt.mint, owner, true, strip.yt.tokenProgram);
57920
- buySetupInstructions = [
57921
- createAssociatedTokenAccountIdempotentInstruction(
57922
- owner,
57923
- ytAta,
57924
- owner,
57925
- strip.yt.mint,
57926
- strip.yt.tokenProgram
57927
- )
57928
- ];
57929
- buyLuts = [strip.addressLookupTable];
57930
- ptOutNative = strip.computeStrippedPtNative(syIn) * keepBps / 10000n;
57931
- }
57932
- const rollLuts = [merge.addressLookupTable, ...buyLuts];
57933
- if (rollOpts.lookupTable) {
57934
- const fetched = (await connection.getAddressLookupTable(rollOpts.lookupTable)).value;
57935
- if (!fetched) {
57936
- throw new Error(`roll-pt: PT-roll lookup table not found: ${rollOpts.lookupTable.toBase58()}`);
57937
- }
57938
- rollLuts.push(fetched);
57939
- }
57940
- return {
57941
- actualWithdrawAmount,
57942
- isFullWithdraw,
57943
- mergeAccounts: merge.mergeAccounts,
57944
- syToken,
57945
- buyInstructions,
57946
- buySetupInstructions,
57947
- ptOutNative,
57948
- rollLuts
57949
- };
57950
- }
57951
57858
  async function makeRollPtTx(params) {
57952
57859
  const {
57953
57860
  program,
@@ -57957,30 +57864,46 @@ async function makeRollPtTx(params) {
57957
57864
  oraclePrices,
57958
57865
  withdrawOpts,
57959
57866
  depositOpts,
57867
+ rollOpts,
57960
57868
  assetShareValueMultiplierByBank,
57961
57869
  addressLookupTableAccounts,
57962
57870
  crossbarUrl
57963
57871
  } = params;
57964
- const resolved = await resolveRoll(params);
57872
+ if (!rollOpts.maturedMarket && !rollOpts.maturedVault) {
57873
+ throw new Error("roll-pt: rollOpts.maturedMarket or maturedVault is required");
57874
+ }
57875
+ const wrapper = await resolveExponentWrapperMergeContext({
57876
+ connection,
57877
+ owner: marginfiAccount.authority,
57878
+ market: rollOpts.maturedMarket,
57879
+ vault: rollOpts.maturedVault,
57880
+ baseMint: rollOpts.baseMint,
57881
+ baseTokenProgram: rollOpts.baseTokenProgram,
57882
+ ptYtTokenProgram: withdrawOpts.tokenProgram
57883
+ });
57965
57884
  const blockhash = (await connection.getLatestBlockhash("confirmed")).blockhash;
57966
57885
  const setupIxs = await makeSetupIx({
57967
57886
  connection,
57968
57887
  authority: marginfiAccount.authority,
57969
57888
  tokens: [
57970
57889
  { mint: withdrawOpts.withdrawBank.mint, tokenProgram: withdrawOpts.tokenProgram },
57971
- { mint: resolved.syToken.mint, tokenProgram: resolved.syToken.tokenProgram },
57972
- { mint: resolved.mergeAccounts.mintYt, tokenProgram: TOKEN_PROGRAM_ID },
57890
+ ...wrapper.setupMints,
57973
57891
  { mint: depositOpts.depositBank.mint, tokenProgram: depositOpts.tokenProgram }
57974
57892
  ]
57975
57893
  });
57976
- if (resolved.buySetupInstructions.length) {
57977
- setupIxs.push(...resolved.buySetupInstructions);
57978
- }
57979
- const { flashloanTx, withdrawIxs, depositIxs } = await buildRollPtFlashloanTx({
57980
- params,
57981
- resolved,
57982
- blockhash
57894
+ setupIxs.push(...wrapper.preInstructions);
57895
+ const { flashloanTx, setupInstructions, swapQuote, withdrawIxs, depositIxs } = await buildRollPtFlashloanTx({ params, wrapper, blockhash });
57896
+ const swapSetupInstructions = setupInstructions.filter((ix) => {
57897
+ if (ix.programId.equals(web3_js.ComputeBudgetProgram.programId)) return false;
57898
+ if (ix.programId.equals(ASSOCIATED_TOKEN_PROGRAM_ID)) {
57899
+ const mintKey = ix.keys[3]?.pubkey;
57900
+ if (mintKey?.equals(withdrawOpts.withdrawBank.mint) || mintKey?.equals(depositOpts.depositBank.mint)) {
57901
+ return false;
57902
+ }
57903
+ }
57904
+ return true;
57983
57905
  });
57906
+ setupIxs.push(...swapSetupInstructions);
57984
57907
  const { instructions: updateFeedIxs, luts: feedLuts } = await makeSmartCrankSwbFeedIx({
57985
57908
  marginfiAccount,
57986
57909
  bankMap,
@@ -58024,12 +57947,12 @@ async function makeRollPtTx(params) {
58024
57947
  return {
58025
57948
  transactions,
58026
57949
  actionTxIndex: transactions.length - 1,
58027
- quoteResponse: void 0
57950
+ quoteResponse: swapQuote
58028
57951
  };
58029
57952
  }
58030
57953
  async function buildRollPtFlashloanTx({
58031
57954
  params,
58032
- resolved,
57955
+ wrapper,
58033
57956
  blockhash
58034
57957
  }) {
58035
57958
  const {
@@ -58038,27 +57961,29 @@ async function buildRollPtFlashloanTx({
58038
57961
  bankMap,
58039
57962
  withdrawOpts,
58040
57963
  depositOpts,
57964
+ swapOpts,
58041
57965
  bankMetadataMap,
57966
+ connection,
58042
57967
  addressLookupTableAccounts,
58043
- overrideInferAccounts
57968
+ overrideInferAccounts,
57969
+ rollOpts,
57970
+ swapEngineRunner
58044
57971
  } = params;
58045
- const {
58046
- actualWithdrawAmount,
58047
- isFullWithdraw,
58048
- mergeAccounts,
58049
- buyInstructions,
58050
- ptOutNative,
58051
- rollLuts
58052
- } = resolved;
58053
- const { withdrawBank, tokenProgram: withdrawTokenProgram } = withdrawOpts;
57972
+ const { withdrawBank, tokenProgram: withdrawTokenProgram, totalPositionAmount, withdrawAmount } = withdrawOpts;
58054
57973
  const { depositBank, tokenProgram: depositTokenProgram } = depositOpts;
58055
57974
  const authority = marginfiAccount.authority;
58056
- if (ptOutNative <= 0n) {
58057
- throw new Error("roll-pt: ptOutNative (PT to buy) must be greater than 0");
58058
- }
58059
- if (buyInstructions.length === 0) {
58060
- throw new Error("roll-pt: buy leg (SY \u2192 PT_new) must not be empty");
57975
+ if (withdrawAmount !== void 0 && withdrawAmount <= 0) {
57976
+ throw new Error("withdrawAmount must be greater than 0");
58061
57977
  }
57978
+ const actualWithdrawAmount = Math.min(withdrawAmount ?? totalPositionAmount, totalPositionAmount);
57979
+ const isFullWithdraw = isWholePosition(
57980
+ { amount: totalPositionAmount, isLending: true },
57981
+ actualWithdrawAmount,
57982
+ withdrawBank.mintDecimals
57983
+ );
57984
+ const withdrawNative = BigInt(
57985
+ uiToNative(actualWithdrawAmount, withdrawBank.mintDecimals).toString()
57986
+ );
58062
57987
  const cuRequestIxs = [
58063
57988
  web3_js.ComputeBudgetProgram.setComputeUnitLimit({ units: 12e5 }),
58064
57989
  web3_js.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 })
@@ -58075,10 +58000,11 @@ async function buildRollPtFlashloanTx({
58075
58000
  isSync: false,
58076
58001
  opts: { createAtas: false, wrapAndUnwrapSol: false, overrideInferAccounts }
58077
58002
  });
58078
- const mergeIx = makeExponentMergeIx(
58079
- mergeAccounts,
58080
- BigInt(uiToNative(actualWithdrawAmount, withdrawBank.mintDecimals).toString())
58081
- );
58003
+ const wrapperMergeIx = makeExponentWrapperMergeIx(wrapper.wrapperMergeAccounts, {
58004
+ amountPyNative: withdrawNative,
58005
+ redeemSyAccountsUntil: wrapper.wrapperMergeAccounts.redeemSyAccountsUntil
58006
+ });
58007
+ const redeemIxs = [wrapperMergeIx];
58082
58008
  const depositIxs = await makeDepositIx3({
58083
58009
  program,
58084
58010
  bank: depositBank,
@@ -58089,19 +58015,77 @@ async function buildRollPtFlashloanTx({
58089
58015
  group: marginfiAccount.group,
58090
58016
  opts: { wrapAndUnwrapSol: false, overrideInferAccounts }
58091
58017
  });
58018
+ let baseLuts;
58019
+ if (rollOpts.lookupTable) {
58020
+ const fetched = (await connection.getAddressLookupTable(rollOpts.lookupTable)).value;
58021
+ if (!fetched) {
58022
+ throw new Error(`roll-pt: PT-roll lookup table not found: ${rollOpts.lookupTable.toBase58()}`);
58023
+ }
58024
+ baseLuts = [fetched];
58025
+ } else {
58026
+ baseLuts = [...addressLookupTableAccounts ?? [], wrapper.addressLookupTable];
58027
+ }
58028
+ const nonSwapFootprint = [
58029
+ ...cuRequestIxs,
58030
+ ...withdrawIxs.instructions,
58031
+ ...redeemIxs,
58032
+ ...depositIxs.instructions
58033
+ ];
58034
+ const { sizeConstraint, maxSwapTotalAccounts } = computeFlashLoanNonSwapBudget({
58035
+ program,
58036
+ marginfiAccount,
58037
+ bankMap,
58038
+ addressLookupTableAccounts: baseLuts,
58039
+ ixs: nonSwapFootprint
58040
+ });
58041
+ const destinationTokenAccount = getAssociatedTokenAddressSync(
58042
+ depositBank.mint,
58043
+ authority,
58044
+ true,
58045
+ depositTokenProgram.equals(TOKEN_2022_PROGRAM_ID) ? TOKEN_2022_PROGRAM_ID : void 0
58046
+ );
58047
+ const baseAmountNative = wrapper.computeRedeemedBaseNative(withdrawNative);
58048
+ const runEngine = swapEngineRunner ?? runSwapEngine;
58049
+ const engineResult = await runEngine({
58050
+ inputMint: wrapper.baseToken.mint.toBase58(),
58051
+ outputMint: depositBank.mint.toBase58(),
58052
+ amountNative: Number(baseAmountNative),
58053
+ inputDecimals: wrapper.baseToken.decimals,
58054
+ outputDecimals: depositBank.mintDecimals,
58055
+ ...swapEngineQuoteFieldsFromOpts(swapOpts),
58056
+ taker: authority,
58057
+ destinationTokenAccount,
58058
+ connection,
58059
+ footprint: {
58060
+ instructions: nonSwapFootprint,
58061
+ luts: baseLuts,
58062
+ payer: authority,
58063
+ sizeConstraint,
58064
+ maxSwapTotalAccounts
58065
+ },
58066
+ providers: swapEngineProvidersFromOpts(swapOpts)
58067
+ });
58092
58068
  const depositIxToPatch = depositIxs.instructions.find(isDepositIx);
58093
58069
  if (!depositIxToPatch) {
58094
58070
  throw new Error("roll-pt: could not locate deposit instruction for amount patching");
58095
58071
  }
58096
- patchDepositAmount(depositIxToPatch, new BN11__default.default(ptOutNative.toString()));
58097
- const luts = [...addressLookupTableAccounts ?? [], ...rollLuts];
58072
+ patchDepositAmount(depositIxToPatch, engineResult.outputAmountNative);
58073
+ const luts = [...baseLuts, ...engineResult.swapLuts];
58098
58074
  const allNonFlIxs = [
58099
58075
  ...cuRequestIxs,
58100
58076
  ...withdrawIxs.instructions,
58101
- mergeIx,
58102
- ...buyInstructions,
58077
+ ...redeemIxs,
58078
+ ...engineResult.swapInstructions,
58103
58079
  ...depositIxs.instructions
58104
58080
  ];
58081
+ compileFlashloanPrecheck({
58082
+ allIxs: allNonFlIxs,
58083
+ payer: authority,
58084
+ luts,
58085
+ sizeConstraint,
58086
+ swapIxCount: engineResult.swapInstructions.length,
58087
+ swapLutCount: engineResult.swapLuts.length
58088
+ });
58105
58089
  const flashloanTx = await makeFlashLoanTx({
58106
58090
  program,
58107
58091
  marginfiAccount,
@@ -58114,10 +58098,16 @@ async function buildRollPtFlashloanTx({
58114
58098
  const txSize = getTxSize(flashloanTx);
58115
58099
  const totalKeys = getTotalAccountKeys(flashloanTx);
58116
58100
  if (txSize > MAX_TX_SIZE || totalKeys > MAX_ACCOUNT_LOCKS) {
58117
- throw TransactionBuildingError.swapSizeExceededPositionSwap(txSize, totalKeys);
58101
+ throw TransactionBuildingError.swapSizeExceededPositionSwap(
58102
+ txSize,
58103
+ totalKeys,
58104
+ swapOpts.swapConfig?.provider
58105
+ );
58118
58106
  }
58119
58107
  return {
58120
58108
  flashloanTx,
58109
+ setupInstructions: engineResult.setupInstructions,
58110
+ swapQuote: engineResult.quoteResponse,
58121
58111
  withdrawIxs,
58122
58112
  depositIxs
58123
58113
  };
@@ -62908,9 +62898,10 @@ var MarginfiAccount = class _MarginfiAccount {
62908
62898
  /**
62909
62899
  * Creates a transaction to roll a matured Exponent PT collateral position into its
62910
62900
  * next-maturity PT, in one flash-loan-wrapped bundle
62911
- * (withdraw PT_old → merge → buy PT_new → deposit). See {@link makeRollPtTx}.
62901
+ * (withdraw PT_old → `wrapper_merge` to base swap-engine buy PT_new → deposit).
62902
+ * See {@link makeRollPtTx}.
62912
62903
  *
62913
- * @param params - Roll-PT parameters (`withdrawOpts`/`depositOpts`/`rollOpts`).
62904
+ * @param params - Roll-PT parameters (`withdrawOpts`/`depositOpts`/`swapOpts`/`rollOpts`).
62914
62905
  */
62915
62906
  async makeRollPtTx(params) {
62916
62907
  return makeRollPtTx({
@@ -63442,12 +63433,12 @@ var MarginfiAccountWrapper = class {
63442
63433
  }
63443
63434
  /**
63444
63435
  * Rolls a matured Exponent PT collateral position into its next-maturity PT, with
63445
- * auto-injected client data (withdraw PT_old → merge buy PT_new deposit, flash-loan
63446
- * wrapped). The buy leg is venue-agnostic supplied via `rollOpts.buyInstructions`.
63436
+ * auto-injected client data (withdraw PT_old → `wrapper_merge` to baseswap-engine buy
63437
+ * PT_new → deposit, flash-loan wrapped). The full deposit ends up as new PT.
63447
63438
  *
63448
63439
  * Auto-injects: program, marginfiAccount, bankMap, oraclePrices, bankMetadataMap, addressLookupTables
63449
63440
  *
63450
- * @param params - Roll-PT parameters (user provides: connection, withdrawOpts, depositOpts, rollOpts, etc.)
63441
+ * @param params - Roll-PT parameters (user provides: connection, withdrawOpts, depositOpts, swapOpts, rollOpts, etc.)
63451
63442
  */
63452
63443
  async makeRollPtTx(params) {
63453
63444
  const fullParams = {