@0dotxyz/p0-ts-sdk 2.8.2 → 2.8.3

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
@@ -54892,8 +54892,6 @@ var SWAP_ADAPTERS = {
54892
54892
  function getSwapAdapter(provider) {
54893
54893
  return SWAP_ADAPTERS[provider];
54894
54894
  }
54895
-
54896
- // src/services/account/services/swap-engine/swap-engine.service.ts
54897
54895
  function resolveAdapters(req, predicate) {
54898
54896
  const resolved = [];
54899
54897
  for (const entry of req.providers) {
@@ -54937,7 +54935,18 @@ async function runSwapEngine(req) {
54937
54935
  failures.join("; ") || "No swap route available"
54938
54936
  );
54939
54937
  }
54940
- const candidates = routes.map((route) => annotateFit(route, req));
54938
+ const wsolAta = getAssociatedTokenAddressSync(NATIVE_MINT, req.taker, true);
54939
+ const isProviderSolWrapIx = (ix) => ix.programId.equals(web3_js.SystemProgram.programId) && ix.data.length >= 12 && ix.data.readUInt32LE(0) === 2 && ix.keys[0]?.pubkey.equals(req.taker) && ix.keys[1]?.pubkey.equals(wsolAta) || ix.programId.equals(TOKEN_PROGRAM_ID) && (ix.data[0] === 17 /* SyncNative */ || ix.data[0] === 9 /* CloseAccount */) && ix.keys[0]?.pubkey.equals(wsolAta);
54940
+ const candidates = routes.map(
54941
+ (route) => annotateFit(
54942
+ {
54943
+ ...route,
54944
+ swapInstructions: route.swapInstructions.filter((ix) => !isProviderSolWrapIx(ix)),
54945
+ setupInstructions: route.setupInstructions.filter((ix) => !isProviderSolWrapIx(ix))
54946
+ },
54947
+ req
54948
+ )
54949
+ );
54941
54950
  const fitting = candidates.filter((c) => c.fits && c.outAmountNative.gtn(0));
54942
54951
  if (fitting.length === 0) {
54943
54952
  const closest = candidates.reduce((best, c) => c.fullTxSize < best.fullTxSize ? c : best);
@@ -55032,6 +55041,7 @@ async function makeEndFlashLoanIx3(program, marginfiAccountPk, group, projectedA
55032
55041
  program,
55033
55042
  {
55034
55043
  marginfiAccount: marginfiAccountPk,
55044
+ group,
55035
55045
  authority
55036
55046
  },
55037
55047
  remainingAccounts.map((account) => ({
@@ -74918,6 +74928,231 @@ async function computeSmartCrank({
74918
74928
  isCrankable: true
74919
74929
  });
74920
74930
  }
74931
+ new web3_js.PublicKey("MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD");
74932
+ var MARINADE_STATE_DISCRIMINATOR = Buffer.from([216, 146, 107, 94, 104, 75, 182, 177]);
74933
+ var DELAYED_UNSTAKE_COOLING_DOWN_OFFSET = 226;
74934
+ var TOTAL_ACTIVE_BALANCE_OFFSET = 376;
74935
+ var AVAILABLE_RESERVE_BALANCE_OFFSET = 496;
74936
+ var MSOL_SUPPLY_OFFSET = 504;
74937
+ var CIRCULATING_TICKET_BALANCE_OFFSET = 528;
74938
+ var EMERGENCY_COOLING_DOWN_OFFSET = 568;
74939
+ var MARINADE_STATE_MIN_SIZE = EMERGENCY_COOLING_DOWN_OFFSET + 8;
74940
+ var U64_MAX = (1n << 64n) - 1n;
74941
+ var MAX_MSOL_SOL_RATE = 3;
74942
+ function decodeMarinadeState(data) {
74943
+ if (data.length < MARINADE_STATE_MIN_SIZE) {
74944
+ throw new Error(`Invalid Marinade State account size: ${data.length}`);
74945
+ }
74946
+ if (!data.subarray(0, 8).equals(MARINADE_STATE_DISCRIMINATOR)) {
74947
+ throw new Error("Invalid Marinade State discriminator");
74948
+ }
74949
+ const delayedUnstakeCoolingDown = data.readBigUInt64LE(DELAYED_UNSTAKE_COOLING_DOWN_OFFSET);
74950
+ const totalActiveBalance = data.readBigUInt64LE(TOTAL_ACTIVE_BALANCE_OFFSET);
74951
+ const availableReserveBalance = data.readBigUInt64LE(AVAILABLE_RESERVE_BALANCE_OFFSET);
74952
+ const msolSupply = data.readBigUInt64LE(MSOL_SUPPLY_OFFSET);
74953
+ const circulatingTicketBalance = data.readBigUInt64LE(CIRCULATING_TICKET_BALANCE_OFFSET);
74954
+ const emergencyCoolingDown = data.readBigUInt64LE(EMERGENCY_COOLING_DOWN_OFFSET);
74955
+ if (msolSupply === 0n) {
74956
+ throw new Error("Marinade State has zero mSOL supply");
74957
+ }
74958
+ const underControl = totalActiveBalance + delayedUnstakeCoolingDown + emergencyCoolingDown + availableReserveBalance;
74959
+ if (underControl > U64_MAX) {
74960
+ throw new Error("Marinade virtual staked balance overflow");
74961
+ }
74962
+ const totalVirtualStakedLamports = underControl > circulatingTicketBalance ? underControl - circulatingTicketBalance : 0n;
74963
+ const msolPrice = new BigNumber3__default.default(totalVirtualStakedLamports.toString()).div(msolSupply.toString());
74964
+ if (!msolPrice.gt(0) || msolPrice.gte(MAX_MSOL_SOL_RATE)) {
74965
+ throw new Error(`Marinade mSOL/SOL rate out of bounds: ${msolPrice.toString()}`);
74966
+ }
74967
+ return { msolPrice };
74968
+ }
74969
+ new web3_js.PublicKey(
74970
+ "SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy"
74971
+ );
74972
+ new web3_js.PublicKey(
74973
+ "SP12tWFxD9oJsVWNavTTBZvMbA6gkAmxtVgxdqvyvhY"
74974
+ );
74975
+ new web3_js.PublicKey(
74976
+ "SPMBzsVUuoHA4Jm6KunbsotaahvVikZs1JyTW6iJvbn"
74977
+ );
74978
+ var ACCOUNT_TYPE_STAKE_POOL = 1;
74979
+ var TOTAL_LAMPORTS_OFFSET = 258;
74980
+ var POOL_TOKEN_SUPPLY_OFFSET = 266;
74981
+ var LAST_UPDATE_EPOCH_OFFSET = 274;
74982
+ var MAX_LST_SOL_RATE = 3;
74983
+ function decodeStakePool(data) {
74984
+ if (data.length < LAST_UPDATE_EPOCH_OFFSET + 8) {
74985
+ throw new Error(`Invalid StakePool account size: ${data.length}`);
74986
+ }
74987
+ if (data[0] !== ACCOUNT_TYPE_STAKE_POOL) {
74988
+ throw new Error(`Invalid StakePool account type: ${data[0]}`);
74989
+ }
74990
+ const totalLamports = data.readBigUInt64LE(TOTAL_LAMPORTS_OFFSET);
74991
+ const poolTokenSupply = data.readBigUInt64LE(POOL_TOKEN_SUPPLY_OFFSET);
74992
+ const lastUpdateEpoch = Number(data.readBigUInt64LE(LAST_UPDATE_EPOCH_OFFSET));
74993
+ if (poolTokenSupply === 0n) {
74994
+ throw new Error("StakePool has zero token supply");
74995
+ }
74996
+ const exchangeRate = new BigNumber3__default.default(totalLamports.toString()).div(
74997
+ new BigNumber3__default.default(poolTokenSupply.toString())
74998
+ );
74999
+ if (!exchangeRate.gt(0) || exchangeRate.gte(MAX_LST_SOL_RATE)) {
75000
+ throw new Error(`StakePool LST/SOL rate out of bounds: ${exchangeRate.toString()}`);
75001
+ }
75002
+ return {
75003
+ totalLamports,
75004
+ poolTokenSupply,
75005
+ lastUpdateEpoch,
75006
+ exchangeRate
75007
+ };
75008
+ }
75009
+
75010
+ // src/services/price/utils/multiplier-data.utils.ts
75011
+ var PT_MAX_MATURITY_HORIZON_SECONDS = 5 * 365 * 24 * 60 * 60;
75012
+ var MAX_SY_EXCHANGE_RATE = new BigNumber3__default.default("18446744073709551615").div(1e12);
75013
+ var MAX_STAKE_POOL_EPOCH_LAG = 1;
75014
+ function multiplierAccountKey(bank) {
75015
+ switch (bank.config.oracleSetup) {
75016
+ case "PythMSOL" /* PythMSOL */:
75017
+ case "PythLST" /* PythLST */:
75018
+ case "PTPyth" /* PTPyth */:
75019
+ return bank.config.oracleKeys[1];
75020
+ case "KaminoMSOL" /* KaminoMSOL */:
75021
+ case "JuplendMSOL" /* JuplendMSOL */:
75022
+ case "KaminoLST" /* KaminoLST */:
75023
+ case "JuplendLST" /* JuplendLST */:
75024
+ return bank.config.oracleKeys[2];
75025
+ case "PTFixed" /* PTFixed */:
75026
+ return bank.config.oracleKeys[0];
75027
+ default:
75028
+ return void 0;
75029
+ }
75030
+ }
75031
+ function getOracleMultiplierBankInput(bank) {
75032
+ const accountKey = multiplierAccountKey(bank);
75033
+ if (!accountKey) return void 0;
75034
+ const isPt = bank.config.oracleSetup === "PTPyth" /* PTPyth */ || bank.config.oracleSetup === "PTFixed" /* PTFixed */;
75035
+ return {
75036
+ bankAddress: bank.address.toBase58(),
75037
+ oracleSetup: bank.config.oracleSetup,
75038
+ multiplierAccountKey: accountKey.toBase58(),
75039
+ fixedPrice: isPt ? bank.config.fixedPrice : void 0
75040
+ };
75041
+ }
75042
+ function decodeMultiplierAccount(data) {
75043
+ try {
75044
+ const vault = decodeExponentVault(data);
75045
+ return {
75046
+ kind: "exponentVault",
75047
+ startTs: vault.startTs,
75048
+ duration: vault.duration,
75049
+ syForPt: vault.syForPt.toString(),
75050
+ ptSupply: vault.ptSupply.toString(),
75051
+ lastSeenSyExchangeRate: vault.lastSeenSyExchangeRate.toString(),
75052
+ allTimeHighSyExchangeRate: vault.allTimeHighSyExchangeRate.toString()
75053
+ };
75054
+ } catch {
75055
+ }
75056
+ try {
75057
+ return { kind: "marinade", msolPrice: decodeMarinadeState(data).msolPrice.toString() };
75058
+ } catch {
75059
+ }
75060
+ try {
75061
+ const pool = decodeStakePool(data);
75062
+ return {
75063
+ kind: "stakePool",
75064
+ exchangeRate: pool.exchangeRate.toString(),
75065
+ lastUpdateEpoch: pool.lastUpdateEpoch
75066
+ };
75067
+ } catch {
75068
+ }
75069
+ return void 0;
75070
+ }
75071
+ function computePtMultiplier(vault, startPrice, nowSeconds) {
75072
+ const maturity = vault.startTs + vault.duration;
75073
+ if (vault.duration <= 0 || maturity > nowSeconds + PT_MAX_MATURITY_HORIZON_SECONDS) {
75074
+ throw new Error("Exponent vault has an invalid maturity schedule");
75075
+ }
75076
+ if (!vault.lastSeenSyExchangeRate.gt(0) || vault.lastSeenSyExchangeRate.gt(MAX_SY_EXCHANGE_RATE)) {
75077
+ throw new Error("Exponent vault SY exchange rate out of bounds");
75078
+ }
75079
+ if (vault.ptSupply === 0n) {
75080
+ throw new Error("Exponent vault has zero PT supply");
75081
+ }
75082
+ if (vault.lastSeenSyExchangeRate.lt(vault.allTimeHighSyExchangeRate)) {
75083
+ throw new Error("Exponent vault is in emergency mode");
75084
+ }
75085
+ let expectedRate;
75086
+ if (nowSeconds <= vault.startTs) {
75087
+ expectedRate = startPrice;
75088
+ } else if (nowSeconds >= maturity) {
75089
+ expectedRate = new BigNumber3__default.default(1);
75090
+ } else {
75091
+ const progress = new BigNumber3__default.default(nowSeconds - vault.startTs).div(vault.duration);
75092
+ expectedRate = startPrice.plus(new BigNumber3__default.default(1).minus(startPrice).times(progress));
75093
+ }
75094
+ const syPerPt = new BigNumber3__default.default(vault.syForPt.toString()).div(
75095
+ new BigNumber3__default.default(vault.ptSupply.toString())
75096
+ );
75097
+ const redemptionCap = syPerPt.times(vault.lastSeenSyExchangeRate);
75098
+ return BigNumber3__default.default.min(expectedRate, redemptionCap);
75099
+ }
75100
+ function computeOracleMultiplier(input, state, ctx) {
75101
+ switch (input.oracleSetup) {
75102
+ case "PythMSOL" /* PythMSOL */:
75103
+ case "KaminoMSOL" /* KaminoMSOL */:
75104
+ case "JuplendMSOL" /* JuplendMSOL */:
75105
+ if (state.kind !== "marinade") throw new Error(`Expected Marinade state, got ${state.kind}`);
75106
+ return Number(state.msolPrice);
75107
+ case "PythLST" /* PythLST */:
75108
+ case "KaminoLST" /* KaminoLST */:
75109
+ case "JuplendLST" /* JuplendLST */:
75110
+ if (state.kind !== "stakePool") throw new Error(`Expected stake pool, got ${state.kind}`);
75111
+ if (ctx.currentEpoch - state.lastUpdateEpoch > MAX_STAKE_POOL_EPOCH_LAG) {
75112
+ throw new Error(
75113
+ `Stale stake pool (last updated epoch ${state.lastUpdateEpoch}, current ${ctx.currentEpoch})`
75114
+ );
75115
+ }
75116
+ return Number(state.exchangeRate);
75117
+ case "PTPyth" /* PTPyth */:
75118
+ case "PTFixed" /* PTFixed */:
75119
+ if (state.kind !== "exponentVault") {
75120
+ throw new Error(`Expected Exponent vault, got ${state.kind}`);
75121
+ }
75122
+ if (!input.fixedPrice) throw new Error("Missing fixedPrice for PT bank");
75123
+ return computePtMultiplier(
75124
+ {
75125
+ startTs: state.startTs,
75126
+ duration: state.duration,
75127
+ syForPt: BigInt(state.syForPt),
75128
+ ptSupply: BigInt(state.ptSupply),
75129
+ lastSeenSyExchangeRate: new BigNumber3__default.default(state.lastSeenSyExchangeRate),
75130
+ allTimeHighSyExchangeRate: new BigNumber3__default.default(state.allTimeHighSyExchangeRate)
75131
+ },
75132
+ input.fixedPrice,
75133
+ ctx.nowSeconds
75134
+ ).toNumber();
75135
+ default:
75136
+ throw new Error(`Oracle setup ${input.oracleSetup} is not multiplier-priced`);
75137
+ }
75138
+ }
75139
+ function computeOracleMultipliers(inputs, accountStates, nowSeconds = Math.floor(Date.now() / 1e3)) {
75140
+ const multiplierByBank = {};
75141
+ const ctx = { currentEpoch: accountStates.currentEpoch, nowSeconds };
75142
+ for (const input of inputs) {
75143
+ const state = accountStates.states[input.multiplierAccountKey];
75144
+ if (!state) {
75145
+ console.error(`Missing multiplier account for bank ${input.bankAddress}`);
75146
+ continue;
75147
+ }
75148
+ try {
75149
+ multiplierByBank[input.bankAddress] = computeOracleMultiplier(input, state, ctx);
75150
+ } catch (e) {
75151
+ console.error(`Failed to compute multiplier for bank ${input.bankAddress}`, e);
75152
+ }
75153
+ }
75154
+ return multiplierByBank;
75155
+ }
74921
75156
  async function makeSmartCrankSwbFeedIx(params) {
74922
75157
  const crankResult = await computeSmartCrank(params);
74923
75158
  if (crankResult.uncrankableLiabilities.length > 0) {
@@ -75244,84 +75479,6 @@ function decodeScopePriceAtIndex(data, entryIndex) {
75244
75479
  unixTimestamp: Number(unixTimestamp)
75245
75480
  };
75246
75481
  }
75247
- new web3_js.PublicKey("MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD");
75248
- var MARINADE_STATE_DISCRIMINATOR = Buffer.from([216, 146, 107, 94, 104, 75, 182, 177]);
75249
- var DELAYED_UNSTAKE_COOLING_DOWN_OFFSET = 226;
75250
- var TOTAL_ACTIVE_BALANCE_OFFSET = 376;
75251
- var AVAILABLE_RESERVE_BALANCE_OFFSET = 496;
75252
- var MSOL_SUPPLY_OFFSET = 504;
75253
- var CIRCULATING_TICKET_BALANCE_OFFSET = 528;
75254
- var EMERGENCY_COOLING_DOWN_OFFSET = 568;
75255
- var MARINADE_STATE_MIN_SIZE = EMERGENCY_COOLING_DOWN_OFFSET + 8;
75256
- var U64_MAX = (1n << 64n) - 1n;
75257
- var MAX_MSOL_SOL_RATE = 3;
75258
- function decodeMarinadeState(data) {
75259
- if (data.length < MARINADE_STATE_MIN_SIZE) {
75260
- throw new Error(`Invalid Marinade State account size: ${data.length}`);
75261
- }
75262
- if (!data.subarray(0, 8).equals(MARINADE_STATE_DISCRIMINATOR)) {
75263
- throw new Error("Invalid Marinade State discriminator");
75264
- }
75265
- const delayedUnstakeCoolingDown = data.readBigUInt64LE(DELAYED_UNSTAKE_COOLING_DOWN_OFFSET);
75266
- const totalActiveBalance = data.readBigUInt64LE(TOTAL_ACTIVE_BALANCE_OFFSET);
75267
- const availableReserveBalance = data.readBigUInt64LE(AVAILABLE_RESERVE_BALANCE_OFFSET);
75268
- const msolSupply = data.readBigUInt64LE(MSOL_SUPPLY_OFFSET);
75269
- const circulatingTicketBalance = data.readBigUInt64LE(CIRCULATING_TICKET_BALANCE_OFFSET);
75270
- const emergencyCoolingDown = data.readBigUInt64LE(EMERGENCY_COOLING_DOWN_OFFSET);
75271
- if (msolSupply === 0n) {
75272
- throw new Error("Marinade State has zero mSOL supply");
75273
- }
75274
- const underControl = totalActiveBalance + delayedUnstakeCoolingDown + emergencyCoolingDown + availableReserveBalance;
75275
- if (underControl > U64_MAX) {
75276
- throw new Error("Marinade virtual staked balance overflow");
75277
- }
75278
- const totalVirtualStakedLamports = underControl > circulatingTicketBalance ? underControl - circulatingTicketBalance : 0n;
75279
- const msolPrice = new BigNumber3__default.default(totalVirtualStakedLamports.toString()).div(msolSupply.toString());
75280
- if (!msolPrice.gt(0) || msolPrice.gte(MAX_MSOL_SOL_RATE)) {
75281
- throw new Error(`Marinade mSOL/SOL rate out of bounds: ${msolPrice.toString()}`);
75282
- }
75283
- return { msolPrice };
75284
- }
75285
- new web3_js.PublicKey(
75286
- "SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy"
75287
- );
75288
- new web3_js.PublicKey(
75289
- "SP12tWFxD9oJsVWNavTTBZvMbA6gkAmxtVgxdqvyvhY"
75290
- );
75291
- new web3_js.PublicKey(
75292
- "SPMBzsVUuoHA4Jm6KunbsotaahvVikZs1JyTW6iJvbn"
75293
- );
75294
- var ACCOUNT_TYPE_STAKE_POOL = 1;
75295
- var TOTAL_LAMPORTS_OFFSET = 258;
75296
- var POOL_TOKEN_SUPPLY_OFFSET = 266;
75297
- var LAST_UPDATE_EPOCH_OFFSET = 274;
75298
- var MAX_LST_SOL_RATE = 3;
75299
- function decodeStakePool(data) {
75300
- if (data.length < LAST_UPDATE_EPOCH_OFFSET + 8) {
75301
- throw new Error(`Invalid StakePool account size: ${data.length}`);
75302
- }
75303
- if (data[0] !== ACCOUNT_TYPE_STAKE_POOL) {
75304
- throw new Error(`Invalid StakePool account type: ${data[0]}`);
75305
- }
75306
- const totalLamports = data.readBigUInt64LE(TOTAL_LAMPORTS_OFFSET);
75307
- const poolTokenSupply = data.readBigUInt64LE(POOL_TOKEN_SUPPLY_OFFSET);
75308
- const lastUpdateEpoch = Number(data.readBigUInt64LE(LAST_UPDATE_EPOCH_OFFSET));
75309
- if (poolTokenSupply === 0n) {
75310
- throw new Error("StakePool has zero token supply");
75311
- }
75312
- const exchangeRate = new BigNumber3__default.default(totalLamports.toString()).div(
75313
- new BigNumber3__default.default(poolTokenSupply.toString())
75314
- );
75315
- if (!exchangeRate.gt(0) || exchangeRate.gte(MAX_LST_SOL_RATE)) {
75316
- throw new Error(`StakePool LST/SOL rate out of bounds: ${exchangeRate.toString()}`);
75317
- }
75318
- return {
75319
- totalLamports,
75320
- poolTokenSupply,
75321
- lastUpdateEpoch,
75322
- exchangeRate
75323
- };
75324
- }
75325
75482
  var GAMMA_VAULT_PROGRAM_ID = new web3_js.PublicKey(
75326
75483
  "GaMmanX9i4jGmqDZZD2tbD6B2v9p21btenPneMXnTczV"
75327
75484
  );
@@ -85171,144 +85328,71 @@ var fetchScopeOraclePricesFromChain = async (requestKeys, connection) => {
85171
85328
  }
85172
85329
  return oraclePriceByRequestKey;
85173
85330
  };
85174
- var PT_MAX_MATURITY_HORIZON_SECONDS = 5 * 365 * 24 * 60 * 60;
85175
- var MAX_SY_EXCHANGE_RATE = new BigNumber3__default.default("18446744073709551615").div(1e12);
85176
- var MAX_STAKE_POOL_EPOCH_LAG = 1;
85177
- function multiplierAccountKey(bank) {
85178
- switch (bank.config.oracleSetup) {
85179
- case "PythMSOL" /* PythMSOL */:
85180
- case "PythLST" /* PythLST */:
85181
- case "PTPyth" /* PTPyth */:
85182
- return bank.config.oracleKeys[1];
85183
- case "KaminoMSOL" /* KaminoMSOL */:
85184
- case "JuplendMSOL" /* JuplendMSOL */:
85185
- case "KaminoLST" /* KaminoLST */:
85186
- case "JuplendLST" /* JuplendLST */:
85187
- return bank.config.oracleKeys[2];
85188
- case "PTFixed" /* PTFixed */:
85189
- return bank.config.oracleKeys[0];
85190
- default:
85191
- return void 0;
85192
- }
85193
- }
85194
- function computePtMultiplier(vault, startPrice, nowSeconds) {
85195
- const maturity = vault.startTs + vault.duration;
85196
- if (vault.duration <= 0 || maturity > nowSeconds + PT_MAX_MATURITY_HORIZON_SECONDS) {
85197
- throw new Error("Exponent vault has an invalid maturity schedule");
85198
- }
85199
- if (!vault.lastSeenSyExchangeRate.gt(0) || vault.lastSeenSyExchangeRate.gt(MAX_SY_EXCHANGE_RATE)) {
85200
- throw new Error("Exponent vault SY exchange rate out of bounds");
85201
- }
85202
- if (vault.ptSupply === 0n) {
85203
- throw new Error("Exponent vault has zero PT supply");
85204
- }
85205
- if (vault.lastSeenSyExchangeRate.lt(vault.allTimeHighSyExchangeRate)) {
85206
- throw new Error("Exponent vault is in emergency mode");
85207
- }
85208
- let expectedRate;
85209
- if (nowSeconds <= vault.startTs) {
85210
- expectedRate = startPrice;
85211
- } else if (nowSeconds >= maturity) {
85212
- expectedRate = new BigNumber3__default.default(1);
85213
- } else {
85214
- const progress = new BigNumber3__default.default(nowSeconds - vault.startTs).div(vault.duration);
85215
- expectedRate = startPrice.plus(new BigNumber3__default.default(1).minus(startPrice).times(progress));
85216
- }
85217
- const syPerPt = new BigNumber3__default.default(vault.syForPt.toString()).div(
85218
- new BigNumber3__default.default(vault.ptSupply.toString())
85219
- );
85220
- const redemptionCap = syPerPt.times(vault.lastSeenSyExchangeRate);
85221
- return BigNumber3__default.default.min(expectedRate, redemptionCap);
85222
- }
85331
+
85332
+ // src/services/price/services/oracle-multiplier.service.ts
85223
85333
  var fetchOracleMultipliers = async (banks, opts) => {
85224
- const multipliedBanks = banks.filter((bank) => multiplierAccountKey(bank) !== void 0);
85225
- if (!multipliedBanks.length) {
85334
+ const inputs = banks.map(getOracleMultiplierBankInput).filter((input) => input !== void 0);
85335
+ if (!inputs.length) {
85226
85336
  return {};
85227
85337
  }
85228
85338
  if (!opts) {
85229
85339
  console.warn(
85230
- `fetchOracleMultipliers: no oracleMultiplierOpts provided; ${multipliedBanks.length} multiplier-priced bank(s) will have zero prices`
85340
+ `fetchOracleMultipliers: no oracleMultiplierOpts provided; ${inputs.length} multiplier-priced bank(s) will have zero prices`
85231
85341
  );
85232
85342
  return {};
85233
85343
  }
85234
85344
  if (opts.mode === "api") {
85235
- return fetchOracleMultipliersFromAPI(
85236
- multipliedBanks.map((bank) => bank.address.toBase58()),
85237
- opts.multiplierData.endpoint,
85238
- { queryKey: opts.multiplierData.queryKey }
85239
- );
85345
+ return fetchOracleMultipliersFromAPI(inputs, opts.multiplierData.endpoint, {
85346
+ queryKey: opts.multiplierData.queryKey
85347
+ });
85240
85348
  }
85241
- return fetchOracleMultipliersFromChain(multipliedBanks, opts.connection);
85349
+ return fetchOracleMultipliersFromChain(inputs, opts.connection);
85242
85350
  };
85243
- var fetchOracleMultipliersFromAPI = async (bankAddresses, apiEndpoint, opts) => {
85244
- const queryKey = opts?.queryKey ?? "bankAddresses";
85245
- const response = await fetch(`${apiEndpoint}?${queryKey}=${bankAddresses.join(",")}`);
85351
+ var fetchOracleMultipliersFromAPI = async (inputs, apiEndpoint, opts) => {
85352
+ const accountStates = await fetchMultiplierAccountStatesFromAPI(
85353
+ inputs.map((input) => input.multiplierAccountKey),
85354
+ apiEndpoint,
85355
+ opts
85356
+ );
85357
+ return computeOracleMultipliers(inputs, accountStates);
85358
+ };
85359
+ var fetchOracleMultipliersFromChain = async (inputs, connection) => {
85360
+ const accountStates = await fetchMultiplierAccountStates(
85361
+ inputs.map((input) => input.multiplierAccountKey),
85362
+ connection
85363
+ );
85364
+ return computeOracleMultipliers(inputs, accountStates);
85365
+ };
85366
+ var fetchMultiplierAccountStatesFromAPI = async (accountKeys, apiEndpoint, opts) => {
85367
+ const queryKey = opts?.queryKey ?? "multiplierAccounts";
85368
+ const uniqueKeys = Array.from(new Set(accountKeys));
85369
+ const response = await fetch(`${apiEndpoint}?${queryKey}=${uniqueKeys.join(",")}`);
85246
85370
  if (!response.ok) {
85247
85371
  throw new Error("Failed to fetch price multiplier data");
85248
85372
  }
85249
85373
  const { data } = await response.json();
85250
- return Object.fromEntries(
85251
- Object.entries(data).map(([bankAddress, multiplier]) => [bankAddress, Number(multiplier)]).filter(([, multiplier]) => Number.isFinite(multiplier))
85252
- );
85374
+ return data;
85253
85375
  };
85254
- var fetchOracleMultipliersFromChain = async (multipliedBanks, connection) => {
85255
- const accountKeyByBank = new Map(
85256
- multipliedBanks.map((bank) => [bank.address.toBase58(), multiplierAccountKey(bank).toBase58()])
85257
- );
85258
- const uniqueAccountKeys = Array.from(new Set(accountKeyByBank.values()));
85259
- const accountAis = await chunkedGetRawMultipleAccountInfoOrderedWithNulls(
85260
- connection,
85261
- uniqueAccountKeys
85262
- );
85263
- const isLstSetup = (setup) => setup === "PythLST" /* PythLST */ || setup === "KaminoLST" /* KaminoLST */ || setup === "JuplendLST" /* JuplendLST */;
85264
- const currentEpoch = multipliedBanks.some((bank) => isLstSetup(bank.config.oracleSetup)) ? (await connection.getEpochInfo()).epoch : 0;
85265
- const accountDataByKey = {};
85266
- uniqueAccountKeys.forEach((accountKey, index) => {
85267
- accountDataByKey[accountKey] = accountAis[index]?.data;
85268
- });
85269
- const multiplierByBank = {};
85270
- const nowSeconds = Math.floor(Date.now() / 1e3);
85271
- for (const bank of multipliedBanks) {
85272
- const bankAddress = bank.address.toBase58();
85273
- const data = accountDataByKey[accountKeyByBank.get(bankAddress)];
85376
+ var fetchMultiplierAccountStates = async (accountKeys, connection) => {
85377
+ const uniqueKeys = Array.from(new Set(accountKeys));
85378
+ const accountAis = await chunkedGetRawMultipleAccountInfoOrderedWithNulls(connection, uniqueKeys);
85379
+ const states = {};
85380
+ uniqueKeys.forEach((accountKey, index) => {
85381
+ const data = accountAis[index]?.data;
85274
85382
  if (!data) {
85275
- console.error(`Missing multiplier account for bank ${bankAddress}`);
85276
- continue;
85383
+ console.error(`Missing multiplier account ${accountKey}`);
85384
+ return;
85277
85385
  }
85278
- try {
85279
- switch (bank.config.oracleSetup) {
85280
- case "PythMSOL" /* PythMSOL */:
85281
- case "KaminoMSOL" /* KaminoMSOL */:
85282
- case "JuplendMSOL" /* JuplendMSOL */:
85283
- multiplierByBank[bankAddress] = decodeMarinadeState(data).msolPrice.toNumber();
85284
- break;
85285
- case "PythLST" /* PythLST */:
85286
- case "KaminoLST" /* KaminoLST */:
85287
- case "JuplendLST" /* JuplendLST */: {
85288
- const stakePool = decodeStakePool(data);
85289
- if (currentEpoch - stakePool.lastUpdateEpoch > MAX_STAKE_POOL_EPOCH_LAG) {
85290
- console.error(
85291
- `Stale stake pool for bank ${bankAddress} (last updated epoch ${stakePool.lastUpdateEpoch}, current ${currentEpoch})`
85292
- );
85293
- continue;
85294
- }
85295
- multiplierByBank[bankAddress] = stakePool.exchangeRate.toNumber();
85296
- break;
85297
- }
85298
- case "PTPyth" /* PTPyth */:
85299
- case "PTFixed" /* PTFixed */:
85300
- multiplierByBank[bankAddress] = computePtMultiplier(
85301
- decodeExponentVault(data),
85302
- bank.config.fixedPrice,
85303
- nowSeconds
85304
- ).toNumber();
85305
- break;
85306
- }
85307
- } catch (e) {
85308
- console.error(`Failed to compute multiplier for bank ${bankAddress}`, e);
85386
+ const state = decodeMultiplierAccount(data);
85387
+ if (!state) {
85388
+ console.error(`Unrecognized multiplier account ${accountKey}`);
85389
+ return;
85309
85390
  }
85310
- }
85311
- return multiplierByBank;
85391
+ states[accountKey] = state;
85392
+ });
85393
+ const hasStakePool = Object.values(states).some((state) => state.kind === "stakePool");
85394
+ const currentEpoch = hasStakePool ? (await connection.getEpochInfo()).epoch : 0;
85395
+ return { states, currentEpoch };
85312
85396
  };
85313
85397
  var fetchOracleData = async (banks, opts) => {
85314
85398
  const { zeroOracleBanks, isolatedAssetBanks, collateralAssetBanks, fixedAssetBanks } = classifyBanksForOracleStrategy(banks);
@@ -89584,6 +89668,8 @@ exports.computeMaxDepositForBank = computeMaxDepositForBank;
89584
89668
  exports.computeMaxLeverage = computeMaxLeverage;
89585
89669
  exports.computeMaxWithdrawForBank = computeMaxWithdrawForBank;
89586
89670
  exports.computeNetApy = computeNetApy;
89671
+ exports.computeOracleMultiplier = computeOracleMultiplier;
89672
+ exports.computeOracleMultipliers = computeOracleMultipliers;
89587
89673
  exports.computeProjectedActiveBalancesNoCpi = computeProjectedActiveBalancesNoCpi;
89588
89674
  exports.computeProjectedActiveBanksNoCpi = computeProjectedActiveBanksNoCpi;
89589
89675
  exports.computePtMultiplier = computePtMultiplier;
@@ -89607,6 +89693,7 @@ exports.createEmptyBalance = createEmptyBalance;
89607
89693
  exports.decodeAccountRaw = decodeAccountRaw;
89608
89694
  exports.decodeBankRaw = decodeBankRaw;
89609
89695
  exports.decodeInstruction = decodeInstruction;
89696
+ exports.decodeMultiplierAccount = decodeMultiplierAccount;
89610
89697
  exports.decompileV0Transaction = decompileV0Transaction;
89611
89698
  exports.deriveBankEmissionsAuth = deriveBankEmissionsAuth;
89612
89699
  exports.deriveBankEmissionsVault = deriveBankEmissionsVault;
@@ -89650,6 +89737,8 @@ exports.fetchMarginfiAccountAddresses = fetchMarginfiAccountAddresses;
89650
89737
  exports.fetchMarginfiAccountAddressesHoldingBank = fetchMarginfiAccountAddressesHoldingBank;
89651
89738
  exports.fetchMarginfiAccountData = fetchMarginfiAccountData;
89652
89739
  exports.fetchMultipleBanks = fetchMultipleBanks;
89740
+ exports.fetchMultiplierAccountStates = fetchMultiplierAccountStates;
89741
+ exports.fetchMultiplierAccountStatesFromAPI = fetchMultiplierAccountStatesFromAPI;
89653
89742
  exports.fetchNativeStakeAccounts = fetchNativeStakeAccounts;
89654
89743
  exports.fetchOracleData = fetchOracleData;
89655
89744
  exports.fetchOracleMultipliers = fetchOracleMultipliers;
@@ -89710,6 +89799,7 @@ exports.getKaminoStatesDto = getKaminoStatesDto;
89710
89799
  exports.getLiabilityQuantity = getLiabilityQuantity;
89711
89800
  exports.getLiabilityShares = getLiabilityShares;
89712
89801
  exports.getLiabilityWeight = getLiabilityWeight;
89802
+ exports.getOracleMultiplierBankInput = getOracleMultiplierBankInput;
89713
89803
  exports.getOracleSourceFromBank = getOracleSourceFromBank;
89714
89804
  exports.getOracleSourceFromOracleSetup = getOracleSourceFromOracleSetup;
89715
89805
  exports.getOracleSourceNameFromKey = getOracleSourceNameFromKey;