@pyron-finance/pyron-client 2.9.5 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -539,6 +539,7 @@ __export(index_exports, {
539
539
  WSOL_MINT: () => WSOL_MINT,
540
540
  accountFlagToBN: () => accountFlagToBN,
541
541
  addOracleToBanksIx: () => addOracleToBanksIx,
542
+ adjustBanksWithEmode: () => adjustBanksWithEmode,
542
543
  balanceToDto: () => balanceToDto,
543
544
  bankConfigRawToDto: () => bankConfigRawToDto,
544
545
  bankConfigToBankConfigRaw: () => bankConfigToBankConfigRaw,
@@ -618,6 +619,7 @@ __export(index_exports, {
618
619
  getBankVaultSeeds: () => getBankVaultSeeds,
619
620
  getConfig: () => getConfig,
620
621
  getConfigPda: () => getConfigPda,
622
+ getEmodePairs: () => getEmodePairs,
621
623
  getHealthCacheStatusDescription: () => getHealthCacheStatusDescription,
622
624
  getLiabilityQuantity: () => getLiabilityQuantity,
623
625
  getLiabilityShares: () => getLiabilityShares,
@@ -640,6 +642,7 @@ __export(index_exports, {
640
642
  lendrAccountToDto: () => lendrAccountToDto,
641
643
  makeAddPermissionlessStakedBankIx: () => makeAddPermissionlessStakedBankIx,
642
644
  makeBundleTipIx: () => makeBundleTipIx,
645
+ makeEmodeAssetWeights: () => makeEmodeAssetWeights,
643
646
  makePoolAddBankIx: () => makePoolAddBankIx2,
644
647
  makePoolConfigureBankIx: () => makePoolConfigureBankIx2,
645
648
  makePriorityFeeIx: () => makePriorityFeeIx,
@@ -685,7 +688,7 @@ module.exports = __toCommonJS(index_exports);
685
688
  var import_anchor10 = require("@coral-xyz/anchor");
686
689
  var import_spl_token8 = require("@solana/spl-token");
687
690
  var import_web332 = require("@solana/web3.js");
688
- var import_bignumber16 = __toESM(require("bignumber.js"), 1);
691
+ var import_bignumber17 = __toESM(require("bignumber.js"), 1);
689
692
  var import_bs582 = __toESM(require("bs58"), 1);
690
693
  var import_unstorage2 = require("unstorage");
691
694
 
@@ -14181,12 +14184,12 @@ var import_anchor7 = require("@coral-xyz/anchor");
14181
14184
  var import_sessions_sdk = require("@fogo/sessions-sdk");
14182
14185
  var import_spl_token6 = require("@solana/spl-token");
14183
14186
  var import_web330 = require("@solana/web3.js");
14184
- var import_bignumber14 = __toESM(require("bignumber.js"), 1);
14187
+ var import_bignumber15 = __toESM(require("bignumber.js"), 1);
14185
14188
  var import_bn13 = __toESM(require("bn.js"), 1);
14186
14189
 
14187
14190
  // src/services/account/account.service.ts
14188
14191
  var import_web325 = require("@solana/web3.js");
14189
- var import_bignumber12 = __toESM(require("bignumber.js"), 1);
14192
+ var import_bignumber14 = __toESM(require("bignumber.js"), 1);
14190
14193
  var import_bn11 = __toESM(require("bn.js"), 1);
14191
14194
 
14192
14195
  // src/models/health-cache.ts
@@ -25149,1168 +25152,1229 @@ function dtoToHealthCache(healthCacheDto) {
25149
25152
  }
25150
25153
 
25151
25154
  // src/services/account/utils/emode.utils.ts
25152
- function computeEmodeImpacts(emodePairs, activeLiabilities, activeCollateral, allBanks) {
25153
- const toKey = (k) => k.toBase58();
25154
- const basePairs = computeActiveEmodePairs(emodePairs, activeLiabilities, activeCollateral);
25155
- const baseOn = basePairs.length > 0;
25156
- const liabTagMap = /* @__PURE__ */ new Map();
25157
- for (const p of emodePairs) {
25158
- liabTagMap.set(p.liabilityBank.toBase58(), p.liabilityBankTag.toString());
25159
- }
25160
- const existingTags = new Set(
25161
- activeLiabilities.map((l) => liabTagMap.get(l.toBase58())).filter((t) => !!t)
25162
- );
25163
- function minWeight(ps) {
25164
- let m = ps[0].assetWeightInit;
25165
- for (const x of ps) if (x.assetWeightInit.lt(m)) m = x.assetWeightInit;
25166
- return m;
25167
- }
25168
- function diffState(before, after) {
25169
- const was = before.length > 0, isOn = after.length > 0;
25170
- if (!was && !isOn) return 5 /* InactiveEmode */;
25171
- if (!was && isOn) return 0 /* ActivateEmode */;
25172
- if (was && !isOn) return 4 /* RemoveEmode */;
25173
- const bMin = minWeight(before), aMin = minWeight(after);
25174
- if (aMin.gt(bMin)) return 2 /* IncreaseEmode */;
25175
- if (aMin.lt(bMin)) return 3 /* ReduceEmode */;
25176
- return 1 /* ExtendEmode */;
25177
- }
25178
- function simulate(bank, action) {
25179
- let L = [...activeLiabilities], C = [...activeCollateral];
25180
- switch (action) {
25181
- case "borrow":
25182
- if (!L.some((x) => x.equals(bank))) L.push(bank);
25183
- break;
25184
- case "repay":
25185
- L = L.filter((x) => !x.equals(bank));
25186
- break;
25187
- case "supply":
25188
- if (!C.some((x) => x.equals(bank))) C.push(bank);
25189
- break;
25190
- case "withdraw":
25191
- C = C.filter((x) => !x.equals(bank));
25192
- break;
25193
- }
25194
- const after = computeActiveEmodePairs(emodePairs, L, C);
25195
- let status = diffState(basePairs, after);
25196
- if (action === "borrow") {
25197
- const tag = liabTagMap.get(bank.toBase58());
25198
- if (!tag) {
25199
- status = baseOn ? 4 /* RemoveEmode */ : 5 /* InactiveEmode */;
25200
- } else if (baseOn) {
25201
- if (after.length === 0) {
25202
- status = 4 /* RemoveEmode */;
25203
- } else if (existingTags.has(tag)) {
25204
- status = 1 /* ExtendEmode */;
25205
- }
25206
- }
25207
- }
25208
- if (action === "supply") {
25209
- const isOn = after.length > 0;
25210
- status = !baseOn && isOn ? 0 /* ActivateEmode */ : baseOn && isOn ? 1 /* ExtendEmode */ : 5 /* InactiveEmode */;
25211
- }
25212
- if (action === "withdraw") {
25213
- if (!baseOn) {
25214
- status = 5 /* InactiveEmode */;
25215
- } else if (after.length === 0) {
25216
- status = 4 /* RemoveEmode */;
25217
- } else {
25218
- const b = minWeight(basePairs), a = minWeight(after);
25219
- if (a.gt(b)) status = 2 /* IncreaseEmode */;
25220
- else if (a.lt(b)) status = 3 /* ReduceEmode */;
25221
- else status = 1 /* ExtendEmode */;
25222
- }
25223
- }
25224
- let bestPair;
25225
- if (after.length > 0) {
25226
- bestPair = after[0];
25227
- for (const p of after) {
25228
- if (p.assetWeightInit.lt(bestPair.assetWeightInit)) {
25229
- bestPair = p;
25230
- }
25231
- }
25232
- }
25233
- const activeEmodePair = bestPair ? {
25234
- collateralBanks: Array.from(
25235
- new Map(after.flatMap((p) => p.collateralBanks).map((bank2) => [bank2.toBase58(), bank2])).values()
25236
- ),
25237
- collateralBankTags: Array.from(new Set(after.flatMap((p) => p.collateralBankTag))),
25238
- liabilityBanks: Array.from(
25239
- new Map(after.flatMap((p) => p.liabilityBank).map((bank2) => [bank2.toBase58(), bank2])).values()
25240
- ),
25241
- liabilityBankTags: Array.from(new Set(after.flatMap((p) => p.liabilityBankTag))),
25242
- assetWeightMaint: bestPair.assetWeightMaint,
25243
- assetWeightInit: bestPair.assetWeightInit
25244
- } : void 0;
25245
- return {
25246
- status,
25247
- resultingPairs: after,
25248
- activePair: activeEmodePair
25249
- };
25250
- }
25251
- const result = {};
25252
- for (const bank of allBanks) {
25253
- const key = toKey(bank);
25254
- const impact = {};
25255
- if (!activeCollateral.some((x) => x.equals(bank))) {
25256
- impact.borrowImpact = simulate(bank, "borrow");
25257
- }
25258
- const collSet = new Set(emodePairs.flatMap((p) => p.collateralBanks.map((c) => c.toBase58())));
25259
- if (collSet.has(key) && !activeCollateral.some((x) => x.equals(bank)) && !activeLiabilities.some((x) => x.equals(bank))) {
25260
- impact.supplyImpact = simulate(bank, "supply");
25261
- }
25262
- if (activeLiabilities.some((x) => x.equals(bank))) {
25263
- impact.repayAllImpact = simulate(bank, "repay");
25264
- }
25265
- if (activeCollateral.some((x) => x.equals(bank))) {
25266
- impact.withdrawAllImpact = simulate(bank, "withdraw");
25267
- }
25268
- result[key] = impact;
25155
+ var import_bignumber13 = __toESM(require("bignumber.js"), 1);
25156
+
25157
+ // src/models/bank.ts
25158
+ var import_bignumber12 = __toESM(require("bignumber.js"), 1);
25159
+ var SECONDS_PER_DAY2 = 24 * 60 * 60;
25160
+ var _SECONDS_PER_YEAR = SECONDS_PER_DAY2 * 365.25;
25161
+ var Bank = class _Bank {
25162
+ 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) {
25163
+ this.address = address;
25164
+ this.mint = mint;
25165
+ this.mintDecimals = mintDecimals;
25166
+ this.group = group;
25167
+ this.mintRate = mintRate;
25168
+ this.mintPrice = mintPrice;
25169
+ this.assetShareValue = assetShareValue;
25170
+ this.liabilityShareValue = liabilityShareValue;
25171
+ this.liquidityVault = liquidityVault;
25172
+ this.liquidityVaultBump = liquidityVaultBump;
25173
+ this.liquidityVaultAuthorityBump = liquidityVaultAuthorityBump;
25174
+ this.insuranceVault = insuranceVault;
25175
+ this.insuranceVaultBump = insuranceVaultBump;
25176
+ this.insuranceVaultAuthorityBump = insuranceVaultAuthorityBump;
25177
+ this.collectedInsuranceFeesOutstanding = collectedInsuranceFeesOutstanding;
25178
+ this.feeVault = feeVault;
25179
+ this.feeVaultBump = feeVaultBump;
25180
+ this.feeVaultAuthorityBump = feeVaultAuthorityBump;
25181
+ this.collectedGroupFeesOutstanding = collectedGroupFeesOutstanding;
25182
+ this.lastUpdate = lastUpdate;
25183
+ this.config = config;
25184
+ this.totalAssetShares = totalAssetShares;
25185
+ this.totalLiabilityShares = totalLiabilityShares;
25186
+ this.flags = flags;
25187
+ this.emissionsActiveBorrowing = emissionsActiveBorrowing;
25188
+ this.emissionsActiveLending = emissionsActiveLending;
25189
+ this.emissionsRate = emissionsRate;
25190
+ this.emissionsMint = emissionsMint;
25191
+ this.emissionsRemaining = emissionsRemaining;
25192
+ this.oracleKey = oracleKey;
25193
+ this.emode = emode;
25194
+ this.feesDestinationAccount = feesDestinationAccount;
25195
+ this.lendingPositionCount = lendingPositionCount;
25196
+ this.borrowingPositionCount = borrowingPositionCount;
25197
+ this.pythShardId = pythShardId;
25198
+ this.tokenSymbol = tokenSymbol;
25199
+ this.extendedMetadata = extendedMetadata;
25200
+ this.owner = owner;
25269
25201
  }
25270
- return result;
25271
- }
25272
- function computeActiveEmodePairs(emodePairs, activeLiabilities, activeCollateral) {
25273
- const configured = emodePairs.filter(
25274
- (p) => p.collateralBankTag !== EmodeTag.UNSET && p.liabilityBankTag !== EmodeTag.UNSET
25275
- );
25276
- const liabTagByBank = /* @__PURE__ */ new Map();
25277
- for (const p of configured) {
25278
- liabTagByBank.set(p.liabilityBank.toBase58(), p.liabilityBankTag.toString());
25202
+ static decodeBankRaw(encoded, idl) {
25203
+ return decodeBankRaw(encoded, idl);
25279
25204
  }
25280
- const requiredTags = /* @__PURE__ */ new Set();
25281
- for (const liab of activeLiabilities) {
25282
- const tag = liabTagByBank.get(liab.toBase58());
25283
- if (!tag) {
25284
- return [];
25285
- }
25286
- requiredTags.add(tag);
25205
+ static fromBuffer(bankPk, rawData, idl, feedIdMap) {
25206
+ const accountParsed = _Bank.decodeBankRaw(rawData, idl);
25207
+ return _Bank.fromAccountParsed(bankPk, accountParsed, feedIdMap);
25287
25208
  }
25288
- const possible = configured.filter(
25289
- (p) => activeLiabilities.some((l) => l.equals(p.liabilityBank)) && p.collateralBanks.some((c) => activeCollateral.some((a) => a.equals(c)))
25290
- );
25291
- if (possible.length === 0) return [];
25292
- const byCollTag = {};
25293
- for (const p of possible) {
25294
- const ct = p.collateralBankTag.toString();
25295
- if (!byCollTag[ct]) {
25296
- byCollTag[ct] = [];
25297
- }
25298
- byCollTag[ct].push(p);
25209
+ static fromBankType(bankType) {
25210
+ const config = new BankConfig(
25211
+ bankType.config.assetWeightInit,
25212
+ bankType.config.assetWeightMaint,
25213
+ bankType.config.liabilityWeightInit,
25214
+ bankType.config.liabilityWeightMaint,
25215
+ bankType.config.depositLimit,
25216
+ bankType.config.borrowLimit,
25217
+ bankType.config.riskTier,
25218
+ bankType.config.totalAssetValueInitLimit,
25219
+ bankType.config.assetTag,
25220
+ bankType.config.oracleSetup,
25221
+ bankType.config.oracleKeys,
25222
+ bankType.config.oracleMaxAge,
25223
+ bankType.config.interestRateConfig,
25224
+ bankType.config.operationalState,
25225
+ bankType.config.oracleMaxConfidence,
25226
+ bankType.config.fixedPrice,
25227
+ bankType.config.configFlags
25228
+ );
25229
+ return new _Bank(
25230
+ bankType.address,
25231
+ bankType.mint,
25232
+ bankType.mintDecimals,
25233
+ bankType.group,
25234
+ bankType.mintRate,
25235
+ bankType.mintPrice,
25236
+ bankType.assetShareValue,
25237
+ bankType.liabilityShareValue,
25238
+ bankType.liquidityVault,
25239
+ bankType.liquidityVaultBump,
25240
+ bankType.liquidityVaultAuthorityBump,
25241
+ bankType.insuranceVault,
25242
+ bankType.insuranceVaultBump,
25243
+ bankType.insuranceVaultAuthorityBump,
25244
+ bankType.collectedInsuranceFeesOutstanding,
25245
+ bankType.feeVault,
25246
+ bankType.feeVaultBump,
25247
+ bankType.feeVaultAuthorityBump,
25248
+ bankType.collectedGroupFeesOutstanding,
25249
+ bankType.lastUpdate,
25250
+ config,
25251
+ bankType.totalAssetShares,
25252
+ bankType.totalLiabilityShares,
25253
+ bankType.flags,
25254
+ bankType.emissionsActiveBorrowing,
25255
+ bankType.emissionsActiveLending,
25256
+ bankType.emissionsRate,
25257
+ bankType.emissionsMint,
25258
+ bankType.emissionsRemaining,
25259
+ bankType.oracleKey,
25260
+ bankType.emode,
25261
+ bankType.feesDestinationAccount,
25262
+ bankType.lendingPositionCount,
25263
+ bankType.borrowingPositionCount,
25264
+ bankType.pythShardId,
25265
+ bankType.tokenSymbol
25266
+ );
25299
25267
  }
25300
- const validGroups = [];
25301
- for (const group of Object.values(byCollTag)) {
25302
- const supports = new Set(group.map((p) => p.liabilityBankTag.toString()));
25303
- let coversAll = true;
25304
- for (const rt of requiredTags) {
25305
- if (!supports.has(rt)) {
25306
- coversAll = false;
25307
- break;
25308
- }
25309
- }
25310
- if (coversAll) {
25311
- validGroups.push(group);
25312
- }
25268
+ static fromAccountParsed(address, accountParsed, feedIdMap, extendedMetadata, owner) {
25269
+ const props = parseBankRaw(address, accountParsed, feedIdMap);
25270
+ return new _Bank(
25271
+ props.address,
25272
+ props.mint,
25273
+ props.mintDecimals,
25274
+ props.group,
25275
+ props.mintRate,
25276
+ props.mintPrice,
25277
+ props.assetShareValue,
25278
+ props.liabilityShareValue,
25279
+ props.liquidityVault,
25280
+ props.liquidityVaultBump,
25281
+ props.liquidityVaultAuthorityBump,
25282
+ props.insuranceVault,
25283
+ props.insuranceVaultBump,
25284
+ props.insuranceVaultAuthorityBump,
25285
+ props.collectedInsuranceFeesOutstanding,
25286
+ props.feeVault,
25287
+ props.feeVaultBump,
25288
+ props.feeVaultAuthorityBump,
25289
+ props.collectedGroupFeesOutstanding,
25290
+ props.lastUpdate,
25291
+ props.config,
25292
+ props.totalAssetShares,
25293
+ props.totalLiabilityShares,
25294
+ props.flags,
25295
+ props.emissionsActiveBorrowing,
25296
+ props.emissionsActiveLending,
25297
+ props.emissionsRate,
25298
+ props.emissionsMint,
25299
+ props.emissionsRemaining,
25300
+ props.oracleKey,
25301
+ props.emode,
25302
+ props.feesDestinationAccount,
25303
+ props.lendingPositionCount,
25304
+ props.borrowingPositionCount,
25305
+ props.pythShardId,
25306
+ extendedMetadata?.symbol,
25307
+ extendedMetadata,
25308
+ owner
25309
+ );
25313
25310
  }
25314
- if (validGroups.length === 0) return [];
25315
- return validGroups.flat();
25316
- }
25317
-
25318
- // src/services/account/utils/fetch.utils.ts
25319
- var fetchLendrAccountAddresses = async (program, authority, group) => {
25320
- const lendrAccounts = (await program.account.lendrAccount.all([
25321
- {
25322
- memcmp: {
25323
- bytes: group.toBase58(),
25324
- offset: 8
25325
- // lendrGroup is the first field in the account, so only offset is the discriminant
25326
- }
25327
- },
25328
- {
25329
- memcmp: {
25330
- bytes: authority.toBase58(),
25331
- offset: 8 + 32
25332
- // authority is the second field in the account after the authority, so offset by the discriminant and a pubkey
25333
- }
25334
- }
25335
- ])).map((a) => a.publicKey);
25336
- return lendrAccounts;
25337
- };
25338
- var fetchLendrAccountData = async (program, lendrAccountPk, bankMap, oraclePrices, bankMetadataMap) => {
25339
- const lendrAccountRaw = await program.account.lendrAccount.fetch(lendrAccountPk, "confirmed");
25340
- const lendrAccount = LendrAccount.fromAccountParsed(lendrAccountPk, lendrAccountRaw);
25341
- const lendrAccountWithCache = await simulateAccountHealthCacheWithFallback({
25342
- program,
25343
- lendrAccount,
25344
- bankMap,
25345
- oraclePrices,
25346
- bankMetadataMap,
25347
- balances: lendrAccount.balances
25348
- });
25349
- return lendrAccountWithCache;
25350
- };
25351
-
25352
- // src/services/account/utils/serialize.utils.ts
25353
- var import_bn10 = __toESM(require("bn.js"), 1);
25354
- function accountFlagToBN(flag) {
25355
- return new import_bn10.default(flag);
25356
- }
25357
- function lendrAccountToDto(lendrAccount) {
25358
- return {
25359
- address: lendrAccount.address.toBase58(),
25360
- group: lendrAccount.group.toBase58(),
25361
- authority: lendrAccount.authority.toBase58(),
25362
- balances: lendrAccount.balances.map(balanceToDto),
25363
- accountFlags: lendrAccount.accountFlags,
25364
- emissionsDestinationAccount: lendrAccount.emissionsDestinationAccount.toBase58(),
25365
- healthCache: healthCacheToDto(lendrAccount.healthCache)
25366
- };
25367
- }
25368
- function balanceToDto(balance) {
25369
- return {
25370
- active: balance.active,
25371
- bankPk: balance.bankPk.toBase58(),
25372
- assetShares: balance.assetShares.toString(),
25373
- liabilityShares: balance.liabilityShares.toString(),
25374
- emissionsOutstanding: balance.emissionsOutstanding.toString(),
25375
- lastUpdate: balance.lastUpdate
25376
- };
25377
- }
25378
- function healthCacheToDto(healthCache) {
25379
- return {
25380
- assetValue: healthCache.assetValue.toString(),
25381
- liabilityValue: healthCache.liabilityValue.toString(),
25382
- assetValueMaint: healthCache.assetValueMaint.toString(),
25383
- liabilityValueMaint: healthCache.liabilityValueMaint.toString(),
25384
- assetValueEquity: healthCache.assetValueEquity.toString(),
25385
- liabilityValueEquity: healthCache.liabilityValueEquity.toString(),
25386
- timestamp: healthCache.timestamp.toString(),
25387
- flags: healthCache.flags,
25388
- prices: healthCache.prices,
25389
- simulationFailed: healthCache.simulationFailed
25390
- };
25391
- }
25392
-
25393
- // src/services/account/account.service.ts
25394
- var HealthCacheSimulationError = class _HealthCacheSimulationError extends Error {
25395
- lndrErr;
25396
- internalErr;
25397
- constructor(message, lndrErr, internalErr) {
25398
- super(message);
25399
- this.name = "HealthCacheSimulationError";
25400
- this.lndrErr = lndrErr;
25401
- this.internalErr = internalErr;
25402
- if (Error.captureStackTrace) {
25403
- Error.captureStackTrace(this, _HealthCacheSimulationError);
25404
- }
25311
+ static withEmodeWeights(bank, emodeWeights) {
25312
+ const newBank = Object.create(_Bank.prototype);
25313
+ Object.assign(newBank, bank);
25314
+ newBank.config = Object.assign({}, bank.config);
25315
+ newBank.config.assetWeightInit = import_bignumber12.default.max(bank.config.assetWeightInit, emodeWeights.assetWeightInit);
25316
+ newBank.config.assetWeightMaint = import_bignumber12.default.max(bank.config.assetWeightMaint, emodeWeights.assetWeightMaint);
25317
+ return newBank;
25405
25318
  }
25406
- };
25407
- async function simulateAccountHealthCacheWithFallback(props) {
25408
- let lendrAccount = props.lendrAccount;
25409
- const activeBalances = props.balances.filter((b) => b.active);
25410
- const { assets: assetValueEquity, liabilities: liabilityValueEquity } = computeHealthComponentsWithoutBiasLegacy(
25411
- activeBalances,
25412
- props.bankMap,
25413
- props.oraclePrices,
25414
- 2 /* Equity */
25415
- );
25416
- try {
25417
- const simulatedAccount = await simulateAccountHealthCache({
25418
- program: props.program,
25419
- bankMap: props.bankMap,
25420
- oraclePrices: props.oraclePrices,
25421
- lendrAccountPk: props.lendrAccount.address,
25422
- balances: props.balances,
25423
- bankMetadataMap: props.bankMetadataMap
25424
- });
25425
- simulatedAccount.healthCache.assetValueEquity = bigNumberToWrappedI80F48(assetValueEquity);
25426
- simulatedAccount.healthCache.liabilityValueEquity = bigNumberToWrappedI80F48(liabilityValueEquity);
25427
- lendrAccount = LendrAccount.fromAccountParsed(props.lendrAccount.address, simulatedAccount);
25428
- } catch (e) {
25429
- console.log("e", e);
25430
- const { assets: assetValueMaint, liabilities: liabilityValueMaint } = computeHealthComponentsLegacy(
25431
- activeBalances,
25432
- props.bankMap,
25433
- props.oraclePrices,
25434
- 1 /* Maintenance */
25435
- );
25436
- const { assets: assetValueInitial, liabilities: liabilityValueInitial } = computeHealthComponentsLegacy(
25437
- activeBalances,
25438
- props.bankMap,
25439
- props.oraclePrices,
25440
- 0 /* Initial */
25441
- );
25442
- lendrAccount.setHealthCache(
25443
- new HealthCache(
25444
- assetValueInitial,
25445
- liabilityValueInitial,
25446
- assetValueMaint,
25447
- liabilityValueMaint,
25448
- assetValueEquity,
25449
- liabilityValueEquity,
25450
- new import_bignumber12.default(0),
25451
- [],
25452
- [],
25453
- true
25454
- )
25455
- );
25456
- if (e instanceof HealthCacheSimulationError) {
25457
- return { lendrAccount, error: e };
25458
- }
25319
+ static getPrice(oraclePrice, priceBias = 1 /* None */, weightedPrice = false) {
25320
+ return getPrice(oraclePrice, priceBias, weightedPrice);
25459
25321
  }
25460
- return { lendrAccount };
25461
- }
25462
- async function simulateAccountHealthCache(props) {
25463
- const { program, bankMap, oraclePrices, lendrAccountPk, balances, bankMetadataMap } = props;
25464
- const activeBalances = balances.filter((b) => b.active);
25465
- const { staleSwbOracles } = getActiveStaleBanks(activeBalances, bankMap, [], oraclePrices, 30);
25466
- const computeIx = import_web325.ComputeBudgetProgram.setComputeUnitLimit({ units: 14e5 });
25467
- const blockhash = (await program.provider.connection.getLatestBlockhash("confirmed")).blockhash;
25468
- const fundAccountIx = import_web325.SystemProgram.transfer({
25469
- fromPubkey: new import_web325.PublicKey("DD3AeAssFvjqTvRTrRAtpfjkBF8FpVKnFuwnMLN9haXD"),
25470
- // lendr SOL VAULT
25471
- toPubkey: program.provider.publicKey,
25472
- lamports: 1e8
25473
- // 0.1 SOL
25474
- });
25475
- const crankPythIxs = {
25476
- postInstructions: [],
25477
- closeInstructions: [],
25478
- keys: [],
25479
- lut: null
25480
- };
25481
- const crankSwbIxs = staleSwbOracles.length > 0 ? await createUpdateFeedIx({
25482
- swbPullOracles: staleSwbOracles.map((oracle) => oracle.oracleKey),
25483
- provider: program.provider
25484
- }) : { instructions: [], luts: [] };
25485
- const healthPulseIxs = await makePulseHealthIx2(
25486
- program,
25487
- lendrAccountPk,
25488
- bankMap,
25489
- balances,
25490
- activeBalances.map((b) => b.bankPk),
25491
- [],
25492
- bankMetadataMap
25493
- );
25494
- const pythLut = crankPythIxs.lut ? [crankPythIxs.lut] : [];
25495
- const txs = [];
25496
- if (crankPythIxs.postInstructions.length > 0) {
25497
- txs.push(
25498
- ...splitInstructionsToFitTransactions(
25499
- [computeIx],
25500
- [
25501
- fundAccountIx,
25502
- ...crankPythIxs.postInstructions.map((ix) => ix.instruction),
25503
- ...crankPythIxs.closeInstructions.map((ix) => ix.instruction)
25504
- ],
25505
- {
25506
- blockhash,
25507
- payerKey: program.provider.publicKey,
25508
- luts: [...crankSwbIxs.luts, ...pythLut]
25509
- }
25510
- )
25511
- );
25322
+ static computeQuantityFromUsdValue(oraclePrice, usdValue, priceBias, weightedPrice) {
25323
+ const price = getPrice(oraclePrice, priceBias, weightedPrice);
25324
+ return usdValue.div(price);
25512
25325
  }
25513
- const messageV0 = new import_web325.TransactionMessage({
25514
- payerKey: program.provider.publicKey,
25515
- recentBlockhash: blockhash,
25516
- instructions: [...crankSwbIxs.instructions]
25517
- }).compileToV0Message([...crankSwbIxs.luts]);
25518
- const swbTx = new import_web325.VersionedTransaction(messageV0);
25519
- txs.push(swbTx);
25520
- const healthTx = new import_web325.TransactionMessage({
25521
- payerKey: program.provider.publicKey,
25522
- recentBlockhash: blockhash,
25523
- instructions: [...healthPulseIxs.instructions]
25524
- }).compileToV0Message([]);
25525
- const healthTxV0 = new import_web325.VersionedTransaction(healthTx);
25526
- txs.push(healthTxV0);
25527
- if (txs.length > 5) {
25528
- console.error("Too many transactions", txs.length);
25529
- throw new Error("Too many transactions");
25326
+ getTotalAssetQuantity() {
25327
+ return getTotalAssetQuantity(this);
25530
25328
  }
25531
- const simulationResult = await simulateBundle(program.provider.connection.rpcEndpoint, txs, [lendrAccountPk]);
25532
- const postExecutionAccount = simulationResult.find((result) => result.postExecutionAccounts.length > 0);
25533
- if (!postExecutionAccount) {
25534
- throw new Error("Account not found");
25329
+ getTotalLiabilityQuantity() {
25330
+ return getTotalLiabilityQuantity(this);
25535
25331
  }
25536
- const lendrAccountPost = LendrAccount.decodeAccountRaw(
25537
- Buffer.from(postExecutionAccount.postExecutionAccounts[0].data[0], "base64"),
25538
- program.idl
25539
- );
25540
- if (lendrAccountPost.healthCache.lndrErr || lendrAccountPost.healthCache.internalErr) {
25541
- console.log(
25542
- "cranked swb oracles",
25543
- staleSwbOracles.map((oracle) => oracle.oracleKey)
25544
- );
25545
- console.log("LendrAccountPost healthCache internalErr", lendrAccountPost.healthCache.internalErr);
25546
- console.log("LendrAccountPost healthCache lndrErr", lendrAccountPost.healthCache.lndrErr);
25547
- if (lendrAccountPost.healthCache.lndrErr === 6009) {
25548
- const assetValue = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.assetValue).isZero();
25549
- const liabilityValue = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.liabilityValue).isZero();
25550
- const assetValueEquity = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.assetValueEquity).isZero();
25551
- const liabilityValueEquity = !wrappedI80F48toBigNumber(
25552
- lendrAccountPost.healthCache.liabilityValueEquity
25553
- ).isZero();
25554
- const assetValueMaint = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.assetValueMaint).isZero();
25555
- const liabilityValueMaint = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.liabilityValueMaint).isZero();
25556
- if (assetValue && liabilityValue && assetValueEquity && liabilityValueEquity && assetValueMaint && liabilityValueMaint) {
25557
- return lendrAccountPost;
25558
- }
25559
- }
25560
- console.error("Account health cache simulation failed", {
25561
- lndrErr: lendrAccountPost.healthCache.lndrErr,
25562
- internalErr: lendrAccountPost.healthCache.internalErr
25563
- });
25564
- throw new HealthCacheSimulationError(
25565
- "Account health cache simulation failed",
25566
- lendrAccountPost.healthCache.lndrErr,
25567
- lendrAccountPost.healthCache.internalErr
25568
- );
25332
+ getAssetQuantity(assetShares) {
25333
+ return getAssetQuantity(this, assetShares);
25569
25334
  }
25570
- return lendrAccountPost;
25571
- }
25572
- async function makePulseHealthIx2(program, lendrAccountPk, banks, balances, mandatoryBanks, excludedBanks, bankMetadataMap) {
25573
- const healthAccounts = computeHealthCheckAccounts(balances, banks, mandatoryBanks, excludedBanks);
25574
- const accountMetas = computeHealthAccountMetas(healthAccounts, bankMetadataMap);
25575
- const ix = await instructions_default.makePulseHealthIx(
25576
- program,
25577
- {
25578
- lendrAccount: lendrAccountPk
25579
- },
25580
- accountMetas.map((account) => ({ pubkey: account, isSigner: false, isWritable: false }))
25581
- );
25582
- return { instructions: [ix], keys: [] };
25583
- }
25584
- async function createUpdateFeedIx(_props) {
25585
- throw new Error("in terms of switchboard, we have no switchboard");
25586
- }
25587
- async function createLendrAccountTx(props) {
25588
- const authority = props.lendrAccount?.authority ?? props.lendrClient.provider.publicKey;
25589
- const lendrAccountKeypair = import_web325.Keypair.generate();
25590
- const dummyWrappedI80F48 = bigNumberToWrappedI80F48(new import_bignumber12.default(0));
25591
- const dummyBalances = Array(15).fill({
25592
- active: false,
25593
- bankPk: new import_web325.PublicKey("11111111111111111111111111111111"),
25594
- assetShares: dummyWrappedI80F48,
25595
- liabilityShares: dummyWrappedI80F48,
25596
- emissionsOutstanding: dummyWrappedI80F48,
25597
- lastUpdate: new import_bn11.default(0)
25598
- });
25599
- const rawAccount = {
25600
- group: props.lendrClient.group.address,
25601
- authority,
25602
- lendingAccount: { balances: dummyBalances },
25603
- healthCache: {
25604
- assetValue: {
25605
- value: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
25606
- },
25607
- liabilityValue: {
25608
- value: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
25609
- },
25610
- timestamp: new import_bn11.default(0),
25611
- flags: 0,
25612
- prices: [],
25613
- assetValueMaint: bigNumberToWrappedI80F48(new import_bignumber12.default(0)),
25614
- liabilityValueMaint: bigNumberToWrappedI80F48(new import_bignumber12.default(0)),
25615
- assetValueEquity: bigNumberToWrappedI80F48(new import_bignumber12.default(0)),
25616
- liabilityValueEquity: bigNumberToWrappedI80F48(new import_bignumber12.default(0)),
25617
- errIndex: 0,
25618
- internalErr: 0,
25619
- internalBankruptcyErr: 0,
25620
- internalLiqErr: 0,
25621
- lndrErr: 0
25622
- },
25623
- emissionsDestinationAccount: new import_web325.PublicKey("11111111111111111111111111111111"),
25624
- accountFlags: new import_bn11.default([0, 0, 0])
25625
- };
25626
- const account = LendrAccount.fromAccountParsed(lendrAccountKeypair.publicKey, rawAccount);
25627
- const wrappedAccount = new LendrAccountWrapper(lendrAccountKeypair.publicKey, props.lendrClient, account);
25628
- return {
25629
- account: wrappedAccount,
25630
- tx: await props.lendrClient.createLendrAccountTx({ accountKeypair: lendrAccountKeypair })
25631
- };
25632
- }
25633
- function getActiveStaleBanks(balances, banks, additionalBanks, oraclePrices, maxAgeOffset = 0) {
25634
- const activeBanks = balances.filter((balance) => balance.active).map((balance) => banks.get(balance.bankPk.toBase58())).filter((bank) => !!bank);
25635
- const allBanks = [...activeBanks, ...additionalBanks];
25636
- const staleBanks = allBanks.filter((bank) => {
25637
- if (bank.config.oracleSetup === "SwitchboardPull" /* SwitchboardPull */ || bank.config.oracleSetup === "SwitchboardV2" /* SwitchboardV2 */ || bank.config.oracleSetup === "KaminoSwitchboardPull" /* KaminoSwitchboardPull */) {
25638
- return true;
25639
- }
25640
- const oraclePrice = oraclePrices.get(bank.address.toBase58());
25641
- const maxAge = bank.config.oracleMaxAge;
25642
- const currentTime = Math.round(Date.now() / 1e3);
25643
- const oracleTime = Math.round(oraclePrice?.timestamp ? oraclePrice.timestamp.toNumber() : Date.now());
25644
- const adjustedMaxAge = Math.max(maxAge - maxAgeOffset, 0);
25645
- const isStale = currentTime - oracleTime > adjustedMaxAge;
25646
- return isStale;
25647
- });
25648
- if (staleBanks.length > 0) {
25649
- const stalePythFeeds = [];
25650
- const staleSwbOracles = [];
25651
- const seenSwbOracles = /* @__PURE__ */ new Set();
25652
- const seenPythFeeds = /* @__PURE__ */ new Set();
25653
- staleBanks.forEach((bank) => {
25654
- if (bank.config.oracleSetup === "SwitchboardPull" /* SwitchboardPull */ || bank.config.oracleSetup === "KaminoSwitchboardPull" /* KaminoSwitchboardPull */) {
25655
- const key = bank.oracleKey.toBase58();
25656
- if (!seenSwbOracles.has(key)) {
25657
- seenSwbOracles.add(key);
25658
- staleSwbOracles.push({ oracleKey: bank.oracleKey });
25659
- }
25660
- } else if (bank.config.oracleSetup === "PythPushOracle" /* PythPushOracle */ || bank.config.oracleSetup === "StakedWithPythPush" /* StakedWithPythPush */ || bank.config.oracleSetup === "KaminoPythPush" /* KaminoPythPush */) {
25661
- const oraclePrice = oraclePrices.get(bank.address.toBase58());
25662
- const shardId = oraclePrice?.pythShardId ?? 0;
25663
- const feedId = bank.config.oracleKeys[0];
25664
- const feedKey = feedIdToString(feedId);
25665
- if (!seenPythFeeds.has(feedKey)) {
25666
- seenPythFeeds.add(feedKey);
25667
- stalePythFeeds.push({ feedId: feedKey, shardId });
25668
- }
25669
- }
25335
+ getLiabilityQuantity(liabilityShares) {
25336
+ return getLiabilityQuantity(this, liabilityShares);
25337
+ }
25338
+ getAssetShares(assetQuantity) {
25339
+ return getAssetShares(this, assetQuantity);
25340
+ }
25341
+ getLiabilityShares(liabilityQuantity) {
25342
+ return getLiabilityShares(this, liabilityQuantity);
25343
+ }
25344
+ computeAssetUsdValue(oraclePrice, assetShares, lendrRequirementType, priceBias) {
25345
+ return computeAssetUsdValue(this, oraclePrice, assetShares, lendrRequirementType, priceBias);
25346
+ }
25347
+ computeLiabilityUsdValue(oraclePrice, liabilityShares, lendrRequirementType, priceBias) {
25348
+ return computeLiabilityUsdValue(this, oraclePrice, liabilityShares, lendrRequirementType, priceBias);
25349
+ }
25350
+ computeUsdValue(oraclePrice, quantity, priceBias, weightedPrice, weight, scaleToBase = true) {
25351
+ return computeUsdValue(this, oraclePrice, quantity, priceBias, weightedPrice, weight, scaleToBase);
25352
+ }
25353
+ getAssetWeight(lendrRequirementType, oraclePrice, ignoreSoftLimits = false, assetWeightInitOverride) {
25354
+ return getAssetWeight(this, lendrRequirementType, oraclePrice, {
25355
+ ignoreSoftLimits,
25356
+ assetWeightInitOverride
25670
25357
  });
25671
- return { stalePythFeeds, staleSwbOracles };
25672
25358
  }
25673
- return { stalePythFeeds: [], staleSwbOracles: [] };
25674
- }
25359
+ getLiabilityWeight(lendrRequirementType) {
25360
+ return getLiabilityWeight(this.config, lendrRequirementType);
25361
+ }
25362
+ computeTvl(oraclePrice) {
25363
+ return computeTvl(this, oraclePrice);
25364
+ }
25365
+ computeInterestRates() {
25366
+ return computeInterestRates(this);
25367
+ }
25368
+ computeBaseInterestRate() {
25369
+ return computeBaseInterestRate(this);
25370
+ }
25371
+ computeUtilizationRate() {
25372
+ return computeUtilizationRate(this);
25373
+ }
25374
+ computeRemainingCapacity() {
25375
+ return computeRemainingCapacity(this);
25376
+ }
25377
+ describe(oraclePrice) {
25378
+ return `
25379
+ Bank address: ${this.address.toBase58()}
25380
+ Mint: ${this.mint.toBase58()}, decimals: ${this.mintDecimals}
25675
25381
 
25676
- // src/services/group/group.service.ts
25677
- var import_spl_token5 = require("@solana/spl-token");
25678
- var import_web326 = require("@solana/web3.js");
25679
- var import_bn12 = __toESM(require("bn.js"), 1);
25680
- init_constants();
25681
- init_single_spl_pool();
25682
- async function makePoolConfigureBankIx2(program, bank, args) {
25683
- const ix = await instructions_default.makePoolConfigureBankIx(
25684
- program,
25685
- {
25686
- bank
25687
- },
25688
- { bankConfigOpt: args }
25689
- );
25690
- return {
25691
- instructions: [ix],
25692
- keys: []
25693
- };
25694
- }
25695
- async function makeAddPermissionlessStakedBankIx(program, group, voteAccountAddress, feePayer, pythOracle) {
25696
- const [settingsKey] = import_web326.PublicKey.findProgramAddressSync(
25697
- [Buffer.from("staked_settings", "utf-8"), group.toBuffer()],
25698
- program.programId
25699
- );
25700
- const poolAddress = findPoolAddress(voteAccountAddress);
25701
- const solPool = findPoolStakeAddress(poolAddress);
25702
- const lstMint = findPoolMintAddress(poolAddress);
25703
- const onRampAddress = findPoolOnRampAddress(poolAddress);
25704
- const keys = [
25705
- { pubkey: poolAddress, isSigner: false, isWritable: false },
25706
- { pubkey: onRampAddress, isSigner: false, isWritable: true },
25707
- { pubkey: solPool, isSigner: false, isWritable: false },
25708
- { pubkey: import_web326.SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
25709
- { pubkey: import_web326.SystemProgram.programId, isSigner: false, isWritable: false },
25710
- { pubkey: import_web326.StakeProgram.programId, isSigner: false, isWritable: false }
25711
- ];
25712
- const data = Buffer.from(Uint8Array.of(6));
25713
- const _onrampIx = new import_web326.TransactionInstruction({
25714
- keys,
25715
- programId: SINGLE_POOL_PROGRAM_ID,
25716
- data
25717
- });
25718
- const remainingKeys = [pythOracle, lstMint, solPool];
25719
- const ix = await instructions_default.makePoolAddPermissionlessStakedBankIx(
25720
- program,
25721
- {
25722
- stakedSettings: settingsKey,
25723
- feePayer,
25724
- bankMint: lstMint,
25725
- solPool,
25726
- stakePool: poolAddress
25727
- },
25728
- remainingKeys.map((key) => ({ pubkey: key, isSigner: false, isWritable: false })),
25729
- {
25730
- seed: new import_bn12.default(0)
25731
- }
25732
- );
25733
- return {
25734
- instructions: [ix],
25735
- keys: []
25736
- };
25737
- }
25738
- async function makePoolAddBankIx2(program, group, bank, feePayer, bankMint, bankConfig, tokenProgram = import_spl_token5.TOKEN_PROGRAM_ID, overrideOpt = {}) {
25739
- const rawBankConfig = serializeBankConfigOpt(bankConfig);
25740
- const rawBankConfigCompact = {
25741
- ...rawBankConfig,
25742
- oracleMaxAge: bankConfig.oracleMaxAge,
25743
- auto_padding_0: [0],
25744
- auto_padding_1: [0]
25745
- };
25746
- const ix = await instructions_default.makePoolAddBankIx(
25747
- program,
25748
- {
25749
- lendrGroup: group,
25750
- feePayer,
25751
- bankMint,
25752
- bank,
25753
- tokenProgram,
25754
- ...overrideOpt
25755
- // if two oracle keys: first is feed id, second is oracle key
25756
- },
25757
- {
25758
- bankConfig: rawBankConfigCompact
25759
- }
25760
- );
25761
- return {
25762
- instructions: [ix],
25763
- //ix
25764
- keys: []
25765
- };
25766
- }
25382
+ Total deposits: ${nativeToUi(this.getTotalAssetQuantity(), this.mintDecimals)}
25383
+ Total borrows: ${nativeToUi(this.getTotalLiabilityQuantity(), this.mintDecimals)}
25767
25384
 
25768
- // src/services/group/utils/deserialize.utils.ts
25769
- var import_web327 = require("@solana/web3.js");
25770
- function dtoToGroup(groupDto) {
25771
- return {
25772
- admin: new import_web327.PublicKey(groupDto.admin),
25773
- address: new import_web327.PublicKey(groupDto.address)
25774
- };
25775
- }
25385
+ Total assets (USD value): ${this.computeAssetUsdValue(
25386
+ oraclePrice,
25387
+ this.totalAssetShares,
25388
+ 2 /* Equity */,
25389
+ 1 /* None */
25390
+ )}
25391
+ Total liabilities (USD value): ${this.computeLiabilityUsdValue(
25392
+ oraclePrice,
25393
+ this.totalLiabilityShares,
25394
+ 2 /* Equity */,
25395
+ 1 /* None */
25396
+ )}
25776
25397
 
25777
- // src/services/group/utils/serialize.utils.ts
25778
- function groupToDto(group) {
25779
- return {
25780
- admin: group.admin.toBase58(),
25781
- address: group.address.toBase58()
25782
- };
25783
- }
25398
+ Asset price (USD): ${_Bank.getPrice(oraclePrice, 1 /* None */, false)}
25399
+ Asset price Weighted (USD): ${_Bank.getPrice(oraclePrice, 1 /* None */, true)}
25784
25400
 
25785
- // src/services/native-stake/utils/deserialize.utils.ts
25786
- var import_web328 = require("@solana/web3.js");
25787
- function dtoToValidatorStakeGroup(validatorStakeGroupDto) {
25788
- return {
25789
- validator: new import_web328.PublicKey(validatorStakeGroupDto.validator),
25790
- poolKey: new import_web328.PublicKey(validatorStakeGroupDto.poolKey),
25791
- poolMintKey: new import_web328.PublicKey(validatorStakeGroupDto.poolMintKey),
25792
- totalStake: validatorStakeGroupDto.totalStake,
25793
- selectedAccount: {
25794
- pubkey: new import_web328.PublicKey(validatorStakeGroupDto.selectedAccount.pubkey),
25795
- amount: validatorStakeGroupDto.selectedAccount.amount
25796
- },
25797
- accounts: validatorStakeGroupDto.accounts.map((account) => ({
25798
- pubkey: new import_web328.PublicKey(account.pubkey),
25799
- amount: account.amount
25800
- }))
25801
- };
25802
- }
25401
+ Config:
25402
+ - Asset weight init: ${this.config.assetWeightInit.toFixed(2)}
25403
+ - Asset weight maint: ${this.config.assetWeightMaint.toFixed(2)}
25404
+ - Liability weight init: ${this.config.liabilityWeightInit.toFixed(2)}
25405
+ - Liability weight maint: ${this.config.liabilityWeightMaint.toFixed(2)}
25803
25406
 
25804
- // src/services/native-stake/utils/fetch.utils.ts
25805
- var import_web329 = require("@solana/web3.js");
25806
- init_constants();
25807
- init_single_spl_pool();
25808
- var fetchNativeStakeAccounts = async (connection, publicKey3, opts = {
25809
- filterInactive: true
25810
- }) => {
25811
- if (!connection || !publicKey3) {
25812
- throw new Error("Invalid connection or public key");
25407
+ - Deposit limit: ${this.config.depositLimit}
25408
+ - Borrow limit: ${this.config.borrowLimit}
25409
+
25410
+ LTVs:
25411
+ - Initial: ${new import_bignumber12.default(1).div(this.config.liabilityWeightInit).times(100).toFixed(2)}%
25412
+ - Maintenance: ${new import_bignumber12.default(1).div(this.config.liabilityWeightMaint).times(100).toFixed(2)}%
25413
+ `;
25813
25414
  }
25814
- try {
25815
- const epochInfo = await connection.getEpochInfo();
25816
- const accounts = await connection.getParsedProgramAccounts(import_web329.StakeProgram.programId, {
25817
- filters: [
25818
- {
25819
- memcmp: {
25820
- offset: 12,
25821
- bytes: publicKey3.toBase58()
25822
- }
25823
- }
25824
- ]
25825
- });
25826
- const validatorMap = /* @__PURE__ */ new Map();
25827
- await Promise.all(
25828
- accounts.map(async (acc) => {
25829
- const parsedAccount = acc.account.data;
25830
- const stakeInfo = parsedAccount.parsed.info;
25831
- if (!stakeInfo.stake?.delegation || opts.filterInactive && (Number(stakeInfo.stake.delegation.activationEpoch) >= epochInfo.epoch || stakeInfo.stake.delegation.deactivationEpoch !== MAX_U64)) {
25832
- return;
25833
- }
25834
- const validatorAddress = stakeInfo.stake.delegation.voter;
25835
- const accountPubkey = acc.pubkey;
25836
- const amount = Number(stakeInfo.stake.delegation.stake) / import_web329.LAMPORTS_PER_SOL;
25837
- const existingAccounts = validatorMap.get(validatorAddress) || [];
25838
- validatorMap.set(validatorAddress, [...existingAccounts, { pubkey: accountPubkey, amount }]);
25839
- })
25840
- );
25841
- return Promise.all(
25842
- Array.from(validatorMap.entries()).map(async ([validatorAddress, accounts2]) => {
25843
- const poolKey = findPoolAddress(new import_web329.PublicKey(validatorAddress));
25844
- const poolMintKey = findPoolMintAddress(poolKey);
25845
- const totalStake = accounts2.reduce((acc, curr) => acc + curr.amount, 0);
25846
- const largestAccount = accounts2.reduce((acc, curr) => acc.amount > curr.amount ? acc : curr);
25847
- const sortedAccounts = accounts2.sort((a, b) => b.amount - a.amount);
25848
- if (!sortedAccounts[0].pubkey.equals(largestAccount.pubkey)) {
25849
- sortedAccounts.unshift(sortedAccounts.splice(sortedAccounts.indexOf(largestAccount), 1)[0]);
25850
- }
25851
- return {
25852
- validator: new import_web329.PublicKey(validatorAddress),
25853
- poolKey,
25854
- poolMintKey,
25855
- accounts: sortedAccounts,
25856
- totalStake,
25857
- selectedAccount: largestAccount
25858
- };
25859
- })
25415
+ };
25416
+ var BankConfig = class _BankConfig {
25417
+ constructor(assetWeightInit, assetWeightMaint, liabilityWeightInit, liabilityWeightMaint, depositLimit, borrowLimit, riskTier, totalAssetValueInitLimit, assetTag, oracleSetup, oracleKeys, oracleMaxAge, interestRateConfig, operationalState, oracleMaxConfidence, fixedPrice, configFlags) {
25418
+ this.assetWeightInit = assetWeightInit;
25419
+ this.assetWeightMaint = assetWeightMaint;
25420
+ this.liabilityWeightInit = liabilityWeightInit;
25421
+ this.liabilityWeightMaint = liabilityWeightMaint;
25422
+ this.depositLimit = depositLimit;
25423
+ this.borrowLimit = borrowLimit;
25424
+ this.riskTier = riskTier;
25425
+ this.totalAssetValueInitLimit = totalAssetValueInitLimit;
25426
+ this.assetTag = assetTag;
25427
+ this.oracleSetup = oracleSetup;
25428
+ this.oracleKeys = oracleKeys;
25429
+ this.oracleMaxAge = oracleMaxAge;
25430
+ this.interestRateConfig = interestRateConfig;
25431
+ this.operationalState = operationalState;
25432
+ this.oracleMaxConfidence = oracleMaxConfidence;
25433
+ this.fixedPrice = fixedPrice;
25434
+ this.configFlags = configFlags;
25435
+ }
25436
+ static fromAccountParsed(bankConfigRaw) {
25437
+ const bankConfig = parseBankConfigRaw(bankConfigRaw);
25438
+ return new _BankConfig(
25439
+ bankConfig.assetWeightInit,
25440
+ bankConfig.assetWeightMaint,
25441
+ bankConfig.liabilityWeightInit,
25442
+ bankConfig.liabilityWeightMaint,
25443
+ bankConfig.depositLimit,
25444
+ bankConfig.borrowLimit,
25445
+ bankConfig.riskTier,
25446
+ bankConfig.totalAssetValueInitLimit,
25447
+ bankConfig.assetTag,
25448
+ bankConfig.oracleSetup,
25449
+ bankConfig.oracleKeys,
25450
+ bankConfig.oracleMaxAge,
25451
+ bankConfig.interestRateConfig,
25452
+ bankConfig.operationalState,
25453
+ bankConfig.oracleMaxConfidence,
25454
+ bankConfig.fixedPrice,
25455
+ bankConfig.configFlags
25860
25456
  );
25861
- } catch (e) {
25862
- console.error("Error getting stake accounts", e);
25863
- return [];
25864
25457
  }
25865
25458
  };
25866
- var fetchStakePoolActiveStates = async (connection, validatorVoteAccounts) => {
25867
- const currentEpoch = await connection.getEpochInfo();
25868
- const activeStates = /* @__PURE__ */ new Map();
25869
- const poolMintAddressRecord = {};
25870
- const poolStakeAddressRecord = {};
25871
- validatorVoteAccounts.forEach((validatorVoteAccount) => {
25872
- const poolAddress = findPoolAddress(validatorVoteAccount);
25873
- const poolStakeAddress = findPoolStakeAddress(poolAddress);
25874
- const poolMintAddress = findPoolMintAddress(poolAddress);
25875
- poolMintAddressRecord[validatorVoteAccount.toBase58()] = poolMintAddress;
25876
- poolStakeAddressRecord[poolStakeAddress.toBase58()] = validatorVoteAccount;
25877
- });
25878
- const poolStakeAddressKeys = Object.keys(poolStakeAddressRecord);
25879
- const poolStakeAccounts = Object.fromEntries(
25880
- (await chunkedGetRawMultipleAccountInfoOrdered(connection, poolStakeAddressKeys)).map((ai, index) => [
25881
- poolStakeAddressRecord[poolStakeAddressKeys[index]],
25882
- ai?.data || null
25883
- ])
25459
+
25460
+ // src/services/account/utils/emode.utils.ts
25461
+ function computeEmodeImpacts(emodePairs, activeLiabilities, activeCollateral, allBanks) {
25462
+ const toKey = (k) => k.toBase58();
25463
+ const basePairs = computeActiveEmodePairs(emodePairs, activeLiabilities, activeCollateral);
25464
+ const baseOn = basePairs.length > 0;
25465
+ const liabTagMap = /* @__PURE__ */ new Map();
25466
+ for (const p of emodePairs) {
25467
+ liabTagMap.set(p.liabilityBank.toBase58(), p.liabilityBankTag.toString());
25468
+ }
25469
+ const existingTags = new Set(
25470
+ activeLiabilities.map((l) => liabTagMap.get(l.toBase58())).filter((t) => !!t)
25884
25471
  );
25885
- validatorVoteAccounts.forEach((validatorVoteAccount) => {
25886
- const stakeAccount = fetchStakeAccount(poolStakeAccounts[validatorVoteAccount.toBase58()]);
25887
- const poolMintAddress = poolMintAddressRecord[validatorVoteAccount.toBase58()];
25888
- if (!stakeAccount) {
25889
- activeStates.set(poolMintAddress.toBase58(), false);
25890
- return;
25472
+ function minWeight(ps) {
25473
+ let m = ps[0].assetWeightInit;
25474
+ for (const x of ps) if (x.assetWeightInit.lt(m)) m = x.assetWeightInit;
25475
+ return m;
25476
+ }
25477
+ function diffState(before, after) {
25478
+ const was = before.length > 0, isOn = after.length > 0;
25479
+ if (!was && !isOn) return 5 /* InactiveEmode */;
25480
+ if (!was && isOn) return 0 /* ActivateEmode */;
25481
+ if (was && !isOn) return 4 /* RemoveEmode */;
25482
+ const bMin = minWeight(before), aMin = minWeight(after);
25483
+ if (aMin.gt(bMin)) return 2 /* IncreaseEmode */;
25484
+ if (aMin.lt(bMin)) return 3 /* ReduceEmode */;
25485
+ return 1 /* ExtendEmode */;
25486
+ }
25487
+ function simulate(bank, action) {
25488
+ let L = [...activeLiabilities], C = [...activeCollateral];
25489
+ switch (action) {
25490
+ case "borrow":
25491
+ if (!L.some((x) => x.equals(bank))) L.push(bank);
25492
+ break;
25493
+ case "repay":
25494
+ L = L.filter((x) => !x.equals(bank));
25495
+ break;
25496
+ case "supply":
25497
+ if (!C.some((x) => x.equals(bank))) C.push(bank);
25498
+ break;
25499
+ case "withdraw":
25500
+ C = C.filter((x) => !x.equals(bank));
25501
+ break;
25891
25502
  }
25892
- if (!stakeAccount.stake?.delegation) {
25893
- activeStates.set(poolMintAddress.toBase58(), false);
25894
- return;
25503
+ const after = computeActiveEmodePairs(emodePairs, L, C);
25504
+ let status = diffState(basePairs, after);
25505
+ if (action === "borrow") {
25506
+ const tag = liabTagMap.get(bank.toBase58());
25507
+ if (!tag) {
25508
+ status = baseOn ? 4 /* RemoveEmode */ : 5 /* InactiveEmode */;
25509
+ } else if (baseOn) {
25510
+ if (after.length === 0) {
25511
+ status = 4 /* RemoveEmode */;
25512
+ } else if (existingTags.has(tag)) {
25513
+ status = 1 /* ExtendEmode */;
25514
+ }
25515
+ }
25895
25516
  }
25896
- const activationEpoch = stakeAccount.stake.delegation.activationEpoch;
25897
- const isActive = currentEpoch.epoch > Number(activationEpoch);
25898
- activeStates.set(validatorVoteAccount.toBase58(), isActive);
25899
- });
25900
- return activeStates;
25901
- };
25902
- var fetchStakeAccount = (data) => {
25903
- let offset = 0;
25904
- const discriminant = data.readUInt32LE(offset);
25905
- offset += 4;
25906
- const rentExemptReserve = data.readBigUInt64LE(offset);
25907
- offset += 8;
25908
- const staker = new import_web329.PublicKey(data.subarray(offset, offset + 32));
25909
- offset += 32;
25910
- const withdrawer = new import_web329.PublicKey(data.subarray(offset, offset + 32));
25911
- offset += 32;
25912
- const unixTimestamp = data.readBigUInt64LE(offset);
25913
- offset += 8;
25914
- const epoch = data.readBigUInt64LE(offset);
25915
- offset += 8;
25916
- const custodian = new import_web329.PublicKey(data.subarray(offset, offset + 32));
25917
- offset += 32;
25918
- const voterPubkey = new import_web329.PublicKey(data.subarray(offset, offset + 32));
25919
- offset += 32;
25920
- const stake = data.readBigUInt64LE(offset);
25921
- offset += 8;
25922
- const activationEpoch = data.readBigUInt64LE(offset);
25923
- offset += 8;
25924
- const deactivationEpoch = data.readBigUInt64LE(offset);
25925
- offset += 8;
25926
- const creditsObserved = data.readBigUInt64LE(offset);
25927
- return {
25928
- discriminant,
25929
- meta: {
25930
- rentExemptReserve,
25931
- authorized: {
25932
- staker,
25933
- withdrawer
25934
- },
25935
- lockup: {
25936
- unixTimestamp,
25937
- epoch,
25938
- custodian
25517
+ if (action === "supply") {
25518
+ const isOn = after.length > 0;
25519
+ status = !baseOn && isOn ? 0 /* ActivateEmode */ : baseOn && isOn ? 1 /* ExtendEmode */ : 5 /* InactiveEmode */;
25520
+ }
25521
+ if (action === "withdraw") {
25522
+ if (!baseOn) {
25523
+ status = 5 /* InactiveEmode */;
25524
+ } else if (after.length === 0) {
25525
+ status = 4 /* RemoveEmode */;
25526
+ } else {
25527
+ const b = minWeight(basePairs), a = minWeight(after);
25528
+ if (a.gt(b)) status = 2 /* IncreaseEmode */;
25529
+ else if (a.lt(b)) status = 3 /* ReduceEmode */;
25530
+ else status = 1 /* ExtendEmode */;
25939
25531
  }
25940
- },
25941
- stake: {
25942
- delegation: {
25943
- voterPubkey,
25944
- stake,
25945
- activationEpoch,
25946
- deactivationEpoch
25947
- },
25948
- creditsObserved
25949
25532
  }
25950
- };
25951
- };
25952
- var fetchStakePoolMev = async (connection, validatorVoteAccounts) => {
25953
- const poolAddressRecord = {};
25954
- const poolStakeAddressRecord = {};
25955
- const onRampAddressRecord = {};
25956
- const mev = /* @__PURE__ */ new Map();
25957
- validatorVoteAccounts.forEach((validatorVoteAccount) => {
25958
- const poolAddress = findPoolAddress(validatorVoteAccount);
25959
- const poolStakeAddress = findPoolStakeAddress(poolAddress);
25960
- const onRampAddress = findPoolOnRampAddress(poolAddress);
25961
- poolAddressRecord[validatorVoteAccount.toBase58()] = poolAddress;
25962
- poolStakeAddressRecord[validatorVoteAccount.toBase58()] = poolStakeAddress;
25963
- onRampAddressRecord[validatorVoteAccount.toBase58()] = onRampAddress;
25964
- });
25965
- const poolStakeAddresses = validatorVoteAccounts.map(
25966
- (validatorVoteAccount) => poolStakeAddressRecord[validatorVoteAccount.toBase58()]
25533
+ let bestPair;
25534
+ if (after.length > 0) {
25535
+ bestPair = after[0];
25536
+ for (const p of after) {
25537
+ if (p.assetWeightInit.lt(bestPair.assetWeightInit)) {
25538
+ bestPair = p;
25539
+ }
25540
+ }
25541
+ }
25542
+ const activeEmodePair = bestPair ? {
25543
+ collateralBanks: Array.from(
25544
+ new Map(after.flatMap((p) => p.collateralBanks).map((bank2) => [bank2.toBase58(), bank2])).values()
25545
+ ),
25546
+ collateralBankTags: Array.from(new Set(after.flatMap((p) => p.collateralBankTag))),
25547
+ liabilityBanks: Array.from(
25548
+ new Map(after.flatMap((p) => p.liabilityBank).map((bank2) => [bank2.toBase58(), bank2])).values()
25549
+ ),
25550
+ liabilityBankTags: Array.from(new Set(after.flatMap((p) => p.liabilityBankTag))),
25551
+ assetWeightMaint: bestPair.assetWeightMaint,
25552
+ assetWeightInit: bestPair.assetWeightInit
25553
+ } : void 0;
25554
+ return {
25555
+ status,
25556
+ resultingPairs: after,
25557
+ activePair: activeEmodePair
25558
+ };
25559
+ }
25560
+ const result = {};
25561
+ for (const bank of allBanks) {
25562
+ const key = toKey(bank);
25563
+ const impact = {};
25564
+ if (!activeCollateral.some((x) => x.equals(bank))) {
25565
+ impact.borrowImpact = simulate(bank, "borrow");
25566
+ }
25567
+ const collSet = new Set(emodePairs.flatMap((p) => p.collateralBanks.map((c) => c.toBase58())));
25568
+ if (collSet.has(key) && !activeCollateral.some((x) => x.equals(bank)) && !activeLiabilities.some((x) => x.equals(bank))) {
25569
+ impact.supplyImpact = simulate(bank, "supply");
25570
+ }
25571
+ if (activeLiabilities.some((x) => x.equals(bank))) {
25572
+ impact.repayAllImpact = simulate(bank, "repay");
25573
+ }
25574
+ if (activeCollateral.some((x) => x.equals(bank))) {
25575
+ impact.withdrawAllImpact = simulate(bank, "withdraw");
25576
+ }
25577
+ result[key] = impact;
25578
+ }
25579
+ return result;
25580
+ }
25581
+ function computeActiveEmodePairs(emodePairs, activeLiabilities, activeCollateral) {
25582
+ const configured = emodePairs.filter((p) => p.collateralBankTag !== EmodeTag.UNSET);
25583
+ const liabTagByBank = /* @__PURE__ */ new Map();
25584
+ for (const p of configured) {
25585
+ liabTagByBank.set(p.liabilityBank.toBase58(), p.liabilityBankTag.toString());
25586
+ }
25587
+ const requiredTags = /* @__PURE__ */ new Set();
25588
+ for (const liab of activeLiabilities) {
25589
+ const tag = liabTagByBank.get(liab.toBase58());
25590
+ if (!tag) {
25591
+ return [];
25592
+ }
25593
+ requiredTags.add(tag);
25594
+ }
25595
+ const possible = configured.filter(
25596
+ (p) => activeLiabilities.some((l) => l.equals(p.liabilityBank)) && p.collateralBanks.some((c) => activeCollateral.some((a) => a.equals(c)))
25967
25597
  );
25968
- const onRampAddresses = validatorVoteAccounts.map(
25969
- (validatorVoteAccount) => onRampAddressRecord[validatorVoteAccount.toBase58()]
25598
+ if (possible.length === 0) return [];
25599
+ const byCollTag = {};
25600
+ for (const p of possible) {
25601
+ const ct = p.collateralBankTag.toString();
25602
+ if (!byCollTag[ct]) {
25603
+ byCollTag[ct] = [];
25604
+ }
25605
+ byCollTag[ct].push(p);
25606
+ }
25607
+ const validGroups = [];
25608
+ for (const group of Object.values(byCollTag)) {
25609
+ const supports = new Set(group.map((p) => p.liabilityBankTag.toString()));
25610
+ let coversAll = true;
25611
+ for (const rt of requiredTags) {
25612
+ if (!supports.has(rt)) {
25613
+ coversAll = false;
25614
+ break;
25615
+ }
25616
+ }
25617
+ if (coversAll) {
25618
+ validGroups.push(group);
25619
+ }
25620
+ }
25621
+ if (validGroups.length === 0) return [];
25622
+ return validGroups.flat();
25623
+ }
25624
+ function getEmodePairs(banks) {
25625
+ return banks.filter(
25626
+ (b) => b.emode.emodeTag !== EmodeTag.UNSET || b.emode.emodeEntries.some((e) => e.collateralBankEmodeTag !== 0)
25627
+ ).flatMap(
25628
+ (bank) => bank.emode.emodeEntries.map((entry) => ({
25629
+ collateralBanks: banks.filter((b) => b.emode.emodeTag === entry.collateralBankEmodeTag && !b.address.equals(bank.address)).map((b) => b.address),
25630
+ collateralBankTag: entry.collateralBankEmodeTag,
25631
+ liabilityBank: bank.address,
25632
+ liabilityBankTag: bank.emode.emodeTag,
25633
+ assetWeightMaint: entry.assetWeightMaint,
25634
+ assetWeightInit: entry.assetWeightInit
25635
+ })).filter((pair) => pair.collateralBanks.length > 0)
25970
25636
  );
25971
- const allAddresses = [...poolStakeAddresses, ...onRampAddresses].map((address) => address.toBase58());
25972
- return chunkedGetRawMultipleAccountInfoOrdered(connection, allAddresses).then((accountInfos) => {
25973
- const poolStakeInfos = accountInfos.slice(0, poolStakeAddresses.length);
25974
- const onRampInfos = accountInfos.slice(poolStakeAddresses.length);
25975
- const rent = 2282280;
25976
- validatorVoteAccounts.forEach((validatorVoteAccount, index) => {
25977
- const poolStakeInfo = poolStakeInfos[index];
25978
- const onRampInfo = onRampInfos[index];
25979
- if (poolStakeInfo && onRampInfo) {
25980
- const stakeDecoded = fetchStakeAccount(poolStakeInfo.data);
25981
- const onrampDecoded = fetchStakeAccount(onRampInfo.data);
25982
- const poolLamps = poolStakeInfo.lamports - rent - Number(stakeDecoded.stake.delegation.stake.toString());
25983
- const onrampStake = Number(onrampDecoded.stake.delegation.stake.toString());
25984
- mev.set(validatorVoteAccount.toBase58(), {
25985
- pool: poolLamps >= 1e3 ? poolLamps : 0,
25986
- onramp: onrampStake
25637
+ }
25638
+ function adjustBanksWithEmode(banks, emodePairs) {
25639
+ const originalAssetWeightsMap = /* @__PURE__ */ new Map();
25640
+ if (emodePairs.length === 0) {
25641
+ return { adjustedBanks: banks, originalAssetWeightsMap };
25642
+ }
25643
+ const lowestWeights = /* @__PURE__ */ new Map();
25644
+ for (const pair of emodePairs) {
25645
+ for (const collateralBankPk of pair.collateralBanks) {
25646
+ const bankPkStr = collateralBankPk.toString();
25647
+ const current = lowestWeights.get(bankPkStr);
25648
+ if (!current) {
25649
+ lowestWeights.set(bankPkStr, {
25650
+ assetWeightMaint: pair.assetWeightMaint,
25651
+ assetWeightInit: pair.assetWeightInit
25987
25652
  });
25653
+ continue;
25988
25654
  }
25655
+ lowestWeights.set(bankPkStr, {
25656
+ assetWeightMaint: import_bignumber13.default.min(current.assetWeightMaint, pair.assetWeightMaint),
25657
+ assetWeightInit: import_bignumber13.default.min(current.assetWeightInit, pair.assetWeightInit)
25658
+ });
25659
+ }
25660
+ }
25661
+ const adjustedBanks = banks.map((bank) => {
25662
+ const bankPkStr = bank.address.toString();
25663
+ const lowestWeight = lowestWeights.get(bankPkStr);
25664
+ if (!lowestWeight) return bank;
25665
+ originalAssetWeightsMap.set(bankPkStr, {
25666
+ assetWeightMaint: bank.config.assetWeightMaint,
25667
+ assetWeightInit: bank.config.assetWeightInit
25989
25668
  });
25990
- return mev;
25669
+ return Bank.withEmodeWeights(bank, {
25670
+ assetWeightMaint: import_bignumber13.default.max(lowestWeight.assetWeightMaint, bank.config.assetWeightMaint),
25671
+ assetWeightInit: import_bignumber13.default.max(lowestWeight.assetWeightInit, bank.config.assetWeightInit)
25672
+ });
25673
+ });
25674
+ return { adjustedBanks, originalAssetWeightsMap };
25675
+ }
25676
+ function makeEmodeAssetWeights(bank, pair) {
25677
+ if (!pair) return void 0;
25678
+ return {
25679
+ assetWeightInit: import_bignumber13.default.max(pair.assetWeightInit, bank.config.assetWeightInit),
25680
+ assetWeightMaint: import_bignumber13.default.max(pair.assetWeightMaint, bank.config.assetWeightMaint),
25681
+ collateralTags: "collateralBankTags" in pair ? pair.collateralBankTags : [pair.collateralBankTag]
25682
+ };
25683
+ }
25684
+
25685
+ // src/services/account/utils/fetch.utils.ts
25686
+ var fetchLendrAccountAddresses = async (program, authority, group) => {
25687
+ const lendrAccounts = (await program.account.lendrAccount.all([
25688
+ {
25689
+ memcmp: {
25690
+ bytes: group.toBase58(),
25691
+ offset: 8
25692
+ // lendrGroup is the first field in the account, so only offset is the discriminant
25693
+ }
25694
+ },
25695
+ {
25696
+ memcmp: {
25697
+ bytes: authority.toBase58(),
25698
+ offset: 8 + 32
25699
+ // authority is the second field in the account after the authority, so offset by the discriminant and a pubkey
25700
+ }
25701
+ }
25702
+ ])).map((a) => a.publicKey);
25703
+ return lendrAccounts;
25704
+ };
25705
+ var fetchLendrAccountData = async (program, lendrAccountPk, bankMap, oraclePrices, bankMetadataMap) => {
25706
+ const lendrAccountRaw = await program.account.lendrAccount.fetch(lendrAccountPk, "confirmed");
25707
+ const lendrAccount = LendrAccount.fromAccountParsed(lendrAccountPk, lendrAccountRaw);
25708
+ const lendrAccountWithCache = await simulateAccountHealthCacheWithFallback({
25709
+ program,
25710
+ lendrAccount,
25711
+ bankMap,
25712
+ oraclePrices,
25713
+ bankMetadataMap,
25714
+ balances: lendrAccount.balances
25991
25715
  });
25716
+ return lendrAccountWithCache;
25992
25717
  };
25993
25718
 
25994
- // src/services/native-stake/utils/serialize.utils.ts
25995
- function validatorStakeGroupToDto(validatorStakeGroup) {
25719
+ // src/services/account/utils/serialize.utils.ts
25720
+ var import_bn10 = __toESM(require("bn.js"), 1);
25721
+ function accountFlagToBN(flag) {
25722
+ return new import_bn10.default(flag);
25723
+ }
25724
+ function lendrAccountToDto(lendrAccount) {
25996
25725
  return {
25997
- validator: validatorStakeGroup.validator.toBase58(),
25998
- poolKey: validatorStakeGroup.poolKey.toBase58(),
25999
- poolMintKey: validatorStakeGroup.poolMintKey.toBase58(),
26000
- totalStake: validatorStakeGroup.totalStake,
26001
- selectedAccount: {
26002
- pubkey: validatorStakeGroup.selectedAccount.pubkey.toBase58(),
26003
- amount: validatorStakeGroup.selectedAccount.amount
26004
- },
26005
- accounts: validatorStakeGroup.accounts.map((account) => ({
26006
- pubkey: account.pubkey.toBase58(),
26007
- amount: account.amount
26008
- }))
25726
+ address: lendrAccount.address.toBase58(),
25727
+ group: lendrAccount.group.toBase58(),
25728
+ authority: lendrAccount.authority.toBase58(),
25729
+ balances: lendrAccount.balances.map(balanceToDto),
25730
+ accountFlags: lendrAccount.accountFlags,
25731
+ emissionsDestinationAccount: lendrAccount.emissionsDestinationAccount.toBase58(),
25732
+ healthCache: healthCacheToDto(lendrAccount.healthCache)
25733
+ };
25734
+ }
25735
+ function balanceToDto(balance) {
25736
+ return {
25737
+ active: balance.active,
25738
+ bankPk: balance.bankPk.toBase58(),
25739
+ assetShares: balance.assetShares.toString(),
25740
+ liabilityShares: balance.liabilityShares.toString(),
25741
+ emissionsOutstanding: balance.emissionsOutstanding.toString(),
25742
+ lastUpdate: balance.lastUpdate
25743
+ };
25744
+ }
25745
+ function healthCacheToDto(healthCache) {
25746
+ return {
25747
+ assetValue: healthCache.assetValue.toString(),
25748
+ liabilityValue: healthCache.liabilityValue.toString(),
25749
+ assetValueMaint: healthCache.assetValueMaint.toString(),
25750
+ liabilityValueMaint: healthCache.liabilityValueMaint.toString(),
25751
+ assetValueEquity: healthCache.assetValueEquity.toString(),
25752
+ liabilityValueEquity: healthCache.liabilityValueEquity.toString(),
25753
+ timestamp: healthCache.timestamp.toString(),
25754
+ flags: healthCache.flags,
25755
+ prices: healthCache.prices,
25756
+ simulationFailed: healthCache.simulationFailed
26009
25757
  };
26010
25758
  }
26011
25759
 
26012
- // src/models/bank.ts
26013
- var import_bignumber13 = __toESM(require("bignumber.js"), 1);
26014
- var SECONDS_PER_DAY2 = 24 * 60 * 60;
26015
- var _SECONDS_PER_YEAR = SECONDS_PER_DAY2 * 365.25;
26016
- var Bank = class _Bank {
26017
- 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) {
26018
- this.address = address;
26019
- this.mint = mint;
26020
- this.mintDecimals = mintDecimals;
26021
- this.group = group;
26022
- this.mintRate = mintRate;
26023
- this.mintPrice = mintPrice;
26024
- this.assetShareValue = assetShareValue;
26025
- this.liabilityShareValue = liabilityShareValue;
26026
- this.liquidityVault = liquidityVault;
26027
- this.liquidityVaultBump = liquidityVaultBump;
26028
- this.liquidityVaultAuthorityBump = liquidityVaultAuthorityBump;
26029
- this.insuranceVault = insuranceVault;
26030
- this.insuranceVaultBump = insuranceVaultBump;
26031
- this.insuranceVaultAuthorityBump = insuranceVaultAuthorityBump;
26032
- this.collectedInsuranceFeesOutstanding = collectedInsuranceFeesOutstanding;
26033
- this.feeVault = feeVault;
26034
- this.feeVaultBump = feeVaultBump;
26035
- this.feeVaultAuthorityBump = feeVaultAuthorityBump;
26036
- this.collectedGroupFeesOutstanding = collectedGroupFeesOutstanding;
26037
- this.lastUpdate = lastUpdate;
26038
- this.config = config;
26039
- this.totalAssetShares = totalAssetShares;
26040
- this.totalLiabilityShares = totalLiabilityShares;
26041
- this.flags = flags;
26042
- this.emissionsActiveBorrowing = emissionsActiveBorrowing;
26043
- this.emissionsActiveLending = emissionsActiveLending;
26044
- this.emissionsRate = emissionsRate;
26045
- this.emissionsMint = emissionsMint;
26046
- this.emissionsRemaining = emissionsRemaining;
26047
- this.oracleKey = oracleKey;
26048
- this.emode = emode;
26049
- this.feesDestinationAccount = feesDestinationAccount;
26050
- this.lendingPositionCount = lendingPositionCount;
26051
- this.borrowingPositionCount = borrowingPositionCount;
26052
- this.pythShardId = pythShardId;
26053
- this.tokenSymbol = tokenSymbol;
26054
- this.extendedMetadata = extendedMetadata;
26055
- this.owner = owner;
26056
- }
26057
- static decodeBankRaw(encoded, idl) {
26058
- return decodeBankRaw(encoded, idl);
26059
- }
26060
- static fromBuffer(bankPk, rawData, idl, feedIdMap) {
26061
- const accountParsed = _Bank.decodeBankRaw(rawData, idl);
26062
- return _Bank.fromAccountParsed(bankPk, accountParsed, feedIdMap);
25760
+ // src/services/account/account.service.ts
25761
+ var HealthCacheSimulationError = class _HealthCacheSimulationError extends Error {
25762
+ lndrErr;
25763
+ internalErr;
25764
+ constructor(message, lndrErr, internalErr) {
25765
+ super(message);
25766
+ this.name = "HealthCacheSimulationError";
25767
+ this.lndrErr = lndrErr;
25768
+ this.internalErr = internalErr;
25769
+ if (Error.captureStackTrace) {
25770
+ Error.captureStackTrace(this, _HealthCacheSimulationError);
25771
+ }
26063
25772
  }
26064
- static fromBankType(bankType) {
26065
- const config = new BankConfig(
26066
- bankType.config.assetWeightInit,
26067
- bankType.config.assetWeightMaint,
26068
- bankType.config.liabilityWeightInit,
26069
- bankType.config.liabilityWeightMaint,
26070
- bankType.config.depositLimit,
26071
- bankType.config.borrowLimit,
26072
- bankType.config.riskTier,
26073
- bankType.config.totalAssetValueInitLimit,
26074
- bankType.config.assetTag,
26075
- bankType.config.oracleSetup,
26076
- bankType.config.oracleKeys,
26077
- bankType.config.oracleMaxAge,
26078
- bankType.config.interestRateConfig,
26079
- bankType.config.operationalState,
26080
- bankType.config.oracleMaxConfidence,
26081
- bankType.config.fixedPrice,
26082
- bankType.config.configFlags
25773
+ };
25774
+ async function simulateAccountHealthCacheWithFallback(props) {
25775
+ let lendrAccount = props.lendrAccount;
25776
+ const activeBalances = props.balances.filter((b) => b.active);
25777
+ const { assets: assetValueEquity, liabilities: liabilityValueEquity } = computeHealthComponentsWithoutBiasLegacy(
25778
+ activeBalances,
25779
+ props.bankMap,
25780
+ props.oraclePrices,
25781
+ 2 /* Equity */
25782
+ );
25783
+ try {
25784
+ const simulatedAccount = await simulateAccountHealthCache({
25785
+ program: props.program,
25786
+ bankMap: props.bankMap,
25787
+ oraclePrices: props.oraclePrices,
25788
+ lendrAccountPk: props.lendrAccount.address,
25789
+ balances: props.balances,
25790
+ bankMetadataMap: props.bankMetadataMap
25791
+ });
25792
+ simulatedAccount.healthCache.assetValueEquity = bigNumberToWrappedI80F48(assetValueEquity);
25793
+ simulatedAccount.healthCache.liabilityValueEquity = bigNumberToWrappedI80F48(liabilityValueEquity);
25794
+ lendrAccount = LendrAccount.fromAccountParsed(props.lendrAccount.address, simulatedAccount);
25795
+ } catch (e) {
25796
+ console.log("e", e);
25797
+ const { assets: assetValueMaint, liabilities: liabilityValueMaint } = computeHealthComponentsLegacy(
25798
+ activeBalances,
25799
+ props.bankMap,
25800
+ props.oraclePrices,
25801
+ 1 /* Maintenance */
26083
25802
  );
26084
- return new _Bank(
26085
- bankType.address,
26086
- bankType.mint,
26087
- bankType.mintDecimals,
26088
- bankType.group,
26089
- bankType.mintRate,
26090
- bankType.mintPrice,
26091
- bankType.assetShareValue,
26092
- bankType.liabilityShareValue,
26093
- bankType.liquidityVault,
26094
- bankType.liquidityVaultBump,
26095
- bankType.liquidityVaultAuthorityBump,
26096
- bankType.insuranceVault,
26097
- bankType.insuranceVaultBump,
26098
- bankType.insuranceVaultAuthorityBump,
26099
- bankType.collectedInsuranceFeesOutstanding,
26100
- bankType.feeVault,
26101
- bankType.feeVaultBump,
26102
- bankType.feeVaultAuthorityBump,
26103
- bankType.collectedGroupFeesOutstanding,
26104
- bankType.lastUpdate,
26105
- config,
26106
- bankType.totalAssetShares,
26107
- bankType.totalLiabilityShares,
26108
- bankType.flags,
26109
- bankType.emissionsActiveBorrowing,
26110
- bankType.emissionsActiveLending,
26111
- bankType.emissionsRate,
26112
- bankType.emissionsMint,
26113
- bankType.emissionsRemaining,
26114
- bankType.oracleKey,
26115
- bankType.emode,
26116
- bankType.feesDestinationAccount,
26117
- bankType.lendingPositionCount,
26118
- bankType.borrowingPositionCount,
26119
- bankType.pythShardId,
26120
- bankType.tokenSymbol
25803
+ const { assets: assetValueInitial, liabilities: liabilityValueInitial } = computeHealthComponentsLegacy(
25804
+ activeBalances,
25805
+ props.bankMap,
25806
+ props.oraclePrices,
25807
+ 0 /* Initial */
26121
25808
  );
26122
- }
26123
- static fromAccountParsed(address, accountParsed, feedIdMap, extendedMetadata, owner) {
26124
- const props = parseBankRaw(address, accountParsed, feedIdMap);
26125
- return new _Bank(
26126
- props.address,
26127
- props.mint,
26128
- props.mintDecimals,
26129
- props.group,
26130
- props.mintRate,
26131
- props.mintPrice,
26132
- props.assetShareValue,
26133
- props.liabilityShareValue,
26134
- props.liquidityVault,
26135
- props.liquidityVaultBump,
26136
- props.liquidityVaultAuthorityBump,
26137
- props.insuranceVault,
26138
- props.insuranceVaultBump,
26139
- props.insuranceVaultAuthorityBump,
26140
- props.collectedInsuranceFeesOutstanding,
26141
- props.feeVault,
26142
- props.feeVaultBump,
26143
- props.feeVaultAuthorityBump,
26144
- props.collectedGroupFeesOutstanding,
26145
- props.lastUpdate,
26146
- props.config,
26147
- props.totalAssetShares,
26148
- props.totalLiabilityShares,
26149
- props.flags,
26150
- props.emissionsActiveBorrowing,
26151
- props.emissionsActiveLending,
26152
- props.emissionsRate,
26153
- props.emissionsMint,
26154
- props.emissionsRemaining,
26155
- props.oracleKey,
26156
- props.emode,
26157
- props.feesDestinationAccount,
26158
- props.lendingPositionCount,
26159
- props.borrowingPositionCount,
26160
- props.pythShardId,
26161
- extendedMetadata?.symbol,
26162
- extendedMetadata,
26163
- owner
25809
+ lendrAccount.setHealthCache(
25810
+ new HealthCache(
25811
+ assetValueInitial,
25812
+ liabilityValueInitial,
25813
+ assetValueMaint,
25814
+ liabilityValueMaint,
25815
+ assetValueEquity,
25816
+ liabilityValueEquity,
25817
+ new import_bignumber14.default(0),
25818
+ [],
25819
+ [],
25820
+ true
25821
+ )
26164
25822
  );
25823
+ if (e instanceof HealthCacheSimulationError) {
25824
+ return { lendrAccount, error: e };
25825
+ }
26165
25826
  }
26166
- static withEmodeWeights(bank, emodeWeights) {
26167
- const newBank = Object.create(_Bank.prototype);
26168
- Object.assign(newBank, bank);
26169
- newBank.config = Object.assign({}, bank.config);
26170
- newBank.config.assetWeightInit = import_bignumber13.default.max(bank.config.assetWeightInit, emodeWeights.assetWeightInit);
26171
- newBank.config.assetWeightMaint = import_bignumber13.default.max(bank.config.assetWeightMaint, emodeWeights.assetWeightMaint);
26172
- return newBank;
26173
- }
26174
- static getPrice(oraclePrice, priceBias = 1 /* None */, weightedPrice = false) {
26175
- return getPrice(oraclePrice, priceBias, weightedPrice);
26176
- }
26177
- static computeQuantityFromUsdValue(oraclePrice, usdValue, priceBias, weightedPrice) {
26178
- const price = getPrice(oraclePrice, priceBias, weightedPrice);
26179
- return usdValue.div(price);
26180
- }
26181
- getTotalAssetQuantity() {
26182
- return getTotalAssetQuantity(this);
26183
- }
26184
- getTotalLiabilityQuantity() {
26185
- return getTotalLiabilityQuantity(this);
26186
- }
26187
- getAssetQuantity(assetShares) {
26188
- return getAssetQuantity(this, assetShares);
26189
- }
26190
- getLiabilityQuantity(liabilityShares) {
26191
- return getLiabilityQuantity(this, liabilityShares);
26192
- }
26193
- getAssetShares(assetQuantity) {
26194
- return getAssetShares(this, assetQuantity);
26195
- }
26196
- getLiabilityShares(liabilityQuantity) {
26197
- return getLiabilityShares(this, liabilityQuantity);
26198
- }
26199
- computeAssetUsdValue(oraclePrice, assetShares, lendrRequirementType, priceBias) {
26200
- return computeAssetUsdValue(this, oraclePrice, assetShares, lendrRequirementType, priceBias);
25827
+ return { lendrAccount };
25828
+ }
25829
+ async function simulateAccountHealthCache(props) {
25830
+ const { program, bankMap, oraclePrices, lendrAccountPk, balances, bankMetadataMap } = props;
25831
+ const activeBalances = balances.filter((b) => b.active);
25832
+ const { staleSwbOracles } = getActiveStaleBanks(activeBalances, bankMap, [], oraclePrices, 30);
25833
+ const computeIx = import_web325.ComputeBudgetProgram.setComputeUnitLimit({ units: 14e5 });
25834
+ const blockhash = (await program.provider.connection.getLatestBlockhash("confirmed")).blockhash;
25835
+ const fundAccountIx = import_web325.SystemProgram.transfer({
25836
+ fromPubkey: new import_web325.PublicKey("DD3AeAssFvjqTvRTrRAtpfjkBF8FpVKnFuwnMLN9haXD"),
25837
+ // lendr SOL VAULT
25838
+ toPubkey: program.provider.publicKey,
25839
+ lamports: 1e8
25840
+ // 0.1 SOL
25841
+ });
25842
+ const crankPythIxs = {
25843
+ postInstructions: [],
25844
+ closeInstructions: [],
25845
+ keys: [],
25846
+ lut: null
25847
+ };
25848
+ const crankSwbIxs = staleSwbOracles.length > 0 ? await createUpdateFeedIx({
25849
+ swbPullOracles: staleSwbOracles.map((oracle) => oracle.oracleKey),
25850
+ provider: program.provider
25851
+ }) : { instructions: [], luts: [] };
25852
+ const healthPulseIxs = await makePulseHealthIx2(
25853
+ program,
25854
+ lendrAccountPk,
25855
+ bankMap,
25856
+ balances,
25857
+ activeBalances.map((b) => b.bankPk),
25858
+ [],
25859
+ bankMetadataMap
25860
+ );
25861
+ const pythLut = crankPythIxs.lut ? [crankPythIxs.lut] : [];
25862
+ const txs = [];
25863
+ if (crankPythIxs.postInstructions.length > 0) {
25864
+ txs.push(
25865
+ ...splitInstructionsToFitTransactions(
25866
+ [computeIx],
25867
+ [
25868
+ fundAccountIx,
25869
+ ...crankPythIxs.postInstructions.map((ix) => ix.instruction),
25870
+ ...crankPythIxs.closeInstructions.map((ix) => ix.instruction)
25871
+ ],
25872
+ {
25873
+ blockhash,
25874
+ payerKey: program.provider.publicKey,
25875
+ luts: [...crankSwbIxs.luts, ...pythLut]
25876
+ }
25877
+ )
25878
+ );
26201
25879
  }
26202
- computeLiabilityUsdValue(oraclePrice, liabilityShares, lendrRequirementType, priceBias) {
26203
- return computeLiabilityUsdValue(this, oraclePrice, liabilityShares, lendrRequirementType, priceBias);
25880
+ const messageV0 = new import_web325.TransactionMessage({
25881
+ payerKey: program.provider.publicKey,
25882
+ recentBlockhash: blockhash,
25883
+ instructions: [...crankSwbIxs.instructions]
25884
+ }).compileToV0Message([...crankSwbIxs.luts]);
25885
+ const swbTx = new import_web325.VersionedTransaction(messageV0);
25886
+ txs.push(swbTx);
25887
+ const healthTx = new import_web325.TransactionMessage({
25888
+ payerKey: program.provider.publicKey,
25889
+ recentBlockhash: blockhash,
25890
+ instructions: [...healthPulseIxs.instructions]
25891
+ }).compileToV0Message([]);
25892
+ const healthTxV0 = new import_web325.VersionedTransaction(healthTx);
25893
+ txs.push(healthTxV0);
25894
+ if (txs.length > 5) {
25895
+ console.error("Too many transactions", txs.length);
25896
+ throw new Error("Too many transactions");
26204
25897
  }
26205
- computeUsdValue(oraclePrice, quantity, priceBias, weightedPrice, weight, scaleToBase = true) {
26206
- return computeUsdValue(this, oraclePrice, quantity, priceBias, weightedPrice, weight, scaleToBase);
25898
+ const simulationResult = await simulateBundle(program.provider.connection.rpcEndpoint, txs, [lendrAccountPk]);
25899
+ const postExecutionAccount = simulationResult.find((result) => result.postExecutionAccounts.length > 0);
25900
+ if (!postExecutionAccount) {
25901
+ throw new Error("Account not found");
26207
25902
  }
26208
- getAssetWeight(lendrRequirementType, oraclePrice, ignoreSoftLimits = false, assetWeightInitOverride) {
26209
- return getAssetWeight(this, lendrRequirementType, oraclePrice, {
26210
- ignoreSoftLimits,
26211
- assetWeightInitOverride
25903
+ const lendrAccountPost = LendrAccount.decodeAccountRaw(
25904
+ Buffer.from(postExecutionAccount.postExecutionAccounts[0].data[0], "base64"),
25905
+ program.idl
25906
+ );
25907
+ if (lendrAccountPost.healthCache.lndrErr || lendrAccountPost.healthCache.internalErr) {
25908
+ console.log(
25909
+ "cranked swb oracles",
25910
+ staleSwbOracles.map((oracle) => oracle.oracleKey)
25911
+ );
25912
+ console.log("LendrAccountPost healthCache internalErr", lendrAccountPost.healthCache.internalErr);
25913
+ console.log("LendrAccountPost healthCache lndrErr", lendrAccountPost.healthCache.lndrErr);
25914
+ if (lendrAccountPost.healthCache.lndrErr === 6009) {
25915
+ const assetValue = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.assetValue).isZero();
25916
+ const liabilityValue = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.liabilityValue).isZero();
25917
+ const assetValueEquity = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.assetValueEquity).isZero();
25918
+ const liabilityValueEquity = !wrappedI80F48toBigNumber(
25919
+ lendrAccountPost.healthCache.liabilityValueEquity
25920
+ ).isZero();
25921
+ const assetValueMaint = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.assetValueMaint).isZero();
25922
+ const liabilityValueMaint = !wrappedI80F48toBigNumber(lendrAccountPost.healthCache.liabilityValueMaint).isZero();
25923
+ if (assetValue && liabilityValue && assetValueEquity && liabilityValueEquity && assetValueMaint && liabilityValueMaint) {
25924
+ return lendrAccountPost;
25925
+ }
25926
+ }
25927
+ console.error("Account health cache simulation failed", {
25928
+ lndrErr: lendrAccountPost.healthCache.lndrErr,
25929
+ internalErr: lendrAccountPost.healthCache.internalErr
26212
25930
  });
25931
+ throw new HealthCacheSimulationError(
25932
+ "Account health cache simulation failed",
25933
+ lendrAccountPost.healthCache.lndrErr,
25934
+ lendrAccountPost.healthCache.internalErr
25935
+ );
26213
25936
  }
26214
- getLiabilityWeight(lendrRequirementType) {
26215
- return getLiabilityWeight(this.config, lendrRequirementType);
26216
- }
26217
- computeTvl(oraclePrice) {
26218
- return computeTvl(this, oraclePrice);
26219
- }
26220
- computeInterestRates() {
26221
- return computeInterestRates(this);
26222
- }
26223
- computeBaseInterestRate() {
26224
- return computeBaseInterestRate(this);
26225
- }
26226
- computeUtilizationRate() {
26227
- return computeUtilizationRate(this);
26228
- }
26229
- computeRemainingCapacity() {
26230
- return computeRemainingCapacity(this);
25937
+ return lendrAccountPost;
25938
+ }
25939
+ async function makePulseHealthIx2(program, lendrAccountPk, banks, balances, mandatoryBanks, excludedBanks, bankMetadataMap) {
25940
+ const healthAccounts = computeHealthCheckAccounts(balances, banks, mandatoryBanks, excludedBanks);
25941
+ const accountMetas = computeHealthAccountMetas(healthAccounts, bankMetadataMap);
25942
+ const ix = await instructions_default.makePulseHealthIx(
25943
+ program,
25944
+ {
25945
+ lendrAccount: lendrAccountPk
25946
+ },
25947
+ accountMetas.map((account) => ({ pubkey: account, isSigner: false, isWritable: false }))
25948
+ );
25949
+ return { instructions: [ix], keys: [] };
25950
+ }
25951
+ async function createUpdateFeedIx(_props) {
25952
+ throw new Error("in terms of switchboard, we have no switchboard");
25953
+ }
25954
+ async function createLendrAccountTx(props) {
25955
+ const authority = props.lendrAccount?.authority ?? props.lendrClient.provider.publicKey;
25956
+ const lendrAccountKeypair = import_web325.Keypair.generate();
25957
+ const dummyWrappedI80F48 = bigNumberToWrappedI80F48(new import_bignumber14.default(0));
25958
+ const dummyBalances = Array(15).fill({
25959
+ active: false,
25960
+ bankPk: new import_web325.PublicKey("11111111111111111111111111111111"),
25961
+ assetShares: dummyWrappedI80F48,
25962
+ liabilityShares: dummyWrappedI80F48,
25963
+ emissionsOutstanding: dummyWrappedI80F48,
25964
+ lastUpdate: new import_bn11.default(0)
25965
+ });
25966
+ const rawAccount = {
25967
+ group: props.lendrClient.group.address,
25968
+ authority,
25969
+ lendingAccount: { balances: dummyBalances },
25970
+ healthCache: {
25971
+ assetValue: {
25972
+ value: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
25973
+ },
25974
+ liabilityValue: {
25975
+ value: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
25976
+ },
25977
+ timestamp: new import_bn11.default(0),
25978
+ flags: 0,
25979
+ prices: [],
25980
+ assetValueMaint: bigNumberToWrappedI80F48(new import_bignumber14.default(0)),
25981
+ liabilityValueMaint: bigNumberToWrappedI80F48(new import_bignumber14.default(0)),
25982
+ assetValueEquity: bigNumberToWrappedI80F48(new import_bignumber14.default(0)),
25983
+ liabilityValueEquity: bigNumberToWrappedI80F48(new import_bignumber14.default(0)),
25984
+ errIndex: 0,
25985
+ internalErr: 0,
25986
+ internalBankruptcyErr: 0,
25987
+ internalLiqErr: 0,
25988
+ lndrErr: 0
25989
+ },
25990
+ emissionsDestinationAccount: new import_web325.PublicKey("11111111111111111111111111111111"),
25991
+ accountFlags: new import_bn11.default([0, 0, 0])
25992
+ };
25993
+ const account = LendrAccount.fromAccountParsed(lendrAccountKeypair.publicKey, rawAccount);
25994
+ const wrappedAccount = new LendrAccountWrapper(lendrAccountKeypair.publicKey, props.lendrClient, account);
25995
+ return {
25996
+ account: wrappedAccount,
25997
+ tx: await props.lendrClient.createLendrAccountTx({ accountKeypair: lendrAccountKeypair })
25998
+ };
25999
+ }
26000
+ function getActiveStaleBanks(balances, banks, additionalBanks, oraclePrices, maxAgeOffset = 0) {
26001
+ const activeBanks = balances.filter((balance) => balance.active).map((balance) => banks.get(balance.bankPk.toBase58())).filter((bank) => !!bank);
26002
+ const allBanks = [...activeBanks, ...additionalBanks];
26003
+ const staleBanks = allBanks.filter((bank) => {
26004
+ if (bank.config.oracleSetup === "SwitchboardPull" /* SwitchboardPull */ || bank.config.oracleSetup === "SwitchboardV2" /* SwitchboardV2 */ || bank.config.oracleSetup === "KaminoSwitchboardPull" /* KaminoSwitchboardPull */) {
26005
+ return true;
26006
+ }
26007
+ const oraclePrice = oraclePrices.get(bank.address.toBase58());
26008
+ const maxAge = bank.config.oracleMaxAge;
26009
+ const currentTime = Math.round(Date.now() / 1e3);
26010
+ const oracleTime = Math.round(oraclePrice?.timestamp ? oraclePrice.timestamp.toNumber() : Date.now());
26011
+ const adjustedMaxAge = Math.max(maxAge - maxAgeOffset, 0);
26012
+ const isStale = currentTime - oracleTime > adjustedMaxAge;
26013
+ return isStale;
26014
+ });
26015
+ if (staleBanks.length > 0) {
26016
+ const stalePythFeeds = [];
26017
+ const staleSwbOracles = [];
26018
+ const seenSwbOracles = /* @__PURE__ */ new Set();
26019
+ const seenPythFeeds = /* @__PURE__ */ new Set();
26020
+ staleBanks.forEach((bank) => {
26021
+ if (bank.config.oracleSetup === "SwitchboardPull" /* SwitchboardPull */ || bank.config.oracleSetup === "KaminoSwitchboardPull" /* KaminoSwitchboardPull */) {
26022
+ const key = bank.oracleKey.toBase58();
26023
+ if (!seenSwbOracles.has(key)) {
26024
+ seenSwbOracles.add(key);
26025
+ staleSwbOracles.push({ oracleKey: bank.oracleKey });
26026
+ }
26027
+ } else if (bank.config.oracleSetup === "PythPushOracle" /* PythPushOracle */ || bank.config.oracleSetup === "StakedWithPythPush" /* StakedWithPythPush */ || bank.config.oracleSetup === "KaminoPythPush" /* KaminoPythPush */) {
26028
+ const oraclePrice = oraclePrices.get(bank.address.toBase58());
26029
+ const shardId = oraclePrice?.pythShardId ?? 0;
26030
+ const feedId = bank.config.oracleKeys[0];
26031
+ const feedKey = feedIdToString(feedId);
26032
+ if (!seenPythFeeds.has(feedKey)) {
26033
+ seenPythFeeds.add(feedKey);
26034
+ stalePythFeeds.push({ feedId: feedKey, shardId });
26035
+ }
26036
+ }
26037
+ });
26038
+ return { stalePythFeeds, staleSwbOracles };
26231
26039
  }
26232
- describe(oraclePrice) {
26233
- return `
26234
- Bank address: ${this.address.toBase58()}
26235
- Mint: ${this.mint.toBase58()}, decimals: ${this.mintDecimals}
26236
-
26237
- Total deposits: ${nativeToUi(this.getTotalAssetQuantity(), this.mintDecimals)}
26238
- Total borrows: ${nativeToUi(this.getTotalLiabilityQuantity(), this.mintDecimals)}
26040
+ return { stalePythFeeds: [], staleSwbOracles: [] };
26041
+ }
26239
26042
 
26240
- Total assets (USD value): ${this.computeAssetUsdValue(
26241
- oraclePrice,
26242
- this.totalAssetShares,
26243
- 2 /* Equity */,
26244
- 1 /* None */
26245
- )}
26246
- Total liabilities (USD value): ${this.computeLiabilityUsdValue(
26247
- oraclePrice,
26248
- this.totalLiabilityShares,
26249
- 2 /* Equity */,
26250
- 1 /* None */
26251
- )}
26043
+ // src/services/group/group.service.ts
26044
+ var import_spl_token5 = require("@solana/spl-token");
26045
+ var import_web326 = require("@solana/web3.js");
26046
+ var import_bn12 = __toESM(require("bn.js"), 1);
26047
+ init_constants();
26048
+ init_single_spl_pool();
26049
+ async function makePoolConfigureBankIx2(program, bank, args) {
26050
+ const ix = await instructions_default.makePoolConfigureBankIx(
26051
+ program,
26052
+ {
26053
+ bank
26054
+ },
26055
+ { bankConfigOpt: args }
26056
+ );
26057
+ return {
26058
+ instructions: [ix],
26059
+ keys: []
26060
+ };
26061
+ }
26062
+ async function makeAddPermissionlessStakedBankIx(program, group, voteAccountAddress, feePayer, pythOracle) {
26063
+ const [settingsKey] = import_web326.PublicKey.findProgramAddressSync(
26064
+ [Buffer.from("staked_settings", "utf-8"), group.toBuffer()],
26065
+ program.programId
26066
+ );
26067
+ const poolAddress = findPoolAddress(voteAccountAddress);
26068
+ const solPool = findPoolStakeAddress(poolAddress);
26069
+ const lstMint = findPoolMintAddress(poolAddress);
26070
+ const onRampAddress = findPoolOnRampAddress(poolAddress);
26071
+ const keys = [
26072
+ { pubkey: poolAddress, isSigner: false, isWritable: false },
26073
+ { pubkey: onRampAddress, isSigner: false, isWritable: true },
26074
+ { pubkey: solPool, isSigner: false, isWritable: false },
26075
+ { pubkey: import_web326.SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
26076
+ { pubkey: import_web326.SystemProgram.programId, isSigner: false, isWritable: false },
26077
+ { pubkey: import_web326.StakeProgram.programId, isSigner: false, isWritable: false }
26078
+ ];
26079
+ const data = Buffer.from(Uint8Array.of(6));
26080
+ const _onrampIx = new import_web326.TransactionInstruction({
26081
+ keys,
26082
+ programId: SINGLE_POOL_PROGRAM_ID,
26083
+ data
26084
+ });
26085
+ const remainingKeys = [pythOracle, lstMint, solPool];
26086
+ const ix = await instructions_default.makePoolAddPermissionlessStakedBankIx(
26087
+ program,
26088
+ {
26089
+ stakedSettings: settingsKey,
26090
+ feePayer,
26091
+ bankMint: lstMint,
26092
+ solPool,
26093
+ stakePool: poolAddress
26094
+ },
26095
+ remainingKeys.map((key) => ({ pubkey: key, isSigner: false, isWritable: false })),
26096
+ {
26097
+ seed: new import_bn12.default(0)
26098
+ }
26099
+ );
26100
+ return {
26101
+ instructions: [ix],
26102
+ keys: []
26103
+ };
26104
+ }
26105
+ async function makePoolAddBankIx2(program, group, bank, feePayer, bankMint, bankConfig, tokenProgram = import_spl_token5.TOKEN_PROGRAM_ID, overrideOpt = {}) {
26106
+ const rawBankConfig = serializeBankConfigOpt(bankConfig);
26107
+ const rawBankConfigCompact = {
26108
+ ...rawBankConfig,
26109
+ oracleMaxAge: bankConfig.oracleMaxAge,
26110
+ auto_padding_0: [0],
26111
+ auto_padding_1: [0]
26112
+ };
26113
+ const ix = await instructions_default.makePoolAddBankIx(
26114
+ program,
26115
+ {
26116
+ lendrGroup: group,
26117
+ feePayer,
26118
+ bankMint,
26119
+ bank,
26120
+ tokenProgram,
26121
+ ...overrideOpt
26122
+ // if two oracle keys: first is feed id, second is oracle key
26123
+ },
26124
+ {
26125
+ bankConfig: rawBankConfigCompact
26126
+ }
26127
+ );
26128
+ return {
26129
+ instructions: [ix],
26130
+ //ix
26131
+ keys: []
26132
+ };
26133
+ }
26252
26134
 
26253
- Asset price (USD): ${_Bank.getPrice(oraclePrice, 1 /* None */, false)}
26254
- Asset price Weighted (USD): ${_Bank.getPrice(oraclePrice, 1 /* None */, true)}
26135
+ // src/services/group/utils/deserialize.utils.ts
26136
+ var import_web327 = require("@solana/web3.js");
26137
+ function dtoToGroup(groupDto) {
26138
+ return {
26139
+ admin: new import_web327.PublicKey(groupDto.admin),
26140
+ address: new import_web327.PublicKey(groupDto.address)
26141
+ };
26142
+ }
26255
26143
 
26256
- Config:
26257
- - Asset weight init: ${this.config.assetWeightInit.toFixed(2)}
26258
- - Asset weight maint: ${this.config.assetWeightMaint.toFixed(2)}
26259
- - Liability weight init: ${this.config.liabilityWeightInit.toFixed(2)}
26260
- - Liability weight maint: ${this.config.liabilityWeightMaint.toFixed(2)}
26144
+ // src/services/group/utils/serialize.utils.ts
26145
+ function groupToDto(group) {
26146
+ return {
26147
+ admin: group.admin.toBase58(),
26148
+ address: group.address.toBase58()
26149
+ };
26150
+ }
26261
26151
 
26262
- - Deposit limit: ${this.config.depositLimit}
26263
- - Borrow limit: ${this.config.borrowLimit}
26152
+ // src/services/native-stake/utils/deserialize.utils.ts
26153
+ var import_web328 = require("@solana/web3.js");
26154
+ function dtoToValidatorStakeGroup(validatorStakeGroupDto) {
26155
+ return {
26156
+ validator: new import_web328.PublicKey(validatorStakeGroupDto.validator),
26157
+ poolKey: new import_web328.PublicKey(validatorStakeGroupDto.poolKey),
26158
+ poolMintKey: new import_web328.PublicKey(validatorStakeGroupDto.poolMintKey),
26159
+ totalStake: validatorStakeGroupDto.totalStake,
26160
+ selectedAccount: {
26161
+ pubkey: new import_web328.PublicKey(validatorStakeGroupDto.selectedAccount.pubkey),
26162
+ amount: validatorStakeGroupDto.selectedAccount.amount
26163
+ },
26164
+ accounts: validatorStakeGroupDto.accounts.map((account) => ({
26165
+ pubkey: new import_web328.PublicKey(account.pubkey),
26166
+ amount: account.amount
26167
+ }))
26168
+ };
26169
+ }
26264
26170
 
26265
- LTVs:
26266
- - Initial: ${new import_bignumber13.default(1).div(this.config.liabilityWeightInit).times(100).toFixed(2)}%
26267
- - Maintenance: ${new import_bignumber13.default(1).div(this.config.liabilityWeightMaint).times(100).toFixed(2)}%
26268
- `;
26269
- }
26270
- };
26271
- var BankConfig = class _BankConfig {
26272
- constructor(assetWeightInit, assetWeightMaint, liabilityWeightInit, liabilityWeightMaint, depositLimit, borrowLimit, riskTier, totalAssetValueInitLimit, assetTag, oracleSetup, oracleKeys, oracleMaxAge, interestRateConfig, operationalState, oracleMaxConfidence, fixedPrice, configFlags) {
26273
- this.assetWeightInit = assetWeightInit;
26274
- this.assetWeightMaint = assetWeightMaint;
26275
- this.liabilityWeightInit = liabilityWeightInit;
26276
- this.liabilityWeightMaint = liabilityWeightMaint;
26277
- this.depositLimit = depositLimit;
26278
- this.borrowLimit = borrowLimit;
26279
- this.riskTier = riskTier;
26280
- this.totalAssetValueInitLimit = totalAssetValueInitLimit;
26281
- this.assetTag = assetTag;
26282
- this.oracleSetup = oracleSetup;
26283
- this.oracleKeys = oracleKeys;
26284
- this.oracleMaxAge = oracleMaxAge;
26285
- this.interestRateConfig = interestRateConfig;
26286
- this.operationalState = operationalState;
26287
- this.oracleMaxConfidence = oracleMaxConfidence;
26288
- this.fixedPrice = fixedPrice;
26289
- this.configFlags = configFlags;
26171
+ // src/services/native-stake/utils/fetch.utils.ts
26172
+ var import_web329 = require("@solana/web3.js");
26173
+ init_constants();
26174
+ init_single_spl_pool();
26175
+ var fetchNativeStakeAccounts = async (connection, publicKey3, opts = {
26176
+ filterInactive: true
26177
+ }) => {
26178
+ if (!connection || !publicKey3) {
26179
+ throw new Error("Invalid connection or public key");
26290
26180
  }
26291
- static fromAccountParsed(bankConfigRaw) {
26292
- const bankConfig = parseBankConfigRaw(bankConfigRaw);
26293
- return new _BankConfig(
26294
- bankConfig.assetWeightInit,
26295
- bankConfig.assetWeightMaint,
26296
- bankConfig.liabilityWeightInit,
26297
- bankConfig.liabilityWeightMaint,
26298
- bankConfig.depositLimit,
26299
- bankConfig.borrowLimit,
26300
- bankConfig.riskTier,
26301
- bankConfig.totalAssetValueInitLimit,
26302
- bankConfig.assetTag,
26303
- bankConfig.oracleSetup,
26304
- bankConfig.oracleKeys,
26305
- bankConfig.oracleMaxAge,
26306
- bankConfig.interestRateConfig,
26307
- bankConfig.operationalState,
26308
- bankConfig.oracleMaxConfidence,
26309
- bankConfig.fixedPrice,
26310
- bankConfig.configFlags
26181
+ try {
26182
+ const epochInfo = await connection.getEpochInfo();
26183
+ const accounts = await connection.getParsedProgramAccounts(import_web329.StakeProgram.programId, {
26184
+ filters: [
26185
+ {
26186
+ memcmp: {
26187
+ offset: 12,
26188
+ bytes: publicKey3.toBase58()
26189
+ }
26190
+ }
26191
+ ]
26192
+ });
26193
+ const validatorMap = /* @__PURE__ */ new Map();
26194
+ await Promise.all(
26195
+ accounts.map(async (acc) => {
26196
+ const parsedAccount = acc.account.data;
26197
+ const stakeInfo = parsedAccount.parsed.info;
26198
+ if (!stakeInfo.stake?.delegation || opts.filterInactive && (Number(stakeInfo.stake.delegation.activationEpoch) >= epochInfo.epoch || stakeInfo.stake.delegation.deactivationEpoch !== MAX_U64)) {
26199
+ return;
26200
+ }
26201
+ const validatorAddress = stakeInfo.stake.delegation.voter;
26202
+ const accountPubkey = acc.pubkey;
26203
+ const amount = Number(stakeInfo.stake.delegation.stake) / import_web329.LAMPORTS_PER_SOL;
26204
+ const existingAccounts = validatorMap.get(validatorAddress) || [];
26205
+ validatorMap.set(validatorAddress, [...existingAccounts, { pubkey: accountPubkey, amount }]);
26206
+ })
26207
+ );
26208
+ return Promise.all(
26209
+ Array.from(validatorMap.entries()).map(async ([validatorAddress, accounts2]) => {
26210
+ const poolKey = findPoolAddress(new import_web329.PublicKey(validatorAddress));
26211
+ const poolMintKey = findPoolMintAddress(poolKey);
26212
+ const totalStake = accounts2.reduce((acc, curr) => acc + curr.amount, 0);
26213
+ const largestAccount = accounts2.reduce((acc, curr) => acc.amount > curr.amount ? acc : curr);
26214
+ const sortedAccounts = accounts2.sort((a, b) => b.amount - a.amount);
26215
+ if (!sortedAccounts[0].pubkey.equals(largestAccount.pubkey)) {
26216
+ sortedAccounts.unshift(sortedAccounts.splice(sortedAccounts.indexOf(largestAccount), 1)[0]);
26217
+ }
26218
+ return {
26219
+ validator: new import_web329.PublicKey(validatorAddress),
26220
+ poolKey,
26221
+ poolMintKey,
26222
+ accounts: sortedAccounts,
26223
+ totalStake,
26224
+ selectedAccount: largestAccount
26225
+ };
26226
+ })
26311
26227
  );
26228
+ } catch (e) {
26229
+ console.error("Error getting stake accounts", e);
26230
+ return [];
26312
26231
  }
26313
26232
  };
26233
+ var fetchStakePoolActiveStates = async (connection, validatorVoteAccounts) => {
26234
+ const currentEpoch = await connection.getEpochInfo();
26235
+ const activeStates = /* @__PURE__ */ new Map();
26236
+ const poolMintAddressRecord = {};
26237
+ const poolStakeAddressRecord = {};
26238
+ validatorVoteAccounts.forEach((validatorVoteAccount) => {
26239
+ const poolAddress = findPoolAddress(validatorVoteAccount);
26240
+ const poolStakeAddress = findPoolStakeAddress(poolAddress);
26241
+ const poolMintAddress = findPoolMintAddress(poolAddress);
26242
+ poolMintAddressRecord[validatorVoteAccount.toBase58()] = poolMintAddress;
26243
+ poolStakeAddressRecord[poolStakeAddress.toBase58()] = validatorVoteAccount;
26244
+ });
26245
+ const poolStakeAddressKeys = Object.keys(poolStakeAddressRecord);
26246
+ const poolStakeAccounts = Object.fromEntries(
26247
+ (await chunkedGetRawMultipleAccountInfoOrdered(connection, poolStakeAddressKeys)).map((ai, index) => [
26248
+ poolStakeAddressRecord[poolStakeAddressKeys[index]],
26249
+ ai?.data || null
26250
+ ])
26251
+ );
26252
+ validatorVoteAccounts.forEach((validatorVoteAccount) => {
26253
+ const stakeAccount = fetchStakeAccount(poolStakeAccounts[validatorVoteAccount.toBase58()]);
26254
+ const poolMintAddress = poolMintAddressRecord[validatorVoteAccount.toBase58()];
26255
+ if (!stakeAccount) {
26256
+ activeStates.set(poolMintAddress.toBase58(), false);
26257
+ return;
26258
+ }
26259
+ if (!stakeAccount.stake?.delegation) {
26260
+ activeStates.set(poolMintAddress.toBase58(), false);
26261
+ return;
26262
+ }
26263
+ const activationEpoch = stakeAccount.stake.delegation.activationEpoch;
26264
+ const isActive = currentEpoch.epoch > Number(activationEpoch);
26265
+ activeStates.set(validatorVoteAccount.toBase58(), isActive);
26266
+ });
26267
+ return activeStates;
26268
+ };
26269
+ var fetchStakeAccount = (data) => {
26270
+ let offset = 0;
26271
+ const discriminant = data.readUInt32LE(offset);
26272
+ offset += 4;
26273
+ const rentExemptReserve = data.readBigUInt64LE(offset);
26274
+ offset += 8;
26275
+ const staker = new import_web329.PublicKey(data.subarray(offset, offset + 32));
26276
+ offset += 32;
26277
+ const withdrawer = new import_web329.PublicKey(data.subarray(offset, offset + 32));
26278
+ offset += 32;
26279
+ const unixTimestamp = data.readBigUInt64LE(offset);
26280
+ offset += 8;
26281
+ const epoch = data.readBigUInt64LE(offset);
26282
+ offset += 8;
26283
+ const custodian = new import_web329.PublicKey(data.subarray(offset, offset + 32));
26284
+ offset += 32;
26285
+ const voterPubkey = new import_web329.PublicKey(data.subarray(offset, offset + 32));
26286
+ offset += 32;
26287
+ const stake = data.readBigUInt64LE(offset);
26288
+ offset += 8;
26289
+ const activationEpoch = data.readBigUInt64LE(offset);
26290
+ offset += 8;
26291
+ const deactivationEpoch = data.readBigUInt64LE(offset);
26292
+ offset += 8;
26293
+ const creditsObserved = data.readBigUInt64LE(offset);
26294
+ return {
26295
+ discriminant,
26296
+ meta: {
26297
+ rentExemptReserve,
26298
+ authorized: {
26299
+ staker,
26300
+ withdrawer
26301
+ },
26302
+ lockup: {
26303
+ unixTimestamp,
26304
+ epoch,
26305
+ custodian
26306
+ }
26307
+ },
26308
+ stake: {
26309
+ delegation: {
26310
+ voterPubkey,
26311
+ stake,
26312
+ activationEpoch,
26313
+ deactivationEpoch
26314
+ },
26315
+ creditsObserved
26316
+ }
26317
+ };
26318
+ };
26319
+ var fetchStakePoolMev = async (connection, validatorVoteAccounts) => {
26320
+ const poolAddressRecord = {};
26321
+ const poolStakeAddressRecord = {};
26322
+ const onRampAddressRecord = {};
26323
+ const mev = /* @__PURE__ */ new Map();
26324
+ validatorVoteAccounts.forEach((validatorVoteAccount) => {
26325
+ const poolAddress = findPoolAddress(validatorVoteAccount);
26326
+ const poolStakeAddress = findPoolStakeAddress(poolAddress);
26327
+ const onRampAddress = findPoolOnRampAddress(poolAddress);
26328
+ poolAddressRecord[validatorVoteAccount.toBase58()] = poolAddress;
26329
+ poolStakeAddressRecord[validatorVoteAccount.toBase58()] = poolStakeAddress;
26330
+ onRampAddressRecord[validatorVoteAccount.toBase58()] = onRampAddress;
26331
+ });
26332
+ const poolStakeAddresses = validatorVoteAccounts.map(
26333
+ (validatorVoteAccount) => poolStakeAddressRecord[validatorVoteAccount.toBase58()]
26334
+ );
26335
+ const onRampAddresses = validatorVoteAccounts.map(
26336
+ (validatorVoteAccount) => onRampAddressRecord[validatorVoteAccount.toBase58()]
26337
+ );
26338
+ const allAddresses = [...poolStakeAddresses, ...onRampAddresses].map((address) => address.toBase58());
26339
+ return chunkedGetRawMultipleAccountInfoOrdered(connection, allAddresses).then((accountInfos) => {
26340
+ const poolStakeInfos = accountInfos.slice(0, poolStakeAddresses.length);
26341
+ const onRampInfos = accountInfos.slice(poolStakeAddresses.length);
26342
+ const rent = 2282280;
26343
+ validatorVoteAccounts.forEach((validatorVoteAccount, index) => {
26344
+ const poolStakeInfo = poolStakeInfos[index];
26345
+ const onRampInfo = onRampInfos[index];
26346
+ if (poolStakeInfo && onRampInfo) {
26347
+ const stakeDecoded = fetchStakeAccount(poolStakeInfo.data);
26348
+ const onrampDecoded = fetchStakeAccount(onRampInfo.data);
26349
+ const poolLamps = poolStakeInfo.lamports - rent - Number(stakeDecoded.stake.delegation.stake.toString());
26350
+ const onrampStake = Number(onrampDecoded.stake.delegation.stake.toString());
26351
+ mev.set(validatorVoteAccount.toBase58(), {
26352
+ pool: poolLamps >= 1e3 ? poolLamps : 0,
26353
+ onramp: onrampStake
26354
+ });
26355
+ }
26356
+ });
26357
+ return mev;
26358
+ });
26359
+ };
26360
+
26361
+ // src/services/native-stake/utils/serialize.utils.ts
26362
+ function validatorStakeGroupToDto(validatorStakeGroup) {
26363
+ return {
26364
+ validator: validatorStakeGroup.validator.toBase58(),
26365
+ poolKey: validatorStakeGroup.poolKey.toBase58(),
26366
+ poolMintKey: validatorStakeGroup.poolMintKey.toBase58(),
26367
+ totalStake: validatorStakeGroup.totalStake,
26368
+ selectedAccount: {
26369
+ pubkey: validatorStakeGroup.selectedAccount.pubkey.toBase58(),
26370
+ amount: validatorStakeGroup.selectedAccount.amount
26371
+ },
26372
+ accounts: validatorStakeGroup.accounts.map((account) => ({
26373
+ pubkey: account.pubkey.toBase58(),
26374
+ amount: account.amount
26375
+ }))
26376
+ };
26377
+ }
26314
26378
 
26315
26379
  // src/models/account/pure.ts
26316
26380
  var TOKEN_ACCOUNT_RENT_EXEMPT = 2039280;
@@ -26492,7 +26556,7 @@ var LendrAccount = class _LendrAccount {
26492
26556
  const useCache = false;
26493
26557
  const freeCollateral = useCache ? this.computeFreeCollateral().times(_volatilityFactor) : this.computeFreeCollateralLegacy(modifiedBanks, oraclePrices).times(_volatilityFactor);
26494
26558
  logger.debug({ freeCollateral: freeCollateral.toFixed(6) }, "[lendr:computeMaxBorrowForBank] Free collateral");
26495
- const untiedCollateralForBank = import_bignumber14.default.min(
26559
+ const untiedCollateralForBank = import_bignumber15.default.min(
26496
26560
  bank.computeAssetUsdValue(priceInfo, balance.assetShares, 0 /* Initial */, 0 /* Lowest */),
26497
26561
  freeCollateral
26498
26562
  );
@@ -26528,7 +26592,7 @@ var LendrAccount = class _LendrAccount {
26528
26592
  const { liabilities: liabilitiesInit } = this.computeHealthComponents(0 /* Initial */);
26529
26593
  if (bank.config.riskTier === "Isolated" /* Isolated */ || initAssetWeight.isZero() && maintAssetWeight.isZero()) {
26530
26594
  if (freeCollateral.isZero() && !liabilitiesInit.isZero()) {
26531
- return new import_bignumber14.default(0);
26595
+ return new import_bignumber15.default(0);
26532
26596
  } else {
26533
26597
  return entireBalance;
26534
26598
  }
@@ -26537,7 +26601,7 @@ var LendrAccount = class _LendrAccount {
26537
26601
  if (liabilitiesInit.eq(0)) {
26538
26602
  return entireBalance;
26539
26603
  } else if (freeCollateral.isZero()) {
26540
- return new import_bignumber14.default(0);
26604
+ return new import_bignumber15.default(0);
26541
26605
  } else {
26542
26606
  const { liabilities: maintLiabilities, assets: maintAssets } = this.computeHealthComponents(
26543
26607
  1 /* Maintenance */
@@ -26654,7 +26718,7 @@ var LendrAccount = class _LendrAccount {
26654
26718
  );
26655
26719
  const assets = assetsAccount.minus(assetBank);
26656
26720
  const liabilities = liabilitiesAccount.minus(liabilitiesBank);
26657
- const amountBn = new import_bignumber14.default(amount);
26721
+ const amountBn = new import_bignumber15.default(amount);
26658
26722
  let liquidationPrice;
26659
26723
  if (isLending) {
26660
26724
  if (liabilities.eq(0)) return null;
@@ -26697,7 +26761,7 @@ var LendrAccount = class _LendrAccount {
26697
26761
  const priceAssetLower = getPrice(assetPriceInfo, 0 /* Lowest */, false);
26698
26762
  const priceAssetMarket = getPrice(assetPriceInfo, 1 /* None */, false);
26699
26763
  const assetMaintWeight = assetBank.config.assetWeightMaint;
26700
- const liquidationDiscount = new import_bignumber14.default(0.95);
26764
+ const liquidationDiscount = new import_bignumber15.default(0.95);
26701
26765
  const priceLiabHighest = getPrice(liabilityPriceInfo, 2 /* Highest */, false);
26702
26766
  const priceLiabMarket = getPrice(liabilityPriceInfo, 1 /* None */, false);
26703
26767
  const liabMaintWeight = liabilityBank.config.liabilityWeightMaint;
@@ -26734,7 +26798,7 @@ var LendrAccount = class _LendrAccount {
26734
26798
  },
26735
26799
  "[lendr:getMaxLiquidatableAssetAmount]"
26736
26800
  );
26737
- const maxLiquidatableUsdValue = import_bignumber14.default.min(assetsUsdValue, underwaterMaintUsdValue, liabUsdValue);
26801
+ const maxLiquidatableUsdValue = import_bignumber15.default.min(assetsUsdValue, underwaterMaintUsdValue, liabUsdValue);
26738
26802
  logger.debug(
26739
26803
  {
26740
26804
  maxLiquidatableUsdValue: maxLiquidatableUsdValue.toFixed(6)
@@ -26796,7 +26860,7 @@ var LendrAccount = class _LendrAccount {
26796
26860
  }
26797
26861
  const depositIxs = [];
26798
26862
  if (bank.mint.equals(import_spl_token6.NATIVE_MINT) && wrapAndUnwrapSol) {
26799
- depositIxs.push(...makeWrapSolIxs(this.authority, new import_bignumber14.default(amount).minus(wSolBalanceUi)));
26863
+ depositIxs.push(...makeWrapSolIxs(this.authority, new import_bignumber15.default(amount).minus(wSolBalanceUi)));
26800
26864
  }
26801
26865
  return {
26802
26866
  depositIxs,
@@ -26861,7 +26925,7 @@ var LendrAccount = class _LendrAccount {
26861
26925
  const depositIx = await instructions_default.makeDepositWithSessionIx(program, accounts, ixArguments, remainingAccounts);
26862
26926
  if (bank.mint.equals(import_spl_token6.NATIVE_MINT)) {
26863
26927
  const wSolBalanceUi = opts.wSolBalanceUi ?? 0;
26864
- const wrapAmount = new import_bignumber14.default(amount).minus(wSolBalanceUi);
26928
+ const wrapAmount = new import_bignumber15.default(amount).minus(wSolBalanceUi);
26865
26929
  const wrapIxs = makeSessionWrapSolIxs(session.walletPublicKey, session.sessionPublicKey, wrapAmount, {
26866
26930
  existingBalance: wSolBalanceUi
26867
26931
  });
@@ -26901,7 +26965,7 @@ var LendrAccount = class _LendrAccount {
26901
26965
  remainingAccounts.push(mintData.mint);
26902
26966
  }
26903
26967
  if (bank.mint.equals(import_spl_token6.NATIVE_MINT) && wrapAndUnwrapSol) {
26904
- repayIxs.push(...makeWrapSolIxs(this.authority, new import_bignumber14.default(amount).minus(wSolBalanceUi)));
26968
+ repayIxs.push(...makeWrapSolIxs(this.authority, new import_bignumber15.default(amount).minus(wSolBalanceUi)));
26905
26969
  }
26906
26970
  return {
26907
26971
  repayIxs,
@@ -26978,7 +27042,7 @@ var LendrAccount = class _LendrAccount {
26978
27042
  );
26979
27043
  if (bank.mint.equals(import_spl_token6.NATIVE_MINT)) {
26980
27044
  const wSolBalanceUi = opts.wSolBalanceUi ?? 0;
26981
- const neededAmount = new import_bignumber14.default(amount).minus(wSolBalanceUi);
27045
+ const neededAmount = new import_bignumber15.default(amount).minus(wSolBalanceUi);
26982
27046
  const wrapIxs = makeSessionWrapSolIxs(session.walletPublicKey, session.sessionPublicKey, neededAmount, {
26983
27047
  existingBalance: wSolBalanceUi,
26984
27048
  wrapAmountUi: opts.wrapAmountUi
@@ -27418,8 +27482,8 @@ var LendrAccount = class _LendrAccount {
27418
27482
  }
27419
27483
  return projectedBalances.filter((b) => b.active).map((b) => b.bankPk);
27420
27484
  }
27421
- wrapInstructionForWSol(ix, amount = new import_bignumber14.default(0)) {
27422
- return [...makeWrapSolIxs(this.authority, new import_bignumber14.default(amount)), ix, makeUnwrapSolIx(this.authority)];
27485
+ wrapInstructionForWSol(ix, amount = new import_bignumber15.default(0)) {
27486
+ return [...makeWrapSolIxs(this.authority, new import_bignumber15.default(amount)), ix, makeUnwrapSolIx(this.authority)];
27423
27487
  }
27424
27488
  describe(banks, oraclePrices) {
27425
27489
  const { assets, liabilities } = this.computeHealthComponents(2 /* Equity */);
@@ -27462,7 +27526,7 @@ function isWeightedPrice(reqType) {
27462
27526
  var import_anchor8 = require("@coral-xyz/anchor");
27463
27527
  var import_spl_token7 = require("@solana/spl-token");
27464
27528
  var import_web331 = require("@solana/web3.js");
27465
- var import_bignumber15 = __toESM(require("bignumber.js"), 1);
27529
+ var import_bignumber16 = __toESM(require("bignumber.js"), 1);
27466
27530
  init_constants();
27467
27531
  var LendrAccountWrapper = class _LendrAccountWrapper {
27468
27532
  // --------------------------------------------------------------------------
@@ -27475,9 +27539,23 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27475
27539
  this.client = client;
27476
27540
  this.address = lendrAccountPk;
27477
27541
  this._lendrAccount = lendrAccount;
27542
+ this.banks = _LendrAccountWrapper.applyEmode(client.banks, lendrAccount);
27478
27543
  }
27479
27544
  address;
27545
+ banks;
27480
27546
  _lendrAccount;
27547
+ static applyEmode(banks, lendrAccount) {
27548
+ const rawBanks = Array.from(banks.values());
27549
+ const emodePairs = getEmodePairs(rawBanks);
27550
+ const activePairs = lendrAccount.computeActiveEmodePairs(emodePairs);
27551
+ if (activePairs.length === 0) return banks;
27552
+ const { adjustedBanks } = adjustBanksWithEmode(rawBanks, activePairs);
27553
+ const adjusted = /* @__PURE__ */ new Map();
27554
+ for (const bank of adjustedBanks) {
27555
+ adjusted.set(bank.address.toBase58(), bank);
27556
+ }
27557
+ return adjusted;
27558
+ }
27481
27559
  static async fetch(lendrAccountPk, client, commitment) {
27482
27560
  const { config, program } = client;
27483
27561
  const _lendrAccountPk = (0, import_anchor8.translateAddress)(lendrAccountPk);
@@ -27544,7 +27622,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27544
27622
  async simulateHealthCache() {
27545
27623
  const { lendrAccount: account } = await this._lendrAccount.simulateHealthCache(
27546
27624
  this._program,
27547
- this.client.banks,
27625
+ this.banks,
27548
27626
  this.client.oraclePrices,
27549
27627
  this.client.bankMetadataMap ?? {}
27550
27628
  );
@@ -27554,7 +27632,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27554
27632
  let { assets, liabilities } = this._lendrAccount.computeHealthComponents(1 /* Maintenance */);
27555
27633
  if (assets.isZero() && liabilities.isZero()) {
27556
27634
  const legacy = this._lendrAccount.computeHealthComponentsLegacy(
27557
- this.client.banks,
27635
+ this.banks,
27558
27636
  this.client.oraclePrices,
27559
27637
  1 /* Maintenance */
27560
27638
  );
@@ -27587,7 +27665,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27587
27665
  // TODO)) migrate to computeHealthComponents
27588
27666
  computeHealthComponentsLegacy(lendrRequirement, excludedBanks = []) {
27589
27667
  return this._lendrAccount.computeHealthComponentsLegacy(
27590
- this.client.banks,
27668
+ this.banks,
27591
27669
  this.client.oraclePrices,
27592
27670
  lendrRequirement,
27593
27671
  excludedBanks
@@ -27595,7 +27673,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27595
27673
  }
27596
27674
  computeHealthComponentsWithoutBiasLegacy(lendrRequirement) {
27597
27675
  return this._lendrAccount.computeHealthComponentsWithoutBiasLegacy(
27598
- this.client.banks,
27676
+ this.banks,
27599
27677
  this.client.oraclePrices,
27600
27678
  lendrRequirement
27601
27679
  );
@@ -27604,7 +27682,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27604
27682
  return this._lendrAccount.computeFreeCollateral(opts);
27605
27683
  }
27606
27684
  computeFreeCollateralLegacy(opts) {
27607
- return this._lendrAccount.computeFreeCollateralLegacy(this.client.banks, this.client.oraclePrices, opts);
27685
+ return this._lendrAccount.computeFreeCollateralLegacy(this.banks, this.client.oraclePrices, opts);
27608
27686
  }
27609
27687
  computeAccountValue() {
27610
27688
  return this._lendrAccount.computeAccountValue();
@@ -27615,12 +27693,12 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27615
27693
  computeEmodeImpacts(emodePairs) {
27616
27694
  return this._lendrAccount.computeEmodeImpacts(
27617
27695
  emodePairs,
27618
- Array.from(this.client.banks.keys()).map((b) => new import_web331.PublicKey(b))
27696
+ Array.from(this.banks.keys()).map((b) => new import_web331.PublicKey(b))
27619
27697
  );
27620
27698
  }
27621
27699
  computeMaxBorrowForBank(bankAddress, opts) {
27622
27700
  return this._lendrAccount.computeMaxBorrowForBank(
27623
- this.client.banks,
27701
+ this.banks,
27624
27702
  this.client.oraclePrices,
27625
27703
  bankAddress,
27626
27704
  opts,
@@ -27628,11 +27706,11 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27628
27706
  );
27629
27707
  }
27630
27708
  computeMaxWithdrawForBank(bankAddress, opts) {
27631
- return this._lendrAccount.computeMaxWithdrawForBank(this.client.banks, this.client.oraclePrices, bankAddress, opts);
27709
+ return this._lendrAccount.computeMaxWithdrawForBank(this.banks, this.client.oraclePrices, bankAddress, opts);
27632
27710
  }
27633
27711
  computeMaxLiquidatableAssetAmount(assetBankAddress, liabilityBankAddress) {
27634
27712
  return this._lendrAccount.computeMaxLiquidatableAssetAmount(
27635
- this.client.banks,
27713
+ this.banks,
27636
27714
  this.client.oraclePrices,
27637
27715
  assetBankAddress,
27638
27716
  liabilityBankAddress,
@@ -27640,11 +27718,11 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27640
27718
  );
27641
27719
  }
27642
27720
  computeLiquidationPriceForBank(bankAddress) {
27643
- return this._lendrAccount.computeLiquidationPriceForBank(this.client.banks, this.client.oraclePrices, bankAddress);
27721
+ return this._lendrAccount.computeLiquidationPriceForBank(this.banks, this.client.oraclePrices, bankAddress);
27644
27722
  }
27645
27723
  computeLiquidationPriceForBankAmount(bankAddress, isLending, amount) {
27646
27724
  return this._lendrAccount.computeLiquidationPriceForBankAmount(
27647
- this.client.banks,
27725
+ this.banks,
27648
27726
  this.client.oraclePrices,
27649
27727
  bankAddress,
27650
27728
  isLending,
@@ -27652,15 +27730,15 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27652
27730
  );
27653
27731
  }
27654
27732
  computeNetApy() {
27655
- return this._lendrAccount.computeNetApy(this.client.banks, this.client.oraclePrices);
27733
+ return this._lendrAccount.computeNetApy(this.banks, this.client.oraclePrices);
27656
27734
  }
27657
27735
  /** Todo move this into client */
27658
27736
  computeLoopingParams(principal, targetLeverage, depositBankAddress, borrowBankAddress) {
27659
- const depositBank = this.client.banks.get(depositBankAddress.toBase58());
27737
+ const depositBank = this.banks.get(depositBankAddress.toBase58());
27660
27738
  if (!depositBank) throw Error(`Bank ${depositBankAddress.toBase58()} not found`);
27661
27739
  const depositPriceInfo = this.client.oraclePrices.get(depositBankAddress.toBase58());
27662
27740
  if (!depositPriceInfo) throw Error(`Price info for ${depositBankAddress.toBase58()} not found`);
27663
- const borrowBank = this.client.banks.get(borrowBankAddress.toBase58());
27741
+ const borrowBank = this.banks.get(borrowBankAddress.toBase58());
27664
27742
  if (!borrowBank) throw Error(`Bank ${borrowBankAddress.toBase58()} not found`);
27665
27743
  const borrowPriceInfo = this.client.oraclePrices.get(borrowBankAddress.toBase58());
27666
27744
  if (!borrowPriceInfo) throw Error(`Price info for ${borrowBankAddress.toBase58()} not found`);
@@ -27957,9 +28035,9 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27957
28035
  },
27958
28036
  "[lendr:lendr-account:loop] Looping into Lendr account"
27959
28037
  );
27960
- const depositBank = this.client.banks.get(props.depositBankAddress.toBase58());
28038
+ const depositBank = this.banks.get(props.depositBankAddress.toBase58());
27961
28039
  if (!depositBank) throw Error("Deposit bank not found");
27962
- const borrowBank = this.client.banks.get(props.borrowBankAddress.toBase58());
28040
+ const borrowBank = this.banks.get(props.borrowBankAddress.toBase58());
27963
28041
  if (!borrowBank) throw Error("Borrow bank not found");
27964
28042
  const { processOpts, txOpts, ...txProps } = props;
27965
28043
  const { transactions } = await this.makeLoopTxV2(txProps);
@@ -27984,9 +28062,9 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27984
28062
  setupBankAddresses,
27985
28063
  overrideInferAccounts
27986
28064
  }) {
27987
- const depositBank = this.client.banks.get(depositBankAddress.toBase58());
28065
+ const depositBank = this.banks.get(depositBankAddress.toBase58());
27988
28066
  if (!depositBank) throw Error("Deposit bank not found");
27989
- const borrowBank = this.client.banks.get(borrowBankAddress.toBase58());
28067
+ const borrowBank = this.banks.get(borrowBankAddress.toBase58());
27990
28068
  if (!borrowBank) throw Error("Borrow bank not found");
27991
28069
  const blockhash = blockhashArg ?? (await this._program.provider.connection.getLatestBlockhash("confirmed")).blockhash;
27992
28070
  const setupIxs = await this.makeSetupIx(setupBankAddresses ?? [borrowBankAddress, depositBankAddress]);
@@ -28010,7 +28088,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28010
28088
  let flashloanTx;
28011
28089
  let txOverflown = false;
28012
28090
  if (depositBank.mint.equals(import_spl_token7.NATIVE_MINT) && inputDepositAmount) {
28013
- setupIxs.push(...makeWrapSolIxs(this.authority, new import_bignumber15.default(inputDepositAmount)));
28091
+ setupIxs.push(...makeWrapSolIxs(this.authority, new import_bignumber16.default(inputDepositAmount)));
28014
28092
  }
28015
28093
  if (setupIxs.length > 0) {
28016
28094
  const message = new import_web331.TransactionMessage({
@@ -28127,7 +28205,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28127
28205
  async makeDepositIx(amount, bankAddress, depositOpts = {}) {
28128
28206
  return this._lendrAccount.makeDepositIx(
28129
28207
  this._program,
28130
- this.client.banks,
28208
+ this.banks,
28131
28209
  this.client.mintDatas,
28132
28210
  amount,
28133
28211
  bankAddress,
@@ -28137,7 +28215,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28137
28215
  async makeDepositWithSessionIx(amount, bankAddress, session, depositOpts = {}) {
28138
28216
  return this._lendrAccount.makeDepositWithSessionIx(
28139
28217
  this._program,
28140
- this.client.banks,
28218
+ this.banks,
28141
28219
  this.client.mintDatas,
28142
28220
  amount,
28143
28221
  bankAddress,
@@ -28383,7 +28461,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28383
28461
  const ldrAccount = LendrAccount.decode(ldrAccountData, this._program.idl);
28384
28462
  console.log("ldrAccount", ldrAccount);
28385
28463
  if (!bankData) throw new Error("Failed to simulate");
28386
- const previewBanks = new Map(this.client.banks);
28464
+ const previewBanks = new Map(this.banks);
28387
28465
  banksToInspect.forEach((bankAddress, idx) => {
28388
28466
  const data = bankData[idx];
28389
28467
  if (!data) throw new Error("Failed to simulate");
@@ -28398,7 +28476,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28398
28476
  wallet: {},
28399
28477
  isReadOnly: true,
28400
28478
  group: this.client.group,
28401
- banks: this.client.banks,
28479
+ banks: previewBanks,
28402
28480
  priceInfos: this.client.oraclePrices,
28403
28481
  mintDatas: this.client.mintDatas,
28404
28482
  feedIdMap: this.client.feedIdMap,
@@ -28430,7 +28508,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28430
28508
  if (!tokenProgramAddress) throw Error("Repay mint not found");
28431
28509
  return this._lendrAccount.makeRepayIx(
28432
28510
  this._program,
28433
- this.client.banks,
28511
+ this.banks,
28434
28512
  this.client.mintDatas,
28435
28513
  amount,
28436
28514
  bankAddress,
@@ -28454,7 +28532,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28454
28532
  if (!tokenProgramAddress) throw Error("Repay mint not found");
28455
28533
  return this._lendrAccount.makeRepayWithSessionIx(
28456
28534
  this._program,
28457
- this.client.banks,
28535
+ this.banks,
28458
28536
  this.client.mintDatas,
28459
28537
  amount,
28460
28538
  bankAddress,
@@ -28583,7 +28661,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28583
28661
  if (!this.client.bankMetadataMap) throw Error("Bank metadata map not found");
28584
28662
  return this._lendrAccount.makeWithdrawIx(
28585
28663
  this._program,
28586
- this.client.banks,
28664
+ this.banks,
28587
28665
  this.client.mintDatas,
28588
28666
  this.client.bankMetadataMap,
28589
28667
  amount,
@@ -28609,7 +28687,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28609
28687
  if (!this.client.bankMetadataMap) throw Error("Bank metadata map not found");
28610
28688
  return this._lendrAccount.makeWithdrawWithSessionIx(
28611
28689
  this._program,
28612
- this.client.banks,
28690
+ this.banks,
28613
28691
  this.client.mintDatas,
28614
28692
  this.client.bankMetadataMap,
28615
28693
  amount,
@@ -28646,7 +28724,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28646
28724
  const mintAuthority = findPoolMintAuthorityAddress(pool);
28647
28725
  const lstAta = (0, import_spl_token7.getAssociatedTokenAddressSync)(lstMint, this.authority);
28648
28726
  const rentExemption = await this._program.provider.connection.getMinimumBalanceForRentExemption(200);
28649
- const stakeAmount = new import_bignumber15.default(new import_bignumber15.default(amount).toString());
28727
+ const stakeAmount = new import_bignumber16.default(new import_bignumber16.default(amount).toString());
28650
28728
  const withdrawIxs = await this.makeWithdrawIx(amount, bankAddress, isWholePosition, {
28651
28729
  createAtas: true,
28652
28730
  wrapAndUnwrapSol: true
@@ -28927,7 +29005,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28927
29005
  if (!this.client.bankMetadataMap) throw Error("Bank metadata map not found");
28928
29006
  return this._lendrAccount.makeBorrowIx(
28929
29007
  this._program,
28930
- this.client.banks,
29008
+ this.banks,
28931
29009
  this.client.mintDatas,
28932
29010
  this.client.bankMetadataMap,
28933
29011
  amount,
@@ -28950,7 +29028,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28950
29028
  if (!this.client.bankMetadataMap) throw Error("Bank metadata map not found");
28951
29029
  return this._lendrAccount.makeBorrowWithSessionIx(
28952
29030
  this._program,
28953
- this.client.banks,
29031
+ this.banks,
28954
29032
  this.client.mintDatas,
28955
29033
  this.client.bankMetadataMap,
28956
29034
  amount,
@@ -29122,12 +29200,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29122
29200
  * @returns An InstructionsWrapper containing the withdraw emissions instructions
29123
29201
  */
29124
29202
  async makeWithdrawEmissionsIx(bankAddress) {
29125
- return this._lendrAccount.makeWithdrawEmissionsIx(
29126
- this._program,
29127
- this.client.banks,
29128
- this.client.mintDatas,
29129
- bankAddress
29130
- );
29203
+ return this._lendrAccount.makeWithdrawEmissionsIx(this._program, this.banks, this.client.mintDatas, bankAddress);
29131
29204
  }
29132
29205
  /**
29133
29206
  * Creates a versioned transaction for withdrawing emissions rewards from multiple lendr bank accounts.
@@ -29204,7 +29277,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29204
29277
  return this._lendrAccount.makeLendingAccountLiquidateIx(
29205
29278
  liquidateeLendrAccount,
29206
29279
  this._program,
29207
- this.client.banks,
29280
+ this.banks,
29208
29281
  this.client.mintDatas,
29209
29282
  this.client.bankMetadataMap,
29210
29283
  assetBankAddress,
@@ -29277,7 +29350,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29277
29350
  * @returns An InstructionsWrapper containing the end flash loan instruction
29278
29351
  */
29279
29352
  async makeEndFlashLoanIx(projectedActiveBalances) {
29280
- return this._lendrAccount.makeEndFlashLoanIx(this._program, this.client.banks, projectedActiveBalances);
29353
+ return this._lendrAccount.makeEndFlashLoanIx(this._program, this.banks, projectedActiveBalances);
29281
29354
  }
29282
29355
  /**
29283
29356
  * Creates an instruction to end a flash loan operation.
@@ -29289,7 +29362,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29289
29362
  async makeEndFlashLoanWithSessionIx(projectedActiveBalances, session) {
29290
29363
  return this._lendrAccount.makeEndFlashLoanWithSessionIx(
29291
29364
  this._program,
29292
- this.client.banks,
29365
+ this.banks,
29293
29366
  projectedActiveBalances,
29294
29367
  session.sessionPublicKey
29295
29368
  );
@@ -29390,7 +29463,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29390
29463
  async makePulseHealthIx(mandatoryBanks = [], excludedBanks = []) {
29391
29464
  return this._lendrAccount.makePulseHealthIx(
29392
29465
  this._program,
29393
- this.client.banks,
29466
+ this.banks,
29394
29467
  mandatoryBanks,
29395
29468
  excludedBanks,
29396
29469
  this.client.bankMetadataMap || {}
@@ -29427,9 +29500,10 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29427
29500
  }
29428
29501
  _updateFromAccountParsed(data) {
29429
29502
  this._lendrAccount = LendrAccount.fromAccountParsed(this.address, data);
29503
+ this.banks = _LendrAccountWrapper.applyEmode(this.client.banks, this._lendrAccount);
29430
29504
  }
29431
29505
  describe() {
29432
- return this._lendrAccount.describe(this.client.banks, this.client.oraclePrices);
29506
+ return this._lendrAccount.describe(this.banks, this.client.oraclePrices);
29433
29507
  }
29434
29508
  // --------------------------------------------------------------------------
29435
29509
  // DEPRECATED METHODS
@@ -29484,7 +29558,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29484
29558
  const simulation = await this.client.simulateTransactions([tx], [this._lendrAccount.address]);
29485
29559
  const rawBuffer = simulation[0];
29486
29560
  if (!rawBuffer) {
29487
- return new import_bignumber15.default(0);
29561
+ return new import_bignumber16.default(0);
29488
29562
  }
29489
29563
  const simulatedLendrAccount = LendrAccount.fromAccountDataRaw(this.address, rawBuffer, this.client.program.idl);
29490
29564
  const outstandingEmissions = simulatedLendrAccount.getBalance(bank).emissionsOutstanding;
@@ -30076,7 +30150,7 @@ var LendrClient = class _LendrClient {
30076
30150
  const oracle = priceInfos.get(bankAddress.toBase58());
30077
30151
  if (oracle) {
30078
30152
  const adjustPrice = (price, stakeActual2, tokenSupply2) => {
30079
- return Number(tokenSupply2) === 0 ? price : new import_bignumber16.default(price.toNumber() * (stakeActual2 - import_web332.LAMPORTS_PER_SOL) / Number(tokenSupply2));
30153
+ return Number(tokenSupply2) === 0 ? price : new import_bignumber17.default(price.toNumber() * (stakeActual2 - import_web332.LAMPORTS_PER_SOL) / Number(tokenSupply2));
30080
30154
  };
30081
30155
  const adjustPriceComponent2 = (priceComponent, stakeActual2, tokenSupply2) => ({
30082
30156
  price: adjustPrice(priceComponent.price, stakeActual2, tokenSupply2),
@@ -30818,6 +30892,7 @@ var EmodeSettings = class _EmodeSettings {
30818
30892
  WSOL_MINT,
30819
30893
  accountFlagToBN,
30820
30894
  addOracleToBanksIx,
30895
+ adjustBanksWithEmode,
30821
30896
  balanceToDto,
30822
30897
  bankConfigRawToDto,
30823
30898
  bankConfigToBankConfigRaw,
@@ -30897,6 +30972,7 @@ var EmodeSettings = class _EmodeSettings {
30897
30972
  getBankVaultSeeds,
30898
30973
  getConfig,
30899
30974
  getConfigPda,
30975
+ getEmodePairs,
30900
30976
  getHealthCacheStatusDescription,
30901
30977
  getLiabilityQuantity,
30902
30978
  getLiabilityShares,
@@ -30919,6 +30995,7 @@ var EmodeSettings = class _EmodeSettings {
30919
30995
  lendrAccountToDto,
30920
30996
  makeAddPermissionlessStakedBankIx,
30921
30997
  makeBundleTipIx,
30998
+ makeEmodeAssetWeights,
30922
30999
  makePoolAddBankIx,
30923
31000
  makePoolConfigureBankIx,
30924
31001
  makePriorityFeeIx,