@pyron-finance/pyron-client 2.9.5 → 2.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.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
26083
- );
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
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 */
26121
25802
  );
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
25803
+ const { assets: assetValueInitial, liabilities: liabilityValueInitial } = computeHealthComponentsLegacy(
25804
+ activeBalances,
25805
+ props.bankMap,
25806
+ props.oraclePrices,
25807
+ 0 /* Initial */
26164
25808
  );
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
+ )
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);
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
+ );
26198
25879
  }
26199
- computeAssetUsdValue(oraclePrice, assetShares, lendrRequirementType, priceBias) {
26200
- return computeAssetUsdValue(this, oraclePrice, assetShares, 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");
26201
25897
  }
26202
- computeLiabilityUsdValue(oraclePrice, liabilityShares, lendrRequirementType, priceBias) {
26203
- return computeLiabilityUsdValue(this, oraclePrice, liabilityShares, lendrRequirementType, priceBias);
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");
26204
25902
  }
26205
- computeUsdValue(oraclePrice, quantity, priceBias, weightedPrice, weight, scaleToBase = true) {
26206
- return computeUsdValue(this, oraclePrice, quantity, priceBias, weightedPrice, weight, scaleToBase);
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
25930
+ });
25931
+ throw new HealthCacheSimulationError(
25932
+ "Account health cache simulation failed",
25933
+ lendrAccountPost.healthCache.lndrErr,
25934
+ lendrAccountPost.healthCache.internalErr
25935
+ );
26207
25936
  }
26208
- getAssetWeight(lendrRequirementType, oraclePrice, ignoreSoftLimits = false, assetWeightInitOverride) {
26209
- return getAssetWeight(this, lendrRequirementType, oraclePrice, {
26210
- ignoreSoftLimits,
26211
- assetWeightInitOverride
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
+ }
26212
26037
  });
26038
+ return { stalePythFeeds, staleSwbOracles };
26213
26039
  }
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);
26231
- }
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)}
26239
-
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
- )}
26040
+ return { stalePythFeeds: [], staleSwbOracles: [] };
26041
+ }
26252
26042
 
26253
- Asset price (USD): ${_Bank.getPrice(oraclePrice, 1 /* None */, false)}
26254
- Asset price Weighted (USD): ${_Bank.getPrice(oraclePrice, 1 /* None */, true)}
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
+ }
26255
26134
 
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)}
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
+ }
26261
26143
 
26262
- - Deposit limit: ${this.config.depositLimit}
26263
- - Borrow limit: ${this.config.borrowLimit}
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
+ }
26264
26151
 
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;
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
+ }
26170
+
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,50 +27622,35 @@ 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
  );
27551
27629
  return new _LendrAccountWrapper(this.address, this.client, account);
27552
27630
  }
27553
27631
  canBeLiquidated() {
27554
- let { assets, liabilities } = this._lendrAccount.computeHealthComponents(1 /* Maintenance */);
27555
- if (assets.isZero() && liabilities.isZero()) {
27556
- const legacy = this._lendrAccount.computeHealthComponentsLegacy(
27557
- this.client.banks,
27558
- this.client.oraclePrices,
27559
- 1 /* Maintenance */
27560
- );
27561
- assets = legacy.assets;
27562
- liabilities = legacy.liabilities;
27563
- this.client.logger.debug(
27564
- {
27565
- address: this.address.toBase58(),
27566
- assets,
27567
- liabilities,
27568
- usedLegacy: true
27569
- },
27570
- "[lendr:lendr-account:canBeLiquidated]"
27571
- );
27572
- } else {
27573
- this.client.logger.debug(
27574
- {
27575
- address: this.address.toBase58(),
27576
- assets,
27577
- liabilities
27578
- },
27579
- "[lendr:lendr-account:canBeLiquidated]"
27580
- );
27581
- }
27632
+ const { assets, liabilities } = this.computeHealthComponents(1 /* Maintenance */);
27633
+ this.client.logger.debug(
27634
+ {
27635
+ address: this.address.toBase58(),
27636
+ assets,
27637
+ liabilities
27638
+ },
27639
+ "[lendr:lendr-account:canBeLiquidated]"
27640
+ );
27582
27641
  return assets.lt(liabilities);
27583
27642
  }
27584
27643
  computeHealthComponents(lendrRequirement) {
27585
- return this._lendrAccount.computeHealthComponents(lendrRequirement);
27644
+ const cached = this._lendrAccount.computeHealthComponents(lendrRequirement);
27645
+ if (cached.assets.isZero() && cached.liabilities.isZero()) {
27646
+ return this.computeHealthComponentsLegacy(lendrRequirement);
27647
+ }
27648
+ return cached;
27586
27649
  }
27587
27650
  // TODO)) migrate to computeHealthComponents
27588
27651
  computeHealthComponentsLegacy(lendrRequirement, excludedBanks = []) {
27589
27652
  return this._lendrAccount.computeHealthComponentsLegacy(
27590
- this.client.banks,
27653
+ this.banks,
27591
27654
  this.client.oraclePrices,
27592
27655
  lendrRequirement,
27593
27656
  excludedBanks
@@ -27595,7 +27658,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27595
27658
  }
27596
27659
  computeHealthComponentsWithoutBiasLegacy(lendrRequirement) {
27597
27660
  return this._lendrAccount.computeHealthComponentsWithoutBiasLegacy(
27598
- this.client.banks,
27661
+ this.banks,
27599
27662
  this.client.oraclePrices,
27600
27663
  lendrRequirement
27601
27664
  );
@@ -27604,7 +27667,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27604
27667
  return this._lendrAccount.computeFreeCollateral(opts);
27605
27668
  }
27606
27669
  computeFreeCollateralLegacy(opts) {
27607
- return this._lendrAccount.computeFreeCollateralLegacy(this.client.banks, this.client.oraclePrices, opts);
27670
+ return this._lendrAccount.computeFreeCollateralLegacy(this.banks, this.client.oraclePrices, opts);
27608
27671
  }
27609
27672
  computeAccountValue() {
27610
27673
  return this._lendrAccount.computeAccountValue();
@@ -27615,12 +27678,12 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27615
27678
  computeEmodeImpacts(emodePairs) {
27616
27679
  return this._lendrAccount.computeEmodeImpacts(
27617
27680
  emodePairs,
27618
- Array.from(this.client.banks.keys()).map((b) => new import_web331.PublicKey(b))
27681
+ Array.from(this.banks.keys()).map((b) => new import_web331.PublicKey(b))
27619
27682
  );
27620
27683
  }
27621
27684
  computeMaxBorrowForBank(bankAddress, opts) {
27622
27685
  return this._lendrAccount.computeMaxBorrowForBank(
27623
- this.client.banks,
27686
+ this.banks,
27624
27687
  this.client.oraclePrices,
27625
27688
  bankAddress,
27626
27689
  opts,
@@ -27628,11 +27691,11 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27628
27691
  );
27629
27692
  }
27630
27693
  computeMaxWithdrawForBank(bankAddress, opts) {
27631
- return this._lendrAccount.computeMaxWithdrawForBank(this.client.banks, this.client.oraclePrices, bankAddress, opts);
27694
+ return this._lendrAccount.computeMaxWithdrawForBank(this.banks, this.client.oraclePrices, bankAddress, opts);
27632
27695
  }
27633
27696
  computeMaxLiquidatableAssetAmount(assetBankAddress, liabilityBankAddress) {
27634
27697
  return this._lendrAccount.computeMaxLiquidatableAssetAmount(
27635
- this.client.banks,
27698
+ this.banks,
27636
27699
  this.client.oraclePrices,
27637
27700
  assetBankAddress,
27638
27701
  liabilityBankAddress,
@@ -27640,11 +27703,11 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27640
27703
  );
27641
27704
  }
27642
27705
  computeLiquidationPriceForBank(bankAddress) {
27643
- return this._lendrAccount.computeLiquidationPriceForBank(this.client.banks, this.client.oraclePrices, bankAddress);
27706
+ return this._lendrAccount.computeLiquidationPriceForBank(this.banks, this.client.oraclePrices, bankAddress);
27644
27707
  }
27645
27708
  computeLiquidationPriceForBankAmount(bankAddress, isLending, amount) {
27646
27709
  return this._lendrAccount.computeLiquidationPriceForBankAmount(
27647
- this.client.banks,
27710
+ this.banks,
27648
27711
  this.client.oraclePrices,
27649
27712
  bankAddress,
27650
27713
  isLending,
@@ -27652,15 +27715,15 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27652
27715
  );
27653
27716
  }
27654
27717
  computeNetApy() {
27655
- return this._lendrAccount.computeNetApy(this.client.banks, this.client.oraclePrices);
27718
+ return this._lendrAccount.computeNetApy(this.banks, this.client.oraclePrices);
27656
27719
  }
27657
27720
  /** Todo move this into client */
27658
27721
  computeLoopingParams(principal, targetLeverage, depositBankAddress, borrowBankAddress) {
27659
- const depositBank = this.client.banks.get(depositBankAddress.toBase58());
27722
+ const depositBank = this.banks.get(depositBankAddress.toBase58());
27660
27723
  if (!depositBank) throw Error(`Bank ${depositBankAddress.toBase58()} not found`);
27661
27724
  const depositPriceInfo = this.client.oraclePrices.get(depositBankAddress.toBase58());
27662
27725
  if (!depositPriceInfo) throw Error(`Price info for ${depositBankAddress.toBase58()} not found`);
27663
- const borrowBank = this.client.banks.get(borrowBankAddress.toBase58());
27726
+ const borrowBank = this.banks.get(borrowBankAddress.toBase58());
27664
27727
  if (!borrowBank) throw Error(`Bank ${borrowBankAddress.toBase58()} not found`);
27665
27728
  const borrowPriceInfo = this.client.oraclePrices.get(borrowBankAddress.toBase58());
27666
27729
  if (!borrowPriceInfo) throw Error(`Price info for ${borrowBankAddress.toBase58()} not found`);
@@ -27957,9 +28020,9 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27957
28020
  },
27958
28021
  "[lendr:lendr-account:loop] Looping into Lendr account"
27959
28022
  );
27960
- const depositBank = this.client.banks.get(props.depositBankAddress.toBase58());
28023
+ const depositBank = this.banks.get(props.depositBankAddress.toBase58());
27961
28024
  if (!depositBank) throw Error("Deposit bank not found");
27962
- const borrowBank = this.client.banks.get(props.borrowBankAddress.toBase58());
28025
+ const borrowBank = this.banks.get(props.borrowBankAddress.toBase58());
27963
28026
  if (!borrowBank) throw Error("Borrow bank not found");
27964
28027
  const { processOpts, txOpts, ...txProps } = props;
27965
28028
  const { transactions } = await this.makeLoopTxV2(txProps);
@@ -27984,9 +28047,9 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
27984
28047
  setupBankAddresses,
27985
28048
  overrideInferAccounts
27986
28049
  }) {
27987
- const depositBank = this.client.banks.get(depositBankAddress.toBase58());
28050
+ const depositBank = this.banks.get(depositBankAddress.toBase58());
27988
28051
  if (!depositBank) throw Error("Deposit bank not found");
27989
- const borrowBank = this.client.banks.get(borrowBankAddress.toBase58());
28052
+ const borrowBank = this.banks.get(borrowBankAddress.toBase58());
27990
28053
  if (!borrowBank) throw Error("Borrow bank not found");
27991
28054
  const blockhash = blockhashArg ?? (await this._program.provider.connection.getLatestBlockhash("confirmed")).blockhash;
27992
28055
  const setupIxs = await this.makeSetupIx(setupBankAddresses ?? [borrowBankAddress, depositBankAddress]);
@@ -28010,7 +28073,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28010
28073
  let flashloanTx;
28011
28074
  let txOverflown = false;
28012
28075
  if (depositBank.mint.equals(import_spl_token7.NATIVE_MINT) && inputDepositAmount) {
28013
- setupIxs.push(...makeWrapSolIxs(this.authority, new import_bignumber15.default(inputDepositAmount)));
28076
+ setupIxs.push(...makeWrapSolIxs(this.authority, new import_bignumber16.default(inputDepositAmount)));
28014
28077
  }
28015
28078
  if (setupIxs.length > 0) {
28016
28079
  const message = new import_web331.TransactionMessage({
@@ -28127,7 +28190,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28127
28190
  async makeDepositIx(amount, bankAddress, depositOpts = {}) {
28128
28191
  return this._lendrAccount.makeDepositIx(
28129
28192
  this._program,
28130
- this.client.banks,
28193
+ this.banks,
28131
28194
  this.client.mintDatas,
28132
28195
  amount,
28133
28196
  bankAddress,
@@ -28137,7 +28200,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28137
28200
  async makeDepositWithSessionIx(amount, bankAddress, session, depositOpts = {}) {
28138
28201
  return this._lendrAccount.makeDepositWithSessionIx(
28139
28202
  this._program,
28140
- this.client.banks,
28203
+ this.banks,
28141
28204
  this.client.mintDatas,
28142
28205
  amount,
28143
28206
  bankAddress,
@@ -28383,7 +28446,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28383
28446
  const ldrAccount = LendrAccount.decode(ldrAccountData, this._program.idl);
28384
28447
  console.log("ldrAccount", ldrAccount);
28385
28448
  if (!bankData) throw new Error("Failed to simulate");
28386
- const previewBanks = new Map(this.client.banks);
28449
+ const previewBanks = new Map(this.banks);
28387
28450
  banksToInspect.forEach((bankAddress, idx) => {
28388
28451
  const data = bankData[idx];
28389
28452
  if (!data) throw new Error("Failed to simulate");
@@ -28398,7 +28461,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28398
28461
  wallet: {},
28399
28462
  isReadOnly: true,
28400
28463
  group: this.client.group,
28401
- banks: this.client.banks,
28464
+ banks: previewBanks,
28402
28465
  priceInfos: this.client.oraclePrices,
28403
28466
  mintDatas: this.client.mintDatas,
28404
28467
  feedIdMap: this.client.feedIdMap,
@@ -28430,7 +28493,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28430
28493
  if (!tokenProgramAddress) throw Error("Repay mint not found");
28431
28494
  return this._lendrAccount.makeRepayIx(
28432
28495
  this._program,
28433
- this.client.banks,
28496
+ this.banks,
28434
28497
  this.client.mintDatas,
28435
28498
  amount,
28436
28499
  bankAddress,
@@ -28454,7 +28517,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28454
28517
  if (!tokenProgramAddress) throw Error("Repay mint not found");
28455
28518
  return this._lendrAccount.makeRepayWithSessionIx(
28456
28519
  this._program,
28457
- this.client.banks,
28520
+ this.banks,
28458
28521
  this.client.mintDatas,
28459
28522
  amount,
28460
28523
  bankAddress,
@@ -28583,7 +28646,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28583
28646
  if (!this.client.bankMetadataMap) throw Error("Bank metadata map not found");
28584
28647
  return this._lendrAccount.makeWithdrawIx(
28585
28648
  this._program,
28586
- this.client.banks,
28649
+ this.banks,
28587
28650
  this.client.mintDatas,
28588
28651
  this.client.bankMetadataMap,
28589
28652
  amount,
@@ -28609,7 +28672,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28609
28672
  if (!this.client.bankMetadataMap) throw Error("Bank metadata map not found");
28610
28673
  return this._lendrAccount.makeWithdrawWithSessionIx(
28611
28674
  this._program,
28612
- this.client.banks,
28675
+ this.banks,
28613
28676
  this.client.mintDatas,
28614
28677
  this.client.bankMetadataMap,
28615
28678
  amount,
@@ -28646,7 +28709,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28646
28709
  const mintAuthority = findPoolMintAuthorityAddress(pool);
28647
28710
  const lstAta = (0, import_spl_token7.getAssociatedTokenAddressSync)(lstMint, this.authority);
28648
28711
  const rentExemption = await this._program.provider.connection.getMinimumBalanceForRentExemption(200);
28649
- const stakeAmount = new import_bignumber15.default(new import_bignumber15.default(amount).toString());
28712
+ const stakeAmount = new import_bignumber16.default(new import_bignumber16.default(amount).toString());
28650
28713
  const withdrawIxs = await this.makeWithdrawIx(amount, bankAddress, isWholePosition, {
28651
28714
  createAtas: true,
28652
28715
  wrapAndUnwrapSol: true
@@ -28927,7 +28990,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28927
28990
  if (!this.client.bankMetadataMap) throw Error("Bank metadata map not found");
28928
28991
  return this._lendrAccount.makeBorrowIx(
28929
28992
  this._program,
28930
- this.client.banks,
28993
+ this.banks,
28931
28994
  this.client.mintDatas,
28932
28995
  this.client.bankMetadataMap,
28933
28996
  amount,
@@ -28950,7 +29013,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
28950
29013
  if (!this.client.bankMetadataMap) throw Error("Bank metadata map not found");
28951
29014
  return this._lendrAccount.makeBorrowWithSessionIx(
28952
29015
  this._program,
28953
- this.client.banks,
29016
+ this.banks,
28954
29017
  this.client.mintDatas,
28955
29018
  this.client.bankMetadataMap,
28956
29019
  amount,
@@ -29122,12 +29185,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29122
29185
  * @returns An InstructionsWrapper containing the withdraw emissions instructions
29123
29186
  */
29124
29187
  async makeWithdrawEmissionsIx(bankAddress) {
29125
- return this._lendrAccount.makeWithdrawEmissionsIx(
29126
- this._program,
29127
- this.client.banks,
29128
- this.client.mintDatas,
29129
- bankAddress
29130
- );
29188
+ return this._lendrAccount.makeWithdrawEmissionsIx(this._program, this.banks, this.client.mintDatas, bankAddress);
29131
29189
  }
29132
29190
  /**
29133
29191
  * Creates a versioned transaction for withdrawing emissions rewards from multiple lendr bank accounts.
@@ -29204,7 +29262,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29204
29262
  return this._lendrAccount.makeLendingAccountLiquidateIx(
29205
29263
  liquidateeLendrAccount,
29206
29264
  this._program,
29207
- this.client.banks,
29265
+ this.banks,
29208
29266
  this.client.mintDatas,
29209
29267
  this.client.bankMetadataMap,
29210
29268
  assetBankAddress,
@@ -29277,7 +29335,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29277
29335
  * @returns An InstructionsWrapper containing the end flash loan instruction
29278
29336
  */
29279
29337
  async makeEndFlashLoanIx(projectedActiveBalances) {
29280
- return this._lendrAccount.makeEndFlashLoanIx(this._program, this.client.banks, projectedActiveBalances);
29338
+ return this._lendrAccount.makeEndFlashLoanIx(this._program, this.banks, projectedActiveBalances);
29281
29339
  }
29282
29340
  /**
29283
29341
  * Creates an instruction to end a flash loan operation.
@@ -29289,7 +29347,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29289
29347
  async makeEndFlashLoanWithSessionIx(projectedActiveBalances, session) {
29290
29348
  return this._lendrAccount.makeEndFlashLoanWithSessionIx(
29291
29349
  this._program,
29292
- this.client.banks,
29350
+ this.banks,
29293
29351
  projectedActiveBalances,
29294
29352
  session.sessionPublicKey
29295
29353
  );
@@ -29390,7 +29448,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29390
29448
  async makePulseHealthIx(mandatoryBanks = [], excludedBanks = []) {
29391
29449
  return this._lendrAccount.makePulseHealthIx(
29392
29450
  this._program,
29393
- this.client.banks,
29451
+ this.banks,
29394
29452
  mandatoryBanks,
29395
29453
  excludedBanks,
29396
29454
  this.client.bankMetadataMap || {}
@@ -29427,9 +29485,10 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29427
29485
  }
29428
29486
  _updateFromAccountParsed(data) {
29429
29487
  this._lendrAccount = LendrAccount.fromAccountParsed(this.address, data);
29488
+ this.banks = _LendrAccountWrapper.applyEmode(this.client.banks, this._lendrAccount);
29430
29489
  }
29431
29490
  describe() {
29432
- return this._lendrAccount.describe(this.client.banks, this.client.oraclePrices);
29491
+ return this._lendrAccount.describe(this.banks, this.client.oraclePrices);
29433
29492
  }
29434
29493
  // --------------------------------------------------------------------------
29435
29494
  // DEPRECATED METHODS
@@ -29484,7 +29543,7 @@ var LendrAccountWrapper = class _LendrAccountWrapper {
29484
29543
  const simulation = await this.client.simulateTransactions([tx], [this._lendrAccount.address]);
29485
29544
  const rawBuffer = simulation[0];
29486
29545
  if (!rawBuffer) {
29487
- return new import_bignumber15.default(0);
29546
+ return new import_bignumber16.default(0);
29488
29547
  }
29489
29548
  const simulatedLendrAccount = LendrAccount.fromAccountDataRaw(this.address, rawBuffer, this.client.program.idl);
29490
29549
  const outstandingEmissions = simulatedLendrAccount.getBalance(bank).emissionsOutstanding;
@@ -30076,7 +30135,7 @@ var LendrClient = class _LendrClient {
30076
30135
  const oracle = priceInfos.get(bankAddress.toBase58());
30077
30136
  if (oracle) {
30078
30137
  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));
30138
+ return Number(tokenSupply2) === 0 ? price : new import_bignumber17.default(price.toNumber() * (stakeActual2 - import_web332.LAMPORTS_PER_SOL) / Number(tokenSupply2));
30080
30139
  };
30081
30140
  const adjustPriceComponent2 = (priceComponent, stakeActual2, tokenSupply2) => ({
30082
30141
  price: adjustPrice(priceComponent.price, stakeActual2, tokenSupply2),
@@ -30818,6 +30877,7 @@ var EmodeSettings = class _EmodeSettings {
30818
30877
  WSOL_MINT,
30819
30878
  accountFlagToBN,
30820
30879
  addOracleToBanksIx,
30880
+ adjustBanksWithEmode,
30821
30881
  balanceToDto,
30822
30882
  bankConfigRawToDto,
30823
30883
  bankConfigToBankConfigRaw,
@@ -30897,6 +30957,7 @@ var EmodeSettings = class _EmodeSettings {
30897
30957
  getBankVaultSeeds,
30898
30958
  getConfig,
30899
30959
  getConfigPda,
30960
+ getEmodePairs,
30900
30961
  getHealthCacheStatusDescription,
30901
30962
  getLiabilityQuantity,
30902
30963
  getLiabilityShares,
@@ -30919,6 +30980,7 @@ var EmodeSettings = class _EmodeSettings {
30919
30980
  lendrAccountToDto,
30920
30981
  makeAddPermissionlessStakedBankIx,
30921
30982
  makeBundleTipIx,
30983
+ makeEmodeAssetWeights,
30922
30984
  makePoolAddBankIx,
30923
30985
  makePoolConfigureBankIx,
30924
30986
  makePriorityFeeIx,