@1delta/margin-fetcher 5.0.28 → 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.d.ts +624 -30
- package/dist/index.js +677 -163
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
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
|
}
|
|
@@ -21931,7 +21934,7 @@ async function fetchTellerMarkets(chainId) {
|
|
|
21931
21934
|
}
|
|
21932
21935
|
return null;
|
|
21933
21936
|
};
|
|
21934
|
-
const
|
|
21937
|
+
const num16 = (i) => {
|
|
21935
21938
|
const b = big18(i);
|
|
21936
21939
|
return b === null ? null : Number(b);
|
|
21937
21940
|
};
|
|
@@ -21941,9 +21944,9 @@ async function fetchTellerMarkets(chainId) {
|
|
|
21941
21944
|
config,
|
|
21942
21945
|
available: big18(base),
|
|
21943
21946
|
committed: big18(base + 1),
|
|
21944
|
-
minRateBps:
|
|
21947
|
+
minRateBps: num16(base + 2),
|
|
21945
21948
|
collateralPerPrincipal: big18(base + 3),
|
|
21946
|
-
maxLoanDuration:
|
|
21949
|
+
maxLoanDuration: num16(base + 4),
|
|
21947
21950
|
marketId: big18(base + 5),
|
|
21948
21951
|
totalAssets: big18(base + 6)
|
|
21949
21952
|
};
|
|
@@ -22906,20 +22909,20 @@ async function fetchInverseMarkets(lender, chainId) {
|
|
|
22906
22909
|
if (Object.keys(byAddr).length > 0) {
|
|
22907
22910
|
const rows = markets.map((market) => {
|
|
22908
22911
|
const m = byAddr[market.address.toLowerCase()];
|
|
22909
|
-
const
|
|
22912
|
+
const num16 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
22910
22913
|
return {
|
|
22911
22914
|
market,
|
|
22912
|
-
totalDebt:
|
|
22913
|
-
dolaLiquidity:
|
|
22914
|
-
leftToBorrow:
|
|
22915
|
-
price:
|
|
22915
|
+
totalDebt: num16(m?.totalDebt),
|
|
22916
|
+
dolaLiquidity: num16(m?.dolaLiquidity),
|
|
22917
|
+
leftToBorrow: num16(m?.leftToBorrow),
|
|
22918
|
+
price: num16(m?.price),
|
|
22916
22919
|
borrowPaused: typeof m?.borrowPaused === "boolean" ? m.borrowPaused : null,
|
|
22917
|
-
dailyBorrows:
|
|
22920
|
+
dailyBorrows: num16(m?.dailyBorrows),
|
|
22918
22921
|
// The API serves it as a DECIMAL (`replenishmentIncentive: 0.1`),
|
|
22919
22922
|
// unlike the on-chain bps — normalize here, and fall back to the
|
|
22920
22923
|
// curated metadata value when the field is missing.
|
|
22921
22924
|
replenishmentIncentiveBps: (() => {
|
|
22922
|
-
const dec2 =
|
|
22925
|
+
const dec2 = num16(m?.replenishmentIncentive);
|
|
22923
22926
|
if (dec2 !== null) return Math.round(dec2 * 1e4);
|
|
22924
22927
|
const meta = Number(market.replenishmentIncentiveBps);
|
|
22925
22928
|
return Number.isFinite(meta) ? meta : null;
|
|
@@ -43887,7 +43890,27 @@ var usddFetcher = {
|
|
|
43887
43890
|
return out;
|
|
43888
43891
|
}
|
|
43889
43892
|
};
|
|
43890
|
-
var
|
|
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:
|
|
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(
|
|
43935
|
+
throw new Error(`Frankencoin: unreadable currentRatePPM() on ${d.chainId}`);
|
|
43918
43936
|
}
|
|
43919
43937
|
return aprFromRatePPM(ppm);
|
|
43920
43938
|
};
|
|
43921
|
-
var
|
|
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
|
|
43929
|
-
|
|
43930
|
-
|
|
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
|
|
43958
|
+
return out;
|
|
43933
43959
|
};
|
|
43934
43960
|
var frankencoinSavingsFetcher = {
|
|
43935
43961
|
label: "FRANKENCOIN_SAVINGS",
|
|
43936
43962
|
fetch: async () => {
|
|
43937
|
-
const
|
|
43938
|
-
fetchRateOnChain
|
|
43939
|
-
|
|
43963
|
+
const [chainLegs, apiLeg] = await Promise.all([
|
|
43964
|
+
Promise.allSettled(FRANKENCOIN_SAVINGS_MODULES.map(fetchRateOnChain)),
|
|
43965
|
+
fetchRatesFromApi().catch((e) => e)
|
|
43940
43966
|
]);
|
|
43941
|
-
const
|
|
43942
|
-
|
|
43943
|
-
|
|
43944
|
-
|
|
43945
|
-
|
|
43946
|
-
|
|
43947
|
-
|
|
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
|
-
|
|
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 —
|
|
46290
|
-
//
|
|
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.
|
|
46350
|
+
// Frankencoin savings module, Ethereum — the reference deployment
|
|
46351
|
+
// and 89 % of the 13.66M ZCHF book. See `frankencoinSavingsBase`.
|
|
46296
46352
|
//
|
|
46297
|
-
// TRAP — the published address config is stale.
|
|
46298
|
-
// exports `savingsV2 = 0x3BF301B0…`, which now
|
|
46299
|
-
// holds 17k ZCHF; the live module is the
|
|
46300
|
-
// deployment below, at 3.5 % holding 12.
|
|
46301
|
-
// 2026-08-
|
|
46302
|
-
// `currentRatePPM()`, so only the balance distinguishes
|
|
46303
|
-
//
|
|
46304
|
-
|
|
46305
|
-
|
|
46306
|
-
|
|
46307
|
-
|
|
46308
|
-
|
|
46309
|
-
|
|
46310
|
-
|
|
46311
|
-
|
|
46312
|
-
//
|
|
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
|
-
//
|
|
46315
|
-
//
|
|
46316
|
-
//
|
|
46317
|
-
|
|
46318
|
-
|
|
46319
|
-
|
|
46320
|
-
|
|
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,
|
|
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 -
|
|
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,
|
|
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 -
|
|
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,
|
|
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 -
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|
|
@@ -66281,8 +66389,6 @@ function splitUid(uid) {
|
|
|
66281
66389
|
if (!venue || !chainId || !ref) return void 0;
|
|
66282
66390
|
return { venue, chainId, ref };
|
|
66283
66391
|
}
|
|
66284
|
-
|
|
66285
|
-
// src/earn/labels.ts
|
|
66286
66392
|
var VENUE_KIND_LABELS = {
|
|
66287
66393
|
lending: "Lending markets",
|
|
66288
66394
|
vault: "Vaults"
|
|
@@ -66350,38 +66456,40 @@ var RATE_SOURCE_LABELS = {
|
|
|
66350
66456
|
oracle: "Oracle",
|
|
66351
66457
|
realized: "Realized"
|
|
66352
66458
|
};
|
|
66353
|
-
var
|
|
66354
|
-
|
|
66355
|
-
|
|
66356
|
-
|
|
66357
|
-
|
|
66358
|
-
|
|
66359
|
-
|
|
66360
|
-
|
|
66361
|
-
SKY: "Sky",
|
|
66362
|
-
USDD: "USDD",
|
|
66363
|
-
LIQUITY_V2: "Liquity V2",
|
|
66364
|
-
SILO_V2: "Silo V2",
|
|
66365
|
-
SILO_V3: "Silo V3",
|
|
66366
|
-
EXACTLY: "Exactly",
|
|
66367
|
-
TELLER: "Teller",
|
|
66368
|
-
TERM_FINANCE: "Term Finance",
|
|
66369
|
-
TERMMAX: "TermMax",
|
|
66370
|
-
LLAMALEND: "LlamaLend",
|
|
66371
|
-
CURVANCE: "Curvance",
|
|
66372
|
-
INVERSE: "Inverse",
|
|
66373
|
-
FRANKENCOIN: "Frankencoin",
|
|
66374
|
-
RIVER: "River",
|
|
66375
|
-
RESUPPLY: "Resupply",
|
|
66376
|
-
TANGENT: "Tangent",
|
|
66377
|
-
DOLOMITE: "Dolomite",
|
|
66459
|
+
var SYNTHETIC_FAMILIES = ["AAVE_V4", "COMPOUND_V3", "SWAYLEND"];
|
|
66460
|
+
var FAMILY_KEYS = [
|
|
66461
|
+
.../* @__PURE__ */ new Set([
|
|
66462
|
+
...Object.values(Lender),
|
|
66463
|
+
...SYNTHETIC_FAMILIES
|
|
66464
|
+
])
|
|
66465
|
+
].sort((a, b) => a.length - b.length || a.localeCompare(b));
|
|
66466
|
+
var BRAND_OVERRIDES = {
|
|
66378
66467
|
LISTA_DAO: "Lista",
|
|
66379
66468
|
FLUX_FINANCE: "Flux",
|
|
66380
|
-
|
|
66381
|
-
|
|
66382
|
-
|
|
66383
|
-
|
|
66384
|
-
|
|
66469
|
+
TERMMAX: "TermMax",
|
|
66470
|
+
LLAMALEND: "LlamaLend",
|
|
66471
|
+
USDD: "USDD",
|
|
66472
|
+
USDAF: "USDaf",
|
|
66473
|
+
DTRINITY: "dTRINITY",
|
|
66474
|
+
DFORCE: "dForce",
|
|
66475
|
+
OVIX: "0VIX",
|
|
66476
|
+
WE_PIGGY: "WePiggy",
|
|
66477
|
+
ZEROLEND: "ZeroLend",
|
|
66478
|
+
HYPERLEND: "HyperLend",
|
|
66479
|
+
HYPURRFI: "HypurrFi",
|
|
66480
|
+
HYPERYIELD: "HyperYield",
|
|
66481
|
+
LAYERBANK_V3: "LayerBank V3",
|
|
66482
|
+
TAKOTAKO: "TakoTako",
|
|
66483
|
+
SWAYLEND: "Swaylend",
|
|
66484
|
+
BENQI: "BENQI",
|
|
66485
|
+
YLDR: "YLDR",
|
|
66486
|
+
YEI: "YEI",
|
|
66487
|
+
RMM: "RMM",
|
|
66488
|
+
PAC: "PAC"
|
|
66489
|
+
};
|
|
66490
|
+
function titleCaseKey(key3) {
|
|
66491
|
+
return key3.split(/[_-]/).filter(Boolean).map((s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase()).join(" ");
|
|
66492
|
+
}
|
|
66385
66493
|
var VAULT_PROVIDER_BRANDS = {
|
|
66386
66494
|
fluid: "Fluid",
|
|
66387
66495
|
gearbox: "Gearbox",
|
|
@@ -66405,21 +66513,23 @@ function isInstanceSegment(seg) {
|
|
|
66405
66513
|
if (/^0X[0-9A-F]+$/i.test(seg)) return true;
|
|
66406
66514
|
return seg.length >= 8 && /^[0-9A-F]+$/i.test(seg);
|
|
66407
66515
|
}
|
|
66408
|
-
function
|
|
66409
|
-
if (venue.startsWith(
|
|
66410
|
-
|
|
66411
|
-
|
|
66516
|
+
function venueBrandKey(venue) {
|
|
66517
|
+
if (venue.startsWith(VAULT_VENUE_PREFIX)) return venue;
|
|
66518
|
+
const key3 = venue.toUpperCase();
|
|
66519
|
+
for (const family of FAMILY_KEYS) {
|
|
66520
|
+
if (key3 === family || key3.startsWith(family + "_")) return family;
|
|
66412
66521
|
}
|
|
66413
|
-
const segments =
|
|
66522
|
+
const segments = key3.split("_");
|
|
66414
66523
|
const cut = segments.findIndex(isInstanceSegment);
|
|
66415
|
-
|
|
66416
|
-
|
|
66417
|
-
|
|
66418
|
-
|
|
66419
|
-
|
|
66420
|
-
|
|
66524
|
+
return (cut > 0 ? segments.slice(0, cut) : segments).join("_");
|
|
66525
|
+
}
|
|
66526
|
+
function venueBrand(venue) {
|
|
66527
|
+
if (venue.startsWith(VAULT_VENUE_PREFIX)) {
|
|
66528
|
+
const provider = venue.slice(VAULT_VENUE_PREFIX.length);
|
|
66529
|
+
return VAULT_PROVIDER_BRANDS[provider] ?? titleCaseKey(provider);
|
|
66421
66530
|
}
|
|
66422
|
-
|
|
66531
|
+
const family = venueBrandKey(venue);
|
|
66532
|
+
return BRAND_OVERRIDES[family] ?? titleCaseKey(family);
|
|
66423
66533
|
}
|
|
66424
66534
|
var EARN_LABELS = {
|
|
66425
66535
|
venueKind: VENUE_KIND_LABELS,
|
|
@@ -66439,9 +66549,29 @@ function earnLabel(dimension, key3) {
|
|
|
66439
66549
|
function earnDescription(dimension, key3) {
|
|
66440
66550
|
return EARN_DESCRIPTIONS[dimension][key3];
|
|
66441
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
|
+
}
|
|
66442
66565
|
function earnMarketLabel(input) {
|
|
66443
66566
|
const asset = input.assetSymbol?.trim();
|
|
66444
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
|
+
}
|
|
66445
66575
|
const collaterals = (input.collateralSymbols ?? []).map((c) => c?.trim()).filter((c) => !!c);
|
|
66446
66576
|
const distinct = [...new Set(collaterals)];
|
|
66447
66577
|
if (distinct.length === 1) return `${asset} \xB7 vs ${distinct[0]}`;
|
|
@@ -66458,6 +66588,21 @@ function isIlliquid(input) {
|
|
|
66458
66588
|
if (input.liquidityUsd === void 0) return false;
|
|
66459
66589
|
return input.liquidityUsd <= 0;
|
|
66460
66590
|
}
|
|
66591
|
+
var CATEGORY_PROVIDERS = /* @__PURE__ */ new Set(["savings", "lst"]);
|
|
66592
|
+
function resolveEarnIdentity(venue, brand) {
|
|
66593
|
+
const isVault = venue.startsWith(VAULT_VENUE_PREFIX);
|
|
66594
|
+
const provider = isVault ? venue.slice(VAULT_VENUE_PREFIX.length) : venue;
|
|
66595
|
+
const providerBrand = venueBrand(venue);
|
|
66596
|
+
const key3 = venueBrandKey(venue);
|
|
66597
|
+
if (isVault && CATEGORY_PROVIDERS.has(provider)) {
|
|
66598
|
+
return { protocol: { key: key3, name: brand?.trim() || providerBrand } };
|
|
66599
|
+
}
|
|
66600
|
+
const name = brand?.trim();
|
|
66601
|
+
if (!name || name.toLowerCase() === providerBrand.toLowerCase()) {
|
|
66602
|
+
return { protocol: { key: key3, name: providerBrand } };
|
|
66603
|
+
}
|
|
66604
|
+
return { protocol: { key: key3, name: providerBrand }, curator: { name } };
|
|
66605
|
+
}
|
|
66461
66606
|
|
|
66462
66607
|
// src/earn/normalize.ts
|
|
66463
66608
|
function num12(v) {
|
|
@@ -66604,6 +66749,15 @@ function earnMarketFromVault(row, chainId, opts = {}) {
|
|
|
66604
66749
|
venueKind: "vault",
|
|
66605
66750
|
// Curator first (it names the actual operator), then the provider brand.
|
|
66606
66751
|
brand: str5(row.curatorName) ?? venueBrand(vaultVenue(provider)),
|
|
66752
|
+
// What the vault is BUILT ON, kept apart from who runs it — see
|
|
66753
|
+
// `resolveEarnIdentity` for why this is not simply provider-vs-brand.
|
|
66754
|
+
...withCuratorEntity(
|
|
66755
|
+
resolveEarnIdentity(
|
|
66756
|
+
vaultVenue(provider),
|
|
66757
|
+
str5(row.curatorName)
|
|
66758
|
+
),
|
|
66759
|
+
str5(row.curatorEntity)
|
|
66760
|
+
),
|
|
66607
66761
|
name: str5(info.name) ?? str5(row.displayName) ?? str5(row.name),
|
|
66608
66762
|
ref: address,
|
|
66609
66763
|
logoURI: str5(info.logoURI) ?? str5(row.underlyingInfo?.asset?.logoURI),
|
|
@@ -66739,6 +66893,10 @@ function amount(raw, formatted, usd, decimals) {
|
|
|
66739
66893
|
usd: num12(usd)
|
|
66740
66894
|
};
|
|
66741
66895
|
}
|
|
66896
|
+
function withCuratorEntity(id, entity) {
|
|
66897
|
+
if (!id.curator || !entity) return id;
|
|
66898
|
+
return { ...id, curator: { ...id.curator, entity } };
|
|
66899
|
+
}
|
|
66742
66900
|
function sum(a, b) {
|
|
66743
66901
|
if (a === void 0 && b === void 0) return void 0;
|
|
66744
66902
|
return (a ?? 0) + (b ?? 0);
|
|
@@ -66824,6 +66982,9 @@ function toVaultTermInput(vault, provider, chainId) {
|
|
|
66824
66982
|
swapFeeRate: num13(row.feeRate),
|
|
66825
66983
|
redemptionDiscountBps: num13(row.redemptionDiscountBps),
|
|
66826
66984
|
instantRedeemEnabled: bool2(row.instantRedeemEnabled),
|
|
66985
|
+
yieldWarmupSeconds: num13(row.yieldWarmupSeconds),
|
|
66986
|
+
accrual: str6(row.accrual),
|
|
66987
|
+
needsDepositApproval: bool2(row.needsDepositApproval),
|
|
66827
66988
|
isMintable: bool2(row.isMintable),
|
|
66828
66989
|
depositCapacity: str6(row.depositCapacity),
|
|
66829
66990
|
supplyCap: str6(row.supplyCap),
|
|
@@ -66885,6 +67046,9 @@ function vaultTermInputFromEarnMarket(m) {
|
|
|
66885
67046
|
swapFeeRate: num13(meta.feeRate),
|
|
66886
67047
|
redemptionDiscountBps: num13(meta.redemptionDiscountBps),
|
|
66887
67048
|
instantRedeemEnabled: bool2(meta.instantRedeemEnabled),
|
|
67049
|
+
yieldWarmupSeconds: num13(meta.yieldWarmupSeconds),
|
|
67050
|
+
accrual: str6(meta.accrual),
|
|
67051
|
+
needsDepositApproval: bool2(meta.needsDepositApproval),
|
|
66888
67052
|
// `canDeposit` already folds in the cap, the pause and the gate, so it is
|
|
66889
67053
|
// the authoritative answer — but the REASON is what a disabled CTA renders,
|
|
66890
67054
|
// and that only survives in the raw fields.
|
|
@@ -66962,6 +67126,9 @@ function vaultTermInputFromSourceRow(row, chainId) {
|
|
|
66962
67126
|
swapFeeRate: num13(meta.feeRate),
|
|
66963
67127
|
redemptionDiscountBps: num13(meta.redemptionDiscountBps),
|
|
66964
67128
|
instantRedeemEnabled: bool2(meta.instantRedeemEnabled),
|
|
67129
|
+
yieldWarmupSeconds: num13(meta.yieldWarmupSeconds),
|
|
67130
|
+
accrual: str6(meta.accrual),
|
|
67131
|
+
needsDepositApproval: bool2(meta.needsDepositApproval),
|
|
66965
67132
|
isMintable: bool2(meta.isMintable),
|
|
66966
67133
|
depositCapacity: str6(meta.depositCapacity) ?? str6(meta.maxDeposit),
|
|
66967
67134
|
supplyCap: str6(meta.supplyCap),
|
|
@@ -67913,7 +68080,12 @@ var ROW_DESCRIPTOR_KEYS = [
|
|
|
67913
68080
|
"curvance",
|
|
67914
68081
|
"broker",
|
|
67915
68082
|
"collateralProvider",
|
|
67916
|
-
"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"
|
|
67917
68089
|
];
|
|
67918
68090
|
function resolveMarketDescriptors(row, ctxMarket) {
|
|
67919
68091
|
const fromParams = pick2(row, "params.market");
|
|
@@ -68571,6 +68743,7 @@ var liquityAdapter = {
|
|
|
68571
68743
|
const minDebt = liquity.minDebt != null ? String(liquity.minDebt) : void 0;
|
|
68572
68744
|
const minApr = typeof liquity.minAnnualInterestRate === "string" || typeof liquity.minAnnualInterestRate === "number" ? Number(liquity.minAnnualInterestRate) / 1e18 * 100 : void 0;
|
|
68573
68745
|
const maxApr = typeof liquity.maxAnnualInterestRate === "string" || typeof liquity.maxAnnualInterestRate === "number" ? Number(liquity.maxAnnualInterestRate) / 1e18 * 100 : void 0;
|
|
68746
|
+
const shutdown = Boolean(liquity.shutdown);
|
|
68574
68747
|
const wadPct = (v) => v == null ? void 0 : Number(v) / 1e18;
|
|
68575
68748
|
const spPenalty = wadPct(liquity.liquidationPenaltySP);
|
|
68576
68749
|
const redistPenalty = wadPct(liquity.liquidationPenaltyRedistribution);
|
|
@@ -68639,20 +68812,41 @@ var liquityAdapter = {
|
|
|
68639
68812
|
penalties: penalties.length ? penalties : void 0,
|
|
68640
68813
|
badDebt: "redistributed",
|
|
68641
68814
|
redeemable: true,
|
|
68642
|
-
redemption
|
|
68643
|
-
|
|
68644
|
-
|
|
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 ? {
|
|
68645
68827
|
trigger: "permissionless-arbitrage",
|
|
68646
|
-
//
|
|
68647
|
-
|
|
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.
|
|
68648
68841
|
driver: "below-peg",
|
|
68649
68842
|
// The rate you chose IS your position in the queue.
|
|
68650
68843
|
order: "lowest-rate-first",
|
|
68651
|
-
// The redemption fee stays in the
|
|
68844
|
+
// The redemption fee stays in the trove as extra collateral, so
|
|
68652
68845
|
// the borrower is ~USD-neutral; what is lost is EXPOSURE.
|
|
68653
68846
|
valueImpact: "usd-neutral",
|
|
68654
|
-
// The ordering is already stated by `order`; say
|
|
68655
|
-
|
|
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."
|
|
68656
68850
|
}
|
|
68657
68851
|
},
|
|
68658
68852
|
counterparty: { kind: "cdp", solvency: "overcollateralized" }
|
|
@@ -68689,14 +68883,28 @@ var riverAdapter = {
|
|
|
68689
68883
|
seizure: "proportional",
|
|
68690
68884
|
redeemable: true,
|
|
68691
68885
|
redemption: {
|
|
68692
|
-
// Not governance and not a liquidation: any holder of the stable
|
|
68693
|
-
//
|
|
68886
|
+
// Not governance and not a liquidation: any holder of the stable can
|
|
68887
|
+
// trigger it, without permission and without targeting anyone.
|
|
68694
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.
|
|
68695
68892
|
driver: "below-peg",
|
|
68696
|
-
|
|
68697
|
-
|
|
68698
|
-
//
|
|
68699
|
-
|
|
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."
|
|
68700
68908
|
}
|
|
68701
68909
|
},
|
|
68702
68910
|
counterparty: { kind: "cdp", solvency: "overcollateralized" }
|
|
@@ -69010,7 +69218,18 @@ var resupplyAdapter = {
|
|
|
69010
69218
|
// rate to raise. Offering "raise your rate" here would be actively
|
|
69011
69219
|
// misleading.
|
|
69012
69220
|
order: "pro-rata",
|
|
69013
|
-
valueImpact
|
|
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."
|
|
69014
69233
|
},
|
|
69015
69234
|
badDebt: "socialized"
|
|
69016
69235
|
},
|
|
@@ -69158,6 +69377,54 @@ var fraxlendAdapter = {
|
|
|
69158
69377
|
}
|
|
69159
69378
|
})
|
|
69160
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
|
+
};
|
|
69161
69428
|
|
|
69162
69429
|
// src/terms/adapters/index.ts
|
|
69163
69430
|
var TERM_ADAPTERS = [
|
|
@@ -69178,7 +69445,8 @@ var TERM_ADAPTERS = [
|
|
|
69178
69445
|
frankencoinAdapter,
|
|
69179
69446
|
resupplyAdapter,
|
|
69180
69447
|
curvanceAdapter,
|
|
69181
|
-
fraxlendAdapter
|
|
69448
|
+
fraxlendAdapter,
|
|
69449
|
+
morphoBlueAdapter
|
|
69182
69450
|
];
|
|
69183
69451
|
function resolveAdapter(lender) {
|
|
69184
69452
|
return TERM_ADAPTERS.find((a) => a.matches(lender));
|
|
@@ -69344,7 +69612,9 @@ function enrichTermSheet(sheet, index) {
|
|
|
69344
69612
|
}
|
|
69345
69613
|
const govRow = index.governanceByMarketUid?.get(uid);
|
|
69346
69614
|
if (govRow) {
|
|
69347
|
-
const
|
|
69615
|
+
const assertedImmutable = sheet.governance?.mutability === "immutable";
|
|
69616
|
+
const immutable = govRow.mode === "immutable" || assertedImmutable;
|
|
69617
|
+
const adapterPowers = assertedImmutable ? sheet.governance?.powers : void 0;
|
|
69348
69618
|
sheet.governance = {
|
|
69349
69619
|
...sheet.governance,
|
|
69350
69620
|
mutability: immutable ? "immutable" : "governed",
|
|
@@ -69362,7 +69632,8 @@ function enrichTermSheet(sheet, index) {
|
|
|
69362
69632
|
};
|
|
69363
69633
|
if (immutable) {
|
|
69364
69634
|
sheet.governance.timelockSecs = void 0;
|
|
69365
|
-
sheet.governance.
|
|
69635
|
+
sheet.governance.timelockUnknown = void 0;
|
|
69636
|
+
sheet.governance.powers = adapterPowers;
|
|
69366
69637
|
}
|
|
69367
69638
|
}
|
|
69368
69639
|
const quality = index.assetRisk;
|
|
@@ -69592,8 +69863,12 @@ function validateTermSheet(sheet) {
|
|
|
69592
69863
|
"immutable-timelock",
|
|
69593
69864
|
"immutable governance must not carry a timelock"
|
|
69594
69865
|
);
|
|
69595
|
-
|
|
69596
|
-
|
|
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
|
+
);
|
|
69597
69872
|
}
|
|
69598
69873
|
if (g.timelockSecs && g.controllerKind && g.controllerKind !== "TIMELOCK" && g.timelockSource !== "on-chain")
|
|
69599
69874
|
fail(
|
|
@@ -69631,7 +69906,27 @@ var USER_SET_RATE_PREFIXES = [
|
|
|
69631
69906
|
"SONETA",
|
|
69632
69907
|
"EBISU"
|
|
69633
69908
|
];
|
|
69634
|
-
function
|
|
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) {
|
|
69635
69930
|
const marketUid = str5(row.marketUid);
|
|
69636
69931
|
if (!marketUid) return void 0;
|
|
69637
69932
|
let earnUid;
|
|
@@ -69675,7 +69970,25 @@ function earnMarketFromPool(row, fallbackChainId) {
|
|
|
69675
69970
|
// The family brand ('Morpho Blue'), not the per-market key. The specific
|
|
69676
69971
|
// market identity survives on `name`.
|
|
69677
69972
|
brand: venueBrand(venue),
|
|
69678
|
-
|
|
69973
|
+
// Same resolver as the vault half, so `protocol.key` means one thing
|
|
69974
|
+
// across the listing: the STABLE family key, never the per-market venue.
|
|
69975
|
+
// No lender publishes a curator today, hence the undefined.
|
|
69976
|
+
...resolveEarnIdentity(venue, void 0),
|
|
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
|
+
}),
|
|
69679
69992
|
// Never re-derived — the uid's third segment as the origin minted it.
|
|
69680
69993
|
ref: marketUid.split(":")[2],
|
|
69681
69994
|
logoURI: str5(assetInfo.logoURI),
|
|
@@ -69953,6 +70266,207 @@ function supportsCancel(provider, meta) {
|
|
|
69953
70266
|
return typeof meta.withdrawQueue === "string" && meta.withdrawQueue.length > 0;
|
|
69954
70267
|
}
|
|
69955
70268
|
|
|
69956
|
-
|
|
70269
|
+
// src/earn/positions.ts
|
|
70270
|
+
function buildLendingPositionUid(lender, chainId) {
|
|
70271
|
+
if (!lender || !chainId) {
|
|
70272
|
+
throw new Error(
|
|
70273
|
+
`Invalid lending positionUid parameters: lender=${lender}, chainId=${chainId}`
|
|
70274
|
+
);
|
|
70275
|
+
}
|
|
70276
|
+
if (isVaultVenue(lender)) {
|
|
70277
|
+
throw new Error(
|
|
70278
|
+
`Lender '${lender}' uses the reserved vault venue namespace`
|
|
70279
|
+
);
|
|
70280
|
+
}
|
|
70281
|
+
return `${lender}:${chainId}`;
|
|
70282
|
+
}
|
|
70283
|
+
function isVaultPosition(p) {
|
|
70284
|
+
return p.venueKind === "vault";
|
|
70285
|
+
}
|
|
70286
|
+
function isLendingPosition(p) {
|
|
70287
|
+
return p.venueKind === "lending";
|
|
70288
|
+
}
|
|
70289
|
+
function legEarnUid(marketUid) {
|
|
70290
|
+
if (!marketUid) return void 0;
|
|
70291
|
+
const parts = marketUid.split(":");
|
|
70292
|
+
if (parts.length !== 3 || parts.some((p) => !p)) return void 0;
|
|
70293
|
+
if (isVaultVenue(parts[0])) return void 0;
|
|
70294
|
+
return marketUid;
|
|
70295
|
+
}
|
|
70296
|
+
function num15(v) {
|
|
70297
|
+
const n = typeof v === "number" ? v : Number(v);
|
|
70298
|
+
return Number.isFinite(n) ? n : 0;
|
|
70299
|
+
}
|
|
70300
|
+
function legAsset(pos) {
|
|
70301
|
+
const asset = pos.underlyingInfo?.asset ?? {};
|
|
70302
|
+
const address = typeof asset.address === "string" ? asset.address.toLowerCase() : (
|
|
70303
|
+
// Fall back to the uid's third segment, which IS the underlying for
|
|
70304
|
+
// the default-format lenders and merely a harmless label for the rest.
|
|
70305
|
+
pos.marketUid?.split(":")[2] ?? ""
|
|
70306
|
+
);
|
|
70307
|
+
const decimals = typeof asset.decimals === "number" ? asset.decimals : void 0;
|
|
70308
|
+
const symbol = typeof asset.symbol === "string" ? asset.symbol : void 0;
|
|
70309
|
+
const logoURI = typeof asset.logoURI === "string" ? asset.logoURI : void 0;
|
|
70310
|
+
return {
|
|
70311
|
+
address,
|
|
70312
|
+
symbol,
|
|
70313
|
+
decimals,
|
|
70314
|
+
...logoURI ? { logoURI } : {}
|
|
70315
|
+
};
|
|
70316
|
+
}
|
|
70317
|
+
function toLeg(pos) {
|
|
70318
|
+
const depositsUsd = num15(pos.depositsUSD);
|
|
70319
|
+
const debtUsd = num15(pos.debtUSD) + num15(pos.debtStableUSD);
|
|
70320
|
+
const hasSupply = depositsUsd !== 0 || num15(pos.deposits) !== 0;
|
|
70321
|
+
const hasDebt = debtUsd !== 0 || num15(pos.debt) !== 0 || num15(pos.debtStable) !== 0;
|
|
70322
|
+
return {
|
|
70323
|
+
earnUid: legEarnUid(pos.marketUid),
|
|
70324
|
+
marketUid: pos.marketUid,
|
|
70325
|
+
...pos.loanId ? { loanId: pos.loanId } : {},
|
|
70326
|
+
asset: legAsset(pos),
|
|
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",
|
|
70330
|
+
deposits: pos.deposits ?? "0",
|
|
70331
|
+
depositsUsd,
|
|
70332
|
+
debt: pos.debt ?? "0",
|
|
70333
|
+
debtUsd,
|
|
70334
|
+
collateralEnabled: pos.collateralEnabled ?? false,
|
|
70335
|
+
...pos.withdrawable !== void 0 ? { withdrawable: pos.withdrawable } : {}
|
|
70336
|
+
};
|
|
70337
|
+
}
|
|
70338
|
+
function isCountable(leg) {
|
|
70339
|
+
return leg.loanId === void 0;
|
|
70340
|
+
}
|
|
70341
|
+
function earnPositionFromLenderEntry(entry) {
|
|
70342
|
+
const subs = entry.data ?? [];
|
|
70343
|
+
const subAccounts = subs.map((sub) => {
|
|
70344
|
+
const legs = (sub.positions ?? []).map(toLeg);
|
|
70345
|
+
const counted = legs.filter(isCountable);
|
|
70346
|
+
const suppliedUsd2 = counted.reduce((a, l) => a + l.depositsUsd, 0);
|
|
70347
|
+
const borrowedUsd2 = counted.reduce((a, l) => a + l.debtUsd, 0);
|
|
70348
|
+
return {
|
|
70349
|
+
accountId: sub.accountId,
|
|
70350
|
+
health: sub.health ?? null,
|
|
70351
|
+
suppliedUsd: suppliedUsd2,
|
|
70352
|
+
borrowedUsd: borrowedUsd2,
|
|
70353
|
+
netUsd: suppliedUsd2 - borrowedUsd2,
|
|
70354
|
+
legs
|
|
70355
|
+
};
|
|
70356
|
+
});
|
|
70357
|
+
const active = subAccounts.filter(
|
|
70358
|
+
(s) => s.legs.some((l) => l.side !== "none") || s.netUsd !== 0
|
|
70359
|
+
);
|
|
70360
|
+
const crossMargin = active.length <= 1;
|
|
70361
|
+
const suppliedUsd = num15(entry.balanceData?.deposits);
|
|
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
|
+
};
|
|
70368
|
+
return {
|
|
70369
|
+
positionUid: buildLendingPositionUid(entry.lender, entry.chainId),
|
|
70370
|
+
chainId: entry.chainId,
|
|
70371
|
+
venue: entry.lender,
|
|
70372
|
+
venueKind: "lending",
|
|
70373
|
+
lender: entry.lender,
|
|
70374
|
+
account: entry.account,
|
|
70375
|
+
brand: entry.lenderInfo?.name,
|
|
70376
|
+
name: entry.lenderInfo?.name,
|
|
70377
|
+
...entry.lenderInfo?.logoUri ? { logoURI: entry.lenderInfo.logoUri } : {},
|
|
70378
|
+
suppliedUsd,
|
|
70379
|
+
borrowedUsd,
|
|
70380
|
+
netUsd: num15(entry.balanceData?.nav),
|
|
70381
|
+
apr: aprBreakdown.market + aprBreakdown.rewards + aprBreakdown.intrinsic,
|
|
70382
|
+
aprBreakdown,
|
|
70383
|
+
depositApr: num15(entry.aprData?.depositApr),
|
|
70384
|
+
borrowApr: num15(entry.aprData?.borrowApr),
|
|
70385
|
+
// Only a cross-margin account HAS one health factor. Publishing the first
|
|
70386
|
+
// sub-account's as the row's would be a number about a different position.
|
|
70387
|
+
health: crossMargin ? active[0]?.health ?? null : null,
|
|
70388
|
+
leverage: num15(entry.leverage),
|
|
70389
|
+
crossMargin,
|
|
70390
|
+
legs: subAccounts.flatMap((s) => s.legs),
|
|
70391
|
+
subAccounts: active,
|
|
70392
|
+
...entry.incomplete ? { incomplete: true } : {},
|
|
70393
|
+
...entry.stale ? { stale: true, staleAgeMs: entry.staleAgeMs } : {}
|
|
70394
|
+
};
|
|
70395
|
+
}
|
|
70396
|
+
function vaultSharesToAssets(sharesRaw, meta) {
|
|
70397
|
+
if (sharesRaw === 0n) return 0n;
|
|
70398
|
+
const totalSupply = BigInt(meta.totalSupply || "0");
|
|
70399
|
+
if (totalSupply === 0n) return 0n;
|
|
70400
|
+
return sharesRaw * BigInt(meta.totalAssets || "0") / totalSupply;
|
|
70401
|
+
}
|
|
70402
|
+
function earnPositionFromVaultBalance(meta, chainId, input, format) {
|
|
70403
|
+
const assetsRaw = vaultSharesToAssets(input.sharesRaw, meta);
|
|
70404
|
+
const assetDecimals = meta.assetDecimals ?? meta.decimals;
|
|
70405
|
+
const assets = format(assetsRaw, assetDecimals);
|
|
70406
|
+
const priceUsd = input.priceUsd ?? 0;
|
|
70407
|
+
const suppliedUsd = priceUsd * parseFloat(assets);
|
|
70408
|
+
const market = input.market;
|
|
70409
|
+
const uid = buildVaultEarnUid(meta.provider, chainId, meta.address);
|
|
70410
|
+
return {
|
|
70411
|
+
positionUid: uid,
|
|
70412
|
+
earnUid: uid,
|
|
70413
|
+
chainId,
|
|
70414
|
+
venue: `vault.${meta.provider}`,
|
|
70415
|
+
venueKind: "vault",
|
|
70416
|
+
provider: meta.provider,
|
|
70417
|
+
vault: meta.address,
|
|
70418
|
+
// The catalogue's identity resolution (curator, brand, branded icon) beats
|
|
70419
|
+
// the raw share-token name where it resolved.
|
|
70420
|
+
name: market?.name ?? meta.name,
|
|
70421
|
+
...market?.brand ? { brand: market.brand } : {},
|
|
70422
|
+
...market?.logoURI ?? meta.logoURI ? { logoURI: market?.logoURI ?? meta.logoURI } : {},
|
|
70423
|
+
asset: {
|
|
70424
|
+
address: meta.underlying,
|
|
70425
|
+
...market?.asset.symbol ? { symbol: market.asset.symbol } : {},
|
|
70426
|
+
decimals: assetDecimals,
|
|
70427
|
+
priceUsd
|
|
70428
|
+
},
|
|
70429
|
+
sharesRaw: input.sharesRaw.toString(),
|
|
70430
|
+
shares: format(input.sharesRaw, meta.decimals),
|
|
70431
|
+
assetsRaw: assetsRaw.toString(),
|
|
70432
|
+
assets,
|
|
70433
|
+
shareDecimals: meta.decimals,
|
|
70434
|
+
suppliedUsd,
|
|
70435
|
+
// A vault share is a supply-only instrument — there is no borrow leg to
|
|
70436
|
+
// report, and `0` here is a fact rather than a missing read.
|
|
70437
|
+
borrowedUsd: 0,
|
|
70438
|
+
netUsd: suppliedUsd,
|
|
70439
|
+
// For a vault the position's APR IS the venue's rate — there is no borrow
|
|
70440
|
+
// leg to net off, so unlike the lending half the two never diverge.
|
|
70441
|
+
...market?.rate?.total !== void 0 ? { apr: market.rate.total } : {},
|
|
70442
|
+
...market?.rate ? { rate: market.rate } : {},
|
|
70443
|
+
...market?.exit ? { exit: market.exit } : {},
|
|
70444
|
+
...market?.availability ? { availability: market.availability } : {},
|
|
70445
|
+
...market?.capabilities ? { capabilities: market.capabilities } : {},
|
|
70446
|
+
...meta.yieldProfile ? { yieldProfile: meta.yieldProfile } : {},
|
|
70447
|
+
...meta.denomination ? { denomination: meta.denomination } : {}
|
|
70448
|
+
};
|
|
70449
|
+
}
|
|
70450
|
+
function earnPositionTotals(items) {
|
|
70451
|
+
let suppliedUsd = 0;
|
|
70452
|
+
let borrowedUsd = 0;
|
|
70453
|
+
let lendingUsd = 0;
|
|
70454
|
+
let vaultUsd = 0;
|
|
70455
|
+
for (const it of items) {
|
|
70456
|
+
suppliedUsd += it.suppliedUsd;
|
|
70457
|
+
borrowedUsd += it.borrowedUsd;
|
|
70458
|
+
if (it.venueKind === "vault") vaultUsd += it.netUsd;
|
|
70459
|
+
else lendingUsd += it.netUsd;
|
|
70460
|
+
}
|
|
70461
|
+
return {
|
|
70462
|
+
suppliedUsd,
|
|
70463
|
+
borrowedUsd,
|
|
70464
|
+
netUsd: suppliedUsd - borrowedUsd,
|
|
70465
|
+
lendingUsd,
|
|
70466
|
+
vaultUsd
|
|
70467
|
+
};
|
|
70468
|
+
}
|
|
70469
|
+
|
|
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 };
|
|
69957
70471
|
//# sourceMappingURL=index.js.map
|
|
69958
70472
|
//# sourceMappingURL=index.js.map
|