@1delta/margin-fetcher 5.0.83 → 5.0.85
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +238 -4
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -48765,8 +48765,129 @@ var sthusdFetcher = {
|
|
|
48765
48765
|
};
|
|
48766
48766
|
}
|
|
48767
48767
|
};
|
|
48768
|
+
var CHAIN_ID13 = Chain.ETHEREUM_MAINNET;
|
|
48769
|
+
var HUMA_PST_FEED = "0x4be50be32db1510240d542f77c5b36ca0d0965e6";
|
|
48770
|
+
var HUMA_PST_KEY = "HUMA::PST";
|
|
48771
|
+
var HUMA_PST_GROUP_KEY = "PayFi Strategy Token::PST";
|
|
48772
|
+
var HUMA_PST_WINDOW_SECONDS = 30 * 86400;
|
|
48773
|
+
var MIN_WINDOW_SECONDS = 7 * 86400;
|
|
48774
|
+
var MAX_STALENESS_SECONDS = 14 * 86400;
|
|
48775
|
+
var PROBE_OFFSETS = [560, 620, 680, 720, 760, 820, 900, 1e3, 1200];
|
|
48776
|
+
var YEAR_SECONDS12 = 365 * 86400;
|
|
48777
|
+
var PHASE_SHIFT = 64n;
|
|
48778
|
+
var ROUND_MASK = (1n << PHASE_SHIFT) - 1n;
|
|
48779
|
+
var FEED_ABI = [
|
|
48780
|
+
{
|
|
48781
|
+
name: "latestRoundData",
|
|
48782
|
+
type: "function",
|
|
48783
|
+
stateMutability: "view",
|
|
48784
|
+
inputs: [],
|
|
48785
|
+
outputs: [
|
|
48786
|
+
{ name: "roundId", type: "uint80" },
|
|
48787
|
+
{ name: "answer", type: "int256" },
|
|
48788
|
+
{ name: "startedAt", type: "uint256" },
|
|
48789
|
+
{ name: "updatedAt", type: "uint256" },
|
|
48790
|
+
{ name: "answeredInRound", type: "uint80" }
|
|
48791
|
+
]
|
|
48792
|
+
},
|
|
48793
|
+
{
|
|
48794
|
+
name: "getRoundData",
|
|
48795
|
+
type: "function",
|
|
48796
|
+
stateMutability: "view",
|
|
48797
|
+
inputs: [{ name: "roundId", type: "uint80" }],
|
|
48798
|
+
outputs: [
|
|
48799
|
+
{ name: "roundId", type: "uint80" },
|
|
48800
|
+
{ name: "answer", type: "int256" },
|
|
48801
|
+
{ name: "startedAt", type: "uint256" },
|
|
48802
|
+
{ name: "updatedAt", type: "uint256" },
|
|
48803
|
+
{ name: "answeredInRound", type: "uint80" }
|
|
48804
|
+
]
|
|
48805
|
+
}
|
|
48806
|
+
];
|
|
48807
|
+
var parseRound = (raw) => {
|
|
48808
|
+
if (!raw) return void 0;
|
|
48809
|
+
const tuple = Array.isArray(raw) ? raw : [
|
|
48810
|
+
raw.roundId,
|
|
48811
|
+
raw.answer,
|
|
48812
|
+
raw.startedAt,
|
|
48813
|
+
raw.updatedAt
|
|
48814
|
+
];
|
|
48815
|
+
const answer = tuple[1];
|
|
48816
|
+
const updatedAt = tuple[3];
|
|
48817
|
+
if (typeof answer !== "bigint" || typeof updatedAt !== "bigint")
|
|
48818
|
+
return void 0;
|
|
48819
|
+
if (answer <= 0n || updatedAt <= 0n) return void 0;
|
|
48820
|
+
return { answer, updatedAt: Number(updatedAt) };
|
|
48821
|
+
};
|
|
48822
|
+
var windowAprFromRounds = (latest, candidates, nowSeconds, windowSeconds = HUMA_PST_WINDOW_SECONDS) => {
|
|
48823
|
+
if (nowSeconds - latest.updatedAt > MAX_STALENESS_SECONDS) {
|
|
48824
|
+
throw new Error(
|
|
48825
|
+
`Huma PST: feed stale \u2014 last update ${nowSeconds - latest.updatedAt}s ago`
|
|
48826
|
+
);
|
|
48827
|
+
}
|
|
48828
|
+
const cutoff = latest.updatedAt - windowSeconds;
|
|
48829
|
+
const older = candidates.filter((c) => c.updatedAt < latest.updatedAt).sort((a, b) => b.updatedAt - a.updatedAt);
|
|
48830
|
+
if (older.length === 0) throw new Error("Huma PST: no historical round");
|
|
48831
|
+
const start = older.find((c) => c.updatedAt <= cutoff) ?? older[older.length - 1];
|
|
48832
|
+
const dt = latest.updatedAt - start.updatedAt;
|
|
48833
|
+
if (dt < MIN_WINDOW_SECONDS) {
|
|
48834
|
+
throw new Error(`Huma PST: window too short (${dt}s)`);
|
|
48835
|
+
}
|
|
48836
|
+
const growth = Number(latest.answer * 10n ** 18n / start.answer) / 1e18 - 1;
|
|
48837
|
+
const apr = growth * YEAR_SECONDS12 * 100 / dt;
|
|
48838
|
+
if (!Number.isFinite(apr) || Math.abs(apr) > 100) {
|
|
48839
|
+
throw new Error(`Huma PST: implausible rate ${apr}`);
|
|
48840
|
+
}
|
|
48841
|
+
return apr;
|
|
48842
|
+
};
|
|
48843
|
+
var fetchPstAprOnChain = async () => {
|
|
48844
|
+
const [latestRaw] = await multicallRetryUniversal({
|
|
48845
|
+
chain: CHAIN_ID13,
|
|
48846
|
+
abi: FEED_ABI,
|
|
48847
|
+
calls: [{ address: HUMA_PST_FEED, name: "latestRoundData", params: [] }],
|
|
48848
|
+
allowFailure: false
|
|
48849
|
+
});
|
|
48850
|
+
const latestTuple = Array.isArray(latestRaw) ? latestRaw : [latestRaw?.roundId];
|
|
48851
|
+
const latestRoundId = latestTuple[0];
|
|
48852
|
+
const latest = parseRound(latestRaw);
|
|
48853
|
+
if (typeof latestRoundId !== "bigint" || !latest) {
|
|
48854
|
+
throw new Error("Huma PST: latestRoundData unreadable");
|
|
48855
|
+
}
|
|
48856
|
+
const phase = latestRoundId >> PHASE_SHIFT;
|
|
48857
|
+
const aggRound = latestRoundId & ROUND_MASK;
|
|
48858
|
+
const probeRounds = [
|
|
48859
|
+
...new Set(
|
|
48860
|
+
PROBE_OFFSETS.map((off) => {
|
|
48861
|
+
const r = aggRound - BigInt(off);
|
|
48862
|
+
return r < 1n ? 1n : r;
|
|
48863
|
+
})
|
|
48864
|
+
)
|
|
48865
|
+
];
|
|
48866
|
+
const results = await multicallRetryUniversal({
|
|
48867
|
+
chain: CHAIN_ID13,
|
|
48868
|
+
abi: FEED_ABI,
|
|
48869
|
+
calls: probeRounds.map((r) => ({
|
|
48870
|
+
address: HUMA_PST_FEED,
|
|
48871
|
+
name: "getRoundData",
|
|
48872
|
+
params: [phase << PHASE_SHIFT | r]
|
|
48873
|
+
})),
|
|
48874
|
+
allowFailure: true
|
|
48875
|
+
});
|
|
48876
|
+
const candidates = results.map(parseRound).filter((r) => r !== void 0);
|
|
48877
|
+
return windowAprFromRounds(latest, candidates, Math.floor(Date.now() / 1e3));
|
|
48878
|
+
};
|
|
48879
|
+
var humaPstFetcher = {
|
|
48880
|
+
label: "HUMA_PST",
|
|
48881
|
+
fetch: async () => {
|
|
48882
|
+
const apr = await fetchPstAprOnChain();
|
|
48883
|
+
return {
|
|
48884
|
+
[HUMA_PST_KEY]: apr,
|
|
48885
|
+
[HUMA_PST_GROUP_KEY]: apr
|
|
48886
|
+
};
|
|
48887
|
+
}
|
|
48888
|
+
};
|
|
48768
48889
|
var RAY9 = 10n ** 27n;
|
|
48769
|
-
var
|
|
48890
|
+
var YEAR_SECONDS13 = 31536e3;
|
|
48770
48891
|
var DSR_ABI = [
|
|
48771
48892
|
{
|
|
48772
48893
|
name: "dsr",
|
|
@@ -48794,7 +48915,7 @@ var SUSDD_GROUP_KEY = "Savings Usdd::sUSDD";
|
|
|
48794
48915
|
var aprFromDsr = (dsr) => {
|
|
48795
48916
|
if (dsr <= RAY9) return 0;
|
|
48796
48917
|
const perSecond = Number(dsr - RAY9) / 1e27;
|
|
48797
|
-
return perSecond *
|
|
48918
|
+
return perSecond * YEAR_SECONDS13 * 100;
|
|
48798
48919
|
};
|
|
48799
48920
|
var fetchChainDsr = async (chainId, pot) => {
|
|
48800
48921
|
const [dsr] = await multicallRetryUniversal({
|
|
@@ -52675,6 +52796,72 @@ var SINGLE_CHAIN_ENTRIES = {
|
|
|
52675
52796
|
withdrawalCooldownSeconds: 432e3,
|
|
52676
52797
|
yieldFetcher: sthusdFetcher,
|
|
52677
52798
|
yieldKey: STHUSD_KEY
|
|
52799
|
+
},
|
|
52800
|
+
{
|
|
52801
|
+
// Huma **PST** (PayFi Strategy Token), bridged. Huma 2.0 is a
|
|
52802
|
+
// SOLANA product: a permissionless USDC pool (no KYC) funding
|
|
52803
|
+
// short-dated cross-border payment receivables — originated almost
|
|
52804
|
+
// entirely by Arf, a Huma affiliate — whose yield is paid as a rising
|
|
52805
|
+
// PST price. 306.6M PST exist ($347M at 1.1325); **148.2M of them are
|
|
52806
|
+
// on Ethereum** through Chainlink CCIP, and 125.8M of THOSE sit as
|
|
52807
|
+
// collateral in Morpho Blue (84.4M, three listed markets at 86 % LLTV)
|
|
52808
|
+
// and Fluid (41.4M, vaults 165/166/169) — the Ethereum book is a
|
|
52809
|
+
// loop book, ~22M floats. Assessed + built 2026-09-16; see HUMA.md.
|
|
52810
|
+
//
|
|
52811
|
+
// This address is NOT a vault. It is Chainlink's `BurnMintERC20`,
|
|
52812
|
+
// whose only minter and burner is the CCIP `BurnMintTokenPool 1.6.1`
|
|
52813
|
+
// (`0xbe776c85…`, one lane, Solana): no `asset()`, no
|
|
52814
|
+
// `convertToAssets()`, no `owner()`, not verified on Sourcify. So there
|
|
52815
|
+
// is **no primary mint and no redemption on this chain at all** — the
|
|
52816
|
+
// ways in and out are the market (Fluid DEX PST-USDC: a $1M round trip
|
|
52817
|
+
// quoted ~4 bps total on KyberSwap at integration) or the bridge back
|
|
52818
|
+
// to Solana. Hence `secondaryMarketOnly`: the Re shape, but with an
|
|
52819
|
+
// even plainer reason — Re's mint is KYC-gated, this one does not
|
|
52820
|
+
// exist. `isMintable: false` states that fact, not a permission.
|
|
52821
|
+
//
|
|
52822
|
+
// Priced by Chainlink's **"PST-USDC Exchange Rate (Calculated)"**
|
|
52823
|
+
// proxy `0x4be50be3…` — the same feed both Morpho PST oracles wrap as
|
|
52824
|
+
// `BASE_FEED_1`, so the earn row and the lending rows cannot disagree
|
|
52825
|
+
// about what a PST is worth. It answers in **6 decimals** (hence
|
|
52826
|
+
// `priceOracleDecimals`), hourly, and — unlike Re's feeds — keeps its
|
|
52827
|
+
// FULL round history, which is where `humaPstFetcher` measures the
|
|
52828
|
+
// realized rate (7.7 % APR on every window since 2026-05-25). TRAP: the
|
|
52829
|
+
// feed's AGGREGATOR reverts `No access` for a contract caller, so any
|
|
52830
|
+
// multicall must target the PROXY, which is what this pins.
|
|
52831
|
+
//
|
|
52832
|
+
// `nav-attested`, asserted: the price is produced by Huma's own
|
|
52833
|
+
// off-chain Price Oracle and relayed by Chainlink — an operator-
|
|
52834
|
+
// published NAV over an off-chain receivables book with a "modest"
|
|
52835
|
+
// first-loss cover and no on-chain solvency invariant (the Theo /
|
|
52836
|
+
// Maple / Native trust class). Every consequence the label earns —
|
|
52837
|
+
// `nav-accrual` as the rate kind, `nav-drawdown` in the risks — is
|
|
52838
|
+
// true here.
|
|
52839
|
+
//
|
|
52840
|
+
// `withdrawalMode` / cooldown describe the exit a holder who BRIDGES
|
|
52841
|
+
// BACK gets on Solana: a redemption request the operator's autotask
|
|
52842
|
+
// settles "typically within 1 business day", SLA 7 days, under a global
|
|
52843
|
+
// daily cap that rejects further requests once hit. The pin is the SLA
|
|
52844
|
+
// worst case (the Re call); a bridge hop each way is on top. For a
|
|
52845
|
+
// holder on this chain the exit is the `market` route.
|
|
52846
|
+
reader: "nav-oracle",
|
|
52847
|
+
solvency: "nav-attested",
|
|
52848
|
+
address: "0x22ae3d9a738471f405169af055d31c687087d4c7",
|
|
52849
|
+
underlying: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
|
|
52850
|
+
// USDC
|
|
52851
|
+
priceOracle: HUMA_PST_FEED,
|
|
52852
|
+
priceOracleDecimals: 6,
|
|
52853
|
+
symbol: "PST",
|
|
52854
|
+
brand: "Huma",
|
|
52855
|
+
description: "Huma's PayFi Strategy Token, bridged from Solana over Chainlink CCIP: a share of Huma 2.0's USDC pool, funding short-dated cross-border payment receivables nearly all originated by Arf, a Huma affiliate; the fee is paid as a rising PST price set by Huma's oracle and relayed by Chainlink. There is no mint and no redemption on Ethereum: you enter and exit by TRADING PST (venue: Fluid DEX PST-USDC) against that NAV, or by bridging back to Solana, where redemption is an operator-settled request under a daily cap. Backing is unsecured receivables credit with a small first-loss cover.",
|
|
52856
|
+
decimals: 6,
|
|
52857
|
+
underlyingDecimals: 6,
|
|
52858
|
+
isRebasing: false,
|
|
52859
|
+
isMintable: false,
|
|
52860
|
+
secondaryMarketOnly: true,
|
|
52861
|
+
withdrawalMode: "request-based",
|
|
52862
|
+
withdrawalCooldownSeconds: 7 * 86400,
|
|
52863
|
+
yieldFetcher: humaPstFetcher,
|
|
52864
|
+
yieldKey: HUMA_PST_KEY
|
|
52678
52865
|
}
|
|
52679
52866
|
],
|
|
52680
52867
|
"100": [
|
|
@@ -52964,6 +53151,53 @@ var SINGLE_CHAIN_ENTRIES = {
|
|
|
52964
53151
|
yieldKey: STHUSD_KEY
|
|
52965
53152
|
}
|
|
52966
53153
|
],
|
|
53154
|
+
// ---------------------------------------------------------------------
|
|
53155
|
+
// Arc (5042) — Circle's USDC-gas L1, mainnet 2026-09-16. One row: Huma's
|
|
53156
|
+
// PST, bridged in over Chainlink CCIP the same day.
|
|
53157
|
+
// ---------------------------------------------------------------------
|
|
53158
|
+
"5042": [
|
|
53159
|
+
{
|
|
53160
|
+
// Huma **PST**, bridged to Arc. Same asset and same trust story as the
|
|
53161
|
+
// chain-1 row (see it for the product); what differs is the SHAPE of
|
|
53162
|
+
// the exit. On Ethereum PST has $16M of DEX depth, so the row is
|
|
53163
|
+
// `secondaryMarketOnly`. Here it has NONE: KyberSwap answers
|
|
53164
|
+
// `route not found` for PST on Arc while routing USDC→WETH fine, and
|
|
53165
|
+
// at integration the whole bridged supply (441,548 PST, ≈ $500k) sat
|
|
53166
|
+
// inside the one listed Morpho Blue PST/USDC market — the Theo-on-
|
|
53167
|
+
// Stable shape, where a `via: 'swap'` route would advertise depth that
|
|
53168
|
+
// does not exist. So `isMintable: false` (a CCIP `BurnMintERC20` has
|
|
53169
|
+
// no mint function) and NOT `secondaryMarketOnly`: the only way in or
|
|
53170
|
+
// out is the bridge back to Solana. Flip the flag when a venue appears.
|
|
53171
|
+
//
|
|
53172
|
+
// Priced by Chainlink's **"PSTUSDC / USDC Exchange Rate"** proxy
|
|
53173
|
+
// `0x1abf15e8…` on Arc — the feed the Morpho market's oracle wraps as
|
|
53174
|
+
// `BASE_FEED_1`, so the earn row and the lending row agree. 6 decimals
|
|
53175
|
+
// TODAY; TRAP: its round history is NOT uniformly scaled — rounds 1
|
|
53176
|
+
// to ~100 (2026-06-19 → 06-23) answered at 12 decimals
|
|
53177
|
+
// (`1111266641610`) before the feed settled at 6 — so never derive a
|
|
53178
|
+
// rate from this feed's history. The rate is `humaPstFetcher`, which
|
|
53179
|
+
// measures the Ethereum feed; PST accrues identically on every chain
|
|
53180
|
+
// (1.132518 here vs 1.132511 on Ethereum at the same hour).
|
|
53181
|
+
reader: "nav-oracle",
|
|
53182
|
+
solvency: "nav-attested",
|
|
53183
|
+
address: "0xa6db07ebf438d91aa653746fc05523e435645525",
|
|
53184
|
+
underlying: "0x3600000000000000000000000000000000000000",
|
|
53185
|
+
// USDC (ERC-20)
|
|
53186
|
+
priceOracle: "0x1abf15e82566d274bf8722ac3e42fc3c79304051",
|
|
53187
|
+
priceOracleDecimals: 6,
|
|
53188
|
+
symbol: "PST",
|
|
53189
|
+
brand: "Huma",
|
|
53190
|
+
description: "Huma's PayFi Strategy Token, bridged to Arc over Chainlink CCIP: a share of Huma 2.0's USDC pool on Solana, funding short-dated cross-border payment receivables nearly all originated by Arf, a Huma affiliate; the fee is paid as a rising PST price set by Huma's oracle and relayed by Chainlink. There is no mint, no redemption and no trading venue on Arc: the only way in or out is bridging back to Solana, where redemption is an operator-settled request under a daily cap. Backing is unsecured receivables credit with a small first-loss cover.",
|
|
53191
|
+
decimals: 6,
|
|
53192
|
+
underlyingDecimals: 6,
|
|
53193
|
+
isRebasing: false,
|
|
53194
|
+
isMintable: false,
|
|
53195
|
+
withdrawalMode: "request-based",
|
|
53196
|
+
withdrawalCooldownSeconds: 7 * 86400,
|
|
53197
|
+
yieldFetcher: humaPstFetcher,
|
|
53198
|
+
yieldKey: HUMA_PST_KEY
|
|
53199
|
+
}
|
|
53200
|
+
],
|
|
52967
53201
|
"4663": [
|
|
52968
53202
|
{
|
|
52969
53203
|
// Spark Vaults V2 spUSDG on Robinhood Chain — the first V2 vault
|
|
@@ -73206,7 +73440,7 @@ var readVaultSharePrices = async (chainId, addresses, multicallRetry) => {
|
|
|
73206
73440
|
};
|
|
73207
73441
|
|
|
73208
73442
|
// src/vaults/yield/annualize.ts
|
|
73209
|
-
var
|
|
73443
|
+
var YEAR_SECONDS14 = 365 * 24 * 60 * 60;
|
|
73210
73444
|
var SCALE = 10n ** 18n;
|
|
73211
73445
|
var appendSnapshot = (points, snap, options) => {
|
|
73212
73446
|
const maxPoints = options?.maxPoints ?? 90;
|
|
@@ -73235,7 +73469,7 @@ var computeVaultApr = (points, options) => {
|
|
|
73235
73469
|
if (pThen === 0n) return void 0;
|
|
73236
73470
|
const ratioScaled = BigInt(now.p) * SCALE / pThen;
|
|
73237
73471
|
const ratio = Number(ratioScaled) / 1e18;
|
|
73238
|
-
const apr = (ratio - 1) * (
|
|
73472
|
+
const apr = (ratio - 1) * (YEAR_SECONDS14 / windowSeconds);
|
|
73239
73473
|
return {
|
|
73240
73474
|
apr,
|
|
73241
73475
|
sharePriceNow: now.p,
|