@1delta/margin-fetcher 5.0.27 → 5.0.29
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 +455 -18
- package/dist/index.js +969 -641
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { Chain } from '@1delta/chain-registry';
|
|
|
9
9
|
import { multicallRetryUniversal, getEvmClient, getEvmChain, getEvmClientUniversal } from '@1delta/providers';
|
|
10
10
|
import { LiquityTroveManagerAbi, LiquityActivePoolAbi, LiquityStabilityPoolAbi, LiquityPriceFeedAbi, LiquitySortedTrovesAbi, RiverTroveManagerAbi, RiverStabilityPoolAbi, TellerMarketRegistryAbi, TellerV2Abi, InverseMarketAbi, InverseOracleAbi, InverseDbrAbi, Erc20Abi, LlamaLendControllerAbi, LlamaLendControllerV1Abi, LlamaLendControllerV2Abi, LlamaLendVaultAbi, LlamaLendAmmAbi, MetaMorphoAbi, ExactlyPreviewerAbi, ExactlyAuditorAbi, LenderCommitmentGroupAbi, ResupplyRegistryAbi, ResupplyPairAbi, ResupplyUtilitiesAbi, ResupplyRewardHandlerAbi, ResupplyPairEmissionsAbi, ConvexPoolUtilAbi, FraxlendPairAbi, FrankencoinPositionAbi, FluidLendingResolverAbi, FluidVaultResolverAbi, FluidLiquidityResolverAbi, MoolahVaultAbi, UsddVatAbi, UsddJugAbi, UsddSpotAbi, MorphoLensAbi, AaveV4SpokeAbi, AaveV4OracleAbi, AaveV4HubAbi, DolomiteMarginAbi, GearboxMarketCompressorV310Abi, MorphoBlueAbi, MidnightAbi, TermRepoTokenAbi, TermRepoServicerAbi, TermRepoCollateralManagerAbi, LiquityTroveNFTAbi, LiquityCollSurplusPoolAbi, TellerCollateralManagerAbi, TermMaxViewerAbi, InverseEscrowAbi, CurvanceMarketManagerAbi, CurvanceCTokenAbi, GearboxCreditAccountCompressorV310Abi, UsddCdpManagerAbi, UsddProxyRegistryAbi, CurvanceProtocolReaderAbi, CurvanceCentralRegistryAbi, TermPriceConsumerAbi, CurvanceOracleManagerAbi, TermMaxOracleAggregatorV2Abi } from '@1delta/abis';
|
|
11
11
|
export { MorphoLensAbi } from '@1delta/abis';
|
|
12
|
-
import { prepareDebitDataMulticall, prepareLenderDebitMulticall, parseDebitDataResult, parseLenderDebitResult, getPermit2ContractAddress, getCompoundV3CometAddress as getCompoundV3CometAddress$1, getMorphoAddress, getAaveCollateralTokenAddress, getSiloHalfForUnderlying, bandLtvCurve, InitMarginAddresses
|
|
12
|
+
import { prepareDebitDataMulticall, prepareLenderDebitMulticall, parseDebitDataResult, parseLenderDebitResult, getPermit2ContractAddress, getLstAcceptedInputs, getCompoundV3CometAddress as getCompoundV3CometAddress$1, getMorphoAddress, getAaveCollateralTokenAddress, getSiloHalfForUnderlying, bandLtvCurve, InitMarginAddresses } from '@1delta/calldata-sdk';
|
|
13
13
|
import { proxyNativeFetch } from '@1delta/proxy-fetch';
|
|
14
14
|
import { BALANCER_V2_FORKS, BALANCER_V3_FORKS, UNISWAP_V4_FORKS, isFlashLoanSourceExcluded, FLASH_LOAN_IDS } from '@1delta/dex-registry';
|
|
15
15
|
|
|
@@ -21931,7 +21931,7 @@ async function fetchTellerMarkets(chainId) {
|
|
|
21931
21931
|
}
|
|
21932
21932
|
return null;
|
|
21933
21933
|
};
|
|
21934
|
-
const
|
|
21934
|
+
const num16 = (i) => {
|
|
21935
21935
|
const b = big18(i);
|
|
21936
21936
|
return b === null ? null : Number(b);
|
|
21937
21937
|
};
|
|
@@ -21941,9 +21941,9 @@ async function fetchTellerMarkets(chainId) {
|
|
|
21941
21941
|
config,
|
|
21942
21942
|
available: big18(base),
|
|
21943
21943
|
committed: big18(base + 1),
|
|
21944
|
-
minRateBps:
|
|
21944
|
+
minRateBps: num16(base + 2),
|
|
21945
21945
|
collateralPerPrincipal: big18(base + 3),
|
|
21946
|
-
maxLoanDuration:
|
|
21946
|
+
maxLoanDuration: num16(base + 4),
|
|
21947
21947
|
marketId: big18(base + 5),
|
|
21948
21948
|
totalAssets: big18(base + 6)
|
|
21949
21949
|
};
|
|
@@ -22906,20 +22906,20 @@ async function fetchInverseMarkets(lender, chainId) {
|
|
|
22906
22906
|
if (Object.keys(byAddr).length > 0) {
|
|
22907
22907
|
const rows = markets.map((market) => {
|
|
22908
22908
|
const m = byAddr[market.address.toLowerCase()];
|
|
22909
|
-
const
|
|
22909
|
+
const num16 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
22910
22910
|
return {
|
|
22911
22911
|
market,
|
|
22912
|
-
totalDebt:
|
|
22913
|
-
dolaLiquidity:
|
|
22914
|
-
leftToBorrow:
|
|
22915
|
-
price:
|
|
22912
|
+
totalDebt: num16(m?.totalDebt),
|
|
22913
|
+
dolaLiquidity: num16(m?.dolaLiquidity),
|
|
22914
|
+
leftToBorrow: num16(m?.leftToBorrow),
|
|
22915
|
+
price: num16(m?.price),
|
|
22916
22916
|
borrowPaused: typeof m?.borrowPaused === "boolean" ? m.borrowPaused : null,
|
|
22917
|
-
dailyBorrows:
|
|
22917
|
+
dailyBorrows: num16(m?.dailyBorrows),
|
|
22918
22918
|
// The API serves it as a DECIMAL (`replenishmentIncentive: 0.1`),
|
|
22919
22919
|
// unlike the on-chain bps — normalize here, and fall back to the
|
|
22920
22920
|
// curated metadata value when the field is missing.
|
|
22921
22921
|
replenishmentIncentiveBps: (() => {
|
|
22922
|
-
const dec2 =
|
|
22922
|
+
const dec2 = num16(m?.replenishmentIncentive);
|
|
22923
22923
|
if (dec2 !== null) return Math.round(dec2 * 1e4);
|
|
22924
22924
|
const meta = Number(market.replenishmentIncentiveBps);
|
|
22925
22925
|
return Number.isFinite(meta) ? meta : null;
|
|
@@ -64138,8 +64138,9 @@ function marketTags(sheet) {
|
|
|
64138
64138
|
if (g) {
|
|
64139
64139
|
if (g.mutability === "immutable") push(out, "immutable");
|
|
64140
64140
|
if (g.mutability === "governed") {
|
|
64141
|
+
const contractEnforced = (g.timelockSecs ?? 0) > 0 && g.timelockSource === "on-chain";
|
|
64141
64142
|
const isTimelockRoot = g.controllerKind === "TIMELOCK";
|
|
64142
|
-
if (!isTimelockRoot) push(out, "no-timelock");
|
|
64143
|
+
if (contractEnforced) ; else if (!isTimelockRoot) push(out, "no-timelock");
|
|
64143
64144
|
else if (!g.timelockSecs && !g.timelockUnknown) push(out, "no-timelock");
|
|
64144
64145
|
if (g.controllerKind === "EOA") push(out, "eoa-controlled");
|
|
64145
64146
|
}
|
|
@@ -64915,7 +64916,8 @@ var TERM_PROFILES = [
|
|
|
64915
64916
|
"There is NO deposit or redemption before maturity \u2014 you enter and exit by TRADING on an AMM, so both legs move against you with size and need a slippage tolerance.",
|
|
64916
64917
|
"The quoted liquidity is pool DEPTH, not idle cash waiting to be withdrawn.",
|
|
64917
64918
|
"The rate is fixed at purchase. Selling early realizes whatever the market pays that block, which can be above or below your entry.",
|
|
64918
|
-
"Buying gives up the underlying\u2019s own floating yield for the term \u2014 that is the trade, not an extra return on top."
|
|
64919
|
+
"Buying gives up the underlying\u2019s own floating yield for the term \u2014 that is the trade, not an extra return on top.",
|
|
64920
|
+
"Redemption is 1:1 in the underlying, so the fixed rate itself carries no credit risk \u2014 but you are paid in that underlying, and whatever risk it carries (a depeg, a failure of the protocol behind it) passes straight through to you."
|
|
64919
64921
|
]
|
|
64920
64922
|
}
|
|
64921
64923
|
}),
|
|
@@ -65561,6 +65563,11 @@ function buildTermSheet(input, opts = {}) {
|
|
|
65561
65563
|
var LENDING_VAULT = {
|
|
65562
65564
|
rateKind: "variable-curve",
|
|
65563
65565
|
rateSource: "utilization-curve",
|
|
65566
|
+
// Structural, not curated: these vaults can only reach markets that require
|
|
65567
|
+
// collateral. A shortfall is possible (bad debt socializes to depositors, and
|
|
65568
|
+
// `principal.risks` carries that), but the loan book itself is collateralized
|
|
65569
|
+
// by construction — which is a different statement from Maple's or Native's.
|
|
65570
|
+
solvency: "overcollateralized",
|
|
65564
65571
|
defaultExitMode: "instant-capped",
|
|
65565
65572
|
priceRisk: "none",
|
|
65566
65573
|
counterpartyKind: "vault-strategy",
|
|
@@ -65600,13 +65607,19 @@ var VAULT_PROVIDER_TRAITS = {
|
|
|
65600
65607
|
},
|
|
65601
65608
|
// The only provider that publishes a real debt accumulator on the row
|
|
65602
65609
|
// (`totalBorrowed` / `expectedLiquidity`), so utilization is exact here.
|
|
65610
|
+
// Lends to leveraged credit accounts, which post collateral and carry a
|
|
65611
|
+
// health factor — collateralized, like the rest of this class.
|
|
65603
65612
|
gearbox: { ...LENDING_VAULT, reportsGovernance: false },
|
|
65604
65613
|
// A thin 4626 wrapper over an Aave v3 supply position: the rate IS the
|
|
65605
65614
|
// reserve's supply curve. Publishes no liquidity field of its own.
|
|
65606
65615
|
"aave-earn": {
|
|
65607
65616
|
...LENDING_VAULT,
|
|
65608
65617
|
counterpartyKind: "pool",
|
|
65609
|
-
reportsGovernance: false
|
|
65618
|
+
reportsGovernance: false,
|
|
65619
|
+
// The ONLY provider reporting `fee` as a fraction. Its own type documents
|
|
65620
|
+
// it (`0.1` = 10 %) while morpho / silo / euler-earn / termmax / yearn all
|
|
65621
|
+
// document percent.
|
|
65622
|
+
feeIsFraction: true
|
|
65610
65623
|
},
|
|
65611
65624
|
// The VAULT is perpetual and its rate floats with what the curator earns
|
|
65612
65625
|
// rolling FT positions — it is NOT itself a fixed-term instrument, which
|
|
@@ -65631,6 +65644,10 @@ var VAULT_PROVIDER_TRAITS = {
|
|
|
65631
65644
|
},
|
|
65632
65645
|
lst: {
|
|
65633
65646
|
rateKind: "variable-managed",
|
|
65647
|
+
// A pro-rata claim on real staked capital — fully backed, no borrower.
|
|
65648
|
+
// The residual risk is slashing and the exit queue, both of which the
|
|
65649
|
+
// exit terms and the profile state; neither is a solvency question.
|
|
65650
|
+
solvency: "overcollateralized",
|
|
65634
65651
|
// Staking rewards are neither a curve nor a governance dial — the rate is
|
|
65635
65652
|
// reconstructed from the share/asset ratio moving.
|
|
65636
65653
|
rateSource: "derived",
|
|
@@ -65647,6 +65664,15 @@ var VAULT_PROVIDER_TRAITS = {
|
|
|
65647
65664
|
// the TermMax FT promise reached by an AMM discount instead of a quote.
|
|
65648
65665
|
pendle: {
|
|
65649
65666
|
rateKind: "fixed-term",
|
|
65667
|
+
// A PT redeems 1:1 for the accounting asset at maturity — there is no
|
|
65668
|
+
// borrower, no leverage and no tranching on the Pendle side, so the
|
|
65669
|
+
// fixed-rate promise itself carries no credit risk.
|
|
65670
|
+
//
|
|
65671
|
+
// What it does NOT mean: the SY it redeems into is only as good as the
|
|
65672
|
+
// protocol behind it, and that risk passes straight through to the PT
|
|
65673
|
+
// holder. That is a property of the underlying, stated in the profile's
|
|
65674
|
+
// implications, not a defect in this classification.
|
|
65675
|
+
solvency: "overcollateralized",
|
|
65650
65676
|
rateSource: "derived",
|
|
65651
65677
|
rateWindow: { kind: "forward" },
|
|
65652
65678
|
defaultExitMode: "market-sale",
|
|
@@ -65757,12 +65783,15 @@ function windowFromAprWindow(aprWindow) {
|
|
|
65757
65783
|
var isNum2 = (v) => typeof v === "number" && Number.isFinite(v);
|
|
65758
65784
|
var clamp012 = (v) => Math.max(0, Math.min(1, v));
|
|
65759
65785
|
function buildRate2(input, t, maturity) {
|
|
65760
|
-
const
|
|
65786
|
+
const hasLegs = input.supplyRate != null || input.rewardsRate != null;
|
|
65787
|
+
const base = hasLegs ? input.supplyRate ?? 0 : input.totalRate ?? 0;
|
|
65761
65788
|
const rewards = input.rewardsRate ?? 0;
|
|
65762
|
-
const total =
|
|
65789
|
+
const total = base + rewards;
|
|
65763
65790
|
const isNav = input.navOracle != null || input.solvency === "nav-attested";
|
|
65764
65791
|
const termIsBacked = maturity.kind === "fixed-date";
|
|
65765
|
-
const
|
|
65792
|
+
const window = resolveRateWindow(input, t);
|
|
65793
|
+
const measured = window?.kind === "trailing" || input.yieldProfile === "volatile";
|
|
65794
|
+
const kind = isNav ? "nav-accrual" : measured && t.rateKind !== "fixed-term" ? "realized" : t.rateKind === "fixed-term" && !termIsBacked ? "variable-managed" : t.rateKind;
|
|
65766
65795
|
const source = isNav ? "oracle" : t.rateSource;
|
|
65767
65796
|
return {
|
|
65768
65797
|
kind,
|
|
@@ -65782,7 +65811,7 @@ function buildRate2(input, t, maturity) {
|
|
|
65782
65811
|
source,
|
|
65783
65812
|
// A PT's discount is fixed at purchase; every other vault floats.
|
|
65784
65813
|
isLocked: kind === "fixed-term" && termIsBacked,
|
|
65785
|
-
window
|
|
65814
|
+
window
|
|
65786
65815
|
};
|
|
65787
65816
|
}
|
|
65788
65817
|
function resolveRateWindow(input, t) {
|
|
@@ -65790,7 +65819,9 @@ function resolveRateWindow(input, t) {
|
|
|
65790
65819
|
if (input.isForwardApr === false) return { kind: "trailing" };
|
|
65791
65820
|
const fromAprWindow = windowFromAprWindow(input.aprWindow);
|
|
65792
65821
|
if (fromAprWindow) return fromAprWindow;
|
|
65793
|
-
return t.rateWindow;
|
|
65822
|
+
if (t.rateWindow) return t.rateWindow;
|
|
65823
|
+
if (input.yieldProfile === "volatile") return { kind: "trailing" };
|
|
65824
|
+
return void 0;
|
|
65794
65825
|
}
|
|
65795
65826
|
function buildMaturity2(input, now) {
|
|
65796
65827
|
const expiry = input.expiry;
|
|
@@ -65814,10 +65845,12 @@ function buildFees2(input, t) {
|
|
|
65814
65845
|
id: "performance",
|
|
65815
65846
|
label: "Performance fee",
|
|
65816
65847
|
when: "performance",
|
|
65817
|
-
// Every provider that reports `fee` reports it as a PERCENT of yield.
|
|
65818
65848
|
unit: "percent",
|
|
65819
65849
|
basis: "yield",
|
|
65820
|
-
|
|
65850
|
+
// Normalized to PERCENT here, because the providers disagree: `aave-earn`
|
|
65851
|
+
// publishes a fraction and the other five publish percent, so a uniform
|
|
65852
|
+
// read renders a 10 % curator cut as "0.1 %".
|
|
65853
|
+
value: t.feeIsFraction ? input.fee * 100 : input.fee,
|
|
65821
65854
|
payee: "curator",
|
|
65822
65855
|
mutable: true,
|
|
65823
65856
|
description: "Taken from the yield the vault earns, not from your principal. The published rate is already net of it."
|
|
@@ -65990,11 +66023,11 @@ function buildCounterparty(input, t) {
|
|
|
65990
66023
|
return {
|
|
65991
66024
|
kind: t.counterpartyKind,
|
|
65992
66025
|
address: input.address,
|
|
65993
|
-
//
|
|
65994
|
-
//
|
|
65995
|
-
//
|
|
65996
|
-
// `overcollateralized` from an assumed one.
|
|
65997
|
-
solvency: input.solvency ?? "overcollateralized",
|
|
66026
|
+
// Three tiers, most specific first: a CURATED per-vault classification, then
|
|
66027
|
+
// the provider's STRUCTURAL answer where one exists, then an assumption.
|
|
66028
|
+
// `coverage` records which tier answered, so a consumer can always tell an
|
|
66029
|
+
// asserted `overcollateralized` from an assumed one.
|
|
66030
|
+
solvency: input.solvency ?? t.solvency ?? "overcollateralized",
|
|
65998
66031
|
socializedLoss: input.solvency === "tranched-junior" ? true : void 0,
|
|
65999
66032
|
curator: input.curatorName ?? input.curator
|
|
66000
66033
|
};
|
|
@@ -66032,7 +66065,10 @@ function buildGovernance(input, t) {
|
|
|
66032
66065
|
// `0` is REAL on the providers that run no timelock pattern (Lista earn) —
|
|
66033
66066
|
// it means no notice period, which is exactly what a holder needs told.
|
|
66034
66067
|
timelockSecs: input.timelock,
|
|
66035
|
-
|
|
66068
|
+
// Read off the VAULT, not inferred from a governance screen — and the vault
|
|
66069
|
+
// enforces the queue itself, which is why this delay stands even though the
|
|
66070
|
+
// controller above is an unscreened curator address.
|
|
66071
|
+
timelockSource: "on-chain",
|
|
66036
66072
|
powers: ["set-caps", "change-fees", "pause-withdrawals"],
|
|
66037
66073
|
roles: hasRole ? roles : void 0
|
|
66038
66074
|
};
|
|
@@ -66092,6 +66128,7 @@ function buildCoverage2(sheet, input, t) {
|
|
|
66092
66128
|
else if (!t.reportsPerformanceFee)
|
|
66093
66129
|
pending.fees = "provider-publishes-no-fee-schedule";
|
|
66094
66130
|
if (input.solvency) present.push("counterparty");
|
|
66131
|
+
else if (t.solvency) present.push("counterparty");
|
|
66095
66132
|
else pending.counterparty = "solvency-not-curated-default-assumed";
|
|
66096
66133
|
if (sheet.supply?.exit.liquidity) present.push("exitLiquidity");
|
|
66097
66134
|
else pending.exitLiquidity = "provider-does-not-publish-liquidity";
|
|
@@ -66105,7 +66142,7 @@ function buildVaultTermSheet(input, opts = {}) {
|
|
|
66105
66142
|
const now = opts.now ?? Math.floor(Date.now() / 1e3);
|
|
66106
66143
|
const t = vaultTraits(input.provider) ?? FALLBACK_TRAITS;
|
|
66107
66144
|
const maturity = buildMaturity2(input, now);
|
|
66108
|
-
const fees = buildFees2(input);
|
|
66145
|
+
const fees = buildFees2(input, t);
|
|
66109
66146
|
const supply = {
|
|
66110
66147
|
// A vault share is never collateral IN the vault — it earns, full stop.
|
|
66111
66148
|
// (It may be collateral somewhere else; that is the other market's sheet.)
|
|
@@ -66244,9 +66281,501 @@ function splitUid(uid) {
|
|
|
66244
66281
|
if (!venue || !chainId || !ref) return void 0;
|
|
66245
66282
|
return { venue, chainId, ref };
|
|
66246
66283
|
}
|
|
66284
|
+
var VENUE_KIND_LABELS = {
|
|
66285
|
+
lending: "Lending markets",
|
|
66286
|
+
vault: "Vaults"
|
|
66287
|
+
};
|
|
66288
|
+
var VENUE_KIND_DESCRIPTIONS = {
|
|
66289
|
+
lending: "Supply into a lending market. Same-block exit, bounded by liquidity.",
|
|
66290
|
+
vault: "Deposit into a yield vault. Exit terms vary per vault."
|
|
66291
|
+
};
|
|
66292
|
+
var EXIT_MODE_LABELS = {
|
|
66293
|
+
instant: "Instant",
|
|
66294
|
+
"instant-capped": "Instant (capped)",
|
|
66295
|
+
"instant-or-queued": "Instant or queue",
|
|
66296
|
+
"fee-or-queued": "Fee or queue",
|
|
66297
|
+
"fixed-cooldown": "Cooldown",
|
|
66298
|
+
queued: "Queued",
|
|
66299
|
+
"request-based": "Request",
|
|
66300
|
+
"market-sale": "Market sale",
|
|
66301
|
+
"at-maturity": "At maturity",
|
|
66302
|
+
"off-chain": "Off-chain",
|
|
66303
|
+
"dex-only": "DEX only"
|
|
66304
|
+
};
|
|
66305
|
+
var EXIT_MODE_DESCRIPTIONS = {
|
|
66306
|
+
instant: "Withdraw any time.",
|
|
66307
|
+
"instant-capped": "Withdraw up to the available liquidity.",
|
|
66308
|
+
"instant-or-queued": "Withdraw instantly, or queue for the rest.",
|
|
66309
|
+
"fee-or-queued": "Instant exit for a fee, or queue for free.",
|
|
66310
|
+
"fixed-cooldown": "Request, wait out a cooldown, then claim.",
|
|
66311
|
+
queued: "Withdrawals are queued.",
|
|
66312
|
+
"request-based": "Withdrawals need a request and a later claim.",
|
|
66313
|
+
"market-sale": "Exit by selling the position on a market.",
|
|
66314
|
+
"at-maturity": "Locked until maturity.",
|
|
66315
|
+
"off-chain": "Exit is settled off-chain.",
|
|
66316
|
+
"dex-only": "Exit only by selling on a DEX."
|
|
66317
|
+
};
|
|
66318
|
+
var ACTION_LABELS = {
|
|
66319
|
+
deposit: "Deposit",
|
|
66320
|
+
withdraw: "Withdraw",
|
|
66321
|
+
"request-withdraw": "Request withdrawal",
|
|
66322
|
+
claim: "Claim",
|
|
66323
|
+
cancel: "Cancel request"
|
|
66324
|
+
};
|
|
66325
|
+
var GATING_LABELS = {
|
|
66326
|
+
"allowlist-contract": "Permissioned",
|
|
66327
|
+
kyc: "KYC required",
|
|
66328
|
+
"cap-full": "Cap full",
|
|
66329
|
+
paused: "Paused",
|
|
66330
|
+
frozen: "Frozen",
|
|
66331
|
+
"collateral-only": "No yield",
|
|
66332
|
+
matured: "Matured"
|
|
66333
|
+
};
|
|
66334
|
+
var RATE_KIND_LABELS = {
|
|
66335
|
+
"variable-curve": "Variable (utilization)",
|
|
66336
|
+
"variable-managed": "Variable (managed)",
|
|
66337
|
+
"user-set": "Borrower-set",
|
|
66338
|
+
"fixed-term": "Fixed term",
|
|
66339
|
+
"fixed-open": "Fixed",
|
|
66340
|
+
"zero-interest": "Interest-free",
|
|
66341
|
+
prepaid: "Prepaid",
|
|
66342
|
+
"nav-accrual": "NAV accrual",
|
|
66343
|
+
none: "No rate"
|
|
66344
|
+
};
|
|
66345
|
+
var RATE_SOURCE_LABELS = {
|
|
66346
|
+
chain: "On-chain",
|
|
66347
|
+
api: "Protocol API",
|
|
66348
|
+
oracle: "Oracle",
|
|
66349
|
+
realized: "Realized"
|
|
66350
|
+
};
|
|
66351
|
+
var SYNTHETIC_FAMILIES = ["AAVE_V4", "COMPOUND_V3", "SWAYLEND"];
|
|
66352
|
+
var FAMILY_KEYS = [
|
|
66353
|
+
.../* @__PURE__ */ new Set([
|
|
66354
|
+
...Object.values(Lender),
|
|
66355
|
+
...SYNTHETIC_FAMILIES
|
|
66356
|
+
])
|
|
66357
|
+
].sort((a, b) => a.length - b.length || a.localeCompare(b));
|
|
66358
|
+
var BRAND_OVERRIDES = {
|
|
66359
|
+
LISTA_DAO: "Lista",
|
|
66360
|
+
FLUX_FINANCE: "Flux",
|
|
66361
|
+
TERMMAX: "TermMax",
|
|
66362
|
+
LLAMALEND: "LlamaLend",
|
|
66363
|
+
USDD: "USDD",
|
|
66364
|
+
USDAF: "USDaf",
|
|
66365
|
+
DTRINITY: "dTRINITY",
|
|
66366
|
+
DFORCE: "dForce",
|
|
66367
|
+
OVIX: "0VIX",
|
|
66368
|
+
WE_PIGGY: "WePiggy",
|
|
66369
|
+
ZEROLEND: "ZeroLend",
|
|
66370
|
+
HYPERLEND: "HyperLend",
|
|
66371
|
+
HYPURRFI: "HypurrFi",
|
|
66372
|
+
HYPERYIELD: "HyperYield",
|
|
66373
|
+
LAYERBANK_V3: "LayerBank V3",
|
|
66374
|
+
TAKOTAKO: "TakoTako",
|
|
66375
|
+
SWAYLEND: "Swaylend",
|
|
66376
|
+
BENQI: "BENQI",
|
|
66377
|
+
YLDR: "YLDR",
|
|
66378
|
+
YEI: "YEI",
|
|
66379
|
+
RMM: "RMM",
|
|
66380
|
+
PAC: "PAC"
|
|
66381
|
+
};
|
|
66382
|
+
function titleCaseKey(key3) {
|
|
66383
|
+
return key3.split(/[_-]/).filter(Boolean).map((s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase()).join(" ");
|
|
66384
|
+
}
|
|
66385
|
+
var VAULT_PROVIDER_BRANDS = {
|
|
66386
|
+
fluid: "Fluid",
|
|
66387
|
+
gearbox: "Gearbox",
|
|
66388
|
+
morpho: "Morpho",
|
|
66389
|
+
lista: "Lista",
|
|
66390
|
+
silo: "Silo",
|
|
66391
|
+
"euler-earn": "Euler",
|
|
66392
|
+
termmax: "TermMax",
|
|
66393
|
+
lst: "Liquid staking",
|
|
66394
|
+
savings: "Savings",
|
|
66395
|
+
lagoon: "Lagoon",
|
|
66396
|
+
"aave-earn": "Aave",
|
|
66397
|
+
upshift: "Upshift",
|
|
66398
|
+
yearn: "Yearn",
|
|
66399
|
+
hypercore: "HyperLiquid",
|
|
66400
|
+
gmx: "GMX",
|
|
66401
|
+
pendle: "Pendle"
|
|
66402
|
+
};
|
|
66403
|
+
function isInstanceSegment(seg) {
|
|
66404
|
+
if (/^\d+$/.test(seg)) return true;
|
|
66405
|
+
if (/^0X[0-9A-F]+$/i.test(seg)) return true;
|
|
66406
|
+
return seg.length >= 8 && /^[0-9A-F]+$/i.test(seg);
|
|
66407
|
+
}
|
|
66408
|
+
function venueBrandKey(venue) {
|
|
66409
|
+
if (venue.startsWith(VAULT_VENUE_PREFIX)) return venue;
|
|
66410
|
+
const key3 = venue.toUpperCase();
|
|
66411
|
+
for (const family of FAMILY_KEYS) {
|
|
66412
|
+
if (key3 === family || key3.startsWith(family + "_")) return family;
|
|
66413
|
+
}
|
|
66414
|
+
const segments = key3.split("_");
|
|
66415
|
+
const cut = segments.findIndex(isInstanceSegment);
|
|
66416
|
+
return (cut > 0 ? segments.slice(0, cut) : segments).join("_");
|
|
66417
|
+
}
|
|
66418
|
+
function venueBrand(venue) {
|
|
66419
|
+
if (venue.startsWith(VAULT_VENUE_PREFIX)) {
|
|
66420
|
+
const provider = venue.slice(VAULT_VENUE_PREFIX.length);
|
|
66421
|
+
return VAULT_PROVIDER_BRANDS[provider] ?? titleCaseKey(provider);
|
|
66422
|
+
}
|
|
66423
|
+
const family = venueBrandKey(venue);
|
|
66424
|
+
return BRAND_OVERRIDES[family] ?? titleCaseKey(family);
|
|
66425
|
+
}
|
|
66426
|
+
var EARN_LABELS = {
|
|
66427
|
+
venueKind: VENUE_KIND_LABELS,
|
|
66428
|
+
exitMode: EXIT_MODE_LABELS,
|
|
66429
|
+
action: ACTION_LABELS,
|
|
66430
|
+
gating: GATING_LABELS,
|
|
66431
|
+
rateKind: RATE_KIND_LABELS,
|
|
66432
|
+
rateSource: RATE_SOURCE_LABELS
|
|
66433
|
+
};
|
|
66434
|
+
var EARN_DESCRIPTIONS = {
|
|
66435
|
+
venueKind: VENUE_KIND_DESCRIPTIONS,
|
|
66436
|
+
exitMode: EXIT_MODE_DESCRIPTIONS
|
|
66437
|
+
};
|
|
66438
|
+
function earnLabel(dimension, key3) {
|
|
66439
|
+
return EARN_LABELS[dimension][key3] ?? key3;
|
|
66440
|
+
}
|
|
66441
|
+
function earnDescription(dimension, key3) {
|
|
66442
|
+
return EARN_DESCRIPTIONS[dimension][key3];
|
|
66443
|
+
}
|
|
66444
|
+
function earnMarketLabel(input) {
|
|
66445
|
+
const asset = input.assetSymbol?.trim();
|
|
66446
|
+
if (!asset) return input.fallbackName ?? "";
|
|
66447
|
+
const collaterals = (input.collateralSymbols ?? []).map((c) => c?.trim()).filter((c) => !!c);
|
|
66448
|
+
const distinct = [...new Set(collaterals)];
|
|
66449
|
+
if (distinct.length === 1) return `${asset} \xB7 vs ${distinct[0]}`;
|
|
66450
|
+
return asset;
|
|
66451
|
+
}
|
|
66452
|
+
var SAME_BLOCK_EXIT_MODES = /* @__PURE__ */ new Set([
|
|
66453
|
+
"instant",
|
|
66454
|
+
"instant-capped"
|
|
66455
|
+
]);
|
|
66456
|
+
function isIlliquid(input) {
|
|
66457
|
+
if (!input.exitMode || !SAME_BLOCK_EXIT_MODES.has(input.exitMode))
|
|
66458
|
+
return false;
|
|
66459
|
+
if (!input.tvlUsd || input.tvlUsd <= 0) return false;
|
|
66460
|
+
if (input.liquidityUsd === void 0) return false;
|
|
66461
|
+
return input.liquidityUsd <= 0;
|
|
66462
|
+
}
|
|
66463
|
+
var CATEGORY_PROVIDERS = /* @__PURE__ */ new Set(["savings", "lst"]);
|
|
66464
|
+
function resolveEarnIdentity(venue, brand) {
|
|
66465
|
+
const isVault = venue.startsWith(VAULT_VENUE_PREFIX);
|
|
66466
|
+
const provider = isVault ? venue.slice(VAULT_VENUE_PREFIX.length) : venue;
|
|
66467
|
+
const providerBrand = venueBrand(venue);
|
|
66468
|
+
const key3 = venueBrandKey(venue);
|
|
66469
|
+
if (isVault && CATEGORY_PROVIDERS.has(provider)) {
|
|
66470
|
+
return { protocol: { key: key3, name: brand?.trim() || providerBrand } };
|
|
66471
|
+
}
|
|
66472
|
+
const name = brand?.trim();
|
|
66473
|
+
if (!name || name.toLowerCase() === providerBrand.toLowerCase()) {
|
|
66474
|
+
return { protocol: { key: key3, name: providerBrand } };
|
|
66475
|
+
}
|
|
66476
|
+
return { protocol: { key: key3, name: providerBrand }, curator: { name } };
|
|
66477
|
+
}
|
|
66478
|
+
|
|
66479
|
+
// src/earn/normalize.ts
|
|
66480
|
+
function num12(v) {
|
|
66481
|
+
if (v == null || v === "") return void 0;
|
|
66482
|
+
const n = typeof v === "number" ? v : Number(v);
|
|
66483
|
+
return Number.isFinite(n) ? n : void 0;
|
|
66484
|
+
}
|
|
66485
|
+
function str5(v) {
|
|
66486
|
+
if (typeof v === "string") return v.length > 0 ? v : void 0;
|
|
66487
|
+
if (typeof v === "number" && Number.isFinite(v)) return String(v);
|
|
66488
|
+
return void 0;
|
|
66489
|
+
}
|
|
66490
|
+
function addr2(v) {
|
|
66491
|
+
return str5(v)?.toLowerCase();
|
|
66492
|
+
}
|
|
66493
|
+
function yieldProfile(v) {
|
|
66494
|
+
return v === "yield-bearing" || v === "volatile" ? v : void 0;
|
|
66495
|
+
}
|
|
66496
|
+
function denomination(v) {
|
|
66497
|
+
return v === "stable" || v === "volatile" ? v : void 0;
|
|
66498
|
+
}
|
|
66499
|
+
function usdValue(formatted, priceUsd) {
|
|
66500
|
+
if (formatted === void 0 || priceUsd === void 0) return void 0;
|
|
66501
|
+
const v = formatted * priceUsd;
|
|
66502
|
+
return Number.isFinite(v) ? v : void 0;
|
|
66503
|
+
}
|
|
66504
|
+
function formatRaw(raw, decimals) {
|
|
66505
|
+
if (raw == null || raw === "") return void 0;
|
|
66506
|
+
let value;
|
|
66507
|
+
try {
|
|
66508
|
+
value = BigInt(raw);
|
|
66509
|
+
} catch {
|
|
66510
|
+
return void 0;
|
|
66511
|
+
}
|
|
66512
|
+
if (decimals <= 0) return Number(value);
|
|
66513
|
+
const base = 10n ** BigInt(decimals);
|
|
66514
|
+
const whole = value / base;
|
|
66515
|
+
const frac = value % base;
|
|
66516
|
+
const n = Number(whole) + Number(frac) / Number(base);
|
|
66517
|
+
return Number.isFinite(n) ? n : void 0;
|
|
66518
|
+
}
|
|
66519
|
+
|
|
66520
|
+
// src/earn/fromVault.ts
|
|
66521
|
+
var FRACTION_RATE_PROVIDERS = /* @__PURE__ */ new Set();
|
|
66522
|
+
var SDK_FRACTION_RATE_PROVIDERS = /* @__PURE__ */ new Set([
|
|
66523
|
+
"hypercore",
|
|
66524
|
+
"gmx"
|
|
66525
|
+
]);
|
|
66526
|
+
var RATE_SOURCE = {
|
|
66527
|
+
morpho: "api",
|
|
66528
|
+
silo: "api",
|
|
66529
|
+
lagoon: "api",
|
|
66530
|
+
hypercore: "api",
|
|
66531
|
+
gmx: "api",
|
|
66532
|
+
upshift: "api",
|
|
66533
|
+
yearn: "api",
|
|
66534
|
+
"aave-earn": "api",
|
|
66535
|
+
pendle: "api",
|
|
66536
|
+
lista: "chain",
|
|
66537
|
+
fluid: "chain",
|
|
66538
|
+
gearbox: "chain",
|
|
66539
|
+
"euler-earn": "chain",
|
|
66540
|
+
termmax: "chain",
|
|
66541
|
+
lst: "chain",
|
|
66542
|
+
savings: "chain"
|
|
66543
|
+
};
|
|
66544
|
+
var RATE_KIND = {
|
|
66545
|
+
morpho: "variable-curve",
|
|
66546
|
+
lista: "variable-curve",
|
|
66547
|
+
silo: "variable-curve",
|
|
66548
|
+
"euler-earn": "variable-curve",
|
|
66549
|
+
fluid: "variable-curve",
|
|
66550
|
+
gearbox: "variable-curve",
|
|
66551
|
+
"aave-earn": "variable-curve",
|
|
66552
|
+
// The TermMax VAULT is a perpetual curated 4626 whose curator rolls
|
|
66553
|
+
// fixed-term FT positions — the vault itself has no maturity and no locked
|
|
66554
|
+
// rate. `fixed-term` here claimed both, producing a "fixed" rate with no date
|
|
66555
|
+
// attached to it. The LENDER `TERMMAX_*` is fixed-term; this is not.
|
|
66556
|
+
termmax: "variable-managed",
|
|
66557
|
+
// A PT's implied APY is locked in at purchase and realized only by holding
|
|
66558
|
+
// to maturity — the same promise TermMax's FT makes, reached by a different
|
|
66559
|
+
// mechanism (an AMM discount rather than a quoted curve).
|
|
66560
|
+
pendle: "fixed-term",
|
|
66561
|
+
savings: "variable-managed",
|
|
66562
|
+
lst: "variable-managed",
|
|
66563
|
+
lagoon: "variable-managed",
|
|
66564
|
+
upshift: "variable-managed",
|
|
66565
|
+
yearn: "variable-managed",
|
|
66566
|
+
hypercore: "realized",
|
|
66567
|
+
gmx: "realized"
|
|
66568
|
+
};
|
|
66569
|
+
function resolveExitMode2(provider, meta, tvl, liq) {
|
|
66570
|
+
const declared = str5(meta.withdrawalMode);
|
|
66571
|
+
if (declared) return declared;
|
|
66572
|
+
const fallback = vaultTraits(provider)?.defaultExitMode ?? "instant";
|
|
66573
|
+
if (fallback !== "instant-capped") return fallback;
|
|
66574
|
+
const total = num12(tvl?.totalAssetsFormatted) ?? num12(tvl?.totalAssetsUsd);
|
|
66575
|
+
const available = num12(liq?.liquidityFormatted) ?? num12(liq?.liquidityUsd);
|
|
66576
|
+
if (total === void 0 || available === void 0) return "instant-capped";
|
|
66577
|
+
if (total <= 0) return "instant";
|
|
66578
|
+
return available >= total ? "instant" : "instant-capped";
|
|
66579
|
+
}
|
|
66580
|
+
function earnMarketFromVault(row, chainId, opts = {}) {
|
|
66581
|
+
const provider = str5(row.provider);
|
|
66582
|
+
const address = str5(row.vaultAddress)?.toLowerCase();
|
|
66583
|
+
const underlying = str5(row.underlying)?.toLowerCase();
|
|
66584
|
+
if (!provider || !address || !underlying) return void 0;
|
|
66585
|
+
const meta = row.providerMeta ?? {};
|
|
66586
|
+
const info = row.vaultInfo ?? {};
|
|
66587
|
+
const rates = row.rates ?? {};
|
|
66588
|
+
const tvl = row.tvl ?? {};
|
|
66589
|
+
const liq = row.liquidity ?? {};
|
|
66590
|
+
const shareDecimals = num12(row.decimals) ?? 18;
|
|
66591
|
+
const assetDecimals = num12(row.assetDecimals) ?? num12(row.underlyingInfo?.asset?.decimals) ?? shareDecimals;
|
|
66592
|
+
const toPercent2 = (v) => ratePercent(v, provider, opts.fractionRateProviders);
|
|
66593
|
+
const rewards = toPercent2(rates.rewardsRate);
|
|
66594
|
+
const deposit = toPercent2(rates.depositRate);
|
|
66595
|
+
const base = toPercent2(rates.supplyRate) ?? (deposit !== void 0 && rewards !== void 0 ? deposit - rewards : deposit);
|
|
66596
|
+
const total = toPercent2(rates.totalRate) ?? deposit ?? sum(base, rewards) ?? 0;
|
|
66597
|
+
const rate = {
|
|
66598
|
+
total,
|
|
66599
|
+
base,
|
|
66600
|
+
rewards,
|
|
66601
|
+
// A vault has no separate intrinsic leg — whatever it pays IS the venue's
|
|
66602
|
+
// own yield. Leaving this undefined rendered an empty "Venue APR" on every
|
|
66603
|
+
// vault row, which read as "this vault pays nothing".
|
|
66604
|
+
marketOwn: total,
|
|
66605
|
+
// ...and for the same reason it can never be pass-through.
|
|
66606
|
+
passthrough: false,
|
|
66607
|
+
kind: resolveRateKind(provider, meta),
|
|
66608
|
+
source: RATE_SOURCE[provider] ?? "api",
|
|
66609
|
+
// The curator's cut. Dropped entirely until now, which left the earn row
|
|
66610
|
+
// unable to say why its net rate sits below the gross one — and left the
|
|
66611
|
+
// term sheet built from this row with no fee schedule at all.
|
|
66612
|
+
fee: toPercent2(rates.fee)
|
|
66613
|
+
};
|
|
66614
|
+
const maturity = resolveMaturity(meta);
|
|
66615
|
+
const availability = resolveAvailability(meta, maturity);
|
|
66616
|
+
const exitMode = resolveExitMode2(provider, meta, tvl, liq);
|
|
66617
|
+
const market = {
|
|
66618
|
+
earnUid: buildVaultEarnUid(provider, chainId, address),
|
|
66619
|
+
chainId,
|
|
66620
|
+
venue: vaultVenue(provider),
|
|
66621
|
+
venueKind: "vault",
|
|
66622
|
+
// Curator first (it names the actual operator), then the provider brand.
|
|
66623
|
+
brand: str5(row.curatorName) ?? venueBrand(vaultVenue(provider)),
|
|
66624
|
+
// What the vault is BUILT ON, kept apart from who runs it — see
|
|
66625
|
+
// `resolveEarnIdentity` for why this is not simply provider-vs-brand.
|
|
66626
|
+
...withCuratorEntity(
|
|
66627
|
+
resolveEarnIdentity(
|
|
66628
|
+
vaultVenue(provider),
|
|
66629
|
+
str5(row.curatorName)
|
|
66630
|
+
),
|
|
66631
|
+
str5(row.curatorEntity)
|
|
66632
|
+
),
|
|
66633
|
+
name: str5(info.name) ?? str5(row.displayName) ?? str5(row.name),
|
|
66634
|
+
ref: address,
|
|
66635
|
+
logoURI: str5(info.logoURI) ?? str5(row.underlyingInfo?.asset?.logoURI),
|
|
66636
|
+
asset: {
|
|
66637
|
+
address: underlying,
|
|
66638
|
+
symbol: str5(row.underlyingInfo?.asset?.symbol) ?? "",
|
|
66639
|
+
decimals: assetDecimals,
|
|
66640
|
+
assetGroup: str5(info.assetGroup),
|
|
66641
|
+
priceUsd: num12(row.underlyingInfo?.prices?.priceUsd)
|
|
66642
|
+
},
|
|
66643
|
+
// The vault IS a share token by construction; carry it so a withdraw in
|
|
66644
|
+
// share units can be built without a second lookup.
|
|
66645
|
+
shareToken: {
|
|
66646
|
+
address,
|
|
66647
|
+
symbol: str5(info.symbol) ?? str5(row.symbol) ?? "",
|
|
66648
|
+
decimals: shareDecimals
|
|
66649
|
+
},
|
|
66650
|
+
rate,
|
|
66651
|
+
// The vault origin reports RAW base units + a pre-formatted convenience
|
|
66652
|
+
// field. Carry both; fall back to formatting the raw amount ourselves so
|
|
66653
|
+
// `formatted` — the field consumers sort on — is never silently absent.
|
|
66654
|
+
tvl: amount(
|
|
66655
|
+
tvl.totalAssets,
|
|
66656
|
+
tvl.totalAssetsFormatted,
|
|
66657
|
+
tvl.totalAssetsUsd,
|
|
66658
|
+
assetDecimals
|
|
66659
|
+
),
|
|
66660
|
+
liquidity: liq.liquidity != null || liq.liquidityUsd != null ? amount(
|
|
66661
|
+
liq.liquidity,
|
|
66662
|
+
liq.liquidityFormatted,
|
|
66663
|
+
liq.liquidityUsd,
|
|
66664
|
+
assetDecimals
|
|
66665
|
+
) : void 0,
|
|
66666
|
+
depositCapacity: str5(meta.depositCapacity) ?? str5(meta.maxDeposit),
|
|
66667
|
+
maturity,
|
|
66668
|
+
exit: {
|
|
66669
|
+
mode: exitMode,
|
|
66670
|
+
settlement: str5(meta.redemptionType),
|
|
66671
|
+
cooldownSecs: num12(meta.withdrawalCooldownSeconds),
|
|
66672
|
+
feeBps: num12(meta.withdrawFeeBps)
|
|
66673
|
+
},
|
|
66674
|
+
availability,
|
|
66675
|
+
risk: {
|
|
66676
|
+
yieldProfile: yieldProfile(info.yieldProfile),
|
|
66677
|
+
denomination: denomination(info.denomination),
|
|
66678
|
+
// The curated trust classification, where one exists. Typed on `EarnRisk`
|
|
66679
|
+
// since the surface was written and never populated — a tranche's
|
|
66680
|
+
// first-loss position is the term most worth surfacing on a rate list.
|
|
66681
|
+
counterparty: str5(meta.solvency),
|
|
66682
|
+
score: num12(row.rating?.score),
|
|
66683
|
+
label: str5(row.rating?.level),
|
|
66684
|
+
illiquid: isIlliquid({
|
|
66685
|
+
exitMode,
|
|
66686
|
+
tvlUsd: num12(tvl.totalAssetsUsd),
|
|
66687
|
+
liquidityUsd: num12(liq.liquidityUsd)
|
|
66688
|
+
})
|
|
66689
|
+
},
|
|
66690
|
+
// Filled by `capabilities.ts` — kept required on the type so a normalizer
|
|
66691
|
+
// that forgets to stamp them is a compile error, not an empty CTA.
|
|
66692
|
+
capabilities: [],
|
|
66693
|
+
providerMeta: row.providerMeta
|
|
66694
|
+
};
|
|
66695
|
+
return market;
|
|
66696
|
+
}
|
|
66697
|
+
function ratePercent(value, provider, fractionProviders = FRACTION_RATE_PROVIDERS) {
|
|
66698
|
+
const n = num12(value);
|
|
66699
|
+
if (n === void 0) return void 0;
|
|
66700
|
+
return fractionProviders.has(provider) ? n * 100 : n;
|
|
66701
|
+
}
|
|
66702
|
+
function implausibleRatePercent(percent) {
|
|
66703
|
+
return !Number.isFinite(percent) || percent < 0 || percent > 1e4;
|
|
66704
|
+
}
|
|
66705
|
+
function resolveRateKind(provider, meta) {
|
|
66706
|
+
if (meta.navOracle || meta.solvency === "nav-attested") return "nav-accrual";
|
|
66707
|
+
return RATE_KIND[provider] ?? "variable-managed";
|
|
66708
|
+
}
|
|
66709
|
+
function resolveAvailability(meta, maturity) {
|
|
66710
|
+
const isMintable = meta.isMintable;
|
|
66711
|
+
const capacity = str5(meta.depositCapacity) ?? str5(meta.maxDeposit);
|
|
66712
|
+
const capFull = capacity === "0";
|
|
66713
|
+
let gating;
|
|
66714
|
+
let reason;
|
|
66715
|
+
if (isMatured(maturity)) {
|
|
66716
|
+
gating = "matured";
|
|
66717
|
+
reason = "This market has reached maturity";
|
|
66718
|
+
} else if (isMintable === false) {
|
|
66719
|
+
gating = "allowlist-contract";
|
|
66720
|
+
reason = "Deposits are permissioned for this vault";
|
|
66721
|
+
} else if (capFull) {
|
|
66722
|
+
gating = "cap-full";
|
|
66723
|
+
reason = "Deposit cap is full";
|
|
66724
|
+
} else if (meta.paused === true) {
|
|
66725
|
+
gating = "paused";
|
|
66726
|
+
reason = "Vault is paused";
|
|
66727
|
+
}
|
|
66728
|
+
return {
|
|
66729
|
+
canDeposit: gating === void 0,
|
|
66730
|
+
// Exits stay open under a deposit cap, a mint allowlist or a maturity —
|
|
66731
|
+
// every wind-down we have integrated (Lista, dTRINITY/Sonic) keeps the
|
|
66732
|
+
// door open outward, and a matured bond is precisely the case where the
|
|
66733
|
+
// holder still needs out. An explicit pause is the one thing that shuts
|
|
66734
|
+
// both.
|
|
66735
|
+
canWithdraw: meta.paused !== true,
|
|
66736
|
+
gating,
|
|
66737
|
+
reason
|
|
66738
|
+
};
|
|
66739
|
+
}
|
|
66740
|
+
function resolveMaturity(meta) {
|
|
66741
|
+
const expiry = num12(meta.expiry) ?? num12(meta.maturity);
|
|
66742
|
+
if (expiry === void 0 || expiry <= 0) return void 0;
|
|
66743
|
+
const nowSecs = Math.floor(Date.now() / 1e3);
|
|
66744
|
+
return {
|
|
66745
|
+
kind: "fixed-date",
|
|
66746
|
+
maturity: expiry,
|
|
66747
|
+
maturityIso: str5(meta.expiryIso) ?? new Date(expiry * 1e3).toISOString(),
|
|
66748
|
+
// A SNAPSHOT — a cached listing ages, so a countdown must be recomputed
|
|
66749
|
+
// from `maturity` rather than ticked down from this.
|
|
66750
|
+
secondsToMaturity: Math.max(expiry - nowSecs, 0),
|
|
66751
|
+
// A PT simply stops earning: it redeems for the underlying at par and
|
|
66752
|
+
// sits there. No penalty, no liquidation, no auto-roll.
|
|
66753
|
+
atMaturity: str5(meta.atMaturity) ?? "stops-earning"
|
|
66754
|
+
};
|
|
66755
|
+
}
|
|
66756
|
+
function isMatured(maturity) {
|
|
66757
|
+
if (!maturity?.maturity) return false;
|
|
66758
|
+
return maturity.maturity <= Math.floor(Date.now() / 1e3);
|
|
66759
|
+
}
|
|
66760
|
+
function amount(raw, formatted, usd, decimals) {
|
|
66761
|
+
const rawStr = raw != null ? String(raw) : void 0;
|
|
66762
|
+
return {
|
|
66763
|
+
raw: rawStr,
|
|
66764
|
+
formatted: num12(formatted) ?? formatRaw(rawStr, decimals),
|
|
66765
|
+
usd: num12(usd)
|
|
66766
|
+
};
|
|
66767
|
+
}
|
|
66768
|
+
function withCuratorEntity(id, entity) {
|
|
66769
|
+
if (!id.curator || !entity) return id;
|
|
66770
|
+
return { ...id, curator: { ...id.curator, entity } };
|
|
66771
|
+
}
|
|
66772
|
+
function sum(a, b) {
|
|
66773
|
+
if (a === void 0 && b === void 0) return void 0;
|
|
66774
|
+
return (a ?? 0) + (b ?? 0);
|
|
66775
|
+
}
|
|
66247
66776
|
|
|
66248
66777
|
// src/terms/vault/input.ts
|
|
66249
|
-
var
|
|
66778
|
+
var num13 = (v) => {
|
|
66250
66779
|
if (typeof v === "number") return Number.isFinite(v) ? v : void 0;
|
|
66251
66780
|
if (typeof v === "string" && v.trim() !== "") {
|
|
66252
66781
|
const n = Number(v);
|
|
@@ -66254,7 +66783,7 @@ var num12 = (v) => {
|
|
|
66254
66783
|
}
|
|
66255
66784
|
return void 0;
|
|
66256
66785
|
};
|
|
66257
|
-
var
|
|
66786
|
+
var str6 = (v) => typeof v === "string" && v.trim() !== "" ? v : void 0;
|
|
66258
66787
|
var bool2 = (v) => typeof v === "boolean" ? v : void 0;
|
|
66259
66788
|
var fromRaw = (raw, decimals) => {
|
|
66260
66789
|
const s = raw == null ? void 0 : String(raw);
|
|
@@ -66262,69 +66791,86 @@ var fromRaw = (raw, decimals) => {
|
|
|
66262
66791
|
const n = Number(s) / 10 ** decimals;
|
|
66263
66792
|
return Number.isFinite(n) ? n : void 0;
|
|
66264
66793
|
};
|
|
66794
|
+
function sdkRates(row, provider) {
|
|
66795
|
+
if (!SDK_FRACTION_RATE_PROVIDERS.has(provider)) {
|
|
66796
|
+
return {
|
|
66797
|
+
supplyRate: num13(row.supplyRate),
|
|
66798
|
+
rewardsRate: num13(row.rewardsRate),
|
|
66799
|
+
totalRate: num13(row.depositRate)
|
|
66800
|
+
};
|
|
66801
|
+
}
|
|
66802
|
+
const pct2 = (v) => {
|
|
66803
|
+
const n = num13(v);
|
|
66804
|
+
return n === void 0 ? void 0 : n * 100;
|
|
66805
|
+
};
|
|
66806
|
+
return {
|
|
66807
|
+
// GMX splits fee APY from incentive APR; HyperCore reports one number.
|
|
66808
|
+
supplyRate: pct2(row.baseApy ?? row.apr),
|
|
66809
|
+
rewardsRate: pct2(row.bonusApr),
|
|
66810
|
+
totalRate: pct2(row.apy ?? row.apr)
|
|
66811
|
+
};
|
|
66812
|
+
}
|
|
66265
66813
|
function toVaultTermInput(vault, provider, chainId) {
|
|
66266
66814
|
const row = vault;
|
|
66267
|
-
const address =
|
|
66815
|
+
const address = str6(row.address)?.toLowerCase();
|
|
66268
66816
|
if (!address) return void 0;
|
|
66269
|
-
const assetDecimals =
|
|
66817
|
+
const assetDecimals = num13(row.assetDecimals) ?? num13(row.decimals);
|
|
66270
66818
|
const asset = row.asset;
|
|
66271
66819
|
return {
|
|
66272
66820
|
provider,
|
|
66273
66821
|
chainId,
|
|
66274
66822
|
address,
|
|
66275
66823
|
vaultUid: `vault.${provider}:${chainId}:${address}`,
|
|
66276
|
-
name:
|
|
66277
|
-
brand:
|
|
66278
|
-
curatorName:
|
|
66279
|
-
description:
|
|
66824
|
+
name: str6(row.displayName) ?? str6(row.name),
|
|
66825
|
+
brand: str6(row.brand),
|
|
66826
|
+
curatorName: str6(row.curatorName),
|
|
66827
|
+
description: str6(row.description),
|
|
66280
66828
|
asset: {
|
|
66281
66829
|
chainId,
|
|
66282
|
-
address:
|
|
66283
|
-
symbol:
|
|
66284
|
-
name:
|
|
66830
|
+
address: str6(row.underlying)?.toLowerCase() ?? "",
|
|
66831
|
+
symbol: str6(asset?.symbol),
|
|
66832
|
+
name: str6(asset?.name),
|
|
66285
66833
|
decimals: assetDecimals,
|
|
66286
|
-
assetGroup:
|
|
66287
|
-
logoURI:
|
|
66834
|
+
assetGroup: str6(asset?.assetGroup),
|
|
66835
|
+
logoURI: str6(asset?.logoURI)
|
|
66288
66836
|
},
|
|
66289
|
-
|
|
66290
|
-
rewardsRate: num12(row.rewardsRate),
|
|
66291
|
-
totalRate: num12(row.depositRate),
|
|
66837
|
+
...sdkRates(row, provider),
|
|
66292
66838
|
isForwardApr: bool2(row.isForwardApr),
|
|
66293
|
-
aprWindow:
|
|
66839
|
+
aprWindow: str6(row.aprWindow),
|
|
66294
66840
|
// GMX / HyperCore / Pendle report USD only and set the token-denominated
|
|
66295
66841
|
// fields to their USD figure — `totalAssetsFormatted` is the cross-provider
|
|
66296
66842
|
// magnitude either way, so prefer it over re-deriving from raw.
|
|
66297
|
-
totalAssets:
|
|
66298
|
-
totalAssetsUsd:
|
|
66299
|
-
liquidity:
|
|
66300
|
-
liquidityUsd:
|
|
66301
|
-
instantLiquidityRatio:
|
|
66843
|
+
totalAssets: num13(row.totalAssetsFormatted) ?? fromRaw(row.totalAssets, assetDecimals),
|
|
66844
|
+
totalAssetsUsd: num13(row.totalAssetsUsd) ?? num13(row.tvlUsd),
|
|
66845
|
+
liquidity: num13(row.liquidityFormatted) ?? fromRaw(row.liquidity, assetDecimals),
|
|
66846
|
+
liquidityUsd: num13(row.liquidityUsd),
|
|
66847
|
+
instantLiquidityRatio: num13(row.instantLiquidityRatio),
|
|
66302
66848
|
totalBorrowed: fromRaw(row.totalBorrowed, assetDecimals),
|
|
66303
66849
|
expectedLiquidity: fromRaw(row.expectedLiquidity, assetDecimals),
|
|
66304
|
-
withdrawalMode:
|
|
66305
|
-
withdrawalCooldownSeconds:
|
|
66306
|
-
withdrawFeeBps:
|
|
66307
|
-
fee:
|
|
66308
|
-
swapFeeRate:
|
|
66309
|
-
redemptionDiscountBps:
|
|
66850
|
+
withdrawalMode: str6(row.withdrawalMode),
|
|
66851
|
+
withdrawalCooldownSeconds: num13(row.withdrawalCooldownSeconds),
|
|
66852
|
+
withdrawFeeBps: num13(row.withdrawFeeBps),
|
|
66853
|
+
fee: num13(row.fee),
|
|
66854
|
+
swapFeeRate: num13(row.feeRate),
|
|
66855
|
+
redemptionDiscountBps: num13(row.redemptionDiscountBps),
|
|
66310
66856
|
instantRedeemEnabled: bool2(row.instantRedeemEnabled),
|
|
66311
66857
|
isMintable: bool2(row.isMintable),
|
|
66312
|
-
depositCapacity:
|
|
66313
|
-
supplyCap:
|
|
66858
|
+
depositCapacity: str6(row.depositCapacity),
|
|
66859
|
+
supplyCap: str6(row.supplyCap),
|
|
66314
66860
|
paused: bool2(row.isPaused),
|
|
66315
66861
|
depositsPaused: bool2(row.isDepositPaused),
|
|
66316
66862
|
withdrawalsPaused: bool2(row.isWithdrawalPaused),
|
|
66317
66863
|
isClosed: bool2(row.isClosed),
|
|
66318
66864
|
whitelisted: bool2(row.whitelisted),
|
|
66319
|
-
expiry:
|
|
66320
|
-
timelock:
|
|
66321
|
-
owner:
|
|
66322
|
-
curator:
|
|
66323
|
-
guardian:
|
|
66324
|
-
feeRecipient:
|
|
66325
|
-
solvency:
|
|
66326
|
-
navOracle:
|
|
66327
|
-
yieldProfile:
|
|
66865
|
+
expiry: num13(row.expiry),
|
|
66866
|
+
timelock: num13(row.timelock),
|
|
66867
|
+
owner: str6(row.owner),
|
|
66868
|
+
curator: str6(row.curator),
|
|
66869
|
+
guardian: str6(row.guardian),
|
|
66870
|
+
feeRecipient: str6(row.feeRecipient),
|
|
66871
|
+
solvency: str6(row.solvency),
|
|
66872
|
+
navOracle: str6(row.navOracle),
|
|
66873
|
+
yieldProfile: str6(row.yieldProfile),
|
|
66328
66874
|
exposures: Array.isArray(row.exposures) ? row.exposures : void 0
|
|
66329
66875
|
};
|
|
66330
66876
|
}
|
|
@@ -66341,7 +66887,7 @@ function vaultTermInputFromEarnMarket(m) {
|
|
|
66341
66887
|
name: m.name,
|
|
66342
66888
|
brand: m.brand,
|
|
66343
66889
|
curatorName: m.brand,
|
|
66344
|
-
description:
|
|
66890
|
+
description: str6(meta.description),
|
|
66345
66891
|
asset: {
|
|
66346
66892
|
chainId: m.chainId,
|
|
66347
66893
|
address: m.asset.address,
|
|
@@ -66354,46 +66900,56 @@ function vaultTermInputFromEarnMarket(m) {
|
|
|
66354
66900
|
rewardsRate: m.rate.rewards,
|
|
66355
66901
|
totalRate: m.rate.total,
|
|
66356
66902
|
isForwardApr: bool2(meta.isForwardApr),
|
|
66357
|
-
aprWindow:
|
|
66903
|
+
aprWindow: str6(meta.aprWindow),
|
|
66358
66904
|
totalAssets: m.tvl.formatted,
|
|
66359
66905
|
totalAssetsUsd: m.tvl.usd,
|
|
66360
66906
|
liquidity: m.liquidity?.formatted,
|
|
66361
66907
|
liquidityUsd: m.liquidity?.usd,
|
|
66362
|
-
instantLiquidityRatio:
|
|
66363
|
-
totalBorrowed:
|
|
66364
|
-
expectedLiquidity:
|
|
66908
|
+
instantLiquidityRatio: num13(meta.instantLiquidityRatio),
|
|
66909
|
+
totalBorrowed: num13(meta.totalBorrowed),
|
|
66910
|
+
expectedLiquidity: num13(meta.expectedLiquidity),
|
|
66365
66911
|
withdrawalMode: m.exit.mode,
|
|
66366
66912
|
withdrawalCooldownSeconds: m.exit.cooldownSecs,
|
|
66367
66913
|
withdrawFeeBps: m.exit.feeBps,
|
|
66368
66914
|
fee: m.rate.fee,
|
|
66369
|
-
swapFeeRate:
|
|
66370
|
-
redemptionDiscountBps:
|
|
66915
|
+
swapFeeRate: num13(meta.feeRate),
|
|
66916
|
+
redemptionDiscountBps: num13(meta.redemptionDiscountBps),
|
|
66371
66917
|
instantRedeemEnabled: bool2(meta.instantRedeemEnabled),
|
|
66372
66918
|
// `canDeposit` already folds in the cap, the pause and the gate, so it is
|
|
66373
66919
|
// the authoritative answer — but the REASON is what a disabled CTA renders,
|
|
66374
66920
|
// and that only survives in the raw fields.
|
|
66375
66921
|
isMintable: m.availability.canDeposit ? void 0 : false,
|
|
66376
66922
|
depositCapacity: m.depositCapacity,
|
|
66377
|
-
supplyCap:
|
|
66923
|
+
supplyCap: str6(meta.supplyCap),
|
|
66378
66924
|
paused: m.availability.gating === "paused" ? true : void 0,
|
|
66379
66925
|
withdrawalsPaused: m.availability.canWithdraw ? void 0 : true,
|
|
66380
66926
|
isClosed: bool2(meta.isClosed),
|
|
66381
66927
|
whitelisted: bool2(meta.whitelisted),
|
|
66382
66928
|
expiry: m.maturity?.maturity,
|
|
66383
|
-
timelock:
|
|
66384
|
-
owner:
|
|
66385
|
-
curator:
|
|
66386
|
-
guardian:
|
|
66387
|
-
feeRecipient:
|
|
66929
|
+
timelock: num13(meta.timelock),
|
|
66930
|
+
owner: str6(meta.owner),
|
|
66931
|
+
curator: str6(meta.curator),
|
|
66932
|
+
guardian: str6(meta.guardian),
|
|
66933
|
+
feeRecipient: str6(meta.feeRecipient),
|
|
66388
66934
|
solvency: m.risk?.counterparty,
|
|
66389
|
-
navOracle:
|
|
66935
|
+
navOracle: str6(meta.navOracle),
|
|
66390
66936
|
yieldProfile: m.risk?.yieldProfile,
|
|
66391
66937
|
exposures: m.refs?.exposures
|
|
66392
66938
|
};
|
|
66393
66939
|
}
|
|
66940
|
+
function originRates(rates) {
|
|
66941
|
+
const supply = num13(rates.supplyRate);
|
|
66942
|
+
const rewards = num13(rates.rewardsRate);
|
|
66943
|
+
const deposit = num13(rates.depositRate);
|
|
66944
|
+
return {
|
|
66945
|
+
supplyRate: supply ?? (deposit !== void 0 && rewards !== void 0 ? deposit - rewards : deposit),
|
|
66946
|
+
rewardsRate: rewards,
|
|
66947
|
+
totalRate: num13(rates.totalRate) ?? deposit
|
|
66948
|
+
};
|
|
66949
|
+
}
|
|
66394
66950
|
function vaultTermInputFromSourceRow(row, chainId) {
|
|
66395
|
-
const provider =
|
|
66396
|
-
const address =
|
|
66951
|
+
const provider = str6(row.provider);
|
|
66952
|
+
const address = str6(row.vaultAddress)?.toLowerCase();
|
|
66397
66953
|
if (!provider || !address) return void 0;
|
|
66398
66954
|
const meta = row.providerMeta ?? {};
|
|
66399
66955
|
const rates = row.rates ?? {};
|
|
@@ -66401,60 +66957,58 @@ function vaultTermInputFromSourceRow(row, chainId) {
|
|
|
66401
66957
|
const liq = row.liquidity ?? {};
|
|
66402
66958
|
const info = row.vaultInfo ?? {};
|
|
66403
66959
|
const assetInfo = row.underlyingInfo?.asset;
|
|
66404
|
-
const assetDecimals =
|
|
66960
|
+
const assetDecimals = num13(row.assetDecimals) ?? num13(assetInfo?.decimals) ?? num13(row.decimals);
|
|
66405
66961
|
return {
|
|
66406
66962
|
provider,
|
|
66407
66963
|
chainId,
|
|
66408
66964
|
address,
|
|
66409
66965
|
vaultUid: `vault.${provider}:${chainId}:${address}`,
|
|
66410
|
-
name:
|
|
66411
|
-
brand:
|
|
66412
|
-
curatorName:
|
|
66413
|
-
description:
|
|
66966
|
+
name: str6(info.name) ?? str6(row.displayName) ?? str6(row.name),
|
|
66967
|
+
brand: str6(row.curatorName) ?? str6(meta.brand),
|
|
66968
|
+
curatorName: str6(row.curatorName),
|
|
66969
|
+
description: str6(meta.description),
|
|
66414
66970
|
asset: {
|
|
66415
66971
|
chainId,
|
|
66416
|
-
address:
|
|
66417
|
-
symbol:
|
|
66972
|
+
address: str6(row.underlying)?.toLowerCase() ?? "",
|
|
66973
|
+
symbol: str6(assetInfo?.symbol),
|
|
66418
66974
|
decimals: assetDecimals,
|
|
66419
|
-
assetGroup:
|
|
66420
|
-
logoURI:
|
|
66975
|
+
assetGroup: str6(info.assetGroup),
|
|
66976
|
+
logoURI: str6(assetInfo?.logoURI)
|
|
66421
66977
|
},
|
|
66422
|
-
|
|
66423
|
-
rewardsRate: num12(rates.rewardsRate),
|
|
66424
|
-
totalRate: num12(rates.totalRate),
|
|
66978
|
+
...originRates(rates),
|
|
66425
66979
|
isForwardApr: bool2(meta.isForwardApr),
|
|
66426
|
-
aprWindow:
|
|
66427
|
-
totalAssets:
|
|
66428
|
-
totalAssetsUsd:
|
|
66429
|
-
liquidity:
|
|
66430
|
-
liquidityUsd:
|
|
66431
|
-
instantLiquidityRatio:
|
|
66980
|
+
aprWindow: str6(meta.aprWindow),
|
|
66981
|
+
totalAssets: num13(tvl.totalAssetsFormatted) ?? fromRaw(tvl.totalAssets, assetDecimals),
|
|
66982
|
+
totalAssetsUsd: num13(tvl.totalAssetsUsd),
|
|
66983
|
+
liquidity: num13(liq.liquidityFormatted) ?? fromRaw(liq.liquidity, assetDecimals),
|
|
66984
|
+
liquidityUsd: num13(liq.liquidityUsd),
|
|
66985
|
+
instantLiquidityRatio: num13(meta.instantLiquidityRatio),
|
|
66432
66986
|
totalBorrowed: fromRaw(meta.totalBorrowed, assetDecimals),
|
|
66433
66987
|
expectedLiquidity: fromRaw(meta.expectedLiquidity, assetDecimals),
|
|
66434
|
-
withdrawalMode:
|
|
66435
|
-
withdrawalCooldownSeconds:
|
|
66436
|
-
withdrawFeeBps:
|
|
66437
|
-
fee:
|
|
66438
|
-
swapFeeRate:
|
|
66439
|
-
redemptionDiscountBps:
|
|
66988
|
+
withdrawalMode: str6(meta.withdrawalMode),
|
|
66989
|
+
withdrawalCooldownSeconds: num13(meta.withdrawalCooldownSeconds),
|
|
66990
|
+
withdrawFeeBps: num13(meta.withdrawFeeBps),
|
|
66991
|
+
fee: num13(rates.fee),
|
|
66992
|
+
swapFeeRate: num13(meta.feeRate),
|
|
66993
|
+
redemptionDiscountBps: num13(meta.redemptionDiscountBps),
|
|
66440
66994
|
instantRedeemEnabled: bool2(meta.instantRedeemEnabled),
|
|
66441
66995
|
isMintable: bool2(meta.isMintable),
|
|
66442
|
-
depositCapacity:
|
|
66443
|
-
supplyCap:
|
|
66996
|
+
depositCapacity: str6(meta.depositCapacity) ?? str6(meta.maxDeposit),
|
|
66997
|
+
supplyCap: str6(meta.supplyCap),
|
|
66444
66998
|
paused: bool2(meta.paused) ?? bool2(meta.isPaused),
|
|
66445
66999
|
depositsPaused: bool2(meta.isDepositPaused),
|
|
66446
67000
|
withdrawalsPaused: bool2(meta.isWithdrawalPaused),
|
|
66447
67001
|
isClosed: bool2(meta.isClosed),
|
|
66448
67002
|
whitelisted: bool2(meta.whitelisted),
|
|
66449
|
-
expiry:
|
|
66450
|
-
timelock:
|
|
66451
|
-
owner:
|
|
66452
|
-
curator:
|
|
66453
|
-
guardian:
|
|
66454
|
-
feeRecipient:
|
|
66455
|
-
solvency:
|
|
66456
|
-
navOracle:
|
|
66457
|
-
yieldProfile:
|
|
67003
|
+
expiry: num13(meta.expiry) ?? num13(meta.maturity),
|
|
67004
|
+
timelock: num13(meta.timelock),
|
|
67005
|
+
owner: str6(meta.owner),
|
|
67006
|
+
curator: str6(meta.curator),
|
|
67007
|
+
guardian: str6(meta.guardian),
|
|
67008
|
+
feeRecipient: str6(meta.feeRecipient),
|
|
67009
|
+
solvency: str6(meta.solvency),
|
|
67010
|
+
navOracle: str6(meta.navOracle),
|
|
67011
|
+
yieldProfile: str6(info.yieldProfile),
|
|
66458
67012
|
exposures: Array.isArray(row.exposures) ? row.exposures : Array.isArray(meta.exposures) ? meta.exposures : void 0
|
|
66459
67013
|
};
|
|
66460
67014
|
}
|
|
@@ -67252,7 +67806,7 @@ async function fetchTokenBalances(chainId, account, tokens, options = {}) {
|
|
|
67252
67806
|
}
|
|
67253
67807
|
|
|
67254
67808
|
// src/terms/input.ts
|
|
67255
|
-
var
|
|
67809
|
+
var num14 = (v) => {
|
|
67256
67810
|
if (v == null) return void 0;
|
|
67257
67811
|
const n = typeof v === "string" ? Number(v) : v;
|
|
67258
67812
|
return Number.isFinite(n) ? n : void 0;
|
|
@@ -67283,12 +67837,12 @@ function toTermSheetInput(row, ctx = {}) {
|
|
|
67283
67837
|
{
|
|
67284
67838
|
category: v?.category ?? k,
|
|
67285
67839
|
label: v?.label,
|
|
67286
|
-
borrowCollateralFactor:
|
|
67287
|
-
collateralFactor:
|
|
67288
|
-
borrowFactor:
|
|
67289
|
-
liquidationPenalty:
|
|
67290
|
-
closeFactor:
|
|
67291
|
-
targetHealthFactor:
|
|
67840
|
+
borrowCollateralFactor: num14(v?.borrowCollateralFactor),
|
|
67841
|
+
collateralFactor: num14(v?.collateralFactor),
|
|
67842
|
+
borrowFactor: num14(v?.borrowFactor),
|
|
67843
|
+
liquidationPenalty: num14(v?.liquidationPenalty),
|
|
67844
|
+
closeFactor: num14(v?.closeFactor),
|
|
67845
|
+
targetHealthFactor: num14(v?.targetHealthFactor),
|
|
67292
67846
|
collateralDisabled: v?.collateralDisabled === true,
|
|
67293
67847
|
debtDisabled: v?.debtDisabled === true
|
|
67294
67848
|
}
|
|
@@ -67296,11 +67850,11 @@ function toTermSheetInput(row, ctx = {}) {
|
|
|
67296
67850
|
) : void 0;
|
|
67297
67851
|
const rewards = pick2(row, "rewards")?.map((r) => ({
|
|
67298
67852
|
asset: r?.asset,
|
|
67299
|
-
depositRate:
|
|
67300
|
-
variableBorrowRate:
|
|
67301
|
-
stableBorrowRate:
|
|
67853
|
+
depositRate: num14(r?.depositRate),
|
|
67854
|
+
variableBorrowRate: num14(r?.variableBorrowRate),
|
|
67855
|
+
stableBorrowRate: num14(r?.stableBorrowRate),
|
|
67302
67856
|
kind: r?.kind,
|
|
67303
|
-
endsAt:
|
|
67857
|
+
endsAt: num14(r?.endsAt),
|
|
67304
67858
|
claim: r?.claim
|
|
67305
67859
|
}));
|
|
67306
67860
|
return {
|
|
@@ -67313,29 +67867,29 @@ function toTermSheetInput(row, ctx = {}) {
|
|
|
67313
67867
|
"underlyingInfo.asset"
|
|
67314
67868
|
),
|
|
67315
67869
|
underlying: pick2(row, "underlying"),
|
|
67316
|
-
decimals:
|
|
67317
|
-
depositRate:
|
|
67318
|
-
variableBorrowRate:
|
|
67319
|
-
stableBorrowRate:
|
|
67320
|
-
intrinsicYield:
|
|
67870
|
+
decimals: num14(pick2(row, "decimals")),
|
|
67871
|
+
depositRate: num14(pick2(row, "depositRate")),
|
|
67872
|
+
variableBorrowRate: num14(pick2(row, "variableBorrowRate")),
|
|
67873
|
+
stableBorrowRate: num14(pick2(row, "stableBorrowRate")),
|
|
67874
|
+
intrinsicYield: num14(pick2(row, "intrinsicYield")),
|
|
67321
67875
|
rewards,
|
|
67322
67876
|
rateModel: pick2(row, "rateModel"),
|
|
67323
|
-
originationFee:
|
|
67324
|
-
totalDeposits:
|
|
67325
|
-
totalDebt:
|
|
67326
|
-
totalDebtStable:
|
|
67327
|
-
totalLiquidity:
|
|
67328
|
-
borrowLiquidity:
|
|
67329
|
-
totalDepositsUsd:
|
|
67330
|
-
totalDebtUsd:
|
|
67331
|
-
totalLiquidityUsd:
|
|
67332
|
-
utilization:
|
|
67333
|
-
irmTotalDeposits:
|
|
67334
|
-
irmTotalDebt:
|
|
67335
|
-
lockupRatio:
|
|
67877
|
+
originationFee: num14(pick2(row, "originationFee")),
|
|
67878
|
+
totalDeposits: num14(pick2(row, "totalDeposits")),
|
|
67879
|
+
totalDebt: num14(pick2(row, "totalDebt")),
|
|
67880
|
+
totalDebtStable: num14(pick2(row, "totalDebtStable")),
|
|
67881
|
+
totalLiquidity: num14(pick2(row, "totalLiquidity")),
|
|
67882
|
+
borrowLiquidity: num14(pick2(row, "borrowLiquidity")),
|
|
67883
|
+
totalDepositsUsd: num14(pick2(row, "totalDepositsUSD", "totalDepositsUsd")),
|
|
67884
|
+
totalDebtUsd: num14(pick2(row, "totalDebtUSD", "totalDebtUsd")),
|
|
67885
|
+
totalLiquidityUsd: num14(pick2(row, "totalLiquidityUSD", "totalLiquidityUsd")),
|
|
67886
|
+
utilization: num14(pick2(row, "utilization")),
|
|
67887
|
+
irmTotalDeposits: num14(pick2(row, "irmTotalDeposits")),
|
|
67888
|
+
irmTotalDebt: num14(pick2(row, "irmTotalDebt")),
|
|
67889
|
+
lockupRatio: num14(pick2(row, "lockupRatio")),
|
|
67336
67890
|
minBorrow: pick2(row, "minBorrow", "caps.minBorrow") ?? void 0,
|
|
67337
|
-
supplyCap:
|
|
67338
|
-
borrowCap:
|
|
67891
|
+
supplyCap: num14(pick2(row, "supplyCap", "caps.supplyCap")),
|
|
67892
|
+
borrowCap: num14(pick2(row, "borrowCap", "caps.borrowCap")),
|
|
67339
67893
|
debtCeiling: pick2(row, "debtCeiling", "caps.debtCeiling"),
|
|
67340
67894
|
isActive: pick2(row, "isActive", "flags.isActive"),
|
|
67341
67895
|
isFrozen: pick2(row, "isFrozen", "flags.isFrozen"),
|
|
@@ -67361,8 +67915,8 @@ function toTermSheetInput(row, ctx = {}) {
|
|
|
67361
67915
|
"flags.variableBorrowDisabled"
|
|
67362
67916
|
),
|
|
67363
67917
|
config,
|
|
67364
|
-
closeFactor:
|
|
67365
|
-
targetHealthFactor:
|
|
67918
|
+
closeFactor: num14(pick2(row, "closeFactor")),
|
|
67919
|
+
targetHealthFactor: num14(pick2(row, "targetHealthFactor")),
|
|
67366
67920
|
fixedTerm: pick2(row, "fixedTerm") ?? ctx.fixedTerm,
|
|
67367
67921
|
terms: pick2(row, "terms"),
|
|
67368
67922
|
market: resolveMarketDescriptors(row, ctx.market)
|
|
@@ -69071,7 +69625,7 @@ function validateTermSheet(sheet) {
|
|
|
69071
69625
|
if (g.powers?.length)
|
|
69072
69626
|
fail("immutable-powers", "immutable governance must not carry powers");
|
|
69073
69627
|
}
|
|
69074
|
-
if (g.timelockSecs && g.controllerKind && g.controllerKind !== "TIMELOCK")
|
|
69628
|
+
if (g.timelockSecs && g.controllerKind && g.controllerKind !== "TIMELOCK" && g.timelockSource !== "on-chain")
|
|
69075
69629
|
fail(
|
|
69076
69630
|
"timelock-without-timelock-root",
|
|
69077
69631
|
`timelockSecs set but controllerKind is ${g.controllerKind}`
|
|
@@ -69089,466 +69643,6 @@ function validateTermSheets(sheets) {
|
|
|
69089
69643
|
return sheets.flatMap((s) => validateTermSheet(s));
|
|
69090
69644
|
}
|
|
69091
69645
|
|
|
69092
|
-
// src/earn/labels.ts
|
|
69093
|
-
var VENUE_KIND_LABELS = {
|
|
69094
|
-
lending: "Lending markets",
|
|
69095
|
-
vault: "Vaults"
|
|
69096
|
-
};
|
|
69097
|
-
var VENUE_KIND_DESCRIPTIONS = {
|
|
69098
|
-
lending: "Supply into a lending market. Same-block exit, bounded by liquidity.",
|
|
69099
|
-
vault: "Deposit into a yield vault. Exit terms vary per vault."
|
|
69100
|
-
};
|
|
69101
|
-
var EXIT_MODE_LABELS = {
|
|
69102
|
-
instant: "Instant",
|
|
69103
|
-
"instant-capped": "Instant (capped)",
|
|
69104
|
-
"instant-or-queued": "Instant or queue",
|
|
69105
|
-
"fee-or-queued": "Fee or queue",
|
|
69106
|
-
"fixed-cooldown": "Cooldown",
|
|
69107
|
-
queued: "Queued",
|
|
69108
|
-
"request-based": "Request",
|
|
69109
|
-
"market-sale": "Market sale",
|
|
69110
|
-
"at-maturity": "At maturity",
|
|
69111
|
-
"off-chain": "Off-chain",
|
|
69112
|
-
"dex-only": "DEX only"
|
|
69113
|
-
};
|
|
69114
|
-
var EXIT_MODE_DESCRIPTIONS = {
|
|
69115
|
-
instant: "Withdraw any time.",
|
|
69116
|
-
"instant-capped": "Withdraw up to the available liquidity.",
|
|
69117
|
-
"instant-or-queued": "Withdraw instantly, or queue for the rest.",
|
|
69118
|
-
"fee-or-queued": "Instant exit for a fee, or queue for free.",
|
|
69119
|
-
"fixed-cooldown": "Request, wait out a cooldown, then claim.",
|
|
69120
|
-
queued: "Withdrawals are queued.",
|
|
69121
|
-
"request-based": "Withdrawals need a request and a later claim.",
|
|
69122
|
-
"market-sale": "Exit by selling the position on a market.",
|
|
69123
|
-
"at-maturity": "Locked until maturity.",
|
|
69124
|
-
"off-chain": "Exit is settled off-chain.",
|
|
69125
|
-
"dex-only": "Exit only by selling on a DEX."
|
|
69126
|
-
};
|
|
69127
|
-
var ACTION_LABELS = {
|
|
69128
|
-
deposit: "Deposit",
|
|
69129
|
-
withdraw: "Withdraw",
|
|
69130
|
-
"request-withdraw": "Request withdrawal",
|
|
69131
|
-
claim: "Claim",
|
|
69132
|
-
cancel: "Cancel request"
|
|
69133
|
-
};
|
|
69134
|
-
var GATING_LABELS = {
|
|
69135
|
-
"allowlist-contract": "Permissioned",
|
|
69136
|
-
kyc: "KYC required",
|
|
69137
|
-
"cap-full": "Cap full",
|
|
69138
|
-
paused: "Paused",
|
|
69139
|
-
frozen: "Frozen",
|
|
69140
|
-
"collateral-only": "No yield",
|
|
69141
|
-
matured: "Matured"
|
|
69142
|
-
};
|
|
69143
|
-
var RATE_KIND_LABELS = {
|
|
69144
|
-
"variable-curve": "Variable (utilization)",
|
|
69145
|
-
"variable-managed": "Variable (managed)",
|
|
69146
|
-
"user-set": "Borrower-set",
|
|
69147
|
-
"fixed-term": "Fixed term",
|
|
69148
|
-
"fixed-open": "Fixed",
|
|
69149
|
-
"zero-interest": "Interest-free",
|
|
69150
|
-
prepaid: "Prepaid",
|
|
69151
|
-
"nav-accrual": "NAV accrual",
|
|
69152
|
-
none: "No rate"
|
|
69153
|
-
};
|
|
69154
|
-
var RATE_SOURCE_LABELS = {
|
|
69155
|
-
chain: "On-chain",
|
|
69156
|
-
api: "Protocol API",
|
|
69157
|
-
oracle: "Oracle",
|
|
69158
|
-
realized: "Realized"
|
|
69159
|
-
};
|
|
69160
|
-
var VENUE_BRANDS = {
|
|
69161
|
-
MORPHO_BLUE: "Morpho Blue",
|
|
69162
|
-
MORPHO_MIDNIGHT: "Morpho Midnight",
|
|
69163
|
-
FLUID: "Fluid",
|
|
69164
|
-
GEARBOX_V3: "Gearbox V3",
|
|
69165
|
-
AAVE_V4: "Aave V4",
|
|
69166
|
-
AAVE_V3: "Aave V3",
|
|
69167
|
-
AAVE_V2: "Aave V2",
|
|
69168
|
-
SKY: "Sky",
|
|
69169
|
-
USDD: "USDD",
|
|
69170
|
-
LIQUITY_V2: "Liquity V2",
|
|
69171
|
-
SILO_V2: "Silo V2",
|
|
69172
|
-
SILO_V3: "Silo V3",
|
|
69173
|
-
EXACTLY: "Exactly",
|
|
69174
|
-
TELLER: "Teller",
|
|
69175
|
-
TERM_FINANCE: "Term Finance",
|
|
69176
|
-
TERMMAX: "TermMax",
|
|
69177
|
-
LLAMALEND: "LlamaLend",
|
|
69178
|
-
CURVANCE: "Curvance",
|
|
69179
|
-
INVERSE: "Inverse",
|
|
69180
|
-
FRANKENCOIN: "Frankencoin",
|
|
69181
|
-
RIVER: "River",
|
|
69182
|
-
RESUPPLY: "Resupply",
|
|
69183
|
-
TANGENT: "Tangent",
|
|
69184
|
-
DOLOMITE: "Dolomite",
|
|
69185
|
-
LISTA_DAO: "Lista",
|
|
69186
|
-
FLUX_FINANCE: "Flux",
|
|
69187
|
-
COMPOUND_V2: "Compound V2",
|
|
69188
|
-
COMPOUND_V3: "Compound V3",
|
|
69189
|
-
EULER_V2: "Euler V2",
|
|
69190
|
-
INIT: "Init"
|
|
69191
|
-
};
|
|
69192
|
-
var VAULT_PROVIDER_BRANDS = {
|
|
69193
|
-
fluid: "Fluid",
|
|
69194
|
-
gearbox: "Gearbox",
|
|
69195
|
-
morpho: "Morpho",
|
|
69196
|
-
lista: "Lista",
|
|
69197
|
-
silo: "Silo",
|
|
69198
|
-
"euler-earn": "Euler",
|
|
69199
|
-
termmax: "TermMax",
|
|
69200
|
-
lst: "Liquid staking",
|
|
69201
|
-
savings: "Savings",
|
|
69202
|
-
lagoon: "Lagoon",
|
|
69203
|
-
"aave-earn": "Aave",
|
|
69204
|
-
upshift: "Upshift",
|
|
69205
|
-
yearn: "Yearn",
|
|
69206
|
-
hypercore: "HyperLiquid",
|
|
69207
|
-
gmx: "GMX",
|
|
69208
|
-
pendle: "Pendle"
|
|
69209
|
-
};
|
|
69210
|
-
function isInstanceSegment(seg) {
|
|
69211
|
-
if (/^\d+$/.test(seg)) return true;
|
|
69212
|
-
if (/^0X[0-9A-F]+$/i.test(seg)) return true;
|
|
69213
|
-
return seg.length >= 8 && /^[0-9A-F]+$/i.test(seg);
|
|
69214
|
-
}
|
|
69215
|
-
function venueBrand(venue) {
|
|
69216
|
-
if (venue.startsWith("vault.")) {
|
|
69217
|
-
const provider = venue.slice("vault.".length);
|
|
69218
|
-
return VAULT_PROVIDER_BRANDS[provider] ?? provider;
|
|
69219
|
-
}
|
|
69220
|
-
const segments = venue.split("_");
|
|
69221
|
-
const cut = segments.findIndex(isInstanceSegment);
|
|
69222
|
-
const family = (cut > 0 ? segments.slice(0, cut) : segments).join("_");
|
|
69223
|
-
if (VENUE_BRANDS[family]) return VENUE_BRANDS[family];
|
|
69224
|
-
let best;
|
|
69225
|
-
for (const key3 of Object.keys(VENUE_BRANDS)) {
|
|
69226
|
-
if (family.startsWith(key3) && (!best || key3.length > best.length))
|
|
69227
|
-
best = key3;
|
|
69228
|
-
}
|
|
69229
|
-
return best ? VENUE_BRANDS[best] : family;
|
|
69230
|
-
}
|
|
69231
|
-
var EARN_LABELS = {
|
|
69232
|
-
venueKind: VENUE_KIND_LABELS,
|
|
69233
|
-
exitMode: EXIT_MODE_LABELS,
|
|
69234
|
-
action: ACTION_LABELS,
|
|
69235
|
-
gating: GATING_LABELS,
|
|
69236
|
-
rateKind: RATE_KIND_LABELS,
|
|
69237
|
-
rateSource: RATE_SOURCE_LABELS
|
|
69238
|
-
};
|
|
69239
|
-
var EARN_DESCRIPTIONS = {
|
|
69240
|
-
venueKind: VENUE_KIND_DESCRIPTIONS,
|
|
69241
|
-
exitMode: EXIT_MODE_DESCRIPTIONS
|
|
69242
|
-
};
|
|
69243
|
-
function earnLabel(dimension, key3) {
|
|
69244
|
-
return EARN_LABELS[dimension][key3] ?? key3;
|
|
69245
|
-
}
|
|
69246
|
-
function earnDescription(dimension, key3) {
|
|
69247
|
-
return EARN_DESCRIPTIONS[dimension][key3];
|
|
69248
|
-
}
|
|
69249
|
-
function earnMarketLabel(input) {
|
|
69250
|
-
const asset = input.assetSymbol?.trim();
|
|
69251
|
-
if (!asset) return input.fallbackName ?? "";
|
|
69252
|
-
const collaterals = (input.collateralSymbols ?? []).map((c) => c?.trim()).filter((c) => !!c);
|
|
69253
|
-
const distinct = [...new Set(collaterals)];
|
|
69254
|
-
if (distinct.length === 1) return `${asset} \xB7 vs ${distinct[0]}`;
|
|
69255
|
-
return asset;
|
|
69256
|
-
}
|
|
69257
|
-
var SAME_BLOCK_EXIT_MODES = /* @__PURE__ */ new Set([
|
|
69258
|
-
"instant",
|
|
69259
|
-
"instant-capped"
|
|
69260
|
-
]);
|
|
69261
|
-
function isIlliquid(input) {
|
|
69262
|
-
if (!input.exitMode || !SAME_BLOCK_EXIT_MODES.has(input.exitMode))
|
|
69263
|
-
return false;
|
|
69264
|
-
if (!input.tvlUsd || input.tvlUsd <= 0) return false;
|
|
69265
|
-
if (input.liquidityUsd === void 0) return false;
|
|
69266
|
-
return input.liquidityUsd <= 0;
|
|
69267
|
-
}
|
|
69268
|
-
|
|
69269
|
-
// src/earn/normalize.ts
|
|
69270
|
-
function num14(v) {
|
|
69271
|
-
if (v == null || v === "") return void 0;
|
|
69272
|
-
const n = typeof v === "number" ? v : Number(v);
|
|
69273
|
-
return Number.isFinite(n) ? n : void 0;
|
|
69274
|
-
}
|
|
69275
|
-
function str6(v) {
|
|
69276
|
-
if (typeof v === "string") return v.length > 0 ? v : void 0;
|
|
69277
|
-
if (typeof v === "number" && Number.isFinite(v)) return String(v);
|
|
69278
|
-
return void 0;
|
|
69279
|
-
}
|
|
69280
|
-
function addr2(v) {
|
|
69281
|
-
return str6(v)?.toLowerCase();
|
|
69282
|
-
}
|
|
69283
|
-
function yieldProfile(v) {
|
|
69284
|
-
return v === "yield-bearing" || v === "volatile" ? v : void 0;
|
|
69285
|
-
}
|
|
69286
|
-
function denomination(v) {
|
|
69287
|
-
return v === "stable" || v === "volatile" ? v : void 0;
|
|
69288
|
-
}
|
|
69289
|
-
function usdValue(formatted, priceUsd) {
|
|
69290
|
-
if (formatted === void 0 || priceUsd === void 0) return void 0;
|
|
69291
|
-
const v = formatted * priceUsd;
|
|
69292
|
-
return Number.isFinite(v) ? v : void 0;
|
|
69293
|
-
}
|
|
69294
|
-
function formatRaw(raw, decimals) {
|
|
69295
|
-
if (raw == null || raw === "") return void 0;
|
|
69296
|
-
let value;
|
|
69297
|
-
try {
|
|
69298
|
-
value = BigInt(raw);
|
|
69299
|
-
} catch {
|
|
69300
|
-
return void 0;
|
|
69301
|
-
}
|
|
69302
|
-
if (decimals <= 0) return Number(value);
|
|
69303
|
-
const base = 10n ** BigInt(decimals);
|
|
69304
|
-
const whole = value / base;
|
|
69305
|
-
const frac = value % base;
|
|
69306
|
-
const n = Number(whole) + Number(frac) / Number(base);
|
|
69307
|
-
return Number.isFinite(n) ? n : void 0;
|
|
69308
|
-
}
|
|
69309
|
-
|
|
69310
|
-
// src/earn/fromVault.ts
|
|
69311
|
-
var FRACTION_RATE_PROVIDERS = /* @__PURE__ */ new Set();
|
|
69312
|
-
var SDK_FRACTION_RATE_PROVIDERS = /* @__PURE__ */ new Set([
|
|
69313
|
-
"hypercore",
|
|
69314
|
-
"gmx"
|
|
69315
|
-
]);
|
|
69316
|
-
var RATE_SOURCE = {
|
|
69317
|
-
morpho: "api",
|
|
69318
|
-
silo: "api",
|
|
69319
|
-
lagoon: "api",
|
|
69320
|
-
hypercore: "api",
|
|
69321
|
-
gmx: "api",
|
|
69322
|
-
upshift: "api",
|
|
69323
|
-
yearn: "api",
|
|
69324
|
-
"aave-earn": "api",
|
|
69325
|
-
pendle: "api",
|
|
69326
|
-
lista: "chain",
|
|
69327
|
-
fluid: "chain",
|
|
69328
|
-
gearbox: "chain",
|
|
69329
|
-
"euler-earn": "chain",
|
|
69330
|
-
termmax: "chain",
|
|
69331
|
-
lst: "chain",
|
|
69332
|
-
savings: "chain"
|
|
69333
|
-
};
|
|
69334
|
-
var RATE_KIND = {
|
|
69335
|
-
morpho: "variable-curve",
|
|
69336
|
-
lista: "variable-curve",
|
|
69337
|
-
silo: "variable-curve",
|
|
69338
|
-
"euler-earn": "variable-curve",
|
|
69339
|
-
fluid: "variable-curve",
|
|
69340
|
-
gearbox: "variable-curve",
|
|
69341
|
-
"aave-earn": "variable-curve",
|
|
69342
|
-
// The TermMax VAULT is a perpetual curated 4626 whose curator rolls
|
|
69343
|
-
// fixed-term FT positions — the vault itself has no maturity and no locked
|
|
69344
|
-
// rate. `fixed-term` here claimed both, producing a "fixed" rate with no date
|
|
69345
|
-
// attached to it. The LENDER `TERMMAX_*` is fixed-term; this is not.
|
|
69346
|
-
termmax: "variable-managed",
|
|
69347
|
-
// A PT's implied APY is locked in at purchase and realized only by holding
|
|
69348
|
-
// to maturity — the same promise TermMax's FT makes, reached by a different
|
|
69349
|
-
// mechanism (an AMM discount rather than a quoted curve).
|
|
69350
|
-
pendle: "fixed-term",
|
|
69351
|
-
savings: "variable-managed",
|
|
69352
|
-
lst: "variable-managed",
|
|
69353
|
-
lagoon: "variable-managed",
|
|
69354
|
-
upshift: "variable-managed",
|
|
69355
|
-
yearn: "variable-managed",
|
|
69356
|
-
hypercore: "realized",
|
|
69357
|
-
gmx: "realized"
|
|
69358
|
-
};
|
|
69359
|
-
function resolveExitMode2(provider, meta, tvl, liq) {
|
|
69360
|
-
const declared = str6(meta.withdrawalMode);
|
|
69361
|
-
if (declared) return declared;
|
|
69362
|
-
const fallback = vaultTraits(provider)?.defaultExitMode ?? "instant";
|
|
69363
|
-
if (fallback !== "instant-capped") return fallback;
|
|
69364
|
-
const total = num14(tvl?.totalAssetsFormatted) ?? num14(tvl?.totalAssetsUsd);
|
|
69365
|
-
const available = num14(liq?.liquidityFormatted) ?? num14(liq?.liquidityUsd);
|
|
69366
|
-
if (total === void 0 || available === void 0) return "instant-capped";
|
|
69367
|
-
if (total <= 0) return "instant";
|
|
69368
|
-
return available >= total ? "instant" : "instant-capped";
|
|
69369
|
-
}
|
|
69370
|
-
function earnMarketFromVault(row, chainId, opts = {}) {
|
|
69371
|
-
const provider = str6(row.provider);
|
|
69372
|
-
const address = str6(row.vaultAddress)?.toLowerCase();
|
|
69373
|
-
const underlying = str6(row.underlying)?.toLowerCase();
|
|
69374
|
-
if (!provider || !address || !underlying) return void 0;
|
|
69375
|
-
const meta = row.providerMeta ?? {};
|
|
69376
|
-
const info = row.vaultInfo ?? {};
|
|
69377
|
-
const rates = row.rates ?? {};
|
|
69378
|
-
const tvl = row.tvl ?? {};
|
|
69379
|
-
const liq = row.liquidity ?? {};
|
|
69380
|
-
const shareDecimals = num14(row.decimals) ?? 18;
|
|
69381
|
-
const assetDecimals = num14(row.assetDecimals) ?? num14(row.underlyingInfo?.asset?.decimals) ?? shareDecimals;
|
|
69382
|
-
const toPercent2 = (v) => ratePercent(v, provider, opts.fractionRateProviders);
|
|
69383
|
-
const base = toPercent2(rates.depositRate ?? rates.supplyRate);
|
|
69384
|
-
const rewards = toPercent2(rates.rewardsRate);
|
|
69385
|
-
const total = toPercent2(rates.totalRate) ?? sum(base, rewards) ?? 0;
|
|
69386
|
-
const rate = {
|
|
69387
|
-
total,
|
|
69388
|
-
base,
|
|
69389
|
-
rewards,
|
|
69390
|
-
// A vault has no separate intrinsic leg — whatever it pays IS the venue's
|
|
69391
|
-
// own yield. Leaving this undefined rendered an empty "Venue APR" on every
|
|
69392
|
-
// vault row, which read as "this vault pays nothing".
|
|
69393
|
-
marketOwn: total,
|
|
69394
|
-
// ...and for the same reason it can never be pass-through.
|
|
69395
|
-
passthrough: false,
|
|
69396
|
-
kind: resolveRateKind(provider, meta),
|
|
69397
|
-
source: RATE_SOURCE[provider] ?? "api",
|
|
69398
|
-
// The curator's cut. Dropped entirely until now, which left the earn row
|
|
69399
|
-
// unable to say why its net rate sits below the gross one — and left the
|
|
69400
|
-
// term sheet built from this row with no fee schedule at all.
|
|
69401
|
-
fee: toPercent2(rates.fee)
|
|
69402
|
-
};
|
|
69403
|
-
const maturity = resolveMaturity(meta);
|
|
69404
|
-
const availability = resolveAvailability(meta, maturity);
|
|
69405
|
-
const exitMode = resolveExitMode2(provider, meta, tvl, liq);
|
|
69406
|
-
return {
|
|
69407
|
-
earnUid: buildVaultEarnUid(provider, chainId, address),
|
|
69408
|
-
chainId,
|
|
69409
|
-
venue: vaultVenue(provider),
|
|
69410
|
-
venueKind: "vault",
|
|
69411
|
-
// Curator first (it names the actual operator), then the provider brand.
|
|
69412
|
-
brand: str6(row.curatorName) ?? venueBrand(vaultVenue(provider)),
|
|
69413
|
-
name: str6(info.name) ?? str6(row.displayName) ?? str6(row.name),
|
|
69414
|
-
ref: address,
|
|
69415
|
-
logoURI: str6(info.logoURI) ?? str6(row.underlyingInfo?.asset?.logoURI),
|
|
69416
|
-
asset: {
|
|
69417
|
-
address: underlying,
|
|
69418
|
-
symbol: str6(row.underlyingInfo?.asset?.symbol) ?? "",
|
|
69419
|
-
decimals: assetDecimals,
|
|
69420
|
-
assetGroup: str6(info.assetGroup),
|
|
69421
|
-
priceUsd: num14(row.underlyingInfo?.prices?.priceUsd)
|
|
69422
|
-
},
|
|
69423
|
-
// The vault IS a share token by construction; carry it so a withdraw in
|
|
69424
|
-
// share units can be built without a second lookup.
|
|
69425
|
-
shareToken: {
|
|
69426
|
-
address,
|
|
69427
|
-
symbol: str6(info.symbol) ?? str6(row.symbol) ?? "",
|
|
69428
|
-
decimals: shareDecimals
|
|
69429
|
-
},
|
|
69430
|
-
rate,
|
|
69431
|
-
// The vault origin reports RAW base units + a pre-formatted convenience
|
|
69432
|
-
// field. Carry both; fall back to formatting the raw amount ourselves so
|
|
69433
|
-
// `formatted` — the field consumers sort on — is never silently absent.
|
|
69434
|
-
tvl: amount(
|
|
69435
|
-
tvl.totalAssets,
|
|
69436
|
-
tvl.totalAssetsFormatted,
|
|
69437
|
-
tvl.totalAssetsUsd,
|
|
69438
|
-
assetDecimals
|
|
69439
|
-
),
|
|
69440
|
-
liquidity: liq.liquidity != null || liq.liquidityUsd != null ? amount(
|
|
69441
|
-
liq.liquidity,
|
|
69442
|
-
liq.liquidityFormatted,
|
|
69443
|
-
liq.liquidityUsd,
|
|
69444
|
-
assetDecimals
|
|
69445
|
-
) : void 0,
|
|
69446
|
-
depositCapacity: str6(meta.depositCapacity) ?? str6(meta.maxDeposit),
|
|
69447
|
-
maturity,
|
|
69448
|
-
exit: {
|
|
69449
|
-
mode: exitMode,
|
|
69450
|
-
settlement: str6(meta.redemptionType),
|
|
69451
|
-
cooldownSecs: num14(meta.withdrawalCooldownSeconds),
|
|
69452
|
-
feeBps: num14(meta.withdrawFeeBps)
|
|
69453
|
-
},
|
|
69454
|
-
availability,
|
|
69455
|
-
risk: {
|
|
69456
|
-
yieldProfile: yieldProfile(info.yieldProfile),
|
|
69457
|
-
denomination: denomination(info.denomination),
|
|
69458
|
-
// The curated trust classification, where one exists. Typed on `EarnRisk`
|
|
69459
|
-
// since the surface was written and never populated — a tranche's
|
|
69460
|
-
// first-loss position is the term most worth surfacing on a rate list.
|
|
69461
|
-
counterparty: str6(meta.solvency),
|
|
69462
|
-
score: num14(row.rating?.score),
|
|
69463
|
-
label: str6(row.rating?.level),
|
|
69464
|
-
illiquid: isIlliquid({
|
|
69465
|
-
exitMode,
|
|
69466
|
-
tvlUsd: num14(tvl.totalAssetsUsd),
|
|
69467
|
-
liquidityUsd: num14(liq.liquidityUsd)
|
|
69468
|
-
})
|
|
69469
|
-
},
|
|
69470
|
-
// Filled by `capabilities.ts` — kept required on the type so a normalizer
|
|
69471
|
-
// that forgets to stamp them is a compile error, not an empty CTA.
|
|
69472
|
-
capabilities: [],
|
|
69473
|
-
providerMeta: row.providerMeta
|
|
69474
|
-
};
|
|
69475
|
-
}
|
|
69476
|
-
function ratePercent(value, provider, fractionProviders = FRACTION_RATE_PROVIDERS) {
|
|
69477
|
-
const n = num14(value);
|
|
69478
|
-
if (n === void 0) return void 0;
|
|
69479
|
-
return fractionProviders.has(provider) ? n * 100 : n;
|
|
69480
|
-
}
|
|
69481
|
-
function implausibleRatePercent(percent) {
|
|
69482
|
-
return !Number.isFinite(percent) || percent < 0 || percent > 1e4;
|
|
69483
|
-
}
|
|
69484
|
-
function resolveRateKind(provider, meta) {
|
|
69485
|
-
if (meta.navOracle || meta.solvency === "nav-attested") return "nav-accrual";
|
|
69486
|
-
return RATE_KIND[provider] ?? "variable-managed";
|
|
69487
|
-
}
|
|
69488
|
-
function resolveAvailability(meta, maturity) {
|
|
69489
|
-
const isMintable = meta.isMintable;
|
|
69490
|
-
const capacity = str6(meta.depositCapacity) ?? str6(meta.maxDeposit);
|
|
69491
|
-
const capFull = capacity === "0";
|
|
69492
|
-
let gating;
|
|
69493
|
-
let reason;
|
|
69494
|
-
if (isMatured(maturity)) {
|
|
69495
|
-
gating = "matured";
|
|
69496
|
-
reason = "This market has reached maturity";
|
|
69497
|
-
} else if (isMintable === false) {
|
|
69498
|
-
gating = "allowlist-contract";
|
|
69499
|
-
reason = "Deposits are permissioned for this vault";
|
|
69500
|
-
} else if (capFull) {
|
|
69501
|
-
gating = "cap-full";
|
|
69502
|
-
reason = "Deposit cap is full";
|
|
69503
|
-
} else if (meta.paused === true) {
|
|
69504
|
-
gating = "paused";
|
|
69505
|
-
reason = "Vault is paused";
|
|
69506
|
-
}
|
|
69507
|
-
return {
|
|
69508
|
-
canDeposit: gating === void 0,
|
|
69509
|
-
// Exits stay open under a deposit cap, a mint allowlist or a maturity —
|
|
69510
|
-
// every wind-down we have integrated (Lista, dTRINITY/Sonic) keeps the
|
|
69511
|
-
// door open outward, and a matured bond is precisely the case where the
|
|
69512
|
-
// holder still needs out. An explicit pause is the one thing that shuts
|
|
69513
|
-
// both.
|
|
69514
|
-
canWithdraw: meta.paused !== true,
|
|
69515
|
-
gating,
|
|
69516
|
-
reason
|
|
69517
|
-
};
|
|
69518
|
-
}
|
|
69519
|
-
function resolveMaturity(meta) {
|
|
69520
|
-
const expiry = num14(meta.expiry) ?? num14(meta.maturity);
|
|
69521
|
-
if (expiry === void 0 || expiry <= 0) return void 0;
|
|
69522
|
-
const nowSecs = Math.floor(Date.now() / 1e3);
|
|
69523
|
-
return {
|
|
69524
|
-
kind: "fixed-date",
|
|
69525
|
-
maturity: expiry,
|
|
69526
|
-
maturityIso: str6(meta.expiryIso) ?? new Date(expiry * 1e3).toISOString(),
|
|
69527
|
-
// A SNAPSHOT — a cached listing ages, so a countdown must be recomputed
|
|
69528
|
-
// from `maturity` rather than ticked down from this.
|
|
69529
|
-
secondsToMaturity: Math.max(expiry - nowSecs, 0),
|
|
69530
|
-
// A PT simply stops earning: it redeems for the underlying at par and
|
|
69531
|
-
// sits there. No penalty, no liquidation, no auto-roll.
|
|
69532
|
-
atMaturity: str6(meta.atMaturity) ?? "stops-earning"
|
|
69533
|
-
};
|
|
69534
|
-
}
|
|
69535
|
-
function isMatured(maturity) {
|
|
69536
|
-
if (!maturity?.maturity) return false;
|
|
69537
|
-
return maturity.maturity <= Math.floor(Date.now() / 1e3);
|
|
69538
|
-
}
|
|
69539
|
-
function amount(raw, formatted, usd, decimals) {
|
|
69540
|
-
const rawStr = raw != null ? String(raw) : void 0;
|
|
69541
|
-
return {
|
|
69542
|
-
raw: rawStr,
|
|
69543
|
-
formatted: num14(formatted) ?? formatRaw(rawStr, decimals),
|
|
69544
|
-
usd: num14(usd)
|
|
69545
|
-
};
|
|
69546
|
-
}
|
|
69547
|
-
function sum(a, b) {
|
|
69548
|
-
if (a === void 0 && b === void 0) return void 0;
|
|
69549
|
-
return (a ?? 0) + (b ?? 0);
|
|
69550
|
-
}
|
|
69551
|
-
|
|
69552
69646
|
// src/earn/fromPool.ts
|
|
69553
69647
|
var FIXED_TERM_PREFIXES = [
|
|
69554
69648
|
"EXACTLY",
|
|
@@ -69568,7 +69662,7 @@ var USER_SET_RATE_PREFIXES = [
|
|
|
69568
69662
|
"EBISU"
|
|
69569
69663
|
];
|
|
69570
69664
|
function earnMarketFromPool(row, fallbackChainId) {
|
|
69571
|
-
const marketUid =
|
|
69665
|
+
const marketUid = str5(row.marketUid);
|
|
69572
69666
|
if (!marketUid) return void 0;
|
|
69573
69667
|
let earnUid;
|
|
69574
69668
|
try {
|
|
@@ -69576,24 +69670,24 @@ function earnMarketFromPool(row, fallbackChainId) {
|
|
|
69576
69670
|
} catch {
|
|
69577
69671
|
return void 0;
|
|
69578
69672
|
}
|
|
69579
|
-
const chainId =
|
|
69580
|
-
const venue =
|
|
69673
|
+
const chainId = str5(row.chainId) ?? fallbackChainId;
|
|
69674
|
+
const venue = str5(row.lender) ?? str5(row.lenderKey);
|
|
69581
69675
|
if (!chainId || !venue) return void 0;
|
|
69582
69676
|
const flags = row.flags ?? {};
|
|
69583
69677
|
const assetInfo = row.underlyingInfo?.asset ?? row.asset ?? {};
|
|
69584
69678
|
const underlying = addr2(assetInfo.address) ?? addr2(row.underlying) ?? addr2(row.poolId);
|
|
69585
69679
|
if (!underlying) return void 0;
|
|
69586
|
-
const decimals =
|
|
69587
|
-
const priceUsd =
|
|
69588
|
-
const base =
|
|
69589
|
-
const intrinsic =
|
|
69680
|
+
const decimals = num12(assetInfo.decimals) ?? num12(row.decimals) ?? 18;
|
|
69681
|
+
const priceUsd = num12(row.underlyingInfo?.prices?.priceUsd) ?? num12(row.price);
|
|
69682
|
+
const base = num12(row.depositRate);
|
|
69683
|
+
const intrinsic = num12(row.intrinsicYield);
|
|
69590
69684
|
const rewards = sumRewardAprs(row.rewards);
|
|
69591
69685
|
const marketOwn = sum2(base, rewards);
|
|
69592
69686
|
const rate = {
|
|
69593
69687
|
// Prefer our own sum over the origin's `apr`, because `apr` is documented
|
|
69594
69688
|
// as `depositRate + intrinsicYield` and therefore EXCLUDES incentives —
|
|
69595
69689
|
// using it as the headline would under-report every incentivized market.
|
|
69596
|
-
total: sum2(base, intrinsic, rewards) ??
|
|
69690
|
+
total: sum2(base, intrinsic, rewards) ?? num12(row.apr) ?? 0,
|
|
69597
69691
|
base,
|
|
69598
69692
|
rewards,
|
|
69599
69693
|
intrinsic,
|
|
@@ -69611,15 +69705,19 @@ function earnMarketFromPool(row, fallbackChainId) {
|
|
|
69611
69705
|
// The family brand ('Morpho Blue'), not the per-market key. The specific
|
|
69612
69706
|
// market identity survives on `name`.
|
|
69613
69707
|
brand: venueBrand(venue),
|
|
69614
|
-
|
|
69708
|
+
// Same resolver as the vault half, so `protocol.key` means one thing
|
|
69709
|
+
// across the listing: the STABLE family key, never the per-market venue.
|
|
69710
|
+
// No lender publishes a curator today, hence the undefined.
|
|
69711
|
+
...resolveEarnIdentity(venue, void 0),
|
|
69712
|
+
name: str5(row.name),
|
|
69615
69713
|
// Never re-derived — the uid's third segment as the origin minted it.
|
|
69616
69714
|
ref: marketUid.split(":")[2],
|
|
69617
|
-
logoURI:
|
|
69715
|
+
logoURI: str5(assetInfo.logoURI),
|
|
69618
69716
|
asset: {
|
|
69619
69717
|
address: underlying,
|
|
69620
|
-
symbol:
|
|
69718
|
+
symbol: str5(assetInfo.symbol) ?? "",
|
|
69621
69719
|
decimals,
|
|
69622
|
-
assetGroup:
|
|
69720
|
+
assetGroup: str5(row.underlyingInfo?.assetGroup) ?? str5(row.asset?.assetGroup),
|
|
69623
69721
|
priceUsd
|
|
69624
69722
|
},
|
|
69625
69723
|
// A lending supply position is an aToken/cToken/eToken balance, but the
|
|
@@ -69640,7 +69738,7 @@ function earnMarketFromPool(row, fallbackChainId) {
|
|
|
69640
69738
|
row.totalLiquidityUSD ?? row.totalLiquidityUsd
|
|
69641
69739
|
),
|
|
69642
69740
|
depositCapacity: void 0,
|
|
69643
|
-
utilization:
|
|
69741
|
+
utilization: num12(row.utilization),
|
|
69644
69742
|
// Lending withdrawals are same-block, bounded by available liquidity —
|
|
69645
69743
|
// which is exactly `instant-capped`, not `instant`. A pool at 100 %
|
|
69646
69744
|
// utilization cannot be exited, and calling that `instant` is the kind of
|
|
@@ -69648,12 +69746,12 @@ function earnMarketFromPool(row, fallbackChainId) {
|
|
|
69648
69746
|
exit: { mode: "instant-capped", settlement: "sync" },
|
|
69649
69747
|
availability,
|
|
69650
69748
|
risk: {
|
|
69651
|
-
score:
|
|
69652
|
-
label:
|
|
69749
|
+
score: num12(row.risk?.score),
|
|
69750
|
+
label: str5(row.risk?.label),
|
|
69653
69751
|
illiquid: isIlliquid({
|
|
69654
69752
|
exitMode: "instant-capped",
|
|
69655
|
-
tvlUsd:
|
|
69656
|
-
liquidityUsd:
|
|
69753
|
+
tvlUsd: num12(row.totalDepositsUSD ?? row.totalDepositsUsd),
|
|
69754
|
+
liquidityUsd: num12(row.totalLiquidityUSD ?? row.totalLiquidityUsd)
|
|
69657
69755
|
})
|
|
69658
69756
|
},
|
|
69659
69757
|
capabilities: [],
|
|
@@ -69708,9 +69806,9 @@ function resolveAvailability2(row, flags, totalRate) {
|
|
|
69708
69806
|
};
|
|
69709
69807
|
}
|
|
69710
69808
|
function isSupplyCapFull(row) {
|
|
69711
|
-
const cap =
|
|
69809
|
+
const cap = num12(row.caps?.supplyCap) ?? num12(row.supplyCap);
|
|
69712
69810
|
if (cap === void 0 || cap <= 0) return false;
|
|
69713
|
-
const deposits =
|
|
69811
|
+
const deposits = num12(row.totalDeposits);
|
|
69714
69812
|
if (deposits === void 0) return false;
|
|
69715
69813
|
return deposits >= cap;
|
|
69716
69814
|
}
|
|
@@ -69719,7 +69817,7 @@ function sumRewardAprs(rewards) {
|
|
|
69719
69817
|
let total = 0;
|
|
69720
69818
|
let seen = false;
|
|
69721
69819
|
for (const r of rewards) {
|
|
69722
|
-
const apr =
|
|
69820
|
+
const apr = num12(r?.depositRate);
|
|
69723
69821
|
if (apr === void 0) continue;
|
|
69724
69822
|
total += apr;
|
|
69725
69823
|
seen = true;
|
|
@@ -69727,14 +69825,12 @@ function sumRewardAprs(rewards) {
|
|
|
69727
69825
|
return seen ? total : void 0;
|
|
69728
69826
|
}
|
|
69729
69827
|
function amount2(formatted, usd) {
|
|
69730
|
-
return { formatted:
|
|
69828
|
+
return { formatted: num12(formatted), usd: num12(usd) };
|
|
69731
69829
|
}
|
|
69732
69830
|
function sum2(...parts) {
|
|
69733
69831
|
const present = parts.filter((p) => p !== void 0);
|
|
69734
69832
|
return present.length ? present.reduce((a, b) => a + b, 0) : void 0;
|
|
69735
69833
|
}
|
|
69736
|
-
|
|
69737
|
-
// src/earn/capabilities.ts
|
|
69738
69834
|
var ASYNC_EXIT_MODES = /* @__PURE__ */ new Set([
|
|
69739
69835
|
"fixed-cooldown",
|
|
69740
69836
|
"request-based",
|
|
@@ -69789,9 +69885,11 @@ function vaultCapabilities(row) {
|
|
|
69789
69885
|
const caps = [];
|
|
69790
69886
|
if (SWAP_ROUTED_PROVIDERS.has(provider)) return swapRoutedCapabilities(row);
|
|
69791
69887
|
if (row.availability.canDeposit) {
|
|
69888
|
+
const inputs = depositInputs(row, provider);
|
|
69792
69889
|
caps.push({
|
|
69793
69890
|
action: "deposit",
|
|
69794
|
-
|
|
69891
|
+
inputs,
|
|
69892
|
+
requires: depositRequires(provider, meta, inputs),
|
|
69795
69893
|
// Phase 3 flips this to `true` once the `vault.*` venues are registered
|
|
69796
69894
|
// with the conversion solver. Advertising it before the route can serve
|
|
69797
69895
|
// it would be worse than the current gap — a client would build a zap
|
|
@@ -69803,13 +69901,14 @@ function vaultCapabilities(row) {
|
|
|
69803
69901
|
const mode = row.exit.mode;
|
|
69804
69902
|
const isAsync = ASYNC_PROVIDERS.has(provider) || ASYNC_EXIT_MODES.has(mode);
|
|
69805
69903
|
if (!isAsync) {
|
|
69806
|
-
caps.push({ action: "withdraw" });
|
|
69904
|
+
caps.push({ action: "withdraw", requires: withdrawRequires(provider) });
|
|
69807
69905
|
return caps;
|
|
69808
69906
|
}
|
|
69809
69907
|
if (mode === "fee-or-queued" && meta.instantRedeemEnabled !== false) {
|
|
69810
69908
|
caps.push({
|
|
69811
69909
|
action: "withdraw",
|
|
69812
|
-
|
|
69910
|
+
requires: withdrawRequires(provider),
|
|
69911
|
+
feeBps: num12(meta.withdrawFeeBps) ?? row.exit.feeBps
|
|
69813
69912
|
});
|
|
69814
69913
|
}
|
|
69815
69914
|
caps.push({
|
|
@@ -69827,14 +69926,58 @@ function vaultCapabilities(row) {
|
|
|
69827
69926
|
}
|
|
69828
69927
|
return caps;
|
|
69829
69928
|
}
|
|
69830
|
-
function
|
|
69929
|
+
function isBookPriced(provider) {
|
|
69930
|
+
const risk = vaultTraits(provider)?.priceRisk;
|
|
69931
|
+
return risk === "market-price" || risk === "may-be-impossible";
|
|
69932
|
+
}
|
|
69933
|
+
function swapRoutedProvidersArePriceConsistent() {
|
|
69934
|
+
return [...SWAP_ROUTED_PROVIDERS].filter((p) => !isBookPriced(p));
|
|
69935
|
+
}
|
|
69936
|
+
function depositInputs(row, provider) {
|
|
69937
|
+
if (provider !== "lst") return void 0;
|
|
69938
|
+
const share = row.shareToken?.address ?? row.ref;
|
|
69939
|
+
if (!share) return void 0;
|
|
69940
|
+
try {
|
|
69941
|
+
const accepted = getLstAcceptedInputs(row.chainId, share);
|
|
69942
|
+
if (!accepted?.length) return void 0;
|
|
69943
|
+
return accepted.map((a) => ({
|
|
69944
|
+
asset: String(a.asset),
|
|
69945
|
+
symbol: a.symbol,
|
|
69946
|
+
mode: a.mode,
|
|
69947
|
+
needs: a.needs,
|
|
69948
|
+
optional: a.optional
|
|
69949
|
+
}));
|
|
69950
|
+
} catch {
|
|
69951
|
+
return void 0;
|
|
69952
|
+
}
|
|
69953
|
+
}
|
|
69954
|
+
function isBoundNeed(need) {
|
|
69955
|
+
return /^min/i.test(need);
|
|
69956
|
+
}
|
|
69957
|
+
function depositRequires(provider, meta, inputs) {
|
|
69831
69958
|
const requires = [];
|
|
69832
69959
|
if (meta.delegation) requires.push("validator");
|
|
69833
69960
|
if (provider === "gmx") requires.push("executionFee");
|
|
69961
|
+
if (isBookPriced(provider)) requires.push("slippage");
|
|
69962
|
+
if (inputs?.length) {
|
|
69963
|
+
const common = inputs[0].needs?.filter(
|
|
69964
|
+
(n) => inputs.every((i) => i.needs?.includes(n))
|
|
69965
|
+
);
|
|
69966
|
+
for (const n of common ?? []) if (!requires.includes(n)) requires.push(n);
|
|
69967
|
+
}
|
|
69968
|
+
return requires.length ? requires : void 0;
|
|
69969
|
+
}
|
|
69970
|
+
function withdrawRequires(provider) {
|
|
69971
|
+
const requires = [];
|
|
69972
|
+
if (isBookPriced(provider)) requires.push("slippage");
|
|
69973
|
+
if (provider === "gmx") requires.push("executionFee");
|
|
69834
69974
|
return requires.length ? requires : void 0;
|
|
69835
69975
|
}
|
|
69836
69976
|
function requestRequires(provider) {
|
|
69837
|
-
|
|
69977
|
+
const requires = [];
|
|
69978
|
+
if (provider === "gmx") requires.push("executionFee");
|
|
69979
|
+
if (isBookPriced(provider)) requires.push("slippage");
|
|
69980
|
+
return requires.length ? requires : void 0;
|
|
69838
69981
|
}
|
|
69839
69982
|
function claimRequires(provider) {
|
|
69840
69983
|
return void 0;
|
|
@@ -69844,6 +69987,191 @@ function supportsCancel(provider, meta) {
|
|
|
69844
69987
|
return typeof meta.withdrawQueue === "string" && meta.withdrawQueue.length > 0;
|
|
69845
69988
|
}
|
|
69846
69989
|
|
|
69847
|
-
|
|
69990
|
+
// src/earn/positions.ts
|
|
69991
|
+
function buildLendingPositionUid(lender, chainId) {
|
|
69992
|
+
if (!lender || !chainId) {
|
|
69993
|
+
throw new Error(
|
|
69994
|
+
`Invalid lending positionUid parameters: lender=${lender}, chainId=${chainId}`
|
|
69995
|
+
);
|
|
69996
|
+
}
|
|
69997
|
+
if (isVaultVenue(lender)) {
|
|
69998
|
+
throw new Error(
|
|
69999
|
+
`Lender '${lender}' uses the reserved vault venue namespace`
|
|
70000
|
+
);
|
|
70001
|
+
}
|
|
70002
|
+
return `${lender}:${chainId}`;
|
|
70003
|
+
}
|
|
70004
|
+
function isVaultPosition(p) {
|
|
70005
|
+
return p.venueKind === "vault";
|
|
70006
|
+
}
|
|
70007
|
+
function isLendingPosition(p) {
|
|
70008
|
+
return p.venueKind === "lending";
|
|
70009
|
+
}
|
|
70010
|
+
function legEarnUid(marketUid) {
|
|
70011
|
+
if (!marketUid) return void 0;
|
|
70012
|
+
const parts = marketUid.split(":");
|
|
70013
|
+
if (parts.length !== 3 || parts.some((p) => !p)) return void 0;
|
|
70014
|
+
if (isVaultVenue(parts[0])) return void 0;
|
|
70015
|
+
return marketUid;
|
|
70016
|
+
}
|
|
70017
|
+
function num15(v) {
|
|
70018
|
+
const n = typeof v === "number" ? v : Number(v);
|
|
70019
|
+
return Number.isFinite(n) ? n : 0;
|
|
70020
|
+
}
|
|
70021
|
+
function legAsset(pos) {
|
|
70022
|
+
const asset = pos.underlyingInfo?.asset ?? {};
|
|
70023
|
+
const address = typeof asset.address === "string" ? asset.address.toLowerCase() : (
|
|
70024
|
+
// Fall back to the uid's third segment, which IS the underlying for
|
|
70025
|
+
// the default-format lenders and merely a harmless label for the rest.
|
|
70026
|
+
pos.marketUid?.split(":")[2] ?? ""
|
|
70027
|
+
);
|
|
70028
|
+
const decimals = typeof asset.decimals === "number" ? asset.decimals : void 0;
|
|
70029
|
+
const symbol = typeof asset.symbol === "string" ? asset.symbol : void 0;
|
|
70030
|
+
return { address, symbol, decimals };
|
|
70031
|
+
}
|
|
70032
|
+
function toLeg(pos) {
|
|
70033
|
+
const depositsUsd = num15(pos.depositsUSD);
|
|
70034
|
+
const debtUsd = num15(pos.debtUSD) + num15(pos.debtStableUSD);
|
|
70035
|
+
const hasSupply = depositsUsd !== 0 || num15(pos.deposits) !== 0;
|
|
70036
|
+
const hasDebt = debtUsd !== 0 || num15(pos.debt) !== 0 || num15(pos.debtStable) !== 0;
|
|
70037
|
+
return {
|
|
70038
|
+
earnUid: legEarnUid(pos.marketUid),
|
|
70039
|
+
marketUid: pos.marketUid,
|
|
70040
|
+
...pos.loanId ? { loanId: pos.loanId } : {},
|
|
70041
|
+
asset: legAsset(pos),
|
|
70042
|
+
side: hasSupply && hasDebt ? "both" : hasDebt ? "borrow" : "supply",
|
|
70043
|
+
deposits: pos.deposits ?? "0",
|
|
70044
|
+
depositsUsd,
|
|
70045
|
+
debt: pos.debt ?? "0",
|
|
70046
|
+
debtUsd,
|
|
70047
|
+
collateralEnabled: pos.collateralEnabled ?? false,
|
|
70048
|
+
...pos.withdrawable !== void 0 ? { withdrawable: pos.withdrawable } : {}
|
|
70049
|
+
};
|
|
70050
|
+
}
|
|
70051
|
+
function isCountable(leg) {
|
|
70052
|
+
return leg.loanId === void 0;
|
|
70053
|
+
}
|
|
70054
|
+
function earnPositionFromLenderEntry(entry) {
|
|
70055
|
+
const subs = entry.data ?? [];
|
|
70056
|
+
const subAccounts = subs.map((sub) => {
|
|
70057
|
+
const legs = (sub.positions ?? []).map(toLeg);
|
|
70058
|
+
const counted = legs.filter(isCountable);
|
|
70059
|
+
const suppliedUsd2 = counted.reduce((a, l) => a + l.depositsUsd, 0);
|
|
70060
|
+
const borrowedUsd2 = counted.reduce((a, l) => a + l.debtUsd, 0);
|
|
70061
|
+
return {
|
|
70062
|
+
accountId: sub.accountId,
|
|
70063
|
+
health: sub.health ?? null,
|
|
70064
|
+
suppliedUsd: suppliedUsd2,
|
|
70065
|
+
borrowedUsd: borrowedUsd2,
|
|
70066
|
+
netUsd: suppliedUsd2 - borrowedUsd2,
|
|
70067
|
+
legs
|
|
70068
|
+
};
|
|
70069
|
+
});
|
|
70070
|
+
const active = subAccounts.filter((s) => s.legs.length > 0 || s.netUsd !== 0);
|
|
70071
|
+
const crossMargin = active.length <= 1;
|
|
70072
|
+
const suppliedUsd = num15(entry.balanceData?.deposits);
|
|
70073
|
+
const borrowedUsd = num15(entry.balanceData?.debt);
|
|
70074
|
+
return {
|
|
70075
|
+
positionUid: buildLendingPositionUid(entry.lender, entry.chainId),
|
|
70076
|
+
chainId: entry.chainId,
|
|
70077
|
+
venue: entry.lender,
|
|
70078
|
+
venueKind: "lending",
|
|
70079
|
+
lender: entry.lender,
|
|
70080
|
+
account: entry.account,
|
|
70081
|
+
brand: entry.lenderInfo?.name,
|
|
70082
|
+
name: entry.lenderInfo?.name,
|
|
70083
|
+
...entry.lenderInfo?.logoUri ? { logoURI: entry.lenderInfo.logoUri } : {},
|
|
70084
|
+
suppliedUsd,
|
|
70085
|
+
borrowedUsd,
|
|
70086
|
+
netUsd: num15(entry.balanceData?.nav),
|
|
70087
|
+
apr: num15(entry.aprData?.apr),
|
|
70088
|
+
depositApr: num15(entry.aprData?.depositApr),
|
|
70089
|
+
borrowApr: num15(entry.aprData?.borrowApr),
|
|
70090
|
+
// Only a cross-margin account HAS one health factor. Publishing the first
|
|
70091
|
+
// sub-account's as the row's would be a number about a different position.
|
|
70092
|
+
health: crossMargin ? active[0]?.health ?? null : null,
|
|
70093
|
+
leverage: num15(entry.leverage),
|
|
70094
|
+
crossMargin,
|
|
70095
|
+
legs: subAccounts.flatMap((s) => s.legs),
|
|
70096
|
+
subAccounts: active,
|
|
70097
|
+
...entry.incomplete ? { incomplete: true } : {},
|
|
70098
|
+
...entry.stale ? { stale: true, staleAgeMs: entry.staleAgeMs } : {}
|
|
70099
|
+
};
|
|
70100
|
+
}
|
|
70101
|
+
function vaultSharesToAssets(sharesRaw, meta) {
|
|
70102
|
+
if (sharesRaw === 0n) return 0n;
|
|
70103
|
+
const totalSupply = BigInt(meta.totalSupply || "0");
|
|
70104
|
+
if (totalSupply === 0n) return 0n;
|
|
70105
|
+
return sharesRaw * BigInt(meta.totalAssets || "0") / totalSupply;
|
|
70106
|
+
}
|
|
70107
|
+
function earnPositionFromVaultBalance(meta, chainId, input, format) {
|
|
70108
|
+
const assetsRaw = vaultSharesToAssets(input.sharesRaw, meta);
|
|
70109
|
+
const assetDecimals = meta.assetDecimals ?? meta.decimals;
|
|
70110
|
+
const assets = format(assetsRaw, assetDecimals);
|
|
70111
|
+
const priceUsd = input.priceUsd ?? 0;
|
|
70112
|
+
const suppliedUsd = priceUsd * parseFloat(assets);
|
|
70113
|
+
const market = input.market;
|
|
70114
|
+
const uid = buildVaultEarnUid(meta.provider, chainId, meta.address);
|
|
70115
|
+
return {
|
|
70116
|
+
positionUid: uid,
|
|
70117
|
+
earnUid: uid,
|
|
70118
|
+
chainId,
|
|
70119
|
+
venue: `vault.${meta.provider}`,
|
|
70120
|
+
venueKind: "vault",
|
|
70121
|
+
provider: meta.provider,
|
|
70122
|
+
vault: meta.address,
|
|
70123
|
+
// The catalogue's identity resolution (curator, brand, branded icon) beats
|
|
70124
|
+
// the raw share-token name where it resolved.
|
|
70125
|
+
name: market?.name ?? meta.name,
|
|
70126
|
+
...market?.brand ? { brand: market.brand } : {},
|
|
70127
|
+
...market?.logoURI ?? meta.logoURI ? { logoURI: market?.logoURI ?? meta.logoURI } : {},
|
|
70128
|
+
asset: {
|
|
70129
|
+
address: meta.underlying,
|
|
70130
|
+
...market?.asset.symbol ? { symbol: market.asset.symbol } : {},
|
|
70131
|
+
decimals: assetDecimals,
|
|
70132
|
+
priceUsd
|
|
70133
|
+
},
|
|
70134
|
+
sharesRaw: input.sharesRaw.toString(),
|
|
70135
|
+
shares: format(input.sharesRaw, meta.decimals),
|
|
70136
|
+
assetsRaw: assetsRaw.toString(),
|
|
70137
|
+
assets,
|
|
70138
|
+
shareDecimals: meta.decimals,
|
|
70139
|
+
suppliedUsd,
|
|
70140
|
+
// A vault share is a supply-only instrument — there is no borrow leg to
|
|
70141
|
+
// report, and `0` here is a fact rather than a missing read.
|
|
70142
|
+
borrowedUsd: 0,
|
|
70143
|
+
netUsd: suppliedUsd,
|
|
70144
|
+
// For a vault the position's APR IS the venue's rate — there is no borrow
|
|
70145
|
+
// leg to net off, so unlike the lending half the two never diverge.
|
|
70146
|
+
...market?.rate?.total !== void 0 ? { apr: market.rate.total } : {},
|
|
70147
|
+
...market?.rate ? { rate: market.rate } : {},
|
|
70148
|
+
...market?.exit ? { exit: market.exit } : {},
|
|
70149
|
+
...market?.availability ? { availability: market.availability } : {},
|
|
70150
|
+
...market?.capabilities ? { capabilities: market.capabilities } : {},
|
|
70151
|
+
...meta.yieldProfile ? { yieldProfile: meta.yieldProfile } : {},
|
|
70152
|
+
...meta.denomination ? { denomination: meta.denomination } : {}
|
|
70153
|
+
};
|
|
70154
|
+
}
|
|
70155
|
+
function earnPositionTotals(items) {
|
|
70156
|
+
let suppliedUsd = 0;
|
|
70157
|
+
let borrowedUsd = 0;
|
|
70158
|
+
let lendingUsd = 0;
|
|
70159
|
+
let vaultUsd = 0;
|
|
70160
|
+
for (const it of items) {
|
|
70161
|
+
suppliedUsd += it.suppliedUsd;
|
|
70162
|
+
borrowedUsd += it.borrowedUsd;
|
|
70163
|
+
if (it.venueKind === "vault") vaultUsd += it.netUsd;
|
|
70164
|
+
else lendingUsd += it.netUsd;
|
|
70165
|
+
}
|
|
70166
|
+
return {
|
|
70167
|
+
suppliedUsd,
|
|
70168
|
+
borrowedUsd,
|
|
70169
|
+
netUsd: suppliedUsd - borrowedUsd,
|
|
70170
|
+
lendingUsd,
|
|
70171
|
+
vaultUsd
|
|
70172
|
+
};
|
|
70173
|
+
}
|
|
70174
|
+
|
|
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 };
|
|
69848
70176
|
//# sourceMappingURL=index.js.map
|
|
69849
70177
|
//# sourceMappingURL=index.js.map
|