@1delta/margin-fetcher 5.0.29 → 5.0.30

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
  }
@@ -43887,7 +43890,27 @@ var usddFetcher = {
43887
43890
  return out;
43888
43891
  }
43889
43892
  };
43890
- var FRANKENCOIN_SAVINGS_MODULE = "0x27d9ad987bde08a0d083ef7e0e4043c857a17b38";
43893
+ var ZCHF_ETHEREUM = "0xb58e61c3098d85632df34eecfb899a1ed80921cb";
43894
+ var ZCHF_BRIDGED = "0xd4dd9e2f021bb459d5a5f6c24c12fe09c5d45553";
43895
+ var FRANKENCOIN_SAVINGS_MODULES = [
43896
+ {
43897
+ chainId: Chain.ETHEREUM_MAINNET,
43898
+ // `savingsReferral`, NOT the config's `savingsV2` — see the header.
43899
+ module: "0x27d9ad987bde08a0d083ef7e0e4043c857a17b38",
43900
+ zchf: ZCHF_ETHEREUM
43901
+ },
43902
+ {
43903
+ chainId: Chain.GNOSIS,
43904
+ module: "0xbf594d0fed79ae56d910cb01b5dd4f4c57b04402",
43905
+ zchf: ZCHF_BRIDGED
43906
+ },
43907
+ {
43908
+ chainId: Chain.BASE,
43909
+ module: "0x6426324af1b14df3cd03b2d500529083c5ea61bc",
43910
+ zchf: ZCHF_BRIDGED
43911
+ }
43912
+ ];
43913
+ FRANKENCOIN_SAVINGS_MODULES[0].module;
43891
43914
  var SAVINGS_INFO_URL = "https://api.frankencoin.com/savings/core/info";
43892
43915
  var RATE_ABI2 = [
43893
43916
  {
@@ -43899,58 +43922,70 @@ var RATE_ABI2 = [
43899
43922
  }
43900
43923
  ];
43901
43924
  var ZCHF_SAVINGS_KEY = "ZCHF_SAVINGS";
43925
+ var zchfSavingsKey = (chainId) => chainId === Chain.ETHEREUM_MAINNET ? ZCHF_SAVINGS_KEY : `${ZCHF_SAVINGS_KEY}::${chainId}`;
43902
43926
  var aprFromRatePPM = (ppm) => Number(ppm) / 1e4;
43903
- var fetchRateOnChain = async () => {
43927
+ var fetchRateOnChain = async (d) => {
43904
43928
  const [ppm] = await multicallRetryUniversal({
43905
- chain: Chain.ETHEREUM_MAINNET,
43929
+ chain: d.chainId,
43906
43930
  abi: RATE_ABI2,
43907
- calls: [
43908
- {
43909
- address: FRANKENCOIN_SAVINGS_MODULE,
43910
- name: "currentRatePPM",
43911
- params: []
43912
- }
43913
- ],
43931
+ calls: [{ address: d.module, name: "currentRatePPM", params: [] }],
43914
43932
  allowFailure: false
43915
43933
  });
43916
43934
  if (ppm === void 0 || ppm === null) {
43917
- throw new Error("Frankencoin: unreadable currentRatePPM()");
43935
+ throw new Error(`Frankencoin: unreadable currentRatePPM() on ${d.chainId}`);
43918
43936
  }
43919
43937
  return aprFromRatePPM(ppm);
43920
43938
  };
43921
- var fetchRateFromApi = async () => {
43939
+ var fetchRatesFromApi = async () => {
43922
43940
  const res = await fetch(SAVINGS_INFO_URL, {
43923
43941
  headers: { accept: "application/json" },
43924
43942
  signal: AbortSignal.timeout(8e3)
43925
43943
  });
43926
43944
  if (!res.ok) throw new Error(`Frankencoin: savings info HTTP ${res.status}`);
43927
43945
  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");
43946
+ const out = {};
43947
+ for (const d of FRANKENCOIN_SAVINGS_MODULES) {
43948
+ const perChain = body?.status?.[d.chainId];
43949
+ if (!perChain) continue;
43950
+ const entry = Object.entries(perChain).find(
43951
+ ([addr3]) => addr3.toLowerCase() === d.module.toLowerCase()
43952
+ )?.[1];
43953
+ const rate = entry?.rate;
43954
+ if (typeof rate === "number" && Number.isFinite(rate)) {
43955
+ out[d.chainId] = aprFromRatePPM(rate);
43956
+ }
43931
43957
  }
43932
- return aprFromRatePPM(rate);
43958
+ return out;
43933
43959
  };
43934
43960
  var frankencoinSavingsFetcher = {
43935
43961
  label: "FRANKENCOIN_SAVINGS",
43936
43962
  fetch: async () => {
43937
- const legs = await Promise.allSettled([
43938
- fetchRateOnChain(),
43939
- fetchRateFromApi()
43963
+ const [chainLegs, apiLeg] = await Promise.all([
43964
+ Promise.allSettled(FRANKENCOIN_SAVINGS_MODULES.map(fetchRateOnChain)),
43965
+ fetchRatesFromApi().catch((e) => e)
43940
43966
  ]);
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 };
43967
+ const apiRates = apiLeg instanceof Error ? {} : apiLeg;
43968
+ const out = {};
43969
+ const failures = [];
43970
+ FRANKENCOIN_SAVINGS_MODULES.forEach((d, i) => {
43971
+ const leg = chainLegs[i];
43972
+ if (leg.status === "fulfilled") {
43973
+ out[zchfSavingsKey(d.chainId)] = leg.value;
43974
+ return;
43975
+ }
43976
+ const fromApi = apiRates[d.chainId];
43977
+ if (fromApi !== void 0) {
43978
+ out[zchfSavingsKey(d.chainId)] = fromApi;
43979
+ return;
43980
+ }
43981
+ failures.push(`${d.chainId}: ${String(leg.reason)}`);
43982
+ });
43983
+ if (Object.keys(out).length === 0) {
43984
+ throw new Error(
43985
+ `Frankencoin: every savings module failed (${failures.join("; ")}${apiLeg instanceof Error ? `; api: ${apiLeg.message}` : ""})`
43986
+ );
43948
43987
  }
43949
- throw new Error(
43950
- `Frankencoin: both rate legs failed (chain: ${String(
43951
- onChain.reason
43952
- )}; api: ${String(api.reason)})`
43953
- );
43988
+ return out;
43954
43989
  }
43955
43990
  };
43956
43991
 
@@ -45473,6 +45508,32 @@ var sparkV2Base = (symbol, decimals) => ({
45473
45508
  yieldFetcher: sparkSavingsFetcher
45474
45509
  });
45475
45510
  var SPARK_V2_WITHDRAW_INTENTS = "0x592b7db9906e6f8924c4d74c2a0ab86ce44fdddf";
45511
+ var frankencoinSavingsBase = {
45512
+ reader: "frankencoin-savings",
45513
+ symbol: "ZCHF",
45514
+ brand: "Frankencoin",
45515
+ 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.",
45516
+ decimals: 18,
45517
+ isRebasing: true,
45518
+ isMintable: true,
45519
+ withdrawalMode: "instant",
45520
+ // The exit is instant; the YIELD is not. `INTEREST_DELAY` is 3 days and a
45521
+ // top-up re-weights the whole position's clock, so a short stay earns zero.
45522
+ yieldWarmupSeconds: 3 * 86400,
45523
+ // `Δticks × saved / 1e6 / 365 days` — linear, compounding only when someone
45524
+ // calls `refresh`.
45525
+ accrual: "linear",
45526
+ // The module is a registered ZCHF minter, so the token already grants it an
45527
+ // implicit infinite allowance — verified on all three chains.
45528
+ needsDepositApproval: false,
45529
+ // Not an assumption: deposits are never lent on. They sit segregated inside
45530
+ // the module (`totalAssets` IS the module's own ZCHF balance) and the exit
45531
+ // is paid from it, so the PRINCIPAL is fully reserved rather than merely
45532
+ // over-collateralised. What is a claim on the protocol is the INTEREST,
45533
+ // which is minted on refresh — stated in the description.
45534
+ solvency: "overcollateralized",
45535
+ yieldFetcher: frankencoinSavingsFetcher
45536
+ };
45476
45537
  var ybMarket = (symbol, underlying, underlyingDecimals, address, capacityContract, yieldKey) => ({
45477
45538
  reader: "yieldbasis-lt",
45478
45539
  address,
@@ -46286,48 +46347,37 @@ var SINGLE_CHAIN_ENTRIES = {
46286
46347
  yieldKey: REUSDE_KEY
46287
46348
  },
46288
46349
  {
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.
46350
+ // Frankencoin savings module, Ethereum the reference deployment
46351
+ // and 89 % of the 13.66M ZCHF book. See `frankencoinSavingsBase`.
46303
46352
  //
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.
46353
+ // TRAP the published address config is stale HERE and only here.
46354
+ // `@frankencoin/zchf` exports `savingsV2 = 0x3BF301B0…`, which now
46355
+ // runs at 1 % and holds 17k ZCHF; the live module is the
46356
+ // `savingsReferral` deployment below, at 3.5 % holding 12.13M
46357
+ // (re-verified 2026-08-12, `currentRatePPM() = 35000`). Both
46358
+ // answer `currentRatePPM()`, so only the balance distinguishes
46359
+ // them. The bridged chains have no such split.
46360
+ ...frankencoinSavingsBase,
46361
+ address: FRANKENCOIN_SAVINGS_MODULES[0].module,
46362
+ underlying: ZCHF_ETHEREUM,
46363
+ yieldKey: zchfSavingsKey(Chain.ETHEREUM_MAINNET)
46364
+ }
46365
+ ],
46366
+ "100": [
46367
+ {
46368
+ // Frankencoin savings module, Gnosis — 1,257,396 ZCHF at
46369
+ // 2026-08-12, the second-largest after Ethereum and by far the
46370
+ // most active bridged chain (4,853 saves / 13,249 withdrawals).
46371
+ // Its own module contract with its own stored rate, kept at the
46372
+ // Ethereum 35 000 ppm by a CCIP leadrate push.
46313
46373
  //
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
46374
+ // 62.8 % of this book belongs to the `svZCHF` ERC-4626 wrapper —
46375
+ // see the warning on `frankencoinSavingsBase` before adding a row
46376
+ // for it.
46377
+ ...frankencoinSavingsBase,
46378
+ address: FRANKENCOIN_SAVINGS_MODULES[1].module,
46379
+ underlying: ZCHF_BRIDGED,
46380
+ yieldKey: zchfSavingsKey(Chain.GNOSIS)
46331
46381
  }
46332
46382
  ],
46333
46383
  "42161": [
@@ -46364,6 +46414,17 @@ var SINGLE_CHAIN_ENTRIES = {
46364
46414
  withdrawalMode: "request-based",
46365
46415
  yieldFetcher: yoFetcher,
46366
46416
  yieldKey: "Yield Optimizer ETH::YOETH"
46417
+ },
46418
+ {
46419
+ // Frankencoin savings module, Base — 255,196 ZCHF at 2026-08-12.
46420
+ // Note the module address is the SAME on Base and Optimism
46421
+ // (`0x6426324a…`, one CREATE2 family); the Optimism twin holds
46422
+ // 1 ZCHF and is deliberately unregistered — see
46423
+ // `FRANKENCOIN_SAVINGS_MODULES`.
46424
+ ...frankencoinSavingsBase,
46425
+ address: FRANKENCOIN_SAVINGS_MODULES[2].module,
46426
+ underlying: ZCHF_BRIDGED,
46427
+ yieldKey: zchfSavingsKey(Chain.BASE)
46367
46428
  }
46368
46429
  ],
46369
46430
  "43114": [
@@ -53716,7 +53777,7 @@ async function fetchVaultSupplyShares(chainId, core, entries, marketIdsByVault,
53716
53777
  });
53717
53778
  return map;
53718
53779
  }
53719
- function computeVaultAllocation(vaultAddress, decimals, totalAssetsFormatted, feePercent, priceUsd, marketIds, rateMap, positionMap, tokenList, uidCtx) {
53780
+ function computeVaultAllocation(vaultAddress, decimals, totalAssetsFormatted, feePercent2, priceUsd, marketIds, rateMap, positionMap, tokenList, uidCtx) {
53720
53781
  if (totalAssetsFormatted <= 0) {
53721
53782
  return { depositRate: 0, exposures: [], liquidityFormatted: 0 };
53722
53783
  }
@@ -53761,13 +53822,13 @@ function computeVaultAllocation(vaultAddress, decimals, totalAssetsFormatted, fe
53761
53822
  const grossApr = weighted / totalAssetsFormatted;
53762
53823
  const idle = Math.max(0, totalAssetsFormatted - allocated);
53763
53824
  return {
53764
- depositRate: grossApr * (1 - feePercent / 100),
53825
+ depositRate: grossApr * (1 - feePercent2 / 100),
53765
53826
  // Tag uninvested deposits as an idle entry so the breakdown sums to ~100%.
53766
53827
  exposures: withIdleExposure(exposures, totalAssetsFormatted, priceUsd),
53767
53828
  liquidityFormatted: Math.min(totalAssetsFormatted, idle + withdrawable)
53768
53829
  };
53769
53830
  }
53770
- function computeV2Allocation(decimals, totalAssetsFormatted, feePercent, priceUsd, marketAssetsRaw, rateMap, tokenList, uidCtx) {
53831
+ function computeV2Allocation(decimals, totalAssetsFormatted, feePercent2, priceUsd, marketAssetsRaw, rateMap, tokenList, uidCtx) {
53771
53832
  if (totalAssetsFormatted <= 0) {
53772
53833
  return { depositRate: 0, exposures: [], liquidityFormatted: 0 };
53773
53834
  }
@@ -53808,7 +53869,7 @@ function computeV2Allocation(decimals, totalAssetsFormatted, feePercent, priceUs
53808
53869
  const grossApr = weighted / totalAssetsFormatted;
53809
53870
  const idle = Math.max(0, totalAssetsFormatted - allocated);
53810
53871
  return {
53811
- depositRate: grossApr * (1 - feePercent / 100),
53872
+ depositRate: grossApr * (1 - feePercent2 / 100),
53812
53873
  exposures: withIdleExposure(exposures, totalAssetsFormatted, priceUsd),
53813
53874
  liquidityFormatted: Math.min(totalAssetsFormatted, idle + withdrawable)
53814
53875
  };
@@ -55028,7 +55089,7 @@ function safeBigInt(v) {
55028
55089
  return ZERO3;
55029
55090
  }
55030
55091
  }
55031
- function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent, evkIndex) {
55092
+ function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent2, evkIndex) {
55032
55093
  if (!strategies?.length) return 0;
55033
55094
  const totalAssets = safeBigInt(totalAssetsRaw);
55034
55095
  if (totalAssets === ZERO3) return 0;
@@ -55045,7 +55106,7 @@ function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent, evkInd
55045
55106
  if (weightedRay === ZERO3) return 0;
55046
55107
  const apyRayPerAsset = weightedRay / totalAssets;
55047
55108
  const grossPercent = apyToAprPercent(Number(apyRayPerAsset) / RAY_TO_PERCENT3);
55048
- const netPercent = grossPercent * (1 - feePercent / 100);
55109
+ const netPercent = grossPercent * (1 - feePercent2 / 100);
55049
55110
  return Number.isFinite(netPercent) ? netPercent : 0;
55050
55111
  }
55051
55112
  function computeRealLiquidity(strategies, totalAssetsRaw, evkIndex) {
@@ -61503,6 +61564,12 @@ var fetchSavingsVaults = async (chainId, multicallRetry, prices = {}, tokenList
61503
61564
  // queue window is per-asset and governance-mutable.
61504
61565
  withdrawalCooldownSeconds: state.withdrawalCooldownSeconds ?? entry.withdrawalCooldownSeconds,
61505
61566
  withdrawFeeBps: state.withdrawFeeBps,
61567
+ // Term-sheet inputs that no reader can derive — see the registry's
61568
+ // docstrings. Passed through verbatim so the sheet can stop hardcoding
61569
+ // "compounds per second" and "needs an approval" for every vault.
61570
+ yieldWarmupSeconds: entry.yieldWarmupSeconds,
61571
+ accrual: entry.accrual,
61572
+ needsDepositApproval: entry.needsDepositApproval,
61506
61573
  instantRedeemEnabled: state.instantRedeemEnabled,
61507
61574
  inventoryContract: entry.inventoryContract?.toLowerCase(),
61508
61575
  withdrawQueue: state.withdrawQueue ?? entry.withdrawQueue?.toLowerCase(),
@@ -64346,7 +64413,8 @@ function feePhrase(fee) {
64346
64413
  }
64347
64414
  const rebate = fee.value < 0 ? " rebate" : "";
64348
64415
  const qualifier = fee.indicative ? " (estimated, resolved at execution)" : "";
64349
- return `${fee.label}: ${amount3}${rebate}${qualifier}`;
64416
+ 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" : "";
64417
+ return `${fee.label}: ${amount3}${rebate}${bound}${qualifier}`;
64350
64418
  }
64351
64419
  function maturityPhrase(m) {
64352
64420
  if (m.kind === "fixed-date" && m.maturity)
@@ -64440,7 +64508,8 @@ function supplyHeadline(s) {
64440
64508
  const exit = exitPhrase[String(s.exit.mode)] ?? (s.exit.settlement === "sync" ? "withdraw any time" : "delayed withdrawal");
64441
64509
  const cooldown = s.exit.cooldownSecs ? ` (${duration(s.exit.cooldownSecs)})` : "";
64442
64510
  const mat = s.maturity.kind === "perpetual" ? "" : ` ${maturityPhrase(s.maturity)}`;
64443
- return `${rate}${mat} \xB7 ${exit}${cooldown}`;
64511
+ const warmup = s.rate.warmupSecs ? ` \xB7 earns after ${duration(s.rate.warmupSecs)}` : "";
64512
+ return `${rate}${mat}${warmup} \xB7 ${exit}${cooldown}`;
64444
64513
  }
64445
64514
  function borrowHeadline(b) {
64446
64515
  const rate = b.rate.kind === "zero-interest" ? "No ongoing interest" : b.rate.kind === "user-set" ? (
@@ -64744,7 +64813,8 @@ var TERM_PROFILES = [
64744
64813
  borrow: {
64745
64814
  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
64815
  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.",
64816
+ "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.",
64817
+ "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
64818
  "You pay a one-off upfront fee equal to roughly a week of interest at open, and again whenever you adjust the rate.",
64749
64819
  "There is a minimum debt size; you cannot leave a position below it."
64750
64820
  ]
@@ -64758,7 +64828,9 @@ var TERM_PROFILES = [
64758
64828
  description: "A CDP with NO ongoing interest. The entire borrowing cost is a one-off decaying mint fee charged at open.",
64759
64829
  implications: [
64760
64830
  "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."
64831
+ "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.",
64832
+ "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.",
64833
+ "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
64834
  ]
64763
64835
  }
64764
64836
  }),
@@ -64835,6 +64907,27 @@ var TERM_PROFILES = [
64835
64907
  ]
64836
64908
  }
64837
64909
  }),
64910
+ P({
64911
+ id: "morpho.blue@v1",
64912
+ name: "Morpho Blue isolated market",
64913
+ family: "morpho-blue",
64914
+ supply: {
64915
+ 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.",
64916
+ implications: [
64917
+ "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.",
64918
+ "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.",
64919
+ "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."
64920
+ ]
64921
+ },
64922
+ borrow: {
64923
+ description: "Borrow against a single collateral in an isolated market whose risk parameters are fixed at creation.",
64924
+ implications: [
64925
+ "Your liquidation threshold is the LLTV the market was created with and cannot be moved under you.",
64926
+ "There is no governance pause and no parameter rescue \u2014 the market runs as deployed."
64927
+ ]
64928
+ },
64929
+ docsUrl: "https://docs.morpho.org/morpho/concepts/markets"
64930
+ }),
64838
64931
  // ── Vaults ───────────────────────────────────────────────────────────────
64839
64932
  P({
64840
64933
  id: "vault.lending@v1",
@@ -65807,7 +65900,16 @@ function buildRate2(input, t, maturity) {
65807
65900
  },
65808
65901
  aprTotal: total,
65809
65902
  basis: "apr-nominal",
65810
- compounding: kind === "none" ? "none" : "per-second",
65903
+ // `per-second` is right for a vault whose share price grows continuously,
65904
+ // which is nearly all of them — but not for a LINEAR accrual. Frankencoin's
65905
+ // savings module books `Δticks × saved / 1e6 / 365 days` and only compounds
65906
+ // if someone happens to call `refresh`, so claiming per-second here would
65907
+ // imply an APY ~2 % relative above what it actually pays. Providers say so
65908
+ // through `accrual`.
65909
+ compounding: kind === "none" ? "none" : input.accrual === "linear" ? "none" : "per-second",
65910
+ // A warm-up is neither a withdrawal lock nor a governance notice period —
65911
+ // see `RateTerms.warmupSecs`. Absent ⇒ earns from the first block.
65912
+ warmupSecs: input.yieldWarmupSeconds && input.yieldWarmupSeconds > 0 ? input.yieldWarmupSeconds : void 0,
65811
65913
  source,
65812
65914
  // A PT's discount is fixed at purchase; every other vault floats.
65813
65915
  isLocked: kind === "fixed-term" && termIsBacked,
@@ -65988,7 +66090,13 @@ function buildAvailability2(input, now) {
65988
66090
  blockedBy,
65989
66091
  gating: gated ? "whitelist" : "permissionless",
65990
66092
  cap: cap != null && cap !== "0" ? cap : void 0,
65991
- requires: ["token-approval"],
66093
+ // Almost every vault pulls the deposit with `transferFrom` and therefore
66094
+ // needs an allowance — but not all. Frankencoin's savings modules are
66095
+ // registered ZCHF minters, and the token grants a registered minter an
66096
+ // implicit infinite allowance, so their deposit route emits NO approval.
66097
+ // Asserting one here would make the sheet contradict the envelope built
66098
+ // beside it, which is worse than saying nothing.
66099
+ requires: input.needsDepositApproval === false ? [] : ["token-approval"],
65992
66100
  opensWith: "standalone"
65993
66101
  };
65994
66102
  }
@@ -66441,9 +66549,29 @@ function earnLabel(dimension, key3) {
66441
66549
  function earnDescription(dimension, key3) {
66442
66550
  return EARN_DESCRIPTIONS[dimension][key3];
66443
66551
  }
66552
+ function stripBrandWords(name, venue) {
66553
+ const brandWords = new Set(
66554
+ (venue ? `${venueBrand(venue)} ${venueBrandKey(venue)}` : "").toLowerCase().split(/[^a-z0-9]+/).filter(Boolean)
66555
+ );
66556
+ const words = name.trim().split(/\s+/);
66557
+ let i = 0;
66558
+ while (i < words.length && brandWords.has(words[i].toLowerCase())) i++;
66559
+ return words.slice(i).join(" ").trim();
66560
+ }
66561
+ function namesToken(text, token) {
66562
+ const wanted = token.toLowerCase();
66563
+ return text.split(/[^a-zA-Z0-9]+/).some((t) => t.toLowerCase() === wanted);
66564
+ }
66444
66565
  function earnMarketLabel(input) {
66445
66566
  const asset = input.assetSymbol?.trim();
66446
66567
  if (!asset) return input.fallbackName ?? "";
66568
+ const detail = stripBrandWords(
66569
+ input.lenderMarketName?.trim() ?? "",
66570
+ input.venue
66571
+ );
66572
+ if (detail && detail.toLowerCase() !== asset.toLowerCase()) {
66573
+ return namesToken(detail, asset) ? detail : `${asset} \xB7 ${detail}`;
66574
+ }
66447
66575
  const collaterals = (input.collateralSymbols ?? []).map((c) => c?.trim()).filter((c) => !!c);
66448
66576
  const distinct = [...new Set(collaterals)];
66449
66577
  if (distinct.length === 1) return `${asset} \xB7 vs ${distinct[0]}`;
@@ -66854,6 +66982,9 @@ function toVaultTermInput(vault, provider, chainId) {
66854
66982
  swapFeeRate: num13(row.feeRate),
66855
66983
  redemptionDiscountBps: num13(row.redemptionDiscountBps),
66856
66984
  instantRedeemEnabled: bool2(row.instantRedeemEnabled),
66985
+ yieldWarmupSeconds: num13(row.yieldWarmupSeconds),
66986
+ accrual: str6(row.accrual),
66987
+ needsDepositApproval: bool2(row.needsDepositApproval),
66857
66988
  isMintable: bool2(row.isMintable),
66858
66989
  depositCapacity: str6(row.depositCapacity),
66859
66990
  supplyCap: str6(row.supplyCap),
@@ -66915,6 +67046,9 @@ function vaultTermInputFromEarnMarket(m) {
66915
67046
  swapFeeRate: num13(meta.feeRate),
66916
67047
  redemptionDiscountBps: num13(meta.redemptionDiscountBps),
66917
67048
  instantRedeemEnabled: bool2(meta.instantRedeemEnabled),
67049
+ yieldWarmupSeconds: num13(meta.yieldWarmupSeconds),
67050
+ accrual: str6(meta.accrual),
67051
+ needsDepositApproval: bool2(meta.needsDepositApproval),
66918
67052
  // `canDeposit` already folds in the cap, the pause and the gate, so it is
66919
67053
  // the authoritative answer — but the REASON is what a disabled CTA renders,
66920
67054
  // and that only survives in the raw fields.
@@ -66992,6 +67126,9 @@ function vaultTermInputFromSourceRow(row, chainId) {
66992
67126
  swapFeeRate: num13(meta.feeRate),
66993
67127
  redemptionDiscountBps: num13(meta.redemptionDiscountBps),
66994
67128
  instantRedeemEnabled: bool2(meta.instantRedeemEnabled),
67129
+ yieldWarmupSeconds: num13(meta.yieldWarmupSeconds),
67130
+ accrual: str6(meta.accrual),
67131
+ needsDepositApproval: bool2(meta.needsDepositApproval),
66995
67132
  isMintable: bool2(meta.isMintable),
66996
67133
  depositCapacity: str6(meta.depositCapacity) ?? str6(meta.maxDeposit),
66997
67134
  supplyCap: str6(meta.supplyCap),
@@ -67943,7 +68080,12 @@ var ROW_DESCRIPTOR_KEYS = [
67943
68080
  "curvance",
67944
68081
  "broker",
67945
68082
  "collateralProvider",
67946
- "loanProvider"
68083
+ "loanProvider",
68084
+ // Morpho Blue's protocol fee — the ONE parameter of an otherwise immutable
68085
+ // market that governance can move. Nested under `params.market` on the
68086
+ // in-package shape but a top-level field on `/pools/latest`, so without it
68087
+ // here the flat path reports a confident 0 % on every Blue market.
68088
+ "fee"
67947
68089
  ];
67948
68090
  function resolveMarketDescriptors(row, ctxMarket) {
67949
68091
  const fromParams = pick2(row, "params.market");
@@ -68601,6 +68743,7 @@ var liquityAdapter = {
68601
68743
  const minDebt = liquity.minDebt != null ? String(liquity.minDebt) : void 0;
68602
68744
  const minApr = typeof liquity.minAnnualInterestRate === "string" || typeof liquity.minAnnualInterestRate === "number" ? Number(liquity.minAnnualInterestRate) / 1e18 * 100 : void 0;
68603
68745
  const maxApr = typeof liquity.maxAnnualInterestRate === "string" || typeof liquity.maxAnnualInterestRate === "number" ? Number(liquity.maxAnnualInterestRate) / 1e18 * 100 : void 0;
68746
+ const shutdown = Boolean(liquity.shutdown);
68604
68747
  const wadPct = (v) => v == null ? void 0 : Number(v) / 1e18;
68605
68748
  const spPenalty = wadPct(liquity.liquidationPenaltySP);
68606
68749
  const redistPenalty = wadPct(liquity.liquidationPenaltyRedistribution);
@@ -68669,20 +68812,41 @@ var liquityAdapter = {
68669
68812
  penalties: penalties.length ? penalties : void 0,
68670
68813
  badDebt: "redistributed",
68671
68814
  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.
68815
+ // Two different mechanisms share the word "redemption", and the
68816
+ // ordinary one stops applying the moment a branch shuts down.
68817
+ //
68818
+ // NORMAL: rate-ordered, fee stays in the trove, borrower ~USD-neutral.
68819
+ // SHUTDOWN (TCR < SCR or oracle failure, permanent): **urgent
68820
+ // redemptions** run at a 2 % collateral BONUS to the redeemer, against
68821
+ // any trove — so the queue position a borrower bought with their rate
68822
+ // is worthless, and they are no longer neutral, they are down 2 %.
68823
+ //
68824
+ // Asserting the normal terms unconditionally told exactly the wrong
68825
+ // story to the only borrowers who could still act on it.
68826
+ redemption: shutdown ? {
68675
68827
  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.
68828
+ // No longer peg-driven: the 2 % bonus pays regardless.
68829
+ driver: "always",
68830
+ // Urgent redemptions ignore the interest-rate ordering.
68831
+ order: "pro-rata",
68832
+ valueImpact: "loss",
68833
+ 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."
68834
+ } : {
68835
+ // Not governance and not a liquidation: any holder of the
68836
+ // stable can trigger it, without permission.
68837
+ trigger: "permissionless-arbitrage",
68838
+ // Permissionless does NOT mean constant — it only pays while
68839
+ // the stable trades under target, which is the point:
68840
+ // redemptions are what push it back up.
68678
68841
  driver: "below-peg",
68679
68842
  // The rate you chose IS your position in the queue.
68680
68843
  order: "lowest-rate-first",
68681
- // The redemption fee stays in the position as extra collateral, so
68844
+ // The redemption fee stays in the trove as extra collateral, so
68682
68845
  // the borrower is ~USD-neutral; what is lost is EXPOSURE.
68683
68846
  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."
68847
+ // The ordering is already stated by `order`; say what to DO
68848
+ // including the trap that follows a partial redemption.
68849
+ 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
68850
  }
68687
68851
  },
68688
68852
  counterparty: { kind: "cdp", solvency: "overcollateralized" }
@@ -68719,14 +68883,28 @@ var riverAdapter = {
68719
68883
  seizure: "proportional",
68720
68884
  redeemable: true,
68721
68885
  redemption: {
68722
- // Not governance and not a liquidation: any holder of the stable may
68723
- // redeem it for collateral at any time.
68886
+ // Not governance and not a liquidation: any holder of the stable can
68887
+ // trigger it, without permission and without targeting anyone.
68724
68888
  trigger: "permissionless-arbitrage",
68889
+ // Permissionless does NOT mean constant: it only pays the redeemer
68890
+ // while the stable trades under target, which is what makes it a peg
68891
+ // defence rather than a standing claim on collateral.
68725
68892
  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."
68893
+ // COLLATERAL-RATIO ordered, V1-style — NOT rate-ordered.
68894
+ //
68895
+ // This said `lowest-rate-first`, copied from the Liquity V2 shape,
68896
+ // and it was wrong twice over: River is Prisma/V1 lineage, which
68897
+ // redeems against the LOWEST-COLLATERALISED troves first, and River
68898
+ // charges no interest at all (`rate.kind: 'zero-interest'` above), so
68899
+ // the accompanying "raise your rate" advice pointed at a control that
68900
+ // does not exist on this protocol. A borrower following it would have
68901
+ // done nothing while sitting first in the real queue.
68902
+ order: "lowest-collateral-ratio",
68903
+ // Deliberately ABSENT rather than `usd-neutral`. The V1 mechanism
68904
+ // sends collateral above the redeemed debt to a surplus balance that
68905
+ // the borrower must CLAIM, so whether they end up whole depends on an
68906
+ // action they may not know to take — see `defence`.
68907
+ 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
68908
  }
68731
68909
  },
68732
68910
  counterparty: { kind: "cdp", solvency: "overcollateralized" }
@@ -69040,7 +69218,18 @@ var resupplyAdapter = {
69040
69218
  // rate to raise. Offering "raise your rate" here would be actively
69041
69219
  // misleading.
69042
69220
  order: "pro-rata",
69043
- valueImpact: "usd-neutral"
69221
+ // `valueImpact` deliberately ABSENT — it is NOT `usd-neutral`.
69222
+ //
69223
+ // That was carried over from Liquity, where the redemption fee stays
69224
+ // IN the trove as extra collateral and leaves the borrower roughly
69225
+ // whole. Resupply does the opposite: `redeemCollateral` takes a 1 %
69226
+ // base fee with half of it going to the protocol, and writes the
69227
+ // collateral off across the pair via a `WriteOffToken` — so nothing
69228
+ // is credited back to the borrower and there is no surplus to claim.
69229
+ // Whether they end up neutral is not something we have established,
69230
+ // and an absent field says that where `usd-neutral` would have
69231
+ // promised it.
69232
+ 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
69233
  },
69045
69234
  badDebt: "socialized"
69046
69235
  },
@@ -69188,6 +69377,54 @@ var fraxlendAdapter = {
69188
69377
  }
69189
69378
  })
69190
69379
  };
69380
+ var MORPHO_BLUE_MAX_FEE_PERCENT = 25;
69381
+ function feePercent(raw) {
69382
+ if (raw == null) return void 0;
69383
+ const n = typeof raw === "string" ? Number(raw) : raw;
69384
+ if (!Number.isFinite(n) || n <= 0) return void 0;
69385
+ return n > 1 ? n / 1e18 * 100 : n * 100;
69386
+ }
69387
+ var morphoBlueAdapter = {
69388
+ id: "morpho-blue",
69389
+ matches: (lender) => isMorphoBlue(lender),
69390
+ profileId: () => "morpho.blue@v1",
69391
+ build: (input) => {
69392
+ const market = input.market ?? {};
69393
+ const fee = feePercent(market.fee);
69394
+ return {
69395
+ governance: {
69396
+ mutability: "immutable",
69397
+ // The ONE power that reaches an existing market. Listing the full owner
69398
+ // surface here would imply `enableLltv` could change THIS market's LLTV,
69399
+ // which is the misreading the whole adapter exists to prevent.
69400
+ powers: ["change-fees"]
69401
+ },
69402
+ supply: {
69403
+ // Stated as a FEE rather than left as a bare governance power, so the
69404
+ // bound travels with it: the number a supplier is exposed to is "0 %
69405
+ // today, never above 25 %", which a `change-fees` enum cannot express.
69406
+ //
69407
+ // Emitted even at 0 — the current Morpho default — because "this market
69408
+ // charges no fee, and the most it could ever charge is 25 %" is the
69409
+ // whole point, and an absent row would leave the power unexplained.
69410
+ fees: [
69411
+ {
69412
+ id: "reserve-factor",
69413
+ label: "Protocol fee on interest",
69414
+ when: "ongoing",
69415
+ unit: "percent",
69416
+ basis: "yield",
69417
+ value: fee ?? 0,
69418
+ payee: "protocol",
69419
+ mutable: true,
69420
+ cap: MORPHO_BLUE_MAX_FEE_PERCENT,
69421
+ 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."
69422
+ }
69423
+ ]
69424
+ }
69425
+ };
69426
+ }
69427
+ };
69191
69428
 
69192
69429
  // src/terms/adapters/index.ts
69193
69430
  var TERM_ADAPTERS = [
@@ -69208,7 +69445,8 @@ var TERM_ADAPTERS = [
69208
69445
  frankencoinAdapter,
69209
69446
  resupplyAdapter,
69210
69447
  curvanceAdapter,
69211
- fraxlendAdapter
69448
+ fraxlendAdapter,
69449
+ morphoBlueAdapter
69212
69450
  ];
69213
69451
  function resolveAdapter(lender) {
69214
69452
  return TERM_ADAPTERS.find((a) => a.matches(lender));
@@ -69374,7 +69612,9 @@ function enrichTermSheet(sheet, index) {
69374
69612
  }
69375
69613
  const govRow = index.governanceByMarketUid?.get(uid);
69376
69614
  if (govRow) {
69377
- const immutable = govRow.mode === "immutable";
69615
+ const assertedImmutable = sheet.governance?.mutability === "immutable";
69616
+ const immutable = govRow.mode === "immutable" || assertedImmutable;
69617
+ const adapterPowers = assertedImmutable ? sheet.governance?.powers : void 0;
69378
69618
  sheet.governance = {
69379
69619
  ...sheet.governance,
69380
69620
  mutability: immutable ? "immutable" : "governed",
@@ -69392,7 +69632,8 @@ function enrichTermSheet(sheet, index) {
69392
69632
  };
69393
69633
  if (immutable) {
69394
69634
  sheet.governance.timelockSecs = void 0;
69395
- sheet.governance.powers = void 0;
69635
+ sheet.governance.timelockUnknown = void 0;
69636
+ sheet.governance.powers = adapterPowers;
69396
69637
  }
69397
69638
  }
69398
69639
  const quality = index.assetRisk;
@@ -69622,8 +69863,12 @@ function validateTermSheet(sheet) {
69622
69863
  "immutable-timelock",
69623
69864
  "immutable governance must not carry a timelock"
69624
69865
  );
69625
- if (g.powers?.length)
69626
- fail("immutable-powers", "immutable governance must not carry powers");
69866
+ const disallowed = (g.powers ?? []).filter((p) => p !== "change-fees");
69867
+ if (disallowed.length)
69868
+ fail(
69869
+ "immutable-powers",
69870
+ `immutable governance must not carry powers: ${disallowed.join(", ")}`
69871
+ );
69627
69872
  }
69628
69873
  if (g.timelockSecs && g.controllerKind && g.controllerKind !== "TIMELOCK" && g.timelockSource !== "on-chain")
69629
69874
  fail(
@@ -69661,7 +69906,27 @@ var USER_SET_RATE_PREFIXES = [
69661
69906
  "SONETA",
69662
69907
  "EBISU"
69663
69908
  ];
69664
- function earnMarketFromPool(row, fallbackChainId) {
69909
+ function collateralSymbolsByVenue(rows, fallbackChainId) {
69910
+ const byVenue = /* @__PURE__ */ new Map();
69911
+ for (const row of rows) {
69912
+ const venue = str5(row.lender) ?? str5(row.lenderKey);
69913
+ const chainId = str5(row.chainId) ?? fallbackChainId;
69914
+ if (!venue || !chainId) continue;
69915
+ const collateralActive = row.flags?.collateralActive ?? row.collateralActive;
69916
+ if (collateralActive !== true) continue;
69917
+ const symbol = str5(row.underlyingInfo?.asset?.symbol) ?? str5(row.asset?.symbol);
69918
+ if (!symbol) continue;
69919
+ const key3 = venueGroupKey(chainId, venue);
69920
+ let set = byVenue.get(key3);
69921
+ if (!set) byVenue.set(key3, set = /* @__PURE__ */ new Set());
69922
+ set.add(symbol);
69923
+ }
69924
+ return new Map([...byVenue].map(([key3, set]) => [key3, [...set]]));
69925
+ }
69926
+ function venueGroupKey(chainId, venue) {
69927
+ return `${chainId}::${venue}`;
69928
+ }
69929
+ function earnMarketFromPool(row, fallbackChainId, venueCollaterals) {
69665
69930
  const marketUid = str5(row.marketUid);
69666
69931
  if (!marketUid) return void 0;
69667
69932
  let earnUid;
@@ -69709,7 +69974,21 @@ function earnMarketFromPool(row, fallbackChainId) {
69709
69974
  // across the listing: the STABLE family key, never the per-market venue.
69710
69975
  // No lender publishes a curator today, hence the undefined.
69711
69976
  ...resolveEarnIdentity(venue, void 0),
69712
- name: str5(row.name),
69977
+ // Pair-aware: "USDT · vs wstETH" for an isolated market, plain "USDC" for
69978
+ // a shared pool. The fetcher's own name is only the fallback — it is the
69979
+ // leg-local "Loan USDC", which a chain repeats across 300 markets and
69980
+ // which says nothing about WHICH market this is. Identical to what the
69981
+ // origin's SQL route builds, so both paths agree.
69982
+ name: earnMarketLabel({
69983
+ assetSymbol: str5(assetInfo.symbol),
69984
+ lenderMarketName: str5(row.lenderInfo?.name),
69985
+ venue,
69986
+ // Minus this row's own leg: on the COLLATERAL row of an isolated market
69987
+ // the only collateral is itself, and "cbBTC · vs cbBTC" is nonsense.
69988
+ // Removing it leaves zero, i.e. the plain name — correct.
69989
+ collateralSymbols: venueCollaterals?.get(venueGroupKey(chainId, venue))?.filter((c) => c !== str5(assetInfo.symbol)),
69990
+ fallbackName: str5(row.name)
69991
+ }),
69713
69992
  // Never re-derived — the uid's third segment as the origin minted it.
69714
69993
  ref: marketUid.split(":")[2],
69715
69994
  logoURI: str5(assetInfo.logoURI),
@@ -70027,7 +70306,13 @@ function legAsset(pos) {
70027
70306
  );
70028
70307
  const decimals = typeof asset.decimals === "number" ? asset.decimals : void 0;
70029
70308
  const symbol = typeof asset.symbol === "string" ? asset.symbol : void 0;
70030
- return { address, symbol, decimals };
70309
+ const logoURI = typeof asset.logoURI === "string" ? asset.logoURI : void 0;
70310
+ return {
70311
+ address,
70312
+ symbol,
70313
+ decimals,
70314
+ ...logoURI ? { logoURI } : {}
70315
+ };
70031
70316
  }
70032
70317
  function toLeg(pos) {
70033
70318
  const depositsUsd = num15(pos.depositsUSD);
@@ -70039,7 +70324,9 @@ function toLeg(pos) {
70039
70324
  marketUid: pos.marketUid,
70040
70325
  ...pos.loanId ? { loanId: pos.loanId } : {},
70041
70326
  asset: legAsset(pos),
70042
- side: hasSupply && hasDebt ? "both" : hasDebt ? "borrow" : "supply",
70327
+ // An empty market is `'none'`, NOT `'supply'` the old fallback quietly
70328
+ // reported every market the account was merely configured in as a holding.
70329
+ side: hasSupply && hasDebt ? "both" : hasDebt ? "borrow" : hasSupply ? "supply" : "none",
70043
70330
  deposits: pos.deposits ?? "0",
70044
70331
  depositsUsd,
70045
70332
  debt: pos.debt ?? "0",
@@ -70067,10 +70354,17 @@ function earnPositionFromLenderEntry(entry) {
70067
70354
  legs
70068
70355
  };
70069
70356
  });
70070
- const active = subAccounts.filter((s) => s.legs.length > 0 || s.netUsd !== 0);
70357
+ const active = subAccounts.filter(
70358
+ (s) => s.legs.some((l) => l.side !== "none") || s.netUsd !== 0
70359
+ );
70071
70360
  const crossMargin = active.length <= 1;
70072
70361
  const suppliedUsd = num15(entry.balanceData?.deposits);
70073
70362
  const borrowedUsd = num15(entry.balanceData?.debt);
70363
+ const aprBreakdown = {
70364
+ market: num15(entry.aprData?.apr),
70365
+ rewards: num15(entry.aprData?.rewardApr),
70366
+ intrinsic: num15(entry.aprData?.intrinsicApr)
70367
+ };
70074
70368
  return {
70075
70369
  positionUid: buildLendingPositionUid(entry.lender, entry.chainId),
70076
70370
  chainId: entry.chainId,
@@ -70084,7 +70378,8 @@ function earnPositionFromLenderEntry(entry) {
70084
70378
  suppliedUsd,
70085
70379
  borrowedUsd,
70086
70380
  netUsd: num15(entry.balanceData?.nav),
70087
- apr: num15(entry.aprData?.apr),
70381
+ apr: aprBreakdown.market + aprBreakdown.rewards + aprBreakdown.intrinsic,
70382
+ aprBreakdown,
70088
70383
  depositApr: num15(entry.aprData?.depositApr),
70089
70384
  borrowApr: num15(entry.aprData?.borrowApr),
70090
70385
  // Only a cross-margin account HAS one health factor. Publishing the first
@@ -70172,6 +70467,6 @@ function earnPositionTotals(items) {
70172
70467
  };
70173
70468
  }
70174
70469
 
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 };
70470
+ 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
70471
  //# sourceMappingURL=index.js.map
70177
70472
  //# sourceMappingURL=index.js.map