@1delta/margin-fetcher 5.0.89 → 5.0.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
- import { parseAbi, keccak256, encodeAbiParameters, formatEther, BaseError, erc20Abi, stringToHex, isAddress, pad, encodeFunctionData, formatUnits, getAddress, decodeFunctionResult, decodeAbiParameters, toBytes, slice, concat, AbiEncodingLengthMismatchError, concatHex, parseAbiParameters, hexToString, InvalidAddressError, boolToHex, integerRegex, numberToHex, bytesRegex, BytesSizeMismatchError, arrayRegex, UnsupportedPackedAbiType } from './chunk-JUYF2XLF.js';
1
+ import { parseAbi, keccak256, encodeAbiParameters, formatEther, BaseError, erc20Abi, isAddress, stringToHex, pad, encodeFunctionData, formatUnits, getAddress, decodeFunctionResult, decodeAbiParameters, toBytes, slice, concat, AbiEncodingLengthMismatchError, concatHex, parseAbiParameters, hexToString, InvalidAddressError, boolToHex, integerRegex, numberToHex, bytesRegex, BytesSizeMismatchError, arrayRegex, UnsupportedPackedAbiType } from './chunk-JUYF2XLF.js';
2
2
  import './chunk-BYTNVMX7.js';
3
3
  import './chunk-PR4QN5HX.js';
4
4
  import { Lender, isExactly, isMidnight, isTerm, isTermMax, isTeller, isListaDao, isLiquityFamily, isRiver, isInverse, isCooler, isDssType, isCompoundV3Type, isFluid, isGearboxV3, isLlamaLend, isFrankencoin, isResupply, isCurvance, isFlyingTulip, isTwyne, isFraxlend, isAaveV4Type, LIQUITY_FAMILY_LENDERS, isAaveType, isCompoundV3, isCompoundV2Type, isMultiMarket, isSiloV2Type, isSiloV3Type, isDolomite, isMorphoType, isUsdd, isSky, hasCrossMarginRisk, isEulerType, isInit, isVenusType, isSumerType, AAVE_V3_LENDERS, AAVE_V2_LENDERS, isMorphoBlue, isAaveV2Type, isAaveV32Type, isAaveV3Type, isYLDR, isLista, hasSubAccounts, isTectonicType, isKineticType, isBenqiType } from '@1delta/lender-registry';
5
5
  export { hasCrossMarginRisk, isAaveType, isAaveV2Type, isAaveV32Type, isAaveV3Type, isCompoundV3, isCompoundV3Type, isInit, isMorphoType, isMultiMarket, isYLDR } from '@1delta/lender-registry';
6
- import { fetchTokenLists, fetchTokenList, aavePools, compoundV3Pools, initConfig, morphoPools, compoundV2Pools, eulerVaults, siloMarkets, siloV2LenderKey, siloMarketsV3, siloV3LenderKey, aaveV4Spokes, aaveV4SpokeLenderKey, fluidResolvers, gearboxResolvers, dolomiteConfigs, midnightConfig, termConfig, termMarketsByChain, exactlyConfig, flyingTulipLendersByChain, liquityLendersByChain, riverLendersByChain, inverseLendersByChain, coolerLendersByChain, llamaLendLendersByChain, usddLendersByChain, skyLendersByChain, frankencoinLendersByChain, resupplyLendersByChain, curvanceLendersByChain, fraxlendLendersByChain, twyneLendersByChain, tellerConfigByChain, tellerPoolsByChain, termMaxConfigByChain, aaveReserves, compoundV3Reserves, dolomiteIsolationMarket, morphoTypeMarkets, resolveTermApiBase, flyingTulipConfigFor, flyingTulipAssetsFor, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, termMaxApiBaseUrl, termMaxLenderKey, inverseConfigFor, inverseChainData, coolerConfigFor, llamaLendConfigFor, llamaLendChainData, llamaLendApiBaseUrl, resupplyConfigFor, fraxlendConfigFor, dssConfigFor, dssChainData, dssDebtToken, dssDebtJoin, frankencoinConfigFor, frankencoinChainData, aaveOracles, resolveMidnightApiBase, llamaLendMarketByVault, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, dolomiteIsolation, curvanceConfigFor, aaveTokens, morphoTypeVaults, listaCollateralProvider, eulerConfigs, gearboxMarketCompressor, gearboxMarketConfigurators, compoundV2TokenArray, gearboxV3LenderKey, midnightMarketsByChain, twyneConfigFor, twyneChainData, midnightCollateralRef, parseAaveV4SpokeLenderKey, fraxlendPairsFor, gearboxAccountCompressor, compoundV2Tokens, exactlyMarketsByChain, aaveOraclesConfig, compoundV2Oracles, compoundV2OraclesConfig, compoundV3OraclesData, compoundV3BaseData, compoundV2Reserves, aaveV4Oracles, morphoTypeOracles } from '@1delta/data-sdk';
6
+ import { fetchTokenLists, fetchTokenList, aavePools, compoundV3Pools, initConfig, morphoPools, compoundV2Pools, eulerVaults, siloMarkets, siloV2LenderKey, siloMarketsV3, siloV3LenderKey, aaveV4Spokes, aaveV4SpokeLenderKey, fluidResolvers, gearboxResolvers, dolomiteConfigs, midnightConfig, termConfig, termMarketsByChain, exactlyConfig, flyingTulipLendersByChain, liquityLendersByChain, riverLendersByChain, inverseLendersByChain, coolerLendersByChain, llamaLendLendersByChain, usddLendersByChain, skyLendersByChain, frankencoinLendersByChain, resupplyLendersByChain, curvanceLendersByChain, fraxlendLendersByChain, twyneLendersByChain, tellerConfigByChain, tellerPoolsByChain, termMaxConfigByChain, aaveReserves, compoundV3Reserves, dolomiteIsolationMarket, morphoTypeMarkets, resolveTermApiBase, flyingTulipConfigFor, flyingTulipAssetsFor, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, termMaxApiBaseUrl, termMaxLenderKey, inverseConfigFor, inverseChainData, coolerConfigFor, llamaLendConfigFor, llamaLendChainData, llamaLendApiBaseUrl, resupplyConfigFor, fraxlendConfigFor, dssConfigFor, dssChainData, dssDebtToken, dssDebtJoin, frankencoinConfigFor, frankencoinChainData, aaveTokens, compoundV3BaseData, compoundV2TokenArray, morphoTypeVaults, eulerConfigs, fluidVaultEntries, gearboxMarketConfigurators, dolomiteIsolation, liquityMarkets, riverMarkets, tellerConfig, tellerPools, termMarkets, termMaxConfig, midnightMarkets, midnightCollateralRef, llamaLendMarkets, fraxlendPairsFor, inverseMarkets, curvanceConfig, frankencoinMarkets, twyneMarkets, twyneConfigFor, exactlyMarkets, aaveOracles, resolveMidnightApiBase, llamaLendMarketByVault, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, curvanceConfigFor, listaCollateralProvider, gearboxMarketCompressor, gearboxV3LenderKey, midnightMarketsByChain, twyneChainData, parseAaveV4SpokeLenderKey, gearboxAccountCompressor, compoundV2Tokens, exactlyMarketsByChain, aaveOraclesConfig, compoundV2Oracles, compoundV2OraclesConfig, compoundV3OraclesData, compoundV2Reserves, aaveV4Oracles, morphoTypeOracles } from '@1delta/data-sdk';
7
7
  import lodash from 'lodash';
8
8
  import { Chain, isEvmChainId } from '@1delta/chain-registry';
9
9
  import { multicallRetryUniversal, getEvmClient, getEvmChain, createMulticallRetryUniversal, LIST_OVERRIDES, getEvmClientUniversal } from '@1delta/providers';
@@ -12,6 +12,7 @@ export { MorphoLensAbi } from '@1delta/abis';
12
12
  import { prepareDebitDataMulticall, prepareLenderDebitMulticall, parseDebitDataResult, parseLenderDebitResult, getPermit2ContractAddress, getLstAcceptedInputs, savingsVerbRequires, savingsSupportsVerb, getCompoundV2Comptroller as getCompoundV2Comptroller$1, getCompoundV3CometAddress as getCompoundV3CometAddress$1, getMorphoAddress, FLUID_VAULT_FACTORY, getAaveStyleLenderTokenAddress, LendingMode, getAaveCollateralTokenAddress, getSiloHalfForUnderlying, findSavingsWithdrawEntry, bandLtvCurve, InitMarginAddresses, ignoresReceiver, buildLstWithdrawRequest, SAVINGS_RECEIVER_CAPABILITY } from '@1delta/calldata-sdk';
13
13
  import { proxyNativeFetch } from '@1delta/proxy-fetch';
14
14
  import { BALANCER_V2_FORKS, BALANCER_V3_FORKS, UNISWAP_V4_FORKS, isFlashLoanSourceExcluded, FLASH_LOAN_IDS } from '@1delta/dex-registry';
15
+ import { getNativeDecimals } from '@1delta/wnative';
15
16
 
16
17
  // src/abis/aave-v2/ProtocolDataProvider.ts
17
18
  var ProtocolDataProviderAbi = [
@@ -6754,6 +6755,12 @@ var buildAaveV3StyleLenderReserveCall = (chainId, lender) => {
6754
6755
  }
6755
6756
  }
6756
6757
  };
6758
+ function getInitPosManagerAddress(chainId) {
6759
+ return addressesInitCore.PosManager[chainId];
6760
+ }
6761
+ function getInitCoreAddress(chainId) {
6762
+ return addressesInitCore.Core[chainId];
6763
+ }
6757
6764
  function getInitLensAddress(chainId) {
6758
6765
  return addressesInitCore.PublicLens[chainId];
6759
6766
  }
@@ -7326,15 +7333,15 @@ var getAaveV2ReservesDataConverter = (lender, chainId, prices, additionalYields,
7326
7333
  isActive: configData?.[8 /* isActive */],
7327
7334
  isFrozen: configData?.[9 /* isFrozen */]
7328
7335
  };
7329
- const aaveTokens3 = aaveTokenMap[asset];
7330
- if (!!aaveTokens3) {
7336
+ const aaveTokens4 = aaveTokenMap[asset];
7337
+ if (!!aaveTokens4) {
7331
7338
  resultReserves[marketUid] = {
7332
7339
  ...resultReserves[marketUid],
7333
7340
  params: {
7334
7341
  metadata: {
7335
- aToken: aaveTokens3.aToken,
7336
- vToken: aaveTokens3.vToken,
7337
- sToken: aaveTokens3.sToken
7342
+ aToken: aaveTokens4.aToken,
7343
+ vToken: aaveTokens4.vToken,
7344
+ sToken: aaveTokens4.sToken
7338
7345
  }
7339
7346
  }
7340
7347
  };
@@ -7564,15 +7571,15 @@ var getAaveV3ReservesDataConverter = (lender, chainId, prices, additionalYields,
7564
7571
  };
7565
7572
  })()
7566
7573
  };
7567
- const aaveTokens3 = aaveTokenMap[asset];
7568
- if (!!aaveTokens3) {
7574
+ const aaveTokens4 = aaveTokenMap[asset];
7575
+ if (!!aaveTokens4) {
7569
7576
  resultReserves[marketUid] = {
7570
7577
  ...resultReserves[marketUid],
7571
7578
  params: {
7572
7579
  metadata: {
7573
- aToken: aaveTokens3.aToken,
7574
- vToken: aaveTokens3.vToken,
7575
- sToken: aaveTokens3.sToken
7580
+ aToken: aaveTokens4.aToken,
7581
+ vToken: aaveTokens4.vToken,
7582
+ sToken: aaveTokens4.sToken
7576
7583
  }
7577
7584
  }
7578
7585
  };
@@ -7803,15 +7810,15 @@ function parseYLDRCall(chainId, lender, additionalYields, prices, tokenList) {
7803
7810
  isActive: configData?.[7 /* isActive */],
7804
7811
  isFrozen: configData?.[8 /* isFrozen */]
7805
7812
  };
7806
- const aaveTokens3 = aaveTokenMap[asset];
7807
- if (!!aaveTokens3) {
7813
+ const aaveTokens4 = aaveTokenMap[asset];
7814
+ if (!!aaveTokens4) {
7808
7815
  resultReserves[marketUid] = {
7809
7816
  ...resultReserves[marketUid],
7810
7817
  params: {
7811
7818
  metadata: {
7812
- aToken: aaveTokens3.aToken,
7813
- vToken: aaveTokens3.vToken,
7814
- sToken: aaveTokens3.sToken
7819
+ aToken: aaveTokens4.aToken,
7820
+ vToken: aaveTokens4.vToken,
7821
+ sToken: aaveTokens4.sToken
7815
7822
  }
7816
7823
  }
7817
7824
  };
@@ -8003,15 +8010,15 @@ function parseAave32(chainId, lender, prices, additionalYields, tokenList) {
8003
8010
  };
8004
8011
  })()
8005
8012
  };
8006
- const aaveTokens3 = aaveTokenMap[asset];
8007
- if (!!aaveTokens3) {
8013
+ const aaveTokens4 = aaveTokenMap[asset];
8014
+ if (!!aaveTokens4) {
8008
8015
  resultReserves[marketUid] = {
8009
8016
  ...resultReserves[marketUid],
8010
8017
  params: {
8011
8018
  metadata: {
8012
- aToken: aaveTokens3.aToken,
8013
- vToken: aaveTokens3.vToken,
8014
- sToken: aaveTokens3.sToken
8019
+ aToken: aaveTokens4.aToken,
8020
+ vToken: aaveTokens4.vToken,
8021
+ sToken: aaveTokens4.sToken
8015
8022
  }
8016
8023
  }
8017
8024
  };
@@ -12166,6 +12173,21 @@ function createMultiAccountTypeUserState(payload, lenderData, histData) {
12166
12173
  data
12167
12174
  };
12168
12175
  }
12176
+ var isFixedTermLender = (lender) => isMidnight(lender) || isTerm(lender) || isTermMax(lender) || isTeller(lender) || isExactly(lender);
12177
+ function positionUnitKind(lenderKey, p) {
12178
+ const hasShares = p.depositShares !== void 0 || p.debtShares !== void 0;
12179
+ if (isMorphoType(lenderKey) && hasShares) return "morpho_shares";
12180
+ if (isCompoundV2Type(lenderKey) && p.depositShares !== void 0)
12181
+ return "ctoken";
12182
+ if ((isSiloV2Type(lenderKey) || isSiloV3Type(lenderKey)) && hasShares)
12183
+ return "silo_shares";
12184
+ if (isDolomite(lenderKey) && p.debtPar !== void 0) return "dolomite_par";
12185
+ if (isFixedTermLender(lenderKey)) return "face_value";
12186
+ return "resolved_amount";
12187
+ }
12188
+ function withUnitKind(lenderKey, p) {
12189
+ return p.unitKind ? p : { ...p, unitKind: positionUnitKind(lenderKey, p) };
12190
+ }
12169
12191
 
12170
12192
  // src/lending/user-data/utils/index.ts
12171
12193
  function divideAccrualsToAprs(aprs, nav, deposits, debt) {
@@ -18383,6 +18405,113 @@ var buildEulerV2LenderReserveCall = (chainId, lender) => {
18383
18405
  }));
18384
18406
  };
18385
18407
 
18408
+ // src/abis/multicall/Multicall.ts
18409
+ var MulticallABI = [
18410
+ {
18411
+ inputs: [],
18412
+ name: "getCurrentBlockTimestamp",
18413
+ outputs: [
18414
+ {
18415
+ internalType: "uint256",
18416
+ name: "timestamp",
18417
+ type: "uint256"
18418
+ }
18419
+ ],
18420
+ stateMutability: "view",
18421
+ type: "function"
18422
+ },
18423
+ {
18424
+ inputs: [
18425
+ {
18426
+ internalType: "address",
18427
+ name: "addr",
18428
+ type: "address"
18429
+ }
18430
+ ],
18431
+ name: "getEthBalance",
18432
+ outputs: [
18433
+ {
18434
+ internalType: "uint256",
18435
+ name: "balance",
18436
+ type: "uint256"
18437
+ }
18438
+ ],
18439
+ stateMutability: "view",
18440
+ type: "function"
18441
+ },
18442
+ {
18443
+ inputs: [],
18444
+ name: "getBlockNumber",
18445
+ outputs: [
18446
+ {
18447
+ internalType: "uint256",
18448
+ name: "blockNumber",
18449
+ type: "uint256"
18450
+ }
18451
+ ],
18452
+ stateMutability: "view",
18453
+ type: "function"
18454
+ },
18455
+ {
18456
+ inputs: [
18457
+ {
18458
+ components: [
18459
+ {
18460
+ internalType: "address",
18461
+ name: "target",
18462
+ type: "address"
18463
+ },
18464
+ {
18465
+ internalType: "uint256",
18466
+ name: "gasLimit",
18467
+ type: "uint256"
18468
+ },
18469
+ {
18470
+ internalType: "bytes",
18471
+ name: "callData",
18472
+ type: "bytes"
18473
+ }
18474
+ ],
18475
+ internalType: "struct UniswapInterfaceMulticall.Call[]",
18476
+ name: "calls",
18477
+ type: "tuple[]"
18478
+ }
18479
+ ],
18480
+ name: "multicall",
18481
+ outputs: [
18482
+ {
18483
+ internalType: "uint256",
18484
+ name: "blockNumber",
18485
+ type: "uint256"
18486
+ },
18487
+ {
18488
+ components: [
18489
+ {
18490
+ internalType: "bool",
18491
+ name: "success",
18492
+ type: "bool"
18493
+ },
18494
+ {
18495
+ internalType: "uint256",
18496
+ name: "gasUsed",
18497
+ type: "uint256"
18498
+ },
18499
+ {
18500
+ internalType: "bytes",
18501
+ name: "returnData",
18502
+ type: "bytes"
18503
+ }
18504
+ ],
18505
+ internalType: "struct UniswapInterfaceMulticall.Result[]",
18506
+ name: "returnData",
18507
+ type: "tuple[]"
18508
+ }
18509
+ ],
18510
+ stateMutability: "nonpayable",
18511
+ type: "function"
18512
+ }
18513
+ ];
18514
+
18386
18515
  // src/lending/public-data/euler/fetcher/cluster.ts
18387
18516
  function getActiveCollaterals(ltvInfo) {
18388
18517
  const active = /* @__PURE__ */ new Set();
@@ -21350,6 +21479,8 @@ var getLenderPublicData = async (chainId, lenders, prices, additionalYields, mul
21350
21479
  const validLenders = [];
21351
21480
  const sliceStart = {};
21352
21481
  const sliceBuilt = {};
21482
+ const blockSentinel = buildBlockSentinelCall(chainId);
21483
+ if (blockSentinel) calls.push(blockSentinel);
21353
21484
  for (const lender of lenders) {
21354
21485
  const abi = getAbi(lender);
21355
21486
  const callData = buildLenderCall(chainId, lender);
@@ -21468,8 +21599,44 @@ var getLenderPublicData = async (chainId, lenders, prices, additionalYields, mul
21468
21599
  } catch {
21469
21600
  }
21470
21601
  }
21602
+ if (blockSentinel) {
21603
+ const block = parseBlockNumber(rawResults?.[0]);
21604
+ if (block !== void 0) stampAccumulatorBlock(lenderData, block);
21605
+ }
21471
21606
  return lenderData;
21472
21607
  };
21608
+ function buildBlockSentinelCall(chainId) {
21609
+ const address = getEvmChain(chainId)?.contracts?.multicall3?.address;
21610
+ if (!address) return void 0;
21611
+ return {
21612
+ call: { address, name: "getBlockNumber", params: [] },
21613
+ abi: MulticallABI
21614
+ };
21615
+ }
21616
+ function parseBlockNumber(raw) {
21617
+ if (raw === void 0 || raw === null || raw === "0x") return void 0;
21618
+ try {
21619
+ const b = typeof raw === "bigint" ? raw : BigInt(String(raw));
21620
+ return b > 0n && b <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(b) : void 0;
21621
+ } catch {
21622
+ return void 0;
21623
+ }
21624
+ }
21625
+ function stampAccumulatorBlock(lenderData, block) {
21626
+ let stamped = 0;
21627
+ for (const bundle of Object.values(lenderData)) {
21628
+ const pools = bundle?.data;
21629
+ if (!pools || typeof pools !== "object") continue;
21630
+ for (const pool of Object.values(pools)) {
21631
+ const acc = pool?.accumulator;
21632
+ if (acc && typeof acc.supplyIndex === "string") {
21633
+ acc.blockNumber = block;
21634
+ stamped++;
21635
+ }
21636
+ }
21637
+ }
21638
+ return stamped;
21639
+ }
21473
21640
  function sliceLenderResults(chainId, rawResults, entries) {
21474
21641
  const out = {};
21475
21642
  for (const { lender, start, built, declared } of entries) {
@@ -26647,7 +26814,7 @@ async function fetchFraxlendPairs(lender, chainId) {
26647
26814
  rateContract,
26648
26815
  swapperOk
26649
26816
  ] = s;
26650
- if (typeof asset !== "string" || typeof collateral !== "string") return;
26817
+ if (!isAddress(asset) || !isAddress(collateral)) return;
26651
26818
  if (!preview || !xrInfo) return;
26652
26819
  const rateInfo = preview[3] ?? {};
26653
26820
  const totalAsset = preview[4] ?? {};
@@ -43803,7 +43970,12 @@ function fuseLenderData(userDataResult, summary) {
43803
43970
  lender,
43804
43971
  chainId,
43805
43972
  account: userData.account,
43806
- data: userData.data,
43973
+ // Tag every row with the unit it carries (POSITION_INDEX_SUPPORT.md,
43974
+ // Contract B): a copy, never a mutation of the parser's objects.
43975
+ data: userData.data.map((sa) => ({
43976
+ ...sa,
43977
+ positions: sa.positions.map((p) => withUnitKind(lender, p))
43978
+ })),
43807
43979
  // Carry the partial-read marker onto the entry the client renders — the
43808
43980
  // top-level `incompleteLenders` list alone leaves a consumer to re-join it
43809
43981
  // by key, which no client did, so broken aggregates rendered as fact.
@@ -43819,1409 +43991,503 @@ function fuseLenderData(userDataResult, summary) {
43819
43991
  return entries;
43820
43992
  }
43821
43993
 
43822
- // src/lending/margin/base/standard/deposit.ts
43823
- function computeDepositDelta(amount4, price2, balanceData2, config, modeId, createNewSubAccount = false, apr, yieldParams) {
43824
- const { borrowCollateralFactor, collateralFactor } = getAssetConfig(config, modeId);
43825
- const base = createNewSubAccount ? EMPTY_BALANCE : balanceData2;
43826
- const dollarAmount = amount4 * price2;
43827
- const postTrade = {
43828
- ...base,
43829
- borrowDiscountedCollateral: base.borrowDiscountedCollateral + borrowCollateralFactor * dollarAmount,
43830
- collateral: base.collateral + collateralFactor * dollarAmount,
43831
- deposits: base.deposits + dollarAmount,
43832
- nav: base.nav + dollarAmount
43833
- };
43834
- const result = computePostTradeMetrics(base, postTrade);
43835
- if (apr && yieldParams) {
43836
- const cashFlowDeposits = base.deposits * apr.depositApr;
43837
- const cashFlowDebt = base.debt * apr.borrowApr;
43838
- const rewardFlowDeposits = base.deposits * (apr.rewardDepositApr ?? 0);
43839
- const rewardFlowDebt = base.debt * (apr.rewardBorrowApr ?? 0);
43840
- const intrinsicFlowDeposits = base.deposits * apr.intrinsicDepositApr;
43841
- const intrinsicFlowDebt = base.debt * apr.intrinsicBorrowApr;
43842
- const newApr = { ...apr };
43843
- [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldDeposit(
43844
- dollarAmount,
43845
- cashFlowDeposits,
43846
- cashFlowDebt,
43847
- base.deposits,
43848
- base.debt,
43849
- yieldParams
43850
- );
43851
- newApr.rewards = getRewardYieldDeposit(
43852
- dollarAmount,
43853
- rewardFlowDeposits,
43854
- rewardFlowDebt,
43855
- base.deposits,
43856
- base.debt,
43857
- yieldParams
43858
- );
43859
- [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldDeposit(
43860
- dollarAmount,
43861
- intrinsicFlowDeposits,
43862
- intrinsicFlowDebt,
43863
- base.deposits,
43864
- base.debt,
43865
- yieldParams
43866
- );
43867
- result.post.aprData = newApr;
43868
- }
43869
- return result;
43870
- }
43871
-
43872
- // src/lending/margin/base/deposit.ts
43873
- function computeDepositDelta2(lender, amount4, price2, balanceData2, config, modeId, createNewSubAccount, apr, yieldParams, targetMarketUid, positions) {
43874
- if (isSumerType(lender)) {
43875
- if (!positions || targetMarketUid === void 0) {
43876
- throw new Error("Sumer operations require positions and targetMarketUid");
43994
+ // src/yields/intrinsic/fetchers/lido.ts
43995
+ var WSTETH_URL = "https://eth-api.lido.fi/v1/protocol/steth/apr/sma";
43996
+ var DEFILLAMA_LIDO_URL = "https://yields.llama.fi/chart/747c1d2a-c668-4682-b9f9-296708a3dd90";
43997
+ var tETH = "Treehouse ETH::TETH";
43998
+ var robustFetchJson = async (url, { timeoutMs = 5e3, attempts = 3 } = {}) => {
43999
+ let lastErr;
44000
+ for (let i = 0; i < attempts; i++) {
44001
+ try {
44002
+ const res = await fetch(url, {
44003
+ headers: {
44004
+ accept: "application/json",
44005
+ "user-agent": "1delta-margin-fetcher"
44006
+ },
44007
+ signal: AbortSignal.timeout(timeoutMs)
44008
+ });
44009
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
44010
+ return await res.json();
44011
+ } catch (e) {
44012
+ lastErr = e;
44013
+ if (i < attempts - 1) {
44014
+ await new Promise((r) => setTimeout(r, 250 * (i + 1)));
44015
+ }
43877
44016
  }
43878
- return computeSumerDepositDelta(
43879
- amount4,
43880
- price2,
43881
- targetMarketUid,
43882
- balanceData2,
43883
- positions,
43884
- createNewSubAccount,
43885
- apr,
43886
- yieldParams
43887
- );
43888
44017
  }
43889
- if (!config || modeId === void 0) {
43890
- throw new Error("Standard operations require config and modeId");
44018
+ throw lastErr;
44019
+ };
44020
+ async function fetchLidoApr() {
44021
+ try {
44022
+ const res = await robustFetchJson(WSTETH_URL);
44023
+ return Number(res.data.aprs.at(-1).apr) * 0.9;
44024
+ } catch {
44025
+ const res = await robustFetchJson(DEFILLAMA_LIDO_URL);
44026
+ const latest = res.data.at(-1);
44027
+ return Number(latest.apyBase) * 0.9;
43891
44028
  }
43892
- return computeDepositDelta(
43893
- amount4,
43894
- price2,
43895
- balanceData2,
43896
- config,
43897
- modeId,
43898
- createNewSubAccount,
43899
- apr,
43900
- yieldParams
43901
- );
43902
44029
  }
44030
+ var wstethFetcher = {
44031
+ label: "WSTETH",
44032
+ fetch: async () => {
44033
+ const apr = await fetchLidoApr();
44034
+ return {
44035
+ WSTETH: apr,
44036
+ [tETH]: apr
44037
+ };
44038
+ }
44039
+ };
44040
+ var stmaticFetcher = {
44041
+ label: "STMATIC",
44042
+ fetch: async () => {
44043
+ return { STMATIC: 0 };
44044
+ }
44045
+ };
43903
44046
 
43904
- // src/lending/margin/base/standard/withdraw.ts
43905
- function computeWithdrawDelta(amount4, price2, balanceData2, config, modeId, apr, yieldParams) {
43906
- const { borrowCollateralFactor, collateralFactor } = getAssetConfig(config, modeId);
43907
- const dollarAmount = amount4 * price2;
43908
- const postTrade = {
43909
- ...balanceData2,
43910
- borrowDiscountedCollateral: balanceData2.borrowDiscountedCollateral - borrowCollateralFactor * dollarAmount,
43911
- collateral: balanceData2.collateral - collateralFactor * dollarAmount,
43912
- deposits: balanceData2.deposits - dollarAmount,
43913
- nav: balanceData2.nav - dollarAmount
43914
- };
43915
- const result = computePostTradeMetrics(balanceData2, postTrade);
43916
- if (apr && yieldParams) {
43917
- const cashFlowDeposits = balanceData2.deposits * apr.depositApr;
43918
- const cashFlowDebt = balanceData2.debt * apr.borrowApr;
43919
- const rewardFlowDeposits = balanceData2.deposits * (apr.rewardDepositApr ?? 0);
43920
- const rewardFlowDebt = balanceData2.debt * (apr.rewardBorrowApr ?? 0);
43921
- const intrinsicFlowDeposits = balanceData2.deposits * apr.intrinsicDepositApr;
43922
- const intrinsicFlowDebt = balanceData2.debt * apr.intrinsicBorrowApr;
43923
- const newApr = { ...apr };
43924
- [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldWithdraw(
43925
- dollarAmount,
43926
- cashFlowDeposits,
43927
- cashFlowDebt,
43928
- balanceData2.deposits,
43929
- balanceData2.debt,
43930
- yieldParams
43931
- );
43932
- newApr.rewards = getRewardYieldWithdraw(
43933
- dollarAmount,
43934
- rewardFlowDeposits,
43935
- rewardFlowDebt,
43936
- balanceData2.deposits,
43937
- balanceData2.debt,
43938
- yieldParams
43939
- );
43940
- [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldWithdraw(
43941
- dollarAmount,
43942
- intrinsicFlowDeposits,
43943
- intrinsicFlowDebt,
43944
- balanceData2.deposits,
43945
- balanceData2.debt,
43946
- yieldParams
43947
- );
43948
- result.post.aprData = newApr;
44047
+ // src/yields/intrinsic/fetchers/rocketpool.ts
44048
+ var RETH_URL = "https://api.rocketpool.net/api/mainnet/payload";
44049
+ var rethFetcher = {
44050
+ label: "RETH",
44051
+ fetch: async () => {
44052
+ const res = await fetch(RETH_URL).then((r) => r.json());
44053
+ return { RETH: Number(res.rethAPR) };
43949
44054
  }
43950
- return result;
43951
- }
44055
+ };
43952
44056
 
43953
- // src/lending/margin/base/withdraw.ts
43954
- function computeWithdrawDelta2(lender, amount4, price2, balanceData2, config, modeId, apr, yieldParams, targetMarketUid, positions) {
43955
- if (isSumerType(lender)) {
43956
- if (!positions || targetMarketUid === void 0) {
43957
- throw new Error("Sumer operations require positions and targetMarketUid");
43958
- }
43959
- return computeSumerWithdrawDelta(
43960
- amount4,
43961
- price2,
43962
- targetMarketUid,
43963
- balanceData2,
43964
- positions,
43965
- apr,
43966
- yieldParams
43967
- );
44057
+ // src/yields/intrinsic/fetchers/renzo.ts
44058
+ var EZETH_URL = "https://app.renzoprotocol.com/api/stats?chainId=1";
44059
+ var ezethFetcher = {
44060
+ label: "EZETH",
44061
+ fetch: async () => {
44062
+ const res = await fetch(EZETH_URL).then((r) => r.json());
44063
+ return { EZETH: Number(res.data.apr.data.rate) };
43968
44064
  }
43969
- if (!config || modeId === void 0) {
43970
- throw new Error("Standard operations require config and modeId");
44065
+ };
44066
+
44067
+ // src/yields/intrinsic/fetchers/kelp.ts
44068
+ var RSETH_URL = "https://universe.kelpdao.xyz/rseth/totalApy";
44069
+ var rsethFetcher = {
44070
+ label: "RSETH",
44071
+ fetch: async () => {
44072
+ const res = await fetch(RSETH_URL).then((r) => r.json());
44073
+ return { RSETH: apyToAprPercent(res.totalAPY) };
43971
44074
  }
43972
- return computeWithdrawDelta(
43973
- amount4,
43974
- price2,
43975
- balanceData2,
43976
- config,
43977
- modeId,
43978
- apr,
43979
- yieldParams
43980
- );
43981
- }
44075
+ };
43982
44076
 
43983
- // src/lending/margin/base/standard/borrow.ts
43984
- function computeBorrowDelta(amount4, price2, balanceData2, config, modeId, apr, yieldParams, irMode) {
43985
- const { borrowFactor } = getAssetConfig(config, modeId);
43986
- const dollarAmount = amount4 * price2;
43987
- const postTrade = {
43988
- ...balanceData2,
43989
- debt: balanceData2.debt + dollarAmount,
43990
- adjustedDebt: balanceData2.adjustedDebt + borrowFactor * dollarAmount,
43991
- nav: balanceData2.nav - dollarAmount
43992
- };
43993
- const result = computePostTradeMetrics(balanceData2, postTrade);
43994
- if (apr && yieldParams) {
43995
- const mode = irMode ?? 2;
43996
- const cashFlowDeposits = balanceData2.deposits * apr.depositApr;
43997
- const cashFlowDebt = balanceData2.debt * apr.borrowApr;
43998
- const rewardFlowDeposits = balanceData2.deposits * (apr.rewardDepositApr ?? 0);
43999
- const rewardFlowDebt = balanceData2.debt * (apr.rewardBorrowApr ?? 0);
44000
- const intrinsicFlowDeposits = balanceData2.deposits * apr.intrinsicDepositApr;
44001
- const intrinsicFlowDebt = balanceData2.debt * apr.intrinsicBorrowApr;
44002
- const newApr = { ...apr };
44003
- [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldBorrow(
44004
- dollarAmount,
44005
- mode,
44006
- cashFlowDeposits,
44007
- cashFlowDebt,
44008
- balanceData2.deposits,
44009
- balanceData2.debt,
44010
- yieldParams
44011
- );
44012
- newApr.rewards = getRewardYieldBorrow(
44013
- dollarAmount,
44014
- mode,
44015
- rewardFlowDeposits,
44016
- rewardFlowDebt,
44017
- balanceData2.deposits,
44018
- balanceData2.debt,
44019
- yieldParams
44020
- );
44021
- [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldBorrow(
44022
- dollarAmount,
44023
- intrinsicFlowDeposits,
44024
- intrinsicFlowDebt,
44025
- balanceData2.deposits,
44026
- balanceData2.debt,
44027
- yieldParams
44028
- );
44029
- result.post.aprData = newApr;
44077
+ // src/yields/intrinsic/fetchers/swell.ts
44078
+ var RSWETH_URL = "https://v3-lst.svc.swellnetwork.io/api/tokens/sweth/apr";
44079
+ var rsweth = "Restaked Swell ETH::RSWETH";
44080
+ var rswethFetcher = {
44081
+ label: "RSWETH",
44082
+ fetch: async () => {
44083
+ const res = await fetch(RSWETH_URL, {
44084
+ method: "GET",
44085
+ headers: { Accept: "application/json", "User-Agent": "1delta/yields" }
44086
+ }).then((r) => r.text());
44087
+ return { [rsweth]: Number(res) ?? 0 };
44030
44088
  }
44031
- return result;
44032
- }
44089
+ };
44033
44090
 
44034
- // src/lending/margin/base/borrow.ts
44035
- function computeBorrowDelta2(lender, amount4, price2, balanceData2, config, modeId, apr, yieldParams, irMode, targetMarketUid, positions) {
44036
- if (isSumerType(lender)) {
44037
- if (!positions || targetMarketUid === void 0) {
44038
- throw new Error("Sumer operations require positions and targetMarketUid");
44039
- }
44040
- return computeSumerBorrowDelta(
44041
- amount4,
44042
- price2,
44043
- targetMarketUid,
44044
- balanceData2,
44045
- positions,
44046
- apr,
44047
- yieldParams,
44048
- irMode
44049
- );
44091
+ // src/yields/intrinsic/annualizeRate.ts
44092
+ var YEAR_SECONDS3 = 365 * 24 * 60 * 60;
44093
+ var annualizeGrowthPercent = (growth, elapsedSeconds) => growth * (YEAR_SECONDS3 / elapsedSeconds) * 100;
44094
+ var annualizeRateDeltaPercent = (rateNow, rateThen, elapsedSeconds) => {
44095
+ const growth = typeof rateNow === "bigint" && typeof rateThen === "bigint" ? Number(rateNow - rateThen) / Number(rateThen) : Number(rateNow) / Number(rateThen) - 1;
44096
+ return annualizeGrowthPercent(growth, elapsedSeconds);
44097
+ };
44098
+
44099
+ // src/yields/intrinsic/fetchers/swBTC.ts
44100
+ var CHAIN_ID = "1";
44101
+ var SWBTC = "0x8db2350d78abc13f5673a411d4700bcf87864dde";
44102
+ var ONE_E8 = 10n ** 8n;
44103
+ var WINDOW_SECONDS = 7 * 24 * 60 * 60;
44104
+ var BLOCK_TIME_SECONDS = 12;
44105
+ var WINDOW_BLOCKS = BigInt(Math.floor(WINDOW_SECONDS / BLOCK_TIME_SECONDS));
44106
+ var MAX_RPC_TRIES = 5;
44107
+ var CONVERT_TO_ASSETS_ABI = [
44108
+ {
44109
+ name: "convertToAssets",
44110
+ type: "function",
44111
+ stateMutability: "view",
44112
+ inputs: [{ type: "uint256", name: "shares" }],
44113
+ outputs: [{ type: "uint256" }]
44050
44114
  }
44051
- if (!config || modeId === void 0) {
44052
- throw new Error("Standard operations require config and modeId");
44115
+ ];
44116
+ var readRateAt = (client, blockNumber) => client.readContract({
44117
+ address: SWBTC,
44118
+ abi: CONVERT_TO_ASSETS_ABI,
44119
+ functionName: "convertToAssets",
44120
+ args: [ONE_E8],
44121
+ ...blockNumber !== void 0 ? { blockNumber } : {}
44122
+ });
44123
+ var computeApr = async () => {
44124
+ let lastErr;
44125
+ for (let rpcId = 0; rpcId < MAX_RPC_TRIES; rpcId++) {
44126
+ try {
44127
+ const client = getEvmClient(CHAIN_ID, rpcId);
44128
+ const head = await client.getBlockNumber();
44129
+ const pastBlock = head > WINDOW_BLOCKS ? head - WINDOW_BLOCKS : 0n;
44130
+ const [rateNow, rateThen, headBlock, thenBlock] = await Promise.all([
44131
+ readRateAt(client),
44132
+ readRateAt(client, pastBlock),
44133
+ client.getBlock({ blockNumber: head }),
44134
+ client.getBlock({ blockNumber: pastBlock })
44135
+ ]);
44136
+ if (rateNow < ONE_E8 || rateThen < ONE_E8 || rateNow < rateThen) {
44137
+ throw new Error(
44138
+ `non-archival or invalid rates (now=${rateNow}, then=${rateThen})`
44139
+ );
44140
+ }
44141
+ const elapsed = Number(headBlock.timestamp - thenBlock.timestamp);
44142
+ if (elapsed <= 0) throw new Error(`bad elapsed ${elapsed}`);
44143
+ const apr = annualizeRateDeltaPercent(rateNow, rateThen, elapsed);
44144
+ if (!Number.isFinite(apr) || apr < 0) throw new Error(`bad apr ${apr}`);
44145
+ return apr;
44146
+ } catch (e) {
44147
+ lastErr = e;
44148
+ }
44053
44149
  }
44054
- return computeBorrowDelta(
44055
- amount4,
44056
- price2,
44057
- balanceData2,
44058
- config,
44059
- modeId,
44060
- apr,
44061
- yieldParams,
44062
- irMode
44150
+ throw new Error(
44151
+ `swBTC APR: no archival Ethereum RPC returned valid historical state (${String(lastErr)})`
44063
44152
  );
44064
- }
44153
+ };
44154
+ var swBtcFetcher = {
44155
+ label: "SWBTC",
44156
+ fetch: async () => {
44157
+ try {
44158
+ return { "Swell Restaked BTC::SWBTC": await computeApr() };
44159
+ } catch {
44160
+ return { "Swell Restaked BTC::SWBTC": 0 };
44161
+ }
44162
+ }
44163
+ };
44065
44164
 
44066
- // src/lending/margin/base/standard/repay.ts
44067
- function computeRepayDelta(amount4, price2, balanceData2, config, modeId, apr, yieldParams, irMode) {
44068
- const { borrowFactor } = getAssetConfig(config, modeId);
44069
- const dollarAmount = amount4 * price2;
44070
- const postTrade = {
44071
- ...balanceData2,
44072
- debt: balanceData2.debt - dollarAmount,
44073
- adjustedDebt: Math.max(0, balanceData2.adjustedDebt - borrowFactor * dollarAmount),
44074
- nav: balanceData2.nav + dollarAmount
44075
- };
44076
- const result = computePostTradeMetrics(balanceData2, postTrade);
44077
- if (apr && yieldParams) {
44078
- const mode = irMode ?? 2;
44079
- const cashFlowDeposits = balanceData2.deposits * apr.depositApr;
44080
- const cashFlowDebt = balanceData2.debt * apr.borrowApr;
44081
- const rewardFlowDeposits = balanceData2.deposits * (apr.rewardDepositApr ?? 0);
44082
- const rewardFlowDebt = balanceData2.debt * (apr.rewardBorrowApr ?? 0);
44083
- const intrinsicFlowDeposits = balanceData2.deposits * apr.intrinsicDepositApr;
44084
- const intrinsicFlowDebt = balanceData2.debt * apr.intrinsicBorrowApr;
44085
- const newApr = { ...apr };
44086
- [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldRepay(
44087
- dollarAmount,
44088
- mode,
44089
- cashFlowDeposits,
44090
- cashFlowDebt,
44091
- balanceData2.deposits,
44092
- balanceData2.debt,
44093
- yieldParams
44094
- );
44095
- newApr.rewards = getRewardYieldRepay(
44096
- dollarAmount,
44097
- mode,
44098
- rewardFlowDeposits,
44099
- rewardFlowDebt,
44100
- balanceData2.deposits,
44101
- balanceData2.debt,
44102
- yieldParams
44103
- );
44104
- [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldRepay(
44105
- dollarAmount,
44106
- intrinsicFlowDeposits,
44107
- intrinsicFlowDebt,
44108
- balanceData2.deposits,
44109
- balanceData2.debt,
44110
- yieldParams
44111
- );
44112
- result.post.aprData = newApr;
44165
+ // src/yields/intrinsic/fetchers/puffer.ts
44166
+ var PUFETH_URL = "https://api-v2.puffer.fi/backend-for-frontend/tvl/all";
44167
+ var pufEth = "PUFETH";
44168
+ var pufethFetcher = {
44169
+ label: "PUFETH",
44170
+ fetch: async () => {
44171
+ const res = await fetch(PUFETH_URL, {
44172
+ method: "GET",
44173
+ headers: { Accept: "application/json" }
44174
+ }).then((r) => r.json());
44175
+ return { [pufEth]: apyToAprPercent(res.apy) };
44113
44176
  }
44114
- return result;
44115
- }
44177
+ };
44116
44178
 
44117
- // src/lending/margin/base/repay.ts
44118
- function computeRepayDelta2(lender, amount4, price2, balanceData2, config, modeId, apr, yieldParams, irMode, targetMarketUid, positions) {
44119
- if (isSumerType(lender)) {
44120
- if (!positions || targetMarketUid === void 0) {
44121
- throw new Error("Sumer operations require positions and targetMarketUid");
44122
- }
44123
- return computeSumerRepayDelta(
44124
- amount4,
44125
- price2,
44126
- targetMarketUid,
44127
- balanceData2,
44128
- positions,
44129
- apr,
44130
- yieldParams,
44131
- irMode
44132
- );
44179
+ // src/yields/intrinsic/fetchers/stakewise.ts
44180
+ var OSETH_URL = "https://graphs.stakewise.io/mainnet-a/subgraphs/name/stakewise/prod?opName=osTokenApy";
44181
+ var osETH = "StakeWise Staked ETH::OSETH";
44182
+ var osethFetcher = {
44183
+ label: "OSETH",
44184
+ fetch: async () => {
44185
+ const res = await fetch(OSETH_URL, {
44186
+ method: "POST",
44187
+ headers: { Accept: "application/json" },
44188
+ body: JSON.stringify({
44189
+ query: "query osTokenApy { osTokens { apy feePercent }}",
44190
+ operationName: "osTokenApy"
44191
+ })
44192
+ }).then((r) => r.json());
44193
+ const apr = apyToAprPercent(res.data?.osTokens?.[0]?.apy);
44194
+ return {
44195
+ [osETH]: apr,
44196
+ // token-lists unifies every osETH deployment (incl. bridged) to the bare `OSETH` group — emit there too.
44197
+ OSETH: apr
44198
+ };
44133
44199
  }
44134
- if (!config || modeId === void 0) {
44135
- throw new Error("Standard operations require config and modeId");
44200
+ };
44201
+
44202
+ // src/yields/intrinsic/fetchers/stader.ts
44203
+ var MATICX_URL = "https://universe.staderlabs.com/polygon/apy";
44204
+ var ETHX_URL = "https://universe.staderlabs.com/eth/apy";
44205
+ var ethX = "Stader ETHx::ETHx";
44206
+ var maticxFetcher = {
44207
+ label: "MATICX",
44208
+ fetch: async () => {
44209
+ const res = await fetch(MATICX_URL).then((r) => r.json());
44210
+ return { MATICX: Number(res.value) * 0.9 };
44136
44211
  }
44137
- return computeRepayDelta(
44138
- amount4,
44139
- price2,
44140
- balanceData2,
44141
- config,
44142
- modeId,
44143
- apr,
44144
- yieldParams,
44145
- irMode
44146
- );
44147
- }
44212
+ };
44213
+ var ethxFetcher = {
44214
+ label: "ETHX",
44215
+ fetch: async () => {
44216
+ const res = await fetch(ETHX_URL).then((r) => r.json());
44217
+ return { [ethX]: apyToAprPercent(res.value) };
44218
+ }
44219
+ };
44148
44220
 
44149
- // src/lending/margin/loop/utils.ts
44150
- var positivePart2 = (n) => n < 0 ? 0 : n;
44151
- function nanTo(possiblyNaN, replacement = Infinity) {
44152
- return isNaN(possiblyNaN) ? replacement : possiblyNaN;
44153
- }
44154
- function getHealthFactor2(collateral, adjustedDebt) {
44155
- if (adjustedDebt === 0) return Infinity;
44156
- const raw = collateral / adjustedDebt;
44157
- return Math.round((isNaN(raw) ? 0 : raw) * 1e4) / 1e4;
44158
- }
44159
- function keysFromMaps(a, b) {
44160
- const set = /* @__PURE__ */ new Set();
44161
- if (a) for (const k of Object.keys(a)) set.add(k);
44162
- if (b) for (const k of Object.keys(b)) set.add(k);
44163
- return [...set];
44164
- }
44165
- function rewardsToMap(rewards) {
44166
- const map = {};
44167
- if (Array.isArray(rewards)) for (const r of rewards) map[r.asset] = r;
44168
- return map;
44169
- }
44170
- function noOpResult(balance, apr) {
44171
- const hf = getHealthFactor2(balance.collateral, balance.adjustedDebt);
44172
- const bc = balance.collateral - balance.adjustedDebt;
44173
- return {
44174
- pre: { healthFactor: hf, borrowCapacity: bc },
44175
- post: { healthFactor: hf, borrowCapacity: bc, balanceData: balance, aprData: apr }
44176
- };
44177
- }
44178
- function buildLoopResult(balance, newBalance, apr, newApr, useAllActive = false) {
44179
- const collateralPost = useAllActive ? newBalance.collateralAllActive : newBalance.collateral;
44180
- return {
44181
- pre: {
44182
- healthFactor: getHealthFactor2(balance.collateral, balance.adjustedDebt),
44183
- borrowCapacity: balance.collateral - balance.adjustedDebt
44184
- },
44185
- post: {
44186
- healthFactor: newBalance.adjustedDebt === 0 ? Infinity : positivePart2(getHealthFactor2(collateralPost, newBalance.adjustedDebt)),
44187
- borrowCapacity: newBalance.collateral - newBalance.adjustedDebt,
44188
- balanceData: newBalance,
44189
- aprData: newApr
44190
- }
44191
- };
44192
- }
44221
+ // src/yields/intrinsic/fetchers/trufin.ts
44222
+ var APY_URL = "https://api.trufin.io/staker/apy?staker=";
44223
+ var createTruFinFetcher = (staker, yieldKey) => ({
44224
+ label: yieldKey,
44225
+ fetch: async () => {
44226
+ const res = await fetch(APY_URL + staker).then((r) => r.json());
44227
+ return { [yieldKey]: apyToAprPercent(res.apy) };
44228
+ }
44229
+ });
44230
+ var trumaticFetcher = createTruFinFetcher("MATIC", "TRUMATIC");
44231
+ var trupolFetcher = createTruFinFetcher("POL", "TRUPOL");
44193
44232
 
44194
- // src/lending/margin/loop/yield/getOraganicYieldChange.ts
44195
- function getOrganicYieldOpen(amountInUSD, amountOutUSD, irModeIn, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
44196
- const _flowIn = amountInUSD * (irModeIn === 1 ? yieldIn.stableBorrowRate : yieldIn.variableBorrowRate);
44197
- const _flowOut = amountOutUSD * yieldOut.depositRate;
44198
- const totalCashFlowDebt = cashFlowDebt + _flowIn;
44199
- const totalCashFlowDeposits = cashFlowDeposits + _flowOut;
44200
- const newCollat = deposits + amountOutUSD;
44201
- const newDebt = debt + amountInUSD;
44202
- return [
44203
- totalCashFlowDebt / newDebt,
44204
- totalCashFlowDeposits / newCollat,
44205
- (totalCashFlowDeposits - totalCashFlowDebt) / (newCollat - newDebt)
44206
- ];
44207
- }
44208
- function getOrganicYieldClose(amountInUSD, amountOutUSD, irModeOut, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
44209
- const _flowIn = amountInUSD * yieldIn.depositRate;
44210
- const _flowOut = amountOutUSD * (irModeOut === 1 ? yieldOut.stableBorrowRate : yieldOut.variableBorrowRate);
44211
- const totalCashFlowDebt = cashFlowDebt - _flowOut;
44212
- const totalCashFlowDeposits = cashFlowDeposits - _flowIn;
44213
- const newCollat = deposits - amountInUSD;
44214
- const newDebt = debt - amountOutUSD;
44215
- return [
44216
- Math.abs(newDebt) < 0.01 ? 0 : totalCashFlowDebt / newDebt,
44217
- totalCashFlowDeposits / newCollat,
44218
- (totalCashFlowDeposits - totalCashFlowDebt) / (newCollat - newDebt)
44219
- ];
44220
- }
44221
- function getOrganicYieldDebtSwap(amountInUSD, amountOutUSD, irModeIn, irModeOut, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
44222
- const _flowIn = amountInUSD * (irModeIn === 1 ? yieldIn.stableBorrowRate : yieldIn.variableBorrowRate);
44223
- const _flowOut = amountOutUSD * (irModeOut === 1 ? yieldOut.stableBorrowRate : yieldOut.variableBorrowRate);
44224
- const totalCashFlowDebt = cashFlowDebt + _flowIn - _flowOut;
44225
- const newDebt = debt - amountOutUSD + amountInUSD;
44226
- return [
44227
- Math.abs(newDebt) < 0.01 ? 0 : totalCashFlowDebt / newDebt,
44228
- cashFlowDeposits / deposits,
44229
- (cashFlowDeposits - totalCashFlowDebt) / (deposits - newDebt)
44230
- ];
44231
- }
44232
- function getOrganicYieldCollateralSwap(amountInUSD, amountOutUSD, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
44233
- const _flowIn = amountInUSD * yieldIn.depositRate;
44234
- const _flowOut = amountOutUSD * yieldOut.depositRate;
44235
- const totalCashFlowDeposits = cashFlowDeposits + _flowOut - _flowIn;
44236
- const newCollat = deposits + amountOutUSD - amountInUSD;
44237
- return [
44238
- Math.abs(debt) < 0.01 ? 0 : cashFlowDebt / debt,
44239
- totalCashFlowDeposits / newCollat,
44240
- (totalCashFlowDeposits - cashFlowDebt) / (newCollat - debt)
44241
- ];
44242
- }
44233
+ // src/yields/intrinsic/fetchers/defillama.ts
44234
+ var POOLS_ENRICHED = "https://yields.llama.fi/poolsEnriched?pool=";
44235
+ var fetchDefiLlamaApy = async (poolId) => {
44236
+ const res = await fetch(POOLS_ENRICHED + poolId, {
44237
+ headers: { accept: "application/json" },
44238
+ signal: AbortSignal.timeout(8e3)
44239
+ });
44240
+ if (!res.ok) throw new Error(`DefiLlama HTTP ${res.status}`);
44241
+ const json = await res.json();
44242
+ const apy = json?.data?.[0]?.apy;
44243
+ if (typeof apy !== "number" || !Number.isFinite(apy)) {
44244
+ throw new Error(`DefiLlama: no apy for pool ${poolId}`);
44245
+ }
44246
+ return apy;
44247
+ };
44243
44248
 
44244
- // src/lending/margin/loop/yield/getRewardYieldChange.ts
44245
- function getRewardYieldOpen(amountInUSD, amountOutUSD, irModeIn, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
44246
- const mapIn = rewardsToMap(yieldIn?.rewards);
44247
- const mapOut = rewardsToMap(yieldOut?.rewards);
44248
- if (!yieldIn?.rewards?.length && !yieldOut?.rewards?.length) return {};
44249
- const data = {};
44250
- for (const key3 of keysFromMaps(mapIn, mapOut)) {
44251
- const _flowIn = amountInUSD * ((irModeIn === 1 ? mapIn[key3]?.stableBorrowRate : mapIn[key3]?.variableBorrowRate) ?? 0);
44252
- const _flowOut = amountOutUSD * (mapOut[key3]?.depositRate ?? 0);
44253
- const totalCashFlowDebt = cashFlowDebt + _flowIn;
44254
- const totalCashFlowDeposits = cashFlowDeposits + _flowOut;
44255
- const newCollat = deposits + amountOutUSD;
44256
- const newDebt = debt + amountInUSD;
44257
- data[key3] = {
44258
- borrowApr: totalCashFlowDebt / newDebt,
44259
- depositApr: totalCashFlowDeposits / newCollat,
44260
- apr: (cashFlowDeposits + cashFlowDebt + _flowIn + _flowOut) / (newCollat - newDebt)
44261
- };
44249
+ // src/yields/intrinsic/fetchers/kinetiq.ts
44250
+ var KHYPE_POOL_ID = "9f25a954-db87-4bb2-a8b2-4be0b843a44c";
44251
+ var KHYPE_KEY = "Kinetiq Staked HYPE::kHYPE";
44252
+ var kinetiqKHypeFetcher = {
44253
+ label: "KHYPE",
44254
+ fetch: async () => {
44255
+ const apy = await fetchDefiLlamaApy(KHYPE_POOL_ID);
44256
+ return { [KHYPE_KEY]: apyToAprPercent(apy) };
44262
44257
  }
44263
- return data;
44264
- }
44265
- function getRewardYieldClose(amountInUSD, amountOutUSD, irModeOut, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
44266
- const mapIn = rewardsToMap(yieldIn?.rewards);
44267
- const mapOut = rewardsToMap(yieldOut?.rewards);
44268
- if (!yieldIn?.rewards?.length && !yieldOut?.rewards?.length) return {};
44269
- const data = {};
44270
- for (const key3 of keysFromMaps(mapIn, mapOut)) {
44271
- const _flowIn = amountInUSD * (mapIn[key3]?.depositRate ?? 0);
44272
- const _flowOut = amountOutUSD * ((irModeOut === 1 ? mapOut[key3]?.stableBorrowRate : mapOut[key3]?.variableBorrowRate) ?? 0);
44273
- const totalCashFlowDebt = cashFlowDebt - _flowOut;
44274
- const totalCashFlowDeposits = cashFlowDeposits - _flowIn;
44275
- const newCollat = deposits - amountInUSD;
44276
- const newDebt = debt - amountOutUSD;
44277
- data[key3] = {
44278
- borrowApr: Math.abs(newDebt) < 0.01 ? 0 : totalCashFlowDebt / newDebt,
44279
- depositApr: totalCashFlowDeposits / newCollat,
44280
- apr: (cashFlowDeposits + cashFlowDebt - _flowIn - _flowOut) / (newCollat - newDebt)
44281
- };
44258
+ };
44259
+
44260
+ // src/yields/intrinsic/fetchers/hyperbeat.ts
44261
+ var HBHYPE_URL = "https://api.hyperbeat.org/api/v1/staking?address=0xCeaD893b162D38e714D82d06a7fe0b0dc3c38E0b";
44262
+ var HBUHYPE_URL = "https://app.hyperbeat.org/api/hyperfolio/vault-infos?vaultAddress=0x96C6cBB6251Ee1c257b2162ca0f39AA5Fa44B1FB";
44263
+ var hbhype = "hyperbeat x ether.fi HYPE::beHYPE";
44264
+ var hbuhype = "Hyperbeat Ultra Hype::hbHYPE";
44265
+ var hbhypeFetcher = {
44266
+ label: "HBHYPE",
44267
+ fetch: async () => {
44268
+ try {
44269
+ const response = await fetch(HBHYPE_URL);
44270
+ if (!response.ok) {
44271
+ throw new Error(`HTTP error! Status: ${response.status}`);
44272
+ }
44273
+ const result = await response.json();
44274
+ if (!result.success || !result.data || !Array.isArray(result.data.delegations)) {
44275
+ throw new Error("Invalid response structure");
44276
+ }
44277
+ const delegations = result.data.delegations;
44278
+ const totalApr = delegations.reduce(
44279
+ (sum3, validator) => sum3 + Number(validator.apr ?? 0),
44280
+ 0
44281
+ );
44282
+ const averageApr = totalApr / delegations.length;
44283
+ return { [hbhype]: averageApr };
44284
+ } catch (e) {
44285
+ return { [hbhype]: 0 };
44286
+ }
44282
44287
  }
44283
- return data;
44284
- }
44285
- function getRewardYieldDebtSwap(amountInUSD, amountOutUSD, irModeIn, irModeOut, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
44286
- const mapIn = rewardsToMap(yieldIn?.rewards);
44287
- const mapOut = rewardsToMap(yieldOut?.rewards);
44288
- if (!yieldIn?.rewards?.length && !yieldOut?.rewards?.length) return {};
44289
- const data = {};
44290
- for (const key3 of keysFromMaps(mapIn, mapOut)) {
44291
- const _flowIn = amountInUSD * ((irModeIn === 1 ? mapIn[key3]?.stableBorrowRate : mapIn[key3]?.variableBorrowRate) ?? 0);
44292
- const _flowOut = amountOutUSD * ((irModeOut === 1 ? mapOut[key3]?.stableBorrowRate : mapOut[key3]?.variableBorrowRate) ?? 0);
44293
- const totalCashFlowDebt = cashFlowDebt + _flowIn - _flowOut;
44294
- const newDebt = debt - amountOutUSD + amountInUSD;
44295
- data[key3] = {
44296
- borrowApr: Math.abs(newDebt) < 0.01 ? 0 : totalCashFlowDebt / newDebt,
44297
- depositApr: cashFlowDeposits / deposits,
44298
- apr: (cashFlowDeposits + totalCashFlowDebt) / (deposits - newDebt)
44299
- };
44288
+ };
44289
+ var hbuhypeFetcher = {
44290
+ label: "HBUHYPE",
44291
+ fetch: async () => {
44292
+ try {
44293
+ const response = await fetch(HBUHYPE_URL);
44294
+ if (!response.ok) {
44295
+ throw new Error(`HTTP error! Status: ${response.status}`);
44296
+ }
44297
+ const result = await response.json();
44298
+ const apy = result.currentAPY?.apy_1d ?? 0;
44299
+ return { [hbuhype]: apyToAprPercent(apy) };
44300
+ } catch (e) {
44301
+ return { [hbuhype]: 0 };
44302
+ }
44300
44303
  }
44301
- return data;
44302
- }
44303
- function getRewardYieldCollateralSwap(amountInUSD, amountOutUSD, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
44304
- const mapIn = rewardsToMap(yieldIn?.rewards);
44305
- const mapOut = rewardsToMap(yieldOut?.rewards);
44306
- if (!yieldIn?.rewards?.length && !yieldOut?.rewards?.length) return {};
44307
- const data = {};
44308
- for (const key3 of keysFromMaps(mapIn, mapOut)) {
44309
- const _flowIn = amountInUSD * (mapIn[key3]?.depositRate ?? 0);
44310
- const _flowOut = amountOutUSD * (mapOut[key3]?.depositRate ?? 0);
44311
- const totalCashFlowDeposits = cashFlowDeposits + _flowOut - _flowIn;
44312
- const newCollat = deposits + amountOutUSD - amountInUSD;
44313
- data[key3] = {
44314
- borrowApr: Math.abs(debt) < 0.01 ? 0 : cashFlowDebt / debt,
44315
- depositApr: totalCashFlowDeposits / newCollat,
44316
- apr: (totalCashFlowDeposits + cashFlowDebt) / (newCollat - debt)
44317
- };
44304
+ };
44305
+ var HYPERBEAT_VAULTS = [
44306
+ {
44307
+ address: "0x5e105266db42f78FA814322Bce7f388B4C2e61eb",
44308
+ key: "Hyperbeat USDT::hbUSDT"
44309
+ },
44310
+ {
44311
+ address: "0x057ced81348D57Aad579A672d521d7b4396E8a61",
44312
+ key: "Hyperbeat USDC::hbUSDC"
44313
+ },
44314
+ {
44315
+ address: "0x81e064d0eB539de7c3170EDF38C1A42CBd752A76",
44316
+ key: "Hyperbeat LST Vault::lstHYPE"
44317
+ },
44318
+ {
44319
+ address: "0x441794D6a8F9A3739F5D4E98a728937b33489D29",
44320
+ key: "Liquid HYPE Yield::liquidHYPE"
44318
44321
  }
44319
- return data;
44320
- }
44322
+ ];
44323
+ var HYPERBEAT_VAULT_APY_URL = (address) => `https://api.hyperbeat.org/api/v1/vaults/apy/${address}?limit=1`;
44324
+ var hyperbeatVaultsFetcher = {
44325
+ label: "HYPERBEAT_VAULTS",
44326
+ fetch: async () => {
44327
+ const out = {};
44328
+ await Promise.all(
44329
+ HYPERBEAT_VAULTS.map(async ({ address, key: key3 }) => {
44330
+ try {
44331
+ const response = await fetch(HYPERBEAT_VAULT_APY_URL(address));
44332
+ if (!response.ok) {
44333
+ throw new Error(`HTTP error! Status: ${response.status}`);
44334
+ }
44335
+ const result = await response.json();
44336
+ const apy = Number(
44337
+ result.current_apy?.apy_7d ?? result.current_apy?.apy ?? 0
44338
+ );
44339
+ out[key3] = apyToAprPercent(apy);
44340
+ } catch (e) {
44341
+ out[key3] = 0;
44342
+ }
44343
+ })
44344
+ );
44345
+ return out;
44346
+ }
44347
+ };
44321
44348
 
44322
- // src/lending/margin/loop/yield/getIntrinsicYieldChange.ts
44323
- function getIntrinsicYieldOpen(amountInUSD, amountOutUSD, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
44324
- const _flowIn = amountInUSD * yieldIn.intrinsicYield;
44325
- const _flowOut = amountOutUSD * yieldOut.intrinsicYield;
44326
- const totalCashFlowDebt = cashFlowDebt + _flowIn;
44327
- const totalCashFlowDeposits = cashFlowDeposits + _flowOut;
44328
- const newCollat = deposits + amountOutUSD;
44329
- const newDebt = debt + amountInUSD;
44330
- return [
44331
- totalCashFlowDebt / newDebt,
44332
- totalCashFlowDeposits / newCollat,
44333
- (totalCashFlowDeposits - totalCashFlowDebt) / (newCollat - newDebt)
44334
- ];
44335
- }
44336
- function getIntrinsicYieldClose(amountInUSD, amountOutUSD, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
44337
- const _flowIn = amountInUSD * yieldIn.intrinsicYield;
44338
- const _flowOut = amountOutUSD * yieldOut.intrinsicYield;
44339
- const totalCashFlowDebt = cashFlowDebt - _flowOut;
44340
- const totalCashFlowDeposits = cashFlowDeposits - _flowIn;
44341
- const newCollat = deposits - amountInUSD;
44342
- const newDebt = debt - amountOutUSD;
44343
- return [
44344
- Math.abs(newDebt) < 0.01 ? 0 : totalCashFlowDebt / newDebt,
44345
- totalCashFlowDeposits / newCollat,
44346
- (totalCashFlowDeposits - totalCashFlowDebt) / (newCollat - newDebt)
44347
- ];
44348
- }
44349
- function getIntrinsicYieldDebtSwap(amountInUSD, amountOutUSD, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
44350
- const _flowIn = amountInUSD * yieldIn.intrinsicYield;
44351
- const _flowOut = amountOutUSD * yieldOut.intrinsicYield;
44352
- const totalCashFlowDebt = cashFlowDebt + _flowIn - _flowOut;
44353
- const newDebt = debt - amountOutUSD + amountInUSD;
44354
- return [
44355
- Math.abs(newDebt) < 0.01 ? 0 : totalCashFlowDebt / newDebt,
44356
- cashFlowDeposits / deposits,
44357
- (cashFlowDeposits - totalCashFlowDebt) / (deposits - newDebt)
44358
- ];
44359
- }
44360
- function getIntrinsicYieldCollateralSwap(amountInUSD, amountOutUSD, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
44361
- const _flowIn = amountInUSD * yieldIn.intrinsicYield;
44362
- const _flowOut = amountOutUSD * yieldOut.intrinsicYield;
44363
- const totalCashFlowDeposits = cashFlowDeposits + _flowOut - _flowIn;
44364
- const newCollat = deposits + amountOutUSD - amountInUSD;
44365
- return [
44366
- Math.abs(debt) < 0.01 ? 0 : cashFlowDebt / debt,
44367
- totalCashFlowDeposits / newCollat,
44368
- (totalCashFlowDeposits - cashFlowDebt) / (newCollat - debt)
44369
- ];
44370
- }
44349
+ // src/yields/intrinsic/fetchers/coinbase.ts
44350
+ var CBETH_URL = "https://api.exchange.coinbase.com/wrapped-assets/cbeth";
44351
+ var cbethFetcher = {
44352
+ label: "CBETH",
44353
+ fetch: async () => {
44354
+ try {
44355
+ const res = await fetch(CBETH_URL, {
44356
+ headers: {
44357
+ "User-Agent": "1delta/yields",
44358
+ "Content-Type": "application/json"
44359
+ }
44360
+ }).then((r) => r.json());
44361
+ return { CBETH: apyToAprPercent(res.apy) * 100 };
44362
+ } catch (e) {
44363
+ console.log("CBETH failed", e);
44364
+ return { CBETH: 0 };
44365
+ }
44366
+ }
44367
+ };
44371
44368
 
44372
- // src/lending/margin/loop/compute/computeCloseDeltas.ts
44373
- function computeCloseTradeDeltas(dollarIn, dollarOut, targetMode, yieldParamsIn, yieldParamsOut, balance, apr, bfOut, ltvIn, collateralLtvIn) {
44374
- if (dollarIn === 0 || dollarOut === 0) return noOpResult(balance, apr);
44375
- const cashFlowDeposits = balance.deposits * apr.depositApr;
44376
- const cashFlowDebt = balance.debt * apr.borrowApr;
44377
- const rewardFlowDeposits = balance.deposits * (apr.rewardDepositApr ?? 0);
44378
- const rewardFlowDebt = balance.debt * (apr.rewardBorrowApr ?? 0);
44379
- const intrinsicFlowDeposits = balance.deposits * apr.intrinsicDepositApr;
44380
- const intrinsicFlowDebt = balance.debt * apr.intrinsicBorrowApr;
44381
- const newBalance = { ...balance };
44382
- const newApr = { ...apr };
44383
- newBalance.debt = positivePart2(newBalance.debt - dollarOut);
44384
- newBalance.borrowDiscountedCollateral = positivePart2(
44385
- newBalance.borrowDiscountedCollateral - ltvIn * dollarIn
44386
- );
44387
- newBalance.collateral = positivePart2(
44388
- newBalance.collateral - collateralLtvIn * dollarIn
44389
- );
44390
- newBalance.deposits = positivePart2(newBalance.deposits - dollarIn);
44391
- newBalance.adjustedDebt = positivePart2(
44392
- newBalance.adjustedDebt - bfOut * dollarOut
44393
- );
44394
- newBalance.nav += dollarOut - dollarIn;
44395
- [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldClose(
44396
- dollarIn,
44397
- dollarOut,
44398
- targetMode,
44399
- cashFlowDeposits,
44400
- cashFlowDebt,
44401
- balance.deposits,
44402
- balance.debt,
44403
- yieldParamsIn,
44404
- yieldParamsOut
44405
- );
44406
- newApr.rewards = getRewardYieldClose(
44407
- dollarIn,
44408
- dollarOut,
44409
- targetMode,
44410
- rewardFlowDeposits,
44411
- rewardFlowDebt,
44412
- balance.deposits,
44413
- balance.debt,
44414
- yieldParamsIn,
44415
- yieldParamsOut
44416
- );
44417
- [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldClose(
44418
- dollarIn,
44419
- dollarOut,
44420
- intrinsicFlowDeposits,
44421
- intrinsicFlowDebt,
44422
- balance.deposits,
44423
- balance.debt,
44424
- yieldParamsIn,
44425
- yieldParamsOut
44426
- );
44427
- return buildLoopResult(balance, newBalance, apr, newApr);
44428
- }
44429
-
44430
- // src/lending/margin/loop/compute/computeCollateralSwapDeltas.ts
44431
- function computeCollateralSwapDeltas(dollarIn, dollarOut, yieldParamsIn, yieldParamsOut, balance, apr, ltvIn, collateralLtvIn, ltvOut, collateralLtvOut) {
44432
- if (dollarIn === 0 || dollarOut === 0) return noOpResult(balance, apr);
44433
- const cashFlowDeposits = balance.deposits * apr.depositApr;
44434
- const cashFlowDebt = balance.debt * apr.borrowApr;
44435
- const rewardFlowDeposits = balance.deposits * (apr.rewardDepositApr ?? 0);
44436
- const rewardFlowDebt = balance.debt * (apr.rewardBorrowApr ?? 0);
44437
- const intrinsicFlowDeposits = balance.deposits * apr.intrinsicDepositApr;
44438
- const intrinsicFlowDebt = balance.debt * apr.intrinsicBorrowApr;
44439
- const newBalance = { ...balance };
44440
- const newApr = { ...apr };
44441
- newBalance.borrowDiscountedCollateral += ltvOut * dollarOut - ltvIn * dollarIn;
44442
- newBalance.deposits += dollarOut - dollarIn;
44443
- newBalance.collateral += collateralLtvOut * dollarOut - collateralLtvIn * dollarIn;
44444
- newBalance.nav += dollarOut - dollarIn;
44445
- [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldCollateralSwap(
44446
- dollarIn,
44447
- dollarOut,
44448
- cashFlowDeposits,
44449
- cashFlowDebt,
44450
- balance.deposits,
44451
- balance.debt,
44452
- yieldParamsIn,
44453
- yieldParamsOut
44454
- );
44455
- newApr.rewards = getRewardYieldCollateralSwap(
44456
- dollarIn,
44457
- dollarOut,
44458
- rewardFlowDeposits,
44459
- rewardFlowDebt,
44460
- balance.deposits,
44461
- balance.debt,
44462
- yieldParamsIn,
44463
- yieldParamsOut
44464
- );
44465
- [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldCollateralSwap(
44466
- dollarIn,
44467
- dollarOut,
44468
- intrinsicFlowDeposits,
44469
- intrinsicFlowDebt,
44470
- balance.deposits,
44471
- balance.debt,
44472
- yieldParamsIn,
44473
- yieldParamsOut
44474
- );
44475
- return buildLoopResult(balance, newBalance, apr, newApr);
44476
- }
44477
-
44478
- // src/lending/margin/loop/compute/computeDebtSwapDeltas.ts
44479
- function computeDebtSwapDeltas(dollarIn, dollarOut, sourceMode, targetMode, yieldParamsIn, yieldParamsOut, balance, apr, bfInFactor, bfOutFactor) {
44480
- if (dollarIn === 0 || dollarOut === 0) return noOpResult(balance, apr);
44481
- const cashFlowDeposits = balance.deposits * apr.depositApr;
44482
- const cashFlowDebt = balance.debt * apr.borrowApr;
44483
- const rewardFlowDeposits = balance.deposits * (apr.rewardDepositApr ?? 0);
44484
- const rewardFlowDebt = balance.debt * apr.rewardBorrowApr;
44485
- const intrinsicFlowDeposits = balance.deposits * apr.intrinsicDepositApr;
44486
- const intrinsicFlowDebt = balance.debt * apr.intrinsicBorrowApr;
44487
- const newBalance = { ...balance };
44488
- const newApr = { ...apr };
44489
- newBalance.debt += dollarOut - dollarIn;
44490
- newBalance.adjustedDebt += bfOutFactor * dollarOut - bfInFactor * dollarIn;
44491
- newBalance.nav += dollarOut - dollarIn;
44492
- [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldDebtSwap(
44493
- dollarIn,
44494
- dollarOut,
44495
- sourceMode,
44496
- targetMode,
44497
- cashFlowDeposits,
44498
- cashFlowDebt,
44499
- balance.deposits,
44500
- balance.debt,
44501
- yieldParamsIn,
44502
- yieldParamsOut
44503
- );
44504
- newApr.rewards = getRewardYieldDebtSwap(
44505
- dollarIn,
44506
- dollarOut,
44507
- sourceMode,
44508
- targetMode,
44509
- rewardFlowDeposits,
44510
- rewardFlowDebt,
44511
- balance.deposits,
44512
- balance.debt,
44513
- yieldParamsIn,
44514
- yieldParamsOut
44515
- );
44516
- [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldDebtSwap(
44517
- dollarIn,
44518
- dollarOut,
44519
- intrinsicFlowDeposits,
44520
- intrinsicFlowDebt,
44521
- balance.deposits,
44522
- balance.debt,
44523
- yieldParamsIn,
44524
- yieldParamsOut
44525
- );
44526
- return buildLoopResult(balance, newBalance, apr, newApr);
44527
- }
44528
-
44529
- // src/lending/margin/loop/compute/computeOpenDeltas.ts
44530
- function computeOpenTradeDeltas(dollarIn, dollarOut, sourceMode, yieldParamsIn, yieldParamsOut, balance, apr, bfIn, collateralLtvOut, borrowLtvOut, useAllActive = false) {
44531
- if (dollarIn === 0 || dollarOut === 0) return noOpResult(balance, apr);
44532
- const cashFlowDeposits = balance.deposits * apr.depositApr;
44533
- const cashFlowDebt = balance.debt * apr.borrowApr;
44534
- const rewardFlowDeposits = balance.deposits * (apr.rewardDepositApr ?? 0);
44535
- const rewardFlowDebt = balance.debt * (apr.rewardBorrowApr ?? 0);
44536
- const intrinsicFlowDeposits = balance.deposits * apr.intrinsicDepositApr;
44537
- const intrinsicFlowDebt = balance.debt * apr.intrinsicBorrowApr;
44538
- const newBalance = { ...balance };
44539
- const newApr = { ...apr };
44540
- newBalance.debt += dollarIn;
44541
- newBalance.borrowDiscountedCollateral += borrowLtvOut * dollarOut;
44542
- newBalance.borrowDiscountedCollateralAllActive += borrowLtvOut * dollarOut;
44543
- newBalance.collateral += collateralLtvOut * dollarOut;
44544
- newBalance.collateralAllActive += collateralLtvOut * dollarOut;
44545
- newBalance.deposits += dollarOut;
44546
- newBalance.adjustedDebt += bfIn * dollarIn;
44547
- newBalance.nav += dollarOut - dollarIn;
44548
- [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldOpen(
44549
- dollarIn,
44550
- dollarOut,
44551
- sourceMode,
44552
- cashFlowDeposits,
44553
- cashFlowDebt,
44554
- balance.deposits,
44555
- balance.debt,
44556
- yieldParamsIn,
44557
- yieldParamsOut
44558
- );
44559
- newApr.rewards = getRewardYieldOpen(
44560
- dollarIn,
44561
- dollarOut,
44562
- sourceMode,
44563
- rewardFlowDeposits,
44564
- rewardFlowDebt,
44565
- balance.deposits,
44566
- balance.debt,
44567
- yieldParamsIn,
44568
- yieldParamsOut
44569
- );
44570
- [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldOpen(
44571
- dollarIn,
44572
- dollarOut,
44573
- intrinsicFlowDeposits,
44574
- intrinsicFlowDebt,
44575
- balance.deposits,
44576
- balance.debt,
44577
- yieldParamsIn,
44578
- yieldParamsOut
44579
- );
44580
- return buildLoopResult(balance, newBalance, apr, newApr, useAllActive);
44581
- }
44582
-
44583
- // src/lending/margin/loop/compute/computeZapDeltas.ts
44584
- function computeZapTradeDeltas(dollarIn, dollarOut, sourceMode, yieldParamsIn, yieldParamsOut, balance, apr, bfIn, collateralLtvOut, borrowLtvOut) {
44585
- if (dollarIn === 0 || dollarOut === 0) return noOpResult(balance, apr);
44586
- const cashFlowDeposits = balance.deposits * apr.depositApr;
44587
- const cashFlowDebt = balance.debt * apr.borrowApr;
44588
- const rewardFlowDeposits = balance.deposits * (apr.rewardDepositApr ?? 0);
44589
- const rewardFlowDebt = balance.debt * (apr.rewardBorrowApr ?? 0);
44590
- const intrinsicFlowDeposits = balance.deposits * apr.intrinsicDepositApr;
44591
- const intrinsicFlowDebt = balance.debt * apr.intrinsicBorrowApr;
44592
- const newBalance = { ...balance };
44593
- const newApr = { ...apr };
44594
- newBalance.debt += dollarIn;
44595
- newBalance.borrowDiscountedCollateral += borrowLtvOut * dollarOut;
44596
- newBalance.collateral += collateralLtvOut * dollarOut;
44597
- newBalance.deposits += dollarOut;
44598
- newBalance.adjustedDebt += bfIn * dollarIn;
44599
- newBalance.nav += dollarOut - dollarIn;
44600
- [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldOpen(
44601
- dollarIn,
44602
- dollarOut,
44603
- sourceMode,
44604
- cashFlowDeposits,
44605
- cashFlowDebt,
44606
- balance.deposits,
44607
- balance.debt,
44608
- yieldParamsIn,
44609
- yieldParamsOut
44610
- );
44611
- newApr.rewards = getRewardYieldOpen(
44612
- dollarIn,
44613
- dollarOut,
44614
- sourceMode,
44615
- rewardFlowDeposits,
44616
- rewardFlowDebt,
44617
- balance.deposits,
44618
- balance.debt,
44619
- yieldParamsIn,
44620
- yieldParamsOut
44621
- );
44622
- [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldOpen(
44623
- dollarIn,
44624
- dollarOut,
44625
- intrinsicFlowDeposits,
44626
- intrinsicFlowDebt,
44627
- balance.deposits,
44628
- balance.debt,
44629
- yieldParamsIn,
44630
- yieldParamsOut
44631
- );
44632
- return buildLoopResult(balance, newBalance, apr, newApr);
44633
- }
44634
-
44635
- // src/lending/margin/loop/ranges/getMaxAmountOpen.ts
44636
- var MaxParamThresholds = /* @__PURE__ */ ((MaxParamThresholds2) => {
44637
- MaxParamThresholds2[MaxParamThresholds2["MIN_HF"] = 1] = "MIN_HF";
44638
- MaxParamThresholds2[MaxParamThresholds2["SAME_OPEN_HF"] = 1.1] = "SAME_OPEN_HF";
44639
- MaxParamThresholds2[MaxParamThresholds2["SAFE_HF"] = 1.01] = "SAFE_HF";
44640
- return MaxParamThresholds2;
44641
- })(MaxParamThresholds || {});
44642
- function getMaxAmountOpen(borrowDiscountedCollateral, collateral, debt, cfOut, bfIn, sameAsset = false) {
44643
- if (sameAsset) {
44644
- return (collateral - 1.1 /* SAME_OPEN_HF */ * debt) / (1.1 /* SAME_OPEN_HF */ * bfIn - cfOut);
44645
- }
44646
- return (borrowDiscountedCollateral - 1.01 /* SAFE_HF */ * debt) / (1.01 /* SAFE_HF */ * bfIn - cfOut);
44647
- }
44648
-
44649
- // src/lending/margin/loop/ranges/getMaxAmountCollateralSwap.ts
44650
- function getMaxAmountCollateralSwap(borrowDiscountedCollateral, adjustedDebt, ltvIn, ltvOut) {
44651
- if (ltvOut >= ltvIn) return Infinity;
44652
- const denominator = ltvIn - ltvOut;
44653
- return (borrowDiscountedCollateral - 1.01 /* SAFE_HF */ * adjustedDebt) / denominator;
44654
- }
44655
-
44656
- // src/lending/margin/loop/ranges/getMaxAmountDebtSwap.ts
44657
- function getMaxAmountDebtSwap(borrowDiscountedCollateral, adjustedDebt, bfIn, bfOut) {
44658
- if (bfOut <= bfIn) return Infinity;
44659
- const denominator = 1.01 /* SAFE_HF */ * (bfOut - bfIn);
44660
- return (borrowDiscountedCollateral - 1.01 /* SAFE_HF */ * adjustedDebt) / denominator;
44661
- }
44662
-
44663
- // src/lending/margin/loop/ranges/getMaxAmountClose.ts
44664
- function getMaxAmountClose(borrowDiscountedCollateral, adjustedDebt, ltvIn, bfOut) {
44665
- const denominator = ltvIn - 1.01 /* SAFE_HF */ * bfOut;
44666
- if (denominator <= 0) return Infinity;
44667
- return (borrowDiscountedCollateral - 1.01 /* SAFE_HF */ * adjustedDebt) / denominator;
44668
- }
44669
- function averageDataLastN(arr, n = 7) {
44670
- const last = arr.slice(-n);
44671
- if (last.length === 0) return 0;
44672
- return last.reduce((sum3, x) => sum3 + x.data, 0) / last.length;
44673
- }
44674
- var safeFetch = async (label, fn) => {
44675
- try {
44676
- return await fn();
44677
- } catch (e) {
44678
- console.error(`Error fetching ${label}:`, e);
44679
- return void 0;
44680
- }
44681
- };
44682
- async function getListsMulti(chainIds) {
44683
- const lists = await fetchTokenLists(chainIds);
44684
- let res = {};
44685
- for (const chainId of chainIds) {
44686
- res[chainId] = { list: lists[chainId] };
44687
- }
44688
- return res;
44689
- }
44690
-
44691
- // src/yields/intrinsic/fetchers/lido.ts
44692
- var WSTETH_URL = "https://eth-api.lido.fi/v1/protocol/steth/apr/sma";
44693
- var DEFILLAMA_LIDO_URL = "https://yields.llama.fi/chart/747c1d2a-c668-4682-b9f9-296708a3dd90";
44694
- var tETH = "Treehouse ETH::TETH";
44695
- var robustFetchJson = async (url, { timeoutMs = 5e3, attempts = 3 } = {}) => {
44696
- let lastErr;
44697
- for (let i = 0; i < attempts; i++) {
44698
- try {
44699
- const res = await fetch(url, {
44700
- headers: {
44701
- accept: "application/json",
44702
- "user-agent": "1delta-margin-fetcher"
44703
- },
44704
- signal: AbortSignal.timeout(timeoutMs)
44705
- });
44706
- if (!res.ok) throw new Error(`HTTP ${res.status}`);
44707
- return await res.json();
44708
- } catch (e) {
44709
- lastErr = e;
44710
- if (i < attempts - 1) {
44711
- await new Promise((r) => setTimeout(r, 250 * (i + 1)));
44712
- }
44713
- }
44714
- }
44715
- throw lastErr;
44716
- };
44717
- async function fetchLidoApr() {
44718
- try {
44719
- const res = await robustFetchJson(WSTETH_URL);
44720
- return Number(res.data.aprs.at(-1).apr) * 0.9;
44721
- } catch {
44722
- const res = await robustFetchJson(DEFILLAMA_LIDO_URL);
44723
- const latest = res.data.at(-1);
44724
- return Number(latest.apyBase) * 0.9;
44725
- }
44726
- }
44727
- var wstethFetcher = {
44728
- label: "WSTETH",
44729
- fetch: async () => {
44730
- const apr = await fetchLidoApr();
44731
- return {
44732
- WSTETH: apr,
44733
- [tETH]: apr
44734
- };
44735
- }
44736
- };
44737
- var stmaticFetcher = {
44738
- label: "STMATIC",
44369
+ // src/yields/intrinsic/fetchers/mantle.ts
44370
+ var METH_URL = "https://meth.mantle.xyz/api/stats/apy";
44371
+ var methFetcher = {
44372
+ label: "METH",
44739
44373
  fetch: async () => {
44740
- return { STMATIC: 0 };
44374
+ const res = await fetch(METH_URL).then((r) => r.json());
44375
+ const apr = apyToApr(Number(res.data[0]?.OneDayAPY)) * 100;
44376
+ return { METH: apr, CMETH: apr };
44741
44377
  }
44742
44378
  };
44743
44379
 
44744
- // src/yields/intrinsic/fetchers/etherfi.ts
44745
- var WEETH_URL = "https://www.ether.fi/api/apr";
44746
- var WEETHS_URL = "https://api.sevenseas.capital/etherfi/ethereum/performance/0x917ceE801a67f933F2e6b33fC0cD1ED2d5909D88";
44747
- var weeths = "Super Symbiotic LRT::weETHs";
44748
- var EBTC_URL = "https://api.sevenseas.capital/etherfi/ethereum/performance/0x657e8C867D8B37dCC18fA4Caead9C45EB088C642";
44749
- var createWeethFetcher = (wstethPromise) => ({
44750
- label: "WEETH",
44380
+ // src/yields/intrinsic/fetchers/yieldnest.ts
44381
+ var YIELDNEST_URL = "https://gateway.yieldnest.finance/api/v1/graphql";
44382
+ var YIELDNEST_GQL_QUERY = "query GetTokenMetrics($networkType: NetworkType!) { getLRTsData(networkType: $networkType) { tokens { token blockchains { chainId apr { apr31d } } } } }";
44383
+ var YN_TOKENS = [
44384
+ { symbol: "ynETHx", chainId: 1, key: "ynETH MAX::YNETHX" },
44385
+ { symbol: "ynETH", chainId: 1, key: "YieldNest Restaked ETH::YNETH" },
44386
+ {
44387
+ symbol: "ynLSDe",
44388
+ chainId: 1,
44389
+ key: "YieldNest Restaked LSD Eigenlayer::YNLSDE"
44390
+ },
44391
+ { symbol: "ynRWAx", chainId: 1, key: "YieldNest RWA MAX::YNRWAX" },
44392
+ { symbol: "ynUSDx", chainId: 1, key: "ynUSD Max::YNUSDX" },
44393
+ { symbol: "STAK", chainId: 1, key: "YieldNest STAK::STAK" },
44394
+ { symbol: "ynBNBx", chainId: 56, key: "ynBNB MAX::ynBNBx" },
44395
+ { symbol: "ynBNB", chainId: 56, key: "YieldNest Restaked BNB::ynBNB" },
44396
+ { symbol: "ynBTCk", chainId: 56, key: "YieldNest BTC Kernel::ynBTCk" }
44397
+ ];
44398
+ function findApr(tokens, symbol, chainId) {
44399
+ const apr = tokens.find((t) => t.token === symbol)?.blockchains?.find((b) => b.chainId === chainId)?.apr?.apr31d;
44400
+ return Number(apr ?? 0);
44401
+ }
44402
+ var yieldNestFetcher = {
44403
+ label: "YIELDNEST",
44751
44404
  fetch: async () => {
44752
- const wstethRes = await wstethPromise;
44753
- const wstethVal = wstethRes?.WSTETH ?? 0;
44754
- let aYield = 0;
44755
- try {
44756
- const weethRes = await fetch(WEETH_URL).then((r) => r.json());
44757
- aYield = Number(weethRes.lrt2Apr);
44758
- } catch (e) {
44759
- aYield = 0.5;
44405
+ const res = await fetch(YIELDNEST_URL, {
44406
+ method: "POST",
44407
+ headers: {
44408
+ Accept: "application/json",
44409
+ "Content-Type": "application/json"
44410
+ },
44411
+ body: JSON.stringify({
44412
+ operationName: "GetTokenMetrics",
44413
+ variables: { networkType: "mainnet" },
44414
+ query: YIELDNEST_GQL_QUERY
44415
+ })
44416
+ }).then((r) => r.json());
44417
+ const tokens = res?.data?.getLRTsData?.tokens ?? [];
44418
+ const result = {};
44419
+ for (const { symbol, chainId, key: key3 } of YN_TOKENS) {
44420
+ const apr = findApr(tokens, symbol, chainId);
44421
+ if (apr > 0) result[key3] = apr;
44760
44422
  }
44761
- return { WEETH: aYield + wstethVal };
44762
- }
44763
- });
44764
- var weethsFetcher = {
44765
- label: "WEETHS",
44766
- fetch: async () => {
44767
- const res = await fetch(WEETHS_URL).then((r) => r.json());
44768
- return { [weeths]: apyToApr(res.Response.apy) * 100 };
44769
- }
44770
- };
44771
- var ebtcFetcher = {
44772
- label: "EBTC",
44773
- fetch: async () => {
44774
- const res = await fetch(EBTC_URL).then((r) => r.json());
44775
- return {
44776
- "Ether fi Staked BTC::EBTC": apyToApr(Number(res?.Response?.apy) || 0) * 100
44777
- };
44778
- }
44779
- };
44780
-
44781
- // src/yields/intrinsic/fetchers/rocketpool.ts
44782
- var RETH_URL = "https://api.rocketpool.net/api/mainnet/payload";
44783
- var rethFetcher = {
44784
- label: "RETH",
44785
- fetch: async () => {
44786
- const res = await fetch(RETH_URL).then((r) => r.json());
44787
- return { RETH: Number(res.rethAPR) };
44788
- }
44789
- };
44790
-
44791
- // src/yields/intrinsic/fetchers/renzo.ts
44792
- var EZETH_URL = "https://app.renzoprotocol.com/api/stats?chainId=1";
44793
- var ezethFetcher = {
44794
- label: "EZETH",
44795
- fetch: async () => {
44796
- const res = await fetch(EZETH_URL).then((r) => r.json());
44797
- return { EZETH: Number(res.data.apr.data.rate) };
44423
+ return result;
44798
44424
  }
44799
44425
  };
44800
44426
 
44801
- // src/yields/intrinsic/fetchers/kelp.ts
44802
- var RSETH_URL = "https://universe.kelpdao.xyz/rseth/totalApy";
44803
- var rsethFetcher = {
44804
- label: "RSETH",
44427
+ // src/yields/intrinsic/fetchers/stS.ts
44428
+ var BEETS_URL = "https://backend-v3.beets-ftm-node.com/";
44429
+ var stS = "Beets Staked Sonic::STS";
44430
+ var stsFetcher = {
44431
+ label: "STS",
44805
44432
  fetch: async () => {
44806
- const res = await fetch(RSETH_URL).then((r) => r.json());
44807
- return { RSETH: apyToAprPercent(res.totalAPY) };
44433
+ const res = await fetch(BEETS_URL, {
44434
+ method: "POST",
44435
+ headers: {
44436
+ Accept: "application/json",
44437
+ "Content-Type": "application/json"
44438
+ },
44439
+ body: JSON.stringify({
44440
+ operationName: "GetStakedSonicData",
44441
+ query: "query GetStakedSonicData { stsGetGqlStakedSonicData { stakingApr } }"
44442
+ })
44443
+ }).then((r) => r.json());
44444
+ const apr = Number(res.data?.stsGetGqlStakedSonicData?.stakingApr) * 100;
44445
+ return { [stS]: apr };
44808
44446
  }
44809
44447
  };
44810
44448
 
44811
- // src/yields/intrinsic/fetchers/swell.ts
44812
- var RSWETH_URL = "https://v3-lst.svc.swellnetwork.io/api/tokens/sweth/apr";
44813
- var rsweth = "Restaked Swell ETH::RSWETH";
44814
- var rswethFetcher = {
44815
- label: "RSWETH",
44449
+ // src/yields/intrinsic/fetchers/savax.ts
44450
+ var SAVAX_URL = "https://api.benqi.fi/liquidstaking/apr";
44451
+ var savaxFetcher = {
44452
+ label: "SAVAX",
44816
44453
  fetch: async () => {
44817
- const res = await fetch(RSWETH_URL, {
44818
- method: "GET",
44819
- headers: { Accept: "application/json", "User-Agent": "1delta/yields" }
44820
- }).then((r) => r.text());
44821
- return { [rsweth]: Number(res) ?? 0 };
44454
+ const res = await fetch(SAVAX_URL).then((r) => r.json());
44455
+ return { SAVAX: Number(res.apr) * 100 };
44822
44456
  }
44823
44457
  };
44824
-
44825
- // src/yields/intrinsic/annualizeRate.ts
44826
- var YEAR_SECONDS3 = 365 * 24 * 60 * 60;
44827
- var annualizeGrowthPercent = (growth, elapsedSeconds) => growth * (YEAR_SECONDS3 / elapsedSeconds) * 100;
44828
- var annualizeRateDeltaPercent = (rateNow, rateThen, elapsedSeconds) => {
44829
- const growth = typeof rateNow === "bigint" && typeof rateThen === "bigint" ? Number(rateNow - rateThen) / Number(rateThen) : Number(rateNow) / Number(rateThen) - 1;
44830
- return annualizeGrowthPercent(growth, elapsedSeconds);
44831
- };
44832
-
44833
- // src/yields/intrinsic/fetchers/swBTC.ts
44834
- var CHAIN_ID = "1";
44835
- var SWBTC = "0x8db2350d78abc13f5673a411d4700bcf87864dde";
44836
- var ONE_E8 = 10n ** 8n;
44837
- var WINDOW_SECONDS = 7 * 24 * 60 * 60;
44838
- var BLOCK_TIME_SECONDS = 12;
44839
- var WINDOW_BLOCKS = BigInt(Math.floor(WINDOW_SECONDS / BLOCK_TIME_SECONDS));
44840
- var MAX_RPC_TRIES = 5;
44841
- var CONVERT_TO_ASSETS_ABI = [
44458
+ var CHAIN_ID2 = "42220";
44459
+ var MANAGER = "0x0239b96d10a434a56cc9e09383077a0490cf9398";
44460
+ var ONE_E18 = 10n ** 18n;
44461
+ var WINDOW_SECONDS2 = 7 * 24 * 60 * 60;
44462
+ var BLOCK_TIME_SECONDS2 = 1;
44463
+ var WINDOW_BLOCKS2 = BigInt(Math.floor(WINDOW_SECONDS2 / BLOCK_TIME_SECONDS2));
44464
+ var MAX_RPC_TRIES2 = 5;
44465
+ var TO_CELO_ABI = [
44842
44466
  {
44843
- name: "convertToAssets",
44467
+ name: "toCelo",
44844
44468
  type: "function",
44845
44469
  stateMutability: "view",
44846
- inputs: [{ type: "uint256", name: "shares" }],
44470
+ inputs: [{ type: "uint256", name: "stCeloAmount" }],
44847
44471
  outputs: [{ type: "uint256" }]
44848
44472
  }
44849
44473
  ];
44850
- var readRateAt = (client, blockNumber) => client.readContract({
44851
- address: SWBTC,
44852
- abi: CONVERT_TO_ASSETS_ABI,
44853
- functionName: "convertToAssets",
44854
- args: [ONE_E8],
44474
+ var readRateAt2 = (client, blockNumber) => client.readContract({
44475
+ address: MANAGER,
44476
+ abi: TO_CELO_ABI,
44477
+ functionName: "toCelo",
44478
+ args: [ONE_E18],
44855
44479
  ...blockNumber !== void 0 ? { blockNumber } : {}
44856
44480
  });
44857
- var computeApr = async () => {
44481
+ var computeApr2 = async () => {
44858
44482
  let lastErr;
44859
- for (let rpcId = 0; rpcId < MAX_RPC_TRIES; rpcId++) {
44483
+ for (let rpcId = 0; rpcId < MAX_RPC_TRIES2; rpcId++) {
44860
44484
  try {
44861
- const client = getEvmClient(CHAIN_ID, rpcId);
44485
+ const client = getEvmClient(CHAIN_ID2, rpcId);
44862
44486
  const head = await client.getBlockNumber();
44863
- const pastBlock = head > WINDOW_BLOCKS ? head - WINDOW_BLOCKS : 0n;
44487
+ const pastBlock = head > WINDOW_BLOCKS2 ? head - WINDOW_BLOCKS2 : 0n;
44864
44488
  const [rateNow, rateThen, headBlock, thenBlock] = await Promise.all([
44865
- readRateAt(client),
44866
- readRateAt(client, pastBlock),
44867
- client.getBlock({ blockNumber: head }),
44868
- client.getBlock({ blockNumber: pastBlock })
44869
- ]);
44870
- if (rateNow < ONE_E8 || rateThen < ONE_E8 || rateNow < rateThen) {
44871
- throw new Error(
44872
- `non-archival or invalid rates (now=${rateNow}, then=${rateThen})`
44873
- );
44874
- }
44875
- const elapsed = Number(headBlock.timestamp - thenBlock.timestamp);
44876
- if (elapsed <= 0) throw new Error(`bad elapsed ${elapsed}`);
44877
- const apr = annualizeRateDeltaPercent(rateNow, rateThen, elapsed);
44878
- if (!Number.isFinite(apr) || apr < 0) throw new Error(`bad apr ${apr}`);
44879
- return apr;
44880
- } catch (e) {
44881
- lastErr = e;
44882
- }
44883
- }
44884
- throw new Error(
44885
- `swBTC APR: no archival Ethereum RPC returned valid historical state (${String(lastErr)})`
44886
- );
44887
- };
44888
- var swBtcFetcher = {
44889
- label: "SWBTC",
44890
- fetch: async () => {
44891
- try {
44892
- return { "Swell Restaked BTC::SWBTC": await computeApr() };
44893
- } catch {
44894
- return { "Swell Restaked BTC::SWBTC": 0 };
44895
- }
44896
- }
44897
- };
44898
-
44899
- // src/yields/intrinsic/fetchers/puffer.ts
44900
- var PUFETH_URL = "https://api-v2.puffer.fi/backend-for-frontend/tvl/all";
44901
- var pufEth = "PUFETH";
44902
- var pufethFetcher = {
44903
- label: "PUFETH",
44904
- fetch: async () => {
44905
- const res = await fetch(PUFETH_URL, {
44906
- method: "GET",
44907
- headers: { Accept: "application/json" }
44908
- }).then((r) => r.json());
44909
- return { [pufEth]: apyToAprPercent(res.apy) };
44910
- }
44911
- };
44912
-
44913
- // src/yields/intrinsic/fetchers/stakewise.ts
44914
- var OSETH_URL = "https://graphs.stakewise.io/mainnet-a/subgraphs/name/stakewise/prod?opName=osTokenApy";
44915
- var osETH = "StakeWise Staked ETH::OSETH";
44916
- var osethFetcher = {
44917
- label: "OSETH",
44918
- fetch: async () => {
44919
- const res = await fetch(OSETH_URL, {
44920
- method: "POST",
44921
- headers: { Accept: "application/json" },
44922
- body: JSON.stringify({
44923
- query: "query osTokenApy { osTokens { apy feePercent }}",
44924
- operationName: "osTokenApy"
44925
- })
44926
- }).then((r) => r.json());
44927
- const apr = apyToAprPercent(res.data?.osTokens?.[0]?.apy);
44928
- return {
44929
- [osETH]: apr,
44930
- // token-lists unifies every osETH deployment (incl. bridged) to the bare `OSETH` group — emit there too.
44931
- OSETH: apr
44932
- };
44933
- }
44934
- };
44935
-
44936
- // src/yields/intrinsic/fetchers/stader.ts
44937
- var MATICX_URL = "https://universe.staderlabs.com/polygon/apy";
44938
- var ETHX_URL = "https://universe.staderlabs.com/eth/apy";
44939
- var ethX = "Stader ETHx::ETHx";
44940
- var maticxFetcher = {
44941
- label: "MATICX",
44942
- fetch: async () => {
44943
- const res = await fetch(MATICX_URL).then((r) => r.json());
44944
- return { MATICX: Number(res.value) * 0.9 };
44945
- }
44946
- };
44947
- var ethxFetcher = {
44948
- label: "ETHX",
44949
- fetch: async () => {
44950
- const res = await fetch(ETHX_URL).then((r) => r.json());
44951
- return { [ethX]: apyToAprPercent(res.value) };
44952
- }
44953
- };
44954
-
44955
- // src/yields/intrinsic/fetchers/trufin.ts
44956
- var APY_URL = "https://api.trufin.io/staker/apy?staker=";
44957
- var createTruFinFetcher = (staker, yieldKey) => ({
44958
- label: yieldKey,
44959
- fetch: async () => {
44960
- const res = await fetch(APY_URL + staker).then((r) => r.json());
44961
- return { [yieldKey]: apyToAprPercent(res.apy) };
44962
- }
44963
- });
44964
- var trumaticFetcher = createTruFinFetcher("MATIC", "TRUMATIC");
44965
- var trupolFetcher = createTruFinFetcher("POL", "TRUPOL");
44966
-
44967
- // src/yields/intrinsic/fetchers/defillama.ts
44968
- var POOLS_ENRICHED = "https://yields.llama.fi/poolsEnriched?pool=";
44969
- var fetchDefiLlamaApy = async (poolId) => {
44970
- const res = await fetch(POOLS_ENRICHED + poolId, {
44971
- headers: { accept: "application/json" },
44972
- signal: AbortSignal.timeout(8e3)
44973
- });
44974
- if (!res.ok) throw new Error(`DefiLlama HTTP ${res.status}`);
44975
- const json = await res.json();
44976
- const apy = json?.data?.[0]?.apy;
44977
- if (typeof apy !== "number" || !Number.isFinite(apy)) {
44978
- throw new Error(`DefiLlama: no apy for pool ${poolId}`);
44979
- }
44980
- return apy;
44981
- };
44982
-
44983
- // src/yields/intrinsic/fetchers/kinetiq.ts
44984
- var KHYPE_POOL_ID = "9f25a954-db87-4bb2-a8b2-4be0b843a44c";
44985
- var KHYPE_KEY = "Kinetiq Staked HYPE::kHYPE";
44986
- var kinetiqKHypeFetcher = {
44987
- label: "KHYPE",
44988
- fetch: async () => {
44989
- const apy = await fetchDefiLlamaApy(KHYPE_POOL_ID);
44990
- return { [KHYPE_KEY]: apyToAprPercent(apy) };
44991
- }
44992
- };
44993
-
44994
- // src/yields/intrinsic/fetchers/hyperbeat.ts
44995
- var HBHYPE_URL = "https://api.hyperbeat.org/api/v1/staking?address=0xCeaD893b162D38e714D82d06a7fe0b0dc3c38E0b";
44996
- var HBUHYPE_URL = "https://app.hyperbeat.org/api/hyperfolio/vault-infos?vaultAddress=0x96C6cBB6251Ee1c257b2162ca0f39AA5Fa44B1FB";
44997
- var hbhype = "hyperbeat x ether.fi HYPE::beHYPE";
44998
- var hbuhype = "Hyperbeat Ultra Hype::hbHYPE";
44999
- var hbhypeFetcher = {
45000
- label: "HBHYPE",
45001
- fetch: async () => {
45002
- try {
45003
- const response = await fetch(HBHYPE_URL);
45004
- if (!response.ok) {
45005
- throw new Error(`HTTP error! Status: ${response.status}`);
45006
- }
45007
- const result = await response.json();
45008
- if (!result.success || !result.data || !Array.isArray(result.data.delegations)) {
45009
- throw new Error("Invalid response structure");
45010
- }
45011
- const delegations = result.data.delegations;
45012
- const totalApr = delegations.reduce(
45013
- (sum3, validator) => sum3 + Number(validator.apr ?? 0),
45014
- 0
45015
- );
45016
- const averageApr = totalApr / delegations.length;
45017
- return { [hbhype]: averageApr };
45018
- } catch (e) {
45019
- return { [hbhype]: 0 };
45020
- }
45021
- }
45022
- };
45023
- var hbuhypeFetcher = {
45024
- label: "HBUHYPE",
45025
- fetch: async () => {
45026
- try {
45027
- const response = await fetch(HBUHYPE_URL);
45028
- if (!response.ok) {
45029
- throw new Error(`HTTP error! Status: ${response.status}`);
45030
- }
45031
- const result = await response.json();
45032
- const apy = result.currentAPY?.apy_1d ?? 0;
45033
- return { [hbuhype]: apyToAprPercent(apy) };
45034
- } catch (e) {
45035
- return { [hbuhype]: 0 };
45036
- }
45037
- }
45038
- };
45039
- var HYPERBEAT_VAULTS = [
45040
- {
45041
- address: "0x5e105266db42f78FA814322Bce7f388B4C2e61eb",
45042
- key: "Hyperbeat USDT::hbUSDT"
45043
- },
45044
- {
45045
- address: "0x057ced81348D57Aad579A672d521d7b4396E8a61",
45046
- key: "Hyperbeat USDC::hbUSDC"
45047
- },
45048
- {
45049
- address: "0x81e064d0eB539de7c3170EDF38C1A42CBd752A76",
45050
- key: "Hyperbeat LST Vault::lstHYPE"
45051
- },
45052
- {
45053
- address: "0x441794D6a8F9A3739F5D4E98a728937b33489D29",
45054
- key: "Liquid HYPE Yield::liquidHYPE"
45055
- }
45056
- ];
45057
- var HYPERBEAT_VAULT_APY_URL = (address) => `https://api.hyperbeat.org/api/v1/vaults/apy/${address}?limit=1`;
45058
- var hyperbeatVaultsFetcher = {
45059
- label: "HYPERBEAT_VAULTS",
45060
- fetch: async () => {
45061
- const out = {};
45062
- await Promise.all(
45063
- HYPERBEAT_VAULTS.map(async ({ address, key: key3 }) => {
45064
- try {
45065
- const response = await fetch(HYPERBEAT_VAULT_APY_URL(address));
45066
- if (!response.ok) {
45067
- throw new Error(`HTTP error! Status: ${response.status}`);
45068
- }
45069
- const result = await response.json();
45070
- const apy = Number(
45071
- result.current_apy?.apy_7d ?? result.current_apy?.apy ?? 0
45072
- );
45073
- out[key3] = apyToAprPercent(apy);
45074
- } catch (e) {
45075
- out[key3] = 0;
45076
- }
45077
- })
45078
- );
45079
- return out;
45080
- }
45081
- };
45082
-
45083
- // src/yields/intrinsic/fetchers/coinbase.ts
45084
- var CBETH_URL = "https://api.exchange.coinbase.com/wrapped-assets/cbeth";
45085
- var cbethFetcher = {
45086
- label: "CBETH",
45087
- fetch: async () => {
45088
- try {
45089
- const res = await fetch(CBETH_URL, {
45090
- headers: {
45091
- "User-Agent": "1delta/yields",
45092
- "Content-Type": "application/json"
45093
- }
45094
- }).then((r) => r.json());
45095
- return { CBETH: apyToAprPercent(res.apy) * 100 };
45096
- } catch (e) {
45097
- console.log("CBETH failed", e);
45098
- return { CBETH: 0 };
45099
- }
45100
- }
45101
- };
45102
-
45103
- // src/yields/intrinsic/fetchers/mantle.ts
45104
- var METH_URL = "https://meth.mantle.xyz/api/stats/apy";
45105
- var methFetcher = {
45106
- label: "METH",
45107
- fetch: async () => {
45108
- const res = await fetch(METH_URL).then((r) => r.json());
45109
- const apr = apyToApr(Number(res.data[0]?.OneDayAPY)) * 100;
45110
- return { METH: apr, CMETH: apr };
45111
- }
45112
- };
45113
-
45114
- // src/yields/intrinsic/fetchers/yieldnest.ts
45115
- var YIELDNEST_URL = "https://gateway.yieldnest.finance/api/v1/graphql";
45116
- var YIELDNEST_GQL_QUERY = "query GetTokenMetrics($networkType: NetworkType!) { getLRTsData(networkType: $networkType) { tokens { token blockchains { chainId apr { apr31d } } } } }";
45117
- var YN_TOKENS = [
45118
- { symbol: "ynETHx", chainId: 1, key: "ynETH MAX::YNETHX" },
45119
- { symbol: "ynETH", chainId: 1, key: "YieldNest Restaked ETH::YNETH" },
45120
- {
45121
- symbol: "ynLSDe",
45122
- chainId: 1,
45123
- key: "YieldNest Restaked LSD Eigenlayer::YNLSDE"
45124
- },
45125
- { symbol: "ynRWAx", chainId: 1, key: "YieldNest RWA MAX::YNRWAX" },
45126
- { symbol: "ynUSDx", chainId: 1, key: "ynUSD Max::YNUSDX" },
45127
- { symbol: "STAK", chainId: 1, key: "YieldNest STAK::STAK" },
45128
- { symbol: "ynBNBx", chainId: 56, key: "ynBNB MAX::ynBNBx" },
45129
- { symbol: "ynBNB", chainId: 56, key: "YieldNest Restaked BNB::ynBNB" },
45130
- { symbol: "ynBTCk", chainId: 56, key: "YieldNest BTC Kernel::ynBTCk" }
45131
- ];
45132
- function findApr(tokens, symbol, chainId) {
45133
- const apr = tokens.find((t) => t.token === symbol)?.blockchains?.find((b) => b.chainId === chainId)?.apr?.apr31d;
45134
- return Number(apr ?? 0);
45135
- }
45136
- var yieldNestFetcher = {
45137
- label: "YIELDNEST",
45138
- fetch: async () => {
45139
- const res = await fetch(YIELDNEST_URL, {
45140
- method: "POST",
45141
- headers: {
45142
- Accept: "application/json",
45143
- "Content-Type": "application/json"
45144
- },
45145
- body: JSON.stringify({
45146
- operationName: "GetTokenMetrics",
45147
- variables: { networkType: "mainnet" },
45148
- query: YIELDNEST_GQL_QUERY
45149
- })
45150
- }).then((r) => r.json());
45151
- const tokens = res?.data?.getLRTsData?.tokens ?? [];
45152
- const result = {};
45153
- for (const { symbol, chainId, key: key3 } of YN_TOKENS) {
45154
- const apr = findApr(tokens, symbol, chainId);
45155
- if (apr > 0) result[key3] = apr;
45156
- }
45157
- return result;
45158
- }
45159
- };
45160
-
45161
- // src/yields/intrinsic/fetchers/stS.ts
45162
- var BEETS_URL = "https://backend-v3.beets-ftm-node.com/";
45163
- var stS = "Beets Staked Sonic::STS";
45164
- var stsFetcher = {
45165
- label: "STS",
45166
- fetch: async () => {
45167
- const res = await fetch(BEETS_URL, {
45168
- method: "POST",
45169
- headers: {
45170
- Accept: "application/json",
45171
- "Content-Type": "application/json"
45172
- },
45173
- body: JSON.stringify({
45174
- operationName: "GetStakedSonicData",
45175
- query: "query GetStakedSonicData { stsGetGqlStakedSonicData { stakingApr } }"
45176
- })
45177
- }).then((r) => r.json());
45178
- const apr = Number(res.data?.stsGetGqlStakedSonicData?.stakingApr) * 100;
45179
- return { [stS]: apr };
45180
- }
45181
- };
45182
-
45183
- // src/yields/intrinsic/fetchers/savax.ts
45184
- var SAVAX_URL = "https://api.benqi.fi/liquidstaking/apr";
45185
- var savaxFetcher = {
45186
- label: "SAVAX",
45187
- fetch: async () => {
45188
- const res = await fetch(SAVAX_URL).then((r) => r.json());
45189
- return { SAVAX: Number(res.apr) * 100 };
45190
- }
45191
- };
45192
- var CHAIN_ID2 = "42220";
45193
- var MANAGER = "0x0239b96d10a434a56cc9e09383077a0490cf9398";
45194
- var ONE_E18 = 10n ** 18n;
45195
- var WINDOW_SECONDS2 = 7 * 24 * 60 * 60;
45196
- var BLOCK_TIME_SECONDS2 = 1;
45197
- var WINDOW_BLOCKS2 = BigInt(Math.floor(WINDOW_SECONDS2 / BLOCK_TIME_SECONDS2));
45198
- var MAX_RPC_TRIES2 = 5;
45199
- var TO_CELO_ABI = [
45200
- {
45201
- name: "toCelo",
45202
- type: "function",
45203
- stateMutability: "view",
45204
- inputs: [{ type: "uint256", name: "stCeloAmount" }],
45205
- outputs: [{ type: "uint256" }]
45206
- }
45207
- ];
45208
- var readRateAt2 = (client, blockNumber) => client.readContract({
45209
- address: MANAGER,
45210
- abi: TO_CELO_ABI,
45211
- functionName: "toCelo",
45212
- args: [ONE_E18],
45213
- ...blockNumber !== void 0 ? { blockNumber } : {}
45214
- });
45215
- var computeApr2 = async () => {
45216
- let lastErr;
45217
- for (let rpcId = 0; rpcId < MAX_RPC_TRIES2; rpcId++) {
45218
- try {
45219
- const client = getEvmClient(CHAIN_ID2, rpcId);
45220
- const head = await client.getBlockNumber();
45221
- const pastBlock = head > WINDOW_BLOCKS2 ? head - WINDOW_BLOCKS2 : 0n;
45222
- const [rateNow, rateThen, headBlock, thenBlock] = await Promise.all([
45223
- readRateAt2(client),
45224
- readRateAt2(client, pastBlock),
44489
+ readRateAt2(client),
44490
+ readRateAt2(client, pastBlock),
45225
44491
  client.getBlock({ blockNumber: head }),
45226
44492
  client.getBlock({ blockNumber: pastBlock })
45227
44493
  ]);
@@ -45746,6 +45012,43 @@ var lombardLbtcvFetcher = createLombardVaultFetcher(
45746
45012
  "LBTCv"
45747
45013
  );
45748
45014
 
45015
+ // src/yields/intrinsic/fetchers/etherfi.ts
45016
+ var WEETH_URL = "https://www.ether.fi/api/apr";
45017
+ var WEETHS_URL = "https://api.sevenseas.capital/etherfi/ethereum/performance/0x917ceE801a67f933F2e6b33fC0cD1ED2d5909D88";
45018
+ var weeths = "Super Symbiotic LRT::weETHs";
45019
+ var EBTC_URL = "https://api.sevenseas.capital/etherfi/ethereum/performance/0x657e8C867D8B37dCC18fA4Caead9C45EB088C642";
45020
+ var createWeethFetcher = (wstethPromise) => ({
45021
+ label: "WEETH",
45022
+ fetch: async () => {
45023
+ const wstethRes = await wstethPromise;
45024
+ const wstethVal = wstethRes?.WSTETH ?? 0;
45025
+ let aYield = 0;
45026
+ try {
45027
+ const weethRes = await fetch(WEETH_URL).then((r) => r.json());
45028
+ aYield = Number(weethRes.lrt2Apr);
45029
+ } catch (e) {
45030
+ aYield = 0.5;
45031
+ }
45032
+ return { WEETH: aYield + wstethVal };
45033
+ }
45034
+ });
45035
+ var weethsFetcher = {
45036
+ label: "WEETHS",
45037
+ fetch: async () => {
45038
+ const res = await fetch(WEETHS_URL).then((r) => r.json());
45039
+ return { [weeths]: apyToApr(res.Response.apy) * 100 };
45040
+ }
45041
+ };
45042
+ var ebtcFetcher = {
45043
+ label: "EBTC",
45044
+ fetch: async () => {
45045
+ const res = await fetch(EBTC_URL).then((r) => r.json());
45046
+ return {
45047
+ "Ether fi Staked BTC::EBTC": apyToApr(Number(res?.Response?.apy) || 0) * 100
45048
+ };
45049
+ }
45050
+ };
45051
+
45749
45052
  // src/yields/intrinsic/fetchers/solv.ts
45750
45053
  var BTCPLUS_STATS_URL = "https://api.solvprotocol.org/btcplus/stats";
45751
45054
  var solvBtcPlusFetcher = {
@@ -53622,35 +52925,1736 @@ var SAVINGS_REGISTRY = (() => {
53622
52925
  if (!out[chainId]) out[chainId] = [];
53623
52926
  out[chainId].push(...entries);
53624
52927
  }
53625
- for (const [chainId, entries] of Object.entries(BITFI_ENTRIES)) {
53626
- if (!out[chainId]) out[chainId] = [];
53627
- out[chainId].push(...entries);
52928
+ for (const [chainId, entries] of Object.entries(BITFI_ENTRIES)) {
52929
+ if (!out[chainId]) out[chainId] = [];
52930
+ out[chainId].push(...entries);
52931
+ }
52932
+ for (const [chainId, entries] of Object.entries(VESPER_ENTRIES)) {
52933
+ if (!out[chainId]) out[chainId] = [];
52934
+ out[chainId].push(...entries);
52935
+ }
52936
+ for (const [chainId, entries] of Object.entries(VENUS_HUB_ENTRIES)) {
52937
+ if (!out[chainId]) out[chainId] = [];
52938
+ out[chainId].push(...entries);
52939
+ }
52940
+ return out;
52941
+ })();
52942
+ var savingsBalanceKind = (chainId, address) => {
52943
+ const lc2 = address.toLowerCase();
52944
+ return (SAVINGS_REGISTRY[chainId] ?? []).find((e) => e.address === lc2)?.balanceKind;
52945
+ };
52946
+ var isSecondaryMarketOnly = (chainId, address) => (SAVINGS_REGISTRY[chainId] ?? []).some(
52947
+ (e) => e.address === address.toLowerCase() && e.secondaryMarketOnly === true
52948
+ );
52949
+ var secondaryMarketVault = (chainId, address) => {
52950
+ const e = (SAVINGS_REGISTRY[chainId] ?? []).find(
52951
+ (x) => x.address === address.toLowerCase() && x.secondaryMarketOnly === true
52952
+ );
52953
+ return e ? { underlying: e.underlying, symbol: e.symbol } : void 0;
52954
+ };
52955
+ var savingsAddresses = (chainId) => (SAVINGS_REGISTRY[chainId] ?? []).map((e) => e.address);
52956
+ var getSavingsRegistry = (chainId) => SAVINGS_REGISTRY[chainId] ?? [];
52957
+
52958
+ // src/lending/user-data/emitters.ts
52959
+ var lc = (a) => a ? a.toLowerCase() : void 0;
52960
+ var FLUID_VAULT_FACTORY2 = "0x324c5dc1fc42c7a4d43d92df1eba58a54d13bf2d";
52961
+ var isAddr = (a) => typeof a === "string" && /^0x[0-9a-fA-F]{40}$/.test(a);
52962
+ function enumerateEmitters(chainId) {
52963
+ const out = [];
52964
+ const seen = /* @__PURE__ */ new Set();
52965
+ const push2 = (r) => {
52966
+ if (!isAddr(r.address)) return;
52967
+ const row = { ...r, address: r.address.toLowerCase() };
52968
+ const k = `${row.address}:${row.lenderKey}:${row.role}`;
52969
+ if (seen.has(k)) return;
52970
+ seen.add(k);
52971
+ out.push(row);
52972
+ };
52973
+ const uid = (lender, ref) => createMarketUid(chainId, lender, ref);
52974
+ for (const [lender, chains] of Object.entries(aavePools() ?? {})) {
52975
+ const pool = chains?.[chainId]?.pool;
52976
+ if (!pool) continue;
52977
+ push2({
52978
+ chainId,
52979
+ address: pool,
52980
+ lenderKey: lender,
52981
+ family: "aave",
52982
+ role: "core",
52983
+ label: `${lender} pool`
52984
+ });
52985
+ for (const [underlying, t] of Object.entries(
52986
+ aaveTokens()?.[lender]?.[chainId] ?? {}
52987
+ )) {
52988
+ const m = uid(lender, underlying);
52989
+ if (isAddr(t.aToken))
52990
+ push2({
52991
+ chainId,
52992
+ address: t.aToken,
52993
+ lenderKey: lender,
52994
+ family: "aave-token",
52995
+ role: "shareToken",
52996
+ side: "supply",
52997
+ marketUid: m,
52998
+ asset: lc(underlying),
52999
+ shareEvents: "transfers"
53000
+ });
53001
+ if (isAddr(t.vToken))
53002
+ push2({
53003
+ chainId,
53004
+ address: t.vToken,
53005
+ lenderKey: lender,
53006
+ family: "aave-token",
53007
+ role: "debtToken",
53008
+ side: "borrow",
53009
+ marketUid: m,
53010
+ asset: lc(underlying),
53011
+ shareEvents: "transfers"
53012
+ });
53013
+ }
53014
+ }
53015
+ for (const [spokeLower, entry] of Object.entries(
53016
+ aaveV4Spokes()?.[chainId] ?? {}
53017
+ )) {
53018
+ const lender = `AAVE_V4_${spokeLower.replace(/^0x/, "").toUpperCase()}`;
53019
+ push2({
53020
+ chainId,
53021
+ address: entry.spoke ?? spokeLower,
53022
+ lenderKey: lender,
53023
+ family: "aave-v4",
53024
+ role: "core",
53025
+ label: entry.label
53026
+ });
53027
+ }
53028
+ for (const [lender, comet] of Object.entries(
53029
+ compoundV3Pools()?.[chainId] ?? {}
53030
+ )) {
53031
+ const base = compoundV3BaseData()?.[lender]?.[chainId]?.baseAsset;
53032
+ push2({
53033
+ chainId,
53034
+ address: comet,
53035
+ lenderKey: lender,
53036
+ family: "comet",
53037
+ role: "market",
53038
+ marketUid: base ? uid(lender, base) : void 0,
53039
+ asset: lc(base)
53040
+ });
53041
+ }
53042
+ for (const [lender, chains] of Object.entries(compoundV2TokenArray() ?? {})) {
53043
+ for (const t of chains?.[chainId] ?? []) {
53044
+ push2({
53045
+ chainId,
53046
+ address: t.cToken,
53047
+ lenderKey: lender,
53048
+ family: "compound-v2",
53049
+ role: "market",
53050
+ marketUid: uid(lender, t.cToken),
53051
+ asset: lc(t.underlying)
53052
+ });
53053
+ }
53054
+ }
53055
+ for (const [lender, chains] of Object.entries(morphoPools() ?? {})) {
53056
+ const core = chains?.[chainId];
53057
+ if (!core) continue;
53058
+ push2({
53059
+ chainId,
53060
+ address: core,
53061
+ lenderKey: lender,
53062
+ family: "morpho",
53063
+ role: "core",
53064
+ label: `${lender} singleton`
53065
+ });
53066
+ }
53067
+ for (const [protocol, chains] of Object.entries(morphoTypeVaults() ?? {})) {
53068
+ for (const v of chains?.[chainId] ?? []) {
53069
+ push2({
53070
+ chainId,
53071
+ address: v.vault,
53072
+ lenderKey: `vault.${protocol.toLowerCase()}`,
53073
+ family: "erc20-share",
53074
+ role: "shareToken",
53075
+ side: "share",
53076
+ marketUid: `vault.${protocol.toLowerCase()}:${chainId}:${v.vault.toLowerCase()}`,
53077
+ asset: lc(v.underlying),
53078
+ label: v.name
53079
+ });
53080
+ }
53081
+ }
53082
+ for (const [lender, chains] of Object.entries(eulerVaults() ?? {})) {
53083
+ for (const v of chains?.[chainId] ?? []) {
53084
+ push2({
53085
+ chainId,
53086
+ address: v.vault,
53087
+ lenderKey: lender,
53088
+ family: "euler",
53089
+ role: "market",
53090
+ marketUid: uid(lender, v.vault),
53091
+ asset: lc(v.underlying)
53092
+ });
53093
+ }
53094
+ const evc = eulerConfigs()?.[lender]?.[chainId]?.evc;
53095
+ if (evc)
53096
+ push2({
53097
+ chainId,
53098
+ address: evc,
53099
+ lenderKey: lender,
53100
+ family: "euler",
53101
+ role: "core",
53102
+ label: "EVC"
53103
+ });
53104
+ }
53105
+ const siloRows = (markets, keyOf) => {
53106
+ for (const m of markets ?? []) {
53107
+ const lender = keyOf(m.siloConfig);
53108
+ for (const side of [m.silo0, m.silo1]) {
53109
+ const mu = uid(lender, side.silo);
53110
+ push2({
53111
+ chainId,
53112
+ address: side.silo,
53113
+ lenderKey: lender,
53114
+ family: "silo",
53115
+ role: "market",
53116
+ marketUid: mu,
53117
+ asset: lc(side.token)
53118
+ });
53119
+ if (isAddr(side.protectedShareToken))
53120
+ push2({
53121
+ chainId,
53122
+ address: side.protectedShareToken,
53123
+ lenderKey: lender,
53124
+ family: "erc20-share",
53125
+ role: "shareToken",
53126
+ side: "collateral",
53127
+ marketUid: mu,
53128
+ asset: lc(side.token),
53129
+ shareEvents: "transfers"
53130
+ });
53131
+ if (isAddr(side.debtShareToken))
53132
+ push2({
53133
+ chainId,
53134
+ address: side.debtShareToken,
53135
+ lenderKey: lender,
53136
+ family: "erc20-share",
53137
+ role: "debtToken",
53138
+ side: "borrow",
53139
+ marketUid: mu,
53140
+ asset: lc(side.token),
53141
+ shareEvents: "transfers"
53142
+ });
53143
+ }
53144
+ }
53145
+ };
53146
+ siloRows(siloMarkets()?.[chainId], siloV2LenderKey);
53147
+ siloRows(siloMarketsV3()?.[chainId], siloV3LenderKey);
53148
+ const siloHooks = (markets, keyOf) => {
53149
+ for (const m of markets ?? []) {
53150
+ const hook = m.silo0?.hookReceiver ?? m.silo1?.hookReceiver;
53151
+ if (!isAddr(hook)) continue;
53152
+ const lender = keyOf(m.siloConfig);
53153
+ const legs = {};
53154
+ for (const side of [m.silo0, m.silo1])
53155
+ if (isAddr(side?.silo))
53156
+ legs[lc(side.silo)] = {
53157
+ marketUid: uid(lender, side.silo),
53158
+ asset: lc(side.token)
53159
+ };
53160
+ push2({
53161
+ chainId,
53162
+ address: hook,
53163
+ lenderKey: lender,
53164
+ family: "silo",
53165
+ role: "hook",
53166
+ markets: legs,
53167
+ label: `${m.name ?? lender} liquidation hook`
53168
+ });
53169
+ }
53170
+ };
53171
+ siloHooks(siloMarkets()?.[chainId], siloV2LenderKey);
53172
+ siloHooks(siloMarketsV3()?.[chainId], siloV3LenderKey);
53173
+ const fluidEntries = fluidVaultEntries(chainId);
53174
+ for (const [vault, meta] of fluidEntries) {
53175
+ const lender = `FLUID_${chainId}_${meta.vaultId}`;
53176
+ const markets = {};
53177
+ meta.supply?.assets?.forEach((a, i) => {
53178
+ if (isAddr(a.underlying))
53179
+ markets[i === 0 ? "supply" : `supply${i}`] = {
53180
+ marketUid: uid(lender, a.underlying),
53181
+ asset: lc(a.underlying)
53182
+ };
53183
+ });
53184
+ meta.borrow?.assets?.forEach((a, i) => {
53185
+ if (isAddr(a.underlying))
53186
+ markets[i === 0 ? "borrow" : `borrow${i}`] = {
53187
+ marketUid: uid(lender, a.underlying),
53188
+ asset: lc(a.underlying)
53189
+ };
53190
+ });
53191
+ push2({
53192
+ chainId,
53193
+ address: vault,
53194
+ lenderKey: lender,
53195
+ family: "fluid",
53196
+ role: "market",
53197
+ markets,
53198
+ label: `vault ${meta.vaultId} t${meta.type}`
53199
+ });
53200
+ for (const a of meta.supply?.assets ?? []) {
53201
+ if (isAddr(a.fToken))
53202
+ push2({
53203
+ chainId,
53204
+ address: a.fToken,
53205
+ lenderKey: `FLUID_${chainId}_LENDING`,
53206
+ family: "erc20-share",
53207
+ role: "shareToken",
53208
+ side: "supply",
53209
+ marketUid: uid(`FLUID_${chainId}_LENDING`, a.underlying),
53210
+ asset: lc(a.underlying)
53211
+ });
53212
+ }
53213
+ }
53214
+ if (fluidEntries.length) {
53215
+ push2({
53216
+ chainId,
53217
+ address: FLUID_VAULT_FACTORY2,
53218
+ lenderKey: `FLUID_${chainId}`,
53219
+ family: "fluid",
53220
+ role: "positionNft",
53221
+ label: "VaultFactory (position NFT)"
53222
+ });
53223
+ }
53224
+ for (const [addr4, name] of Object.entries(
53225
+ gearboxMarketConfigurators(chainId) ?? {}
53226
+ )) {
53227
+ push2({
53228
+ chainId,
53229
+ address: addr4,
53230
+ lenderKey: "GEARBOX_V3",
53231
+ family: "gearbox",
53232
+ role: "factory",
53233
+ label: `market configurator ${name}`
53234
+ });
53235
+ }
53236
+ const dolo = dolomiteConfigs()?.[chainId];
53237
+ if (dolo?.dolomiteMargin) {
53238
+ push2({
53239
+ chainId,
53240
+ address: dolo.dolomiteMargin,
53241
+ lenderKey: "DOLOMITE",
53242
+ family: "dolomite",
53243
+ role: "core"
53244
+ });
53245
+ for (const r of [
53246
+ dolo.depositWithdrawalRouter,
53247
+ dolo.borrowPositionRouter,
53248
+ dolo.genericTraderRouter,
53249
+ dolo.depositWithdrawalProxy,
53250
+ dolo.borrowPositionProxy,
53251
+ dolo.genericTraderProxy
53252
+ ])
53253
+ if (isAddr(r))
53254
+ push2({
53255
+ chainId,
53256
+ address: r,
53257
+ lenderKey: "DOLOMITE",
53258
+ family: "dolomite",
53259
+ role: "router"
53260
+ });
53261
+ for (const [marketId, iso] of Object.entries(
53262
+ dolomiteIsolation()?.[chainId] ?? {}
53263
+ )) {
53264
+ if (isAddr(iso.factory))
53265
+ push2({
53266
+ chainId,
53267
+ address: iso.factory,
53268
+ lenderKey: "DOLOMITE",
53269
+ family: "dolomite",
53270
+ role: "factory",
53271
+ marketUid: uid("DOLOMITE", marketId),
53272
+ asset: lc(iso.underlying),
53273
+ label: `isolation ${iso.underlyingSymbol}`
53274
+ });
53275
+ }
53276
+ }
53277
+ for (const [lender, chains] of Object.entries(initConfig() ?? {})) {
53278
+ const pools = chains?.[chainId] ?? [];
53279
+ const core = getInitCoreAddress(chainId);
53280
+ const posManager = getInitPosManagerAddress(chainId);
53281
+ if (pools.length && isAddr(core)) {
53282
+ const poolRows = {};
53283
+ for (const p of pools)
53284
+ if (isAddr(p.pool)) poolRows[p.pool.toLowerCase()] = { marketUid: uid(lender, p.pool), asset: lc(p.underlying) };
53285
+ push2({ chainId, address: core, lenderKey: lender, family: "init", role: "core", markets: poolRows });
53286
+ if (isAddr(posManager))
53287
+ push2({ chainId, address: posManager, lenderKey: lender, family: "init", role: "positionNft" });
53288
+ }
53289
+ for (const p of pools) {
53290
+ push2({
53291
+ chainId,
53292
+ address: p.pool,
53293
+ lenderKey: lender,
53294
+ family: "init",
53295
+ role: "market",
53296
+ marketUid: uid(lender, p.pool),
53297
+ asset: lc(p.underlying)
53298
+ });
53299
+ }
53300
+ }
53301
+ for (const [lender, chains] of Object.entries(liquityMarkets() ?? {})) {
53302
+ for (const b of chains?.[chainId] ?? []) {
53303
+ const m = uid(lender, b.collToken);
53304
+ push2({
53305
+ chainId,
53306
+ address: b.troveManager,
53307
+ lenderKey: lender,
53308
+ family: "liquity",
53309
+ role: "market",
53310
+ marketUid: m,
53311
+ asset: lc(b.collToken),
53312
+ label: b.name
53313
+ });
53314
+ if (isAddr(b.troveNFT))
53315
+ push2({
53316
+ chainId,
53317
+ address: b.troveNFT,
53318
+ lenderKey: lender,
53319
+ family: "liquity",
53320
+ role: "positionNft",
53321
+ marketUid: m
53322
+ });
53323
+ if (isAddr(b.borrowerOperations))
53324
+ push2({
53325
+ chainId,
53326
+ address: b.borrowerOperations,
53327
+ lenderKey: lender,
53328
+ family: "liquity",
53329
+ role: "core",
53330
+ marketUid: m
53331
+ });
53332
+ if (isAddr(b.stabilityPool))
53333
+ push2({
53334
+ chainId,
53335
+ address: b.stabilityPool,
53336
+ lenderKey: lender,
53337
+ family: "liquity",
53338
+ role: "market",
53339
+ marketUid: `${m}:sp`,
53340
+ side: "supply",
53341
+ label: "stability pool"
53342
+ });
53343
+ }
53344
+ }
53345
+ for (const [lender, chains] of Object.entries(riverMarkets() ?? {})) {
53346
+ const debtToken = riverConfigFor(lender, chainId)?.debtToken;
53347
+ for (const m of chains?.[chainId]?.markets ?? []) {
53348
+ const key3 = `${lender}_${chainId}_${m.index}`;
53349
+ push2({
53350
+ chainId,
53351
+ address: m.troveManager,
53352
+ lenderKey: key3,
53353
+ family: "river",
53354
+ role: "market",
53355
+ marketUid: uid(key3, m.collToken),
53356
+ asset: lc(m.collToken),
53357
+ // TroveUpdated carries debt AND collateral; the debt row is satUSD
53358
+ markets: isAddr(debtToken) ? { loan: { marketUid: uid(key3, debtToken), asset: lc(debtToken) } } : void 0,
53359
+ label: m.name
53360
+ });
53361
+ }
53362
+ }
53363
+ const tellerCfg = tellerConfig()?.[chainId];
53364
+ if (isAddr(tellerCfg?.tellerV2))
53365
+ push2({
53366
+ chainId,
53367
+ address: tellerCfg.tellerV2,
53368
+ lenderKey: "TELLER",
53369
+ family: "teller",
53370
+ role: "core",
53371
+ label: "TellerV2 (bid lifecycle)"
53372
+ });
53373
+ for (const p of tellerPools()?.[chainId] ?? []) {
53374
+ const lender = `TELLER_${p.pool.replace(/^0x/, "").toUpperCase()}`;
53375
+ push2({
53376
+ chainId,
53377
+ address: p.pool,
53378
+ lenderKey: lender,
53379
+ family: "teller",
53380
+ role: "market",
53381
+ marketUid: uid(lender, p.principal),
53382
+ asset: lc(p.principal),
53383
+ label: p.name
53384
+ });
53385
+ }
53386
+ const termEmitters = {
53387
+ "1": "0xf021b31282a60528b2f47d07ce353da870be78b3"
53388
+ };
53389
+ const termLoanRows = {};
53390
+ for (const m of termMarkets()?.[chainId] ?? []) {
53391
+ const lender = termLenderKey(m.termRepoId);
53392
+ if (isAddr(m.purchaseToken))
53393
+ termLoanRows[m.termRepoId.toLowerCase()] = { marketUid: uid(lender, m.purchaseToken), asset: lc(m.purchaseToken) };
53394
+ push2({
53395
+ chainId,
53396
+ address: m.servicer,
53397
+ lenderKey: lender,
53398
+ family: "term",
53399
+ role: "market",
53400
+ marketUid: uid(lender, m.purchaseToken),
53401
+ asset: lc(m.purchaseToken),
53402
+ label: m.name
53403
+ });
53404
+ if (isAddr(m.repoToken))
53405
+ push2({
53406
+ chainId,
53407
+ address: m.repoToken,
53408
+ lenderKey: lender,
53409
+ family: "erc20-share",
53410
+ role: "shareToken",
53411
+ side: "supply",
53412
+ marketUid: uid(lender, m.purchaseToken),
53413
+ asset: lc(m.purchaseToken)
53414
+ });
53415
+ if (isAddr(m.auction))
53416
+ push2({
53417
+ chainId,
53418
+ address: m.auction,
53419
+ lenderKey: lender,
53420
+ family: "term",
53421
+ role: "core",
53422
+ label: "auction"
53423
+ });
53424
+ }
53425
+ if (isAddr(termEmitters[chainId]))
53426
+ push2({
53427
+ chainId,
53428
+ address: termEmitters[chainId],
53429
+ lenderKey: "TERM",
53430
+ family: "term",
53431
+ role: "core",
53432
+ label: "event emitter",
53433
+ markets: Object.keys(termLoanRows).length ? termLoanRows : void 0
53434
+ });
53435
+ const termC = termConfig()?.[chainId];
53436
+ if (termC?.termController)
53437
+ push2({
53438
+ chainId,
53439
+ address: termC.termController,
53440
+ lenderKey: "TERM",
53441
+ family: "term",
53442
+ role: "core",
53443
+ label: "controller"
53444
+ });
53445
+ const tm = termMaxConfig()?.[chainId];
53446
+ if (tm) {
53447
+ for (const f of tm.marketFactories ?? [])
53448
+ if (isAddr(f))
53449
+ push2({
53450
+ chainId,
53451
+ address: f,
53452
+ lenderKey: "TERMMAX",
53453
+ family: "termmax",
53454
+ role: "factory"
53455
+ });
53456
+ if (isAddr(tm.routerV2))
53457
+ push2({
53458
+ chainId,
53459
+ address: tm.routerV2,
53460
+ lenderKey: "TERMMAX",
53461
+ family: "termmax",
53462
+ role: "router"
53463
+ });
53464
+ }
53465
+ const mn = midnightConfig()?.[chainId];
53466
+ if (mn?.midnight) {
53467
+ const mnMarkets = {};
53468
+ for (const m of midnightMarkets()?.[chainId] ?? []) {
53469
+ const key3 = midnightLenderKey(m.marketId);
53470
+ const id = m.marketId.toLowerCase();
53471
+ if (isAddr(m.loanToken)) mnMarkets[id] = { marketUid: uid(key3, m.loanToken), asset: lc(m.loanToken) };
53472
+ m.collateralParams?.forEach((c, i) => {
53473
+ if (isAddr(c.token))
53474
+ mnMarkets[`${id}:${c.token.toLowerCase()}`] = {
53475
+ marketUid: uid(key3, midnightCollateralRef(c.token, i)),
53476
+ asset: lc(c.token)
53477
+ };
53478
+ });
53479
+ }
53480
+ push2({
53481
+ chainId,
53482
+ address: mn.midnight,
53483
+ lenderKey: "MORPHO_MIDNIGHT",
53484
+ family: "midnight",
53485
+ role: "core",
53486
+ markets: Object.keys(mnMarkets).length ? mnMarkets : void 0
53487
+ });
53488
+ }
53489
+ for (const [lender, chains] of Object.entries(llamaLendMarkets() ?? {})) {
53490
+ for (const m of chains?.[chainId]?.markets ?? []) {
53491
+ const key3 = `LLAMALEND_${m.controller.replace(/^0x/, "").toUpperCase()}`;
53492
+ const mu = uid(key3, m.borrowedToken);
53493
+ push2({
53494
+ chainId,
53495
+ address: m.controller,
53496
+ lenderKey: key3,
53497
+ family: "llamalend",
53498
+ role: "market",
53499
+ marketUid: mu,
53500
+ asset: lc(m.borrowedToken),
53501
+ label: m.name,
53502
+ markets: {
53503
+ loan: { marketUid: mu, asset: lc(m.borrowedToken) },
53504
+ collateral: {
53505
+ marketUid: uid(key3, m.collateralToken),
53506
+ asset: lc(m.collateralToken)
53507
+ }
53508
+ }
53509
+ });
53510
+ if (isAddr(m.vault))
53511
+ push2({
53512
+ chainId,
53513
+ address: m.vault,
53514
+ lenderKey: key3,
53515
+ family: "erc20-share",
53516
+ role: "shareToken",
53517
+ side: "supply",
53518
+ marketUid: mu,
53519
+ asset: lc(m.borrowedToken)
53520
+ });
53521
+ }
53522
+ }
53523
+ for (const lender of ["FRAXLEND"]) {
53524
+ for (const p of fraxlendPairsFor(lender, chainId) ?? []) {
53525
+ const key3 = fraxlendLenderKey(lender, chainId, p.address);
53526
+ push2({
53527
+ chainId,
53528
+ address: p.address,
53529
+ lenderKey: key3,
53530
+ family: "fraxlend",
53531
+ role: "market",
53532
+ label: p.label ?? p.symbol
53533
+ });
53534
+ }
53535
+ }
53536
+ for (const [lender, chains] of Object.entries(inverseMarkets() ?? {})) {
53537
+ const dola = inverseConfigFor(lender, chainId)?.dola;
53538
+ for (const m of chains?.[chainId]?.markets ?? []) {
53539
+ const key3 = `INVERSE_${m.address.replace(/^0x/, "").toUpperCase()}`;
53540
+ push2({
53541
+ chainId,
53542
+ address: m.address,
53543
+ lenderKey: key3,
53544
+ family: "inverse",
53545
+ role: "market",
53546
+ marketUid: uid(key3, m.collToken),
53547
+ asset: lc(m.collToken),
53548
+ label: m.name,
53549
+ markets: {
53550
+ collateral: {
53551
+ marketUid: uid(key3, m.collToken),
53552
+ asset: lc(m.collToken)
53553
+ },
53554
+ ...isAddr(dola) ? { loan: { marketUid: uid(key3, dola), asset: lc(dola) } } : {}
53555
+ }
53556
+ });
53557
+ }
53558
+ }
53559
+ for (const lender of resupplyLendersByChain(chainId)) {
53560
+ const c = resupplyConfigFor(lender, chainId);
53561
+ if (!c) continue;
53562
+ if (isAddr(c.registry))
53563
+ push2({
53564
+ chainId,
53565
+ address: c.registry,
53566
+ lenderKey: lender,
53567
+ family: "resupply",
53568
+ role: "factory"
53569
+ });
53570
+ for (const p of c.pairAllowlist ?? [])
53571
+ if (isAddr(p))
53572
+ push2({
53573
+ chainId,
53574
+ address: p,
53575
+ lenderKey: lender,
53576
+ family: "resupply",
53577
+ role: "market"
53578
+ });
53579
+ }
53580
+ for (const [lender, chains] of Object.entries(curvanceConfig() ?? {})) {
53581
+ const c = chains?.[chainId];
53582
+ if (!c) continue;
53583
+ if (isAddr(c.centralRegistry))
53584
+ push2({
53585
+ chainId,
53586
+ address: c.centralRegistry,
53587
+ lenderKey: lender,
53588
+ family: "curvance",
53589
+ role: "factory"
53590
+ });
53591
+ for (const pm of Object.values(c.positionManagers ?? {}))
53592
+ for (const a of Object.values(pm))
53593
+ if (isAddr(a))
53594
+ push2({
53595
+ chainId,
53596
+ address: a,
53597
+ lenderKey: lender,
53598
+ family: "curvance",
53599
+ role: "router"
53600
+ });
53601
+ }
53602
+ for (const [lender, chains] of Object.entries(frankencoinMarkets() ?? {})) {
53603
+ for (const m of chains?.[chainId]?.markets ?? []) {
53604
+ const key3 = `FRANKENCOIN_${chainId}_${m.position.replace(/^0x/, "").toUpperCase()}`;
53605
+ push2({
53606
+ chainId,
53607
+ address: m.position,
53608
+ lenderKey: key3,
53609
+ family: "frankencoin",
53610
+ role: "market",
53611
+ marketUid: uid(key3, m.collToken),
53612
+ asset: lc(m.collToken),
53613
+ label: m.name
53614
+ });
53615
+ }
53616
+ }
53617
+ for (const lender of ["SKY", "USDD"]) {
53618
+ const cfg = dssConfigFor(lender, chainId);
53619
+ if (!cfg) continue;
53620
+ if (isAddr(cfg.cdpManager))
53621
+ push2({
53622
+ chainId,
53623
+ address: cfg.cdpManager,
53624
+ lenderKey: lender,
53625
+ family: "dss",
53626
+ role: "core",
53627
+ label: "CDP manager"
53628
+ });
53629
+ const debt = dssDebtToken(cfg);
53630
+ const ilkLegs = {};
53631
+ for (const m of dssChainData(lender, chainId)?.markets ?? []) {
53632
+ if (!m.ilk) continue;
53633
+ const key3 = `${lender}_${chainId}_${m.ilk}`;
53634
+ const ilkHex = dssIlkBytes32(m.ilk).toLowerCase();
53635
+ if (isAddr(m.collToken))
53636
+ ilkLegs[`${ilkHex}:collateral`] = { marketUid: uid(key3, m.collToken), asset: lc(m.collToken) };
53637
+ if (isAddr(debt)) ilkLegs[`${ilkHex}:loan`] = { marketUid: uid(key3, debt), asset: lc(debt) };
53638
+ }
53639
+ if (isAddr(cfg.vat))
53640
+ push2({
53641
+ chainId,
53642
+ address: cfg.vat,
53643
+ lenderKey: lender,
53644
+ family: "dss",
53645
+ role: "core",
53646
+ label: "vat",
53647
+ markets: Object.keys(ilkLegs).length ? ilkLegs : void 0
53648
+ });
53649
+ const proxyRegistry = cfg.proxyRegistry;
53650
+ if (isAddr(proxyRegistry))
53651
+ push2({
53652
+ chainId,
53653
+ address: proxyRegistry,
53654
+ lenderKey: lender,
53655
+ family: "dss",
53656
+ role: "factory",
53657
+ label: "proxy registry"
53658
+ });
53659
+ for (const m of dssChainData(lender, chainId)?.markets ?? [])
53660
+ if (isAddr(m.gemJoin))
53661
+ push2({
53662
+ chainId,
53663
+ address: m.gemJoin,
53664
+ lenderKey: `${lender}_${chainId}_${m.ilk}`,
53665
+ family: "dss",
53666
+ role: "market",
53667
+ label: m.ilk
53668
+ });
53669
+ }
53670
+ for (const lender of coolerLendersByChain(chainId)) {
53671
+ const c = coolerConfigFor(lender, chainId);
53672
+ if (c?.monoCooler)
53673
+ push2({
53674
+ chainId,
53675
+ address: c.monoCooler,
53676
+ lenderKey: lender,
53677
+ family: "cooler",
53678
+ role: "core",
53679
+ markets: {
53680
+ ...isAddr(c.gohm) ? {
53681
+ collateral: {
53682
+ marketUid: uid(lender, c.gohm),
53683
+ asset: lc(c.gohm)
53684
+ }
53685
+ } : {},
53686
+ ...isAddr(c.usds) ? { loan: { marketUid: uid(lender, c.usds), asset: lc(c.usds) } } : {}
53687
+ }
53688
+ });
53689
+ }
53690
+ for (const [lender, chains] of Object.entries(twyneMarkets() ?? {})) {
53691
+ const tc = twyneConfigFor(lender, chainId);
53692
+ if (isAddr(tc?.collateralVaultFactory))
53693
+ push2({
53694
+ chainId,
53695
+ address: tc.collateralVaultFactory,
53696
+ lenderKey: lender,
53697
+ family: "twyne",
53698
+ role: "factory",
53699
+ label: `${lender} CollateralVaultFactory`
53700
+ });
53701
+ if (isAddr(tc?.evc))
53702
+ push2({
53703
+ chainId,
53704
+ address: tc.evc,
53705
+ lenderKey: lender,
53706
+ family: "twyne",
53707
+ role: "core",
53708
+ label: `${lender} EVC`
53709
+ });
53710
+ for (const m of chains?.[chainId]?.markets ?? []) {
53711
+ const key3 = m.key.startsWith("TWYNE_") ? m.key : `TWYNE_${chainId}_${m.key}`;
53712
+ push2({
53713
+ chainId,
53714
+ address: m.intermediateVault,
53715
+ lenderKey: key3,
53716
+ family: "twyne",
53717
+ role: "market",
53718
+ marketUid: `${key3}:${chainId}:${lc(m.underlyingAsset)}`,
53719
+ asset: lc(m.underlyingAsset),
53720
+ label: m.name
53721
+ });
53722
+ }
53723
+ }
53724
+ for (const m of exactlyMarkets()?.[chainId] ?? []) {
53725
+ const key3 = EXACTLY_LENDER_KEY;
53726
+ push2({
53727
+ chainId,
53728
+ address: m.market,
53729
+ lenderKey: key3,
53730
+ family: "exactly",
53731
+ role: "market",
53732
+ marketUid: uid(key3, m.asset),
53733
+ asset: lc(m.asset),
53734
+ label: m.name
53735
+ });
53736
+ }
53737
+ for (const lender of ["FLYING_TULIP"]) {
53738
+ const c = flyingTulipConfigFor(lender, chainId);
53739
+ if (c?.positionsManager)
53740
+ push2({
53741
+ chainId,
53742
+ address: c.positionsManager,
53743
+ lenderKey: lender,
53744
+ family: "flying-tulip",
53745
+ role: "core"
53746
+ });
53747
+ }
53748
+ for (const s of getSavingsRegistry(chainId) ?? []) {
53749
+ push2({
53750
+ chainId,
53751
+ address: s.address,
53752
+ lenderKey: "vault.savings",
53753
+ family: "erc20-share",
53754
+ role: "shareToken",
53755
+ side: "share",
53756
+ marketUid: `vault.savings:${chainId}:${s.address.toLowerCase()}`,
53757
+ asset: lc(s.underlying),
53758
+ label: s.symbol
53759
+ });
53760
+ }
53761
+ for (const l of getLstRegistry(chainId) ?? []) {
53762
+ push2({
53763
+ chainId,
53764
+ address: l.address,
53765
+ lenderKey: "vault.lst",
53766
+ family: "erc20-share",
53767
+ role: "shareToken",
53768
+ side: "share",
53769
+ marketUid: `vault.lst:${chainId}:${l.address.toLowerCase()}`,
53770
+ asset: lc(l.underlying),
53771
+ label: l.symbol
53772
+ });
53773
+ }
53774
+ return out;
53775
+ }
53776
+ function emitterCoverage(chainId) {
53777
+ const rows = enumerateEmitters(chainId);
53778
+ const keys = new Set(rows.map((r) => r.lenderKey));
53779
+ const covered = [];
53780
+ const missing = [];
53781
+ for (const lender of getLendersForChain(chainId)) {
53782
+ const hit = keys.has(lender) || [...keys].some(
53783
+ (k) => lender.startsWith(k + "_") || k.startsWith(lender + "_") || k.startsWith(lender)
53784
+ );
53785
+ (hit ? covered : missing).push(lender);
53786
+ }
53787
+ return { covered, missing };
53788
+ }
53789
+
53790
+ // src/lending/margin/base/standard/deposit.ts
53791
+ function computeDepositDelta(amount4, price2, balanceData2, config, modeId, createNewSubAccount = false, apr, yieldParams) {
53792
+ const { borrowCollateralFactor, collateralFactor } = getAssetConfig(config, modeId);
53793
+ const base = createNewSubAccount ? EMPTY_BALANCE : balanceData2;
53794
+ const dollarAmount = amount4 * price2;
53795
+ const postTrade = {
53796
+ ...base,
53797
+ borrowDiscountedCollateral: base.borrowDiscountedCollateral + borrowCollateralFactor * dollarAmount,
53798
+ collateral: base.collateral + collateralFactor * dollarAmount,
53799
+ deposits: base.deposits + dollarAmount,
53800
+ nav: base.nav + dollarAmount
53801
+ };
53802
+ const result = computePostTradeMetrics(base, postTrade);
53803
+ if (apr && yieldParams) {
53804
+ const cashFlowDeposits = base.deposits * apr.depositApr;
53805
+ const cashFlowDebt = base.debt * apr.borrowApr;
53806
+ const rewardFlowDeposits = base.deposits * (apr.rewardDepositApr ?? 0);
53807
+ const rewardFlowDebt = base.debt * (apr.rewardBorrowApr ?? 0);
53808
+ const intrinsicFlowDeposits = base.deposits * apr.intrinsicDepositApr;
53809
+ const intrinsicFlowDebt = base.debt * apr.intrinsicBorrowApr;
53810
+ const newApr = { ...apr };
53811
+ [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldDeposit(
53812
+ dollarAmount,
53813
+ cashFlowDeposits,
53814
+ cashFlowDebt,
53815
+ base.deposits,
53816
+ base.debt,
53817
+ yieldParams
53818
+ );
53819
+ newApr.rewards = getRewardYieldDeposit(
53820
+ dollarAmount,
53821
+ rewardFlowDeposits,
53822
+ rewardFlowDebt,
53823
+ base.deposits,
53824
+ base.debt,
53825
+ yieldParams
53826
+ );
53827
+ [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldDeposit(
53828
+ dollarAmount,
53829
+ intrinsicFlowDeposits,
53830
+ intrinsicFlowDebt,
53831
+ base.deposits,
53832
+ base.debt,
53833
+ yieldParams
53834
+ );
53835
+ result.post.aprData = newApr;
53836
+ }
53837
+ return result;
53838
+ }
53839
+
53840
+ // src/lending/margin/base/deposit.ts
53841
+ function computeDepositDelta2(lender, amount4, price2, balanceData2, config, modeId, createNewSubAccount, apr, yieldParams, targetMarketUid, positions) {
53842
+ if (isSumerType(lender)) {
53843
+ if (!positions || targetMarketUid === void 0) {
53844
+ throw new Error("Sumer operations require positions and targetMarketUid");
53845
+ }
53846
+ return computeSumerDepositDelta(
53847
+ amount4,
53848
+ price2,
53849
+ targetMarketUid,
53850
+ balanceData2,
53851
+ positions,
53852
+ createNewSubAccount,
53853
+ apr,
53854
+ yieldParams
53855
+ );
53856
+ }
53857
+ if (!config || modeId === void 0) {
53858
+ throw new Error("Standard operations require config and modeId");
53859
+ }
53860
+ return computeDepositDelta(
53861
+ amount4,
53862
+ price2,
53863
+ balanceData2,
53864
+ config,
53865
+ modeId,
53866
+ createNewSubAccount,
53867
+ apr,
53868
+ yieldParams
53869
+ );
53870
+ }
53871
+
53872
+ // src/lending/margin/base/standard/withdraw.ts
53873
+ function computeWithdrawDelta(amount4, price2, balanceData2, config, modeId, apr, yieldParams) {
53874
+ const { borrowCollateralFactor, collateralFactor } = getAssetConfig(config, modeId);
53875
+ const dollarAmount = amount4 * price2;
53876
+ const postTrade = {
53877
+ ...balanceData2,
53878
+ borrowDiscountedCollateral: balanceData2.borrowDiscountedCollateral - borrowCollateralFactor * dollarAmount,
53879
+ collateral: balanceData2.collateral - collateralFactor * dollarAmount,
53880
+ deposits: balanceData2.deposits - dollarAmount,
53881
+ nav: balanceData2.nav - dollarAmount
53882
+ };
53883
+ const result = computePostTradeMetrics(balanceData2, postTrade);
53884
+ if (apr && yieldParams) {
53885
+ const cashFlowDeposits = balanceData2.deposits * apr.depositApr;
53886
+ const cashFlowDebt = balanceData2.debt * apr.borrowApr;
53887
+ const rewardFlowDeposits = balanceData2.deposits * (apr.rewardDepositApr ?? 0);
53888
+ const rewardFlowDebt = balanceData2.debt * (apr.rewardBorrowApr ?? 0);
53889
+ const intrinsicFlowDeposits = balanceData2.deposits * apr.intrinsicDepositApr;
53890
+ const intrinsicFlowDebt = balanceData2.debt * apr.intrinsicBorrowApr;
53891
+ const newApr = { ...apr };
53892
+ [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldWithdraw(
53893
+ dollarAmount,
53894
+ cashFlowDeposits,
53895
+ cashFlowDebt,
53896
+ balanceData2.deposits,
53897
+ balanceData2.debt,
53898
+ yieldParams
53899
+ );
53900
+ newApr.rewards = getRewardYieldWithdraw(
53901
+ dollarAmount,
53902
+ rewardFlowDeposits,
53903
+ rewardFlowDebt,
53904
+ balanceData2.deposits,
53905
+ balanceData2.debt,
53906
+ yieldParams
53907
+ );
53908
+ [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldWithdraw(
53909
+ dollarAmount,
53910
+ intrinsicFlowDeposits,
53911
+ intrinsicFlowDebt,
53912
+ balanceData2.deposits,
53913
+ balanceData2.debt,
53914
+ yieldParams
53915
+ );
53916
+ result.post.aprData = newApr;
53917
+ }
53918
+ return result;
53919
+ }
53920
+
53921
+ // src/lending/margin/base/withdraw.ts
53922
+ function computeWithdrawDelta2(lender, amount4, price2, balanceData2, config, modeId, apr, yieldParams, targetMarketUid, positions) {
53923
+ if (isSumerType(lender)) {
53924
+ if (!positions || targetMarketUid === void 0) {
53925
+ throw new Error("Sumer operations require positions and targetMarketUid");
53926
+ }
53927
+ return computeSumerWithdrawDelta(
53928
+ amount4,
53929
+ price2,
53930
+ targetMarketUid,
53931
+ balanceData2,
53932
+ positions,
53933
+ apr,
53934
+ yieldParams
53935
+ );
53936
+ }
53937
+ if (!config || modeId === void 0) {
53938
+ throw new Error("Standard operations require config and modeId");
53939
+ }
53940
+ return computeWithdrawDelta(
53941
+ amount4,
53942
+ price2,
53943
+ balanceData2,
53944
+ config,
53945
+ modeId,
53946
+ apr,
53947
+ yieldParams
53948
+ );
53949
+ }
53950
+
53951
+ // src/lending/margin/base/standard/borrow.ts
53952
+ function computeBorrowDelta(amount4, price2, balanceData2, config, modeId, apr, yieldParams, irMode) {
53953
+ const { borrowFactor } = getAssetConfig(config, modeId);
53954
+ const dollarAmount = amount4 * price2;
53955
+ const postTrade = {
53956
+ ...balanceData2,
53957
+ debt: balanceData2.debt + dollarAmount,
53958
+ adjustedDebt: balanceData2.adjustedDebt + borrowFactor * dollarAmount,
53959
+ nav: balanceData2.nav - dollarAmount
53960
+ };
53961
+ const result = computePostTradeMetrics(balanceData2, postTrade);
53962
+ if (apr && yieldParams) {
53963
+ const mode = irMode ?? 2;
53964
+ const cashFlowDeposits = balanceData2.deposits * apr.depositApr;
53965
+ const cashFlowDebt = balanceData2.debt * apr.borrowApr;
53966
+ const rewardFlowDeposits = balanceData2.deposits * (apr.rewardDepositApr ?? 0);
53967
+ const rewardFlowDebt = balanceData2.debt * (apr.rewardBorrowApr ?? 0);
53968
+ const intrinsicFlowDeposits = balanceData2.deposits * apr.intrinsicDepositApr;
53969
+ const intrinsicFlowDebt = balanceData2.debt * apr.intrinsicBorrowApr;
53970
+ const newApr = { ...apr };
53971
+ [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldBorrow(
53972
+ dollarAmount,
53973
+ mode,
53974
+ cashFlowDeposits,
53975
+ cashFlowDebt,
53976
+ balanceData2.deposits,
53977
+ balanceData2.debt,
53978
+ yieldParams
53979
+ );
53980
+ newApr.rewards = getRewardYieldBorrow(
53981
+ dollarAmount,
53982
+ mode,
53983
+ rewardFlowDeposits,
53984
+ rewardFlowDebt,
53985
+ balanceData2.deposits,
53986
+ balanceData2.debt,
53987
+ yieldParams
53988
+ );
53989
+ [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldBorrow(
53990
+ dollarAmount,
53991
+ intrinsicFlowDeposits,
53992
+ intrinsicFlowDebt,
53993
+ balanceData2.deposits,
53994
+ balanceData2.debt,
53995
+ yieldParams
53996
+ );
53997
+ result.post.aprData = newApr;
53998
+ }
53999
+ return result;
54000
+ }
54001
+
54002
+ // src/lending/margin/base/borrow.ts
54003
+ function computeBorrowDelta2(lender, amount4, price2, balanceData2, config, modeId, apr, yieldParams, irMode, targetMarketUid, positions) {
54004
+ if (isSumerType(lender)) {
54005
+ if (!positions || targetMarketUid === void 0) {
54006
+ throw new Error("Sumer operations require positions and targetMarketUid");
54007
+ }
54008
+ return computeSumerBorrowDelta(
54009
+ amount4,
54010
+ price2,
54011
+ targetMarketUid,
54012
+ balanceData2,
54013
+ positions,
54014
+ apr,
54015
+ yieldParams,
54016
+ irMode
54017
+ );
54018
+ }
54019
+ if (!config || modeId === void 0) {
54020
+ throw new Error("Standard operations require config and modeId");
54021
+ }
54022
+ return computeBorrowDelta(
54023
+ amount4,
54024
+ price2,
54025
+ balanceData2,
54026
+ config,
54027
+ modeId,
54028
+ apr,
54029
+ yieldParams,
54030
+ irMode
54031
+ );
54032
+ }
54033
+
54034
+ // src/lending/margin/base/standard/repay.ts
54035
+ function computeRepayDelta(amount4, price2, balanceData2, config, modeId, apr, yieldParams, irMode) {
54036
+ const { borrowFactor } = getAssetConfig(config, modeId);
54037
+ const dollarAmount = amount4 * price2;
54038
+ const postTrade = {
54039
+ ...balanceData2,
54040
+ debt: balanceData2.debt - dollarAmount,
54041
+ adjustedDebt: Math.max(0, balanceData2.adjustedDebt - borrowFactor * dollarAmount),
54042
+ nav: balanceData2.nav + dollarAmount
54043
+ };
54044
+ const result = computePostTradeMetrics(balanceData2, postTrade);
54045
+ if (apr && yieldParams) {
54046
+ const mode = irMode ?? 2;
54047
+ const cashFlowDeposits = balanceData2.deposits * apr.depositApr;
54048
+ const cashFlowDebt = balanceData2.debt * apr.borrowApr;
54049
+ const rewardFlowDeposits = balanceData2.deposits * (apr.rewardDepositApr ?? 0);
54050
+ const rewardFlowDebt = balanceData2.debt * (apr.rewardBorrowApr ?? 0);
54051
+ const intrinsicFlowDeposits = balanceData2.deposits * apr.intrinsicDepositApr;
54052
+ const intrinsicFlowDebt = balanceData2.debt * apr.intrinsicBorrowApr;
54053
+ const newApr = { ...apr };
54054
+ [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldRepay(
54055
+ dollarAmount,
54056
+ mode,
54057
+ cashFlowDeposits,
54058
+ cashFlowDebt,
54059
+ balanceData2.deposits,
54060
+ balanceData2.debt,
54061
+ yieldParams
54062
+ );
54063
+ newApr.rewards = getRewardYieldRepay(
54064
+ dollarAmount,
54065
+ mode,
54066
+ rewardFlowDeposits,
54067
+ rewardFlowDebt,
54068
+ balanceData2.deposits,
54069
+ balanceData2.debt,
54070
+ yieldParams
54071
+ );
54072
+ [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldRepay(
54073
+ dollarAmount,
54074
+ intrinsicFlowDeposits,
54075
+ intrinsicFlowDebt,
54076
+ balanceData2.deposits,
54077
+ balanceData2.debt,
54078
+ yieldParams
54079
+ );
54080
+ result.post.aprData = newApr;
54081
+ }
54082
+ return result;
54083
+ }
54084
+
54085
+ // src/lending/margin/base/repay.ts
54086
+ function computeRepayDelta2(lender, amount4, price2, balanceData2, config, modeId, apr, yieldParams, irMode, targetMarketUid, positions) {
54087
+ if (isSumerType(lender)) {
54088
+ if (!positions || targetMarketUid === void 0) {
54089
+ throw new Error("Sumer operations require positions and targetMarketUid");
54090
+ }
54091
+ return computeSumerRepayDelta(
54092
+ amount4,
54093
+ price2,
54094
+ targetMarketUid,
54095
+ balanceData2,
54096
+ positions,
54097
+ apr,
54098
+ yieldParams,
54099
+ irMode
54100
+ );
54101
+ }
54102
+ if (!config || modeId === void 0) {
54103
+ throw new Error("Standard operations require config and modeId");
54104
+ }
54105
+ return computeRepayDelta(
54106
+ amount4,
54107
+ price2,
54108
+ balanceData2,
54109
+ config,
54110
+ modeId,
54111
+ apr,
54112
+ yieldParams,
54113
+ irMode
54114
+ );
54115
+ }
54116
+
54117
+ // src/lending/margin/loop/utils.ts
54118
+ var positivePart2 = (n) => n < 0 ? 0 : n;
54119
+ function nanTo(possiblyNaN, replacement = Infinity) {
54120
+ return isNaN(possiblyNaN) ? replacement : possiblyNaN;
54121
+ }
54122
+ function getHealthFactor2(collateral, adjustedDebt) {
54123
+ if (adjustedDebt === 0) return Infinity;
54124
+ const raw = collateral / adjustedDebt;
54125
+ return Math.round((isNaN(raw) ? 0 : raw) * 1e4) / 1e4;
54126
+ }
54127
+ function keysFromMaps(a, b) {
54128
+ const set = /* @__PURE__ */ new Set();
54129
+ if (a) for (const k of Object.keys(a)) set.add(k);
54130
+ if (b) for (const k of Object.keys(b)) set.add(k);
54131
+ return [...set];
54132
+ }
54133
+ function rewardsToMap(rewards) {
54134
+ const map = {};
54135
+ if (Array.isArray(rewards)) for (const r of rewards) map[r.asset] = r;
54136
+ return map;
54137
+ }
54138
+ function noOpResult(balance, apr) {
54139
+ const hf = getHealthFactor2(balance.collateral, balance.adjustedDebt);
54140
+ const bc = balance.collateral - balance.adjustedDebt;
54141
+ return {
54142
+ pre: { healthFactor: hf, borrowCapacity: bc },
54143
+ post: { healthFactor: hf, borrowCapacity: bc, balanceData: balance, aprData: apr }
54144
+ };
54145
+ }
54146
+ function buildLoopResult(balance, newBalance, apr, newApr, useAllActive = false) {
54147
+ const collateralPost = useAllActive ? newBalance.collateralAllActive : newBalance.collateral;
54148
+ return {
54149
+ pre: {
54150
+ healthFactor: getHealthFactor2(balance.collateral, balance.adjustedDebt),
54151
+ borrowCapacity: balance.collateral - balance.adjustedDebt
54152
+ },
54153
+ post: {
54154
+ healthFactor: newBalance.adjustedDebt === 0 ? Infinity : positivePart2(getHealthFactor2(collateralPost, newBalance.adjustedDebt)),
54155
+ borrowCapacity: newBalance.collateral - newBalance.adjustedDebt,
54156
+ balanceData: newBalance,
54157
+ aprData: newApr
54158
+ }
54159
+ };
54160
+ }
54161
+
54162
+ // src/lending/margin/loop/yield/getOraganicYieldChange.ts
54163
+ function getOrganicYieldOpen(amountInUSD, amountOutUSD, irModeIn, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
54164
+ const _flowIn = amountInUSD * (irModeIn === 1 ? yieldIn.stableBorrowRate : yieldIn.variableBorrowRate);
54165
+ const _flowOut = amountOutUSD * yieldOut.depositRate;
54166
+ const totalCashFlowDebt = cashFlowDebt + _flowIn;
54167
+ const totalCashFlowDeposits = cashFlowDeposits + _flowOut;
54168
+ const newCollat = deposits + amountOutUSD;
54169
+ const newDebt = debt + amountInUSD;
54170
+ return [
54171
+ totalCashFlowDebt / newDebt,
54172
+ totalCashFlowDeposits / newCollat,
54173
+ (totalCashFlowDeposits - totalCashFlowDebt) / (newCollat - newDebt)
54174
+ ];
54175
+ }
54176
+ function getOrganicYieldClose(amountInUSD, amountOutUSD, irModeOut, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
54177
+ const _flowIn = amountInUSD * yieldIn.depositRate;
54178
+ const _flowOut = amountOutUSD * (irModeOut === 1 ? yieldOut.stableBorrowRate : yieldOut.variableBorrowRate);
54179
+ const totalCashFlowDebt = cashFlowDebt - _flowOut;
54180
+ const totalCashFlowDeposits = cashFlowDeposits - _flowIn;
54181
+ const newCollat = deposits - amountInUSD;
54182
+ const newDebt = debt - amountOutUSD;
54183
+ return [
54184
+ Math.abs(newDebt) < 0.01 ? 0 : totalCashFlowDebt / newDebt,
54185
+ totalCashFlowDeposits / newCollat,
54186
+ (totalCashFlowDeposits - totalCashFlowDebt) / (newCollat - newDebt)
54187
+ ];
54188
+ }
54189
+ function getOrganicYieldDebtSwap(amountInUSD, amountOutUSD, irModeIn, irModeOut, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
54190
+ const _flowIn = amountInUSD * (irModeIn === 1 ? yieldIn.stableBorrowRate : yieldIn.variableBorrowRate);
54191
+ const _flowOut = amountOutUSD * (irModeOut === 1 ? yieldOut.stableBorrowRate : yieldOut.variableBorrowRate);
54192
+ const totalCashFlowDebt = cashFlowDebt + _flowIn - _flowOut;
54193
+ const newDebt = debt - amountOutUSD + amountInUSD;
54194
+ return [
54195
+ Math.abs(newDebt) < 0.01 ? 0 : totalCashFlowDebt / newDebt,
54196
+ cashFlowDeposits / deposits,
54197
+ (cashFlowDeposits - totalCashFlowDebt) / (deposits - newDebt)
54198
+ ];
54199
+ }
54200
+ function getOrganicYieldCollateralSwap(amountInUSD, amountOutUSD, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
54201
+ const _flowIn = amountInUSD * yieldIn.depositRate;
54202
+ const _flowOut = amountOutUSD * yieldOut.depositRate;
54203
+ const totalCashFlowDeposits = cashFlowDeposits + _flowOut - _flowIn;
54204
+ const newCollat = deposits + amountOutUSD - amountInUSD;
54205
+ return [
54206
+ Math.abs(debt) < 0.01 ? 0 : cashFlowDebt / debt,
54207
+ totalCashFlowDeposits / newCollat,
54208
+ (totalCashFlowDeposits - cashFlowDebt) / (newCollat - debt)
54209
+ ];
54210
+ }
54211
+
54212
+ // src/lending/margin/loop/yield/getRewardYieldChange.ts
54213
+ function getRewardYieldOpen(amountInUSD, amountOutUSD, irModeIn, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
54214
+ const mapIn = rewardsToMap(yieldIn?.rewards);
54215
+ const mapOut = rewardsToMap(yieldOut?.rewards);
54216
+ if (!yieldIn?.rewards?.length && !yieldOut?.rewards?.length) return {};
54217
+ const data = {};
54218
+ for (const key3 of keysFromMaps(mapIn, mapOut)) {
54219
+ const _flowIn = amountInUSD * ((irModeIn === 1 ? mapIn[key3]?.stableBorrowRate : mapIn[key3]?.variableBorrowRate) ?? 0);
54220
+ const _flowOut = amountOutUSD * (mapOut[key3]?.depositRate ?? 0);
54221
+ const totalCashFlowDebt = cashFlowDebt + _flowIn;
54222
+ const totalCashFlowDeposits = cashFlowDeposits + _flowOut;
54223
+ const newCollat = deposits + amountOutUSD;
54224
+ const newDebt = debt + amountInUSD;
54225
+ data[key3] = {
54226
+ borrowApr: totalCashFlowDebt / newDebt,
54227
+ depositApr: totalCashFlowDeposits / newCollat,
54228
+ apr: (cashFlowDeposits + cashFlowDebt + _flowIn + _flowOut) / (newCollat - newDebt)
54229
+ };
54230
+ }
54231
+ return data;
54232
+ }
54233
+ function getRewardYieldClose(amountInUSD, amountOutUSD, irModeOut, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
54234
+ const mapIn = rewardsToMap(yieldIn?.rewards);
54235
+ const mapOut = rewardsToMap(yieldOut?.rewards);
54236
+ if (!yieldIn?.rewards?.length && !yieldOut?.rewards?.length) return {};
54237
+ const data = {};
54238
+ for (const key3 of keysFromMaps(mapIn, mapOut)) {
54239
+ const _flowIn = amountInUSD * (mapIn[key3]?.depositRate ?? 0);
54240
+ const _flowOut = amountOutUSD * ((irModeOut === 1 ? mapOut[key3]?.stableBorrowRate : mapOut[key3]?.variableBorrowRate) ?? 0);
54241
+ const totalCashFlowDebt = cashFlowDebt - _flowOut;
54242
+ const totalCashFlowDeposits = cashFlowDeposits - _flowIn;
54243
+ const newCollat = deposits - amountInUSD;
54244
+ const newDebt = debt - amountOutUSD;
54245
+ data[key3] = {
54246
+ borrowApr: Math.abs(newDebt) < 0.01 ? 0 : totalCashFlowDebt / newDebt,
54247
+ depositApr: totalCashFlowDeposits / newCollat,
54248
+ apr: (cashFlowDeposits + cashFlowDebt - _flowIn - _flowOut) / (newCollat - newDebt)
54249
+ };
54250
+ }
54251
+ return data;
54252
+ }
54253
+ function getRewardYieldDebtSwap(amountInUSD, amountOutUSD, irModeIn, irModeOut, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
54254
+ const mapIn = rewardsToMap(yieldIn?.rewards);
54255
+ const mapOut = rewardsToMap(yieldOut?.rewards);
54256
+ if (!yieldIn?.rewards?.length && !yieldOut?.rewards?.length) return {};
54257
+ const data = {};
54258
+ for (const key3 of keysFromMaps(mapIn, mapOut)) {
54259
+ const _flowIn = amountInUSD * ((irModeIn === 1 ? mapIn[key3]?.stableBorrowRate : mapIn[key3]?.variableBorrowRate) ?? 0);
54260
+ const _flowOut = amountOutUSD * ((irModeOut === 1 ? mapOut[key3]?.stableBorrowRate : mapOut[key3]?.variableBorrowRate) ?? 0);
54261
+ const totalCashFlowDebt = cashFlowDebt + _flowIn - _flowOut;
54262
+ const newDebt = debt - amountOutUSD + amountInUSD;
54263
+ data[key3] = {
54264
+ borrowApr: Math.abs(newDebt) < 0.01 ? 0 : totalCashFlowDebt / newDebt,
54265
+ depositApr: cashFlowDeposits / deposits,
54266
+ apr: (cashFlowDeposits + totalCashFlowDebt) / (deposits - newDebt)
54267
+ };
54268
+ }
54269
+ return data;
54270
+ }
54271
+ function getRewardYieldCollateralSwap(amountInUSD, amountOutUSD, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
54272
+ const mapIn = rewardsToMap(yieldIn?.rewards);
54273
+ const mapOut = rewardsToMap(yieldOut?.rewards);
54274
+ if (!yieldIn?.rewards?.length && !yieldOut?.rewards?.length) return {};
54275
+ const data = {};
54276
+ for (const key3 of keysFromMaps(mapIn, mapOut)) {
54277
+ const _flowIn = amountInUSD * (mapIn[key3]?.depositRate ?? 0);
54278
+ const _flowOut = amountOutUSD * (mapOut[key3]?.depositRate ?? 0);
54279
+ const totalCashFlowDeposits = cashFlowDeposits + _flowOut - _flowIn;
54280
+ const newCollat = deposits + amountOutUSD - amountInUSD;
54281
+ data[key3] = {
54282
+ borrowApr: Math.abs(debt) < 0.01 ? 0 : cashFlowDebt / debt,
54283
+ depositApr: totalCashFlowDeposits / newCollat,
54284
+ apr: (totalCashFlowDeposits + cashFlowDebt) / (newCollat - debt)
54285
+ };
53628
54286
  }
53629
- for (const [chainId, entries] of Object.entries(VESPER_ENTRIES)) {
53630
- if (!out[chainId]) out[chainId] = [];
53631
- out[chainId].push(...entries);
54287
+ return data;
54288
+ }
54289
+
54290
+ // src/lending/margin/loop/yield/getIntrinsicYieldChange.ts
54291
+ function getIntrinsicYieldOpen(amountInUSD, amountOutUSD, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
54292
+ const _flowIn = amountInUSD * yieldIn.intrinsicYield;
54293
+ const _flowOut = amountOutUSD * yieldOut.intrinsicYield;
54294
+ const totalCashFlowDebt = cashFlowDebt + _flowIn;
54295
+ const totalCashFlowDeposits = cashFlowDeposits + _flowOut;
54296
+ const newCollat = deposits + amountOutUSD;
54297
+ const newDebt = debt + amountInUSD;
54298
+ return [
54299
+ totalCashFlowDebt / newDebt,
54300
+ totalCashFlowDeposits / newCollat,
54301
+ (totalCashFlowDeposits - totalCashFlowDebt) / (newCollat - newDebt)
54302
+ ];
54303
+ }
54304
+ function getIntrinsicYieldClose(amountInUSD, amountOutUSD, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
54305
+ const _flowIn = amountInUSD * yieldIn.intrinsicYield;
54306
+ const _flowOut = amountOutUSD * yieldOut.intrinsicYield;
54307
+ const totalCashFlowDebt = cashFlowDebt - _flowOut;
54308
+ const totalCashFlowDeposits = cashFlowDeposits - _flowIn;
54309
+ const newCollat = deposits - amountInUSD;
54310
+ const newDebt = debt - amountOutUSD;
54311
+ return [
54312
+ Math.abs(newDebt) < 0.01 ? 0 : totalCashFlowDebt / newDebt,
54313
+ totalCashFlowDeposits / newCollat,
54314
+ (totalCashFlowDeposits - totalCashFlowDebt) / (newCollat - newDebt)
54315
+ ];
54316
+ }
54317
+ function getIntrinsicYieldDebtSwap(amountInUSD, amountOutUSD, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
54318
+ const _flowIn = amountInUSD * yieldIn.intrinsicYield;
54319
+ const _flowOut = amountOutUSD * yieldOut.intrinsicYield;
54320
+ const totalCashFlowDebt = cashFlowDebt + _flowIn - _flowOut;
54321
+ const newDebt = debt - amountOutUSD + amountInUSD;
54322
+ return [
54323
+ Math.abs(newDebt) < 0.01 ? 0 : totalCashFlowDebt / newDebt,
54324
+ cashFlowDeposits / deposits,
54325
+ (cashFlowDeposits - totalCashFlowDebt) / (deposits - newDebt)
54326
+ ];
54327
+ }
54328
+ function getIntrinsicYieldCollateralSwap(amountInUSD, amountOutUSD, cashFlowDeposits, cashFlowDebt, deposits, debt, yieldIn, yieldOut) {
54329
+ const _flowIn = amountInUSD * yieldIn.intrinsicYield;
54330
+ const _flowOut = amountOutUSD * yieldOut.intrinsicYield;
54331
+ const totalCashFlowDeposits = cashFlowDeposits + _flowOut - _flowIn;
54332
+ const newCollat = deposits + amountOutUSD - amountInUSD;
54333
+ return [
54334
+ Math.abs(debt) < 0.01 ? 0 : cashFlowDebt / debt,
54335
+ totalCashFlowDeposits / newCollat,
54336
+ (totalCashFlowDeposits - cashFlowDebt) / (newCollat - debt)
54337
+ ];
54338
+ }
54339
+
54340
+ // src/lending/margin/loop/compute/computeCloseDeltas.ts
54341
+ function computeCloseTradeDeltas(dollarIn, dollarOut, targetMode, yieldParamsIn, yieldParamsOut, balance, apr, bfOut, ltvIn, collateralLtvIn) {
54342
+ if (dollarIn === 0 || dollarOut === 0) return noOpResult(balance, apr);
54343
+ const cashFlowDeposits = balance.deposits * apr.depositApr;
54344
+ const cashFlowDebt = balance.debt * apr.borrowApr;
54345
+ const rewardFlowDeposits = balance.deposits * (apr.rewardDepositApr ?? 0);
54346
+ const rewardFlowDebt = balance.debt * (apr.rewardBorrowApr ?? 0);
54347
+ const intrinsicFlowDeposits = balance.deposits * apr.intrinsicDepositApr;
54348
+ const intrinsicFlowDebt = balance.debt * apr.intrinsicBorrowApr;
54349
+ const newBalance = { ...balance };
54350
+ const newApr = { ...apr };
54351
+ newBalance.debt = positivePart2(newBalance.debt - dollarOut);
54352
+ newBalance.borrowDiscountedCollateral = positivePart2(
54353
+ newBalance.borrowDiscountedCollateral - ltvIn * dollarIn
54354
+ );
54355
+ newBalance.collateral = positivePart2(
54356
+ newBalance.collateral - collateralLtvIn * dollarIn
54357
+ );
54358
+ newBalance.deposits = positivePart2(newBalance.deposits - dollarIn);
54359
+ newBalance.adjustedDebt = positivePart2(
54360
+ newBalance.adjustedDebt - bfOut * dollarOut
54361
+ );
54362
+ newBalance.nav += dollarOut - dollarIn;
54363
+ [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldClose(
54364
+ dollarIn,
54365
+ dollarOut,
54366
+ targetMode,
54367
+ cashFlowDeposits,
54368
+ cashFlowDebt,
54369
+ balance.deposits,
54370
+ balance.debt,
54371
+ yieldParamsIn,
54372
+ yieldParamsOut
54373
+ );
54374
+ newApr.rewards = getRewardYieldClose(
54375
+ dollarIn,
54376
+ dollarOut,
54377
+ targetMode,
54378
+ rewardFlowDeposits,
54379
+ rewardFlowDebt,
54380
+ balance.deposits,
54381
+ balance.debt,
54382
+ yieldParamsIn,
54383
+ yieldParamsOut
54384
+ );
54385
+ [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldClose(
54386
+ dollarIn,
54387
+ dollarOut,
54388
+ intrinsicFlowDeposits,
54389
+ intrinsicFlowDebt,
54390
+ balance.deposits,
54391
+ balance.debt,
54392
+ yieldParamsIn,
54393
+ yieldParamsOut
54394
+ );
54395
+ return buildLoopResult(balance, newBalance, apr, newApr);
54396
+ }
54397
+
54398
+ // src/lending/margin/loop/compute/computeCollateralSwapDeltas.ts
54399
+ function computeCollateralSwapDeltas(dollarIn, dollarOut, yieldParamsIn, yieldParamsOut, balance, apr, ltvIn, collateralLtvIn, ltvOut, collateralLtvOut) {
54400
+ if (dollarIn === 0 || dollarOut === 0) return noOpResult(balance, apr);
54401
+ const cashFlowDeposits = balance.deposits * apr.depositApr;
54402
+ const cashFlowDebt = balance.debt * apr.borrowApr;
54403
+ const rewardFlowDeposits = balance.deposits * (apr.rewardDepositApr ?? 0);
54404
+ const rewardFlowDebt = balance.debt * (apr.rewardBorrowApr ?? 0);
54405
+ const intrinsicFlowDeposits = balance.deposits * apr.intrinsicDepositApr;
54406
+ const intrinsicFlowDebt = balance.debt * apr.intrinsicBorrowApr;
54407
+ const newBalance = { ...balance };
54408
+ const newApr = { ...apr };
54409
+ newBalance.borrowDiscountedCollateral += ltvOut * dollarOut - ltvIn * dollarIn;
54410
+ newBalance.deposits += dollarOut - dollarIn;
54411
+ newBalance.collateral += collateralLtvOut * dollarOut - collateralLtvIn * dollarIn;
54412
+ newBalance.nav += dollarOut - dollarIn;
54413
+ [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldCollateralSwap(
54414
+ dollarIn,
54415
+ dollarOut,
54416
+ cashFlowDeposits,
54417
+ cashFlowDebt,
54418
+ balance.deposits,
54419
+ balance.debt,
54420
+ yieldParamsIn,
54421
+ yieldParamsOut
54422
+ );
54423
+ newApr.rewards = getRewardYieldCollateralSwap(
54424
+ dollarIn,
54425
+ dollarOut,
54426
+ rewardFlowDeposits,
54427
+ rewardFlowDebt,
54428
+ balance.deposits,
54429
+ balance.debt,
54430
+ yieldParamsIn,
54431
+ yieldParamsOut
54432
+ );
54433
+ [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldCollateralSwap(
54434
+ dollarIn,
54435
+ dollarOut,
54436
+ intrinsicFlowDeposits,
54437
+ intrinsicFlowDebt,
54438
+ balance.deposits,
54439
+ balance.debt,
54440
+ yieldParamsIn,
54441
+ yieldParamsOut
54442
+ );
54443
+ return buildLoopResult(balance, newBalance, apr, newApr);
54444
+ }
54445
+
54446
+ // src/lending/margin/loop/compute/computeDebtSwapDeltas.ts
54447
+ function computeDebtSwapDeltas(dollarIn, dollarOut, sourceMode, targetMode, yieldParamsIn, yieldParamsOut, balance, apr, bfInFactor, bfOutFactor) {
54448
+ if (dollarIn === 0 || dollarOut === 0) return noOpResult(balance, apr);
54449
+ const cashFlowDeposits = balance.deposits * apr.depositApr;
54450
+ const cashFlowDebt = balance.debt * apr.borrowApr;
54451
+ const rewardFlowDeposits = balance.deposits * (apr.rewardDepositApr ?? 0);
54452
+ const rewardFlowDebt = balance.debt * apr.rewardBorrowApr;
54453
+ const intrinsicFlowDeposits = balance.deposits * apr.intrinsicDepositApr;
54454
+ const intrinsicFlowDebt = balance.debt * apr.intrinsicBorrowApr;
54455
+ const newBalance = { ...balance };
54456
+ const newApr = { ...apr };
54457
+ newBalance.debt += dollarOut - dollarIn;
54458
+ newBalance.adjustedDebt += bfOutFactor * dollarOut - bfInFactor * dollarIn;
54459
+ newBalance.nav += dollarOut - dollarIn;
54460
+ [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldDebtSwap(
54461
+ dollarIn,
54462
+ dollarOut,
54463
+ sourceMode,
54464
+ targetMode,
54465
+ cashFlowDeposits,
54466
+ cashFlowDebt,
54467
+ balance.deposits,
54468
+ balance.debt,
54469
+ yieldParamsIn,
54470
+ yieldParamsOut
54471
+ );
54472
+ newApr.rewards = getRewardYieldDebtSwap(
54473
+ dollarIn,
54474
+ dollarOut,
54475
+ sourceMode,
54476
+ targetMode,
54477
+ rewardFlowDeposits,
54478
+ rewardFlowDebt,
54479
+ balance.deposits,
54480
+ balance.debt,
54481
+ yieldParamsIn,
54482
+ yieldParamsOut
54483
+ );
54484
+ [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldDebtSwap(
54485
+ dollarIn,
54486
+ dollarOut,
54487
+ intrinsicFlowDeposits,
54488
+ intrinsicFlowDebt,
54489
+ balance.deposits,
54490
+ balance.debt,
54491
+ yieldParamsIn,
54492
+ yieldParamsOut
54493
+ );
54494
+ return buildLoopResult(balance, newBalance, apr, newApr);
54495
+ }
54496
+
54497
+ // src/lending/margin/loop/compute/computeOpenDeltas.ts
54498
+ function computeOpenTradeDeltas(dollarIn, dollarOut, sourceMode, yieldParamsIn, yieldParamsOut, balance, apr, bfIn, collateralLtvOut, borrowLtvOut, useAllActive = false) {
54499
+ if (dollarIn === 0 || dollarOut === 0) return noOpResult(balance, apr);
54500
+ const cashFlowDeposits = balance.deposits * apr.depositApr;
54501
+ const cashFlowDebt = balance.debt * apr.borrowApr;
54502
+ const rewardFlowDeposits = balance.deposits * (apr.rewardDepositApr ?? 0);
54503
+ const rewardFlowDebt = balance.debt * (apr.rewardBorrowApr ?? 0);
54504
+ const intrinsicFlowDeposits = balance.deposits * apr.intrinsicDepositApr;
54505
+ const intrinsicFlowDebt = balance.debt * apr.intrinsicBorrowApr;
54506
+ const newBalance = { ...balance };
54507
+ const newApr = { ...apr };
54508
+ newBalance.debt += dollarIn;
54509
+ newBalance.borrowDiscountedCollateral += borrowLtvOut * dollarOut;
54510
+ newBalance.borrowDiscountedCollateralAllActive += borrowLtvOut * dollarOut;
54511
+ newBalance.collateral += collateralLtvOut * dollarOut;
54512
+ newBalance.collateralAllActive += collateralLtvOut * dollarOut;
54513
+ newBalance.deposits += dollarOut;
54514
+ newBalance.adjustedDebt += bfIn * dollarIn;
54515
+ newBalance.nav += dollarOut - dollarIn;
54516
+ [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldOpen(
54517
+ dollarIn,
54518
+ dollarOut,
54519
+ sourceMode,
54520
+ cashFlowDeposits,
54521
+ cashFlowDebt,
54522
+ balance.deposits,
54523
+ balance.debt,
54524
+ yieldParamsIn,
54525
+ yieldParamsOut
54526
+ );
54527
+ newApr.rewards = getRewardYieldOpen(
54528
+ dollarIn,
54529
+ dollarOut,
54530
+ sourceMode,
54531
+ rewardFlowDeposits,
54532
+ rewardFlowDebt,
54533
+ balance.deposits,
54534
+ balance.debt,
54535
+ yieldParamsIn,
54536
+ yieldParamsOut
54537
+ );
54538
+ [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldOpen(
54539
+ dollarIn,
54540
+ dollarOut,
54541
+ intrinsicFlowDeposits,
54542
+ intrinsicFlowDebt,
54543
+ balance.deposits,
54544
+ balance.debt,
54545
+ yieldParamsIn,
54546
+ yieldParamsOut
54547
+ );
54548
+ return buildLoopResult(balance, newBalance, apr, newApr, useAllActive);
54549
+ }
54550
+
54551
+ // src/lending/margin/loop/compute/computeZapDeltas.ts
54552
+ function computeZapTradeDeltas(dollarIn, dollarOut, sourceMode, yieldParamsIn, yieldParamsOut, balance, apr, bfIn, collateralLtvOut, borrowLtvOut) {
54553
+ if (dollarIn === 0 || dollarOut === 0) return noOpResult(balance, apr);
54554
+ const cashFlowDeposits = balance.deposits * apr.depositApr;
54555
+ const cashFlowDebt = balance.debt * apr.borrowApr;
54556
+ const rewardFlowDeposits = balance.deposits * (apr.rewardDepositApr ?? 0);
54557
+ const rewardFlowDebt = balance.debt * (apr.rewardBorrowApr ?? 0);
54558
+ const intrinsicFlowDeposits = balance.deposits * apr.intrinsicDepositApr;
54559
+ const intrinsicFlowDebt = balance.debt * apr.intrinsicBorrowApr;
54560
+ const newBalance = { ...balance };
54561
+ const newApr = { ...apr };
54562
+ newBalance.debt += dollarIn;
54563
+ newBalance.borrowDiscountedCollateral += borrowLtvOut * dollarOut;
54564
+ newBalance.collateral += collateralLtvOut * dollarOut;
54565
+ newBalance.deposits += dollarOut;
54566
+ newBalance.adjustedDebt += bfIn * dollarIn;
54567
+ newBalance.nav += dollarOut - dollarIn;
54568
+ [newApr.borrowApr, newApr.depositApr, newApr.apr] = getOrganicYieldOpen(
54569
+ dollarIn,
54570
+ dollarOut,
54571
+ sourceMode,
54572
+ cashFlowDeposits,
54573
+ cashFlowDebt,
54574
+ balance.deposits,
54575
+ balance.debt,
54576
+ yieldParamsIn,
54577
+ yieldParamsOut
54578
+ );
54579
+ newApr.rewards = getRewardYieldOpen(
54580
+ dollarIn,
54581
+ dollarOut,
54582
+ sourceMode,
54583
+ rewardFlowDeposits,
54584
+ rewardFlowDebt,
54585
+ balance.deposits,
54586
+ balance.debt,
54587
+ yieldParamsIn,
54588
+ yieldParamsOut
54589
+ );
54590
+ [newApr.intrinsicBorrowApr, newApr.intrinsicDepositApr, newApr.intrinsicApr] = getIntrinsicYieldOpen(
54591
+ dollarIn,
54592
+ dollarOut,
54593
+ intrinsicFlowDeposits,
54594
+ intrinsicFlowDebt,
54595
+ balance.deposits,
54596
+ balance.debt,
54597
+ yieldParamsIn,
54598
+ yieldParamsOut
54599
+ );
54600
+ return buildLoopResult(balance, newBalance, apr, newApr);
54601
+ }
54602
+
54603
+ // src/lending/margin/loop/ranges/getMaxAmountOpen.ts
54604
+ var MaxParamThresholds = /* @__PURE__ */ ((MaxParamThresholds2) => {
54605
+ MaxParamThresholds2[MaxParamThresholds2["MIN_HF"] = 1] = "MIN_HF";
54606
+ MaxParamThresholds2[MaxParamThresholds2["SAME_OPEN_HF"] = 1.1] = "SAME_OPEN_HF";
54607
+ MaxParamThresholds2[MaxParamThresholds2["SAFE_HF"] = 1.01] = "SAFE_HF";
54608
+ return MaxParamThresholds2;
54609
+ })(MaxParamThresholds || {});
54610
+ function getMaxAmountOpen(borrowDiscountedCollateral, collateral, debt, cfOut, bfIn, sameAsset = false) {
54611
+ if (sameAsset) {
54612
+ return (collateral - 1.1 /* SAME_OPEN_HF */ * debt) / (1.1 /* SAME_OPEN_HF */ * bfIn - cfOut);
53632
54613
  }
53633
- for (const [chainId, entries] of Object.entries(VENUS_HUB_ENTRIES)) {
53634
- if (!out[chainId]) out[chainId] = [];
53635
- out[chainId].push(...entries);
54614
+ return (borrowDiscountedCollateral - 1.01 /* SAFE_HF */ * debt) / (1.01 /* SAFE_HF */ * bfIn - cfOut);
54615
+ }
54616
+
54617
+ // src/lending/margin/loop/ranges/getMaxAmountCollateralSwap.ts
54618
+ function getMaxAmountCollateralSwap(borrowDiscountedCollateral, adjustedDebt, ltvIn, ltvOut) {
54619
+ if (ltvOut >= ltvIn) return Infinity;
54620
+ const denominator = ltvIn - ltvOut;
54621
+ return (borrowDiscountedCollateral - 1.01 /* SAFE_HF */ * adjustedDebt) / denominator;
54622
+ }
54623
+
54624
+ // src/lending/margin/loop/ranges/getMaxAmountDebtSwap.ts
54625
+ function getMaxAmountDebtSwap(borrowDiscountedCollateral, adjustedDebt, bfIn, bfOut) {
54626
+ if (bfOut <= bfIn) return Infinity;
54627
+ const denominator = 1.01 /* SAFE_HF */ * (bfOut - bfIn);
54628
+ return (borrowDiscountedCollateral - 1.01 /* SAFE_HF */ * adjustedDebt) / denominator;
54629
+ }
54630
+
54631
+ // src/lending/margin/loop/ranges/getMaxAmountClose.ts
54632
+ function getMaxAmountClose(borrowDiscountedCollateral, adjustedDebt, ltvIn, bfOut) {
54633
+ const denominator = ltvIn - 1.01 /* SAFE_HF */ * bfOut;
54634
+ if (denominator <= 0) return Infinity;
54635
+ return (borrowDiscountedCollateral - 1.01 /* SAFE_HF */ * adjustedDebt) / denominator;
54636
+ }
54637
+ function averageDataLastN(arr, n = 7) {
54638
+ const last = arr.slice(-n);
54639
+ if (last.length === 0) return 0;
54640
+ return last.reduce((sum3, x) => sum3 + x.data, 0) / last.length;
54641
+ }
54642
+ var safeFetch = async (label, fn) => {
54643
+ try {
54644
+ return await fn();
54645
+ } catch (e) {
54646
+ console.error(`Error fetching ${label}:`, e);
54647
+ return void 0;
53636
54648
  }
53637
- return out;
53638
- })();
53639
- var savingsBalanceKind = (chainId, address) => {
53640
- const lc = address.toLowerCase();
53641
- return (SAVINGS_REGISTRY[chainId] ?? []).find((e) => e.address === lc)?.balanceKind;
53642
- };
53643
- var isSecondaryMarketOnly = (chainId, address) => (SAVINGS_REGISTRY[chainId] ?? []).some(
53644
- (e) => e.address === address.toLowerCase() && e.secondaryMarketOnly === true
53645
- );
53646
- var secondaryMarketVault = (chainId, address) => {
53647
- const e = (SAVINGS_REGISTRY[chainId] ?? []).find(
53648
- (x) => x.address === address.toLowerCase() && x.secondaryMarketOnly === true
53649
- );
53650
- return e ? { underlying: e.underlying, symbol: e.symbol } : void 0;
53651
54649
  };
53652
- var savingsAddresses = (chainId) => (SAVINGS_REGISTRY[chainId] ?? []).map((e) => e.address);
53653
- var getSavingsRegistry = (chainId) => SAVINGS_REGISTRY[chainId] ?? [];
54650
+ async function getListsMulti(chainIds) {
54651
+ const lists = await fetchTokenLists(chainIds);
54652
+ let res = {};
54653
+ for (const chainId of chainIds) {
54654
+ res[chainId] = { list: lists[chainId] };
54655
+ }
54656
+ return res;
54657
+ }
53654
54658
 
53655
54659
  // src/yields/intrinsic/fetchers/morphoVaults.ts
53656
54660
  var MORPHO_VAULTS_URL = "https://blue-api.morpho.org/graphql";
@@ -53897,6 +54901,78 @@ var gmxFetcher = {
53897
54901
  var PENDLE_API_BASE = "https://api-v2.pendle.finance/core";
53898
54902
  var MARKETS_ENDPOINT = `${PENDLE_API_BASE}/v1/markets/all`;
53899
54903
  var PRICES_ENDPOINT = (types) => `${PENDLE_API_BASE}/v1/prices/assets${types ? `?type=${types.join(",")}` : ""}`;
54904
+ async function fetchPendleChainIds() {
54905
+ try {
54906
+ const response = await fetch(`${PENDLE_API_BASE}/v1/assets/all`);
54907
+ if (!response.ok)
54908
+ throw new Error(`Failed to fetch assets: ${response.status}`);
54909
+ const data = await response.json();
54910
+ const ids = /* @__PURE__ */ new Set();
54911
+ for (const a of data.assets ?? []) {
54912
+ if (Number.isFinite(a?.chainId)) ids.add(String(a.chainId));
54913
+ }
54914
+ return [...ids];
54915
+ } catch (error) {
54916
+ console.error("Error fetching pendle asset chains:", error);
54917
+ return [];
54918
+ }
54919
+ }
54920
+ var ORIGIN_CHAIN_BY_CODE = {
54921
+ ETH: "1",
54922
+ ARB: "42161",
54923
+ PLASMA: "9745"
54924
+ };
54925
+ var ORIGIN_SUFFIX = /-\(([A-Z0-9]+)\)$/;
54926
+ function applyBridgedPendleYields(yields, lists, now = /* @__PURE__ */ new Date()) {
54927
+ const out = { ...yields };
54928
+ for (const [chainId, { list }] of Object.entries(lists)) {
54929
+ for (const [address, entry] of Object.entries(list ?? {})) {
54930
+ const pendle = entry?.props?.pendle;
54931
+ if (!pendle?.bridgedFrom || pendle.tokenType !== "PT") continue;
54932
+ const assetKey2 = entry.assetGroup;
54933
+ if (!assetKey2 || assetKey2 in out) continue;
54934
+ if (pendle.expiry !== void 0 && pendle.expiry * 1e3 <= now.getTime()) {
54935
+ out[assetKey2] = 0;
54936
+ continue;
54937
+ }
54938
+ const originKey = resolveOriginAssetGroup(lists, entry, chainId, address);
54939
+ if (!originKey) continue;
54940
+ const originYield = yields[originKey];
54941
+ if (originYield === void 0) continue;
54942
+ out[assetKey2] = originYield;
54943
+ }
54944
+ }
54945
+ return out;
54946
+ }
54947
+ function resolveOriginAssetGroup(lists, entry, chainId, address) {
54948
+ const pendle = entry.props?.pendle;
54949
+ const origin = pendle.origin;
54950
+ if (origin) {
54951
+ const originEntry = lists[origin.chainId]?.list?.[origin.address.toLowerCase()];
54952
+ if (originEntry?.assetGroup) return originEntry.assetGroup;
54953
+ }
54954
+ const originChain = ORIGIN_CHAIN_BY_CODE[pendle.bridgedFrom];
54955
+ const stripped = entry.symbol?.replace(ORIGIN_SUFFIX, "");
54956
+ if (!originChain || !stripped || stripped === entry.symbol) return void 0;
54957
+ const candidates = [];
54958
+ for (const candidate of Object.values(lists[originChain]?.list ?? {})) {
54959
+ const cp = candidate?.props?.pendle;
54960
+ if (cp?.tokenType !== "PT" || cp.bridgedFrom || candidate.symbol !== stripped)
54961
+ continue;
54962
+ if (pendle.expiry !== void 0 && cp.expiry !== void 0 && cp.expiry !== pendle.expiry)
54963
+ continue;
54964
+ if (candidate.assetGroup) candidates.push(candidate.assetGroup);
54965
+ }
54966
+ if (candidates.length !== 1) {
54967
+ if (candidates.length > 1) {
54968
+ console.warn(
54969
+ `pendle: bridged PT ${chainId}:${address} (${entry.symbol}) matches ${candidates.length} origin PTs \u2014 not joined`
54970
+ );
54971
+ }
54972
+ return void 0;
54973
+ }
54974
+ return candidates[0];
54975
+ }
53900
54976
  async function fetchPendleMarkets() {
53901
54977
  try {
53902
54978
  const response = await fetch(MARKETS_ENDPOINT);
@@ -53988,7 +55064,7 @@ async function fetchPendleYields(lists = {}) {
53988
55064
  }
53989
55065
  });
53990
55066
  });
53991
- return yields;
55067
+ return applyBridgedPendleYields(yields, lists, now);
53992
55068
  } catch (error) {
53993
55069
  console.error("Error in fetchPendlePrices:", error);
53994
55070
  return {};
@@ -54002,21 +55078,48 @@ function yearFractionToExpiry(expiryISO, now = /* @__PURE__ */ new Date()) {
54002
55078
  }
54003
55079
 
54004
55080
  // src/yields/intrinsic/fetchers/pendle.ts
55081
+ var FALLBACK_CHAINS = [
55082
+ Chain.ETHEREUM_MAINNET,
55083
+ Chain.ARBITRUM_ONE,
55084
+ Chain.OP_MAINNET,
55085
+ Chain.BNB_SMART_CHAIN_MAINNET,
55086
+ Chain.MANTLE,
55087
+ Chain.BASE,
55088
+ Chain.SONIC_MAINNET,
55089
+ Chain.BERACHAIN,
55090
+ Chain.HYPEREVM,
55091
+ Chain.MONAD_MAINNET,
55092
+ Chain.PLASMA_MAINNET,
55093
+ Chain.UNICHAIN,
55094
+ Chain.INK,
55095
+ Chain.KATANA,
55096
+ Chain.X_LAYER_MAINNET,
55097
+ Chain.ROBINHOOD_CHAIN
55098
+ ];
55099
+ async function loadPendleLists() {
55100
+ const known = new Set(Object.values(Chain));
55101
+ const live = (await fetchPendleChainIds()).filter((c) => known.has(c));
55102
+ const chainIds = live.length ? live : FALLBACK_CHAINS;
55103
+ const settled = await Promise.allSettled(
55104
+ chainIds.map(
55105
+ async (chainId) => [chainId, await fetchTokenList(chainId)]
55106
+ )
55107
+ );
55108
+ const lists = {};
55109
+ settled.forEach((r, i) => {
55110
+ if (r.status === "fulfilled") lists[r.value[0]] = { list: r.value[1] };
55111
+ else
55112
+ console.warn(
55113
+ `[PENDLE] token list for chain ${chainIds[i]} unavailable \u2014 skipped`,
55114
+ r.reason
55115
+ );
55116
+ });
55117
+ return lists;
55118
+ }
54005
55119
  var pendleFetcher = {
54006
55120
  label: "PENDLE",
54007
55121
  fetch: async () => {
54008
- const lists = await getListsMulti([
54009
- Chain.PLASMA_MAINNET,
54010
- Chain.ETHEREUM_MAINNET,
54011
- Chain.BERACHAIN,
54012
- Chain.MANTLE,
54013
- Chain.BASE,
54014
- Chain.OP_MAINNET,
54015
- Chain.ARBITRUM_ONE,
54016
- Chain.SONIC_MAINNET,
54017
- Chain.HYPEREVM,
54018
- Chain.BNB_SMART_CHAIN_MAINNET
54019
- ]);
55122
+ const lists = await loadPendleLists();
54020
55123
  return fetchPendleYields(lists);
54021
55124
  }
54022
55125
  };
@@ -57791,9 +58894,9 @@ var SiloOracleAbi = [
57791
58894
  ];
57792
58895
  var ZERO_ADDRESS9 = "0x0000000000000000000000000000000000000000";
57793
58896
  function lookupUSD(context, asset) {
57794
- const lc = asset.toLowerCase();
57795
- const groupKey = context.tokenList?.[lc]?.assetGroup ?? `${context.chainId}-${lc}`;
57796
- return context.usdPrices[groupKey] ?? context.usdPrices[lc] ?? 0;
58897
+ const lc2 = asset.toLowerCase();
58898
+ const groupKey = context.tokenList?.[lc2]?.assetGroup ?? `${context.chainId}-${lc2}`;
58899
+ return context.usdPrices[groupKey] ?? context.usdPrices[lc2] ?? 0;
57797
58900
  }
57798
58901
  function getSiloV2Calls(chainId) {
57799
58902
  const allMarkets = siloMarkets()?.[chainId];
@@ -57960,9 +59063,9 @@ var SiloOracleAbi2 = [
57960
59063
  ];
57961
59064
  var ZERO_ADDRESS10 = "0x0000000000000000000000000000000000000000";
57962
59065
  function lookupUSD2(context, asset) {
57963
- const lc = asset.toLowerCase();
57964
- const groupKey = context.tokenList?.[lc]?.assetGroup ?? `${context.chainId}-${lc}`;
57965
- return context.usdPrices[groupKey] ?? context.usdPrices[lc] ?? 0;
59066
+ const lc2 = asset.toLowerCase();
59067
+ const groupKey = context.tokenList?.[lc2]?.assetGroup ?? `${context.chainId}-${lc2}`;
59068
+ return context.usdPrices[groupKey] ?? context.usdPrices[lc2] ?? 0;
57966
59069
  }
57967
59070
  function getSiloV3Calls(chainId) {
57968
59071
  const allMarkets = siloMarketsV3()?.[chainId];
@@ -58378,9 +59481,9 @@ function safeNumber3(v) {
58378
59481
  return Number.isFinite(n) ? n : 0;
58379
59482
  }
58380
59483
  function lookupUSD3(context, asset) {
58381
- const lc = asset.toLowerCase();
58382
- const groupKey = context.tokenList?.[lc]?.assetGroup ?? `${context.chainId}-${lc}`;
58383
- return context.usdPrices[groupKey] ?? context.usdPrices[lc] ?? 0;
59484
+ const lc2 = asset.toLowerCase();
59485
+ const groupKey = context.tokenList?.[lc2]?.assetGroup ?? `${context.chainId}-${lc2}`;
59486
+ return context.usdPrices[groupKey] ?? context.usdPrices[lc2] ?? 0;
58384
59487
  }
58385
59488
  function parseSiloV2GraphQLResults(items, context) {
58386
59489
  const ZERO_ADDRESS12 = "0x0000000000000000000000000000000000000000";
@@ -58521,9 +59624,9 @@ function safeNumber4(v) {
58521
59624
  return Number.isFinite(n) ? n : 0;
58522
59625
  }
58523
59626
  function lookupUSD4(context, asset) {
58524
- const lc = asset.toLowerCase();
58525
- const groupKey = context.tokenList?.[lc]?.assetGroup ?? `${context.chainId}-${lc}`;
58526
- return context.usdPrices[groupKey] ?? context.usdPrices[lc] ?? 0;
59627
+ const lc2 = asset.toLowerCase();
59628
+ const groupKey = context.tokenList?.[lc2]?.assetGroup ?? `${context.chainId}-${lc2}`;
59629
+ return context.usdPrices[groupKey] ?? context.usdPrices[lc2] ?? 0;
58527
59630
  }
58528
59631
  function parseSiloV3GraphQLResults(items, context) {
58529
59632
  const ZERO_ADDRESS12 = "0x0000000000000000000000000000000000000000";
@@ -60405,7 +61508,6 @@ var FlashAbi = [
60405
61508
  ];
60406
61509
  var DEFAULT_BATCH_SIZE = 4096;
60407
61510
  var isValidResult = (v) => typeof v === "bigint";
60408
- var NATIVE_DECIMALS = 18;
60409
61511
  function parseDecimalsResult(v) {
60410
61512
  const n = typeof v === "bigint" ? Number(v) : v;
60411
61513
  if (typeof n !== "number" || !Number.isInteger(n) || n < 0 || n > 36) {
@@ -60479,7 +61581,7 @@ async function fetchFlashLiquidityForChain(chain, multicallRetry, list = {}) {
60479
61581
  const uniswapV4s = RELEVANT_UNISWAP_V4_FORKS[chain] ?? [];
60480
61582
  const uniswapV4Calls = buildBalanceCalls(uniswapV4s);
60481
61583
  const decimalsByAsset = {
60482
- [zeroAddress]: NATIVE_DECIMALS
61584
+ [zeroAddress]: getNativeDecimals(chain)
60483
61585
  };
60484
61586
  for (const asset of unifiedAssets) {
60485
61587
  const fromList = list[asset]?.decimals;
@@ -73960,11 +75062,11 @@ var ConvertToAssetsAbi = [
73960
75062
  }
73961
75063
  ];
73962
75064
  var readVaultSharePrices = async (chainId, addresses, multicallRetry) => {
73963
- const lc = Array.from(new Set(addresses.map((a) => a.toLowerCase())));
73964
- if (lc.length === 0) return {};
75065
+ const lc2 = Array.from(new Set(addresses.map((a) => a.toLowerCase())));
75066
+ if (lc2.length === 0) return {};
73965
75067
  const results = await multicallRetry({
73966
75068
  chain: chainId,
73967
- calls: lc.map((address) => ({
75069
+ calls: lc2.map((address) => ({
73968
75070
  address,
73969
75071
  name: "convertToAssets",
73970
75072
  params: [VAULT_SHARE_PRICE_PROBE]
@@ -73974,9 +75076,9 @@ var readVaultSharePrices = async (chainId, addresses, multicallRetry) => {
73974
75076
  allowFailure: true
73975
75077
  });
73976
75078
  const out = {};
73977
- for (let i = 0; i < lc.length; i++) {
75079
+ for (let i = 0; i < lc2.length; i++) {
73978
75080
  const v = results[i];
73979
- if (typeof v === "bigint" && v > 0n) out[lc[i]] = v.toString();
75081
+ if (typeof v === "bigint" && v > 0n) out[lc2[i]] = v.toString();
73980
75082
  }
73981
75083
  return out;
73982
75084
  };
@@ -74154,6 +75256,15 @@ function counterpartyTags(c) {
74154
75256
  if (c.socializedLoss) push(out, "socialized-loss");
74155
75257
  return [...out];
74156
75258
  }
75259
+ function assetTags(sheet) {
75260
+ const out = /* @__PURE__ */ new Set();
75261
+ const inst = sheet.asset?.instrument;
75262
+ if (inst) {
75263
+ push(out, "asset-matures");
75264
+ if (!inst.redemption.local) push(out, "asset-bridged");
75265
+ }
75266
+ return [...out];
75267
+ }
74157
75268
  function deriveSupplyTags(supply, market = {}) {
74158
75269
  const out = /* @__PURE__ */ new Set();
74159
75270
  push(out, ...rateTags(supply.rate));
@@ -74161,6 +75272,7 @@ function deriveSupplyTags(supply, market = {}) {
74161
75272
  push(out, ...availabilityTags(supply.availability));
74162
75273
  push(out, ...counterpartyTags(supply.counterparty));
74163
75274
  push(out, ...marketTags(market));
75275
+ push(out, ...assetTags(market));
74164
75276
  switch (supply.exit.mode) {
74165
75277
  case "instant":
74166
75278
  push(out, "exit-instant");
@@ -74294,6 +75406,57 @@ function hasMatured(m, nowSecs) {
74294
75406
  if (m.kind !== "fixed-date" || !m.maturity) return false;
74295
75407
  return m.maturity <= (Math.floor(Date.now() / 1e3));
74296
75408
  }
75409
+ var CHAIN_LABEL = {
75410
+ "1": "Ethereum",
75411
+ "10": "Optimism",
75412
+ "56": "BNB Chain",
75413
+ "130": "Unichain",
75414
+ "143": "Monad",
75415
+ "146": "Sonic",
75416
+ "196": "X Layer",
75417
+ "999": "HyperEVM",
75418
+ "4663": "Robinhood Chain",
75419
+ "5000": "Mantle",
75420
+ "8453": "Base",
75421
+ "9745": "Plasma",
75422
+ "42161": "Arbitrum",
75423
+ "57073": "Ink",
75424
+ "80094": "Berachain",
75425
+ "747474": "Katana"
75426
+ };
75427
+ function chainLabel(chainId) {
75428
+ if (!chainId) return "its origin chain";
75429
+ return CHAIN_LABEL[chainId] ?? `chain ${chainId}`;
75430
+ }
75431
+ var VENUE_LABEL = {
75432
+ pendle: "Pendle",
75433
+ spectra: "Spectra"
75434
+ };
75435
+ function instrumentPhrase(inst) {
75436
+ const when = `${inst.matured ? "matured" : "matures"} ${shortDate(inst.maturity)}`;
75437
+ const where = inst.redemption.local ? "" : ` \xB7 redeem on ${chainLabel(inst.redemption.chainId)} only`;
75438
+ return `PT ${when}${where}`;
75439
+ }
75440
+ function instrumentSentences(inst) {
75441
+ const venue = VENUE_LABEL[String(inst.venue)] ?? String(inst.venue);
75442
+ const origin = chainLabel(inst.redemption.chainId);
75443
+ const out = [];
75444
+ if (inst.matured) {
75445
+ out.push(
75446
+ `This ${venue} principal token matured on ${shortDate(inst.maturity)} and earns nothing further; it is redeemable 1:1 for its underlying.`
75447
+ );
75448
+ } else {
75449
+ out.push(
75450
+ `The asset is a ${venue} principal token maturing ${shortDate(inst.maturity)} (in ${duration(inst.secondsToMaturity)}): it accrues to par and is redeemable 1:1 for its underlying from then on.`
75451
+ );
75452
+ }
75453
+ if (!inst.redemption.local) {
75454
+ out.push(
75455
+ `It is a bridged mirror and cannot be minted or redeemed on this chain \u2014 sell it here, or bridge it back to ${origin} to redeem at par.`
75456
+ );
75457
+ }
75458
+ return out;
75459
+ }
74297
75460
  function maturityPhrase(m) {
74298
75461
  if (m.kind === "fixed-date" && m.maturity)
74299
75462
  return `${hasMatured(m) ? "matured" : "until"} ${shortDate(m.maturity)}`;
@@ -74408,7 +75571,8 @@ function headlineExitFromRoutes(routes2, symbol) {
74408
75571
  }
74409
75572
  function supplyHeadline(s, sheet = {}) {
74410
75573
  if (s.role === "collateral") {
74411
- return `Collateral only \xB7 ${maturityPhrase(s.maturity)}`;
75574
+ const inst2 = sheet.asset?.instrument;
75575
+ return `Collateral only \xB7 ${inst2 ? instrumentPhrase(inst2) : maturityPhrase(s.maturity)}`;
74412
75576
  }
74413
75577
  const rate = `${rateLabel(s)} ${pct(s.rate.aprTotal)}${windowNote(s.rate)}${provenance(s.rate)}`;
74414
75578
  const exit = headlineExitFromRoutes(s.exit.routes, sheet.asset?.symbol) ?? exitPhrase[String(s.exit.mode)] ?? (s.exit.settlement === "sync" ? "withdraw any time" : "delayed withdrawal");
@@ -74418,7 +75582,9 @@ function supplyHeadline(s, sheet = {}) {
74418
75582
  }
74419
75583
  const mat = s.maturity.kind === "perpetual" ? "" : ` ${maturityPhrase(s.maturity)}`;
74420
75584
  const warmup = s.rate.warmupSecs ? ` \xB7 earns after ${duration(s.rate.warmupSecs)}` : "";
74421
- return `${rate}${mat}${warmup} \xB7 ${exit}${cooldown}`;
75585
+ const inst = sheet.asset?.instrument;
75586
+ const instrument = inst ? ` \xB7 ${instrumentPhrase(inst)}` : "";
75587
+ return `${rate}${mat}${warmup}${instrument} \xB7 ${exit}${cooldown}`;
74422
75588
  }
74423
75589
  function borrowHeadline(b) {
74424
75590
  const rate = b.rate.kind === "zero-interest" ? "No ongoing interest" : b.rate.kind === "user-set" ? (
@@ -74450,6 +75616,8 @@ function supplyDescription(s, sheet = {}) {
74450
75616
  `You earn ${pct(s.rate.aprTotal)} (${comp.join(" + ")}), ${rateBehaviour(s.rate)}.`
74451
75617
  );
74452
75618
  }
75619
+ if (sheet.asset?.instrument)
75620
+ parts.push(...instrumentSentences(sheet.asset.instrument));
74453
75621
  if (s.exit.routes && s.exit.routes.length > 1) {
74454
75622
  parts.push(routesSentence(s.exit.routes, sheet.asset?.symbol));
74455
75623
  } else if (s.exit.mode === "instant") {
@@ -75130,16 +76298,73 @@ var TERM_SHEET_SCHEMA_VERSION = 1;
75130
76298
  // src/terms/buildTermSheet.ts
75131
76299
  var isNum = (v) => typeof v === "number" && Number.isFinite(v);
75132
76300
  var clamp013 = (v) => Math.max(0, Math.min(1, v));
75133
- function assetRef(input) {
76301
+ function assetRef(input, now) {
75134
76302
  const a = input.asset ?? {};
76303
+ const chainId = String(a.chainId ?? input.chainId);
76304
+ const address = String(a.address ?? input.underlying ?? "").toLowerCase();
75135
76305
  return {
75136
- chainId: String(a.chainId ?? input.chainId),
75137
- address: String(a.address ?? input.underlying ?? "").toLowerCase(),
76306
+ chainId,
76307
+ address,
75138
76308
  symbol: a.symbol,
75139
76309
  name: a.name,
75140
76310
  decimals: a.decimals ?? input.decimals,
75141
76311
  assetGroup: a.assetGroup,
75142
- logoURI: a.logoURI
76312
+ logoURI: a.logoURI,
76313
+ instrument: instrumentOf(
76314
+ a.props,
76315
+ chainId,
76316
+ address,
76317
+ now ?? Math.floor(Date.now() / 1e3)
76318
+ )
76319
+ };
76320
+ }
76321
+ var PENDLE_ORIGIN_CHAIN_BY_CODE = {
76322
+ ETH: "1",
76323
+ ARB: "42161",
76324
+ PLASMA: "9745"
76325
+ };
76326
+ function instrumentOf(props, chainId, address, now) {
76327
+ if (!props) return void 0;
76328
+ const pendle = props.pendle;
76329
+ if (pendle?.tokenType === "PT" && isNum(pendle.expiry) && pendle.expiry > 0) {
76330
+ const bridged = typeof pendle.bridgedFrom === "string" && pendle.bridgedFrom;
76331
+ const origin = pendle.origin && typeof pendle.origin.chainId === "string" && typeof pendle.origin.address === "string" ? {
76332
+ chainId: String(pendle.origin.chainId),
76333
+ address: String(pendle.origin.address).toLowerCase()
76334
+ } : void 0;
76335
+ const originChain = origin?.chainId ?? (bridged ? PENDLE_ORIGIN_CHAIN_BY_CODE[bridged] : void 0);
76336
+ return {
76337
+ kind: "principal-token",
76338
+ venue: "pendle",
76339
+ ...maturityFields(pendle.expiry, now),
76340
+ redemption: bridged ? (
76341
+ // An unknown origin code is still a bridged token — say where it is
76342
+ // NOT redeemable rather than pretend it is here.
76343
+ {
76344
+ local: false,
76345
+ chainId: originChain ?? "unknown",
76346
+ address: origin?.address
76347
+ }
76348
+ ) : { local: true, chainId, address }
76349
+ };
76350
+ }
76351
+ const spectra = props.spectra;
76352
+ if (spectra?.tokenType === "PT" && isNum(spectra.maturity) && spectra.maturity > 0) {
76353
+ return {
76354
+ kind: "principal-token",
76355
+ venue: "spectra",
76356
+ ...maturityFields(spectra.maturity, now),
76357
+ redemption: { local: true, chainId, address }
76358
+ };
76359
+ }
76360
+ return void 0;
76361
+ }
76362
+ function maturityFields(maturity, now) {
76363
+ return {
76364
+ maturity,
76365
+ maturityIso: new Date(maturity * 1e3).toISOString(),
76366
+ secondsToMaturity: Math.max(0, maturity - now),
76367
+ matured: maturity <= now
75143
76368
  };
75144
76369
  }
75145
76370
  function defaultConfig(input) {
@@ -75600,7 +76825,11 @@ function mergeDeep(base, patch) {
75600
76825
  return out;
75601
76826
  }
75602
76827
  function finalizeInfo(sheet) {
75603
- const market = { governance: sheet.governance, oracle: sheet.oracle };
76828
+ const market = {
76829
+ governance: sheet.governance,
76830
+ oracle: sheet.oracle,
76831
+ asset: sheet.asset
76832
+ };
75604
76833
  if (sheet.supply && !sheet.supply.info)
75605
76834
  sheet.supply.info = { headline: "", description: "", tags: [] };
75606
76835
  if (sheet.borrow && !sheet.borrow.info)
@@ -75655,7 +76884,7 @@ function buildTermSheet(input, opts = {}) {
75655
76884
  marketUid: input.marketUid,
75656
76885
  lender: input.lender,
75657
76886
  chainId: input.chainId,
75658
- asset: assetRef(input),
76887
+ asset: assetRef(input, now),
75659
76888
  supply: buildSupply(input, now, siblings),
75660
76889
  borrow: buildBorrow(input, now, siblings),
75661
76890
  utilization: buildUtilization(input),
@@ -77844,8 +79073,8 @@ var SupportsInterfaceAbi = [
77844
79073
  var detectInterfaceKinds = async (addresses, chainId, multicallRetry) => {
77845
79074
  const out = {};
77846
79075
  if (addresses.length === 0) return out;
77847
- const lc = addresses.map((a) => a.toLowerCase());
77848
- const calls = lc.flatMap((address) => [
79076
+ const lc2 = addresses.map((a) => a.toLowerCase());
79077
+ const calls = lc2.flatMap((address) => [
77849
79078
  {
77850
79079
  address,
77851
79080
  name: "supportsInterface",
@@ -77863,13 +79092,13 @@ var detectInterfaceKinds = async (addresses, chainId, multicallRetry) => {
77863
79092
  allowFailure: true
77864
79093
  });
77865
79094
  } catch {
77866
- for (const a of lc) out[a] = "erc4626";
79095
+ for (const a of lc2) out[a] = "erc4626";
77867
79096
  return out;
77868
79097
  }
77869
- for (let i = 0; i < lc.length; i++) {
79098
+ for (let i = 0; i < lc2.length; i++) {
77870
79099
  const is7540 = results[i * 2] === true;
77871
79100
  const is7575 = results[i * 2 + 1] === true;
77872
- out[lc[i]] = is7540 ? "erc7540" : is7575 ? "erc7575" : "erc4626";
79101
+ out[lc2[i]] = is7540 ? "erc7540" : is7575 ? "erc7575" : "erc4626";
77873
79102
  }
77874
79103
  return out;
77875
79104
  };
@@ -78492,10 +79721,11 @@ function toTermSheetInput(row, ctx = {}) {
78492
79721
  marketUid,
78493
79722
  lender,
78494
79723
  chainId,
78495
- asset: pick2(
78496
- row,
78497
- "asset",
78498
- "underlyingInfo.asset"
79724
+ // In-package rows carry `asset` as a bare ADDRESS and the metadata under
79725
+ // `underlyingInfo.asset`; the origin's rows carry the object under both.
79726
+ // Take the first OBJECT, so a string never shadows the metadata beside it.
79727
+ asset: [pick2(row, "asset"), pick2(row, "underlyingInfo.asset")].find(
79728
+ (v) => !!v && typeof v === "object"
78499
79729
  ),
78500
79730
  underlying: pick2(row, "underlying"),
78501
79731
  decimals: num15(pick2(row, "decimals")),
@@ -78988,8 +80218,37 @@ function borrowFindings(borrow) {
78988
80218
  }
78989
80219
  return out;
78990
80220
  }
80221
+ function assetFindings(sheet) {
80222
+ const inst = sheet.asset?.instrument;
80223
+ if (!inst) return [];
80224
+ const out = [];
80225
+ const origin = chainLabel(inst.redemption.chainId);
80226
+ if (inst.matured) {
80227
+ out.push({
80228
+ severity: "warn",
80229
+ id: "asset-matured",
80230
+ side: "supply",
80231
+ message: inst.redemption.local ? `The asset is a principal token that matured on ${shortDate(inst.maturity)} \u2014 it earns nothing further and should be redeemed for its underlying.` : `The asset is a principal token that matured on ${shortDate(inst.maturity)} \u2014 it earns nothing further, and can only be redeemed by bridging it back to ${origin}.`
80232
+ });
80233
+ } else if (!inst.redemption.local) {
80234
+ out.push({
80235
+ severity: "warn",
80236
+ id: "asset-bridged-pt",
80237
+ side: "supply",
80238
+ message: `The asset is a principal token bridged from ${origin}: it cannot be minted or redeemed on this chain. At maturity (${shortDate(inst.maturity)}) it is only redeemable at par back on ${origin}; here it can be sold.`
80239
+ });
80240
+ } else {
80241
+ out.push({
80242
+ severity: "info",
80243
+ id: "asset-matures",
80244
+ side: "supply",
80245
+ message: `The asset is a principal token maturing ${shortDate(inst.maturity)}, redeemable 1:1 for its underlying from then on.`
80246
+ });
80247
+ }
80248
+ return out;
80249
+ }
78991
80250
  function findingsFor(sheet, side) {
78992
- const sideFindings = side === "supply" ? sheet.supply ? supplyFindings(sheet.supply) : [] : sheet.borrow ? borrowFindings(sheet.borrow) : [];
80251
+ const sideFindings = side === "supply" ? sheet.supply ? [...supplyFindings(sheet.supply), ...assetFindings(sheet)] : [] : sheet.borrow ? borrowFindings(sheet.borrow) : [];
78993
80252
  return rankFindings([...sideFindings, ...marketFindings(sheet)]);
78994
80253
  }
78995
80254
  function hasCritical(sheet, side) {
@@ -81500,6 +82759,6 @@ function earnPositionTotals(items) {
81500
82759
  };
81501
82760
  }
81502
82761
 
81503
- export { ApiBookSource, DEFAULT_MIDNIGHT_API, DEFAULT_OUTLIER_GUARD, DEFAULT_PROFILE_ID, DEFAULT_STALE_REJECT_SECONDS, DEFAULT_TERMMAX_API, DEFAULT_TERM_ORDER_STORE, DOLOMITE_ISO_ID_PREFIX, EARN_DESCRIPTIONS, EARN_LABELS, EARN_RATE_SOURCE_BY_PROVIDER, EMPTY_BALANCE, EXACTLY_LENDER_KEY, FLYING_TULIP_LENDER_KEY, FRACTION_RATE_PROVIDERS, GMX_API_HOSTS, GMX_READ_CONTRACTS, GMX_SUPPORTED_CHAINS, HYPERCORE_VAULT_REGISTRY, IDLE_MARKET_ID, INTERFACE_IDS, LAGOON_API_URL, LAGOON_CHAIN_IDS, MORPHO_LENS, MULTICALL_FAILURE, MaxParamThresholds, PASSTHROUGH_RATE_EPSILON, PENDLE_ASSETS_URL, PENDLE_CHAIN_IDS, PENDLE_MARKETS_URL, SDK_FRACTION_RATE_PROVIDERS, SPECTRA_NETWORKS, SPECTRA_RATE_MAX_PERCENT, SPECTRA_RATE_MIN_PERCENT, STABLECOIN_SYMBOLS, STCELO_MANAGER_ADDRESS, TELLER_CALLS_PER_BID, DECIMAL_BASE as TERMMAX_DECIMAL_BASE, TERMMAX_LIQUIDATION_PENALTY, TERMMAX_LIQUIDATION_WINDOW_SECS, TERMMAX_LIQUIDATOR_BONUS, TERMMAX_MARKETS_PER_CALL, TERMMAX_PARTIAL_CLOSE_FACTOR, TERMMAX_PARTIAL_LIQUIDATION_THRESHOLD_USD, TERM_ADAPTERS, TERM_PROFILES, TERM_SHEET_SCHEMA_VERSION, TermMaxApiSource, TermSubgraphSource, UPSHIFT_CHAIN_IDS, UPSHIFT_VAULTS_URL, VAULT_PROVIDERS, VAULT_PROVIDER_PROFILE, VAULT_PROVIDER_TRAITS, VAULT_SHARE_PRICE_PROBE, VAULT_VENUE_PREFIX, VOLATILE_VAULT_OVERRIDES, YEARN_CHAIN_IDS, YEARN_YDAEMON_BASE, __resetResupplyUserCaches, accountDepositListKey, accountWithdrawalListKey, appendSnapshot, applyEarnSanity, applyPositionDelta, attachImplications, attachPricesToFlashLiquidity, borrowDescription, borrowFindings, borrowHeadline, buildExposures2 as buildExposures, buildFluidFTokensCall, buildLendingPositionUid, buildLiquityUserCall, buildLoopResult, buildMorphoTypeCall, buildMorphoTypeUserCallWithLens, buildPortfolioTotals, buildSumerAccumulators, buildSummaries, buildTellerUserCall, buildTermMaxUserCall, buildTermSheet, buildTermSheetsForGroup, buildVaultEarnUid, buildVaultLookup, buildVaultTermSheet, calculateLeverage, calculateNetApr, calculateOverallNetApr, calculateWeightedAverage, classifyFreshness, classifyReliability, classifyVault, clearPendleMarketsCache, clearSpectraMarketsCache, collateralSymbolsByVenue, collectFeedObservations, computeBorrowDelta2 as computeBorrowDelta, computeCloseTradeDeltas, computeCollateralSwapDeltas, computeDebtSwapDeltas, computeDepositDelta2 as computeDepositDelta, computeEModeAnalysis, computeOpenTradeDeltas, computePostTradeMetrics, computeRepayDelta2 as computeRepayDelta, computeSumerBorrowDelta, computeSumerDepositDelta, computeSumerRepayDelta, computeSumerWaterfall, computeSumerWithdrawDelta, computeVaultApr, computeWithdrawDelta2 as computeWithdrawDelta, computeZapTradeDeltas, consensusReference, convertCoolerMarketsToResponse, convertDssMarketsToResponse, convertExactlyMarketsToResponse, convertFlyingTulipMarketsToResponse, convertFrankencoinMarketsToResponse, convertFraxlendPairsToResponse, convertInverseMarketsToResponse, convertLenderUserDataResult, convertLiquityMarketsToResponse, convertLlamaLendMarketsToResponse, convertResupplyMarketsToResponse, convertRiverMarketsToResponse, convertTellerMarketsToResponse, convertTermMarketsToResponse, convertTermMaxMarketsToResponse, convertUsddMarketsToResponse, createMarketUid, createMidnightBookSource, createMulticallRpcCall, createRawRpcCalls, createTermBookSource, createTermMaxDataSource, decodeListaMarkets, decodeMarkets, decodePackedListaUserDataset, decodePackedMorphoUserDataset, deriveBorrowTags, deriveSupplyTags, detectInterfaceKinds, dexResolverFor, disambiguateEarnNames, dolomiteVaultAddress, dssIlkBytes32, dssKeyParts, dssLenderKey, duration, earnDescription, earnLabel, earnMarketFromPool, earnMarketFromVault, earnMarketLabel, earnPositionFromLenderEntry, earnPositionFromVaultBalance, earnPositionTotals, earnRateAtMaturity, earnRowSubtitle, earnUidFromMarketUid, earnVaultTerms, earnVenueKind, encodeBalanceFetcherCalldata, enrichTermSheet, enrichmentIndexFromRows, exactlyPairLtv, exactlyPenaltyRateToAprPercent, exactlyWadRateToPercent, feePhrase, feedKeyOf, feedStatKey, fetchCoolerMarkets, fetchDolomiteAccountNumbers, fetchDolomiteSubAccounts, fetchDssMarkets, fetchEulerEarnVaults, fetchEulerEarnVaultsFromSubgraph, fetchEulerSubAccountIndexes, fetchExactlyMarkets, fetchFlashLiquidityForChain, fetchFluidDexState, fetchFluidFTokens, fetchFlyingTulipMarkets, fetchFrankencoinMarkets, fetchFraxlendPairs, fetchGeneralYields, fetchGeneralYieldsByMarketUid, fetchGmxExecutionFees, fetchGmxTickerPrices, fetchGmxVaults, fetchHypercoreVaults, fetchInverseMarkets, fetchLagoonApiVaults, fetchLagoonVaults, fetchLiquityMarkets, fetchListaVaultsFromChain, fetchLlamaLendMarkets, fetchMorphoUserBalances, fetchMorphoUserPositionMarkets, fetchMorphoVaults, fetchMorphoVaultsFromApi, fetchMorphoVaultsFromChain, fetchOraclePrices, fetchPendleApiAssets, fetchPendleApiMarkets, fetchPendlePrices, fetchPendlePtMarkets, fetchResupplyMarkets, fetchRiverMarkets, fetchSiloVaults, fetchSpectraApiMarkets, fetchSpectraPtMarkets, fetchTellerMarkets, fetchTermMarkets, fetchTermMaxMarkets, fetchTermStoreOrders, fetchTokenBalances, fetchTokenMetadata, fetchUpshiftApiVaults, fetchUpshiftVaults, fetchUsddMarkets, fetchYearnApiVaults, fetchYearnVaults, fillableRemaining, filterActiveLenders, filterLendersByProtocol, finalizeInfo, findingsFor, formatRaw, frankencoinKeyParts, frankencoinLenderKey, fraxlendAssetPerCollateral, fraxlendKeyParts, fraxlendLenderKey, fuseLenderData, generateLendingPools, getAavesForChain, getAssetConfig, getBalanceForMarketUid, getBorrowCapacity, getCachedFluidDexState, getCachedLiquityTroves, getCachedTellerBids, getCachedTermMaxDiscovery, getCachedTermMaxMarket, getCachedTermMaxMarkets, getCoreValidators, getFluidFTokensConverter, getGmxApiHost, getGmxReadContracts, getGmxUserPositions, getHealthFactor, getHypercoreUserPositions, getHypercoreVaultRegistry, getLenderAssets, getLenderPublicData, getLenderPublicDataAll, getLenderPublicDataViaApi, getLenderUserDataMulti, getLenderUserDataResult, getLendersForChain, getLstDelegation, getLstValidators, getLstWithdrawalRegistry, getLstWithdrawalRequests, getMaxAmountClose, getMaxAmountCollateralSwap, getMaxAmountDebtSwap, getMaxAmountOpen, getMergedUserData, getMorphoTypeMarketConverter, getReadFailurePolicy, getResolvedDolomiteAccountNumbers, getResolvedDolomiteSubAccounts, getStCeloValidatorGroups, getSubAccountAddress, getSubAccountIndex, getTermProfile, getVaultPublicDataAll, getVaultWithdrawalRequests, hasCritical, hasEulerEarnVaultSubgraph, hasLagoonVaults, hasMorphoPositionIndex, hasMorphoUserApi, hasMorphoUserSubgraph, hasPendleMarkets, hasSpectraMarkets, hasUpshiftVaults, hasYearnVaults, ilkToKeySegment, implausibleRatePercent, inverseKeyParts, inverseLenderKey, isBoundNeed, isFailedCall, isIlliquid, isLendingPosition, isLiveMarket as isLivePendleMarket, isLiveSpectraMarket, isMaturedTerm, isSecondaryMarketOnly, isStablecoinSymbol, isUnearnableEarnRate, isUnrealizableEarnRate, isVaultPosition, isVaultVenue, isYearnV3, keySegmentToIlk, keysFromMaps, lenderApiOnly, lenderFamily, liquityCandidateTroveIds, liquityKeyParts, liquityLenderKey, llamaLendKeyParts, llamaLendLenderKey, meetsLiquidityFloor, mergeDeep, multicall3Abi2 as multicall3Abi, nanTo, needsLenderApproval, needsTokenApproval, noOpResult, normalizeToBytes, organizeUserQueries, parseBalanceFetcherResult, parseDolomiteSubAccountId, parseEarnUid, parseMergedResult, parseMulticallRpcResponses, parseExpirySeconds as parsePendleExpirySeconds, parseRawRpcBatchResponses, parseRawRpcResponses, parseCurveFee as parseSpectraCurveFee, parsePtRate as parseSpectraPtRate, parseTermMaxLtv, parseTokenBalanceResult, pct, assetKey as pendleAssetKey, pickPool as pickSpectraPool, positivePart2 as positivePart, predictInverseEscrow, prepareLenderUserDataRpcCalls, prepareMergedMulticallParams, prepareMergedRpcCalls, prepareMulticallInputs, prepareTokenBalanceRpcCalls, priceGlvVaults, priceGmMarkets, probeAaveFeedTimestamps, pruneFeedStats, rankFindings, ratePercent, readVaultSharePrices, rejectOutliers as rejectPriceOutliers, repairImpossibleTvl, resolveAdapter, resolveDerivation, resolveDolomiteRowIdentity, resolveEarnIdentity, resolveModeConfig, resolveStCeloDepositGroup, resolveVaultProfileId, resupplyKeyParts, resupplyLenderKey, resupplyMarketLabel, riverKeyParts, riverLenderKey, sanePercent as saneSpectraPercent, savingsAddresses, savingsBalanceKind, secondaryMarketVault, selectAssetGroupPrices, setMysticApiKey, shortDate, spectraAddress, spectraNetwork, spectraPoolsUrl, splitChainScopedAddress as splitPendleChainScopedAddress, stampCapabilities, stampEarnSubtitles, stampVaultClassification, stampVaultTermSheets, stripLeadingBrand, supplyDescription, supplyFindings, supplyHeadline, swapRoutedProvidersArePriceConsistent, tellerBpsToPercent, tellerImpliedLtv, tellerLenderKey, tellerPoolFromLenderKey, termApiBaseUrl, termLenderKey, termMaxApiBase, borrowNif as termMaxBorrowNif, curveApr as termMaxCurveApr, curveAprNumber as termMaxCurveAprNumber, daysToMaturity as termMaxDaysToMaturity, lendNif as termMaxLendNif, mintGtFeeRatio as termMaxMintGtFeeRatio, ratioToNumber as termMaxRatioToNumber, ratioToPercent as termMaxRatioToPercent, termOfferRateToAprPct, termOrderStoreBaseUrl, tickToAprNumber, tickToPrice, toDigest, toDolomiteSubAccountId, toTermFillNow, toTermSheetInput, toVaultTermInput, trancheFromCounterparty, tryParseEarnUid, unflattenLenderData, updateFeedStats, usdValue, usddIlkBytes32, usddKeyParts, usddLenderKey, validateTermSheet, validateTermSheets, validateUserData, vaultSharesToAssets, vaultTermInputFromEarnMarket, vaultTermInputFromSourceRow, vaultTraits, vaultVenue, venueBrand, venueBrandKey, withMaturityLabel, withTrancheLabel };
82762
+ export { ApiBookSource, DEFAULT_MIDNIGHT_API, DEFAULT_OUTLIER_GUARD, DEFAULT_PROFILE_ID, DEFAULT_STALE_REJECT_SECONDS, DEFAULT_TERMMAX_API, DEFAULT_TERM_ORDER_STORE, DOLOMITE_ISO_ID_PREFIX, EARN_DESCRIPTIONS, EARN_LABELS, EARN_RATE_SOURCE_BY_PROVIDER, EMPTY_BALANCE, EXACTLY_LENDER_KEY, FLYING_TULIP_LENDER_KEY, FRACTION_RATE_PROVIDERS, GMX_API_HOSTS, GMX_READ_CONTRACTS, GMX_SUPPORTED_CHAINS, HYPERCORE_VAULT_REGISTRY, IDLE_MARKET_ID, INTERFACE_IDS, LAGOON_API_URL, LAGOON_CHAIN_IDS, MORPHO_LENS, MULTICALL_FAILURE, MaxParamThresholds, PASSTHROUGH_RATE_EPSILON, PENDLE_ASSETS_URL, PENDLE_CHAIN_IDS, PENDLE_MARKETS_URL, SDK_FRACTION_RATE_PROVIDERS, SPECTRA_NETWORKS, SPECTRA_RATE_MAX_PERCENT, SPECTRA_RATE_MIN_PERCENT, STABLECOIN_SYMBOLS, STCELO_MANAGER_ADDRESS, TELLER_CALLS_PER_BID, DECIMAL_BASE as TERMMAX_DECIMAL_BASE, TERMMAX_LIQUIDATION_PENALTY, TERMMAX_LIQUIDATION_WINDOW_SECS, TERMMAX_LIQUIDATOR_BONUS, TERMMAX_MARKETS_PER_CALL, TERMMAX_PARTIAL_CLOSE_FACTOR, TERMMAX_PARTIAL_LIQUIDATION_THRESHOLD_USD, TERM_ADAPTERS, TERM_PROFILES, TERM_SHEET_SCHEMA_VERSION, TermMaxApiSource, TermSubgraphSource, UPSHIFT_CHAIN_IDS, UPSHIFT_VAULTS_URL, VAULT_PROVIDERS, VAULT_PROVIDER_PROFILE, VAULT_PROVIDER_TRAITS, VAULT_SHARE_PRICE_PROBE, VAULT_VENUE_PREFIX, VOLATILE_VAULT_OVERRIDES, YEARN_CHAIN_IDS, YEARN_YDAEMON_BASE, __resetResupplyUserCaches, accountDepositListKey, accountWithdrawalListKey, appendSnapshot, applyEarnSanity, applyPositionDelta, attachImplications, attachPricesToFlashLiquidity, borrowDescription, borrowFindings, borrowHeadline, buildExposures2 as buildExposures, buildFluidFTokensCall, buildLendingPositionUid, buildLiquityUserCall, buildLoopResult, buildMorphoTypeCall, buildMorphoTypeUserCallWithLens, buildPortfolioTotals, buildSumerAccumulators, buildSummaries, buildTellerUserCall, buildTermMaxUserCall, buildTermSheet, buildTermSheetsForGroup, buildVaultEarnUid, buildVaultLookup, buildVaultTermSheet, calculateLeverage, calculateNetApr, calculateOverallNetApr, calculateWeightedAverage, classifyFreshness, classifyReliability, classifyVault, clearPendleMarketsCache, clearSpectraMarketsCache, collateralSymbolsByVenue, collectFeedObservations, computeBorrowDelta2 as computeBorrowDelta, computeCloseTradeDeltas, computeCollateralSwapDeltas, computeDebtSwapDeltas, computeDepositDelta2 as computeDepositDelta, computeEModeAnalysis, computeOpenTradeDeltas, computePostTradeMetrics, computeRepayDelta2 as computeRepayDelta, computeSumerBorrowDelta, computeSumerDepositDelta, computeSumerRepayDelta, computeSumerWaterfall, computeSumerWithdrawDelta, computeVaultApr, computeWithdrawDelta2 as computeWithdrawDelta, computeZapTradeDeltas, consensusReference, convertCoolerMarketsToResponse, convertDssMarketsToResponse, convertExactlyMarketsToResponse, convertFlyingTulipMarketsToResponse, convertFrankencoinMarketsToResponse, convertFraxlendPairsToResponse, convertInverseMarketsToResponse, convertLenderUserDataResult, convertLiquityMarketsToResponse, convertLlamaLendMarketsToResponse, convertResupplyMarketsToResponse, convertRiverMarketsToResponse, convertTellerMarketsToResponse, convertTermMarketsToResponse, convertTermMaxMarketsToResponse, convertUsddMarketsToResponse, createMarketUid, createMidnightBookSource, createMulticallRpcCall, createRawRpcCalls, createTermBookSource, createTermMaxDataSource, decodeListaMarkets, decodeMarkets, decodePackedListaUserDataset, decodePackedMorphoUserDataset, deriveBorrowTags, deriveSupplyTags, detectInterfaceKinds, dexResolverFor, disambiguateEarnNames, dolomiteVaultAddress, dssIlkBytes32, dssKeyParts, dssLenderKey, duration, earnDescription, earnLabel, earnMarketFromPool, earnMarketFromVault, earnMarketLabel, earnPositionFromLenderEntry, earnPositionFromVaultBalance, earnPositionTotals, earnRateAtMaturity, earnRowSubtitle, earnUidFromMarketUid, earnVaultTerms, earnVenueKind, emitterCoverage, encodeBalanceFetcherCalldata, enrichTermSheet, enrichmentIndexFromRows, enumerateEmitters, exactlyPairLtv, exactlyPenaltyRateToAprPercent, exactlyWadRateToPercent, feePhrase, feedKeyOf, feedStatKey, fetchCoolerMarkets, fetchDolomiteAccountNumbers, fetchDolomiteSubAccounts, fetchDssMarkets, fetchEulerEarnVaults, fetchEulerEarnVaultsFromSubgraph, fetchEulerSubAccountIndexes, fetchExactlyMarkets, fetchFlashLiquidityForChain, fetchFluidDexState, fetchFluidFTokens, fetchFlyingTulipMarkets, fetchFrankencoinMarkets, fetchFraxlendPairs, fetchGeneralYields, fetchGeneralYieldsByMarketUid, fetchGmxExecutionFees, fetchGmxTickerPrices, fetchGmxVaults, fetchHypercoreVaults, fetchInverseMarkets, fetchLagoonApiVaults, fetchLagoonVaults, fetchLiquityMarkets, fetchListaVaultsFromChain, fetchLlamaLendMarkets, fetchMorphoUserBalances, fetchMorphoUserPositionMarkets, fetchMorphoVaults, fetchMorphoVaultsFromApi, fetchMorphoVaultsFromChain, fetchOraclePrices, fetchPendleApiAssets, fetchPendleApiMarkets, fetchPendlePrices, fetchPendlePtMarkets, fetchResupplyMarkets, fetchRiverMarkets, fetchSiloVaults, fetchSpectraApiMarkets, fetchSpectraPtMarkets, fetchTellerMarkets, fetchTermMarkets, fetchTermMaxMarkets, fetchTermStoreOrders, fetchTokenBalances, fetchTokenMetadata, fetchUpshiftApiVaults, fetchUpshiftVaults, fetchUsddMarkets, fetchYearnApiVaults, fetchYearnVaults, fillableRemaining, filterActiveLenders, filterLendersByProtocol, finalizeInfo, findingsFor, formatRaw, frankencoinKeyParts, frankencoinLenderKey, fraxlendAssetPerCollateral, fraxlendKeyParts, fraxlendLenderKey, fuseLenderData, generateLendingPools, getAavesForChain, getAssetConfig, getBalanceForMarketUid, getBorrowCapacity, getCachedFluidDexState, getCachedLiquityTroves, getCachedTellerBids, getCachedTermMaxDiscovery, getCachedTermMaxMarket, getCachedTermMaxMarkets, getCoreValidators, getFluidFTokensConverter, getGmxApiHost, getGmxReadContracts, getGmxUserPositions, getHealthFactor, getHypercoreUserPositions, getHypercoreVaultRegistry, getLenderAssets, getLenderPublicData, getLenderPublicDataAll, getLenderPublicDataViaApi, getLenderUserDataMulti, getLenderUserDataResult, getLendersForChain, getLstDelegation, getLstValidators, getLstWithdrawalRegistry, getLstWithdrawalRequests, getMaxAmountClose, getMaxAmountCollateralSwap, getMaxAmountDebtSwap, getMaxAmountOpen, getMergedUserData, getMorphoTypeMarketConverter, getReadFailurePolicy, getResolvedDolomiteAccountNumbers, getResolvedDolomiteSubAccounts, getStCeloValidatorGroups, getSubAccountAddress, getSubAccountIndex, getTermProfile, getVaultPublicDataAll, getVaultWithdrawalRequests, hasCritical, hasEulerEarnVaultSubgraph, hasLagoonVaults, hasMorphoPositionIndex, hasMorphoUserApi, hasMorphoUserSubgraph, hasPendleMarkets, hasSpectraMarkets, hasUpshiftVaults, hasYearnVaults, ilkToKeySegment, implausibleRatePercent, inverseKeyParts, inverseLenderKey, isBoundNeed, isFailedCall, isIlliquid, isLendingPosition, isLiveMarket as isLivePendleMarket, isLiveSpectraMarket, isMaturedTerm, isSecondaryMarketOnly, isStablecoinSymbol, isUnearnableEarnRate, isUnrealizableEarnRate, isVaultPosition, isVaultVenue, isYearnV3, keySegmentToIlk, keysFromMaps, lenderApiOnly, lenderFamily, liquityCandidateTroveIds, liquityKeyParts, liquityLenderKey, llamaLendKeyParts, llamaLendLenderKey, meetsLiquidityFloor, mergeDeep, multicall3Abi2 as multicall3Abi, nanTo, needsLenderApproval, needsTokenApproval, noOpResult, normalizeToBytes, organizeUserQueries, parseBalanceFetcherResult, parseDolomiteSubAccountId, parseEarnUid, parseMergedResult, parseMulticallRpcResponses, parseExpirySeconds as parsePendleExpirySeconds, parseRawRpcBatchResponses, parseRawRpcResponses, parseCurveFee as parseSpectraCurveFee, parsePtRate as parseSpectraPtRate, parseTermMaxLtv, parseTokenBalanceResult, pct, assetKey as pendleAssetKey, pickPool as pickSpectraPool, positivePart2 as positivePart, predictInverseEscrow, prepareLenderUserDataRpcCalls, prepareMergedMulticallParams, prepareMergedRpcCalls, prepareMulticallInputs, prepareTokenBalanceRpcCalls, priceGlvVaults, priceGmMarkets, probeAaveFeedTimestamps, pruneFeedStats, rankFindings, ratePercent, readVaultSharePrices, rejectOutliers as rejectPriceOutliers, repairImpossibleTvl, resolveAdapter, resolveDerivation, resolveDolomiteRowIdentity, resolveEarnIdentity, resolveModeConfig, resolveStCeloDepositGroup, resolveVaultProfileId, resupplyKeyParts, resupplyLenderKey, resupplyMarketLabel, riverKeyParts, riverLenderKey, sanePercent as saneSpectraPercent, savingsAddresses, savingsBalanceKind, secondaryMarketVault, selectAssetGroupPrices, setMysticApiKey, shortDate, spectraAddress, spectraNetwork, spectraPoolsUrl, splitChainScopedAddress as splitPendleChainScopedAddress, stampCapabilities, stampEarnSubtitles, stampVaultClassification, stampVaultTermSheets, stripLeadingBrand, supplyDescription, supplyFindings, supplyHeadline, swapRoutedProvidersArePriceConsistent, tellerBpsToPercent, tellerImpliedLtv, tellerLenderKey, tellerPoolFromLenderKey, termApiBaseUrl, termLenderKey, termMaxApiBase, borrowNif as termMaxBorrowNif, curveApr as termMaxCurveApr, curveAprNumber as termMaxCurveAprNumber, daysToMaturity as termMaxDaysToMaturity, lendNif as termMaxLendNif, mintGtFeeRatio as termMaxMintGtFeeRatio, ratioToNumber as termMaxRatioToNumber, ratioToPercent as termMaxRatioToPercent, termOfferRateToAprPct, termOrderStoreBaseUrl, tickToAprNumber, tickToPrice, toDigest, toDolomiteSubAccountId, toTermFillNow, toTermSheetInput, toVaultTermInput, trancheFromCounterparty, tryParseEarnUid, unflattenLenderData, updateFeedStats, usdValue, usddIlkBytes32, usddKeyParts, usddLenderKey, validateTermSheet, validateTermSheets, validateUserData, vaultSharesToAssets, vaultTermInputFromEarnMarket, vaultTermInputFromSourceRow, vaultTraits, vaultVenue, venueBrand, venueBrandKey, withMaturityLabel, withTrancheLabel };
81504
82763
  //# sourceMappingURL=index.js.map
81505
82764
  //# sourceMappingURL=index.js.map