@pyron-finance/pyron-client 2.9.5 → 2.10.1

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
25905
- );
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
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 */
25943
25621
  );
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
25622
+ const { assets: assetValueInitial, liabilities: liabilityValueInitial } = computeHealthComponentsLegacy(
25623
+ activeBalances,
25624
+ props.bankMap,
25625
+ props.oraclePrices,
25626
+ 0 /* Initial */
25986
25627
  );
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
+ )
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);
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
+ );
26020
25698
  }
26021
- computeAssetUsdValue(oraclePrice, assetShares, lendrRequirementType, priceBias) {
26022
- return computeAssetUsdValue(this, oraclePrice, assetShares, 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");
26023
25716
  }
26024
- computeLiabilityUsdValue(oraclePrice, liabilityShares, lendrRequirementType, priceBias) {
26025
- return computeLiabilityUsdValue(this, oraclePrice, liabilityShares, lendrRequirementType, priceBias);
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");
26026
25721
  }
26027
- computeUsdValue(oraclePrice, quantity, priceBias, weightedPrice, weight, scaleToBase = true) {
26028
- return computeUsdValue(this, oraclePrice, quantity, priceBias, weightedPrice, weight, scaleToBase);
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
25749
+ });
25750
+ throw new HealthCacheSimulationError(
25751
+ "Account health cache simulation failed",
25752
+ lendrAccountPost.healthCache.lndrErr,
25753
+ lendrAccountPost.healthCache.internalErr
25754
+ );
26029
25755
  }
26030
- getAssetWeight(lendrRequirementType, oraclePrice, ignoreSoftLimits = false, assetWeightInitOverride) {
26031
- return getAssetWeight(this, lendrRequirementType, oraclePrice, {
26032
- ignoreSoftLimits,
26033
- assetWeightInitOverride
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
+ }
26034
25856
  });
25857
+ return { stalePythFeeds, staleSwbOracles };
26035
25858
  }
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);
26053
- }
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)}
26061
-
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
- )}
25859
+ return { stalePythFeeds: [], staleSwbOracles: [] };
25860
+ }
26074
25861
 
26075
- Asset price (USD): ${_Bank.getPrice(oraclePrice, 1 /* None */, false)}
26076
- Asset price Weighted (USD): ${_Bank.getPrice(oraclePrice, 1 /* None */, true)}
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
+ }
26077
25953
 
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)}
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
+ }
26083
25962
 
26084
- - Deposit limit: ${this.config.depositLimit}
26085
- - Borrow limit: ${this.config.borrowLimit}
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
+ }
26086
25970
 
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;
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
+ }
25989
+
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,50 +27460,35 @@ 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
  );
27392
27467
  return new _LendrAccountWrapper(this.address, this.client, account);
27393
27468
  }
27394
27469
  canBeLiquidated() {
27395
- let { assets, liabilities } = this._lendrAccount.computeHealthComponents(1 /* Maintenance */);
27396
- if (assets.isZero() && liabilities.isZero()) {
27397
- const legacy = this._lendrAccount.computeHealthComponentsLegacy(
27398
- this.client.banks,
27399
- this.client.oraclePrices,
27400
- 1 /* Maintenance */
27401
- );
27402
- assets = legacy.assets;
27403
- liabilities = legacy.liabilities;
27404
- this.client.logger.debug(
27405
- {
27406
- address: this.address.toBase58(),
27407
- assets,
27408
- liabilities,
27409
- usedLegacy: true
27410
- },
27411
- "[lendr:lendr-account:canBeLiquidated]"
27412
- );
27413
- } else {
27414
- this.client.logger.debug(
27415
- {
27416
- address: this.address.toBase58(),
27417
- assets,
27418
- liabilities
27419
- },
27420
- "[lendr:lendr-account:canBeLiquidated]"
27421
- );
27422
- }
27470
+ const { assets, liabilities } = this.computeHealthComponents(1 /* Maintenance */);
27471
+ this.client.logger.debug(
27472
+ {
27473
+ address: this.address.toBase58(),
27474
+ assets,
27475
+ liabilities
27476
+ },
27477
+ "[lendr:lendr-account:canBeLiquidated]"
27478
+ );
27423
27479
  return assets.lt(liabilities);
27424
27480
  }
27425
27481
  computeHealthComponents(lendrRequirement) {
27426
- return this._lendrAccount.computeHealthComponents(lendrRequirement);
27482
+ const cached = this._lendrAccount.computeHealthComponents(lendrRequirement);
27483
+ if (cached.assets.isZero() && cached.liabilities.isZero()) {
27484
+ return this.computeHealthComponentsLegacy(lendrRequirement);
27485
+ }
27486
+ return cached;
27427
27487
  }
27428
27488
  // TODO)) migrate to computeHealthComponents
27429
27489
  computeHealthComponentsLegacy(lendrRequirement, excludedBanks = []) {
27430
27490
  return this._lendrAccount.computeHealthComponentsLegacy(
27431
- this.client.banks,
27491
+ this.banks,
27432
27492
  this.client.oraclePrices,
27433
27493
  lendrRequirement,
27434
27494
  excludedBanks
@@ -27436,7 +27496,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27436
27496
  }
27437
27497
  computeHealthComponentsWithoutBiasLegacy(lendrRequirement) {
27438
27498
  return this._lendrAccount.computeHealthComponentsWithoutBiasLegacy(
27439
- this.client.banks,
27499
+ this.banks,
27440
27500
  this.client.oraclePrices,
27441
27501
  lendrRequirement
27442
27502
  );
@@ -27445,7 +27505,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27445
27505
  return this._lendrAccount.computeFreeCollateral(opts);
27446
27506
  }
27447
27507
  computeFreeCollateralLegacy(opts) {
27448
- return this._lendrAccount.computeFreeCollateralLegacy(this.client.banks, this.client.oraclePrices, opts);
27508
+ return this._lendrAccount.computeFreeCollateralLegacy(this.banks, this.client.oraclePrices, opts);
27449
27509
  }
27450
27510
  computeAccountValue() {
27451
27511
  return this._lendrAccount.computeAccountValue();
@@ -27456,12 +27516,12 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27456
27516
  computeEmodeImpacts(emodePairs) {
27457
27517
  return this._lendrAccount.computeEmodeImpacts(
27458
27518
  emodePairs,
27459
- Array.from(this.client.banks.keys()).map((b) => new PublicKey28(b))
27519
+ Array.from(this.banks.keys()).map((b) => new PublicKey28(b))
27460
27520
  );
27461
27521
  }
27462
27522
  computeMaxBorrowForBank(bankAddress, opts) {
27463
27523
  return this._lendrAccount.computeMaxBorrowForBank(
27464
- this.client.banks,
27524
+ this.banks,
27465
27525
  this.client.oraclePrices,
27466
27526
  bankAddress,
27467
27527
  opts,
@@ -27469,11 +27529,11 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27469
27529
  );
27470
27530
  }
27471
27531
  computeMaxWithdrawForBank(bankAddress, opts) {
27472
- return this._lendrAccount.computeMaxWithdrawForBank(this.client.banks, this.client.oraclePrices, bankAddress, opts);
27532
+ return this._lendrAccount.computeMaxWithdrawForBank(this.banks, this.client.oraclePrices, bankAddress, opts);
27473
27533
  }
27474
27534
  computeMaxLiquidatableAssetAmount(assetBankAddress, liabilityBankAddress) {
27475
27535
  return this._lendrAccount.computeMaxLiquidatableAssetAmount(
27476
- this.client.banks,
27536
+ this.banks,
27477
27537
  this.client.oraclePrices,
27478
27538
  assetBankAddress,
27479
27539
  liabilityBankAddress,
@@ -27481,11 +27541,11 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27481
27541
  );
27482
27542
  }
27483
27543
  computeLiquidationPriceForBank(bankAddress) {
27484
- return this._lendrAccount.computeLiquidationPriceForBank(this.client.banks, this.client.oraclePrices, bankAddress);
27544
+ return this._lendrAccount.computeLiquidationPriceForBank(this.banks, this.client.oraclePrices, bankAddress);
27485
27545
  }
27486
27546
  computeLiquidationPriceForBankAmount(bankAddress, isLending, amount) {
27487
27547
  return this._lendrAccount.computeLiquidationPriceForBankAmount(
27488
- this.client.banks,
27548
+ this.banks,
27489
27549
  this.client.oraclePrices,
27490
27550
  bankAddress,
27491
27551
  isLending,
@@ -27493,15 +27553,15 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27493
27553
  );
27494
27554
  }
27495
27555
  computeNetApy() {
27496
- return this._lendrAccount.computeNetApy(this.client.banks, this.client.oraclePrices);
27556
+ return this._lendrAccount.computeNetApy(this.banks, this.client.oraclePrices);
27497
27557
  }
27498
27558
  /** Todo move this into client */
27499
27559
  computeLoopingParams(principal, targetLeverage, depositBankAddress, borrowBankAddress) {
27500
- const depositBank = this.client.banks.get(depositBankAddress.toBase58());
27560
+ const depositBank = this.banks.get(depositBankAddress.toBase58());
27501
27561
  if (!depositBank) throw Error(`Bank ${depositBankAddress.toBase58()} not found`);
27502
27562
  const depositPriceInfo = this.client.oraclePrices.get(depositBankAddress.toBase58());
27503
27563
  if (!depositPriceInfo) throw Error(`Price info for ${depositBankAddress.toBase58()} not found`);
27504
- const borrowBank = this.client.banks.get(borrowBankAddress.toBase58());
27564
+ const borrowBank = this.banks.get(borrowBankAddress.toBase58());
27505
27565
  if (!borrowBank) throw Error(`Bank ${borrowBankAddress.toBase58()} not found`);
27506
27566
  const borrowPriceInfo = this.client.oraclePrices.get(borrowBankAddress.toBase58());
27507
27567
  if (!borrowPriceInfo) throw Error(`Price info for ${borrowBankAddress.toBase58()} not found`);
@@ -27798,9 +27858,9 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27798
27858
  },
27799
27859
  "[lendr:lendr-account:loop] Looping into Lendr account"
27800
27860
  );
27801
- const depositBank = this.client.banks.get(props.depositBankAddress.toBase58());
27861
+ const depositBank = this.banks.get(props.depositBankAddress.toBase58());
27802
27862
  if (!depositBank) throw Error("Deposit bank not found");
27803
- const borrowBank = this.client.banks.get(props.borrowBankAddress.toBase58());
27863
+ const borrowBank = this.banks.get(props.borrowBankAddress.toBase58());
27804
27864
  if (!borrowBank) throw Error("Borrow bank not found");
27805
27865
  const { processOpts, txOpts, ...txProps } = props;
27806
27866
  const { transactions } = await this.makeLoopTxV2(txProps);
@@ -27825,9 +27885,9 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27825
27885
  setupBankAddresses,
27826
27886
  overrideInferAccounts
27827
27887
  }) {
27828
- const depositBank = this.client.banks.get(depositBankAddress.toBase58());
27888
+ const depositBank = this.banks.get(depositBankAddress.toBase58());
27829
27889
  if (!depositBank) throw Error("Deposit bank not found");
27830
- const borrowBank = this.client.banks.get(borrowBankAddress.toBase58());
27890
+ const borrowBank = this.banks.get(borrowBankAddress.toBase58());
27831
27891
  if (!borrowBank) throw Error("Borrow bank not found");
27832
27892
  const blockhash = blockhashArg ?? (await this._program.provider.connection.getLatestBlockhash("confirmed")).blockhash;
27833
27893
  const setupIxs = await this.makeSetupIx(setupBankAddresses ?? [borrowBankAddress, depositBankAddress]);
@@ -27851,7 +27911,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27851
27911
  let flashloanTx;
27852
27912
  let txOverflown = false;
27853
27913
  if (depositBank.mint.equals(NATIVE_MINT3) && inputDepositAmount) {
27854
- setupIxs.push(...makeWrapSolIxs(this.authority, new BigNumber15(inputDepositAmount)));
27914
+ setupIxs.push(...makeWrapSolIxs(this.authority, new BigNumber16(inputDepositAmount)));
27855
27915
  }
27856
27916
  if (setupIxs.length > 0) {
27857
27917
  const message = new TransactionMessage5({
@@ -27968,7 +28028,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27968
28028
  async makeDepositIx(amount, bankAddress, depositOpts = {}) {
27969
28029
  return this._lendrAccount.makeDepositIx(
27970
28030
  this._program,
27971
- this.client.banks,
28031
+ this.banks,
27972
28032
  this.client.mintDatas,
27973
28033
  amount,
27974
28034
  bankAddress,
@@ -27978,7 +28038,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27978
28038
  async makeDepositWithSessionIx(amount, bankAddress, session, depositOpts = {}) {
27979
28039
  return this._lendrAccount.makeDepositWithSessionIx(
27980
28040
  this._program,
27981
- this.client.banks,
28041
+ this.banks,
27982
28042
  this.client.mintDatas,
27983
28043
  amount,
27984
28044
  bankAddress,
@@ -28224,7 +28284,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28224
28284
  const ldrAccount = LendrAccount.decode(ldrAccountData, this._program.idl);
28225
28285
  console.log("ldrAccount", ldrAccount);
28226
28286
  if (!bankData) throw new Error("Failed to simulate");
28227
- const previewBanks = new Map(this.client.banks);
28287
+ const previewBanks = new Map(this.banks);
28228
28288
  banksToInspect.forEach((bankAddress, idx) => {
28229
28289
  const data = bankData[idx];
28230
28290
  if (!data) throw new Error("Failed to simulate");
@@ -28239,7 +28299,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28239
28299
  wallet: {},
28240
28300
  isReadOnly: true,
28241
28301
  group: this.client.group,
28242
- banks: this.client.banks,
28302
+ banks: previewBanks,
28243
28303
  priceInfos: this.client.oraclePrices,
28244
28304
  mintDatas: this.client.mintDatas,
28245
28305
  feedIdMap: this.client.feedIdMap,
@@ -28271,7 +28331,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28271
28331
  if (!tokenProgramAddress) throw Error("Repay mint not found");
28272
28332
  return this._lendrAccount.makeRepayIx(
28273
28333
  this._program,
28274
- this.client.banks,
28334
+ this.banks,
28275
28335
  this.client.mintDatas,
28276
28336
  amount,
28277
28337
  bankAddress,
@@ -28295,7 +28355,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28295
28355
  if (!tokenProgramAddress) throw Error("Repay mint not found");
28296
28356
  return this._lendrAccount.makeRepayWithSessionIx(
28297
28357
  this._program,
28298
- this.client.banks,
28358
+ this.banks,
28299
28359
  this.client.mintDatas,
28300
28360
  amount,
28301
28361
  bankAddress,
@@ -28424,7 +28484,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28424
28484
  if (!this.client.bankMetadataMap) throw Error("Bank metadata map not found");
28425
28485
  return this._lendrAccount.makeWithdrawIx(
28426
28486
  this._program,
28427
- this.client.banks,
28487
+ this.banks,
28428
28488
  this.client.mintDatas,
28429
28489
  this.client.bankMetadataMap,
28430
28490
  amount,
@@ -28450,7 +28510,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28450
28510
  if (!this.client.bankMetadataMap) throw Error("Bank metadata map not found");
28451
28511
  return this._lendrAccount.makeWithdrawWithSessionIx(
28452
28512
  this._program,
28453
- this.client.banks,
28513
+ this.banks,
28454
28514
  this.client.mintDatas,
28455
28515
  this.client.bankMetadataMap,
28456
28516
  amount,
@@ -28487,7 +28547,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28487
28547
  const mintAuthority = findPoolMintAuthorityAddress(pool);
28488
28548
  const lstAta = getAssociatedTokenAddressSync3(lstMint, this.authority);
28489
28549
  const rentExemption = await this._program.provider.connection.getMinimumBalanceForRentExemption(200);
28490
- const stakeAmount = new BigNumber15(new BigNumber15(amount).toString());
28550
+ const stakeAmount = new BigNumber16(new BigNumber16(amount).toString());
28491
28551
  const withdrawIxs = await this.makeWithdrawIx(amount, bankAddress, isWholePosition, {
28492
28552
  createAtas: true,
28493
28553
  wrapAndUnwrapSol: true
@@ -28768,7 +28828,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28768
28828
  if (!this.client.bankMetadataMap) throw Error("Bank metadata map not found");
28769
28829
  return this._lendrAccount.makeBorrowIx(
28770
28830
  this._program,
28771
- this.client.banks,
28831
+ this.banks,
28772
28832
  this.client.mintDatas,
28773
28833
  this.client.bankMetadataMap,
28774
28834
  amount,
@@ -28791,7 +28851,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28791
28851
  if (!this.client.bankMetadataMap) throw Error("Bank metadata map not found");
28792
28852
  return this._lendrAccount.makeBorrowWithSessionIx(
28793
28853
  this._program,
28794
- this.client.banks,
28854
+ this.banks,
28795
28855
  this.client.mintDatas,
28796
28856
  this.client.bankMetadataMap,
28797
28857
  amount,
@@ -28963,12 +29023,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28963
29023
  * @returns An InstructionsWrapper containing the withdraw emissions instructions
28964
29024
  */
28965
29025
  async makeWithdrawEmissionsIx(bankAddress) {
28966
- return this._lendrAccount.makeWithdrawEmissionsIx(
28967
- this._program,
28968
- this.client.banks,
28969
- this.client.mintDatas,
28970
- bankAddress
28971
- );
29026
+ return this._lendrAccount.makeWithdrawEmissionsIx(this._program, this.banks, this.client.mintDatas, bankAddress);
28972
29027
  }
28973
29028
  /**
28974
29029
  * Creates a versioned transaction for withdrawing emissions rewards from multiple lendr bank accounts.
@@ -29045,7 +29100,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29045
29100
  return this._lendrAccount.makeLendingAccountLiquidateIx(
29046
29101
  liquidateeLendrAccount,
29047
29102
  this._program,
29048
- this.client.banks,
29103
+ this.banks,
29049
29104
  this.client.mintDatas,
29050
29105
  this.client.bankMetadataMap,
29051
29106
  assetBankAddress,
@@ -29118,7 +29173,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29118
29173
  * @returns An InstructionsWrapper containing the end flash loan instruction
29119
29174
  */
29120
29175
  async makeEndFlashLoanIx(projectedActiveBalances) {
29121
- return this._lendrAccount.makeEndFlashLoanIx(this._program, this.client.banks, projectedActiveBalances);
29176
+ return this._lendrAccount.makeEndFlashLoanIx(this._program, this.banks, projectedActiveBalances);
29122
29177
  }
29123
29178
  /**
29124
29179
  * Creates an instruction to end a flash loan operation.
@@ -29130,7 +29185,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29130
29185
  async makeEndFlashLoanWithSessionIx(projectedActiveBalances, session) {
29131
29186
  return this._lendrAccount.makeEndFlashLoanWithSessionIx(
29132
29187
  this._program,
29133
- this.client.banks,
29188
+ this.banks,
29134
29189
  projectedActiveBalances,
29135
29190
  session.sessionPublicKey
29136
29191
  );
@@ -29231,7 +29286,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29231
29286
  async makePulseHealthIx(mandatoryBanks = [], excludedBanks = []) {
29232
29287
  return this._lendrAccount.makePulseHealthIx(
29233
29288
  this._program,
29234
- this.client.banks,
29289
+ this.banks,
29235
29290
  mandatoryBanks,
29236
29291
  excludedBanks,
29237
29292
  this.client.bankMetadataMap || {}
@@ -29268,9 +29323,10 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29268
29323
  }
29269
29324
  _updateFromAccountParsed(data) {
29270
29325
  this._lendrAccount = LendrAccount.fromAccountParsed(this.address, data);
29326
+ this.banks = _LendrAccountWrapper.applyEmode(this.client.banks, this._lendrAccount);
29271
29327
  }
29272
29328
  describe() {
29273
- return this._lendrAccount.describe(this.client.banks, this.client.oraclePrices);
29329
+ return this._lendrAccount.describe(this.banks, this.client.oraclePrices);
29274
29330
  }
29275
29331
  // --------------------------------------------------------------------------
29276
29332
  // DEPRECATED METHODS
@@ -29325,7 +29381,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29325
29381
  const simulation = await this.client.simulateTransactions([tx], [this._lendrAccount.address]);
29326
29382
  const rawBuffer = simulation[0];
29327
29383
  if (!rawBuffer) {
29328
- return new BigNumber15(0);
29384
+ return new BigNumber16(0);
29329
29385
  }
29330
29386
  const simulatedLendrAccount = LendrAccount.fromAccountDataRaw(this.address, rawBuffer, this.client.program.idl);
29331
29387
  const outstandingEmissions = simulatedLendrAccount.getBalance(bank).emissionsOutstanding;
@@ -29917,7 +29973,7 @@ var LendrClient = class _LendrClient {
29917
29973
  const oracle = priceInfos.get(bankAddress.toBase58());
29918
29974
  if (oracle) {
29919
29975
  const adjustPrice = (price, stakeActual2, tokenSupply2) => {
29920
- return Number(tokenSupply2) === 0 ? price : new BigNumber16(price.toNumber() * (stakeActual2 - LAMPORTS_PER_SOL6) / Number(tokenSupply2));
29976
+ return Number(tokenSupply2) === 0 ? price : new BigNumber17(price.toNumber() * (stakeActual2 - LAMPORTS_PER_SOL6) / Number(tokenSupply2));
29921
29977
  };
29922
29978
  const adjustPriceComponent2 = (priceComponent, stakeActual2, tokenSupply2) => ({
29923
29979
  price: adjustPrice(priceComponent.price, stakeActual2, tokenSupply2),
@@ -30658,6 +30714,7 @@ export {
30658
30714
  WSOL_MINT,
30659
30715
  accountFlagToBN,
30660
30716
  addOracleToBanksIx,
30717
+ adjustBanksWithEmode,
30661
30718
  balanceToDto,
30662
30719
  bankConfigRawToDto,
30663
30720
  bankConfigToBankConfigRaw,
@@ -30737,6 +30794,7 @@ export {
30737
30794
  getBankVaultSeeds,
30738
30795
  getConfig,
30739
30796
  getConfigPda,
30797
+ getEmodePairs,
30740
30798
  getHealthCacheStatusDescription,
30741
30799
  getLiabilityQuantity,
30742
30800
  getLiabilityShares,
@@ -30759,6 +30817,7 @@ export {
30759
30817
  lendrAccountToDto,
30760
30818
  makeAddPermissionlessStakedBankIx,
30761
30819
  makeBundleTipIx,
30820
+ makeEmodeAssetWeights,
30762
30821
  makePoolAddBankIx2 as makePoolAddBankIx,
30763
30822
  makePoolConfigureBankIx2 as makePoolConfigureBankIx,
30764
30823
  makePriorityFeeIx,