@1delta/margin-fetcher 5.0.108 → 5.0.110
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 +49 -2
- package/dist/index.js +453 -45
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -49133,6 +49133,33 @@ var sthusdFetcher = {
|
|
|
49133
49133
|
};
|
|
49134
49134
|
}
|
|
49135
49135
|
};
|
|
49136
|
+
|
|
49137
|
+
// src/yields/intrinsic/fetchers/usual.ts
|
|
49138
|
+
var USDZEROPLUS_URL = "https://app.usual.money/api/rewards/rates/USD0++";
|
|
49139
|
+
var ETHZERO_URL = "https://app.usual.money/api/rewards/rates/ETH0";
|
|
49140
|
+
var BUSD0_KEY = "Staked USD0::USD0++";
|
|
49141
|
+
var usdZeroPlus = BUSD0_KEY;
|
|
49142
|
+
var ethZero = "ETH0::ETH0";
|
|
49143
|
+
var usdZeroPlusFetcher = {
|
|
49144
|
+
label: "USDZEROPLUS",
|
|
49145
|
+
fetch: async () => {
|
|
49146
|
+
const res = await fetch(USDZEROPLUS_URL, {
|
|
49147
|
+
method: "GET",
|
|
49148
|
+
headers: { Accept: "application/json" }
|
|
49149
|
+
}).then((r) => r.json());
|
|
49150
|
+
return { [usdZeroPlus]: Number(res?.rewards[0]?.apr ?? 0) * 100 };
|
|
49151
|
+
}
|
|
49152
|
+
};
|
|
49153
|
+
var ethZeroFetcher = {
|
|
49154
|
+
label: "ETHZERO",
|
|
49155
|
+
fetch: async () => {
|
|
49156
|
+
const res = await fetch(ETHZERO_URL, {
|
|
49157
|
+
method: "GET",
|
|
49158
|
+
headers: { Accept: "application/json" }
|
|
49159
|
+
}).then((r) => r.json());
|
|
49160
|
+
return { [ethZero]: Number(res?.rewards[0]?.apr ?? 0) * 100 };
|
|
49161
|
+
}
|
|
49162
|
+
};
|
|
49136
49163
|
var CHAIN_ID14 = Chain.ETHEREUM_MAINNET;
|
|
49137
49164
|
var HUMA_PST_FEED = "0x4be50be32db1510240d542f77c5b36ca0d0965e6";
|
|
49138
49165
|
var HUMA_PST_KEY = "HUMA::PST";
|
|
@@ -52479,6 +52506,50 @@ var SINGLE_CHAIN_ENTRIES = {
|
|
|
52479
52506
|
yieldFetcher: saturnFetcher,
|
|
52480
52507
|
yieldKey: SUSDAT_KEY
|
|
52481
52508
|
},
|
|
52509
|
+
// ---- Usual (usual.money) — bUSD0, Bond USD0 (ex-USD0++) ------------
|
|
52510
|
+
//
|
|
52511
|
+
// A fixed-maturity BOND over USD0, not a staked stablecoin: one bUSD0 is
|
|
52512
|
+
// one USD0 at `getEndTime()` = 1844335800 (2028-06-11 11:30 UTC; the bond
|
|
52513
|
+
// started 2024-06-11 and runs `totalBondTimes()` = 4 years). Not ERC-4626
|
|
52514
|
+
// in any part, hence the `usual-bond` reader. Fully backed 1:1 — the
|
|
52515
|
+
// contract held exactly its supply in USD0 (518,288,230.80 each) on
|
|
52516
|
+
// 2026-10-07 — but the backing is admin-sweepable (`emergencyWithdraw`),
|
|
52517
|
+
// so `solvency` stays unasserted and the reader clamps the rate to it.
|
|
52518
|
+
//
|
|
52519
|
+
// The rate is par and NEVER drifts: the yield is a USUAL reward stream
|
|
52520
|
+
// (Usual's `rewards/rates/USD0++` API, 5.69 % at integration). The
|
|
52521
|
+
// interesting numbers are the early exits — `unlockUsd0ppFloorPrice` at
|
|
52522
|
+
// `getFloorPrice()` (0.92 → `withdrawFeeBps` 800), `unlockUSD0ppWithUsual`
|
|
52523
|
+
// at par for `calculateRequiredUsual` (2.147 USUAL per bUSD0 ≈ 2.6 % at
|
|
52524
|
+
// $0.0122), and `reconstruct` at par for an equal rt-bUSD0 burn, which only
|
|
52525
|
+
// V3 mints receive (~337.9k rt against ~518M bUSD0). The market sat at
|
|
52526
|
+
// ~0.971, so the floor is NOT the cheapest exit — the market and the USUAL
|
|
52527
|
+
// unlock both beat it. Every user path is `whenNotPaused`, and transfers
|
|
52528
|
+
// revert for USD0-blacklisted addresses.
|
|
52529
|
+
{
|
|
52530
|
+
reader: "usual-bond",
|
|
52531
|
+
address: "0x35d8949372d46b7a3d5a56006ae77b215fc69bc0",
|
|
52532
|
+
underlying: "0x73a15fed60bf67631dc6cd7bc5b6e8da8190acf5",
|
|
52533
|
+
// USD0
|
|
52534
|
+
symbol: "bUSD0",
|
|
52535
|
+
brand: "Usual",
|
|
52536
|
+
description: "Usual's four-year bond on its USD0 stablecoin: each bUSD0 is backed by one USD0 held in the contract and redeems for it at par on 11 June 2028. The yield is paid separately in USUAL tokens, not added to the bond. Leaving before maturity costs something \u2014 the guaranteed floor price (currently 0.92), a fee paid in USUAL for par, or a sale on the market below par \u2014 unless you still hold the redemption token from minting.",
|
|
52537
|
+
decimals: 18,
|
|
52538
|
+
isRebasing: false,
|
|
52539
|
+
isMintable: true,
|
|
52540
|
+
withdrawalMode: "fee-or-maturity",
|
|
52541
|
+
expiry: 1844335800,
|
|
52542
|
+
// getEndTime() — 2028-06-11 11:30 UTC
|
|
52543
|
+
usualBond: {
|
|
52544
|
+
redemptionToken: "0x82dca22b48b14de38ccf83b03330120c4b8acfe9",
|
|
52545
|
+
// rt-bUSD0
|
|
52546
|
+
parUnlockToken: "0xc4441c2be5d8fa8126822b9929ca0b81ea0de38e",
|
|
52547
|
+
// USUAL
|
|
52548
|
+
parUnlockTokenSymbol: "USUAL"
|
|
52549
|
+
},
|
|
52550
|
+
yieldFetcher: usdZeroPlusFetcher,
|
|
52551
|
+
yieldKey: BUSD0_KEY
|
|
52552
|
+
},
|
|
52482
52553
|
// ---- Strata (docs.strata.markets) — senior/junior risk tranches ----
|
|
52483
52554
|
//
|
|
52484
52555
|
// Six CDO markets, twelve ERC-4626 tranche tokens, all Ethereum.
|
|
@@ -55558,32 +55629,6 @@ var csusdlFetcher = {
|
|
|
55558
55629
|
}
|
|
55559
55630
|
};
|
|
55560
55631
|
|
|
55561
|
-
// src/yields/intrinsic/fetchers/usual.ts
|
|
55562
|
-
var USDZEROPLUS_URL = "https://app.usual.money/api/rewards/rates/USD0++";
|
|
55563
|
-
var ETHZERO_URL = "https://app.usual.money/api/rewards/rates/ETH0";
|
|
55564
|
-
var usdZeroPlus = "Staked USD0::USD0++";
|
|
55565
|
-
var ethZero = "ETH0::ETH0";
|
|
55566
|
-
var usdZeroPlusFetcher = {
|
|
55567
|
-
label: "USDZEROPLUS",
|
|
55568
|
-
fetch: async () => {
|
|
55569
|
-
const res = await fetch(USDZEROPLUS_URL, {
|
|
55570
|
-
method: "GET",
|
|
55571
|
-
headers: { Accept: "application/json" }
|
|
55572
|
-
}).then((r) => r.json());
|
|
55573
|
-
return { [usdZeroPlus]: Number(res?.rewards[0]?.apr ?? 0) * 100 };
|
|
55574
|
-
}
|
|
55575
|
-
};
|
|
55576
|
-
var ethZeroFetcher = {
|
|
55577
|
-
label: "ETHZERO",
|
|
55578
|
-
fetch: async () => {
|
|
55579
|
-
const res = await fetch(ETHZERO_URL, {
|
|
55580
|
-
method: "GET",
|
|
55581
|
-
headers: { Accept: "application/json" }
|
|
55582
|
-
}).then((r) => r.json());
|
|
55583
|
-
return { [ethZero]: Number(res?.rewards[0]?.apr ?? 0) * 100 };
|
|
55584
|
-
}
|
|
55585
|
-
};
|
|
55586
|
-
|
|
55587
55632
|
// src/yields/intrinsic/fetchers/jito.ts
|
|
55588
55633
|
var JITOSOL_URL = "https://www.jito.network/api/getJitoPoolStats/";
|
|
55589
55634
|
var jitoSol = "Jito Staked SOL::JitoSOL";
|
|
@@ -55662,6 +55707,108 @@ var onycFetcher = {
|
|
|
55662
55707
|
}
|
|
55663
55708
|
};
|
|
55664
55709
|
|
|
55710
|
+
// src/yields/intrinsic/fetchers/sanctum.ts
|
|
55711
|
+
var KAMINO_STAKING_YIELDS = "https://api.kamino.finance/staking-yields/tokens";
|
|
55712
|
+
var INF_MINT = "5oVNBeEEQvYi1cX3ir8Dx5n1P7pdxydbGF2X4TxVusJm";
|
|
55713
|
+
var INF_LLAMA_POOL = "3075a746-bdd1-4aac-bcd5-b035abee2622";
|
|
55714
|
+
var INF_KEY = "Infinity::INF::solana";
|
|
55715
|
+
var INF_EPOCHS = 10;
|
|
55716
|
+
var MAX_PLAUSIBLE_APY = 0.3;
|
|
55717
|
+
function meanEpochApy(rows, n = INF_EPOCHS) {
|
|
55718
|
+
if (!Array.isArray(rows)) return void 0;
|
|
55719
|
+
const ok2 = rows.map((r) => ({ epoch: Number(r?.epoch), apy: Number(r?.apy) })).filter(
|
|
55720
|
+
(r) => Number.isFinite(r.epoch) && Number.isFinite(r.apy) && r.apy > 0 && r.apy < MAX_PLAUSIBLE_APY
|
|
55721
|
+
).sort((a, b) => b.epoch - a.epoch).slice(0, n);
|
|
55722
|
+
if (ok2.length === 0) return void 0;
|
|
55723
|
+
return ok2.reduce((s, r) => s + r.apy, 0) / ok2.length;
|
|
55724
|
+
}
|
|
55725
|
+
async function kaminoInfApy() {
|
|
55726
|
+
const end = /* @__PURE__ */ new Date();
|
|
55727
|
+
const start = new Date(end.getTime() - 30 * 864e5);
|
|
55728
|
+
const d = (x) => x.toISOString().slice(0, 10);
|
|
55729
|
+
const res = await fetch(
|
|
55730
|
+
`${KAMINO_STAKING_YIELDS}/${INF_MINT}/history?start=${d(start)}&end=${d(end)}`,
|
|
55731
|
+
{
|
|
55732
|
+
headers: { accept: "application/json" },
|
|
55733
|
+
signal: AbortSignal.timeout(8e3)
|
|
55734
|
+
}
|
|
55735
|
+
);
|
|
55736
|
+
if (!res.ok) throw new Error(`Kamino staking-yields HTTP ${res.status}`);
|
|
55737
|
+
return meanEpochApy(await res.json());
|
|
55738
|
+
}
|
|
55739
|
+
var infFetcher = {
|
|
55740
|
+
label: "SANCTUM_INF",
|
|
55741
|
+
fetch: async () => {
|
|
55742
|
+
const apy = await kaminoInfApy().catch((e) => {
|
|
55743
|
+
console.warn(`[sanctum] Kamino INF history unavailable: ${e.message}`);
|
|
55744
|
+
return void 0;
|
|
55745
|
+
});
|
|
55746
|
+
if (apy !== void 0) return { [INF_KEY]: apyToAprPercent(apy * 100) };
|
|
55747
|
+
const llama = await fetchDefiLlamaApy(INF_LLAMA_POOL);
|
|
55748
|
+
if (!(llama > 0) || llama >= MAX_PLAUSIBLE_APY * 100) return {};
|
|
55749
|
+
return { [INF_KEY]: apyToAprPercent(llama) };
|
|
55750
|
+
}
|
|
55751
|
+
};
|
|
55752
|
+
|
|
55753
|
+
// src/yields/intrinsic/fetchers/exponentTranching.ts
|
|
55754
|
+
var EXPONENT_APP_API = "https://app.exponent.finance/api/tranching-markets";
|
|
55755
|
+
var EXPONENT_SENIOR_GROUPS = {
|
|
55756
|
+
FvQP1fjox2GPSwkEhENuZisz8UeRURLWf7GYF9n2mURD: "Exponent Senior eHYUSD::srEHYUSD::solana",
|
|
55757
|
+
F17tzaQaFf1x3tC5gQFVvXAF2hcgq1qX6Mc9595zo3FD: "Exponent Senior AUTO::srAUTO::solana",
|
|
55758
|
+
"9J8VvigcjFTkN3jhZH2ieTi2hdGVBVpEXbcA1JDo7QpA": "Exponent Senior ONyc::srONyc::solana",
|
|
55759
|
+
"4tnzVYkaXKwMt7p86wpDzeTyzHSZhj2BvdGwBem7peH5": "Exponent Senior nOPAL::srnOPAL::solana"
|
|
55760
|
+
};
|
|
55761
|
+
var EXPONENT_BASE_GROUPS = {
|
|
55762
|
+
HnnGv3HrSqjRpgdFmx7vQGjntNEoex1SU4e9Lxcxuihz: "Earn Hylo USD::eHYUSD::solana"
|
|
55763
|
+
};
|
|
55764
|
+
var MAX_PLAUSIBLE_APY2 = 0.5;
|
|
55765
|
+
function seniorApy(stats) {
|
|
55766
|
+
const s = stats;
|
|
55767
|
+
for (const k of ["seniorApy30d", "seniorApy7d", "seniorApy1d"]) {
|
|
55768
|
+
const v = Number(s?.[k] ?? NaN);
|
|
55769
|
+
if (s?.[k] != null && Number.isFinite(v) && v > -MAX_PLAUSIBLE_APY2 && v < MAX_PLAUSIBLE_APY2)
|
|
55770
|
+
return v;
|
|
55771
|
+
}
|
|
55772
|
+
return void 0;
|
|
55773
|
+
}
|
|
55774
|
+
var getJson3 = async (url) => {
|
|
55775
|
+
const res = await fetch(url, {
|
|
55776
|
+
headers: { accept: "application/json" },
|
|
55777
|
+
signal: AbortSignal.timeout(8e3)
|
|
55778
|
+
});
|
|
55779
|
+
if (!res.ok) throw new Error(`Exponent HTTP ${res.status} for ${url}`);
|
|
55780
|
+
return res.json();
|
|
55781
|
+
};
|
|
55782
|
+
var exponentSeniorFetcher = {
|
|
55783
|
+
label: "EXPONENT_SENIOR",
|
|
55784
|
+
fetch: async () => {
|
|
55785
|
+
const markets = await getJson3(EXPONENT_APP_API);
|
|
55786
|
+
const wanted = (Array.isArray(markets) ? markets : []).filter(
|
|
55787
|
+
(m) => m.address && m.mintLpSenior && EXPONENT_SENIOR_GROUPS[m.mintLpSenior]
|
|
55788
|
+
);
|
|
55789
|
+
const out = {};
|
|
55790
|
+
for (const m of Array.isArray(markets) ? markets : []) {
|
|
55791
|
+
const group = m.mintBase ? EXPONENT_BASE_GROUPS[m.mintBase] : void 0;
|
|
55792
|
+
const apy = Number(m.underlyingApy7d);
|
|
55793
|
+
if (group && m.underlyingApy7d != null && apy > 0 && apy < MAX_PLAUSIBLE_APY2)
|
|
55794
|
+
out[group] = apyToAprPercent(apy * 100);
|
|
55795
|
+
}
|
|
55796
|
+
await Promise.all(
|
|
55797
|
+
wanted.map(async (m) => {
|
|
55798
|
+
const apy = await getJson3(`${EXPONENT_APP_API}/${m.address}/stats`).then(seniorApy).catch((e) => {
|
|
55799
|
+
console.warn(`[exponent] ${m.address} stats: ${e.message}`);
|
|
55800
|
+
return void 0;
|
|
55801
|
+
});
|
|
55802
|
+
if (apy !== void 0)
|
|
55803
|
+
out[EXPONENT_SENIOR_GROUPS[m.mintLpSenior]] = apyToAprPercent(
|
|
55804
|
+
apy * 100
|
|
55805
|
+
);
|
|
55806
|
+
})
|
|
55807
|
+
);
|
|
55808
|
+
return out;
|
|
55809
|
+
}
|
|
55810
|
+
};
|
|
55811
|
+
|
|
55665
55812
|
// src/yields/intrinsic/fetchers/superreturn.ts
|
|
55666
55813
|
var SSUPERUSD_URL = "https://www.superreturn.ai/api/trpc/cmc.getUSDCPrice,rewardBackend.getYield,rewardBackend.getTvlChange?batch=1&input=%7B%220%22%3A%7B%22json%22%3Anull%2C%22meta%22%3A%7B%22values%22%3A%5B%22undefined%22%5D%7D%7D%2C%221%22%3A%7B%22json%22%3Anull%2C%22meta%22%3A%7B%22values%22%3A%5B%22undefined%22%5D%7D%7D%2C%222%22%3A%7B%22json%22%3Anull%2C%22meta%22%3A%7B%22values%22%3A%5B%22undefined%22%5D%7D%7D%7D";
|
|
55667
55814
|
var ssuperusd = "SuperReturn sSuperUSD::SSUPERUSD";
|
|
@@ -55777,7 +55924,7 @@ var getGmxApiHost = (chainId) => GMX_API_HOSTS[chainId];
|
|
|
55777
55924
|
|
|
55778
55925
|
// src/vaults/gmx/api.ts
|
|
55779
55926
|
var GMX_DEFAULT_APY_PERIOD = "1d";
|
|
55780
|
-
var
|
|
55927
|
+
var getJson4 = async (url) => {
|
|
55781
55928
|
const res = await fetch(url, {
|
|
55782
55929
|
method: "GET",
|
|
55783
55930
|
headers: { Accept: "application/json" }
|
|
@@ -55789,12 +55936,12 @@ var fetchGmxRawData = async (chainId, period, apiUrlOverride) => {
|
|
|
55789
55936
|
const host = apiUrlOverride ?? getGmxApiHost(chainId);
|
|
55790
55937
|
if (!host) throw new Error(`GMX not supported on chain ${chainId}`);
|
|
55791
55938
|
const [apy, marketsRes, glvsRes, tokensRes] = await Promise.all([
|
|
55792
|
-
|
|
55793
|
-
|
|
55939
|
+
getJson4(`${host}/apy?period=${encodeURIComponent(period)}`),
|
|
55940
|
+
getJson4(`${host}/markets`).catch(() => ({
|
|
55794
55941
|
markets: []
|
|
55795
55942
|
})),
|
|
55796
|
-
|
|
55797
|
-
|
|
55943
|
+
getJson4(`${host}/glvs`).catch(() => ({ glvs: [] })),
|
|
55944
|
+
getJson4(`${host}/tokens`).catch(() => ({
|
|
55798
55945
|
tokens: []
|
|
55799
55946
|
}))
|
|
55800
55947
|
]);
|
|
@@ -56416,6 +56563,13 @@ var LENDING_ONLY_FETCHERS = [
|
|
|
56416
56563
|
// ONyc (OnRe reinsurance, Solana): NAV-accruing collateral on Loopscale /
|
|
56417
56564
|
// Kamino / Jupiter Lend, no vault row.
|
|
56418
56565
|
onycFetcher,
|
|
56566
|
+
// INF (Sanctum Infinity, Solana): the SOL-value accrual of the multi-LST
|
|
56567
|
+
// pool, collateral on Kamino / Jupiter Lend / Project 0 / Save. Its earn
|
|
56568
|
+
// row lives in margin-fetcher-sol, so it is lending-only here.
|
|
56569
|
+
infFetcher,
|
|
56570
|
+
// Exponent senior tranches (srEHYUSD / srAUTO / srONyc / srnOPAL, Solana):
|
|
56571
|
+
// Loopscale loop collateral, no earn row.
|
|
56572
|
+
exponentSeniorFetcher,
|
|
56419
56573
|
thbillFetcher,
|
|
56420
56574
|
// sthusdFetcher / scrvusdFetcher are NOT here (and deliberately not
|
|
56421
56575
|
// imported): both are vault-wired by their savings rows, so they reach
|
|
@@ -65071,7 +65225,7 @@ function rescaleExchangeRate(exchangeRate, shareDecimals) {
|
|
|
65071
65225
|
const dec2 = Math.max(0, Math.round(Number(shareDecimals) || 0));
|
|
65072
65226
|
return (r * 10n ** BigInt(dec2) / 10n ** 18n).toString();
|
|
65073
65227
|
}
|
|
65074
|
-
async function
|
|
65228
|
+
async function getJson5(url) {
|
|
65075
65229
|
const controller = new AbortController();
|
|
65076
65230
|
const timer = setTimeout(() => controller.abort(), API_TIMEOUT_MS2);
|
|
65077
65231
|
try {
|
|
@@ -65163,7 +65317,7 @@ async function mapWithConcurrency(items, limit, fn) {
|
|
|
65163
65317
|
return out;
|
|
65164
65318
|
}
|
|
65165
65319
|
async function fetchEulerEarnVaultsFromApi(chainId, prices = {}, tokenList = {}, multicallRetry) {
|
|
65166
|
-
const list = await
|
|
65320
|
+
const list = await getJson5(
|
|
65167
65321
|
`${EULER_DATA_API_BASE2}/earn/vaults?chainId=${chainId}&limit=200&visibility=${VISIBILITY_ALL}`
|
|
65168
65322
|
);
|
|
65169
65323
|
if (!list) return void 0;
|
|
@@ -65180,7 +65334,7 @@ async function fetchEulerEarnVaultsFromApi(chainId, prices = {}, tokenList = {},
|
|
|
65180
65334
|
mapWithConcurrency(
|
|
65181
65335
|
rows,
|
|
65182
65336
|
DETAIL_CONCURRENCY,
|
|
65183
|
-
(row) =>
|
|
65337
|
+
(row) => getJson5(
|
|
65184
65338
|
`${EULER_DATA_API_BASE2}/earn/vaults/${chainId}/${row.address}?include=strategies`
|
|
65185
65339
|
).then((d) => d?.data)
|
|
65186
65340
|
),
|
|
@@ -67472,6 +67626,87 @@ var marketRoute = () => ({
|
|
|
67472
67626
|
settlement: "market",
|
|
67473
67627
|
description: "The protocol's own mint and redeem are permissioned, so for a holder without that permission this is the route: sell the share token at whatever the book bids, with price impact that grows with size. It fills at the MARKET price, which is not the row's `exchangeRate` \u2014 that stays the NAV \u2014 so the leg must be built with a slippage bound."
|
|
67474
67628
|
});
|
|
67629
|
+
var capped = (a, b) => {
|
|
67630
|
+
if (a === void 0) return b;
|
|
67631
|
+
if (b === void 0) return a;
|
|
67632
|
+
return BigInt(a) < BigInt(b) ? a : b;
|
|
67633
|
+
};
|
|
67634
|
+
var bondExitRoutes = (i) => {
|
|
67635
|
+
const routes2 = [];
|
|
67636
|
+
const now = i.now ?? Math.floor(Date.now() / 1e3);
|
|
67637
|
+
const matured = i.expiry !== void 0 && now >= i.expiry;
|
|
67638
|
+
const capacity = {
|
|
67639
|
+
capacity: i.liquidity,
|
|
67640
|
+
capacityFormatted: i.liquidityFormatted,
|
|
67641
|
+
capacityUsd: i.liquidityUsd
|
|
67642
|
+
};
|
|
67643
|
+
if (i.withdrawFeeBps != null)
|
|
67644
|
+
routes2.push({
|
|
67645
|
+
id: "floor",
|
|
67646
|
+
kind: "instant",
|
|
67647
|
+
label: "Early exit at the floor price",
|
|
67648
|
+
settlement: "sync",
|
|
67649
|
+
feeBps: i.withdrawFeeBps,
|
|
67650
|
+
waitSeconds: 0,
|
|
67651
|
+
...capacity,
|
|
67652
|
+
selfOnly: true,
|
|
67653
|
+
description: "Burns the bond now for the protocol's floor price; the difference to par goes to the protocol's treasury, not to you. Pays the sender only."
|
|
67654
|
+
});
|
|
67655
|
+
if (i.parUnlockAvailable) {
|
|
67656
|
+
const token = i.parUnlockTokenSymbol ?? "the protocol token";
|
|
67657
|
+
routes2.push({
|
|
67658
|
+
id: "usual-unlock",
|
|
67659
|
+
kind: "instant",
|
|
67660
|
+
label: `Early exit at par (pays ${token})`,
|
|
67661
|
+
settlement: "sync",
|
|
67662
|
+
feeBps: i.parUnlockFeeBps,
|
|
67663
|
+
...i.parUnlockFeeBps == null ? { feeUnknown: true } : {},
|
|
67664
|
+
waitSeconds: 0,
|
|
67665
|
+
...capacity,
|
|
67666
|
+
selfOnly: true,
|
|
67667
|
+
description: `Pays par in the underlying, but you must also pay ${token} \u2014 a fixed amount per bond, so its cost in dollars moves with ${token}'s price. Pays the sender only.`
|
|
67668
|
+
});
|
|
67669
|
+
}
|
|
67670
|
+
if (i.redemptionTokenCapacity !== void 0)
|
|
67671
|
+
routes2.push({
|
|
67672
|
+
id: "reconstruct",
|
|
67673
|
+
kind: "instant",
|
|
67674
|
+
label: "Par with the redemption token",
|
|
67675
|
+
settlement: "sync",
|
|
67676
|
+
feeBps: 0,
|
|
67677
|
+
waitSeconds: 0,
|
|
67678
|
+
capacity: capped(i.liquidity, i.redemptionTokenCapacity),
|
|
67679
|
+
capacityFormatted: i.liquidityFormatted !== void 0 && i.redemptionTokenCapacityFormatted !== void 0 ? Math.min(i.liquidityFormatted, i.redemptionTokenCapacityFormatted) : i.redemptionTokenCapacityFormatted ?? i.liquidityFormatted,
|
|
67680
|
+
description: "Free and at par any time, but it burns an equal amount of the redemption token, which only fresh mints receive \u2014 a holder who bought the bond, or minted it before the token existed, cannot take this route. Capacity is the token supply across everyone."
|
|
67681
|
+
});
|
|
67682
|
+
routes2.push(
|
|
67683
|
+
matured ? {
|
|
67684
|
+
id: "maturity",
|
|
67685
|
+
kind: "instant",
|
|
67686
|
+
label: "Par at maturity",
|
|
67687
|
+
settlement: "sync",
|
|
67688
|
+
feeBps: 0,
|
|
67689
|
+
waitSeconds: 0,
|
|
67690
|
+
description: "The bond has matured: redeem at par. Burns your WHOLE balance in one call."
|
|
67691
|
+
} : {
|
|
67692
|
+
id: "maturity",
|
|
67693
|
+
kind: "queued",
|
|
67694
|
+
label: i.expiry !== void 0 ? `Par at maturity (${new Date(i.expiry * 1e3).toISOString().slice(0, 10)})` : "Par at maturity",
|
|
67695
|
+
settlement: "async",
|
|
67696
|
+
feeBps: 0,
|
|
67697
|
+
waitSeconds: i.expiry !== void 0 ? Math.max(0, i.expiry - now) : void 0,
|
|
67698
|
+
description: "Hold to the maturity date and redeem at par \u2014 nothing to request in the meantime. The redemption burns your WHOLE balance in one call."
|
|
67699
|
+
}
|
|
67700
|
+
);
|
|
67701
|
+
routes2.push({
|
|
67702
|
+
id: "market",
|
|
67703
|
+
kind: "market",
|
|
67704
|
+
label: "Sell on the market",
|
|
67705
|
+
settlement: "market",
|
|
67706
|
+
description: "Sell the bond to somebody else. It fills at the market price \u2014 usually a discount to par that closes toward maturity \u2014 not at the row's `exchangeRate`, with price impact that grows with size, so the leg must be built with a slippage bound."
|
|
67707
|
+
});
|
|
67708
|
+
return routes2;
|
|
67709
|
+
};
|
|
67475
67710
|
var deriveExitRoutes = (i) => {
|
|
67476
67711
|
const routes2 = deriveProtocolExitRoutes(i);
|
|
67477
67712
|
return i.secondaryMarketOnly ? [...routes2, marketRoute()] : routes2;
|
|
@@ -67498,6 +67733,8 @@ var deriveProtocolExitRoutes = (i) => {
|
|
|
67498
67733
|
// inventory instead.
|
|
67499
67734
|
case "instant-or-queued":
|
|
67500
67735
|
return [instantRoute(i, i.withdrawFeeBps ?? 0), queuedRoute(i)];
|
|
67736
|
+
case "fee-or-maturity":
|
|
67737
|
+
return bondExitRoutes(i);
|
|
67501
67738
|
case "instant":
|
|
67502
67739
|
return [
|
|
67503
67740
|
{
|
|
@@ -72127,6 +72364,30 @@ var NEST_FEE_INSTANT_REDEMPTION = 0;
|
|
|
72127
72364
|
var NEST_FEE_DEPOSIT = 1;
|
|
72128
72365
|
var NEST_FEE_REDEMPTION = 2;
|
|
72129
72366
|
|
|
72367
|
+
// src/vaults/savings/abis/usual.ts
|
|
72368
|
+
var view = (name, inputs = []) => ({
|
|
72369
|
+
name,
|
|
72370
|
+
type: "function",
|
|
72371
|
+
stateMutability: "view",
|
|
72372
|
+
inputs,
|
|
72373
|
+
outputs: [{ name: "", type: "uint256" }]
|
|
72374
|
+
});
|
|
72375
|
+
var UsualBondFloorPriceAbi = [view("getFloorPrice")];
|
|
72376
|
+
var UsualBondStartTimeAbi = [view("getStartTime")];
|
|
72377
|
+
var UsualBondEndTimeAbi = [view("getEndTime")];
|
|
72378
|
+
var UsualBondRequiredUsualAbi = [
|
|
72379
|
+
view("calculateRequiredUsual", [{ name: "usd0ppAmount", type: "uint256" }])
|
|
72380
|
+
];
|
|
72381
|
+
var UsualBondPausedAbi = [
|
|
72382
|
+
{
|
|
72383
|
+
name: "paused",
|
|
72384
|
+
type: "function",
|
|
72385
|
+
stateMutability: "view",
|
|
72386
|
+
inputs: [],
|
|
72387
|
+
outputs: [{ name: "", type: "bool" }]
|
|
72388
|
+
}
|
|
72389
|
+
];
|
|
72390
|
+
|
|
72130
72391
|
// src/vaults/savings/readers/erc4626Idle.ts
|
|
72131
72392
|
var readerErc4626Idle = (entry) => {
|
|
72132
72393
|
const shareUnit = 10n ** BigInt(entry.decimals);
|
|
@@ -72692,6 +72953,88 @@ var readerSaturnVault = (entry) => {
|
|
|
72692
72953
|
};
|
|
72693
72954
|
};
|
|
72694
72955
|
|
|
72956
|
+
// src/vaults/savings/readers/usualBond.ts
|
|
72957
|
+
var readerUsualBond = (entry) => {
|
|
72958
|
+
const cfg = entry.usualBond;
|
|
72959
|
+
const shareUnit = 10n ** BigInt(entry.decimals);
|
|
72960
|
+
return {
|
|
72961
|
+
calls: [
|
|
72962
|
+
{ address: entry.address, name: "totalSupply", params: [] },
|
|
72963
|
+
{ address: entry.underlying, name: "balanceOf", params: [entry.address] },
|
|
72964
|
+
{ address: entry.address, name: "getFloorPrice", params: [] },
|
|
72965
|
+
{ address: entry.address, name: "getStartTime", params: [] },
|
|
72966
|
+
{ address: entry.address, name: "getEndTime", params: [] },
|
|
72967
|
+
{ address: entry.address, name: "paused", params: [] },
|
|
72968
|
+
// No pinned rt token ⇒ read the bond's own supply in its place and
|
|
72969
|
+
// discard it, keeping the slice width fixed.
|
|
72970
|
+
{
|
|
72971
|
+
address: cfg?.redemptionToken ?? entry.address,
|
|
72972
|
+
name: "totalSupply",
|
|
72973
|
+
params: []
|
|
72974
|
+
},
|
|
72975
|
+
{
|
|
72976
|
+
address: entry.address,
|
|
72977
|
+
name: "calculateRequiredUsual",
|
|
72978
|
+
params: [shareUnit]
|
|
72979
|
+
}
|
|
72980
|
+
],
|
|
72981
|
+
abis: [
|
|
72982
|
+
TotalSupplyAbi2,
|
|
72983
|
+
BalanceOfAbi,
|
|
72984
|
+
UsualBondFloorPriceAbi,
|
|
72985
|
+
UsualBondStartTimeAbi,
|
|
72986
|
+
UsualBondEndTimeAbi,
|
|
72987
|
+
UsualBondPausedAbi,
|
|
72988
|
+
TotalSupplyAbi2,
|
|
72989
|
+
UsualBondRequiredUsualAbi
|
|
72990
|
+
],
|
|
72991
|
+
parse: ([
|
|
72992
|
+
supply,
|
|
72993
|
+
backingRaw,
|
|
72994
|
+
floor,
|
|
72995
|
+
start,
|
|
72996
|
+
end,
|
|
72997
|
+
paused,
|
|
72998
|
+
rtSupply,
|
|
72999
|
+
usual
|
|
73000
|
+
]) => {
|
|
73001
|
+
const totalSupply = toBigInt16(supply);
|
|
73002
|
+
const backing = toBigInt16(backingRaw);
|
|
73003
|
+
const endTime = toBigInt16(end);
|
|
73004
|
+
if (totalSupply === void 0 || backing === void 0 || endTime === void 0 || endTime <= 0n)
|
|
73005
|
+
return void 0;
|
|
73006
|
+
const exchangeRate = totalSupply > 0n && backing < totalSupply ? backing * ONE_E1815 / totalSupply : ONE_E1815;
|
|
73007
|
+
const floorPrice = toBigInt16(floor);
|
|
73008
|
+
const startTime = toBigInt16(start);
|
|
73009
|
+
const isPaused = typeof paused === "boolean" ? paused : void 0;
|
|
73010
|
+
const parUnlockCostPerShare = toBigInt16(usual);
|
|
73011
|
+
return {
|
|
73012
|
+
totalAssets: backing,
|
|
73013
|
+
totalSupply,
|
|
73014
|
+
exchangeRate,
|
|
73015
|
+
expiry: Number(endTime),
|
|
73016
|
+
paused: isPaused,
|
|
73017
|
+
// The floor exit's haircut, in the field every reader uses for "what
|
|
73018
|
+
// the immediate exit costs". Rounded UP: 0.92 → 800 bps exactly, and a
|
|
73019
|
+
// floor that is not a whole bps never reads cheaper than it is.
|
|
73020
|
+
withdrawFeeBps: floorPrice !== void 0 && floorPrice > 0n && floorPrice <= ONE_E1815 ? Number((ONE_E1815 - floorPrice + 10n ** 14n - 1n) / 10n ** 14n) : void 0,
|
|
73021
|
+
// Unread ⇒ assume open (the immediate exits are the norm); a READ pause
|
|
73022
|
+
// closes every leg, maturity included.
|
|
73023
|
+
instantRedeemEnabled: isPaused !== true,
|
|
73024
|
+
// Every immediate exit pays out of the bond's own USD0 — at most the
|
|
73025
|
+
// whole backing, never more.
|
|
73026
|
+
instantRedeemCapacity: isPaused === true ? 0n : backing,
|
|
73027
|
+
bond: {
|
|
73028
|
+
floorPrice,
|
|
73029
|
+
startTime: startTime !== void 0 ? Number(startTime) : void 0,
|
|
73030
|
+
redemptionTokenSupply: cfg?.redemptionToken ? toBigInt16(rtSupply) : void 0,
|
|
73031
|
+
parUnlockCostPerShare
|
|
73032
|
+
}
|
|
73033
|
+
};
|
|
73034
|
+
}
|
|
73035
|
+
};
|
|
73036
|
+
};
|
|
73037
|
+
|
|
72695
73038
|
// src/vaults/savings/readers/venusHub.ts
|
|
72696
73039
|
var NEUTRAL_PROBE2 = "0x000000000000000000000000000000000000dead";
|
|
72697
73040
|
var BPS_TO_PCT = 100;
|
|
@@ -72983,6 +73326,8 @@ var buildReader2 = (entry) => {
|
|
|
72983
73326
|
return readerSaturnVault(entry);
|
|
72984
73327
|
case "nest-vault":
|
|
72985
73328
|
return readerNestVault(entry);
|
|
73329
|
+
case "usual-bond":
|
|
73330
|
+
return readerUsualBond(entry);
|
|
72986
73331
|
case "erc4626-cooldown":
|
|
72987
73332
|
return readerErc4626Cooldown(entry);
|
|
72988
73333
|
case "erc4626-idle":
|
|
@@ -73094,6 +73439,18 @@ var fetchSavingsVaults = async (chainId, multicallRetry, prices = {}, tokenList
|
|
|
73094
73439
|
const redemptionDiscountBps = state.fundamentalExchangeRate !== void 0 && state.fundamentalExchangeRate > 0n ? Number(
|
|
73095
73440
|
state.exchangeRate * 100000000n / state.fundamentalExchangeRate - 100000000n
|
|
73096
73441
|
) / 1e4 : void 0;
|
|
73442
|
+
const bond = state.bond;
|
|
73443
|
+
const isBond = entry.withdrawalMode === "fee-or-maturity";
|
|
73444
|
+
const sharePriceUsd = prices[addressLc];
|
|
73445
|
+
const redeemableUsd = priceUsd !== void 0 ? Number(state.exchangeRate) / 1e18 * priceUsd : 0;
|
|
73446
|
+
const marketDiscountBps = isBond && sharePriceUsd !== void 0 && redeemableUsd > 0 ? Math.round((sharePriceUsd / redeemableUsd - 1) * 1e5) / 10 : void 0;
|
|
73447
|
+
const parToken = entry.usualBond?.parUnlockToken.toLowerCase();
|
|
73448
|
+
const parTokenPrice = parToken !== void 0 ? prices[parToken] : void 0;
|
|
73449
|
+
const parTokenDec = parToken !== void 0 ? tokenList[parToken]?.decimals ?? 18 : 18;
|
|
73450
|
+
const parUnlockFeeBps = bond?.parUnlockCostPerShare !== void 0 && parTokenPrice !== void 0 && redeemableUsd > 0 ? Math.round(
|
|
73451
|
+
Number(bond.parUnlockCostPerShare) / 10 ** parTokenDec * parTokenPrice * 1e4 / redeemableUsd
|
|
73452
|
+
) : void 0;
|
|
73453
|
+
const rtSupply = bond?.redemptionTokenSupply;
|
|
73097
73454
|
const productName = entry.label ?? entry.symbol;
|
|
73098
73455
|
const displayName = entry.label ? `${entry.brand} ${entry.label}` : composeVaultDisplayName(
|
|
73099
73456
|
entry.brand,
|
|
@@ -73155,6 +73512,18 @@ var fetchSavingsVaults = async (chainId, multicallRetry, prices = {}, tokenList
|
|
|
73155
73512
|
withdrawalCooldownSeconds: state.withdrawalCooldownSeconds ?? entry.withdrawalCooldownSeconds,
|
|
73156
73513
|
withdrawFeeBps: state.withdrawFeeBps,
|
|
73157
73514
|
depositFeeBps: state.depositFeeBps,
|
|
73515
|
+
// Bond terms — absent on every perpetual vault. See the type.
|
|
73516
|
+
expiry: state.expiry ?? entry.expiry,
|
|
73517
|
+
isPaused: state.paused,
|
|
73518
|
+
floorPrice: bond?.floorPrice?.toString(),
|
|
73519
|
+
marketDiscountBps,
|
|
73520
|
+
bond: bond ? {
|
|
73521
|
+
startTime: bond.startTime,
|
|
73522
|
+
redemptionToken: entry.usualBond?.redemptionToken.toLowerCase(),
|
|
73523
|
+
redemptionTokenSupply: rtSupply?.toString(),
|
|
73524
|
+
parUnlockToken: parToken,
|
|
73525
|
+
parUnlockCostPerShare: bond.parUnlockCostPerShare?.toString()
|
|
73526
|
+
} : void 0,
|
|
73158
73527
|
// Term-sheet inputs that no reader can derive — see the registry's
|
|
73159
73528
|
// docstrings. Passed through verbatim so the sheet can stop hardcoding
|
|
73160
73529
|
// "compounds per second" and "needs an approval" for every vault.
|
|
@@ -73189,7 +73558,14 @@ var fetchSavingsVaults = async (chainId, multicallRetry, prices = {}, tokenList
|
|
|
73189
73558
|
exitMinAmountFormatted: state.exitMinAmount !== void 0 ? Number(state.exitMinAmount) / 10 ** underlyingDec : void 0,
|
|
73190
73559
|
// Adds the `market` leg — the only route a holder without the
|
|
73191
73560
|
// protocol's mint/redeem permission actually has.
|
|
73192
|
-
secondaryMarketOnly: entry.secondaryMarketOnly
|
|
73561
|
+
secondaryMarketOnly: entry.secondaryMarketOnly,
|
|
73562
|
+
// Bond legs (`fee-or-maturity` only; ignored by every other mode).
|
|
73563
|
+
expiry: state.expiry ?? entry.expiry,
|
|
73564
|
+
redemptionTokenCapacity: rtSupply?.toString(),
|
|
73565
|
+
redemptionTokenCapacityFormatted: rtSupply !== void 0 ? Number(rtSupply) / 10 ** underlyingDec : void 0,
|
|
73566
|
+
parUnlockAvailable: bond?.parUnlockCostPerShare !== void 0 && bond.parUnlockCostPerShare > 0n,
|
|
73567
|
+
parUnlockFeeBps,
|
|
73568
|
+
parUnlockTokenSymbol: entry.usualBond?.parUnlockTokenSymbol
|
|
73193
73569
|
}),
|
|
73194
73570
|
resolveSelfOnly(chainId, entry.address)
|
|
73195
73571
|
),
|
|
@@ -74224,6 +74600,7 @@ var classifyRedemption = (provider, v) => {
|
|
|
74224
74600
|
if (SYNC_REDEMPTION_PROVIDERS.has(provider)) return "sync";
|
|
74225
74601
|
if (provider === "lst") return "async";
|
|
74226
74602
|
if (provider === "savings") {
|
|
74603
|
+
if (v.withdrawalMode === "fee-or-maturity") return void 0;
|
|
74227
74604
|
return v.withdrawalMode === "instant" && !v.withdrawalCooldownSeconds ? "sync" : "async";
|
|
74228
74605
|
}
|
|
74229
74606
|
return "sync";
|
|
@@ -75610,7 +75987,7 @@ function clearPendleMarketsCache() {
|
|
|
75610
75987
|
marketsCache = void 0;
|
|
75611
75988
|
assetsCache = void 0;
|
|
75612
75989
|
}
|
|
75613
|
-
async function
|
|
75990
|
+
async function getJson6(url, label) {
|
|
75614
75991
|
const response = await fetch(url, { headers: { Accept: "application/json" } });
|
|
75615
75992
|
if (!response.ok) {
|
|
75616
75993
|
throw new Error(
|
|
@@ -75631,7 +76008,7 @@ function cache5(slot, build6, store) {
|
|
|
75631
76008
|
function fetchPendleApiMarkets() {
|
|
75632
76009
|
return cache5(
|
|
75633
76010
|
marketsCache,
|
|
75634
|
-
async () => (await
|
|
76011
|
+
async () => (await getJson6(PENDLE_MARKETS_URL, "markets"))?.markets ?? [],
|
|
75635
76012
|
(c) => {
|
|
75636
76013
|
marketsCache = c;
|
|
75637
76014
|
}
|
|
@@ -75642,7 +76019,7 @@ function fetchPendleApiAssets() {
|
|
|
75642
76019
|
return cache5(
|
|
75643
76020
|
assetsCache,
|
|
75644
76021
|
async () => {
|
|
75645
|
-
const json = await
|
|
76022
|
+
const json = await getJson6(PENDLE_ASSETS_URL, "assets");
|
|
75646
76023
|
const map = /* @__PURE__ */ new Map();
|
|
75647
76024
|
for (const a of json?.assets ?? []) {
|
|
75648
76025
|
if (a?.chainId == null || !a?.address) continue;
|
|
@@ -76567,6 +76944,7 @@ var exitPhrase = {
|
|
|
76567
76944
|
"request-based": "withdrawals need a request",
|
|
76568
76945
|
"market-sale": "exit by selling on the market",
|
|
76569
76946
|
"at-maturity": "locked until maturity",
|
|
76947
|
+
"fee-or-maturity": "exit early at a discount, or at par at maturity",
|
|
76570
76948
|
"off-chain": "exit off-chain",
|
|
76571
76949
|
"dex-only": "exit only via a DEX"
|
|
76572
76950
|
};
|
|
@@ -76606,6 +76984,7 @@ function headlineExitFromRoutes(routes2, symbol) {
|
|
|
76606
76984
|
const fastPart = fast.feeBps == null ? "instant exit" : fast.feeBps === 0 ? "free instant exit" : `instant exit for ${(fast.feeBps / 100).toFixed(2)} %`;
|
|
76607
76985
|
const slowCost = slow.feeBps === 0 ? "free" : slow.feeBps != null ? `${(slow.feeBps / 100).toFixed(2)} %` : void 0;
|
|
76608
76986
|
const floor = slow.minAmountFormatted != null && slow.minAmountFormatted > 0 ? ` above ${amount(slow.minAmountFormatted)}${symbol ? ` ${symbol}` : ""}` : "";
|
|
76987
|
+
if (slow.id === "maturity") return `${fastPart}, or par at maturity`;
|
|
76609
76988
|
const slowPart = slowCost ? `queue${floor} for ${slowCost}` : `queue${floor}`;
|
|
76610
76989
|
return `${fastPart}, or ${slowPart}`;
|
|
76611
76990
|
}
|
|
@@ -78958,6 +79337,7 @@ var EXIT_MODE_LABELS = {
|
|
|
78958
79337
|
"request-based": "Request",
|
|
78959
79338
|
"market-sale": "Market sale",
|
|
78960
79339
|
"at-maturity": "At maturity",
|
|
79340
|
+
"fee-or-maturity": "Fee or maturity",
|
|
78961
79341
|
"off-chain": "Off-chain",
|
|
78962
79342
|
"dex-only": "DEX only"
|
|
78963
79343
|
};
|
|
@@ -78971,6 +79351,7 @@ var EXIT_MODE_DESCRIPTIONS = {
|
|
|
78971
79351
|
"request-based": "Withdrawals need a request and a later claim.",
|
|
78972
79352
|
"market-sale": "Exit by selling the position on a market.",
|
|
78973
79353
|
"at-maturity": "Locked until maturity.",
|
|
79354
|
+
"fee-or-maturity": "Exit early at a discount, or at par at maturity.",
|
|
78974
79355
|
"off-chain": "Exit is settled off-chain.",
|
|
78975
79356
|
"dex-only": "Exit only by selling on a DEX."
|
|
78976
79357
|
};
|
|
@@ -79277,7 +79658,10 @@ var UNCAPPED_EXIT_MODES = /* @__PURE__ */ new Set([
|
|
|
79277
79658
|
"instant-or-queued",
|
|
79278
79659
|
"request-based",
|
|
79279
79660
|
"off-chain",
|
|
79280
|
-
"at-maturity"
|
|
79661
|
+
"at-maturity",
|
|
79662
|
+
// A bond's par leg is the maturity, uncapped like `at-maturity`; the early
|
|
79663
|
+
// legs are bounded by the backing, which `liquidity` already reports.
|
|
79664
|
+
"fee-or-maturity"
|
|
79281
79665
|
]);
|
|
79282
79666
|
function meetsLiquidityFloor(input, minUsd) {
|
|
79283
79667
|
if (input.canWithdraw === false) return false;
|
|
@@ -79838,7 +80222,10 @@ function savingsCuration(provider, chainId, address) {
|
|
|
79838
80222
|
solvency: e.solvency,
|
|
79839
80223
|
accrual: e.accrual,
|
|
79840
80224
|
yieldWarmupSeconds: e.yieldWarmupSeconds,
|
|
79841
|
-
needsDepositApproval: e.needsDepositApproval
|
|
80225
|
+
needsDepositApproval: e.needsDepositApproval,
|
|
80226
|
+
// A dated bond's maturity (Usual bUSD0) — static, and the one fact that
|
|
80227
|
+
// keeps a proxied bond row from rendering as perpetual.
|
|
80228
|
+
expiry: e.expiry
|
|
79842
80229
|
};
|
|
79843
80230
|
}
|
|
79844
80231
|
function vaultTermInputFromEarnMarket(m) {
|
|
@@ -79898,7 +80285,7 @@ function vaultTermInputFromEarnMarket(m) {
|
|
|
79898
80285
|
withdrawalsPaused: m.availability.canWithdraw ? void 0 : true,
|
|
79899
80286
|
isClosed: bool2(meta.isClosed),
|
|
79900
80287
|
whitelisted: bool2(meta.whitelisted),
|
|
79901
|
-
expiry: m.maturity?.maturity,
|
|
80288
|
+
expiry: m.maturity?.maturity ?? curated.expiry,
|
|
79902
80289
|
timelock: num14(meta.timelock),
|
|
79903
80290
|
allocators: strArray(meta.allocators),
|
|
79904
80291
|
owner: str7(meta.owner),
|
|
@@ -79980,7 +80367,7 @@ function vaultTermInputFromSourceRow(row, chainId) {
|
|
|
79980
80367
|
withdrawalsPaused: bool2(meta.isWithdrawalPaused),
|
|
79981
80368
|
isClosed: bool2(meta.isClosed),
|
|
79982
80369
|
whitelisted: bool2(meta.whitelisted),
|
|
79983
|
-
expiry: num14(meta.expiry) ?? num14(meta.maturity),
|
|
80370
|
+
expiry: num14(meta.expiry) ?? num14(meta.maturity) ?? curated.expiry,
|
|
79984
80371
|
timelock: num14(meta.timelock),
|
|
79985
80372
|
allocators: strArray(meta.allocators),
|
|
79986
80373
|
owner: str7(meta.owner),
|
|
@@ -82784,6 +83171,11 @@ var isNum4 = (v) => typeof v === "number" && Number.isFinite(v);
|
|
|
82784
83171
|
function build2(input) {
|
|
82785
83172
|
const vault = jupiterLendVaultFromKey(input.lender);
|
|
82786
83173
|
const address = input.asset?.address ?? input.underlying;
|
|
83174
|
+
const smart = input.market?.fluid ?? {};
|
|
83175
|
+
const isSmartCol = !!smart.isSmartCol;
|
|
83176
|
+
const isSmartDebt = !!smart.isSmartDebt;
|
|
83177
|
+
const isSmart = isSmartCol || isSmartDebt;
|
|
83178
|
+
const pair = (p) => Array.isArray(p) ? p.join(" + ") : void 0;
|
|
82787
83179
|
const pending = {
|
|
82788
83180
|
"borrow.liquidation.liquidationMaxLimit": "the max liquidation limit (the LTV past which a position is liquidated ENTIRELY) is not served",
|
|
82789
83181
|
"borrow.availability.cap": "the layer's EXPANDING borrow limit (current, hard max, expand percent and duration) is not served \u2014 it is not a cap, so the row carries none",
|
|
@@ -82844,12 +83236,22 @@ function build2(input) {
|
|
|
82844
83236
|
constraints: {
|
|
82845
83237
|
crossMargin: false,
|
|
82846
83238
|
positionModel: "nft",
|
|
82847
|
-
positionIdMeaning: "The vault position NFT id (per vault; one collateral / debt pair each). positionId 0 MINTS a new position \u2014 only an opening deposit may pass 0; any other action sent with 0 acts on a fresh empty position and reports success."
|
|
83239
|
+
positionIdMeaning: "The vault position NFT id (per vault; one collateral / debt pair each). positionId 0 MINTS a new position \u2014 only an opening deposit may pass 0; any other action sent with 0 acts on a fresh empty position and reports success.",
|
|
83240
|
+
...isSmart ? {
|
|
83241
|
+
// the fluid adapter's notes: a smart side is a DEX share, not a token
|
|
83242
|
+
notes: [
|
|
83243
|
+
isSmartCol ? `Collateral is a Jupiter Lend DEX position (shares) over ${pair(smart.collateralPair) ?? "two tokens"}; this row is one leg of it.` : void 0,
|
|
83244
|
+
isSmartDebt ? `Debt is a Jupiter Lend DEX position (shares) over ${pair(smart.debtPair) ?? "two tokens"}; this row is one leg of it.` : void 0,
|
|
83245
|
+
isSmartDebt ? "The borrow rate is NET of the trading yield the debt LP earns, so it can be negative." : void 0,
|
|
83246
|
+
isSmartCol ? "The supply rate INCLUDES the DEX trading yield (trailing 7 days, after the protocol revenue cut) on top of the liquidity-layer rate." : void 0,
|
|
83247
|
+
"Both legs of a side move together \u2014 a leg cannot be supplied, borrowed or withdrawn on its own; the pool rebalances the split."
|
|
83248
|
+
].filter(Boolean)
|
|
83249
|
+
} : {}
|
|
82848
83250
|
},
|
|
82849
83251
|
ext: {
|
|
82850
83252
|
jupiterLend: {
|
|
82851
83253
|
...vault ? { market: vault.market, vaultId: vault.vaultId } : {},
|
|
82852
|
-
fluidVaultType: FLUID_VAULT_TYPE_T1,
|
|
83254
|
+
fluidVaultType: isNum4(smart.vaultType) ? smart.vaultType : FLUID_VAULT_TYPE_T1,
|
|
82853
83255
|
...vault?.market === "main" ? { programs: JL_MAIN_PROGRAMS } : {},
|
|
82854
83256
|
/** The marketUid ref is the leg's MINT. */
|
|
82855
83257
|
marketUidRef: "mint"
|
|
@@ -84198,7 +84600,13 @@ var SVM_EARN_VAULT_BUILDERS = {
|
|
|
84198
84600
|
"savings:Nest": { verbs: ["deposit", "request-withdraw"] },
|
|
84199
84601
|
// PRIME / AUTO: the vault-stake pool's own stake / redeem, same
|
|
84200
84602
|
// transaction; wYLDS in (or USDC, minted 1:1 first), wYLDS out
|
|
84201
|
-
"savings:Hastra": { verbs: ["deposit", "withdraw"], payAsset: true }
|
|
84603
|
+
"savings:Hastra": { verbs: ["deposit", "withdraw"], payAsset: true },
|
|
84604
|
+
// INF: Sanctum Infinity's own add / remove liquidity against wSOL
|
|
84605
|
+
"savings:Sanctum": {
|
|
84606
|
+
verbs: ["deposit", "withdraw"],
|
|
84607
|
+
nativeDeposit: true,
|
|
84608
|
+
nativeWithdraw: true
|
|
84609
|
+
}
|
|
84202
84610
|
};
|
|
84203
84611
|
var UNBUILT_REASONS = {
|
|
84204
84612
|
exponent: "Exponent PTs are not tradable through this API yet",
|