@pyron-finance/pyron-client 2.9.5 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -462,7 +462,7 @@ import {
462
462
  TransactionMessage as TransactionMessage6,
463
463
  VersionedTransaction as VersionedTransaction6
464
464
  } from "@solana/web3.js";
465
- import BigNumber16 from "bignumber.js";
465
+ import BigNumber17 from "bignumber.js";
466
466
  import bs582 from "bs58";
467
467
  import { createStorage } from "unstorage";
468
468
 
@@ -13974,7 +13974,7 @@ import {
13974
13974
  TOKEN_2022_PROGRAM_ID
13975
13975
  } from "@solana/spl-token";
13976
13976
  import { ComputeBudgetProgram as ComputeBudgetProgram5, PublicKey as PublicKey27 } from "@solana/web3.js";
13977
- import BigNumber14 from "bignumber.js";
13977
+ import BigNumber15 from "bignumber.js";
13978
13978
  import BN13 from "bn.js";
13979
13979
 
13980
13980
  // src/services/account/account.service.ts
@@ -13986,7 +13986,7 @@ import {
13986
13986
  TransactionMessage as TransactionMessage4,
13987
13987
  VersionedTransaction as VersionedTransaction4
13988
13988
  } from "@solana/web3.js";
13989
- import BigNumber12 from "bignumber.js";
13989
+ import BigNumber14 from "bignumber.js";
13990
13990
  import BN11 from "bn.js";
13991
13991
 
13992
13992
  // src/models/health-cache.ts
@@ -24971,1168 +24971,1229 @@ function dtoToHealthCache(healthCacheDto) {
24971
24971
  }
24972
24972
 
24973
24973
  // src/services/account/utils/emode.utils.ts
24974
- function computeEmodeImpacts(emodePairs, activeLiabilities, activeCollateral, allBanks) {
24975
- const toKey = (k) => k.toBase58();
24976
- const basePairs = computeActiveEmodePairs(emodePairs, activeLiabilities, activeCollateral);
24977
- const baseOn = basePairs.length > 0;
24978
- const liabTagMap = /* @__PURE__ */ new Map();
24979
- for (const p of emodePairs) {
24980
- liabTagMap.set(p.liabilityBank.toBase58(), p.liabilityBankTag.toString());
24981
- }
24982
- const existingTags = new Set(
24983
- activeLiabilities.map((l) => liabTagMap.get(l.toBase58())).filter((t) => !!t)
24984
- );
24985
- function minWeight(ps) {
24986
- let m = ps[0].assetWeightInit;
24987
- for (const x of ps) if (x.assetWeightInit.lt(m)) m = x.assetWeightInit;
24988
- return m;
24989
- }
24990
- function diffState(before, after) {
24991
- const was = before.length > 0, isOn = after.length > 0;
24992
- if (!was && !isOn) return 5 /* InactiveEmode */;
24993
- if (!was && isOn) return 0 /* ActivateEmode */;
24994
- if (was && !isOn) return 4 /* RemoveEmode */;
24995
- const bMin = minWeight(before), aMin = minWeight(after);
24996
- if (aMin.gt(bMin)) return 2 /* IncreaseEmode */;
24997
- if (aMin.lt(bMin)) return 3 /* ReduceEmode */;
24998
- return 1 /* ExtendEmode */;
24999
- }
25000
- function simulate(bank, action) {
25001
- let L = [...activeLiabilities], C = [...activeCollateral];
25002
- switch (action) {
25003
- case "borrow":
25004
- if (!L.some((x) => x.equals(bank))) L.push(bank);
25005
- break;
25006
- case "repay":
25007
- L = L.filter((x) => !x.equals(bank));
25008
- break;
25009
- case "supply":
25010
- if (!C.some((x) => x.equals(bank))) C.push(bank);
25011
- break;
25012
- case "withdraw":
25013
- C = C.filter((x) => !x.equals(bank));
25014
- break;
25015
- }
25016
- const after = computeActiveEmodePairs(emodePairs, L, C);
25017
- let status = diffState(basePairs, after);
25018
- if (action === "borrow") {
25019
- const tag = liabTagMap.get(bank.toBase58());
25020
- if (!tag) {
25021
- status = baseOn ? 4 /* RemoveEmode */ : 5 /* InactiveEmode */;
25022
- } else if (baseOn) {
25023
- if (after.length === 0) {
25024
- status = 4 /* RemoveEmode */;
25025
- } else if (existingTags.has(tag)) {
25026
- status = 1 /* ExtendEmode */;
25027
- }
25028
- }
25029
- }
25030
- if (action === "supply") {
25031
- const isOn = after.length > 0;
25032
- status = !baseOn && isOn ? 0 /* ActivateEmode */ : baseOn && isOn ? 1 /* ExtendEmode */ : 5 /* InactiveEmode */;
25033
- }
25034
- if (action === "withdraw") {
25035
- if (!baseOn) {
25036
- status = 5 /* InactiveEmode */;
25037
- } else if (after.length === 0) {
25038
- status = 4 /* RemoveEmode */;
25039
- } else {
25040
- const b = minWeight(basePairs), a = minWeight(after);
25041
- if (a.gt(b)) status = 2 /* IncreaseEmode */;
25042
- else if (a.lt(b)) status = 3 /* ReduceEmode */;
25043
- else status = 1 /* ExtendEmode */;
25044
- }
25045
- }
25046
- let bestPair;
25047
- if (after.length > 0) {
25048
- bestPair = after[0];
25049
- for (const p of after) {
25050
- if (p.assetWeightInit.lt(bestPair.assetWeightInit)) {
25051
- bestPair = p;
25052
- }
25053
- }
25054
- }
25055
- const activeEmodePair = bestPair ? {
25056
- collateralBanks: Array.from(
25057
- new Map(after.flatMap((p) => p.collateralBanks).map((bank2) => [bank2.toBase58(), bank2])).values()
25058
- ),
25059
- collateralBankTags: Array.from(new Set(after.flatMap((p) => p.collateralBankTag))),
25060
- liabilityBanks: Array.from(
25061
- new Map(after.flatMap((p) => p.liabilityBank).map((bank2) => [bank2.toBase58(), bank2])).values()
25062
- ),
25063
- liabilityBankTags: Array.from(new Set(after.flatMap((p) => p.liabilityBankTag))),
25064
- assetWeightMaint: bestPair.assetWeightMaint,
25065
- assetWeightInit: bestPair.assetWeightInit
25066
- } : void 0;
25067
- return {
25068
- status,
25069
- resultingPairs: after,
25070
- activePair: activeEmodePair
25071
- };
25072
- }
25073
- const result = {};
25074
- for (const bank of allBanks) {
25075
- const key = toKey(bank);
25076
- const impact = {};
25077
- if (!activeCollateral.some((x) => x.equals(bank))) {
25078
- impact.borrowImpact = simulate(bank, "borrow");
25079
- }
25080
- const collSet = new Set(emodePairs.flatMap((p) => p.collateralBanks.map((c) => c.toBase58())));
25081
- if (collSet.has(key) && !activeCollateral.some((x) => x.equals(bank)) && !activeLiabilities.some((x) => x.equals(bank))) {
25082
- impact.supplyImpact = simulate(bank, "supply");
25083
- }
25084
- if (activeLiabilities.some((x) => x.equals(bank))) {
25085
- impact.repayAllImpact = simulate(bank, "repay");
25086
- }
25087
- if (activeCollateral.some((x) => x.equals(bank))) {
25088
- impact.withdrawAllImpact = simulate(bank, "withdraw");
25089
- }
25090
- result[key] = impact;
24974
+ import BigNumber13 from "bignumber.js";
24975
+
24976
+ // src/models/bank.ts
24977
+ import BigNumber12 from "bignumber.js";
24978
+ var SECONDS_PER_DAY2 = 24 * 60 * 60;
24979
+ var _SECONDS_PER_YEAR = SECONDS_PER_DAY2 * 365.25;
24980
+ var Bank = class _Bank {
24981
+ constructor(address, mint, mintDecimals, group, mintRate, mintPrice, assetShareValue, liabilityShareValue, liquidityVault, liquidityVaultBump, liquidityVaultAuthorityBump, insuranceVault, insuranceVaultBump, insuranceVaultAuthorityBump, collectedInsuranceFeesOutstanding, feeVault, feeVaultBump, feeVaultAuthorityBump, collectedGroupFeesOutstanding, lastUpdate, config, totalAssetShares, totalLiabilityShares, flags, emissionsActiveBorrowing, emissionsActiveLending, emissionsRate, emissionsMint, emissionsRemaining, oracleKey, emode, feesDestinationAccount, lendingPositionCount, borrowingPositionCount, pythShardId, tokenSymbol, extendedMetadata, owner) {
24982
+ this.address = address;
24983
+ this.mint = mint;
24984
+ this.mintDecimals = mintDecimals;
24985
+ this.group = group;
24986
+ this.mintRate = mintRate;
24987
+ this.mintPrice = mintPrice;
24988
+ this.assetShareValue = assetShareValue;
24989
+ this.liabilityShareValue = liabilityShareValue;
24990
+ this.liquidityVault = liquidityVault;
24991
+ this.liquidityVaultBump = liquidityVaultBump;
24992
+ this.liquidityVaultAuthorityBump = liquidityVaultAuthorityBump;
24993
+ this.insuranceVault = insuranceVault;
24994
+ this.insuranceVaultBump = insuranceVaultBump;
24995
+ this.insuranceVaultAuthorityBump = insuranceVaultAuthorityBump;
24996
+ this.collectedInsuranceFeesOutstanding = collectedInsuranceFeesOutstanding;
24997
+ this.feeVault = feeVault;
24998
+ this.feeVaultBump = feeVaultBump;
24999
+ this.feeVaultAuthorityBump = feeVaultAuthorityBump;
25000
+ this.collectedGroupFeesOutstanding = collectedGroupFeesOutstanding;
25001
+ this.lastUpdate = lastUpdate;
25002
+ this.config = config;
25003
+ this.totalAssetShares = totalAssetShares;
25004
+ this.totalLiabilityShares = totalLiabilityShares;
25005
+ this.flags = flags;
25006
+ this.emissionsActiveBorrowing = emissionsActiveBorrowing;
25007
+ this.emissionsActiveLending = emissionsActiveLending;
25008
+ this.emissionsRate = emissionsRate;
25009
+ this.emissionsMint = emissionsMint;
25010
+ this.emissionsRemaining = emissionsRemaining;
25011
+ this.oracleKey = oracleKey;
25012
+ this.emode = emode;
25013
+ this.feesDestinationAccount = feesDestinationAccount;
25014
+ this.lendingPositionCount = lendingPositionCount;
25015
+ this.borrowingPositionCount = borrowingPositionCount;
25016
+ this.pythShardId = pythShardId;
25017
+ this.tokenSymbol = tokenSymbol;
25018
+ this.extendedMetadata = extendedMetadata;
25019
+ this.owner = owner;
25091
25020
  }
25092
- return result;
25093
- }
25094
- function computeActiveEmodePairs(emodePairs, activeLiabilities, activeCollateral) {
25095
- const configured = emodePairs.filter(
25096
- (p) => p.collateralBankTag !== EmodeTag.UNSET && p.liabilityBankTag !== EmodeTag.UNSET
25097
- );
25098
- const liabTagByBank = /* @__PURE__ */ new Map();
25099
- for (const p of configured) {
25100
- liabTagByBank.set(p.liabilityBank.toBase58(), p.liabilityBankTag.toString());
25021
+ static decodeBankRaw(encoded, idl) {
25022
+ return decodeBankRaw(encoded, idl);
25101
25023
  }
25102
- const requiredTags = /* @__PURE__ */ new Set();
25103
- for (const liab of activeLiabilities) {
25104
- const tag = liabTagByBank.get(liab.toBase58());
25105
- if (!tag) {
25106
- return [];
25107
- }
25108
- requiredTags.add(tag);
25024
+ static fromBuffer(bankPk, rawData, idl, feedIdMap) {
25025
+ const accountParsed = _Bank.decodeBankRaw(rawData, idl);
25026
+ return _Bank.fromAccountParsed(bankPk, accountParsed, feedIdMap);
25109
25027
  }
25110
- const possible = configured.filter(
25111
- (p) => activeLiabilities.some((l) => l.equals(p.liabilityBank)) && p.collateralBanks.some((c) => activeCollateral.some((a) => a.equals(c)))
25112
- );
25113
- if (possible.length === 0) return [];
25114
- const byCollTag = {};
25115
- for (const p of possible) {
25116
- const ct = p.collateralBankTag.toString();
25117
- if (!byCollTag[ct]) {
25118
- byCollTag[ct] = [];
25119
- }
25120
- byCollTag[ct].push(p);
25028
+ static fromBankType(bankType) {
25029
+ const config = new BankConfig(
25030
+ bankType.config.assetWeightInit,
25031
+ bankType.config.assetWeightMaint,
25032
+ bankType.config.liabilityWeightInit,
25033
+ bankType.config.liabilityWeightMaint,
25034
+ bankType.config.depositLimit,
25035
+ bankType.config.borrowLimit,
25036
+ bankType.config.riskTier,
25037
+ bankType.config.totalAssetValueInitLimit,
25038
+ bankType.config.assetTag,
25039
+ bankType.config.oracleSetup,
25040
+ bankType.config.oracleKeys,
25041
+ bankType.config.oracleMaxAge,
25042
+ bankType.config.interestRateConfig,
25043
+ bankType.config.operationalState,
25044
+ bankType.config.oracleMaxConfidence,
25045
+ bankType.config.fixedPrice,
25046
+ bankType.config.configFlags
25047
+ );
25048
+ return new _Bank(
25049
+ bankType.address,
25050
+ bankType.mint,
25051
+ bankType.mintDecimals,
25052
+ bankType.group,
25053
+ bankType.mintRate,
25054
+ bankType.mintPrice,
25055
+ bankType.assetShareValue,
25056
+ bankType.liabilityShareValue,
25057
+ bankType.liquidityVault,
25058
+ bankType.liquidityVaultBump,
25059
+ bankType.liquidityVaultAuthorityBump,
25060
+ bankType.insuranceVault,
25061
+ bankType.insuranceVaultBump,
25062
+ bankType.insuranceVaultAuthorityBump,
25063
+ bankType.collectedInsuranceFeesOutstanding,
25064
+ bankType.feeVault,
25065
+ bankType.feeVaultBump,
25066
+ bankType.feeVaultAuthorityBump,
25067
+ bankType.collectedGroupFeesOutstanding,
25068
+ bankType.lastUpdate,
25069
+ config,
25070
+ bankType.totalAssetShares,
25071
+ bankType.totalLiabilityShares,
25072
+ bankType.flags,
25073
+ bankType.emissionsActiveBorrowing,
25074
+ bankType.emissionsActiveLending,
25075
+ bankType.emissionsRate,
25076
+ bankType.emissionsMint,
25077
+ bankType.emissionsRemaining,
25078
+ bankType.oracleKey,
25079
+ bankType.emode,
25080
+ bankType.feesDestinationAccount,
25081
+ bankType.lendingPositionCount,
25082
+ bankType.borrowingPositionCount,
25083
+ bankType.pythShardId,
25084
+ bankType.tokenSymbol
25085
+ );
25121
25086
  }
25122
- const validGroups = [];
25123
- for (const group of Object.values(byCollTag)) {
25124
- const supports = new Set(group.map((p) => p.liabilityBankTag.toString()));
25125
- let coversAll = true;
25126
- for (const rt of requiredTags) {
25127
- if (!supports.has(rt)) {
25128
- coversAll = false;
25129
- break;
25130
- }
25131
- }
25132
- if (coversAll) {
25133
- validGroups.push(group);
25134
- }
25087
+ static fromAccountParsed(address, accountParsed, feedIdMap, extendedMetadata, owner) {
25088
+ const props = parseBankRaw(address, accountParsed, feedIdMap);
25089
+ return new _Bank(
25090
+ props.address,
25091
+ props.mint,
25092
+ props.mintDecimals,
25093
+ props.group,
25094
+ props.mintRate,
25095
+ props.mintPrice,
25096
+ props.assetShareValue,
25097
+ props.liabilityShareValue,
25098
+ props.liquidityVault,
25099
+ props.liquidityVaultBump,
25100
+ props.liquidityVaultAuthorityBump,
25101
+ props.insuranceVault,
25102
+ props.insuranceVaultBump,
25103
+ props.insuranceVaultAuthorityBump,
25104
+ props.collectedInsuranceFeesOutstanding,
25105
+ props.feeVault,
25106
+ props.feeVaultBump,
25107
+ props.feeVaultAuthorityBump,
25108
+ props.collectedGroupFeesOutstanding,
25109
+ props.lastUpdate,
25110
+ props.config,
25111
+ props.totalAssetShares,
25112
+ props.totalLiabilityShares,
25113
+ props.flags,
25114
+ props.emissionsActiveBorrowing,
25115
+ props.emissionsActiveLending,
25116
+ props.emissionsRate,
25117
+ props.emissionsMint,
25118
+ props.emissionsRemaining,
25119
+ props.oracleKey,
25120
+ props.emode,
25121
+ props.feesDestinationAccount,
25122
+ props.lendingPositionCount,
25123
+ props.borrowingPositionCount,
25124
+ props.pythShardId,
25125
+ extendedMetadata?.symbol,
25126
+ extendedMetadata,
25127
+ owner
25128
+ );
25135
25129
  }
25136
- if (validGroups.length === 0) return [];
25137
- return validGroups.flat();
25138
- }
25139
-
25140
- // src/services/account/utils/fetch.utils.ts
25141
- var fetchLendrAccountAddresses = async (program, authority, group) => {
25142
- const lendrAccounts = (await program.account.lendrAccount.all([
25143
- {
25144
- memcmp: {
25145
- bytes: group.toBase58(),
25146
- offset: 8
25147
- // lendrGroup is the first field in the account, so only offset is the discriminant
25148
- }
25149
- },
25150
- {
25151
- memcmp: {
25152
- bytes: authority.toBase58(),
25153
- offset: 8 + 32
25154
- // authority is the second field in the account after the authority, so offset by the discriminant and a pubkey
25155
- }
25156
- }
25157
- ])).map((a) => a.publicKey);
25158
- return lendrAccounts;
25159
- };
25160
- var fetchLendrAccountData = async (program, lendrAccountPk, bankMap, oraclePrices, bankMetadataMap) => {
25161
- const lendrAccountRaw = await program.account.lendrAccount.fetch(lendrAccountPk, "confirmed");
25162
- const lendrAccount = LendrAccount.fromAccountParsed(lendrAccountPk, lendrAccountRaw);
25163
- const lendrAccountWithCache = await simulateAccountHealthCacheWithFallback({
25164
- program,
25165
- lendrAccount,
25166
- bankMap,
25167
- oraclePrices,
25168
- bankMetadataMap,
25169
- balances: lendrAccount.balances
25170
- });
25171
- return lendrAccountWithCache;
25172
- };
25173
-
25174
- // src/services/account/utils/serialize.utils.ts
25175
- import BN10 from "bn.js";
25176
- function accountFlagToBN(flag) {
25177
- return new BN10(flag);
25178
- }
25179
- function lendrAccountToDto(lendrAccount) {
25180
- return {
25181
- address: lendrAccount.address.toBase58(),
25182
- group: lendrAccount.group.toBase58(),
25183
- authority: lendrAccount.authority.toBase58(),
25184
- balances: lendrAccount.balances.map(balanceToDto),
25185
- accountFlags: lendrAccount.accountFlags,
25186
- emissionsDestinationAccount: lendrAccount.emissionsDestinationAccount.toBase58(),
25187
- healthCache: healthCacheToDto(lendrAccount.healthCache)
25188
- };
25189
- }
25190
- function balanceToDto(balance) {
25191
- return {
25192
- active: balance.active,
25193
- bankPk: balance.bankPk.toBase58(),
25194
- assetShares: balance.assetShares.toString(),
25195
- liabilityShares: balance.liabilityShares.toString(),
25196
- emissionsOutstanding: balance.emissionsOutstanding.toString(),
25197
- lastUpdate: balance.lastUpdate
25198
- };
25199
- }
25200
- function healthCacheToDto(healthCache) {
25201
- return {
25202
- assetValue: healthCache.assetValue.toString(),
25203
- liabilityValue: healthCache.liabilityValue.toString(),
25204
- assetValueMaint: healthCache.assetValueMaint.toString(),
25205
- liabilityValueMaint: healthCache.liabilityValueMaint.toString(),
25206
- assetValueEquity: healthCache.assetValueEquity.toString(),
25207
- liabilityValueEquity: healthCache.liabilityValueEquity.toString(),
25208
- timestamp: healthCache.timestamp.toString(),
25209
- flags: healthCache.flags,
25210
- prices: healthCache.prices,
25211
- simulationFailed: healthCache.simulationFailed
25212
- };
25213
- }
25214
-
25215
- // src/services/account/account.service.ts
25216
- var HealthCacheSimulationError = class _HealthCacheSimulationError extends Error {
25217
- lndrErr;
25218
- internalErr;
25219
- constructor(message, lndrErr, internalErr) {
25220
- super(message);
25221
- this.name = "HealthCacheSimulationError";
25222
- this.lndrErr = lndrErr;
25223
- this.internalErr = internalErr;
25224
- if (Error.captureStackTrace) {
25225
- Error.captureStackTrace(this, _HealthCacheSimulationError);
25226
- }
25130
+ static withEmodeWeights(bank, emodeWeights) {
25131
+ const newBank = Object.create(_Bank.prototype);
25132
+ Object.assign(newBank, bank);
25133
+ newBank.config = Object.assign({}, bank.config);
25134
+ newBank.config.assetWeightInit = BigNumber12.max(bank.config.assetWeightInit, emodeWeights.assetWeightInit);
25135
+ newBank.config.assetWeightMaint = BigNumber12.max(bank.config.assetWeightMaint, emodeWeights.assetWeightMaint);
25136
+ return newBank;
25227
25137
  }
25228
- };
25229
- async function simulateAccountHealthCacheWithFallback(props) {
25230
- let lendrAccount = props.lendrAccount;
25231
- const activeBalances = props.balances.filter((b) => b.active);
25232
- const { assets: assetValueEquity, liabilities: liabilityValueEquity } = computeHealthComponentsWithoutBiasLegacy(
25233
- activeBalances,
25234
- props.bankMap,
25235
- props.oraclePrices,
25236
- 2 /* Equity */
25237
- );
25238
- try {
25239
- const simulatedAccount = await simulateAccountHealthCache({
25240
- program: props.program,
25241
- bankMap: props.bankMap,
25242
- oraclePrices: props.oraclePrices,
25243
- lendrAccountPk: props.lendrAccount.address,
25244
- balances: props.balances,
25245
- bankMetadataMap: props.bankMetadataMap
25246
- });
25247
- simulatedAccount.healthCache.assetValueEquity = bigNumberToWrappedI80F48(assetValueEquity);
25248
- simulatedAccount.healthCache.liabilityValueEquity = bigNumberToWrappedI80F48(liabilityValueEquity);
25249
- lendrAccount = LendrAccount.fromAccountParsed(props.lendrAccount.address, simulatedAccount);
25250
- } catch (e) {
25251
- console.log("e", e);
25252
- const { assets: assetValueMaint, liabilities: liabilityValueMaint } = computeHealthComponentsLegacy(
25253
- activeBalances,
25254
- props.bankMap,
25255
- props.oraclePrices,
25256
- 1 /* Maintenance */
25257
- );
25258
- const { assets: assetValueInitial, liabilities: liabilityValueInitial } = computeHealthComponentsLegacy(
25259
- activeBalances,
25260
- props.bankMap,
25261
- props.oraclePrices,
25262
- 0 /* Initial */
25263
- );
25264
- lendrAccount.setHealthCache(
25265
- new HealthCache(
25266
- assetValueInitial,
25267
- liabilityValueInitial,
25268
- assetValueMaint,
25269
- liabilityValueMaint,
25270
- assetValueEquity,
25271
- liabilityValueEquity,
25272
- new BigNumber12(0),
25273
- [],
25274
- [],
25275
- true
25276
- )
25277
- );
25278
- if (e instanceof HealthCacheSimulationError) {
25279
- return { lendrAccount, error: e };
25280
- }
25138
+ static getPrice(oraclePrice, priceBias = 1 /* None */, weightedPrice = false) {
25139
+ return getPrice(oraclePrice, priceBias, weightedPrice);
25281
25140
  }
25282
- return { lendrAccount };
25283
- }
25284
- async function simulateAccountHealthCache(props) {
25285
- const { program, bankMap, oraclePrices, lendrAccountPk, balances, bankMetadataMap } = props;
25286
- const activeBalances = balances.filter((b) => b.active);
25287
- const { staleSwbOracles } = getActiveStaleBanks(activeBalances, bankMap, [], oraclePrices, 30);
25288
- const computeIx = ComputeBudgetProgram4.setComputeUnitLimit({ units: 14e5 });
25289
- const blockhash = (await program.provider.connection.getLatestBlockhash("confirmed")).blockhash;
25290
- const fundAccountIx = SystemProgram3.transfer({
25291
- fromPubkey: new PublicKey22("DD3AeAssFvjqTvRTrRAtpfjkBF8FpVKnFuwnMLN9haXD"),
25292
- // lendr SOL VAULT
25293
- toPubkey: program.provider.publicKey,
25294
- lamports: 1e8
25295
- // 0.1 SOL
25296
- });
25297
- const crankPythIxs = {
25298
- postInstructions: [],
25299
- closeInstructions: [],
25300
- keys: [],
25301
- lut: null
25302
- };
25303
- const crankSwbIxs = staleSwbOracles.length > 0 ? await createUpdateFeedIx({
25304
- swbPullOracles: staleSwbOracles.map((oracle) => oracle.oracleKey),
25305
- provider: program.provider
25306
- }) : { instructions: [], luts: [] };
25307
- const healthPulseIxs = await makePulseHealthIx2(
25308
- program,
25309
- lendrAccountPk,
25310
- bankMap,
25311
- balances,
25312
- activeBalances.map((b) => b.bankPk),
25313
- [],
25314
- bankMetadataMap
25315
- );
25316
- const pythLut = crankPythIxs.lut ? [crankPythIxs.lut] : [];
25317
- const txs = [];
25318
- if (crankPythIxs.postInstructions.length > 0) {
25319
- txs.push(
25320
- ...splitInstructionsToFitTransactions(
25321
- [computeIx],
25322
- [
25323
- fundAccountIx,
25324
- ...crankPythIxs.postInstructions.map((ix) => ix.instruction),
25325
- ...crankPythIxs.closeInstructions.map((ix) => ix.instruction)
25326
- ],
25327
- {
25328
- blockhash,
25329
- payerKey: program.provider.publicKey,
25330
- luts: [...crankSwbIxs.luts, ...pythLut]
25331
- }
25332
- )
25333
- );
25141
+ static computeQuantityFromUsdValue(oraclePrice, usdValue, priceBias, weightedPrice) {
25142
+ const price = getPrice(oraclePrice, priceBias, weightedPrice);
25143
+ return usdValue.div(price);
25334
25144
  }
25335
- const messageV0 = new TransactionMessage4({
25336
- payerKey: program.provider.publicKey,
25337
- recentBlockhash: blockhash,
25338
- instructions: [...crankSwbIxs.instructions]
25339
- }).compileToV0Message([...crankSwbIxs.luts]);
25340
- const swbTx = new VersionedTransaction4(messageV0);
25341
- txs.push(swbTx);
25342
- const healthTx = new TransactionMessage4({
25343
- payerKey: program.provider.publicKey,
25344
- recentBlockhash: blockhash,
25345
- instructions: [...healthPulseIxs.instructions]
25346
- }).compileToV0Message([]);
25347
- const healthTxV0 = new VersionedTransaction4(healthTx);
25348
- txs.push(healthTxV0);
25349
- if (txs.length > 5) {
25350
- console.error("Too many transactions", txs.length);
25351
- throw new Error("Too many transactions");
25145
+ getTotalAssetQuantity() {
25146
+ return getTotalAssetQuantity(this);
25352
25147
  }
25353
- const simulationResult = await simulateBundle(program.provider.connection.rpcEndpoint, txs, [lendrAccountPk]);
25354
- const postExecutionAccount = simulationResult.find((result) => result.postExecutionAccounts.length > 0);
25355
- if (!postExecutionAccount) {
25356
- throw new Error("Account not found");
25148
+ getTotalLiabilityQuantity() {
25149
+ return getTotalLiabilityQuantity(this);
25357
25150
  }
25358
- const lendrAccountPost = LendrAccount.decodeAccountRaw(
25359
- Buffer.from(postExecutionAccount.postExecutionAccounts[0].data[0], "base64"),
25360
- program.idl
25361
- );
25362
- if (lendrAccountPost.healthCache.lndrErr || lendrAccountPost.healthCache.internalErr) {
25363
- console.log(
25364
- "cranked swb oracles",
25365
- staleSwbOracles.map((oracle) => oracle.oracleKey)
25366
- );
25367
- console.log("LendrAccountPost healthCache internalErr", lendrAccountPost.healthCache.internalErr);
25368
- console.log("LendrAccountPost healthCache lndrErr", lendrAccountPost.healthCache.lndrErr);
25369
- if (lendrAccountPost.healthCache.lndrErr === 6009) {
25370
- const assetValue = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.assetValue).isZero();
25371
- const liabilityValue = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.liabilityValue).isZero();
25372
- const assetValueEquity = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.assetValueEquity).isZero();
25373
- const liabilityValueEquity = !wrappedI80F48toBigNumber(
25374
- lendrAccountPost.healthCache.liabilityValueEquity
25375
- ).isZero();
25376
- const assetValueMaint = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.assetValueMaint).isZero();
25377
- const liabilityValueMaint = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.liabilityValueMaint).isZero();
25378
- if (assetValue && liabilityValue && assetValueEquity && liabilityValueEquity && assetValueMaint && liabilityValueMaint) {
25379
- return lendrAccountPost;
25380
- }
25381
- }
25382
- console.error("Account health cache simulation failed", {
25383
- lndrErr: lendrAccountPost.healthCache.lndrErr,
25384
- internalErr: lendrAccountPost.healthCache.internalErr
25385
- });
25386
- throw new HealthCacheSimulationError(
25387
- "Account health cache simulation failed",
25388
- lendrAccountPost.healthCache.lndrErr,
25389
- lendrAccountPost.healthCache.internalErr
25390
- );
25151
+ getAssetQuantity(assetShares) {
25152
+ return getAssetQuantity(this, assetShares);
25391
25153
  }
25392
- return lendrAccountPost;
25393
- }
25394
- async function makePulseHealthIx2(program, lendrAccountPk, banks, balances, mandatoryBanks, excludedBanks, bankMetadataMap) {
25395
- const healthAccounts = computeHealthCheckAccounts(balances, banks, mandatoryBanks, excludedBanks);
25396
- const accountMetas = computeHealthAccountMetas(healthAccounts, bankMetadataMap);
25397
- const ix = await instructions_default.makePulseHealthIx(
25398
- program,
25399
- {
25400
- lendrAccount: lendrAccountPk
25401
- },
25402
- accountMetas.map((account) => ({ pubkey: account, isSigner: false, isWritable: false }))
25403
- );
25404
- return { instructions: [ix], keys: [] };
25405
- }
25406
- async function createUpdateFeedIx(_props) {
25407
- throw new Error("in terms of switchboard, we have no switchboard");
25408
- }
25409
- async function createLendrAccountTx(props) {
25410
- const authority = props.lendrAccount?.authority ?? props.lendrClient.provider.publicKey;
25411
- const lendrAccountKeypair = Keypair2.generate();
25412
- const dummyWrappedI80F48 = bigNumberToWrappedI80F48(new BigNumber12(0));
25413
- const dummyBalances = Array(15).fill({
25414
- active: false,
25415
- bankPk: new PublicKey22("11111111111111111111111111111111"),
25416
- assetShares: dummyWrappedI80F48,
25417
- liabilityShares: dummyWrappedI80F48,
25418
- emissionsOutstanding: dummyWrappedI80F48,
25419
- lastUpdate: new BN11(0)
25420
- });
25421
- const rawAccount = {
25422
- group: props.lendrClient.group.address,
25423
- authority,
25424
- lendingAccount: { balances: dummyBalances },
25425
- healthCache: {
25426
- assetValue: {
25427
- value: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
25428
- },
25429
- liabilityValue: {
25430
- value: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
25431
- },
25432
- timestamp: new BN11(0),
25433
- flags: 0,
25434
- prices: [],
25435
- assetValueMaint: bigNumberToWrappedI80F48(new BigNumber12(0)),
25436
- liabilityValueMaint: bigNumberToWrappedI80F48(new BigNumber12(0)),
25437
- assetValueEquity: bigNumberToWrappedI80F48(new BigNumber12(0)),
25438
- liabilityValueEquity: bigNumberToWrappedI80F48(new BigNumber12(0)),
25439
- errIndex: 0,
25440
- internalErr: 0,
25441
- internalBankruptcyErr: 0,
25442
- internalLiqErr: 0,
25443
- lndrErr: 0
25444
- },
25445
- emissionsDestinationAccount: new PublicKey22("11111111111111111111111111111111"),
25446
- accountFlags: new BN11([0, 0, 0])
25447
- };
25448
- const account = LendrAccount.fromAccountParsed(lendrAccountKeypair.publicKey, rawAccount);
25449
- const wrappedAccount = new LendrAccountWrapper(lendrAccountKeypair.publicKey, props.lendrClient, account);
25450
- return {
25451
- account: wrappedAccount,
25452
- tx: await props.lendrClient.createLendrAccountTx({ accountKeypair: lendrAccountKeypair })
25453
- };
25454
- }
25455
- function getActiveStaleBanks(balances, banks, additionalBanks, oraclePrices, maxAgeOffset = 0) {
25456
- const activeBanks = balances.filter((balance) => balance.active).map((balance) => banks.get(balance.bankPk.toBase58())).filter((bank) => !!bank);
25457
- const allBanks = [...activeBanks, ...additionalBanks];
25458
- const staleBanks = allBanks.filter((bank) => {
25459
- if (bank.config.oracleSetup === "SwitchboardPull" /* SwitchboardPull */ || bank.config.oracleSetup === "SwitchboardV2" /* SwitchboardV2 */ || bank.config.oracleSetup === "KaminoSwitchboardPull" /* KaminoSwitchboardPull */) {
25460
- return true;
25461
- }
25462
- const oraclePrice = oraclePrices.get(bank.address.toBase58());
25463
- const maxAge = bank.config.oracleMaxAge;
25464
- const currentTime = Math.round(Date.now() / 1e3);
25465
- const oracleTime = Math.round(oraclePrice?.timestamp ? oraclePrice.timestamp.toNumber() : Date.now());
25466
- const adjustedMaxAge = Math.max(maxAge - maxAgeOffset, 0);
25467
- const isStale = currentTime - oracleTime > adjustedMaxAge;
25468
- return isStale;
25469
- });
25470
- if (staleBanks.length > 0) {
25471
- const stalePythFeeds = [];
25472
- const staleSwbOracles = [];
25473
- const seenSwbOracles = /* @__PURE__ */ new Set();
25474
- const seenPythFeeds = /* @__PURE__ */ new Set();
25475
- staleBanks.forEach((bank) => {
25476
- if (bank.config.oracleSetup === "SwitchboardPull" /* SwitchboardPull */ || bank.config.oracleSetup === "KaminoSwitchboardPull" /* KaminoSwitchboardPull */) {
25477
- const key = bank.oracleKey.toBase58();
25478
- if (!seenSwbOracles.has(key)) {
25479
- seenSwbOracles.add(key);
25480
- staleSwbOracles.push({ oracleKey: bank.oracleKey });
25481
- }
25482
- } else if (bank.config.oracleSetup === "PythPushOracle" /* PythPushOracle */ || bank.config.oracleSetup === "StakedWithPythPush" /* StakedWithPythPush */ || bank.config.oracleSetup === "KaminoPythPush" /* KaminoPythPush */) {
25483
- const oraclePrice = oraclePrices.get(bank.address.toBase58());
25484
- const shardId = oraclePrice?.pythShardId ?? 0;
25485
- const feedId = bank.config.oracleKeys[0];
25486
- const feedKey = feedIdToString(feedId);
25487
- if (!seenPythFeeds.has(feedKey)) {
25488
- seenPythFeeds.add(feedKey);
25489
- stalePythFeeds.push({ feedId: feedKey, shardId });
25490
- }
25491
- }
25154
+ getLiabilityQuantity(liabilityShares) {
25155
+ return getLiabilityQuantity(this, liabilityShares);
25156
+ }
25157
+ getAssetShares(assetQuantity) {
25158
+ return getAssetShares(this, assetQuantity);
25159
+ }
25160
+ getLiabilityShares(liabilityQuantity) {
25161
+ return getLiabilityShares(this, liabilityQuantity);
25162
+ }
25163
+ computeAssetUsdValue(oraclePrice, assetShares, lendrRequirementType, priceBias) {
25164
+ return computeAssetUsdValue(this, oraclePrice, assetShares, lendrRequirementType, priceBias);
25165
+ }
25166
+ computeLiabilityUsdValue(oraclePrice, liabilityShares, lendrRequirementType, priceBias) {
25167
+ return computeLiabilityUsdValue(this, oraclePrice, liabilityShares, lendrRequirementType, priceBias);
25168
+ }
25169
+ computeUsdValue(oraclePrice, quantity, priceBias, weightedPrice, weight, scaleToBase = true) {
25170
+ return computeUsdValue(this, oraclePrice, quantity, priceBias, weightedPrice, weight, scaleToBase);
25171
+ }
25172
+ getAssetWeight(lendrRequirementType, oraclePrice, ignoreSoftLimits = false, assetWeightInitOverride) {
25173
+ return getAssetWeight(this, lendrRequirementType, oraclePrice, {
25174
+ ignoreSoftLimits,
25175
+ assetWeightInitOverride
25492
25176
  });
25493
- return { stalePythFeeds, staleSwbOracles };
25494
25177
  }
25495
- return { stalePythFeeds: [], staleSwbOracles: [] };
25496
- }
25178
+ getLiabilityWeight(lendrRequirementType) {
25179
+ return getLiabilityWeight(this.config, lendrRequirementType);
25180
+ }
25181
+ computeTvl(oraclePrice) {
25182
+ return computeTvl(this, oraclePrice);
25183
+ }
25184
+ computeInterestRates() {
25185
+ return computeInterestRates(this);
25186
+ }
25187
+ computeBaseInterestRate() {
25188
+ return computeBaseInterestRate(this);
25189
+ }
25190
+ computeUtilizationRate() {
25191
+ return computeUtilizationRate(this);
25192
+ }
25193
+ computeRemainingCapacity() {
25194
+ return computeRemainingCapacity(this);
25195
+ }
25196
+ describe(oraclePrice) {
25197
+ return `
25198
+ Bank address: ${this.address.toBase58()}
25199
+ Mint: ${this.mint.toBase58()}, decimals: ${this.mintDecimals}
25497
25200
 
25498
- // src/services/group/group.service.ts
25499
- init_constants();
25500
- import { TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID4 } from "@solana/spl-token";
25501
- import { PublicKey as PublicKey23, StakeProgram as StakeProgram2, SYSVAR_RENT_PUBKEY as SYSVAR_RENT_PUBKEY2, SystemProgram as SystemProgram4, TransactionInstruction as TransactionInstruction2 } from "@solana/web3.js";
25502
- import BN12 from "bn.js";
25503
- init_single_spl_pool();
25504
- async function makePoolConfigureBankIx2(program, bank, args) {
25505
- const ix = await instructions_default.makePoolConfigureBankIx(
25506
- program,
25507
- {
25508
- bank
25509
- },
25510
- { bankConfigOpt: args }
25511
- );
25512
- return {
25513
- instructions: [ix],
25514
- keys: []
25515
- };
25516
- }
25517
- async function makeAddPermissionlessStakedBankIx(program, group, voteAccountAddress, feePayer, pythOracle) {
25518
- const [settingsKey] = PublicKey23.findProgramAddressSync(
25519
- [Buffer.from("staked_settings", "utf-8"), group.toBuffer()],
25520
- program.programId
25521
- );
25522
- const poolAddress = findPoolAddress(voteAccountAddress);
25523
- const solPool = findPoolStakeAddress(poolAddress);
25524
- const lstMint = findPoolMintAddress(poolAddress);
25525
- const onRampAddress = findPoolOnRampAddress(poolAddress);
25526
- const keys = [
25527
- { pubkey: poolAddress, isSigner: false, isWritable: false },
25528
- { pubkey: onRampAddress, isSigner: false, isWritable: true },
25529
- { pubkey: solPool, isSigner: false, isWritable: false },
25530
- { pubkey: SYSVAR_RENT_PUBKEY2, isSigner: false, isWritable: false },
25531
- { pubkey: SystemProgram4.programId, isSigner: false, isWritable: false },
25532
- { pubkey: StakeProgram2.programId, isSigner: false, isWritable: false }
25533
- ];
25534
- const data = Buffer.from(Uint8Array.of(6));
25535
- const _onrampIx = new TransactionInstruction2({
25536
- keys,
25537
- programId: SINGLE_POOL_PROGRAM_ID,
25538
- data
25539
- });
25540
- const remainingKeys = [pythOracle, lstMint, solPool];
25541
- const ix = await instructions_default.makePoolAddPermissionlessStakedBankIx(
25542
- program,
25543
- {
25544
- stakedSettings: settingsKey,
25545
- feePayer,
25546
- bankMint: lstMint,
25547
- solPool,
25548
- stakePool: poolAddress
25549
- },
25550
- remainingKeys.map((key) => ({ pubkey: key, isSigner: false, isWritable: false })),
25551
- {
25552
- seed: new BN12(0)
25553
- }
25554
- );
25555
- return {
25556
- instructions: [ix],
25557
- keys: []
25558
- };
25559
- }
25560
- async function makePoolAddBankIx2(program, group, bank, feePayer, bankMint, bankConfig, tokenProgram = TOKEN_PROGRAM_ID4, overrideOpt = {}) {
25561
- const rawBankConfig = serializeBankConfigOpt(bankConfig);
25562
- const rawBankConfigCompact = {
25563
- ...rawBankConfig,
25564
- oracleMaxAge: bankConfig.oracleMaxAge,
25565
- auto_padding_0: [0],
25566
- auto_padding_1: [0]
25567
- };
25568
- const ix = await instructions_default.makePoolAddBankIx(
25569
- program,
25570
- {
25571
- lendrGroup: group,
25572
- feePayer,
25573
- bankMint,
25574
- bank,
25575
- tokenProgram,
25576
- ...overrideOpt
25577
- // if two oracle keys: first is feed id, second is oracle key
25578
- },
25579
- {
25580
- bankConfig: rawBankConfigCompact
25581
- }
25582
- );
25583
- return {
25584
- instructions: [ix],
25585
- //ix
25586
- keys: []
25587
- };
25588
- }
25201
+ Total deposits: ${nativeToUi(this.getTotalAssetQuantity(), this.mintDecimals)}
25202
+ Total borrows: ${nativeToUi(this.getTotalLiabilityQuantity(), this.mintDecimals)}
25589
25203
 
25590
- // src/services/group/utils/deserialize.utils.ts
25591
- import { PublicKey as PublicKey24 } from "@solana/web3.js";
25592
- function dtoToGroup(groupDto) {
25593
- return {
25594
- admin: new PublicKey24(groupDto.admin),
25595
- address: new PublicKey24(groupDto.address)
25596
- };
25597
- }
25204
+ Total assets (USD value): ${this.computeAssetUsdValue(
25205
+ oraclePrice,
25206
+ this.totalAssetShares,
25207
+ 2 /* Equity */,
25208
+ 1 /* None */
25209
+ )}
25210
+ Total liabilities (USD value): ${this.computeLiabilityUsdValue(
25211
+ oraclePrice,
25212
+ this.totalLiabilityShares,
25213
+ 2 /* Equity */,
25214
+ 1 /* None */
25215
+ )}
25598
25216
 
25599
- // src/services/group/utils/serialize.utils.ts
25600
- function groupToDto(group) {
25601
- return {
25602
- admin: group.admin.toBase58(),
25603
- address: group.address.toBase58()
25604
- };
25605
- }
25217
+ Asset price (USD): ${_Bank.getPrice(oraclePrice, 1 /* None */, false)}
25218
+ Asset price Weighted (USD): ${_Bank.getPrice(oraclePrice, 1 /* None */, true)}
25606
25219
 
25607
- // src/services/native-stake/utils/deserialize.utils.ts
25608
- import { PublicKey as PublicKey25 } from "@solana/web3.js";
25609
- function dtoToValidatorStakeGroup(validatorStakeGroupDto) {
25610
- return {
25611
- validator: new PublicKey25(validatorStakeGroupDto.validator),
25612
- poolKey: new PublicKey25(validatorStakeGroupDto.poolKey),
25613
- poolMintKey: new PublicKey25(validatorStakeGroupDto.poolMintKey),
25614
- totalStake: validatorStakeGroupDto.totalStake,
25615
- selectedAccount: {
25616
- pubkey: new PublicKey25(validatorStakeGroupDto.selectedAccount.pubkey),
25617
- amount: validatorStakeGroupDto.selectedAccount.amount
25618
- },
25619
- accounts: validatorStakeGroupDto.accounts.map((account) => ({
25620
- pubkey: new PublicKey25(account.pubkey),
25621
- amount: account.amount
25622
- }))
25623
- };
25624
- }
25220
+ Config:
25221
+ - Asset weight init: ${this.config.assetWeightInit.toFixed(2)}
25222
+ - Asset weight maint: ${this.config.assetWeightMaint.toFixed(2)}
25223
+ - Liability weight init: ${this.config.liabilityWeightInit.toFixed(2)}
25224
+ - Liability weight maint: ${this.config.liabilityWeightMaint.toFixed(2)}
25625
25225
 
25626
- // src/services/native-stake/utils/fetch.utils.ts
25627
- init_constants();
25628
- init_single_spl_pool();
25629
- import { LAMPORTS_PER_SOL as LAMPORTS_PER_SOL4, PublicKey as PublicKey26, StakeProgram as StakeProgram3 } from "@solana/web3.js";
25630
- var fetchNativeStakeAccounts = async (connection, publicKey3, opts = {
25631
- filterInactive: true
25632
- }) => {
25633
- if (!connection || !publicKey3) {
25634
- throw new Error("Invalid connection or public key");
25226
+ - Deposit limit: ${this.config.depositLimit}
25227
+ - Borrow limit: ${this.config.borrowLimit}
25228
+
25229
+ LTVs:
25230
+ - Initial: ${new BigNumber12(1).div(this.config.liabilityWeightInit).times(100).toFixed(2)}%
25231
+ - Maintenance: ${new BigNumber12(1).div(this.config.liabilityWeightMaint).times(100).toFixed(2)}%
25232
+ `;
25635
25233
  }
25636
- try {
25637
- const epochInfo = await connection.getEpochInfo();
25638
- const accounts = await connection.getParsedProgramAccounts(StakeProgram3.programId, {
25639
- filters: [
25640
- {
25641
- memcmp: {
25642
- offset: 12,
25643
- bytes: publicKey3.toBase58()
25644
- }
25645
- }
25646
- ]
25647
- });
25648
- const validatorMap = /* @__PURE__ */ new Map();
25649
- await Promise.all(
25650
- accounts.map(async (acc) => {
25651
- const parsedAccount = acc.account.data;
25652
- const stakeInfo = parsedAccount.parsed.info;
25653
- if (!stakeInfo.stake?.delegation || opts.filterInactive && (Number(stakeInfo.stake.delegation.activationEpoch) >= epochInfo.epoch || stakeInfo.stake.delegation.deactivationEpoch !== MAX_U64)) {
25654
- return;
25655
- }
25656
- const validatorAddress = stakeInfo.stake.delegation.voter;
25657
- const accountPubkey = acc.pubkey;
25658
- const amount = Number(stakeInfo.stake.delegation.stake) / LAMPORTS_PER_SOL4;
25659
- const existingAccounts = validatorMap.get(validatorAddress) || [];
25660
- validatorMap.set(validatorAddress, [...existingAccounts, { pubkey: accountPubkey, amount }]);
25661
- })
25662
- );
25663
- return Promise.all(
25664
- Array.from(validatorMap.entries()).map(async ([validatorAddress, accounts2]) => {
25665
- const poolKey = findPoolAddress(new PublicKey26(validatorAddress));
25666
- const poolMintKey = findPoolMintAddress(poolKey);
25667
- const totalStake = accounts2.reduce((acc, curr) => acc + curr.amount, 0);
25668
- const largestAccount = accounts2.reduce((acc, curr) => acc.amount > curr.amount ? acc : curr);
25669
- const sortedAccounts = accounts2.sort((a, b) => b.amount - a.amount);
25670
- if (!sortedAccounts[0].pubkey.equals(largestAccount.pubkey)) {
25671
- sortedAccounts.unshift(sortedAccounts.splice(sortedAccounts.indexOf(largestAccount), 1)[0]);
25672
- }
25673
- return {
25674
- validator: new PublicKey26(validatorAddress),
25675
- poolKey,
25676
- poolMintKey,
25677
- accounts: sortedAccounts,
25678
- totalStake,
25679
- selectedAccount: largestAccount
25680
- };
25681
- })
25234
+ };
25235
+ var BankConfig = class _BankConfig {
25236
+ constructor(assetWeightInit, assetWeightMaint, liabilityWeightInit, liabilityWeightMaint, depositLimit, borrowLimit, riskTier, totalAssetValueInitLimit, assetTag, oracleSetup, oracleKeys, oracleMaxAge, interestRateConfig, operationalState, oracleMaxConfidence, fixedPrice, configFlags) {
25237
+ this.assetWeightInit = assetWeightInit;
25238
+ this.assetWeightMaint = assetWeightMaint;
25239
+ this.liabilityWeightInit = liabilityWeightInit;
25240
+ this.liabilityWeightMaint = liabilityWeightMaint;
25241
+ this.depositLimit = depositLimit;
25242
+ this.borrowLimit = borrowLimit;
25243
+ this.riskTier = riskTier;
25244
+ this.totalAssetValueInitLimit = totalAssetValueInitLimit;
25245
+ this.assetTag = assetTag;
25246
+ this.oracleSetup = oracleSetup;
25247
+ this.oracleKeys = oracleKeys;
25248
+ this.oracleMaxAge = oracleMaxAge;
25249
+ this.interestRateConfig = interestRateConfig;
25250
+ this.operationalState = operationalState;
25251
+ this.oracleMaxConfidence = oracleMaxConfidence;
25252
+ this.fixedPrice = fixedPrice;
25253
+ this.configFlags = configFlags;
25254
+ }
25255
+ static fromAccountParsed(bankConfigRaw) {
25256
+ const bankConfig = parseBankConfigRaw(bankConfigRaw);
25257
+ return new _BankConfig(
25258
+ bankConfig.assetWeightInit,
25259
+ bankConfig.assetWeightMaint,
25260
+ bankConfig.liabilityWeightInit,
25261
+ bankConfig.liabilityWeightMaint,
25262
+ bankConfig.depositLimit,
25263
+ bankConfig.borrowLimit,
25264
+ bankConfig.riskTier,
25265
+ bankConfig.totalAssetValueInitLimit,
25266
+ bankConfig.assetTag,
25267
+ bankConfig.oracleSetup,
25268
+ bankConfig.oracleKeys,
25269
+ bankConfig.oracleMaxAge,
25270
+ bankConfig.interestRateConfig,
25271
+ bankConfig.operationalState,
25272
+ bankConfig.oracleMaxConfidence,
25273
+ bankConfig.fixedPrice,
25274
+ bankConfig.configFlags
25682
25275
  );
25683
- } catch (e) {
25684
- console.error("Error getting stake accounts", e);
25685
- return [];
25686
25276
  }
25687
25277
  };
25688
- var fetchStakePoolActiveStates = async (connection, validatorVoteAccounts) => {
25689
- const currentEpoch = await connection.getEpochInfo();
25690
- const activeStates = /* @__PURE__ */ new Map();
25691
- const poolMintAddressRecord = {};
25692
- const poolStakeAddressRecord = {};
25693
- validatorVoteAccounts.forEach((validatorVoteAccount) => {
25694
- const poolAddress = findPoolAddress(validatorVoteAccount);
25695
- const poolStakeAddress = findPoolStakeAddress(poolAddress);
25696
- const poolMintAddress = findPoolMintAddress(poolAddress);
25697
- poolMintAddressRecord[validatorVoteAccount.toBase58()] = poolMintAddress;
25698
- poolStakeAddressRecord[poolStakeAddress.toBase58()] = validatorVoteAccount;
25699
- });
25700
- const poolStakeAddressKeys = Object.keys(poolStakeAddressRecord);
25701
- const poolStakeAccounts = Object.fromEntries(
25702
- (await chunkedGetRawMultipleAccountInfoOrdered(connection, poolStakeAddressKeys)).map((ai, index) => [
25703
- poolStakeAddressRecord[poolStakeAddressKeys[index]],
25704
- ai?.data || null
25705
- ])
25278
+
25279
+ // src/services/account/utils/emode.utils.ts
25280
+ function computeEmodeImpacts(emodePairs, activeLiabilities, activeCollateral, allBanks) {
25281
+ const toKey = (k) => k.toBase58();
25282
+ const basePairs = computeActiveEmodePairs(emodePairs, activeLiabilities, activeCollateral);
25283
+ const baseOn = basePairs.length > 0;
25284
+ const liabTagMap = /* @__PURE__ */ new Map();
25285
+ for (const p of emodePairs) {
25286
+ liabTagMap.set(p.liabilityBank.toBase58(), p.liabilityBankTag.toString());
25287
+ }
25288
+ const existingTags = new Set(
25289
+ activeLiabilities.map((l) => liabTagMap.get(l.toBase58())).filter((t) => !!t)
25706
25290
  );
25707
- validatorVoteAccounts.forEach((validatorVoteAccount) => {
25708
- const stakeAccount = fetchStakeAccount(poolStakeAccounts[validatorVoteAccount.toBase58()]);
25709
- const poolMintAddress = poolMintAddressRecord[validatorVoteAccount.toBase58()];
25710
- if (!stakeAccount) {
25711
- activeStates.set(poolMintAddress.toBase58(), false);
25712
- return;
25291
+ function minWeight(ps) {
25292
+ let m = ps[0].assetWeightInit;
25293
+ for (const x of ps) if (x.assetWeightInit.lt(m)) m = x.assetWeightInit;
25294
+ return m;
25295
+ }
25296
+ function diffState(before, after) {
25297
+ const was = before.length > 0, isOn = after.length > 0;
25298
+ if (!was && !isOn) return 5 /* InactiveEmode */;
25299
+ if (!was && isOn) return 0 /* ActivateEmode */;
25300
+ if (was && !isOn) return 4 /* RemoveEmode */;
25301
+ const bMin = minWeight(before), aMin = minWeight(after);
25302
+ if (aMin.gt(bMin)) return 2 /* IncreaseEmode */;
25303
+ if (aMin.lt(bMin)) return 3 /* ReduceEmode */;
25304
+ return 1 /* ExtendEmode */;
25305
+ }
25306
+ function simulate(bank, action) {
25307
+ let L = [...activeLiabilities], C = [...activeCollateral];
25308
+ switch (action) {
25309
+ case "borrow":
25310
+ if (!L.some((x) => x.equals(bank))) L.push(bank);
25311
+ break;
25312
+ case "repay":
25313
+ L = L.filter((x) => !x.equals(bank));
25314
+ break;
25315
+ case "supply":
25316
+ if (!C.some((x) => x.equals(bank))) C.push(bank);
25317
+ break;
25318
+ case "withdraw":
25319
+ C = C.filter((x) => !x.equals(bank));
25320
+ break;
25713
25321
  }
25714
- if (!stakeAccount.stake?.delegation) {
25715
- activeStates.set(poolMintAddress.toBase58(), false);
25716
- return;
25322
+ const after = computeActiveEmodePairs(emodePairs, L, C);
25323
+ let status = diffState(basePairs, after);
25324
+ if (action === "borrow") {
25325
+ const tag = liabTagMap.get(bank.toBase58());
25326
+ if (!tag) {
25327
+ status = baseOn ? 4 /* RemoveEmode */ : 5 /* InactiveEmode */;
25328
+ } else if (baseOn) {
25329
+ if (after.length === 0) {
25330
+ status = 4 /* RemoveEmode */;
25331
+ } else if (existingTags.has(tag)) {
25332
+ status = 1 /* ExtendEmode */;
25333
+ }
25334
+ }
25717
25335
  }
25718
- const activationEpoch = stakeAccount.stake.delegation.activationEpoch;
25719
- const isActive = currentEpoch.epoch > Number(activationEpoch);
25720
- activeStates.set(validatorVoteAccount.toBase58(), isActive);
25721
- });
25722
- return activeStates;
25723
- };
25724
- var fetchStakeAccount = (data) => {
25725
- let offset = 0;
25726
- const discriminant = data.readUInt32LE(offset);
25727
- offset += 4;
25728
- const rentExemptReserve = data.readBigUInt64LE(offset);
25729
- offset += 8;
25730
- const staker = new PublicKey26(data.subarray(offset, offset + 32));
25731
- offset += 32;
25732
- const withdrawer = new PublicKey26(data.subarray(offset, offset + 32));
25733
- offset += 32;
25734
- const unixTimestamp = data.readBigUInt64LE(offset);
25735
- offset += 8;
25736
- const epoch = data.readBigUInt64LE(offset);
25737
- offset += 8;
25738
- const custodian = new PublicKey26(data.subarray(offset, offset + 32));
25739
- offset += 32;
25740
- const voterPubkey = new PublicKey26(data.subarray(offset, offset + 32));
25741
- offset += 32;
25742
- const stake = data.readBigUInt64LE(offset);
25743
- offset += 8;
25744
- const activationEpoch = data.readBigUInt64LE(offset);
25745
- offset += 8;
25746
- const deactivationEpoch = data.readBigUInt64LE(offset);
25747
- offset += 8;
25748
- const creditsObserved = data.readBigUInt64LE(offset);
25749
- return {
25750
- discriminant,
25751
- meta: {
25752
- rentExemptReserve,
25753
- authorized: {
25754
- staker,
25755
- withdrawer
25756
- },
25757
- lockup: {
25758
- unixTimestamp,
25759
- epoch,
25760
- custodian
25336
+ if (action === "supply") {
25337
+ const isOn = after.length > 0;
25338
+ status = !baseOn && isOn ? 0 /* ActivateEmode */ : baseOn && isOn ? 1 /* ExtendEmode */ : 5 /* InactiveEmode */;
25339
+ }
25340
+ if (action === "withdraw") {
25341
+ if (!baseOn) {
25342
+ status = 5 /* InactiveEmode */;
25343
+ } else if (after.length === 0) {
25344
+ status = 4 /* RemoveEmode */;
25345
+ } else {
25346
+ const b = minWeight(basePairs), a = minWeight(after);
25347
+ if (a.gt(b)) status = 2 /* IncreaseEmode */;
25348
+ else if (a.lt(b)) status = 3 /* ReduceEmode */;
25349
+ else status = 1 /* ExtendEmode */;
25761
25350
  }
25762
- },
25763
- stake: {
25764
- delegation: {
25765
- voterPubkey,
25766
- stake,
25767
- activationEpoch,
25768
- deactivationEpoch
25769
- },
25770
- creditsObserved
25771
25351
  }
25772
- };
25773
- };
25774
- var fetchStakePoolMev = async (connection, validatorVoteAccounts) => {
25775
- const poolAddressRecord = {};
25776
- const poolStakeAddressRecord = {};
25777
- const onRampAddressRecord = {};
25778
- const mev = /* @__PURE__ */ new Map();
25779
- validatorVoteAccounts.forEach((validatorVoteAccount) => {
25780
- const poolAddress = findPoolAddress(validatorVoteAccount);
25781
- const poolStakeAddress = findPoolStakeAddress(poolAddress);
25782
- const onRampAddress = findPoolOnRampAddress(poolAddress);
25783
- poolAddressRecord[validatorVoteAccount.toBase58()] = poolAddress;
25784
- poolStakeAddressRecord[validatorVoteAccount.toBase58()] = poolStakeAddress;
25785
- onRampAddressRecord[validatorVoteAccount.toBase58()] = onRampAddress;
25786
- });
25787
- const poolStakeAddresses = validatorVoteAccounts.map(
25788
- (validatorVoteAccount) => poolStakeAddressRecord[validatorVoteAccount.toBase58()]
25352
+ let bestPair;
25353
+ if (after.length > 0) {
25354
+ bestPair = after[0];
25355
+ for (const p of after) {
25356
+ if (p.assetWeightInit.lt(bestPair.assetWeightInit)) {
25357
+ bestPair = p;
25358
+ }
25359
+ }
25360
+ }
25361
+ const activeEmodePair = bestPair ? {
25362
+ collateralBanks: Array.from(
25363
+ new Map(after.flatMap((p) => p.collateralBanks).map((bank2) => [bank2.toBase58(), bank2])).values()
25364
+ ),
25365
+ collateralBankTags: Array.from(new Set(after.flatMap((p) => p.collateralBankTag))),
25366
+ liabilityBanks: Array.from(
25367
+ new Map(after.flatMap((p) => p.liabilityBank).map((bank2) => [bank2.toBase58(), bank2])).values()
25368
+ ),
25369
+ liabilityBankTags: Array.from(new Set(after.flatMap((p) => p.liabilityBankTag))),
25370
+ assetWeightMaint: bestPair.assetWeightMaint,
25371
+ assetWeightInit: bestPair.assetWeightInit
25372
+ } : void 0;
25373
+ return {
25374
+ status,
25375
+ resultingPairs: after,
25376
+ activePair: activeEmodePair
25377
+ };
25378
+ }
25379
+ const result = {};
25380
+ for (const bank of allBanks) {
25381
+ const key = toKey(bank);
25382
+ const impact = {};
25383
+ if (!activeCollateral.some((x) => x.equals(bank))) {
25384
+ impact.borrowImpact = simulate(bank, "borrow");
25385
+ }
25386
+ const collSet = new Set(emodePairs.flatMap((p) => p.collateralBanks.map((c) => c.toBase58())));
25387
+ if (collSet.has(key) && !activeCollateral.some((x) => x.equals(bank)) && !activeLiabilities.some((x) => x.equals(bank))) {
25388
+ impact.supplyImpact = simulate(bank, "supply");
25389
+ }
25390
+ if (activeLiabilities.some((x) => x.equals(bank))) {
25391
+ impact.repayAllImpact = simulate(bank, "repay");
25392
+ }
25393
+ if (activeCollateral.some((x) => x.equals(bank))) {
25394
+ impact.withdrawAllImpact = simulate(bank, "withdraw");
25395
+ }
25396
+ result[key] = impact;
25397
+ }
25398
+ return result;
25399
+ }
25400
+ function computeActiveEmodePairs(emodePairs, activeLiabilities, activeCollateral) {
25401
+ const configured = emodePairs.filter((p) => p.collateralBankTag !== EmodeTag.UNSET);
25402
+ const liabTagByBank = /* @__PURE__ */ new Map();
25403
+ for (const p of configured) {
25404
+ liabTagByBank.set(p.liabilityBank.toBase58(), p.liabilityBankTag.toString());
25405
+ }
25406
+ const requiredTags = /* @__PURE__ */ new Set();
25407
+ for (const liab of activeLiabilities) {
25408
+ const tag = liabTagByBank.get(liab.toBase58());
25409
+ if (!tag) {
25410
+ return [];
25411
+ }
25412
+ requiredTags.add(tag);
25413
+ }
25414
+ const possible = configured.filter(
25415
+ (p) => activeLiabilities.some((l) => l.equals(p.liabilityBank)) && p.collateralBanks.some((c) => activeCollateral.some((a) => a.equals(c)))
25789
25416
  );
25790
- const onRampAddresses = validatorVoteAccounts.map(
25791
- (validatorVoteAccount) => onRampAddressRecord[validatorVoteAccount.toBase58()]
25417
+ if (possible.length === 0) return [];
25418
+ const byCollTag = {};
25419
+ for (const p of possible) {
25420
+ const ct = p.collateralBankTag.toString();
25421
+ if (!byCollTag[ct]) {
25422
+ byCollTag[ct] = [];
25423
+ }
25424
+ byCollTag[ct].push(p);
25425
+ }
25426
+ const validGroups = [];
25427
+ for (const group of Object.values(byCollTag)) {
25428
+ const supports = new Set(group.map((p) => p.liabilityBankTag.toString()));
25429
+ let coversAll = true;
25430
+ for (const rt of requiredTags) {
25431
+ if (!supports.has(rt)) {
25432
+ coversAll = false;
25433
+ break;
25434
+ }
25435
+ }
25436
+ if (coversAll) {
25437
+ validGroups.push(group);
25438
+ }
25439
+ }
25440
+ if (validGroups.length === 0) return [];
25441
+ return validGroups.flat();
25442
+ }
25443
+ function getEmodePairs(banks) {
25444
+ return banks.filter(
25445
+ (b) => b.emode.emodeTag !== EmodeTag.UNSET || b.emode.emodeEntries.some((e) => e.collateralBankEmodeTag !== 0)
25446
+ ).flatMap(
25447
+ (bank) => bank.emode.emodeEntries.map((entry) => ({
25448
+ collateralBanks: banks.filter((b) => b.emode.emodeTag === entry.collateralBankEmodeTag && !b.address.equals(bank.address)).map((b) => b.address),
25449
+ collateralBankTag: entry.collateralBankEmodeTag,
25450
+ liabilityBank: bank.address,
25451
+ liabilityBankTag: bank.emode.emodeTag,
25452
+ assetWeightMaint: entry.assetWeightMaint,
25453
+ assetWeightInit: entry.assetWeightInit
25454
+ })).filter((pair) => pair.collateralBanks.length > 0)
25792
25455
  );
25793
- const allAddresses = [...poolStakeAddresses, ...onRampAddresses].map((address) => address.toBase58());
25794
- return chunkedGetRawMultipleAccountInfoOrdered(connection, allAddresses).then((accountInfos) => {
25795
- const poolStakeInfos = accountInfos.slice(0, poolStakeAddresses.length);
25796
- const onRampInfos = accountInfos.slice(poolStakeAddresses.length);
25797
- const rent = 2282280;
25798
- validatorVoteAccounts.forEach((validatorVoteAccount, index) => {
25799
- const poolStakeInfo = poolStakeInfos[index];
25800
- const onRampInfo = onRampInfos[index];
25801
- if (poolStakeInfo && onRampInfo) {
25802
- const stakeDecoded = fetchStakeAccount(poolStakeInfo.data);
25803
- const onrampDecoded = fetchStakeAccount(onRampInfo.data);
25804
- const poolLamps = poolStakeInfo.lamports - rent - Number(stakeDecoded.stake.delegation.stake.toString());
25805
- const onrampStake = Number(onrampDecoded.stake.delegation.stake.toString());
25806
- mev.set(validatorVoteAccount.toBase58(), {
25807
- pool: poolLamps >= 1e3 ? poolLamps : 0,
25808
- onramp: onrampStake
25456
+ }
25457
+ function adjustBanksWithEmode(banks, emodePairs) {
25458
+ const originalAssetWeightsMap = /* @__PURE__ */ new Map();
25459
+ if (emodePairs.length === 0) {
25460
+ return { adjustedBanks: banks, originalAssetWeightsMap };
25461
+ }
25462
+ const lowestWeights = /* @__PURE__ */ new Map();
25463
+ for (const pair of emodePairs) {
25464
+ for (const collateralBankPk of pair.collateralBanks) {
25465
+ const bankPkStr = collateralBankPk.toString();
25466
+ const current = lowestWeights.get(bankPkStr);
25467
+ if (!current) {
25468
+ lowestWeights.set(bankPkStr, {
25469
+ assetWeightMaint: pair.assetWeightMaint,
25470
+ assetWeightInit: pair.assetWeightInit
25809
25471
  });
25472
+ continue;
25810
25473
  }
25474
+ lowestWeights.set(bankPkStr, {
25475
+ assetWeightMaint: BigNumber13.min(current.assetWeightMaint, pair.assetWeightMaint),
25476
+ assetWeightInit: BigNumber13.min(current.assetWeightInit, pair.assetWeightInit)
25477
+ });
25478
+ }
25479
+ }
25480
+ const adjustedBanks = banks.map((bank) => {
25481
+ const bankPkStr = bank.address.toString();
25482
+ const lowestWeight = lowestWeights.get(bankPkStr);
25483
+ if (!lowestWeight) return bank;
25484
+ originalAssetWeightsMap.set(bankPkStr, {
25485
+ assetWeightMaint: bank.config.assetWeightMaint,
25486
+ assetWeightInit: bank.config.assetWeightInit
25811
25487
  });
25812
- return mev;
25488
+ return Bank.withEmodeWeights(bank, {
25489
+ assetWeightMaint: BigNumber13.max(lowestWeight.assetWeightMaint, bank.config.assetWeightMaint),
25490
+ assetWeightInit: BigNumber13.max(lowestWeight.assetWeightInit, bank.config.assetWeightInit)
25491
+ });
25492
+ });
25493
+ return { adjustedBanks, originalAssetWeightsMap };
25494
+ }
25495
+ function makeEmodeAssetWeights(bank, pair) {
25496
+ if (!pair) return void 0;
25497
+ return {
25498
+ assetWeightInit: BigNumber13.max(pair.assetWeightInit, bank.config.assetWeightInit),
25499
+ assetWeightMaint: BigNumber13.max(pair.assetWeightMaint, bank.config.assetWeightMaint),
25500
+ collateralTags: "collateralBankTags" in pair ? pair.collateralBankTags : [pair.collateralBankTag]
25501
+ };
25502
+ }
25503
+
25504
+ // src/services/account/utils/fetch.utils.ts
25505
+ var fetchLendrAccountAddresses = async (program, authority, group) => {
25506
+ const lendrAccounts = (await program.account.lendrAccount.all([
25507
+ {
25508
+ memcmp: {
25509
+ bytes: group.toBase58(),
25510
+ offset: 8
25511
+ // lendrGroup is the first field in the account, so only offset is the discriminant
25512
+ }
25513
+ },
25514
+ {
25515
+ memcmp: {
25516
+ bytes: authority.toBase58(),
25517
+ offset: 8 + 32
25518
+ // authority is the second field in the account after the authority, so offset by the discriminant and a pubkey
25519
+ }
25520
+ }
25521
+ ])).map((a) => a.publicKey);
25522
+ return lendrAccounts;
25523
+ };
25524
+ var fetchLendrAccountData = async (program, lendrAccountPk, bankMap, oraclePrices, bankMetadataMap) => {
25525
+ const lendrAccountRaw = await program.account.lendrAccount.fetch(lendrAccountPk, "confirmed");
25526
+ const lendrAccount = LendrAccount.fromAccountParsed(lendrAccountPk, lendrAccountRaw);
25527
+ const lendrAccountWithCache = await simulateAccountHealthCacheWithFallback({
25528
+ program,
25529
+ lendrAccount,
25530
+ bankMap,
25531
+ oraclePrices,
25532
+ bankMetadataMap,
25533
+ balances: lendrAccount.balances
25813
25534
  });
25535
+ return lendrAccountWithCache;
25814
25536
  };
25815
25537
 
25816
- // src/services/native-stake/utils/serialize.utils.ts
25817
- function validatorStakeGroupToDto(validatorStakeGroup) {
25538
+ // src/services/account/utils/serialize.utils.ts
25539
+ import BN10 from "bn.js";
25540
+ function accountFlagToBN(flag) {
25541
+ return new BN10(flag);
25542
+ }
25543
+ function lendrAccountToDto(lendrAccount) {
25818
25544
  return {
25819
- validator: validatorStakeGroup.validator.toBase58(),
25820
- poolKey: validatorStakeGroup.poolKey.toBase58(),
25821
- poolMintKey: validatorStakeGroup.poolMintKey.toBase58(),
25822
- totalStake: validatorStakeGroup.totalStake,
25823
- selectedAccount: {
25824
- pubkey: validatorStakeGroup.selectedAccount.pubkey.toBase58(),
25825
- amount: validatorStakeGroup.selectedAccount.amount
25826
- },
25827
- accounts: validatorStakeGroup.accounts.map((account) => ({
25828
- pubkey: account.pubkey.toBase58(),
25829
- amount: account.amount
25830
- }))
25545
+ address: lendrAccount.address.toBase58(),
25546
+ group: lendrAccount.group.toBase58(),
25547
+ authority: lendrAccount.authority.toBase58(),
25548
+ balances: lendrAccount.balances.map(balanceToDto),
25549
+ accountFlags: lendrAccount.accountFlags,
25550
+ emissionsDestinationAccount: lendrAccount.emissionsDestinationAccount.toBase58(),
25551
+ healthCache: healthCacheToDto(lendrAccount.healthCache)
25552
+ };
25553
+ }
25554
+ function balanceToDto(balance) {
25555
+ return {
25556
+ active: balance.active,
25557
+ bankPk: balance.bankPk.toBase58(),
25558
+ assetShares: balance.assetShares.toString(),
25559
+ liabilityShares: balance.liabilityShares.toString(),
25560
+ emissionsOutstanding: balance.emissionsOutstanding.toString(),
25561
+ lastUpdate: balance.lastUpdate
25562
+ };
25563
+ }
25564
+ function healthCacheToDto(healthCache) {
25565
+ return {
25566
+ assetValue: healthCache.assetValue.toString(),
25567
+ liabilityValue: healthCache.liabilityValue.toString(),
25568
+ assetValueMaint: healthCache.assetValueMaint.toString(),
25569
+ liabilityValueMaint: healthCache.liabilityValueMaint.toString(),
25570
+ assetValueEquity: healthCache.assetValueEquity.toString(),
25571
+ liabilityValueEquity: healthCache.liabilityValueEquity.toString(),
25572
+ timestamp: healthCache.timestamp.toString(),
25573
+ flags: healthCache.flags,
25574
+ prices: healthCache.prices,
25575
+ simulationFailed: healthCache.simulationFailed
25831
25576
  };
25832
25577
  }
25833
25578
 
25834
- // src/models/bank.ts
25835
- import BigNumber13 from "bignumber.js";
25836
- var SECONDS_PER_DAY2 = 24 * 60 * 60;
25837
- var _SECONDS_PER_YEAR = SECONDS_PER_DAY2 * 365.25;
25838
- var Bank = class _Bank {
25839
- constructor(address, mint, mintDecimals, group, mintRate, mintPrice, assetShareValue, liabilityShareValue, liquidityVault, liquidityVaultBump, liquidityVaultAuthorityBump, insuranceVault, insuranceVaultBump, insuranceVaultAuthorityBump, collectedInsuranceFeesOutstanding, feeVault, feeVaultBump, feeVaultAuthorityBump, collectedGroupFeesOutstanding, lastUpdate, config, totalAssetShares, totalLiabilityShares, flags, emissionsActiveBorrowing, emissionsActiveLending, emissionsRate, emissionsMint, emissionsRemaining, oracleKey, emode, feesDestinationAccount, lendingPositionCount, borrowingPositionCount, pythShardId, tokenSymbol, extendedMetadata, owner) {
25840
- this.address = address;
25841
- this.mint = mint;
25842
- this.mintDecimals = mintDecimals;
25843
- this.group = group;
25844
- this.mintRate = mintRate;
25845
- this.mintPrice = mintPrice;
25846
- this.assetShareValue = assetShareValue;
25847
- this.liabilityShareValue = liabilityShareValue;
25848
- this.liquidityVault = liquidityVault;
25849
- this.liquidityVaultBump = liquidityVaultBump;
25850
- this.liquidityVaultAuthorityBump = liquidityVaultAuthorityBump;
25851
- this.insuranceVault = insuranceVault;
25852
- this.insuranceVaultBump = insuranceVaultBump;
25853
- this.insuranceVaultAuthorityBump = insuranceVaultAuthorityBump;
25854
- this.collectedInsuranceFeesOutstanding = collectedInsuranceFeesOutstanding;
25855
- this.feeVault = feeVault;
25856
- this.feeVaultBump = feeVaultBump;
25857
- this.feeVaultAuthorityBump = feeVaultAuthorityBump;
25858
- this.collectedGroupFeesOutstanding = collectedGroupFeesOutstanding;
25859
- this.lastUpdate = lastUpdate;
25860
- this.config = config;
25861
- this.totalAssetShares = totalAssetShares;
25862
- this.totalLiabilityShares = totalLiabilityShares;
25863
- this.flags = flags;
25864
- this.emissionsActiveBorrowing = emissionsActiveBorrowing;
25865
- this.emissionsActiveLending = emissionsActiveLending;
25866
- this.emissionsRate = emissionsRate;
25867
- this.emissionsMint = emissionsMint;
25868
- this.emissionsRemaining = emissionsRemaining;
25869
- this.oracleKey = oracleKey;
25870
- this.emode = emode;
25871
- this.feesDestinationAccount = feesDestinationAccount;
25872
- this.lendingPositionCount = lendingPositionCount;
25873
- this.borrowingPositionCount = borrowingPositionCount;
25874
- this.pythShardId = pythShardId;
25875
- this.tokenSymbol = tokenSymbol;
25876
- this.extendedMetadata = extendedMetadata;
25877
- this.owner = owner;
25878
- }
25879
- static decodeBankRaw(encoded, idl) {
25880
- return decodeBankRaw(encoded, idl);
25881
- }
25882
- static fromBuffer(bankPk, rawData, idl, feedIdMap) {
25883
- const accountParsed = _Bank.decodeBankRaw(rawData, idl);
25884
- return _Bank.fromAccountParsed(bankPk, accountParsed, feedIdMap);
25579
+ // src/services/account/account.service.ts
25580
+ var HealthCacheSimulationError = class _HealthCacheSimulationError extends Error {
25581
+ lndrErr;
25582
+ internalErr;
25583
+ constructor(message, lndrErr, internalErr) {
25584
+ super(message);
25585
+ this.name = "HealthCacheSimulationError";
25586
+ this.lndrErr = lndrErr;
25587
+ this.internalErr = internalErr;
25588
+ if (Error.captureStackTrace) {
25589
+ Error.captureStackTrace(this, _HealthCacheSimulationError);
25590
+ }
25885
25591
  }
25886
- static fromBankType(bankType) {
25887
- const config = new BankConfig(
25888
- bankType.config.assetWeightInit,
25889
- bankType.config.assetWeightMaint,
25890
- bankType.config.liabilityWeightInit,
25891
- bankType.config.liabilityWeightMaint,
25892
- bankType.config.depositLimit,
25893
- bankType.config.borrowLimit,
25894
- bankType.config.riskTier,
25895
- bankType.config.totalAssetValueInitLimit,
25896
- bankType.config.assetTag,
25897
- bankType.config.oracleSetup,
25898
- bankType.config.oracleKeys,
25899
- bankType.config.oracleMaxAge,
25900
- bankType.config.interestRateConfig,
25901
- bankType.config.operationalState,
25902
- bankType.config.oracleMaxConfidence,
25903
- bankType.config.fixedPrice,
25904
- bankType.config.configFlags
25592
+ };
25593
+ async function simulateAccountHealthCacheWithFallback(props) {
25594
+ let lendrAccount = props.lendrAccount;
25595
+ const activeBalances = props.balances.filter((b) => b.active);
25596
+ const { assets: assetValueEquity, liabilities: liabilityValueEquity } = computeHealthComponentsWithoutBiasLegacy(
25597
+ activeBalances,
25598
+ props.bankMap,
25599
+ props.oraclePrices,
25600
+ 2 /* Equity */
25601
+ );
25602
+ try {
25603
+ const simulatedAccount = await simulateAccountHealthCache({
25604
+ program: props.program,
25605
+ bankMap: props.bankMap,
25606
+ oraclePrices: props.oraclePrices,
25607
+ lendrAccountPk: props.lendrAccount.address,
25608
+ balances: props.balances,
25609
+ bankMetadataMap: props.bankMetadataMap
25610
+ });
25611
+ simulatedAccount.healthCache.assetValueEquity = bigNumberToWrappedI80F48(assetValueEquity);
25612
+ simulatedAccount.healthCache.liabilityValueEquity = bigNumberToWrappedI80F48(liabilityValueEquity);
25613
+ lendrAccount = LendrAccount.fromAccountParsed(props.lendrAccount.address, simulatedAccount);
25614
+ } catch (e) {
25615
+ console.log("e", e);
25616
+ const { assets: assetValueMaint, liabilities: liabilityValueMaint } = computeHealthComponentsLegacy(
25617
+ activeBalances,
25618
+ props.bankMap,
25619
+ props.oraclePrices,
25620
+ 1 /* Maintenance */
25905
25621
  );
25906
- return new _Bank(
25907
- bankType.address,
25908
- bankType.mint,
25909
- bankType.mintDecimals,
25910
- bankType.group,
25911
- bankType.mintRate,
25912
- bankType.mintPrice,
25913
- bankType.assetShareValue,
25914
- bankType.liabilityShareValue,
25915
- bankType.liquidityVault,
25916
- bankType.liquidityVaultBump,
25917
- bankType.liquidityVaultAuthorityBump,
25918
- bankType.insuranceVault,
25919
- bankType.insuranceVaultBump,
25920
- bankType.insuranceVaultAuthorityBump,
25921
- bankType.collectedInsuranceFeesOutstanding,
25922
- bankType.feeVault,
25923
- bankType.feeVaultBump,
25924
- bankType.feeVaultAuthorityBump,
25925
- bankType.collectedGroupFeesOutstanding,
25926
- bankType.lastUpdate,
25927
- config,
25928
- bankType.totalAssetShares,
25929
- bankType.totalLiabilityShares,
25930
- bankType.flags,
25931
- bankType.emissionsActiveBorrowing,
25932
- bankType.emissionsActiveLending,
25933
- bankType.emissionsRate,
25934
- bankType.emissionsMint,
25935
- bankType.emissionsRemaining,
25936
- bankType.oracleKey,
25937
- bankType.emode,
25938
- bankType.feesDestinationAccount,
25939
- bankType.lendingPositionCount,
25940
- bankType.borrowingPositionCount,
25941
- bankType.pythShardId,
25942
- bankType.tokenSymbol
25622
+ const { assets: assetValueInitial, liabilities: liabilityValueInitial } = computeHealthComponentsLegacy(
25623
+ activeBalances,
25624
+ props.bankMap,
25625
+ props.oraclePrices,
25626
+ 0 /* Initial */
25943
25627
  );
25944
- }
25945
- static fromAccountParsed(address, accountParsed, feedIdMap, extendedMetadata, owner) {
25946
- const props = parseBankRaw(address, accountParsed, feedIdMap);
25947
- return new _Bank(
25948
- props.address,
25949
- props.mint,
25950
- props.mintDecimals,
25951
- props.group,
25952
- props.mintRate,
25953
- props.mintPrice,
25954
- props.assetShareValue,
25955
- props.liabilityShareValue,
25956
- props.liquidityVault,
25957
- props.liquidityVaultBump,
25958
- props.liquidityVaultAuthorityBump,
25959
- props.insuranceVault,
25960
- props.insuranceVaultBump,
25961
- props.insuranceVaultAuthorityBump,
25962
- props.collectedInsuranceFeesOutstanding,
25963
- props.feeVault,
25964
- props.feeVaultBump,
25965
- props.feeVaultAuthorityBump,
25966
- props.collectedGroupFeesOutstanding,
25967
- props.lastUpdate,
25968
- props.config,
25969
- props.totalAssetShares,
25970
- props.totalLiabilityShares,
25971
- props.flags,
25972
- props.emissionsActiveBorrowing,
25973
- props.emissionsActiveLending,
25974
- props.emissionsRate,
25975
- props.emissionsMint,
25976
- props.emissionsRemaining,
25977
- props.oracleKey,
25978
- props.emode,
25979
- props.feesDestinationAccount,
25980
- props.lendingPositionCount,
25981
- props.borrowingPositionCount,
25982
- props.pythShardId,
25983
- extendedMetadata?.symbol,
25984
- extendedMetadata,
25985
- owner
25628
+ lendrAccount.setHealthCache(
25629
+ new HealthCache(
25630
+ assetValueInitial,
25631
+ liabilityValueInitial,
25632
+ assetValueMaint,
25633
+ liabilityValueMaint,
25634
+ assetValueEquity,
25635
+ liabilityValueEquity,
25636
+ new BigNumber14(0),
25637
+ [],
25638
+ [],
25639
+ true
25640
+ )
25986
25641
  );
25642
+ if (e instanceof HealthCacheSimulationError) {
25643
+ return { lendrAccount, error: e };
25644
+ }
25987
25645
  }
25988
- static withEmodeWeights(bank, emodeWeights) {
25989
- const newBank = Object.create(_Bank.prototype);
25990
- Object.assign(newBank, bank);
25991
- newBank.config = Object.assign({}, bank.config);
25992
- newBank.config.assetWeightInit = BigNumber13.max(bank.config.assetWeightInit, emodeWeights.assetWeightInit);
25993
- newBank.config.assetWeightMaint = BigNumber13.max(bank.config.assetWeightMaint, emodeWeights.assetWeightMaint);
25994
- return newBank;
25995
- }
25996
- static getPrice(oraclePrice, priceBias = 1 /* None */, weightedPrice = false) {
25997
- return getPrice(oraclePrice, priceBias, weightedPrice);
25998
- }
25999
- static computeQuantityFromUsdValue(oraclePrice, usdValue, priceBias, weightedPrice) {
26000
- const price = getPrice(oraclePrice, priceBias, weightedPrice);
26001
- return usdValue.div(price);
26002
- }
26003
- getTotalAssetQuantity() {
26004
- return getTotalAssetQuantity(this);
26005
- }
26006
- getTotalLiabilityQuantity() {
26007
- return getTotalLiabilityQuantity(this);
26008
- }
26009
- getAssetQuantity(assetShares) {
26010
- return getAssetQuantity(this, assetShares);
26011
- }
26012
- getLiabilityQuantity(liabilityShares) {
26013
- return getLiabilityQuantity(this, liabilityShares);
26014
- }
26015
- getAssetShares(assetQuantity) {
26016
- return getAssetShares(this, assetQuantity);
26017
- }
26018
- getLiabilityShares(liabilityQuantity) {
26019
- return getLiabilityShares(this, liabilityQuantity);
26020
- }
26021
- computeAssetUsdValue(oraclePrice, assetShares, lendrRequirementType, priceBias) {
26022
- return computeAssetUsdValue(this, oraclePrice, assetShares, lendrRequirementType, priceBias);
25646
+ return { lendrAccount };
25647
+ }
25648
+ async function simulateAccountHealthCache(props) {
25649
+ const { program, bankMap, oraclePrices, lendrAccountPk, balances, bankMetadataMap } = props;
25650
+ const activeBalances = balances.filter((b) => b.active);
25651
+ const { staleSwbOracles } = getActiveStaleBanks(activeBalances, bankMap, [], oraclePrices, 30);
25652
+ const computeIx = ComputeBudgetProgram4.setComputeUnitLimit({ units: 14e5 });
25653
+ const blockhash = (await program.provider.connection.getLatestBlockhash("confirmed")).blockhash;
25654
+ const fundAccountIx = SystemProgram3.transfer({
25655
+ fromPubkey: new PublicKey22("DD3AeAssFvjqTvRTrRAtpfjkBF8FpVKnFuwnMLN9haXD"),
25656
+ // lendr SOL VAULT
25657
+ toPubkey: program.provider.publicKey,
25658
+ lamports: 1e8
25659
+ // 0.1 SOL
25660
+ });
25661
+ const crankPythIxs = {
25662
+ postInstructions: [],
25663
+ closeInstructions: [],
25664
+ keys: [],
25665
+ lut: null
25666
+ };
25667
+ const crankSwbIxs = staleSwbOracles.length > 0 ? await createUpdateFeedIx({
25668
+ swbPullOracles: staleSwbOracles.map((oracle) => oracle.oracleKey),
25669
+ provider: program.provider
25670
+ }) : { instructions: [], luts: [] };
25671
+ const healthPulseIxs = await makePulseHealthIx2(
25672
+ program,
25673
+ lendrAccountPk,
25674
+ bankMap,
25675
+ balances,
25676
+ activeBalances.map((b) => b.bankPk),
25677
+ [],
25678
+ bankMetadataMap
25679
+ );
25680
+ const pythLut = crankPythIxs.lut ? [crankPythIxs.lut] : [];
25681
+ const txs = [];
25682
+ if (crankPythIxs.postInstructions.length > 0) {
25683
+ txs.push(
25684
+ ...splitInstructionsToFitTransactions(
25685
+ [computeIx],
25686
+ [
25687
+ fundAccountIx,
25688
+ ...crankPythIxs.postInstructions.map((ix) => ix.instruction),
25689
+ ...crankPythIxs.closeInstructions.map((ix) => ix.instruction)
25690
+ ],
25691
+ {
25692
+ blockhash,
25693
+ payerKey: program.provider.publicKey,
25694
+ luts: [...crankSwbIxs.luts, ...pythLut]
25695
+ }
25696
+ )
25697
+ );
26023
25698
  }
26024
- computeLiabilityUsdValue(oraclePrice, liabilityShares, lendrRequirementType, priceBias) {
26025
- return computeLiabilityUsdValue(this, oraclePrice, liabilityShares, lendrRequirementType, priceBias);
25699
+ const messageV0 = new TransactionMessage4({
25700
+ payerKey: program.provider.publicKey,
25701
+ recentBlockhash: blockhash,
25702
+ instructions: [...crankSwbIxs.instructions]
25703
+ }).compileToV0Message([...crankSwbIxs.luts]);
25704
+ const swbTx = new VersionedTransaction4(messageV0);
25705
+ txs.push(swbTx);
25706
+ const healthTx = new TransactionMessage4({
25707
+ payerKey: program.provider.publicKey,
25708
+ recentBlockhash: blockhash,
25709
+ instructions: [...healthPulseIxs.instructions]
25710
+ }).compileToV0Message([]);
25711
+ const healthTxV0 = new VersionedTransaction4(healthTx);
25712
+ txs.push(healthTxV0);
25713
+ if (txs.length > 5) {
25714
+ console.error("Too many transactions", txs.length);
25715
+ throw new Error("Too many transactions");
26026
25716
  }
26027
- computeUsdValue(oraclePrice, quantity, priceBias, weightedPrice, weight, scaleToBase = true) {
26028
- return computeUsdValue(this, oraclePrice, quantity, priceBias, weightedPrice, weight, scaleToBase);
25717
+ const simulationResult = await simulateBundle(program.provider.connection.rpcEndpoint, txs, [lendrAccountPk]);
25718
+ const postExecutionAccount = simulationResult.find((result) => result.postExecutionAccounts.length > 0);
25719
+ if (!postExecutionAccount) {
25720
+ throw new Error("Account not found");
26029
25721
  }
26030
- getAssetWeight(lendrRequirementType, oraclePrice, ignoreSoftLimits = false, assetWeightInitOverride) {
26031
- return getAssetWeight(this, lendrRequirementType, oraclePrice, {
26032
- ignoreSoftLimits,
26033
- assetWeightInitOverride
25722
+ const lendrAccountPost = LendrAccount.decodeAccountRaw(
25723
+ Buffer.from(postExecutionAccount.postExecutionAccounts[0].data[0], "base64"),
25724
+ program.idl
25725
+ );
25726
+ if (lendrAccountPost.healthCache.lndrErr || lendrAccountPost.healthCache.internalErr) {
25727
+ console.log(
25728
+ "cranked swb oracles",
25729
+ staleSwbOracles.map((oracle) => oracle.oracleKey)
25730
+ );
25731
+ console.log("LendrAccountPost healthCache internalErr", lendrAccountPost.healthCache.internalErr);
25732
+ console.log("LendrAccountPost healthCache lndrErr", lendrAccountPost.healthCache.lndrErr);
25733
+ if (lendrAccountPost.healthCache.lndrErr === 6009) {
25734
+ const assetValue = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.assetValue).isZero();
25735
+ const liabilityValue = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.liabilityValue).isZero();
25736
+ const assetValueEquity = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.assetValueEquity).isZero();
25737
+ const liabilityValueEquity = !wrappedI80F48toBigNumber(
25738
+ lendrAccountPost.healthCache.liabilityValueEquity
25739
+ ).isZero();
25740
+ const assetValueMaint = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.assetValueMaint).isZero();
25741
+ const liabilityValueMaint = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.liabilityValueMaint).isZero();
25742
+ if (assetValue && liabilityValue && assetValueEquity && liabilityValueEquity && assetValueMaint && liabilityValueMaint) {
25743
+ return lendrAccountPost;
25744
+ }
25745
+ }
25746
+ console.error("Account health cache simulation failed", {
25747
+ lndrErr: lendrAccountPost.healthCache.lndrErr,
25748
+ internalErr: lendrAccountPost.healthCache.internalErr
26034
25749
  });
25750
+ throw new HealthCacheSimulationError(
25751
+ "Account health cache simulation failed",
25752
+ lendrAccountPost.healthCache.lndrErr,
25753
+ lendrAccountPost.healthCache.internalErr
25754
+ );
26035
25755
  }
26036
- getLiabilityWeight(lendrRequirementType) {
26037
- return getLiabilityWeight(this.config, lendrRequirementType);
26038
- }
26039
- computeTvl(oraclePrice) {
26040
- return computeTvl(this, oraclePrice);
26041
- }
26042
- computeInterestRates() {
26043
- return computeInterestRates(this);
26044
- }
26045
- computeBaseInterestRate() {
26046
- return computeBaseInterestRate(this);
26047
- }
26048
- computeUtilizationRate() {
26049
- return computeUtilizationRate(this);
26050
- }
26051
- computeRemainingCapacity() {
26052
- return computeRemainingCapacity(this);
25756
+ return lendrAccountPost;
25757
+ }
25758
+ async function makePulseHealthIx2(program, lendrAccountPk, banks, balances, mandatoryBanks, excludedBanks, bankMetadataMap) {
25759
+ const healthAccounts = computeHealthCheckAccounts(balances, banks, mandatoryBanks, excludedBanks);
25760
+ const accountMetas = computeHealthAccountMetas(healthAccounts, bankMetadataMap);
25761
+ const ix = await instructions_default.makePulseHealthIx(
25762
+ program,
25763
+ {
25764
+ lendrAccount: lendrAccountPk
25765
+ },
25766
+ accountMetas.map((account) => ({ pubkey: account, isSigner: false, isWritable: false }))
25767
+ );
25768
+ return { instructions: [ix], keys: [] };
25769
+ }
25770
+ async function createUpdateFeedIx(_props) {
25771
+ throw new Error("in terms of switchboard, we have no switchboard");
25772
+ }
25773
+ async function createLendrAccountTx(props) {
25774
+ const authority = props.lendrAccount?.authority ?? props.lendrClient.provider.publicKey;
25775
+ const lendrAccountKeypair = Keypair2.generate();
25776
+ const dummyWrappedI80F48 = bigNumberToWrappedI80F48(new BigNumber14(0));
25777
+ const dummyBalances = Array(15).fill({
25778
+ active: false,
25779
+ bankPk: new PublicKey22("11111111111111111111111111111111"),
25780
+ assetShares: dummyWrappedI80F48,
25781
+ liabilityShares: dummyWrappedI80F48,
25782
+ emissionsOutstanding: dummyWrappedI80F48,
25783
+ lastUpdate: new BN11(0)
25784
+ });
25785
+ const rawAccount = {
25786
+ group: props.lendrClient.group.address,
25787
+ authority,
25788
+ lendingAccount: { balances: dummyBalances },
25789
+ healthCache: {
25790
+ assetValue: {
25791
+ value: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
25792
+ },
25793
+ liabilityValue: {
25794
+ value: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
25795
+ },
25796
+ timestamp: new BN11(0),
25797
+ flags: 0,
25798
+ prices: [],
25799
+ assetValueMaint: bigNumberToWrappedI80F48(new BigNumber14(0)),
25800
+ liabilityValueMaint: bigNumberToWrappedI80F48(new BigNumber14(0)),
25801
+ assetValueEquity: bigNumberToWrappedI80F48(new BigNumber14(0)),
25802
+ liabilityValueEquity: bigNumberToWrappedI80F48(new BigNumber14(0)),
25803
+ errIndex: 0,
25804
+ internalErr: 0,
25805
+ internalBankruptcyErr: 0,
25806
+ internalLiqErr: 0,
25807
+ lndrErr: 0
25808
+ },
25809
+ emissionsDestinationAccount: new PublicKey22("11111111111111111111111111111111"),
25810
+ accountFlags: new BN11([0, 0, 0])
25811
+ };
25812
+ const account = LendrAccount.fromAccountParsed(lendrAccountKeypair.publicKey, rawAccount);
25813
+ const wrappedAccount = new LendrAccountWrapper(lendrAccountKeypair.publicKey, props.lendrClient, account);
25814
+ return {
25815
+ account: wrappedAccount,
25816
+ tx: await props.lendrClient.createLendrAccountTx({ accountKeypair: lendrAccountKeypair })
25817
+ };
25818
+ }
25819
+ function getActiveStaleBanks(balances, banks, additionalBanks, oraclePrices, maxAgeOffset = 0) {
25820
+ const activeBanks = balances.filter((balance) => balance.active).map((balance) => banks.get(balance.bankPk.toBase58())).filter((bank) => !!bank);
25821
+ const allBanks = [...activeBanks, ...additionalBanks];
25822
+ const staleBanks = allBanks.filter((bank) => {
25823
+ if (bank.config.oracleSetup === "SwitchboardPull" /* SwitchboardPull */ || bank.config.oracleSetup === "SwitchboardV2" /* SwitchboardV2 */ || bank.config.oracleSetup === "KaminoSwitchboardPull" /* KaminoSwitchboardPull */) {
25824
+ return true;
25825
+ }
25826
+ const oraclePrice = oraclePrices.get(bank.address.toBase58());
25827
+ const maxAge = bank.config.oracleMaxAge;
25828
+ const currentTime = Math.round(Date.now() / 1e3);
25829
+ const oracleTime = Math.round(oraclePrice?.timestamp ? oraclePrice.timestamp.toNumber() : Date.now());
25830
+ const adjustedMaxAge = Math.max(maxAge - maxAgeOffset, 0);
25831
+ const isStale = currentTime - oracleTime > adjustedMaxAge;
25832
+ return isStale;
25833
+ });
25834
+ if (staleBanks.length > 0) {
25835
+ const stalePythFeeds = [];
25836
+ const staleSwbOracles = [];
25837
+ const seenSwbOracles = /* @__PURE__ */ new Set();
25838
+ const seenPythFeeds = /* @__PURE__ */ new Set();
25839
+ staleBanks.forEach((bank) => {
25840
+ if (bank.config.oracleSetup === "SwitchboardPull" /* SwitchboardPull */ || bank.config.oracleSetup === "KaminoSwitchboardPull" /* KaminoSwitchboardPull */) {
25841
+ const key = bank.oracleKey.toBase58();
25842
+ if (!seenSwbOracles.has(key)) {
25843
+ seenSwbOracles.add(key);
25844
+ staleSwbOracles.push({ oracleKey: bank.oracleKey });
25845
+ }
25846
+ } else if (bank.config.oracleSetup === "PythPushOracle" /* PythPushOracle */ || bank.config.oracleSetup === "StakedWithPythPush" /* StakedWithPythPush */ || bank.config.oracleSetup === "KaminoPythPush" /* KaminoPythPush */) {
25847
+ const oraclePrice = oraclePrices.get(bank.address.toBase58());
25848
+ const shardId = oraclePrice?.pythShardId ?? 0;
25849
+ const feedId = bank.config.oracleKeys[0];
25850
+ const feedKey = feedIdToString(feedId);
25851
+ if (!seenPythFeeds.has(feedKey)) {
25852
+ seenPythFeeds.add(feedKey);
25853
+ stalePythFeeds.push({ feedId: feedKey, shardId });
25854
+ }
25855
+ }
25856
+ });
25857
+ return { stalePythFeeds, staleSwbOracles };
26053
25858
  }
26054
- describe(oraclePrice) {
26055
- return `
26056
- Bank address: ${this.address.toBase58()}
26057
- Mint: ${this.mint.toBase58()}, decimals: ${this.mintDecimals}
26058
-
26059
- Total deposits: ${nativeToUi(this.getTotalAssetQuantity(), this.mintDecimals)}
26060
- Total borrows: ${nativeToUi(this.getTotalLiabilityQuantity(), this.mintDecimals)}
25859
+ return { stalePythFeeds: [], staleSwbOracles: [] };
25860
+ }
26061
25861
 
26062
- Total assets (USD value): ${this.computeAssetUsdValue(
26063
- oraclePrice,
26064
- this.totalAssetShares,
26065
- 2 /* Equity */,
26066
- 1 /* None */
26067
- )}
26068
- Total liabilities (USD value): ${this.computeLiabilityUsdValue(
26069
- oraclePrice,
26070
- this.totalLiabilityShares,
26071
- 2 /* Equity */,
26072
- 1 /* None */
26073
- )}
25862
+ // src/services/group/group.service.ts
25863
+ init_constants();
25864
+ import { TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID4 } from "@solana/spl-token";
25865
+ import { PublicKey as PublicKey23, StakeProgram as StakeProgram2, SYSVAR_RENT_PUBKEY as SYSVAR_RENT_PUBKEY2, SystemProgram as SystemProgram4, TransactionInstruction as TransactionInstruction2 } from "@solana/web3.js";
25866
+ import BN12 from "bn.js";
25867
+ init_single_spl_pool();
25868
+ async function makePoolConfigureBankIx2(program, bank, args) {
25869
+ const ix = await instructions_default.makePoolConfigureBankIx(
25870
+ program,
25871
+ {
25872
+ bank
25873
+ },
25874
+ { bankConfigOpt: args }
25875
+ );
25876
+ return {
25877
+ instructions: [ix],
25878
+ keys: []
25879
+ };
25880
+ }
25881
+ async function makeAddPermissionlessStakedBankIx(program, group, voteAccountAddress, feePayer, pythOracle) {
25882
+ const [settingsKey] = PublicKey23.findProgramAddressSync(
25883
+ [Buffer.from("staked_settings", "utf-8"), group.toBuffer()],
25884
+ program.programId
25885
+ );
25886
+ const poolAddress = findPoolAddress(voteAccountAddress);
25887
+ const solPool = findPoolStakeAddress(poolAddress);
25888
+ const lstMint = findPoolMintAddress(poolAddress);
25889
+ const onRampAddress = findPoolOnRampAddress(poolAddress);
25890
+ const keys = [
25891
+ { pubkey: poolAddress, isSigner: false, isWritable: false },
25892
+ { pubkey: onRampAddress, isSigner: false, isWritable: true },
25893
+ { pubkey: solPool, isSigner: false, isWritable: false },
25894
+ { pubkey: SYSVAR_RENT_PUBKEY2, isSigner: false, isWritable: false },
25895
+ { pubkey: SystemProgram4.programId, isSigner: false, isWritable: false },
25896
+ { pubkey: StakeProgram2.programId, isSigner: false, isWritable: false }
25897
+ ];
25898
+ const data = Buffer.from(Uint8Array.of(6));
25899
+ const _onrampIx = new TransactionInstruction2({
25900
+ keys,
25901
+ programId: SINGLE_POOL_PROGRAM_ID,
25902
+ data
25903
+ });
25904
+ const remainingKeys = [pythOracle, lstMint, solPool];
25905
+ const ix = await instructions_default.makePoolAddPermissionlessStakedBankIx(
25906
+ program,
25907
+ {
25908
+ stakedSettings: settingsKey,
25909
+ feePayer,
25910
+ bankMint: lstMint,
25911
+ solPool,
25912
+ stakePool: poolAddress
25913
+ },
25914
+ remainingKeys.map((key) => ({ pubkey: key, isSigner: false, isWritable: false })),
25915
+ {
25916
+ seed: new BN12(0)
25917
+ }
25918
+ );
25919
+ return {
25920
+ instructions: [ix],
25921
+ keys: []
25922
+ };
25923
+ }
25924
+ async function makePoolAddBankIx2(program, group, bank, feePayer, bankMint, bankConfig, tokenProgram = TOKEN_PROGRAM_ID4, overrideOpt = {}) {
25925
+ const rawBankConfig = serializeBankConfigOpt(bankConfig);
25926
+ const rawBankConfigCompact = {
25927
+ ...rawBankConfig,
25928
+ oracleMaxAge: bankConfig.oracleMaxAge,
25929
+ auto_padding_0: [0],
25930
+ auto_padding_1: [0]
25931
+ };
25932
+ const ix = await instructions_default.makePoolAddBankIx(
25933
+ program,
25934
+ {
25935
+ lendrGroup: group,
25936
+ feePayer,
25937
+ bankMint,
25938
+ bank,
25939
+ tokenProgram,
25940
+ ...overrideOpt
25941
+ // if two oracle keys: first is feed id, second is oracle key
25942
+ },
25943
+ {
25944
+ bankConfig: rawBankConfigCompact
25945
+ }
25946
+ );
25947
+ return {
25948
+ instructions: [ix],
25949
+ //ix
25950
+ keys: []
25951
+ };
25952
+ }
26074
25953
 
26075
- Asset price (USD): ${_Bank.getPrice(oraclePrice, 1 /* None */, false)}
26076
- Asset price Weighted (USD): ${_Bank.getPrice(oraclePrice, 1 /* None */, true)}
25954
+ // src/services/group/utils/deserialize.utils.ts
25955
+ import { PublicKey as PublicKey24 } from "@solana/web3.js";
25956
+ function dtoToGroup(groupDto) {
25957
+ return {
25958
+ admin: new PublicKey24(groupDto.admin),
25959
+ address: new PublicKey24(groupDto.address)
25960
+ };
25961
+ }
26077
25962
 
26078
- Config:
26079
- - Asset weight init: ${this.config.assetWeightInit.toFixed(2)}
26080
- - Asset weight maint: ${this.config.assetWeightMaint.toFixed(2)}
26081
- - Liability weight init: ${this.config.liabilityWeightInit.toFixed(2)}
26082
- - Liability weight maint: ${this.config.liabilityWeightMaint.toFixed(2)}
25963
+ // src/services/group/utils/serialize.utils.ts
25964
+ function groupToDto(group) {
25965
+ return {
25966
+ admin: group.admin.toBase58(),
25967
+ address: group.address.toBase58()
25968
+ };
25969
+ }
26083
25970
 
26084
- - Deposit limit: ${this.config.depositLimit}
26085
- - Borrow limit: ${this.config.borrowLimit}
25971
+ // src/services/native-stake/utils/deserialize.utils.ts
25972
+ import { PublicKey as PublicKey25 } from "@solana/web3.js";
25973
+ function dtoToValidatorStakeGroup(validatorStakeGroupDto) {
25974
+ return {
25975
+ validator: new PublicKey25(validatorStakeGroupDto.validator),
25976
+ poolKey: new PublicKey25(validatorStakeGroupDto.poolKey),
25977
+ poolMintKey: new PublicKey25(validatorStakeGroupDto.poolMintKey),
25978
+ totalStake: validatorStakeGroupDto.totalStake,
25979
+ selectedAccount: {
25980
+ pubkey: new PublicKey25(validatorStakeGroupDto.selectedAccount.pubkey),
25981
+ amount: validatorStakeGroupDto.selectedAccount.amount
25982
+ },
25983
+ accounts: validatorStakeGroupDto.accounts.map((account) => ({
25984
+ pubkey: new PublicKey25(account.pubkey),
25985
+ amount: account.amount
25986
+ }))
25987
+ };
25988
+ }
26086
25989
 
26087
- LTVs:
26088
- - Initial: ${new BigNumber13(1).div(this.config.liabilityWeightInit).times(100).toFixed(2)}%
26089
- - Maintenance: ${new BigNumber13(1).div(this.config.liabilityWeightMaint).times(100).toFixed(2)}%
26090
- `;
26091
- }
26092
- };
26093
- var BankConfig = class _BankConfig {
26094
- constructor(assetWeightInit, assetWeightMaint, liabilityWeightInit, liabilityWeightMaint, depositLimit, borrowLimit, riskTier, totalAssetValueInitLimit, assetTag, oracleSetup, oracleKeys, oracleMaxAge, interestRateConfig, operationalState, oracleMaxConfidence, fixedPrice, configFlags) {
26095
- this.assetWeightInit = assetWeightInit;
26096
- this.assetWeightMaint = assetWeightMaint;
26097
- this.liabilityWeightInit = liabilityWeightInit;
26098
- this.liabilityWeightMaint = liabilityWeightMaint;
26099
- this.depositLimit = depositLimit;
26100
- this.borrowLimit = borrowLimit;
26101
- this.riskTier = riskTier;
26102
- this.totalAssetValueInitLimit = totalAssetValueInitLimit;
26103
- this.assetTag = assetTag;
26104
- this.oracleSetup = oracleSetup;
26105
- this.oracleKeys = oracleKeys;
26106
- this.oracleMaxAge = oracleMaxAge;
26107
- this.interestRateConfig = interestRateConfig;
26108
- this.operationalState = operationalState;
26109
- this.oracleMaxConfidence = oracleMaxConfidence;
26110
- this.fixedPrice = fixedPrice;
26111
- this.configFlags = configFlags;
25990
+ // src/services/native-stake/utils/fetch.utils.ts
25991
+ init_constants();
25992
+ init_single_spl_pool();
25993
+ import { LAMPORTS_PER_SOL as LAMPORTS_PER_SOL4, PublicKey as PublicKey26, StakeProgram as StakeProgram3 } from "@solana/web3.js";
25994
+ var fetchNativeStakeAccounts = async (connection, publicKey3, opts = {
25995
+ filterInactive: true
25996
+ }) => {
25997
+ if (!connection || !publicKey3) {
25998
+ throw new Error("Invalid connection or public key");
26112
25999
  }
26113
- static fromAccountParsed(bankConfigRaw) {
26114
- const bankConfig = parseBankConfigRaw(bankConfigRaw);
26115
- return new _BankConfig(
26116
- bankConfig.assetWeightInit,
26117
- bankConfig.assetWeightMaint,
26118
- bankConfig.liabilityWeightInit,
26119
- bankConfig.liabilityWeightMaint,
26120
- bankConfig.depositLimit,
26121
- bankConfig.borrowLimit,
26122
- bankConfig.riskTier,
26123
- bankConfig.totalAssetValueInitLimit,
26124
- bankConfig.assetTag,
26125
- bankConfig.oracleSetup,
26126
- bankConfig.oracleKeys,
26127
- bankConfig.oracleMaxAge,
26128
- bankConfig.interestRateConfig,
26129
- bankConfig.operationalState,
26130
- bankConfig.oracleMaxConfidence,
26131
- bankConfig.fixedPrice,
26132
- bankConfig.configFlags
26000
+ try {
26001
+ const epochInfo = await connection.getEpochInfo();
26002
+ const accounts = await connection.getParsedProgramAccounts(StakeProgram3.programId, {
26003
+ filters: [
26004
+ {
26005
+ memcmp: {
26006
+ offset: 12,
26007
+ bytes: publicKey3.toBase58()
26008
+ }
26009
+ }
26010
+ ]
26011
+ });
26012
+ const validatorMap = /* @__PURE__ */ new Map();
26013
+ await Promise.all(
26014
+ accounts.map(async (acc) => {
26015
+ const parsedAccount = acc.account.data;
26016
+ const stakeInfo = parsedAccount.parsed.info;
26017
+ if (!stakeInfo.stake?.delegation || opts.filterInactive && (Number(stakeInfo.stake.delegation.activationEpoch) >= epochInfo.epoch || stakeInfo.stake.delegation.deactivationEpoch !== MAX_U64)) {
26018
+ return;
26019
+ }
26020
+ const validatorAddress = stakeInfo.stake.delegation.voter;
26021
+ const accountPubkey = acc.pubkey;
26022
+ const amount = Number(stakeInfo.stake.delegation.stake) / LAMPORTS_PER_SOL4;
26023
+ const existingAccounts = validatorMap.get(validatorAddress) || [];
26024
+ validatorMap.set(validatorAddress, [...existingAccounts, { pubkey: accountPubkey, amount }]);
26025
+ })
26026
+ );
26027
+ return Promise.all(
26028
+ Array.from(validatorMap.entries()).map(async ([validatorAddress, accounts2]) => {
26029
+ const poolKey = findPoolAddress(new PublicKey26(validatorAddress));
26030
+ const poolMintKey = findPoolMintAddress(poolKey);
26031
+ const totalStake = accounts2.reduce((acc, curr) => acc + curr.amount, 0);
26032
+ const largestAccount = accounts2.reduce((acc, curr) => acc.amount > curr.amount ? acc : curr);
26033
+ const sortedAccounts = accounts2.sort((a, b) => b.amount - a.amount);
26034
+ if (!sortedAccounts[0].pubkey.equals(largestAccount.pubkey)) {
26035
+ sortedAccounts.unshift(sortedAccounts.splice(sortedAccounts.indexOf(largestAccount), 1)[0]);
26036
+ }
26037
+ return {
26038
+ validator: new PublicKey26(validatorAddress),
26039
+ poolKey,
26040
+ poolMintKey,
26041
+ accounts: sortedAccounts,
26042
+ totalStake,
26043
+ selectedAccount: largestAccount
26044
+ };
26045
+ })
26133
26046
  );
26047
+ } catch (e) {
26048
+ console.error("Error getting stake accounts", e);
26049
+ return [];
26134
26050
  }
26135
26051
  };
26052
+ var fetchStakePoolActiveStates = async (connection, validatorVoteAccounts) => {
26053
+ const currentEpoch = await connection.getEpochInfo();
26054
+ const activeStates = /* @__PURE__ */ new Map();
26055
+ const poolMintAddressRecord = {};
26056
+ const poolStakeAddressRecord = {};
26057
+ validatorVoteAccounts.forEach((validatorVoteAccount) => {
26058
+ const poolAddress = findPoolAddress(validatorVoteAccount);
26059
+ const poolStakeAddress = findPoolStakeAddress(poolAddress);
26060
+ const poolMintAddress = findPoolMintAddress(poolAddress);
26061
+ poolMintAddressRecord[validatorVoteAccount.toBase58()] = poolMintAddress;
26062
+ poolStakeAddressRecord[poolStakeAddress.toBase58()] = validatorVoteAccount;
26063
+ });
26064
+ const poolStakeAddressKeys = Object.keys(poolStakeAddressRecord);
26065
+ const poolStakeAccounts = Object.fromEntries(
26066
+ (await chunkedGetRawMultipleAccountInfoOrdered(connection, poolStakeAddressKeys)).map((ai, index) => [
26067
+ poolStakeAddressRecord[poolStakeAddressKeys[index]],
26068
+ ai?.data || null
26069
+ ])
26070
+ );
26071
+ validatorVoteAccounts.forEach((validatorVoteAccount) => {
26072
+ const stakeAccount = fetchStakeAccount(poolStakeAccounts[validatorVoteAccount.toBase58()]);
26073
+ const poolMintAddress = poolMintAddressRecord[validatorVoteAccount.toBase58()];
26074
+ if (!stakeAccount) {
26075
+ activeStates.set(poolMintAddress.toBase58(), false);
26076
+ return;
26077
+ }
26078
+ if (!stakeAccount.stake?.delegation) {
26079
+ activeStates.set(poolMintAddress.toBase58(), false);
26080
+ return;
26081
+ }
26082
+ const activationEpoch = stakeAccount.stake.delegation.activationEpoch;
26083
+ const isActive = currentEpoch.epoch > Number(activationEpoch);
26084
+ activeStates.set(validatorVoteAccount.toBase58(), isActive);
26085
+ });
26086
+ return activeStates;
26087
+ };
26088
+ var fetchStakeAccount = (data) => {
26089
+ let offset = 0;
26090
+ const discriminant = data.readUInt32LE(offset);
26091
+ offset += 4;
26092
+ const rentExemptReserve = data.readBigUInt64LE(offset);
26093
+ offset += 8;
26094
+ const staker = new PublicKey26(data.subarray(offset, offset + 32));
26095
+ offset += 32;
26096
+ const withdrawer = new PublicKey26(data.subarray(offset, offset + 32));
26097
+ offset += 32;
26098
+ const unixTimestamp = data.readBigUInt64LE(offset);
26099
+ offset += 8;
26100
+ const epoch = data.readBigUInt64LE(offset);
26101
+ offset += 8;
26102
+ const custodian = new PublicKey26(data.subarray(offset, offset + 32));
26103
+ offset += 32;
26104
+ const voterPubkey = new PublicKey26(data.subarray(offset, offset + 32));
26105
+ offset += 32;
26106
+ const stake = data.readBigUInt64LE(offset);
26107
+ offset += 8;
26108
+ const activationEpoch = data.readBigUInt64LE(offset);
26109
+ offset += 8;
26110
+ const deactivationEpoch = data.readBigUInt64LE(offset);
26111
+ offset += 8;
26112
+ const creditsObserved = data.readBigUInt64LE(offset);
26113
+ return {
26114
+ discriminant,
26115
+ meta: {
26116
+ rentExemptReserve,
26117
+ authorized: {
26118
+ staker,
26119
+ withdrawer
26120
+ },
26121
+ lockup: {
26122
+ unixTimestamp,
26123
+ epoch,
26124
+ custodian
26125
+ }
26126
+ },
26127
+ stake: {
26128
+ delegation: {
26129
+ voterPubkey,
26130
+ stake,
26131
+ activationEpoch,
26132
+ deactivationEpoch
26133
+ },
26134
+ creditsObserved
26135
+ }
26136
+ };
26137
+ };
26138
+ var fetchStakePoolMev = async (connection, validatorVoteAccounts) => {
26139
+ const poolAddressRecord = {};
26140
+ const poolStakeAddressRecord = {};
26141
+ const onRampAddressRecord = {};
26142
+ const mev = /* @__PURE__ */ new Map();
26143
+ validatorVoteAccounts.forEach((validatorVoteAccount) => {
26144
+ const poolAddress = findPoolAddress(validatorVoteAccount);
26145
+ const poolStakeAddress = findPoolStakeAddress(poolAddress);
26146
+ const onRampAddress = findPoolOnRampAddress(poolAddress);
26147
+ poolAddressRecord[validatorVoteAccount.toBase58()] = poolAddress;
26148
+ poolStakeAddressRecord[validatorVoteAccount.toBase58()] = poolStakeAddress;
26149
+ onRampAddressRecord[validatorVoteAccount.toBase58()] = onRampAddress;
26150
+ });
26151
+ const poolStakeAddresses = validatorVoteAccounts.map(
26152
+ (validatorVoteAccount) => poolStakeAddressRecord[validatorVoteAccount.toBase58()]
26153
+ );
26154
+ const onRampAddresses = validatorVoteAccounts.map(
26155
+ (validatorVoteAccount) => onRampAddressRecord[validatorVoteAccount.toBase58()]
26156
+ );
26157
+ const allAddresses = [...poolStakeAddresses, ...onRampAddresses].map((address) => address.toBase58());
26158
+ return chunkedGetRawMultipleAccountInfoOrdered(connection, allAddresses).then((accountInfos) => {
26159
+ const poolStakeInfos = accountInfos.slice(0, poolStakeAddresses.length);
26160
+ const onRampInfos = accountInfos.slice(poolStakeAddresses.length);
26161
+ const rent = 2282280;
26162
+ validatorVoteAccounts.forEach((validatorVoteAccount, index) => {
26163
+ const poolStakeInfo = poolStakeInfos[index];
26164
+ const onRampInfo = onRampInfos[index];
26165
+ if (poolStakeInfo && onRampInfo) {
26166
+ const stakeDecoded = fetchStakeAccount(poolStakeInfo.data);
26167
+ const onrampDecoded = fetchStakeAccount(onRampInfo.data);
26168
+ const poolLamps = poolStakeInfo.lamports - rent - Number(stakeDecoded.stake.delegation.stake.toString());
26169
+ const onrampStake = Number(onrampDecoded.stake.delegation.stake.toString());
26170
+ mev.set(validatorVoteAccount.toBase58(), {
26171
+ pool: poolLamps >= 1e3 ? poolLamps : 0,
26172
+ onramp: onrampStake
26173
+ });
26174
+ }
26175
+ });
26176
+ return mev;
26177
+ });
26178
+ };
26179
+
26180
+ // src/services/native-stake/utils/serialize.utils.ts
26181
+ function validatorStakeGroupToDto(validatorStakeGroup) {
26182
+ return {
26183
+ validator: validatorStakeGroup.validator.toBase58(),
26184
+ poolKey: validatorStakeGroup.poolKey.toBase58(),
26185
+ poolMintKey: validatorStakeGroup.poolMintKey.toBase58(),
26186
+ totalStake: validatorStakeGroup.totalStake,
26187
+ selectedAccount: {
26188
+ pubkey: validatorStakeGroup.selectedAccount.pubkey.toBase58(),
26189
+ amount: validatorStakeGroup.selectedAccount.amount
26190
+ },
26191
+ accounts: validatorStakeGroup.accounts.map((account) => ({
26192
+ pubkey: account.pubkey.toBase58(),
26193
+ amount: account.amount
26194
+ }))
26195
+ };
26196
+ }
26136
26197
 
26137
26198
  // src/models/account/pure.ts
26138
26199
  var TOKEN_ACCOUNT_RENT_EXEMPT = 2039280;
@@ -26314,7 +26375,7 @@ var LendrAccount = class _LendrAccount {
26314
26375
  const useCache = false;
26315
26376
  const freeCollateral = useCache ? this.computeFreeCollateral().times(_volatilityFactor) : this.computeFreeCollateralLegacy(modifiedBanks, oraclePrices).times(_volatilityFactor);
26316
26377
  logger.debug({ freeCollateral: freeCollateral.toFixed(6) }, "[lendr:computeMaxBorrowForBank] Free collateral");
26317
- const untiedCollateralForBank = BigNumber14.min(
26378
+ const untiedCollateralForBank = BigNumber15.min(
26318
26379
  bank.computeAssetUsdValue(priceInfo, balance.assetShares, 0 /* Initial */, 0 /* Lowest */),
26319
26380
  freeCollateral
26320
26381
  );
@@ -26350,7 +26411,7 @@ var LendrAccount = class _LendrAccount {
26350
26411
  const { liabilities: liabilitiesInit } = this.computeHealthComponents(0 /* Initial */);
26351
26412
  if (bank.config.riskTier === "Isolated" /* Isolated */ || initAssetWeight.isZero() && maintAssetWeight.isZero()) {
26352
26413
  if (freeCollateral.isZero() && !liabilitiesInit.isZero()) {
26353
- return new BigNumber14(0);
26414
+ return new BigNumber15(0);
26354
26415
  } else {
26355
26416
  return entireBalance;
26356
26417
  }
@@ -26359,7 +26420,7 @@ var LendrAccount = class _LendrAccount {
26359
26420
  if (liabilitiesInit.eq(0)) {
26360
26421
  return entireBalance;
26361
26422
  } else if (freeCollateral.isZero()) {
26362
- return new BigNumber14(0);
26423
+ return new BigNumber15(0);
26363
26424
  } else {
26364
26425
  const { liabilities: maintLiabilities, assets: maintAssets } = this.computeHealthComponents(
26365
26426
  1 /* Maintenance */
@@ -26476,7 +26537,7 @@ var LendrAccount = class _LendrAccount {
26476
26537
  );
26477
26538
  const assets = assetsAccount.minus(assetBank);
26478
26539
  const liabilities = liabilitiesAccount.minus(liabilitiesBank);
26479
- const amountBn = new BigNumber14(amount);
26540
+ const amountBn = new BigNumber15(amount);
26480
26541
  let liquidationPrice;
26481
26542
  if (isLending) {
26482
26543
  if (liabilities.eq(0)) return null;
@@ -26519,7 +26580,7 @@ var LendrAccount = class _LendrAccount {
26519
26580
  const priceAssetLower = getPrice(assetPriceInfo, 0 /* Lowest */, false);
26520
26581
  const priceAssetMarket = getPrice(assetPriceInfo, 1 /* None */, false);
26521
26582
  const assetMaintWeight = assetBank.config.assetWeightMaint;
26522
- const liquidationDiscount = new BigNumber14(0.95);
26583
+ const liquidationDiscount = new BigNumber15(0.95);
26523
26584
  const priceLiabHighest = getPrice(liabilityPriceInfo, 2 /* Highest */, false);
26524
26585
  const priceLiabMarket = getPrice(liabilityPriceInfo, 1 /* None */, false);
26525
26586
  const liabMaintWeight = liabilityBank.config.liabilityWeightMaint;
@@ -26556,7 +26617,7 @@ var LendrAccount = class _LendrAccount {
26556
26617
  },
26557
26618
  "[lendr:getMaxLiquidatableAssetAmount]"
26558
26619
  );
26559
- const maxLiquidatableUsdValue = BigNumber14.min(assetsUsdValue, underwaterMaintUsdValue, liabUsdValue);
26620
+ const maxLiquidatableUsdValue = BigNumber15.min(assetsUsdValue, underwaterMaintUsdValue, liabUsdValue);
26560
26621
  logger.debug(
26561
26622
  {
26562
26623
  maxLiquidatableUsdValue: maxLiquidatableUsdValue.toFixed(6)
@@ -26618,7 +26679,7 @@ var LendrAccount = class _LendrAccount {
26618
26679
  }
26619
26680
  const depositIxs = [];
26620
26681
  if (bank.mint.equals(NATIVE_MINT2) && wrapAndUnwrapSol) {
26621
- depositIxs.push(...makeWrapSolIxs(this.authority, new BigNumber14(amount).minus(wSolBalanceUi)));
26682
+ depositIxs.push(...makeWrapSolIxs(this.authority, new BigNumber15(amount).minus(wSolBalanceUi)));
26622
26683
  }
26623
26684
  return {
26624
26685
  depositIxs,
@@ -26683,7 +26744,7 @@ var LendrAccount = class _LendrAccount {
26683
26744
  const depositIx = await instructions_default.makeDepositWithSessionIx(program, accounts, ixArguments, remainingAccounts);
26684
26745
  if (bank.mint.equals(NATIVE_MINT2)) {
26685
26746
  const wSolBalanceUi = opts.wSolBalanceUi ?? 0;
26686
- const wrapAmount = new BigNumber14(amount).minus(wSolBalanceUi);
26747
+ const wrapAmount = new BigNumber15(amount).minus(wSolBalanceUi);
26687
26748
  const wrapIxs = makeSessionWrapSolIxs(session.walletPublicKey, session.sessionPublicKey, wrapAmount, {
26688
26749
  existingBalance: wSolBalanceUi
26689
26750
  });
@@ -26723,7 +26784,7 @@ var LendrAccount = class _LendrAccount {
26723
26784
  remainingAccounts.push(mintData.mint);
26724
26785
  }
26725
26786
  if (bank.mint.equals(NATIVE_MINT2) && wrapAndUnwrapSol) {
26726
- repayIxs.push(...makeWrapSolIxs(this.authority, new BigNumber14(amount).minus(wSolBalanceUi)));
26787
+ repayIxs.push(...makeWrapSolIxs(this.authority, new BigNumber15(amount).minus(wSolBalanceUi)));
26727
26788
  }
26728
26789
  return {
26729
26790
  repayIxs,
@@ -26800,7 +26861,7 @@ var LendrAccount = class _LendrAccount {
26800
26861
  );
26801
26862
  if (bank.mint.equals(NATIVE_MINT2)) {
26802
26863
  const wSolBalanceUi = opts.wSolBalanceUi ?? 0;
26803
- const neededAmount = new BigNumber14(amount).minus(wSolBalanceUi);
26864
+ const neededAmount = new BigNumber15(amount).minus(wSolBalanceUi);
26804
26865
  const wrapIxs = makeSessionWrapSolIxs(session.walletPublicKey, session.sessionPublicKey, neededAmount, {
26805
26866
  existingBalance: wSolBalanceUi,
26806
26867
  wrapAmountUi: opts.wrapAmountUi
@@ -27240,8 +27301,8 @@ var LendrAccount = class _LendrAccount {
27240
27301
  }
27241
27302
  return projectedBalances.filter((b) => b.active).map((b) => b.bankPk);
27242
27303
  }
27243
- wrapInstructionForWSol(ix, amount = new BigNumber14(0)) {
27244
- return [...makeWrapSolIxs(this.authority, new BigNumber14(amount)), ix, makeUnwrapSolIx(this.authority)];
27304
+ wrapInstructionForWSol(ix, amount = new BigNumber15(0)) {
27305
+ return [...makeWrapSolIxs(this.authority, new BigNumber15(amount)), ix, makeUnwrapSolIx(this.authority)];
27245
27306
  }
27246
27307
  describe(banks, oraclePrices) {
27247
27308
  const { assets, liabilities } = this.computeHealthComponents(2 /* Equity */);
@@ -27303,7 +27364,7 @@ import {
27303
27364
  TransactionMessage as TransactionMessage5,
27304
27365
  VersionedTransaction as VersionedTransaction5
27305
27366
  } from "@solana/web3.js";
27306
- import BigNumber15 from "bignumber.js";
27367
+ import BigNumber16 from "bignumber.js";
27307
27368
  init_constants();
27308
27369
  var LendrAccountWrapper = class _LendrAccountWrapper {
27309
27370
  // --------------------------------------------------------------------------
@@ -27316,9 +27377,23 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27316
27377
  this.client = client;
27317
27378
  this.address = lendrAccountPk;
27318
27379
  this._lendrAccount = lendrAccount;
27380
+ this.banks = _LendrAccountWrapper.applyEmode(client.banks, lendrAccount);
27319
27381
  }
27320
27382
  address;
27383
+ banks;
27321
27384
  _lendrAccount;
27385
+ static applyEmode(banks, lendrAccount) {
27386
+ const rawBanks = Array.from(banks.values());
27387
+ const emodePairs = getEmodePairs(rawBanks);
27388
+ const activePairs = lendrAccount.computeActiveEmodePairs(emodePairs);
27389
+ if (activePairs.length === 0) return banks;
27390
+ const { adjustedBanks } = adjustBanksWithEmode(rawBanks, activePairs);
27391
+ const adjusted = /* @__PURE__ */ new Map();
27392
+ for (const bank of adjustedBanks) {
27393
+ adjusted.set(bank.address.toBase58(), bank);
27394
+ }
27395
+ return adjusted;
27396
+ }
27322
27397
  static async fetch(lendrAccountPk, client, commitment) {
27323
27398
  const { config, program } = client;
27324
27399
  const _lendrAccountPk = translateAddress(lendrAccountPk);
@@ -27385,7 +27460,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27385
27460
  async simulateHealthCache() {
27386
27461
  const { lendrAccount: account } = await this._lendrAccount.simulateHealthCache(
27387
27462
  this._program,
27388
- this.client.banks,
27463
+ this.banks,
27389
27464
  this.client.oraclePrices,
27390
27465
  this.client.bankMetadataMap ?? {}
27391
27466
  );
@@ -27395,7 +27470,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27395
27470
  let { assets, liabilities } = this._lendrAccount.computeHealthComponents(1 /* Maintenance */);
27396
27471
  if (assets.isZero() && liabilities.isZero()) {
27397
27472
  const legacy = this._lendrAccount.computeHealthComponentsLegacy(
27398
- this.client.banks,
27473
+ this.banks,
27399
27474
  this.client.oraclePrices,
27400
27475
  1 /* Maintenance */
27401
27476
  );
@@ -27428,7 +27503,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27428
27503
  // TODO)) migrate to computeHealthComponents
27429
27504
  computeHealthComponentsLegacy(lendrRequirement, excludedBanks = []) {
27430
27505
  return this._lendrAccount.computeHealthComponentsLegacy(
27431
- this.client.banks,
27506
+ this.banks,
27432
27507
  this.client.oraclePrices,
27433
27508
  lendrRequirement,
27434
27509
  excludedBanks
@@ -27436,7 +27511,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27436
27511
  }
27437
27512
  computeHealthComponentsWithoutBiasLegacy(lendrRequirement) {
27438
27513
  return this._lendrAccount.computeHealthComponentsWithoutBiasLegacy(
27439
- this.client.banks,
27514
+ this.banks,
27440
27515
  this.client.oraclePrices,
27441
27516
  lendrRequirement
27442
27517
  );
@@ -27445,7 +27520,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27445
27520
  return this._lendrAccount.computeFreeCollateral(opts);
27446
27521
  }
27447
27522
  computeFreeCollateralLegacy(opts) {
27448
- return this._lendrAccount.computeFreeCollateralLegacy(this.client.banks, this.client.oraclePrices, opts);
27523
+ return this._lendrAccount.computeFreeCollateralLegacy(this.banks, this.client.oraclePrices, opts);
27449
27524
  }
27450
27525
  computeAccountValue() {
27451
27526
  return this._lendrAccount.computeAccountValue();
@@ -27456,12 +27531,12 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27456
27531
  computeEmodeImpacts(emodePairs) {
27457
27532
  return this._lendrAccount.computeEmodeImpacts(
27458
27533
  emodePairs,
27459
- Array.from(this.client.banks.keys()).map((b) => new PublicKey28(b))
27534
+ Array.from(this.banks.keys()).map((b) => new PublicKey28(b))
27460
27535
  );
27461
27536
  }
27462
27537
  computeMaxBorrowForBank(bankAddress, opts) {
27463
27538
  return this._lendrAccount.computeMaxBorrowForBank(
27464
- this.client.banks,
27539
+ this.banks,
27465
27540
  this.client.oraclePrices,
27466
27541
  bankAddress,
27467
27542
  opts,
@@ -27469,11 +27544,11 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27469
27544
  );
27470
27545
  }
27471
27546
  computeMaxWithdrawForBank(bankAddress, opts) {
27472
- return this._lendrAccount.computeMaxWithdrawForBank(this.client.banks, this.client.oraclePrices, bankAddress, opts);
27547
+ return this._lendrAccount.computeMaxWithdrawForBank(this.banks, this.client.oraclePrices, bankAddress, opts);
27473
27548
  }
27474
27549
  computeMaxLiquidatableAssetAmount(assetBankAddress, liabilityBankAddress) {
27475
27550
  return this._lendrAccount.computeMaxLiquidatableAssetAmount(
27476
- this.client.banks,
27551
+ this.banks,
27477
27552
  this.client.oraclePrices,
27478
27553
  assetBankAddress,
27479
27554
  liabilityBankAddress,
@@ -27481,11 +27556,11 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27481
27556
  );
27482
27557
  }
27483
27558
  computeLiquidationPriceForBank(bankAddress) {
27484
- return this._lendrAccount.computeLiquidationPriceForBank(this.client.banks, this.client.oraclePrices, bankAddress);
27559
+ return this._lendrAccount.computeLiquidationPriceForBank(this.banks, this.client.oraclePrices, bankAddress);
27485
27560
  }
27486
27561
  computeLiquidationPriceForBankAmount(bankAddress, isLending, amount) {
27487
27562
  return this._lendrAccount.computeLiquidationPriceForBankAmount(
27488
- this.client.banks,
27563
+ this.banks,
27489
27564
  this.client.oraclePrices,
27490
27565
  bankAddress,
27491
27566
  isLending,
@@ -27493,15 +27568,15 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27493
27568
  );
27494
27569
  }
27495
27570
  computeNetApy() {
27496
- return this._lendrAccount.computeNetApy(this.client.banks, this.client.oraclePrices);
27571
+ return this._lendrAccount.computeNetApy(this.banks, this.client.oraclePrices);
27497
27572
  }
27498
27573
  /** Todo move this into client */
27499
27574
  computeLoopingParams(principal, targetLeverage, depositBankAddress, borrowBankAddress) {
27500
- const depositBank = this.client.banks.get(depositBankAddress.toBase58());
27575
+ const depositBank = this.banks.get(depositBankAddress.toBase58());
27501
27576
  if (!depositBank) throw Error(`Bank ${depositBankAddress.toBase58()} not found`);
27502
27577
  const depositPriceInfo = this.client.oraclePrices.get(depositBankAddress.toBase58());
27503
27578
  if (!depositPriceInfo) throw Error(`Price info for ${depositBankAddress.toBase58()} not found`);
27504
- const borrowBank = this.client.banks.get(borrowBankAddress.toBase58());
27579
+ const borrowBank = this.banks.get(borrowBankAddress.toBase58());
27505
27580
  if (!borrowBank) throw Error(`Bank ${borrowBankAddress.toBase58()} not found`);
27506
27581
  const borrowPriceInfo = this.client.oraclePrices.get(borrowBankAddress.toBase58());
27507
27582
  if (!borrowPriceInfo) throw Error(`Price info for ${borrowBankAddress.toBase58()} not found`);
@@ -27798,9 +27873,9 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27798
27873
  },
27799
27874
  "[lendr:lendr-account:loop] Looping into Lendr account"
27800
27875
  );
27801
- const depositBank = this.client.banks.get(props.depositBankAddress.toBase58());
27876
+ const depositBank = this.banks.get(props.depositBankAddress.toBase58());
27802
27877
  if (!depositBank) throw Error("Deposit bank not found");
27803
- const borrowBank = this.client.banks.get(props.borrowBankAddress.toBase58());
27878
+ const borrowBank = this.banks.get(props.borrowBankAddress.toBase58());
27804
27879
  if (!borrowBank) throw Error("Borrow bank not found");
27805
27880
  const { processOpts, txOpts, ...txProps } = props;
27806
27881
  const { transactions } = await this.makeLoopTxV2(txProps);
@@ -27825,9 +27900,9 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27825
27900
  setupBankAddresses,
27826
27901
  overrideInferAccounts
27827
27902
  }) {
27828
- const depositBank = this.client.banks.get(depositBankAddress.toBase58());
27903
+ const depositBank = this.banks.get(depositBankAddress.toBase58());
27829
27904
  if (!depositBank) throw Error("Deposit bank not found");
27830
- const borrowBank = this.client.banks.get(borrowBankAddress.toBase58());
27905
+ const borrowBank = this.banks.get(borrowBankAddress.toBase58());
27831
27906
  if (!borrowBank) throw Error("Borrow bank not found");
27832
27907
  const blockhash = blockhashArg ?? (await this._program.provider.connection.getLatestBlockhash("confirmed")).blockhash;
27833
27908
  const setupIxs = await this.makeSetupIx(setupBankAddresses ?? [borrowBankAddress, depositBankAddress]);
@@ -27851,7 +27926,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27851
27926
  let flashloanTx;
27852
27927
  let txOverflown = false;
27853
27928
  if (depositBank.mint.equals(NATIVE_MINT3) && inputDepositAmount) {
27854
- setupIxs.push(...makeWrapSolIxs(this.authority, new BigNumber15(inputDepositAmount)));
27929
+ setupIxs.push(...makeWrapSolIxs(this.authority, new BigNumber16(inputDepositAmount)));
27855
27930
  }
27856
27931
  if (setupIxs.length > 0) {
27857
27932
  const message = new TransactionMessage5({
@@ -27968,7 +28043,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27968
28043
  async makeDepositIx(amount, bankAddress, depositOpts = {}) {
27969
28044
  return this._lendrAccount.makeDepositIx(
27970
28045
  this._program,
27971
- this.client.banks,
28046
+ this.banks,
27972
28047
  this.client.mintDatas,
27973
28048
  amount,
27974
28049
  bankAddress,
@@ -27978,7 +28053,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27978
28053
  async makeDepositWithSessionIx(amount, bankAddress, session, depositOpts = {}) {
27979
28054
  return this._lendrAccount.makeDepositWithSessionIx(
27980
28055
  this._program,
27981
- this.client.banks,
28056
+ this.banks,
27982
28057
  this.client.mintDatas,
27983
28058
  amount,
27984
28059
  bankAddress,
@@ -28224,7 +28299,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28224
28299
  const ldrAccount = LendrAccount.decode(ldrAccountData, this._program.idl);
28225
28300
  console.log("ldrAccount", ldrAccount);
28226
28301
  if (!bankData) throw new Error("Failed to simulate");
28227
- const previewBanks = new Map(this.client.banks);
28302
+ const previewBanks = new Map(this.banks);
28228
28303
  banksToInspect.forEach((bankAddress, idx) => {
28229
28304
  const data = bankData[idx];
28230
28305
  if (!data) throw new Error("Failed to simulate");
@@ -28239,7 +28314,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28239
28314
  wallet: {},
28240
28315
  isReadOnly: true,
28241
28316
  group: this.client.group,
28242
- banks: this.client.banks,
28317
+ banks: previewBanks,
28243
28318
  priceInfos: this.client.oraclePrices,
28244
28319
  mintDatas: this.client.mintDatas,
28245
28320
  feedIdMap: this.client.feedIdMap,
@@ -28271,7 +28346,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28271
28346
  if (!tokenProgramAddress) throw Error("Repay mint not found");
28272
28347
  return this._lendrAccount.makeRepayIx(
28273
28348
  this._program,
28274
- this.client.banks,
28349
+ this.banks,
28275
28350
  this.client.mintDatas,
28276
28351
  amount,
28277
28352
  bankAddress,
@@ -28295,7 +28370,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28295
28370
  if (!tokenProgramAddress) throw Error("Repay mint not found");
28296
28371
  return this._lendrAccount.makeRepayWithSessionIx(
28297
28372
  this._program,
28298
- this.client.banks,
28373
+ this.banks,
28299
28374
  this.client.mintDatas,
28300
28375
  amount,
28301
28376
  bankAddress,
@@ -28424,7 +28499,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28424
28499
  if (!this.client.bankMetadataMap) throw Error("Bank metadata map not found");
28425
28500
  return this._lendrAccount.makeWithdrawIx(
28426
28501
  this._program,
28427
- this.client.banks,
28502
+ this.banks,
28428
28503
  this.client.mintDatas,
28429
28504
  this.client.bankMetadataMap,
28430
28505
  amount,
@@ -28450,7 +28525,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28450
28525
  if (!this.client.bankMetadataMap) throw Error("Bank metadata map not found");
28451
28526
  return this._lendrAccount.makeWithdrawWithSessionIx(
28452
28527
  this._program,
28453
- this.client.banks,
28528
+ this.banks,
28454
28529
  this.client.mintDatas,
28455
28530
  this.client.bankMetadataMap,
28456
28531
  amount,
@@ -28487,7 +28562,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28487
28562
  const mintAuthority = findPoolMintAuthorityAddress(pool);
28488
28563
  const lstAta = getAssociatedTokenAddressSync3(lstMint, this.authority);
28489
28564
  const rentExemption = await this._program.provider.connection.getMinimumBalanceForRentExemption(200);
28490
- const stakeAmount = new BigNumber15(new BigNumber15(amount).toString());
28565
+ const stakeAmount = new BigNumber16(new BigNumber16(amount).toString());
28491
28566
  const withdrawIxs = await this.makeWithdrawIx(amount, bankAddress, isWholePosition, {
28492
28567
  createAtas: true,
28493
28568
  wrapAndUnwrapSol: true
@@ -28768,7 +28843,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28768
28843
  if (!this.client.bankMetadataMap) throw Error("Bank metadata map not found");
28769
28844
  return this._lendrAccount.makeBorrowIx(
28770
28845
  this._program,
28771
- this.client.banks,
28846
+ this.banks,
28772
28847
  this.client.mintDatas,
28773
28848
  this.client.bankMetadataMap,
28774
28849
  amount,
@@ -28791,7 +28866,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28791
28866
  if (!this.client.bankMetadataMap) throw Error("Bank metadata map not found");
28792
28867
  return this._lendrAccount.makeBorrowWithSessionIx(
28793
28868
  this._program,
28794
- this.client.banks,
28869
+ this.banks,
28795
28870
  this.client.mintDatas,
28796
28871
  this.client.bankMetadataMap,
28797
28872
  amount,
@@ -28963,12 +29038,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28963
29038
  * @returns An InstructionsWrapper containing the withdraw emissions instructions
28964
29039
  */
28965
29040
  async makeWithdrawEmissionsIx(bankAddress) {
28966
- return this._lendrAccount.makeWithdrawEmissionsIx(
28967
- this._program,
28968
- this.client.banks,
28969
- this.client.mintDatas,
28970
- bankAddress
28971
- );
29041
+ return this._lendrAccount.makeWithdrawEmissionsIx(this._program, this.banks, this.client.mintDatas, bankAddress);
28972
29042
  }
28973
29043
  /**
28974
29044
  * Creates a versioned transaction for withdrawing emissions rewards from multiple lendr bank accounts.
@@ -29045,7 +29115,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29045
29115
  return this._lendrAccount.makeLendingAccountLiquidateIx(
29046
29116
  liquidateeLendrAccount,
29047
29117
  this._program,
29048
- this.client.banks,
29118
+ this.banks,
29049
29119
  this.client.mintDatas,
29050
29120
  this.client.bankMetadataMap,
29051
29121
  assetBankAddress,
@@ -29118,7 +29188,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29118
29188
  * @returns An InstructionsWrapper containing the end flash loan instruction
29119
29189
  */
29120
29190
  async makeEndFlashLoanIx(projectedActiveBalances) {
29121
- return this._lendrAccount.makeEndFlashLoanIx(this._program, this.client.banks, projectedActiveBalances);
29191
+ return this._lendrAccount.makeEndFlashLoanIx(this._program, this.banks, projectedActiveBalances);
29122
29192
  }
29123
29193
  /**
29124
29194
  * Creates an instruction to end a flash loan operation.
@@ -29130,7 +29200,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29130
29200
  async makeEndFlashLoanWithSessionIx(projectedActiveBalances, session) {
29131
29201
  return this._lendrAccount.makeEndFlashLoanWithSessionIx(
29132
29202
  this._program,
29133
- this.client.banks,
29203
+ this.banks,
29134
29204
  projectedActiveBalances,
29135
29205
  session.sessionPublicKey
29136
29206
  );
@@ -29231,7 +29301,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29231
29301
  async makePulseHealthIx(mandatoryBanks = [], excludedBanks = []) {
29232
29302
  return this._lendrAccount.makePulseHealthIx(
29233
29303
  this._program,
29234
- this.client.banks,
29304
+ this.banks,
29235
29305
  mandatoryBanks,
29236
29306
  excludedBanks,
29237
29307
  this.client.bankMetadataMap || {}
@@ -29268,9 +29338,10 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29268
29338
  }
29269
29339
  _updateFromAccountParsed(data) {
29270
29340
  this._lendrAccount = LendrAccount.fromAccountParsed(this.address, data);
29341
+ this.banks = _LendrAccountWrapper.applyEmode(this.client.banks, this._lendrAccount);
29271
29342
  }
29272
29343
  describe() {
29273
- return this._lendrAccount.describe(this.client.banks, this.client.oraclePrices);
29344
+ return this._lendrAccount.describe(this.banks, this.client.oraclePrices);
29274
29345
  }
29275
29346
  // --------------------------------------------------------------------------
29276
29347
  // DEPRECATED METHODS
@@ -29325,7 +29396,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29325
29396
  const simulation = await this.client.simulateTransactions([tx], [this._lendrAccount.address]);
29326
29397
  const rawBuffer = simulation[0];
29327
29398
  if (!rawBuffer) {
29328
- return new BigNumber15(0);
29399
+ return new BigNumber16(0);
29329
29400
  }
29330
29401
  const simulatedLendrAccount = LendrAccount.fromAccountDataRaw(this.address, rawBuffer, this.client.program.idl);
29331
29402
  const outstandingEmissions = simulatedLendrAccount.getBalance(bank).emissionsOutstanding;
@@ -29917,7 +29988,7 @@ var LendrClient = class _LendrClient {
29917
29988
  const oracle = priceInfos.get(bankAddress.toBase58());
29918
29989
  if (oracle) {
29919
29990
  const adjustPrice = (price, stakeActual2, tokenSupply2) => {
29920
- return Number(tokenSupply2) === 0 ? price : new BigNumber16(price.toNumber() * (stakeActual2 - LAMPORTS_PER_SOL6) / Number(tokenSupply2));
29991
+ return Number(tokenSupply2) === 0 ? price : new BigNumber17(price.toNumber() * (stakeActual2 - LAMPORTS_PER_SOL6) / Number(tokenSupply2));
29921
29992
  };
29922
29993
  const adjustPriceComponent2 = (priceComponent, stakeActual2, tokenSupply2) => ({
29923
29994
  price: adjustPrice(priceComponent.price, stakeActual2, tokenSupply2),
@@ -30658,6 +30729,7 @@ export {
30658
30729
  WSOL_MINT,
30659
30730
  accountFlagToBN,
30660
30731
  addOracleToBanksIx,
30732
+ adjustBanksWithEmode,
30661
30733
  balanceToDto,
30662
30734
  bankConfigRawToDto,
30663
30735
  bankConfigToBankConfigRaw,
@@ -30737,6 +30809,7 @@ export {
30737
30809
  getBankVaultSeeds,
30738
30810
  getConfig,
30739
30811
  getConfigPda,
30812
+ getEmodePairs,
30740
30813
  getHealthCacheStatusDescription,
30741
30814
  getLiabilityQuantity,
30742
30815
  getLiabilityShares,
@@ -30759,6 +30832,7 @@ export {
30759
30832
  lendrAccountToDto,
30760
30833
  makeAddPermissionlessStakedBankIx,
30761
30834
  makeBundleTipIx,
30835
+ makeEmodeAssetWeights,
30762
30836
  makePoolAddBankIx2 as makePoolAddBankIx,
30763
30837
  makePoolConfigureBankIx2 as makePoolConfigureBankIx,
30764
30838
  makePriorityFeeIx,