@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 +290 -200
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +93 -19
- package/dist/index.d.ts +93 -19
- package/dist/index.js +285 -201
- package/dist/index.js.map +1 -1
- package/dist/instructions.cjs.map +1 -1
- package/dist/instructions.d.cts +1 -0
- package/dist/instructions.d.ts +1 -0
- package/dist/instructions.js.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
-
|
|
85175
|
-
|
|
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
|
|
85225
|
-
if (!
|
|
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; ${
|
|
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
|
-
|
|
85237
|
-
|
|
85238
|
-
{ queryKey: opts.multiplierData.queryKey }
|
|
85239
|
-
);
|
|
85345
|
+
return fetchOracleMultipliersFromAPI(inputs, opts.multiplierData.endpoint, {
|
|
85346
|
+
queryKey: opts.multiplierData.queryKey
|
|
85347
|
+
});
|
|
85240
85348
|
}
|
|
85241
|
-
return fetchOracleMultipliersFromChain(
|
|
85349
|
+
return fetchOracleMultipliersFromChain(inputs, opts.connection);
|
|
85242
85350
|
};
|
|
85243
|
-
var fetchOracleMultipliersFromAPI = async (
|
|
85244
|
-
const
|
|
85245
|
-
|
|
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
|
|
85251
|
-
Object.entries(data).map(([bankAddress, multiplier]) => [bankAddress, Number(multiplier)]).filter(([, multiplier]) => Number.isFinite(multiplier))
|
|
85252
|
-
);
|
|
85374
|
+
return data;
|
|
85253
85375
|
};
|
|
85254
|
-
var
|
|
85255
|
-
const
|
|
85256
|
-
|
|
85257
|
-
|
|
85258
|
-
|
|
85259
|
-
|
|
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
|
|
85276
|
-
|
|
85383
|
+
console.error(`Missing multiplier account ${accountKey}`);
|
|
85384
|
+
return;
|
|
85277
85385
|
}
|
|
85278
|
-
|
|
85279
|
-
|
|
85280
|
-
|
|
85281
|
-
|
|
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
|
-
|
|
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;
|