@1delta/margin-fetcher 5.0.29 → 5.0.31

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
1
  import { parseAbi, keccak256, encodeAbiParameters, formatEther, BaseError, erc20Abi, stringToHex, isAddress, pad, encodeFunctionData, formatUnits, getAddress, decodeFunctionResult, decodeAbiParameters, concat, AbiEncodingLengthMismatchError, concatHex, toBytes, slice, hexToString, InvalidAddressError, boolToHex, integerRegex, numberToHex, bytesRegex, BytesSizeMismatchError, arrayRegex, UnsupportedPackedAbiType } from './chunk-YILYOOYB.js';
2
2
  import './chunk-BYTNVMX7.js';
3
3
  import './chunk-PR4QN5HX.js';
4
- import { Lender, isExactly, isMidnight, isTerm, isTermMax, isTeller, isListaDao, isLiquityFamily, isRiver, isInverse, isDssType, isCompoundV3Type, isFluid, isGearboxV3, isLlamaLend, isFrankencoin, isResupply, isCurvance, isFraxlend, LIQUITY_FAMILY_LENDERS, isAaveType, isCompoundV3, isMultiMarket, isSiloV2Type, isSiloV3Type, isDolomite, hasCrossMarginRisk, isEulerType, isAaveV4Type, isInit, isMorphoType, isCompoundV2Type, isVenusType, isSumerType, AAVE_V3_LENDERS, AAVE_V2_LENDERS, isAaveV2Type, isAaveV32Type, isAaveV3Type, isUsdd, isSky, isYLDR, isLista, hasSubAccounts, isTectonicType, isKineticType, isBenqiType } from '@1delta/lender-registry';
4
+ import { Lender, isExactly, isMidnight, isTerm, isTermMax, isTeller, isListaDao, isLiquityFamily, isRiver, isInverse, isDssType, isCompoundV3Type, isFluid, isGearboxV3, isLlamaLend, isFrankencoin, isResupply, isCurvance, isFraxlend, LIQUITY_FAMILY_LENDERS, isAaveType, isCompoundV3, isMultiMarket, isSiloV2Type, isSiloV3Type, isDolomite, hasCrossMarginRisk, isEulerType, isAaveV4Type, isInit, isMorphoType, isCompoundV2Type, isVenusType, isSumerType, AAVE_V3_LENDERS, AAVE_V2_LENDERS, isMorphoBlue, isAaveV2Type, isAaveV32Type, isAaveV3Type, isUsdd, isSky, 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, liquityLendersByChain, riverLendersByChain, inverseLendersByChain, llamaLendLendersByChain, usddLendersByChain, skyLendersByChain, frankencoinLendersByChain, resupplyLendersByChain, curvanceLendersByChain, tellerConfigByChain, tellerPoolsByChain, termMaxConfigByChain, aaveReserves, compoundV3Reserves, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, termMaxApiBaseUrl, termMaxLenderKey, inverseConfigFor, inverseChainData, llamaLendConfigFor, llamaLendChainData, llamaLendApiBaseUrl, resupplyConfigFor, fraxlendConfigFor, dssConfigFor, dssChainData, dssDebtToken, dssDebtJoin, frankencoinConfigFor, frankencoinChainData, aaveOracles, morphoTypeMarkets, resolveMidnightApiBase, resolveTermApiBase, llamaLendMarketByVault, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, curvanceConfigFor, aaveTokens, morphoTypeVaults, eulerConfigs, gearboxMarketCompressor, gearboxMarketConfigurators, gearboxV3LenderKey, midnightMarketsByChain, parseAaveV4SpokeLenderKey, fraxlendPairsFor, gearboxAccountCompressor, compoundV2Tokens, exactlyMarketsByChain, aaveOraclesConfig, compoundV2Oracles, compoundV2TokenArray, compoundV2OraclesConfig, compoundV3OraclesData, compoundV3BaseData, compoundV2Reserves, aaveV4Oracles } 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, liquityLendersByChain, riverLendersByChain, inverseLendersByChain, llamaLendLendersByChain, usddLendersByChain, skyLendersByChain, frankencoinLendersByChain, resupplyLendersByChain, curvanceLendersByChain, fraxlendLendersByChain, tellerConfigByChain, tellerPoolsByChain, termMaxConfigByChain, aaveReserves, compoundV3Reserves, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, termMaxApiBaseUrl, termMaxLenderKey, inverseConfigFor, inverseChainData, llamaLendConfigFor, llamaLendChainData, llamaLendApiBaseUrl, resupplyConfigFor, fraxlendConfigFor, dssConfigFor, dssChainData, dssDebtToken, dssDebtJoin, frankencoinConfigFor, frankencoinChainData, aaveOracles, morphoTypeMarkets, resolveMidnightApiBase, resolveTermApiBase, llamaLendMarketByVault, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, curvanceConfigFor, aaveTokens, morphoTypeVaults, eulerConfigs, gearboxMarketCompressor, gearboxMarketConfigurators, gearboxV3LenderKey, midnightMarketsByChain, parseAaveV4SpokeLenderKey, fraxlendPairsFor, gearboxAccountCompressor, compoundV2Tokens, exactlyMarketsByChain, aaveOraclesConfig, compoundV2Oracles, compoundV2TokenArray, compoundV2OraclesConfig, compoundV3OraclesData, compoundV3BaseData, compoundV2Reserves, aaveV4Oracles } from '@1delta/data-sdk';
7
7
  import lodash from 'lodash';
8
8
  import { Chain } from '@1delta/chain-registry';
9
9
  import { multicallRetryUniversal, getEvmClient, getEvmChain, getEvmClientUniversal } from '@1delta/providers';
@@ -6436,6 +6436,9 @@ var getLendersForChain = (c) => {
6436
6436
  for (const l of curvanceLendersByChain(c)) {
6437
6437
  lenders.push(l);
6438
6438
  }
6439
+ for (const l of fraxlendLendersByChain(c)) {
6440
+ lenders.push(l);
6441
+ }
6439
6442
  if (tellerConfigByChain(c)?.tellerV2 && tellerPoolsByChain(c).length > 0) {
6440
6443
  lenders.push(Lender.TELLER);
6441
6444
  }
@@ -25434,6 +25437,25 @@ function convertFraxlendPairsToResponse(raw, chainId, prices = {}, _additionalYi
25434
25437
  isActive: true,
25435
25438
  isFrozen: depositsHalted && borrowHalted
25436
25439
  };
25440
+ entry.params = {
25441
+ market: {
25442
+ lender: lenderKey,
25443
+ name: `${p.assetSymbol} / ${p.collateralSymbol}`,
25444
+ id: p.pair.toLowerCase(),
25445
+ loanAddress: p.asset,
25446
+ collateralAddress: p.collateral,
25447
+ loanDecimals: p.assetDecimals,
25448
+ collateralDecimals: p.collateralDecimals,
25449
+ /** RAW, on the pair's own 1e5 scale — and it is ALSO the liquidation
25450
+ * threshold, so there is no separate LT to publish. */
25451
+ lltv: p.maxLtv.toString(),
25452
+ oracle: p.oracle,
25453
+ irm: p.rateContract,
25454
+ /** Whether the NATIVE loop is available on this pair right now,
25455
+ * probed live. Gate any leverage UI on this. */
25456
+ leverageEnabled: p.leverageSwapperApproved
25457
+ }
25458
+ };
25437
25459
  entry.descriptor = {
25438
25460
  pair: p.pair.toLowerCase(),
25439
25461
  symbol: p.symbol,
@@ -43887,7 +43909,27 @@ var usddFetcher = {
43887
43909
  return out;
43888
43910
  }
43889
43911
  };
43890
- var FRANKENCOIN_SAVINGS_MODULE = "0x27d9ad987bde08a0d083ef7e0e4043c857a17b38";
43912
+ var ZCHF_ETHEREUM = "0xb58e61c3098d85632df34eecfb899a1ed80921cb";
43913
+ var ZCHF_BRIDGED = "0xd4dd9e2f021bb459d5a5f6c24c12fe09c5d45553";
43914
+ var FRANKENCOIN_SAVINGS_MODULES = [
43915
+ {
43916
+ chainId: Chain.ETHEREUM_MAINNET,
43917
+ // `savingsReferral`, NOT the config's `savingsV2` — see the header.
43918
+ module: "0x27d9ad987bde08a0d083ef7e0e4043c857a17b38",
43919
+ zchf: ZCHF_ETHEREUM
43920
+ },
43921
+ {
43922
+ chainId: Chain.GNOSIS,
43923
+ module: "0xbf594d0fed79ae56d910cb01b5dd4f4c57b04402",
43924
+ zchf: ZCHF_BRIDGED
43925
+ },
43926
+ {
43927
+ chainId: Chain.BASE,
43928
+ module: "0x6426324af1b14df3cd03b2d500529083c5ea61bc",
43929
+ zchf: ZCHF_BRIDGED
43930
+ }
43931
+ ];
43932
+ FRANKENCOIN_SAVINGS_MODULES[0].module;
43891
43933
  var SAVINGS_INFO_URL = "https://api.frankencoin.com/savings/core/info";
43892
43934
  var RATE_ABI2 = [
43893
43935
  {
@@ -43899,58 +43941,70 @@ var RATE_ABI2 = [
43899
43941
  }
43900
43942
  ];
43901
43943
  var ZCHF_SAVINGS_KEY = "ZCHF_SAVINGS";
43944
+ var zchfSavingsKey = (chainId) => chainId === Chain.ETHEREUM_MAINNET ? ZCHF_SAVINGS_KEY : `${ZCHF_SAVINGS_KEY}::${chainId}`;
43902
43945
  var aprFromRatePPM = (ppm) => Number(ppm) / 1e4;
43903
- var fetchRateOnChain = async () => {
43946
+ var fetchRateOnChain = async (d) => {
43904
43947
  const [ppm] = await multicallRetryUniversal({
43905
- chain: Chain.ETHEREUM_MAINNET,
43948
+ chain: d.chainId,
43906
43949
  abi: RATE_ABI2,
43907
- calls: [
43908
- {
43909
- address: FRANKENCOIN_SAVINGS_MODULE,
43910
- name: "currentRatePPM",
43911
- params: []
43912
- }
43913
- ],
43950
+ calls: [{ address: d.module, name: "currentRatePPM", params: [] }],
43914
43951
  allowFailure: false
43915
43952
  });
43916
43953
  if (ppm === void 0 || ppm === null) {
43917
- throw new Error("Frankencoin: unreadable currentRatePPM()");
43954
+ throw new Error(`Frankencoin: unreadable currentRatePPM() on ${d.chainId}`);
43918
43955
  }
43919
43956
  return aprFromRatePPM(ppm);
43920
43957
  };
43921
- var fetchRateFromApi = async () => {
43958
+ var fetchRatesFromApi = async () => {
43922
43959
  const res = await fetch(SAVINGS_INFO_URL, {
43923
43960
  headers: { accept: "application/json" },
43924
43961
  signal: AbortSignal.timeout(8e3)
43925
43962
  });
43926
43963
  if (!res.ok) throw new Error(`Frankencoin: savings info HTTP ${res.status}`);
43927
43964
  const body = await res.json();
43928
- const rate = body?.status?.[String(Chain.ETHEREUM_MAINNET)]?.[FRANKENCOIN_SAVINGS_MODULE]?.rate;
43929
- if (typeof rate !== "number" || !Number.isFinite(rate)) {
43930
- throw new Error("Frankencoin: savings info carried no rate for the module");
43965
+ const out = {};
43966
+ for (const d of FRANKENCOIN_SAVINGS_MODULES) {
43967
+ const perChain = body?.status?.[d.chainId];
43968
+ if (!perChain) continue;
43969
+ const entry = Object.entries(perChain).find(
43970
+ ([addr3]) => addr3.toLowerCase() === d.module.toLowerCase()
43971
+ )?.[1];
43972
+ const rate = entry?.rate;
43973
+ if (typeof rate === "number" && Number.isFinite(rate)) {
43974
+ out[d.chainId] = aprFromRatePPM(rate);
43975
+ }
43931
43976
  }
43932
- return aprFromRatePPM(rate);
43977
+ return out;
43933
43978
  };
43934
43979
  var frankencoinSavingsFetcher = {
43935
43980
  label: "FRANKENCOIN_SAVINGS",
43936
43981
  fetch: async () => {
43937
- const legs = await Promise.allSettled([
43938
- fetchRateOnChain(),
43939
- fetchRateFromApi()
43982
+ const [chainLegs, apiLeg] = await Promise.all([
43983
+ Promise.allSettled(FRANKENCOIN_SAVINGS_MODULES.map(fetchRateOnChain)),
43984
+ fetchRatesFromApi().catch((e) => e)
43940
43985
  ]);
43941
- const onChain = legs[0];
43942
- if (onChain.status === "fulfilled") {
43943
- return { [ZCHF_SAVINGS_KEY]: onChain.value };
43944
- }
43945
- const api = legs[1];
43946
- if (api.status === "fulfilled") {
43947
- return { [ZCHF_SAVINGS_KEY]: api.value };
43986
+ const apiRates = apiLeg instanceof Error ? {} : apiLeg;
43987
+ const out = {};
43988
+ const failures = [];
43989
+ FRANKENCOIN_SAVINGS_MODULES.forEach((d, i) => {
43990
+ const leg = chainLegs[i];
43991
+ if (leg.status === "fulfilled") {
43992
+ out[zchfSavingsKey(d.chainId)] = leg.value;
43993
+ return;
43994
+ }
43995
+ const fromApi = apiRates[d.chainId];
43996
+ if (fromApi !== void 0) {
43997
+ out[zchfSavingsKey(d.chainId)] = fromApi;
43998
+ return;
43999
+ }
44000
+ failures.push(`${d.chainId}: ${String(leg.reason)}`);
44001
+ });
44002
+ if (Object.keys(out).length === 0) {
44003
+ throw new Error(
44004
+ `Frankencoin: every savings module failed (${failures.join("; ")}${apiLeg instanceof Error ? `; api: ${apiLeg.message}` : ""})`
44005
+ );
43948
44006
  }
43949
- throw new Error(
43950
- `Frankencoin: both rate legs failed (chain: ${String(
43951
- onChain.reason
43952
- )}; api: ${String(api.reason)})`
43953
- );
44007
+ return out;
43954
44008
  }
43955
44009
  };
43956
44010
 
@@ -45473,6 +45527,32 @@ var sparkV2Base = (symbol, decimals) => ({
45473
45527
  yieldFetcher: sparkSavingsFetcher
45474
45528
  });
45475
45529
  var SPARK_V2_WITHDRAW_INTENTS = "0x592b7db9906e6f8924c4d74c2a0ab86ce44fdddf";
45530
+ var frankencoinSavingsBase = {
45531
+ reader: "frankencoin-savings",
45532
+ symbol: "ZCHF",
45533
+ brand: "Frankencoin",
45534
+ description: "ZCHF is Frankencoin's decentralised Swiss-franc stablecoin, minted against collateral in permissionless, auction-policed positions. The savings module pays a governance-set rate funded by borrower interest: deposits are never lent on (they sit segregated inside the module) and interest is minted by the protocol into your balance, so there are no shares and no share price. Withdrawals are instant and uncapped, but interest only starts accruing after 3 days and a top-up restarts that clock pro-rata, so a short stay can earn nothing.",
45535
+ decimals: 18,
45536
+ isRebasing: true,
45537
+ isMintable: true,
45538
+ withdrawalMode: "instant",
45539
+ // The exit is instant; the YIELD is not. `INTEREST_DELAY` is 3 days and a
45540
+ // top-up re-weights the whole position's clock, so a short stay earns zero.
45541
+ yieldWarmupSeconds: 3 * 86400,
45542
+ // `Δticks × saved / 1e6 / 365 days` — linear, compounding only when someone
45543
+ // calls `refresh`.
45544
+ accrual: "linear",
45545
+ // The module is a registered ZCHF minter, so the token already grants it an
45546
+ // implicit infinite allowance — verified on all three chains.
45547
+ needsDepositApproval: false,
45548
+ // Not an assumption: deposits are never lent on. They sit segregated inside
45549
+ // the module (`totalAssets` IS the module's own ZCHF balance) and the exit
45550
+ // is paid from it, so the PRINCIPAL is fully reserved rather than merely
45551
+ // over-collateralised. What is a claim on the protocol is the INTEREST,
45552
+ // which is minted on refresh — stated in the description.
45553
+ solvency: "overcollateralized",
45554
+ yieldFetcher: frankencoinSavingsFetcher
45555
+ };
45476
45556
  var ybMarket = (symbol, underlying, underlyingDecimals, address, capacityContract, yieldKey) => ({
45477
45557
  reader: "yieldbasis-lt",
45478
45558
  address,
@@ -46286,48 +46366,37 @@ var SINGLE_CHAIN_ENTRIES = {
46286
46366
  yieldKey: REUSDE_KEY
46287
46367
  },
46288
46368
  {
46289
- // Frankencoin savings module — a Swiss-franc savings account, not
46290
- // a vault. There is NO share token: `save(amount)` books ZCHF into
46291
- // an internal `savings(address)` account and `withdraw(target,
46292
- // amount)` pays it back out, so the position is a balance that
46293
- // grows in place (`isRebasing: true`, `exchangeRate` pinned at
46294
- // par) and the module's own ZCHF balance is the whole book. Hence
46295
- // the bespoke `frankencoin-savings` reader.
46296
- //
46297
- // TRAP — the published address config is stale. `@frankencoin/zchf`
46298
- // exports `savingsV2 = 0x3BF301B0…`, which now runs at 1 % and
46299
- // holds 17k ZCHF; the live module is the `savingsReferral`
46300
- // deployment below, at 3.5 % holding 12.17M (verified on-chain
46301
- // 2026-08-04, `currentRatePPM() = 35000`). Both answer
46302
- // `currentRatePPM()`, so only the balance distinguishes them.
46369
+ // Frankencoin savings module, Ethereum the reference deployment
46370
+ // and 89 % of the 13.66M ZCHF book. See `frankencoinSavingsBase`.
46303
46371
  //
46304
- // `symbol: 'ZCHF'` is deliberate. `fetchPublic` composes
46305
- // `displayName` from the *underlying's* token-list symbol
46306
- // (→ "Frankencoin ZCHF"), so `symbol` only drives `name` and the
46307
- // ticker a vault list renders and the honest ticker for a
46308
- // position denominated 1:1 in ZCHF is ZCHF. Inventing `sZCHF`
46309
- // would name a token that does not exist, and `svZCHF` is already
46310
- // taken by an unrelated third-party ERC-4626 wrapper
46311
- // (0x637f00cA…, ~1 ZCHF of TVL) that would then be conflated with
46312
- // this row.
46372
+ // TRAP the published address config is stale HERE and only here.
46373
+ // `@frankencoin/zchf` exports `savingsV2 = 0x3BF301B0…`, which now
46374
+ // runs at 1 % and holds 17k ZCHF; the live module is the
46375
+ // `savingsReferral` deployment below, at 3.5 % holding 12.13M
46376
+ // (re-verified 2026-08-12, `currentRatePPM() = 35000`). Both
46377
+ // answer `currentRatePPM()`, so only the balance distinguishes
46378
+ // them. The bridged chains have no such split.
46379
+ ...frankencoinSavingsBase,
46380
+ address: FRANKENCOIN_SAVINGS_MODULES[0].module,
46381
+ underlying: ZCHF_ETHEREUM,
46382
+ yieldKey: zchfSavingsKey(Chain.ETHEREUM_MAINNET)
46383
+ }
46384
+ ],
46385
+ "100": [
46386
+ {
46387
+ // Frankencoin savings module, Gnosis — 1,257,396 ZCHF at
46388
+ // 2026-08-12, the second-largest after Ethereum and by far the
46389
+ // most active bridged chain (4,853 saves / 13,249 withdrawals).
46390
+ // Its own module contract with its own stored rate, kept at the
46391
+ // Ethereum 35 000 ppm by a CCIP leadrate push.
46313
46392
  //
46314
- // Exit is instant and never short (withdrawals are paid from the
46315
- // module's own balance), but the YIELD is not instant:
46316
- // `INTEREST_DELAY` is 3 days and a top-up re-weights the account's
46317
- // tick counter, so exiting early can realise ~0 %.
46318
- reader: "frankencoin-savings",
46319
- address: "0x27d9ad987bde08a0d083ef7e0e4043c857a17b38",
46320
- underlying: "0xb58e61c3098d85632df34eecfb899a1ed80921cb",
46321
- // ZCHF
46322
- symbol: "ZCHF",
46323
- brand: "Frankencoin",
46324
- description: "ZCHF is Frankencoin's decentralised Swiss-franc stablecoin, minted against collateral in permissionless, auction-policed positions. The savings module pays a governance-set rate funded by borrower interest: deposits are never lent on (they sit segregated inside the module) and interest is minted by the protocol into your balance, so there are no shares and no share price. Withdrawals are instant and uncapped, but interest only starts accruing after 3 days and a top-up restarts that clock pro-rata, so a short stay can earn nothing.",
46325
- decimals: 18,
46326
- isRebasing: true,
46327
- isMintable: true,
46328
- withdrawalMode: "instant",
46329
- yieldFetcher: frankencoinSavingsFetcher,
46330
- yieldKey: ZCHF_SAVINGS_KEY
46393
+ // 62.8 % of this book belongs to the `svZCHF` ERC-4626 wrapper —
46394
+ // see the warning on `frankencoinSavingsBase` before adding a row
46395
+ // for it.
46396
+ ...frankencoinSavingsBase,
46397
+ address: FRANKENCOIN_SAVINGS_MODULES[1].module,
46398
+ underlying: ZCHF_BRIDGED,
46399
+ yieldKey: zchfSavingsKey(Chain.GNOSIS)
46331
46400
  }
46332
46401
  ],
46333
46402
  "42161": [
@@ -46364,6 +46433,17 @@ var SINGLE_CHAIN_ENTRIES = {
46364
46433
  withdrawalMode: "request-based",
46365
46434
  yieldFetcher: yoFetcher,
46366
46435
  yieldKey: "Yield Optimizer ETH::YOETH"
46436
+ },
46437
+ {
46438
+ // Frankencoin savings module, Base — 255,196 ZCHF at 2026-08-12.
46439
+ // Note the module address is the SAME on Base and Optimism
46440
+ // (`0x6426324a…`, one CREATE2 family); the Optimism twin holds
46441
+ // 1 ZCHF and is deliberately unregistered — see
46442
+ // `FRANKENCOIN_SAVINGS_MODULES`.
46443
+ ...frankencoinSavingsBase,
46444
+ address: FRANKENCOIN_SAVINGS_MODULES[2].module,
46445
+ underlying: ZCHF_BRIDGED,
46446
+ yieldKey: zchfSavingsKey(Chain.BASE)
46367
46447
  }
46368
46448
  ],
46369
46449
  "43114": [
@@ -53716,7 +53796,7 @@ async function fetchVaultSupplyShares(chainId, core, entries, marketIdsByVault,
53716
53796
  });
53717
53797
  return map;
53718
53798
  }
53719
- function computeVaultAllocation(vaultAddress, decimals, totalAssetsFormatted, feePercent, priceUsd, marketIds, rateMap, positionMap, tokenList, uidCtx) {
53799
+ function computeVaultAllocation(vaultAddress, decimals, totalAssetsFormatted, feePercent2, priceUsd, marketIds, rateMap, positionMap, tokenList, uidCtx) {
53720
53800
  if (totalAssetsFormatted <= 0) {
53721
53801
  return { depositRate: 0, exposures: [], liquidityFormatted: 0 };
53722
53802
  }
@@ -53761,13 +53841,13 @@ function computeVaultAllocation(vaultAddress, decimals, totalAssetsFormatted, fe
53761
53841
  const grossApr = weighted / totalAssetsFormatted;
53762
53842
  const idle = Math.max(0, totalAssetsFormatted - allocated);
53763
53843
  return {
53764
- depositRate: grossApr * (1 - feePercent / 100),
53844
+ depositRate: grossApr * (1 - feePercent2 / 100),
53765
53845
  // Tag uninvested deposits as an idle entry so the breakdown sums to ~100%.
53766
53846
  exposures: withIdleExposure(exposures, totalAssetsFormatted, priceUsd),
53767
53847
  liquidityFormatted: Math.min(totalAssetsFormatted, idle + withdrawable)
53768
53848
  };
53769
53849
  }
53770
- function computeV2Allocation(decimals, totalAssetsFormatted, feePercent, priceUsd, marketAssetsRaw, rateMap, tokenList, uidCtx) {
53850
+ function computeV2Allocation(decimals, totalAssetsFormatted, feePercent2, priceUsd, marketAssetsRaw, rateMap, tokenList, uidCtx) {
53771
53851
  if (totalAssetsFormatted <= 0) {
53772
53852
  return { depositRate: 0, exposures: [], liquidityFormatted: 0 };
53773
53853
  }
@@ -53808,7 +53888,7 @@ function computeV2Allocation(decimals, totalAssetsFormatted, feePercent, priceUs
53808
53888
  const grossApr = weighted / totalAssetsFormatted;
53809
53889
  const idle = Math.max(0, totalAssetsFormatted - allocated);
53810
53890
  return {
53811
- depositRate: grossApr * (1 - feePercent / 100),
53891
+ depositRate: grossApr * (1 - feePercent2 / 100),
53812
53892
  exposures: withIdleExposure(exposures, totalAssetsFormatted, priceUsd),
53813
53893
  liquidityFormatted: Math.min(totalAssetsFormatted, idle + withdrawable)
53814
53894
  };
@@ -55028,7 +55108,7 @@ function safeBigInt(v) {
55028
55108
  return ZERO3;
55029
55109
  }
55030
55110
  }
55031
- function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent, evkIndex) {
55111
+ function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent2, evkIndex) {
55032
55112
  if (!strategies?.length) return 0;
55033
55113
  const totalAssets = safeBigInt(totalAssetsRaw);
55034
55114
  if (totalAssets === ZERO3) return 0;
@@ -55045,7 +55125,7 @@ function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent, evkInd
55045
55125
  if (weightedRay === ZERO3) return 0;
55046
55126
  const apyRayPerAsset = weightedRay / totalAssets;
55047
55127
  const grossPercent = apyToAprPercent(Number(apyRayPerAsset) / RAY_TO_PERCENT3);
55048
- const netPercent = grossPercent * (1 - feePercent / 100);
55128
+ const netPercent = grossPercent * (1 - feePercent2 / 100);
55049
55129
  return Number.isFinite(netPercent) ? netPercent : 0;
55050
55130
  }
55051
55131
  function computeRealLiquidity(strategies, totalAssetsRaw, evkIndex) {
@@ -61503,6 +61583,12 @@ var fetchSavingsVaults = async (chainId, multicallRetry, prices = {}, tokenList
61503
61583
  // queue window is per-asset and governance-mutable.
61504
61584
  withdrawalCooldownSeconds: state.withdrawalCooldownSeconds ?? entry.withdrawalCooldownSeconds,
61505
61585
  withdrawFeeBps: state.withdrawFeeBps,
61586
+ // Term-sheet inputs that no reader can derive — see the registry's
61587
+ // docstrings. Passed through verbatim so the sheet can stop hardcoding
61588
+ // "compounds per second" and "needs an approval" for every vault.
61589
+ yieldWarmupSeconds: entry.yieldWarmupSeconds,
61590
+ accrual: entry.accrual,
61591
+ needsDepositApproval: entry.needsDepositApproval,
61506
61592
  instantRedeemEnabled: state.instantRedeemEnabled,
61507
61593
  inventoryContract: entry.inventoryContract?.toLowerCase(),
61508
61594
  withdrawQueue: state.withdrawQueue ?? entry.withdrawQueue?.toLowerCase(),
@@ -64346,7 +64432,8 @@ function feePhrase(fee) {
64346
64432
  }
64347
64433
  const rebate = fee.value < 0 ? " rebate" : "";
64348
64434
  const qualifier = fee.indicative ? " (estimated, resolved at execution)" : "";
64349
- return `${fee.label}: ${amount3}${rebate}${qualifier}`;
64435
+ const bound = fee.mutable && fee.cap != null ? `, governance-set up to a maximum of ${fee.unit === "bps" ? `${fee.cap} bps` : pct(fee.cap)}` : fee.mutable ? ", governance-set" : "";
64436
+ return `${fee.label}: ${amount3}${rebate}${bound}${qualifier}`;
64350
64437
  }
64351
64438
  function maturityPhrase(m) {
64352
64439
  if (m.kind === "fixed-date" && m.maturity)
@@ -64440,7 +64527,8 @@ function supplyHeadline(s) {
64440
64527
  const exit = exitPhrase[String(s.exit.mode)] ?? (s.exit.settlement === "sync" ? "withdraw any time" : "delayed withdrawal");
64441
64528
  const cooldown = s.exit.cooldownSecs ? ` (${duration(s.exit.cooldownSecs)})` : "";
64442
64529
  const mat = s.maturity.kind === "perpetual" ? "" : ` ${maturityPhrase(s.maturity)}`;
64443
- return `${rate}${mat} \xB7 ${exit}${cooldown}`;
64530
+ const warmup = s.rate.warmupSecs ? ` \xB7 earns after ${duration(s.rate.warmupSecs)}` : "";
64531
+ return `${rate}${mat}${warmup} \xB7 ${exit}${cooldown}`;
64444
64532
  }
64445
64533
  function borrowHeadline(b) {
64446
64534
  const rate = b.rate.kind === "zero-interest" ? "No ongoing interest" : b.rate.kind === "user-set" ? (
@@ -64744,7 +64832,8 @@ var TERM_PROFILES = [
64744
64832
  borrow: {
64745
64833
  description: "A CDP where YOU set the interest rate. A one-off upfront fee is charged at open, and there is a minimum debt size.",
64746
64834
  implications: [
64747
- "Your collateral can be REDEEMED at par while the position is perfectly healthy, if you carry the lowest interest rate on the branch. Raising your rate is the only defence.",
64835
+ "Your collateral can be REDEEMED at par while the position is perfectly healthy, if you carry the lowest interest rate on the branch. Raising your rate is the defence \u2014 but note a redemption that leaves you under the minimum debt puts the trove in a ZOMBIE state that must be topped back up or closed.",
64836
+ "If the branch ever SHUTS DOWN (system collateral ratio below its floor, or an oracle failure), that changes: urgent redemptions then pay the redeemer a 2 % collateral bonus against any trove regardless of rate, so the queue position your rate bought is worth nothing and you are no longer left whole.",
64748
64837
  "You pay a one-off upfront fee equal to roughly a week of interest at open, and again whenever you adjust the rate.",
64749
64838
  "There is a minimum debt size; you cannot leave a position below it."
64750
64839
  ]
@@ -64758,7 +64847,9 @@ var TERM_PROFILES = [
64758
64847
  description: "A CDP with NO ongoing interest. The entire borrowing cost is a one-off decaying mint fee charged at open.",
64759
64848
  implications: [
64760
64849
  "There is no APR \u2014 the cost is the mint fee, so a short-held loan is expensive and a long-held one is cheap.",
64761
- "Your collateral can be redeemed at par while healthy."
64850
+ "Your collateral can be redeemed at par while the position is perfectly healthy \u2014 permissionlessly, by any holder of the stablecoin, whenever it trades below its target.",
64851
+ "Redemptions here hit the LOWEST-COLLATERALISED troves first. There is no interest rate to raise (this protocol charges none), so the only defence is adding collateral or repaying.",
64852
+ "If you are redeemed, collateral left over above the redeemed debt is NOT returned automatically \u2014 you have to claim it from the surplus balance."
64762
64853
  ]
64763
64854
  }
64764
64855
  }),
@@ -64835,6 +64926,27 @@ var TERM_PROFILES = [
64835
64926
  ]
64836
64927
  }
64837
64928
  }),
64929
+ P({
64930
+ id: "morpho.blue@v1",
64931
+ name: "Morpho Blue isolated market",
64932
+ family: "morpho-blue",
64933
+ supply: {
64934
+ description: "An isolated two-asset market whose parameters \u2014 collateral, oracle, interest-rate model and LLTV \u2014 are fixed when the market is created and cannot be changed afterwards.",
64935
+ implications: [
64936
+ "Nobody can raise this market\u2019s LLTV, swap its interest-rate model or point it at a different collateral. Those are set once, at creation.",
64937
+ "What CAN still change: the protocol fee on interest (governance-set, capped at 25 %), and \u2014 where the oracle contract behind the fixed oracle address is itself upgradeable \u2014 the price it reports. Check the oracle block.",
64938
+ "Immutability cuts both ways: a market created with a bad oracle or an aggressive LLTV cannot be fixed either, and nobody can pause it for you."
64939
+ ]
64940
+ },
64941
+ borrow: {
64942
+ description: "Borrow against a single collateral in an isolated market whose risk parameters are fixed at creation.",
64943
+ implications: [
64944
+ "Your liquidation threshold is the LLTV the market was created with and cannot be moved under you.",
64945
+ "There is no governance pause and no parameter rescue \u2014 the market runs as deployed."
64946
+ ]
64947
+ },
64948
+ docsUrl: "https://docs.morpho.org/morpho/concepts/markets"
64949
+ }),
64838
64950
  // ── Vaults ───────────────────────────────────────────────────────────────
64839
64951
  P({
64840
64952
  id: "vault.lending@v1",
@@ -65807,7 +65919,16 @@ function buildRate2(input, t, maturity) {
65807
65919
  },
65808
65920
  aprTotal: total,
65809
65921
  basis: "apr-nominal",
65810
- compounding: kind === "none" ? "none" : "per-second",
65922
+ // `per-second` is right for a vault whose share price grows continuously,
65923
+ // which is nearly all of them — but not for a LINEAR accrual. Frankencoin's
65924
+ // savings module books `Δticks × saved / 1e6 / 365 days` and only compounds
65925
+ // if someone happens to call `refresh`, so claiming per-second here would
65926
+ // imply an APY ~2 % relative above what it actually pays. Providers say so
65927
+ // through `accrual`.
65928
+ compounding: kind === "none" ? "none" : input.accrual === "linear" ? "none" : "per-second",
65929
+ // A warm-up is neither a withdrawal lock nor a governance notice period —
65930
+ // see `RateTerms.warmupSecs`. Absent ⇒ earns from the first block.
65931
+ warmupSecs: input.yieldWarmupSeconds && input.yieldWarmupSeconds > 0 ? input.yieldWarmupSeconds : void 0,
65811
65932
  source,
65812
65933
  // A PT's discount is fixed at purchase; every other vault floats.
65813
65934
  isLocked: kind === "fixed-term" && termIsBacked,
@@ -65988,7 +66109,13 @@ function buildAvailability2(input, now) {
65988
66109
  blockedBy,
65989
66110
  gating: gated ? "whitelist" : "permissionless",
65990
66111
  cap: cap != null && cap !== "0" ? cap : void 0,
65991
- requires: ["token-approval"],
66112
+ // Almost every vault pulls the deposit with `transferFrom` and therefore
66113
+ // needs an allowance — but not all. Frankencoin's savings modules are
66114
+ // registered ZCHF minters, and the token grants a registered minter an
66115
+ // implicit infinite allowance, so their deposit route emits NO approval.
66116
+ // Asserting one here would make the sheet contradict the envelope built
66117
+ // beside it, which is worse than saying nothing.
66118
+ requires: input.needsDepositApproval === false ? [] : ["token-approval"],
65992
66119
  opensWith: "standalone"
65993
66120
  };
65994
66121
  }
@@ -66441,9 +66568,29 @@ function earnLabel(dimension, key3) {
66441
66568
  function earnDescription(dimension, key3) {
66442
66569
  return EARN_DESCRIPTIONS[dimension][key3];
66443
66570
  }
66571
+ function stripBrandWords(name, venue) {
66572
+ const brandWords = new Set(
66573
+ (venue ? `${venueBrand(venue)} ${venueBrandKey(venue)}` : "").toLowerCase().split(/[^a-z0-9]+/).filter(Boolean)
66574
+ );
66575
+ const words = name.trim().split(/\s+/);
66576
+ let i = 0;
66577
+ while (i < words.length && brandWords.has(words[i].toLowerCase())) i++;
66578
+ return words.slice(i).join(" ").trim();
66579
+ }
66580
+ function namesToken(text, token) {
66581
+ const wanted = token.toLowerCase();
66582
+ return text.split(/[^a-zA-Z0-9]+/).some((t) => t.toLowerCase() === wanted);
66583
+ }
66444
66584
  function earnMarketLabel(input) {
66445
66585
  const asset = input.assetSymbol?.trim();
66446
66586
  if (!asset) return input.fallbackName ?? "";
66587
+ const detail = stripBrandWords(
66588
+ input.lenderMarketName?.trim() ?? "",
66589
+ input.venue
66590
+ );
66591
+ if (detail && detail.toLowerCase() !== asset.toLowerCase()) {
66592
+ return namesToken(detail, asset) ? detail : `${asset} \xB7 ${detail}`;
66593
+ }
66447
66594
  const collaterals = (input.collateralSymbols ?? []).map((c) => c?.trim()).filter((c) => !!c);
66448
66595
  const distinct = [...new Set(collaterals)];
66449
66596
  if (distinct.length === 1) return `${asset} \xB7 vs ${distinct[0]}`;
@@ -66854,6 +67001,9 @@ function toVaultTermInput(vault, provider, chainId) {
66854
67001
  swapFeeRate: num13(row.feeRate),
66855
67002
  redemptionDiscountBps: num13(row.redemptionDiscountBps),
66856
67003
  instantRedeemEnabled: bool2(row.instantRedeemEnabled),
67004
+ yieldWarmupSeconds: num13(row.yieldWarmupSeconds),
67005
+ accrual: str6(row.accrual),
67006
+ needsDepositApproval: bool2(row.needsDepositApproval),
66857
67007
  isMintable: bool2(row.isMintable),
66858
67008
  depositCapacity: str6(row.depositCapacity),
66859
67009
  supplyCap: str6(row.supplyCap),
@@ -66915,6 +67065,9 @@ function vaultTermInputFromEarnMarket(m) {
66915
67065
  swapFeeRate: num13(meta.feeRate),
66916
67066
  redemptionDiscountBps: num13(meta.redemptionDiscountBps),
66917
67067
  instantRedeemEnabled: bool2(meta.instantRedeemEnabled),
67068
+ yieldWarmupSeconds: num13(meta.yieldWarmupSeconds),
67069
+ accrual: str6(meta.accrual),
67070
+ needsDepositApproval: bool2(meta.needsDepositApproval),
66918
67071
  // `canDeposit` already folds in the cap, the pause and the gate, so it is
66919
67072
  // the authoritative answer — but the REASON is what a disabled CTA renders,
66920
67073
  // and that only survives in the raw fields.
@@ -66992,6 +67145,9 @@ function vaultTermInputFromSourceRow(row, chainId) {
66992
67145
  swapFeeRate: num13(meta.feeRate),
66993
67146
  redemptionDiscountBps: num13(meta.redemptionDiscountBps),
66994
67147
  instantRedeemEnabled: bool2(meta.instantRedeemEnabled),
67148
+ yieldWarmupSeconds: num13(meta.yieldWarmupSeconds),
67149
+ accrual: str6(meta.accrual),
67150
+ needsDepositApproval: bool2(meta.needsDepositApproval),
66995
67151
  isMintable: bool2(meta.isMintable),
66996
67152
  depositCapacity: str6(meta.depositCapacity) ?? str6(meta.maxDeposit),
66997
67153
  supplyCap: str6(meta.supplyCap),
@@ -67943,7 +68099,12 @@ var ROW_DESCRIPTOR_KEYS = [
67943
68099
  "curvance",
67944
68100
  "broker",
67945
68101
  "collateralProvider",
67946
- "loanProvider"
68102
+ "loanProvider",
68103
+ // Morpho Blue's protocol fee — the ONE parameter of an otherwise immutable
68104
+ // market that governance can move. Nested under `params.market` on the
68105
+ // in-package shape but a top-level field on `/pools/latest`, so without it
68106
+ // here the flat path reports a confident 0 % on every Blue market.
68107
+ "fee"
67947
68108
  ];
67948
68109
  function resolveMarketDescriptors(row, ctxMarket) {
67949
68110
  const fromParams = pick2(row, "params.market");
@@ -68601,6 +68762,7 @@ var liquityAdapter = {
68601
68762
  const minDebt = liquity.minDebt != null ? String(liquity.minDebt) : void 0;
68602
68763
  const minApr = typeof liquity.minAnnualInterestRate === "string" || typeof liquity.minAnnualInterestRate === "number" ? Number(liquity.minAnnualInterestRate) / 1e18 * 100 : void 0;
68603
68764
  const maxApr = typeof liquity.maxAnnualInterestRate === "string" || typeof liquity.maxAnnualInterestRate === "number" ? Number(liquity.maxAnnualInterestRate) / 1e18 * 100 : void 0;
68765
+ const shutdown = Boolean(liquity.shutdown);
68604
68766
  const wadPct = (v) => v == null ? void 0 : Number(v) / 1e18;
68605
68767
  const spPenalty = wadPct(liquity.liquidationPenaltySP);
68606
68768
  const redistPenalty = wadPct(liquity.liquidationPenaltyRedistribution);
@@ -68669,20 +68831,41 @@ var liquityAdapter = {
68669
68831
  penalties: penalties.length ? penalties : void 0,
68670
68832
  badDebt: "redistributed",
68671
68833
  redeemable: true,
68672
- redemption: {
68673
- // Not governance and not a liquidation: any holder of the stable
68674
- // may redeem it for collateral at any time.
68834
+ // Two different mechanisms share the word "redemption", and the
68835
+ // ordinary one stops applying the moment a branch shuts down.
68836
+ //
68837
+ // NORMAL: rate-ordered, fee stays in the trove, borrower ~USD-neutral.
68838
+ // SHUTDOWN (TCR < SCR or oracle failure, permanent): **urgent
68839
+ // redemptions** run at a 2 % collateral BONUS to the redeemer, against
68840
+ // any trove — so the queue position a borrower bought with their rate
68841
+ // is worthless, and they are no longer neutral, they are down 2 %.
68842
+ //
68843
+ // Asserting the normal terms unconditionally told exactly the wrong
68844
+ // story to the only borrowers who could still act on it.
68845
+ redemption: shutdown ? {
68675
68846
  trigger: "permissionless-arbitrage",
68676
- // It only pays while the stable trades under its target — which is
68677
- // the point: redemptions are what push it back up.
68847
+ // No longer peg-driven: the 2 % bonus pays regardless.
68848
+ driver: "always",
68849
+ // Urgent redemptions ignore the interest-rate ordering.
68850
+ order: "pro-rata",
68851
+ valueImpact: "loss",
68852
+ defence: "This branch is shut down and urgent redemptions pay a 2 % collateral bonus, so your interest rate no longer protects you. Closing or repaying the position is the only way out from under it."
68853
+ } : {
68854
+ // Not governance and not a liquidation: any holder of the
68855
+ // stable can trigger it, without permission.
68856
+ trigger: "permissionless-arbitrage",
68857
+ // Permissionless does NOT mean constant — it only pays while
68858
+ // the stable trades under target, which is the point:
68859
+ // redemptions are what push it back up.
68678
68860
  driver: "below-peg",
68679
68861
  // The rate you chose IS your position in the queue.
68680
68862
  order: "lowest-rate-first",
68681
- // The redemption fee stays in the position as extra collateral, so
68863
+ // The redemption fee stays in the trove as extra collateral, so
68682
68864
  // the borrower is ~USD-neutral; what is lost is EXPOSURE.
68683
68865
  valueImpact: "usd-neutral",
68684
- // The ordering is already stated by `order`; say only what to DO.
68685
- defence: "Raising your rate moves you back in that queue."
68866
+ // The ordering is already stated by `order`; say what to DO
68867
+ // including the trap that follows a partial redemption.
68868
+ defence: "Raising your rate moves you back in that queue. If a redemption leaves you below the minimum debt your trove goes ZOMBIE \u2014 removed from the queue, and only recoverable by topping it back above the floor or closing it."
68686
68869
  }
68687
68870
  },
68688
68871
  counterparty: { kind: "cdp", solvency: "overcollateralized" }
@@ -68719,14 +68902,28 @@ var riverAdapter = {
68719
68902
  seizure: "proportional",
68720
68903
  redeemable: true,
68721
68904
  redemption: {
68722
- // Not governance and not a liquidation: any holder of the stable may
68723
- // redeem it for collateral at any time.
68905
+ // Not governance and not a liquidation: any holder of the stable can
68906
+ // trigger it, without permission and without targeting anyone.
68724
68907
  trigger: "permissionless-arbitrage",
68908
+ // Permissionless does NOT mean constant: it only pays the redeemer
68909
+ // while the stable trades under target, which is what makes it a peg
68910
+ // defence rather than a standing claim on collateral.
68725
68911
  driver: "below-peg",
68726
- order: "lowest-rate-first",
68727
- valueImpact: "usd-neutral",
68728
- // The ordering is already stated by `order`; say only what to DO.
68729
- defence: "Raising your rate moves you back in that queue."
68912
+ // COLLATERAL-RATIO ordered, V1-style — NOT rate-ordered.
68913
+ //
68914
+ // This said `lowest-rate-first`, copied from the Liquity V2 shape,
68915
+ // and it was wrong twice over: River is Prisma/V1 lineage, which
68916
+ // redeems against the LOWEST-COLLATERALISED troves first, and River
68917
+ // charges no interest at all (`rate.kind: 'zero-interest'` above), so
68918
+ // the accompanying "raise your rate" advice pointed at a control that
68919
+ // does not exist on this protocol. A borrower following it would have
68920
+ // done nothing while sitting first in the real queue.
68921
+ order: "lowest-collateral-ratio",
68922
+ // Deliberately ABSENT rather than `usd-neutral`. The V1 mechanism
68923
+ // sends collateral above the redeemed debt to a surplus balance that
68924
+ // the borrower must CLAIM, so whether they end up whole depends on an
68925
+ // action they may not know to take — see `defence`.
68926
+ defence: "Add collateral or repay to raise your collateral ratio and move behind other troves in the queue. If you are redeemed, claim the leftover collateral from the surplus balance \u2014 it is not returned automatically."
68730
68927
  }
68731
68928
  },
68732
68929
  counterparty: { kind: "cdp", solvency: "overcollateralized" }
@@ -69040,7 +69237,18 @@ var resupplyAdapter = {
69040
69237
  // rate to raise. Offering "raise your rate" here would be actively
69041
69238
  // misleading.
69042
69239
  order: "pro-rata",
69043
- valueImpact: "usd-neutral"
69240
+ // `valueImpact` deliberately ABSENT — it is NOT `usd-neutral`.
69241
+ //
69242
+ // That was carried over from Liquity, where the redemption fee stays
69243
+ // IN the trove as extra collateral and leaves the borrower roughly
69244
+ // whole. Resupply does the opposite: `redeemCollateral` takes a 1 %
69245
+ // base fee with half of it going to the protocol, and writes the
69246
+ // collateral off across the pair via a `WriteOffToken` — so nothing
69247
+ // is credited back to the borrower and there is no surplus to claim.
69248
+ // Whether they end up neutral is not something we have established,
69249
+ // and an absent field says that where `usd-neutral` would have
69250
+ // promised it.
69251
+ defence: "Nothing \u2014 redemptions are skimmed pro-rata from every borrower in the pair, so there is no queue to move down and no action that exempts you. Your collateral can shrink with no transaction of your own."
69044
69252
  },
69045
69253
  badDebt: "socialized"
69046
69254
  },
@@ -69188,6 +69396,54 @@ var fraxlendAdapter = {
69188
69396
  }
69189
69397
  })
69190
69398
  };
69399
+ var MORPHO_BLUE_MAX_FEE_PERCENT = 25;
69400
+ function feePercent(raw) {
69401
+ if (raw == null) return void 0;
69402
+ const n = typeof raw === "string" ? Number(raw) : raw;
69403
+ if (!Number.isFinite(n) || n <= 0) return void 0;
69404
+ return n > 1 ? n / 1e18 * 100 : n * 100;
69405
+ }
69406
+ var morphoBlueAdapter = {
69407
+ id: "morpho-blue",
69408
+ matches: (lender) => isMorphoBlue(lender),
69409
+ profileId: () => "morpho.blue@v1",
69410
+ build: (input) => {
69411
+ const market = input.market ?? {};
69412
+ const fee = feePercent(market.fee);
69413
+ return {
69414
+ governance: {
69415
+ mutability: "immutable",
69416
+ // The ONE power that reaches an existing market. Listing the full owner
69417
+ // surface here would imply `enableLltv` could change THIS market's LLTV,
69418
+ // which is the misreading the whole adapter exists to prevent.
69419
+ powers: ["change-fees"]
69420
+ },
69421
+ supply: {
69422
+ // Stated as a FEE rather than left as a bare governance power, so the
69423
+ // bound travels with it: the number a supplier is exposed to is "0 %
69424
+ // today, never above 25 %", which a `change-fees` enum cannot express.
69425
+ //
69426
+ // Emitted even at 0 — the current Morpho default — because "this market
69427
+ // charges no fee, and the most it could ever charge is 25 %" is the
69428
+ // whole point, and an absent row would leave the power unexplained.
69429
+ fees: [
69430
+ {
69431
+ id: "reserve-factor",
69432
+ label: "Protocol fee on interest",
69433
+ when: "ongoing",
69434
+ unit: "percent",
69435
+ basis: "yield",
69436
+ value: fee ?? 0,
69437
+ payee: "protocol",
69438
+ mutable: true,
69439
+ cap: MORPHO_BLUE_MAX_FEE_PERCENT,
69440
+ description: "A share of the interest borrowers pay, taken before it reaches suppliers. Morpho governance can change it on a live market, but the contract refuses anything above 25 % \u2014 it is the only parameter of this market that can move."
69441
+ }
69442
+ ]
69443
+ }
69444
+ };
69445
+ }
69446
+ };
69191
69447
 
69192
69448
  // src/terms/adapters/index.ts
69193
69449
  var TERM_ADAPTERS = [
@@ -69208,7 +69464,8 @@ var TERM_ADAPTERS = [
69208
69464
  frankencoinAdapter,
69209
69465
  resupplyAdapter,
69210
69466
  curvanceAdapter,
69211
- fraxlendAdapter
69467
+ fraxlendAdapter,
69468
+ morphoBlueAdapter
69212
69469
  ];
69213
69470
  function resolveAdapter(lender) {
69214
69471
  return TERM_ADAPTERS.find((a) => a.matches(lender));
@@ -69374,7 +69631,9 @@ function enrichTermSheet(sheet, index) {
69374
69631
  }
69375
69632
  const govRow = index.governanceByMarketUid?.get(uid);
69376
69633
  if (govRow) {
69377
- const immutable = govRow.mode === "immutable";
69634
+ const assertedImmutable = sheet.governance?.mutability === "immutable";
69635
+ const immutable = govRow.mode === "immutable" || assertedImmutable;
69636
+ const adapterPowers = assertedImmutable ? sheet.governance?.powers : void 0;
69378
69637
  sheet.governance = {
69379
69638
  ...sheet.governance,
69380
69639
  mutability: immutable ? "immutable" : "governed",
@@ -69392,7 +69651,8 @@ function enrichTermSheet(sheet, index) {
69392
69651
  };
69393
69652
  if (immutable) {
69394
69653
  sheet.governance.timelockSecs = void 0;
69395
- sheet.governance.powers = void 0;
69654
+ sheet.governance.timelockUnknown = void 0;
69655
+ sheet.governance.powers = adapterPowers;
69396
69656
  }
69397
69657
  }
69398
69658
  const quality = index.assetRisk;
@@ -69622,8 +69882,12 @@ function validateTermSheet(sheet) {
69622
69882
  "immutable-timelock",
69623
69883
  "immutable governance must not carry a timelock"
69624
69884
  );
69625
- if (g.powers?.length)
69626
- fail("immutable-powers", "immutable governance must not carry powers");
69885
+ const disallowed = (g.powers ?? []).filter((p) => p !== "change-fees");
69886
+ if (disallowed.length)
69887
+ fail(
69888
+ "immutable-powers",
69889
+ `immutable governance must not carry powers: ${disallowed.join(", ")}`
69890
+ );
69627
69891
  }
69628
69892
  if (g.timelockSecs && g.controllerKind && g.controllerKind !== "TIMELOCK" && g.timelockSource !== "on-chain")
69629
69893
  fail(
@@ -69661,7 +69925,27 @@ var USER_SET_RATE_PREFIXES = [
69661
69925
  "SONETA",
69662
69926
  "EBISU"
69663
69927
  ];
69664
- function earnMarketFromPool(row, fallbackChainId) {
69928
+ function collateralSymbolsByVenue(rows, fallbackChainId) {
69929
+ const byVenue = /* @__PURE__ */ new Map();
69930
+ for (const row of rows) {
69931
+ const venue = str5(row.lender) ?? str5(row.lenderKey);
69932
+ const chainId = str5(row.chainId) ?? fallbackChainId;
69933
+ if (!venue || !chainId) continue;
69934
+ const collateralActive = row.flags?.collateralActive ?? row.collateralActive;
69935
+ if (collateralActive !== true) continue;
69936
+ const symbol = str5(row.underlyingInfo?.asset?.symbol) ?? str5(row.asset?.symbol);
69937
+ if (!symbol) continue;
69938
+ const key3 = venueGroupKey(chainId, venue);
69939
+ let set = byVenue.get(key3);
69940
+ if (!set) byVenue.set(key3, set = /* @__PURE__ */ new Set());
69941
+ set.add(symbol);
69942
+ }
69943
+ return new Map([...byVenue].map(([key3, set]) => [key3, [...set]]));
69944
+ }
69945
+ function venueGroupKey(chainId, venue) {
69946
+ return `${chainId}::${venue}`;
69947
+ }
69948
+ function earnMarketFromPool(row, fallbackChainId, venueCollaterals) {
69665
69949
  const marketUid = str5(row.marketUid);
69666
69950
  if (!marketUid) return void 0;
69667
69951
  let earnUid;
@@ -69709,7 +69993,21 @@ function earnMarketFromPool(row, fallbackChainId) {
69709
69993
  // across the listing: the STABLE family key, never the per-market venue.
69710
69994
  // No lender publishes a curator today, hence the undefined.
69711
69995
  ...resolveEarnIdentity(venue, void 0),
69712
- name: str5(row.name),
69996
+ // Pair-aware: "USDT · vs wstETH" for an isolated market, plain "USDC" for
69997
+ // a shared pool. The fetcher's own name is only the fallback — it is the
69998
+ // leg-local "Loan USDC", which a chain repeats across 300 markets and
69999
+ // which says nothing about WHICH market this is. Identical to what the
70000
+ // origin's SQL route builds, so both paths agree.
70001
+ name: earnMarketLabel({
70002
+ assetSymbol: str5(assetInfo.symbol),
70003
+ lenderMarketName: str5(row.lenderInfo?.name),
70004
+ venue,
70005
+ // Minus this row's own leg: on the COLLATERAL row of an isolated market
70006
+ // the only collateral is itself, and "cbBTC · vs cbBTC" is nonsense.
70007
+ // Removing it leaves zero, i.e. the plain name — correct.
70008
+ collateralSymbols: venueCollaterals?.get(venueGroupKey(chainId, venue))?.filter((c) => c !== str5(assetInfo.symbol)),
70009
+ fallbackName: str5(row.name)
70010
+ }),
69713
70011
  // Never re-derived — the uid's third segment as the origin minted it.
69714
70012
  ref: marketUid.split(":")[2],
69715
70013
  logoURI: str5(assetInfo.logoURI),
@@ -70027,7 +70325,13 @@ function legAsset(pos) {
70027
70325
  );
70028
70326
  const decimals = typeof asset.decimals === "number" ? asset.decimals : void 0;
70029
70327
  const symbol = typeof asset.symbol === "string" ? asset.symbol : void 0;
70030
- return { address, symbol, decimals };
70328
+ const logoURI = typeof asset.logoURI === "string" ? asset.logoURI : void 0;
70329
+ return {
70330
+ address,
70331
+ symbol,
70332
+ decimals,
70333
+ ...logoURI ? { logoURI } : {}
70334
+ };
70031
70335
  }
70032
70336
  function toLeg(pos) {
70033
70337
  const depositsUsd = num15(pos.depositsUSD);
@@ -70039,7 +70343,9 @@ function toLeg(pos) {
70039
70343
  marketUid: pos.marketUid,
70040
70344
  ...pos.loanId ? { loanId: pos.loanId } : {},
70041
70345
  asset: legAsset(pos),
70042
- side: hasSupply && hasDebt ? "both" : hasDebt ? "borrow" : "supply",
70346
+ // An empty market is `'none'`, NOT `'supply'` the old fallback quietly
70347
+ // reported every market the account was merely configured in as a holding.
70348
+ side: hasSupply && hasDebt ? "both" : hasDebt ? "borrow" : hasSupply ? "supply" : "none",
70043
70349
  deposits: pos.deposits ?? "0",
70044
70350
  depositsUsd,
70045
70351
  debt: pos.debt ?? "0",
@@ -70067,10 +70373,17 @@ function earnPositionFromLenderEntry(entry) {
70067
70373
  legs
70068
70374
  };
70069
70375
  });
70070
- const active = subAccounts.filter((s) => s.legs.length > 0 || s.netUsd !== 0);
70376
+ const active = subAccounts.filter(
70377
+ (s) => s.legs.some((l) => l.side !== "none") || s.netUsd !== 0
70378
+ );
70071
70379
  const crossMargin = active.length <= 1;
70072
70380
  const suppliedUsd = num15(entry.balanceData?.deposits);
70073
70381
  const borrowedUsd = num15(entry.balanceData?.debt);
70382
+ const aprBreakdown = {
70383
+ market: num15(entry.aprData?.apr),
70384
+ rewards: num15(entry.aprData?.rewardApr),
70385
+ intrinsic: num15(entry.aprData?.intrinsicApr)
70386
+ };
70074
70387
  return {
70075
70388
  positionUid: buildLendingPositionUid(entry.lender, entry.chainId),
70076
70389
  chainId: entry.chainId,
@@ -70084,7 +70397,8 @@ function earnPositionFromLenderEntry(entry) {
70084
70397
  suppliedUsd,
70085
70398
  borrowedUsd,
70086
70399
  netUsd: num15(entry.balanceData?.nav),
70087
- apr: num15(entry.aprData?.apr),
70400
+ apr: aprBreakdown.market + aprBreakdown.rewards + aprBreakdown.intrinsic,
70401
+ aprBreakdown,
70088
70402
  depositApr: num15(entry.aprData?.depositApr),
70089
70403
  borrowApr: num15(entry.aprData?.borrowApr),
70090
70404
  // Only a cross-margin account HAS one health factor. Publishing the first
@@ -70172,6 +70486,6 @@ function earnPositionTotals(items) {
70172
70486
  };
70173
70487
  }
70174
70488
 
70175
- export { ApiBookSource, DEFAULT_MIDNIGHT_API, DEFAULT_OUTLIER_GUARD, DEFAULT_PROFILE_ID, DEFAULT_STALE_REJECT_SECONDS, DEFAULT_TERMMAX_API, EARN_DESCRIPTIONS, EARN_LABELS, EMPTY_BALANCE, EXACTLY_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, STABLECOIN_SYMBOLS, STCELO_MANAGER_ADDRESS, TELLER_CALLS_PER_BID, TERMMAX_CALLS_PER_ACCOUNT, DECIMAL_BASE as TERMMAX_DECIMAL_BASE, TERMMAX_LIQUIDATION_PENALTY, TERMMAX_LIQUIDATION_WINDOW_SECS, TERMMAX_LIQUIDATOR_BONUS, 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_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, 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, 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, convertDssMarketsToResponse, convertExactlyMarketsToResponse, 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, dssIlkBytes32, dssKeyParts, dssLenderKey, duration, earnDescription, earnLabel, earnMarketFromPool, earnMarketFromVault, earnMarketLabel, earnPositionFromLenderEntry, earnPositionFromVaultBalance, earnPositionTotals, earnUidFromMarketUid, earnVenueKind, encodeBalanceFetcherCalldata, enrichTermSheet, enrichmentIndexFromRows, exactlyPairLtv, exactlyPenaltyRateToAprPercent, exactlyWadRateToPercent, feePhrase, feedKeyOf, feedStatKey, fetchDolomiteAccountNumbers, fetchDssMarkets, fetchEulerEarnVaults, fetchEulerEarnVaultsFromSubgraph, fetchEulerSubAccountIndexes, fetchExactlyMarkets, fetchFlashLiquidityForChain, fetchFluidFTokens, 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, fetchTellerMarkets, fetchTermMarkets, fetchTermMaxMarkets, fetchTokenBalances, fetchTokenMetadata, fetchUpshiftApiVaults, fetchUpshiftVaults, fetchUsddMarkets, fetchYearnApiVaults, fetchYearnVaults, filterActiveLenders, filterLendersByProtocol, finalizeInfo, findingsFor, formatRaw, frankencoinKeyParts, frankencoinLenderKey, fraxlendAssetPerCollateral, fraxlendKeyParts, fraxlendLenderKey, fuseLenderData, generateLendingPools, getAavesForChain, getAssetConfig, getBalanceForMarketUid, getBorrowCapacity, 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, getStCeloValidatorGroups, getSubAccountAddress, getSubAccountIndex, getTermProfile, getVaultPublicDataAll, getVaultWithdrawalRequests, hasCritical, hasEulerEarnVaultSubgraph, hasLagoonVaults, hasMorphoPositionIndex, hasMorphoUserApi, hasMorphoUserSubgraph, hasPendleMarkets, hasUpshiftVaults, hasYearnVaults, ilkToKeySegment, implausibleRatePercent, inverseKeyParts, inverseLenderKey, isBoundNeed, isFailedCall, isIlliquid, isLendingPosition, isLiveMarket as isLivePendleMarket, isStablecoinSymbol, isVaultPosition, isVaultVenue, isYearnV3, keySegmentToIlk, keysFromMaps, lenderApiOnly, lenderFamily, liquityCandidateTroveIds, liquityKeyParts, liquityLenderKey, llamaLendKeyParts, llamaLendLenderKey, mergeDeep, multicall3Abi2 as multicall3Abi, nanTo, needsLenderApproval, needsTokenApproval, noOpResult, normalizeToBytes, parseBalanceFetcherResult, parseEarnUid, parseMergedResult, parseMulticallRpcResponses, parseExpirySeconds as parsePendleExpirySeconds, parseRawRpcBatchResponses, parseRawRpcResponses, parseTermMaxLtv, parseTokenBalanceResult, pct, assetKey as pendleAssetKey, positivePart2 as positivePart, predictInverseEscrow, prepareLenderUserDataRpcCalls, prepareMergedMulticallParams, prepareMergedRpcCalls, prepareMulticallInputs, prepareTokenBalanceRpcCalls, priceGlvVaults, priceGmMarkets, probeAaveFeedTimestamps, pruneFeedStats, rankFindings, ratePercent, readVaultSharePrices, rejectOutliers as rejectPriceOutliers, resolveAdapter, resolveDerivation, resolveEarnIdentity, resolveStCeloDepositGroup, resolveVaultProfileId, resupplyKeyParts, resupplyLenderKey, resupplyMarketLabel, riverKeyParts, riverLenderKey, selectAssetGroupPrices, shortDate, splitChainScopedAddress as splitPendleChainScopedAddress, stampCapabilities, stampVaultClassification, stampVaultTermSheets, supplyDescription, supplyFindings, supplyHeadline, swapRoutedProvidersArePriceConsistent, tellerBpsToPercent, tellerImpliedLtv, tellerLenderKey, tellerPoolFromLenderKey, 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, tickToAprNumber, tickToPrice, toDigest, toTermSheetInput, toVaultTermInput, tryParseEarnUid, unflattenLenderData, updateFeedStats, usdValue, usddIlkBytes32, usddKeyParts, usddLenderKey, validateTermSheet, validateTermSheets, validateUserData, vaultSharesToAssets, vaultTermInputFromEarnMarket, vaultTermInputFromSourceRow, vaultTraits, vaultVenue, venueBrand, venueBrandKey };
70489
+ export { ApiBookSource, DEFAULT_MIDNIGHT_API, DEFAULT_OUTLIER_GUARD, DEFAULT_PROFILE_ID, DEFAULT_STALE_REJECT_SECONDS, DEFAULT_TERMMAX_API, EARN_DESCRIPTIONS, EARN_LABELS, EMPTY_BALANCE, EXACTLY_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, STABLECOIN_SYMBOLS, STCELO_MANAGER_ADDRESS, TELLER_CALLS_PER_BID, TERMMAX_CALLS_PER_ACCOUNT, DECIMAL_BASE as TERMMAX_DECIMAL_BASE, TERMMAX_LIQUIDATION_PENALTY, TERMMAX_LIQUIDATION_WINDOW_SECS, TERMMAX_LIQUIDATOR_BONUS, 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_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, 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, 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, convertDssMarketsToResponse, convertExactlyMarketsToResponse, 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, dssIlkBytes32, dssKeyParts, dssLenderKey, duration, earnDescription, earnLabel, earnMarketFromPool, earnMarketFromVault, earnMarketLabel, earnPositionFromLenderEntry, earnPositionFromVaultBalance, earnPositionTotals, earnUidFromMarketUid, earnVenueKind, encodeBalanceFetcherCalldata, enrichTermSheet, enrichmentIndexFromRows, exactlyPairLtv, exactlyPenaltyRateToAprPercent, exactlyWadRateToPercent, feePhrase, feedKeyOf, feedStatKey, fetchDolomiteAccountNumbers, fetchDssMarkets, fetchEulerEarnVaults, fetchEulerEarnVaultsFromSubgraph, fetchEulerSubAccountIndexes, fetchExactlyMarkets, fetchFlashLiquidityForChain, fetchFluidFTokens, 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, fetchTellerMarkets, fetchTermMarkets, fetchTermMaxMarkets, fetchTokenBalances, fetchTokenMetadata, fetchUpshiftApiVaults, fetchUpshiftVaults, fetchUsddMarkets, fetchYearnApiVaults, fetchYearnVaults, filterActiveLenders, filterLendersByProtocol, finalizeInfo, findingsFor, formatRaw, frankencoinKeyParts, frankencoinLenderKey, fraxlendAssetPerCollateral, fraxlendKeyParts, fraxlendLenderKey, fuseLenderData, generateLendingPools, getAavesForChain, getAssetConfig, getBalanceForMarketUid, getBorrowCapacity, 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, getStCeloValidatorGroups, getSubAccountAddress, getSubAccountIndex, getTermProfile, getVaultPublicDataAll, getVaultWithdrawalRequests, hasCritical, hasEulerEarnVaultSubgraph, hasLagoonVaults, hasMorphoPositionIndex, hasMorphoUserApi, hasMorphoUserSubgraph, hasPendleMarkets, hasUpshiftVaults, hasYearnVaults, ilkToKeySegment, implausibleRatePercent, inverseKeyParts, inverseLenderKey, isBoundNeed, isFailedCall, isIlliquid, isLendingPosition, isLiveMarket as isLivePendleMarket, isStablecoinSymbol, isVaultPosition, isVaultVenue, isYearnV3, keySegmentToIlk, keysFromMaps, lenderApiOnly, lenderFamily, liquityCandidateTroveIds, liquityKeyParts, liquityLenderKey, llamaLendKeyParts, llamaLendLenderKey, mergeDeep, multicall3Abi2 as multicall3Abi, nanTo, needsLenderApproval, needsTokenApproval, noOpResult, normalizeToBytes, parseBalanceFetcherResult, parseEarnUid, parseMergedResult, parseMulticallRpcResponses, parseExpirySeconds as parsePendleExpirySeconds, parseRawRpcBatchResponses, parseRawRpcResponses, parseTermMaxLtv, parseTokenBalanceResult, pct, assetKey as pendleAssetKey, positivePart2 as positivePart, predictInverseEscrow, prepareLenderUserDataRpcCalls, prepareMergedMulticallParams, prepareMergedRpcCalls, prepareMulticallInputs, prepareTokenBalanceRpcCalls, priceGlvVaults, priceGmMarkets, probeAaveFeedTimestamps, pruneFeedStats, rankFindings, ratePercent, readVaultSharePrices, rejectOutliers as rejectPriceOutliers, resolveAdapter, resolveDerivation, resolveEarnIdentity, resolveStCeloDepositGroup, resolveVaultProfileId, resupplyKeyParts, resupplyLenderKey, resupplyMarketLabel, riverKeyParts, riverLenderKey, selectAssetGroupPrices, shortDate, splitChainScopedAddress as splitPendleChainScopedAddress, stampCapabilities, stampVaultClassification, stampVaultTermSheets, supplyDescription, supplyFindings, supplyHeadline, swapRoutedProvidersArePriceConsistent, tellerBpsToPercent, tellerImpliedLtv, tellerLenderKey, tellerPoolFromLenderKey, 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, tickToAprNumber, tickToPrice, toDigest, toTermSheetInput, toVaultTermInput, tryParseEarnUid, unflattenLenderData, updateFeedStats, usdValue, usddIlkBytes32, usddKeyParts, usddLenderKey, validateTermSheet, validateTermSheets, validateUserData, vaultSharesToAssets, vaultTermInputFromEarnMarket, vaultTermInputFromSourceRow, vaultTraits, vaultVenue, venueBrand, venueBrandKey };
70176
70490
  //# sourceMappingURL=index.js.map
70177
70491
  //# sourceMappingURL=index.js.map