@pyron-finance/pyron-client 2.9.4 → 2.10.0

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