@1delta/margin-fetcher 0.0.319 → 0.0.320
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/README.md +34 -1
- package/dist/index.js +84 -4
- package/dist/index.js.map +1 -1
- package/dist/lending/public-data/midnight/convertPublic.d.ts.map +1 -1
- package/dist/lending/public-data/midnight/convertPublic.test.d.ts +2 -0
- package/dist/lending/public-data/midnight/convertPublic.test.d.ts.map +1 -0
- package/dist/lending/public-data/midnight/math.d.ts +31 -0
- package/dist/lending/public-data/midnight/math.d.ts.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @1delta/margin-fetcher
|
|
2
2
|
|
|
3
|
-
Multi-protocol lending data fetcher supporting Morpho Blue, Aave V2/V3, Compound V2/V3, Euler, Init, and
|
|
3
|
+
Multi-protocol lending data fetcher supporting Morpho Blue, Aave V2/V3, Compound V2/V3, Euler, Init, Lista DAO, and Morpho Midnight. Provides public market data (rates, TVL, configs) and per-user position data (balances, shares, collateral) in a unified format.
|
|
4
4
|
|
|
5
5
|
## How Morpho Blue Works
|
|
6
6
|
|
|
@@ -299,3 +299,36 @@ Brokered markets emit **no variable debt** — the position's `debt` is `0`, the
|
|
|
299
299
|
|
|
300
300
|
> **Note:** `terms[]` currently itemizes only fixed loans. The dynamic position (post-refinance) is
|
|
301
301
|
> included in the `debtStable` total but not yet surfaced as its own repayable term.
|
|
302
|
+
|
|
303
|
+
## Morpho Midnight extension
|
|
304
|
+
|
|
305
|
+
Morpho Midnight is a Base-only, **fixed-rate / fixed-maturity** lending protocol built on an
|
|
306
|
+
**order book of off-chain signed offers** (zero-coupon credit/debt units) — it is **NOT a Morpho
|
|
307
|
+
Blue fork**, so it is modeled as its own `'midnight'` provider (`Lender.MORPHO_MIDNIGHT`,
|
|
308
|
+
`isMidnight`), not `isMorphoType`. There is no pool and no utilization curve: rates are derived
|
|
309
|
+
from each offer's `tick` → price and its time-to-maturity, knowable only via the API. Each
|
|
310
|
+
maturity is its own isolated market, keyed `MORPHO_MIDNIGHT_<marketId>`.
|
|
311
|
+
|
|
312
|
+
### API-first fetching
|
|
313
|
+
|
|
314
|
+
Unlike Morpho Blue's GraphQL-then-on-chain hybrid, Midnight public data is **API-only** — there
|
|
315
|
+
is no on-chain public fallback in `fetchLenderAll`. The fetcher lives in
|
|
316
|
+
[`lending/public-data/midnight/`](src/lending/public-data/midnight/):
|
|
317
|
+
|
|
318
|
+
- **`apiClient` / `fetchPublic`** — an `ApiBookSource` reads the order book per market
|
|
319
|
+
(`GET /books/{id}`) from the Midnight API. The base URL resolves override → config → hosted
|
|
320
|
+
default (`https://api.morpho.org/v0/midnight`); the worker can point it at a dev API via
|
|
321
|
+
`MIDNIGHT_API_BASE` (see `data-sdk` `setMidnightApiBase`).
|
|
322
|
+
- **`math.ts`** — ported `TickLib` (`tickToApr` etc.), bit-verified against `@morpho-org/midnight-sdk`.
|
|
323
|
+
- **`convertPublic`** — normalizes the book into a `MorphoGeneralPublicResponse` keyed by
|
|
324
|
+
`MORPHO_MIDNIGHT_<id>`, emitting the fixed borrow/supply APR and a single-term
|
|
325
|
+
`params.market.terms[]` (`{termId, durationSecs, durationDays, apr}`) carrying the maturity — so
|
|
326
|
+
the maturity flows through the same generic `terms[]` path as Lista's fixed loans. Units are in
|
|
327
|
+
the **loan token's decimals** (not 18): `assets = units × price / WAD`, so `units ≈ assets`.
|
|
328
|
+
|
|
329
|
+
User positions (`{credit, debt, collateral[128], collateralBitmap}`) are read via multicall in
|
|
330
|
+
[`lending/user-data/midnight/`](src/lending/user-data/midnight/), one `UserData` per market.
|
|
331
|
+
|
|
332
|
+
> **Scope:** the fetcher and direct spot actions (supply collateral / borrow-via-`take` / repay /
|
|
333
|
+
> withdraw) are wired. Composer-routed leverage and native ETH are deferred — see
|
|
334
|
+
> [`calldata-sdk/src/evm/generic/midnight/COMPOSER_PLAN.md`](../calldata-sdk/src/evm/generic/midnight/COMPOSER_PLAN.md).
|
package/dist/index.js
CHANGED
|
@@ -20885,9 +20885,63 @@ function tickToApr(tick, timeToMaturity) {
|
|
|
20885
20885
|
function tickToAprNumber(tick, timeToMaturity) {
|
|
20886
20886
|
return Number(tickToApr(tick, timeToMaturity)) / 1e18;
|
|
20887
20887
|
}
|
|
20888
|
+
function midnightMaxLif(lltv, liquidationCursor) {
|
|
20889
|
+
const denom = WAD2 - liquidationCursor * (WAD2 - lltv) / WAD2;
|
|
20890
|
+
if (denom <= 0n) return 0n;
|
|
20891
|
+
return WAD2 * WAD2 / denom;
|
|
20892
|
+
}
|
|
20893
|
+
function midnightLiquidationPenaltyNumber(lltv, liquidationCursor) {
|
|
20894
|
+
if (lltv <= 0n || liquidationCursor <= 0n) return 0;
|
|
20895
|
+
const lif = midnightMaxLif(lltv, liquidationCursor);
|
|
20896
|
+
if (lif <= WAD2) return 0;
|
|
20897
|
+
return Number(lif - WAD2) / 1e18;
|
|
20898
|
+
}
|
|
20899
|
+
var SETTLEMENT_FEE_BREAKPOINTS_SECS = [
|
|
20900
|
+
0,
|
|
20901
|
+
86400,
|
|
20902
|
+
604800,
|
|
20903
|
+
2592e3,
|
|
20904
|
+
7776e3,
|
|
20905
|
+
15552e3,
|
|
20906
|
+
31104e3
|
|
20907
|
+
];
|
|
20908
|
+
var CBP_TO_FRACTION = 1e-6;
|
|
20909
|
+
function midnightSettlementFeeForTtm(settlementFeeCbp, ttmSecs) {
|
|
20910
|
+
const cbp = settlementFeeCbp;
|
|
20911
|
+
if (!cbp || cbp.length < 7) return 0;
|
|
20912
|
+
const bps = SETTLEMENT_FEE_BREAKPOINTS_SECS;
|
|
20913
|
+
if (ttmSecs <= 0) return cbp[0] * CBP_TO_FRACTION;
|
|
20914
|
+
if (ttmSecs >= bps[6]) return cbp[6] * CBP_TO_FRACTION;
|
|
20915
|
+
let i = 0;
|
|
20916
|
+
while (i < 6 && ttmSecs > bps[i + 1]) i++;
|
|
20917
|
+
const spanLo = bps[i];
|
|
20918
|
+
const spanHi = bps[i + 1];
|
|
20919
|
+
const t = (ttmSecs - spanLo) / (spanHi - spanLo);
|
|
20920
|
+
const feeCbp = cbp[i] + (cbp[i + 1] - cbp[i]) * t;
|
|
20921
|
+
return feeCbp * CBP_TO_FRACTION;
|
|
20922
|
+
}
|
|
20923
|
+
function midnightContinuousFeeAprPercent(continuousFeeRaw) {
|
|
20924
|
+
if (continuousFeeRaw == null) return 0;
|
|
20925
|
+
let raw;
|
|
20926
|
+
try {
|
|
20927
|
+
raw = typeof continuousFeeRaw === "bigint" ? continuousFeeRaw : BigInt(continuousFeeRaw);
|
|
20928
|
+
} catch {
|
|
20929
|
+
return 0;
|
|
20930
|
+
}
|
|
20931
|
+
if (raw <= 0n) return 0;
|
|
20932
|
+
return Number(raw * SECONDS_PER_YEAR7) / 1e18 * 100;
|
|
20933
|
+
}
|
|
20888
20934
|
|
|
20889
20935
|
// src/lending/public-data/midnight/convertPublic.ts
|
|
20890
20936
|
var nowSec = () => Math.floor(Date.now() / 1e3);
|
|
20937
|
+
function toBigIntOr0(v) {
|
|
20938
|
+
if (v === void 0 || v === null || v === "") return 0n;
|
|
20939
|
+
try {
|
|
20940
|
+
return typeof v === "bigint" ? v : BigInt(v);
|
|
20941
|
+
} catch {
|
|
20942
|
+
return 0n;
|
|
20943
|
+
}
|
|
20944
|
+
}
|
|
20891
20945
|
function midnightLenderKey(marketId) {
|
|
20892
20946
|
return "MORPHO_MIDNIGHT_" + marketId.slice(2).toUpperCase();
|
|
20893
20947
|
}
|
|
@@ -20916,6 +20970,13 @@ function convertMidnightMarketsToResponse(raw, chainId, prices = {}, _additional
|
|
|
20916
20970
|
const ttmBig = BigInt(Math.max(0, ttm));
|
|
20917
20971
|
const supplyAprPct = top?.bestSupplyTick != null && !matured ? tickToAprNumber(top.bestSupplyTick, ttmBig) * 100 : 0;
|
|
20918
20972
|
const borrowAprPct = top?.bestBorrowTick != null && !matured ? tickToAprNumber(top.bestBorrowTick, ttmBig) * 100 : 0;
|
|
20973
|
+
const settlementFee = midnightSettlementFeeForTtm(
|
|
20974
|
+
config.settlementFeeCbp,
|
|
20975
|
+
ttm
|
|
20976
|
+
);
|
|
20977
|
+
const continuousFeeAprPct = midnightContinuousFeeAprPercent(
|
|
20978
|
+
config.continuousFee
|
|
20979
|
+
);
|
|
20919
20980
|
const terms = borrowAprPct > 0 && !matured ? [
|
|
20920
20981
|
{
|
|
20921
20982
|
termId: 0,
|
|
@@ -20926,10 +20987,16 @@ function convertMidnightMarketsToResponse(raw, chainId, prices = {}, _additional
|
|
|
20926
20987
|
] : void 0;
|
|
20927
20988
|
const loanAddr = config.loanToken.toLowerCase();
|
|
20928
20989
|
const loanAsset = tokens[loanAddr];
|
|
20929
|
-
const loanKey = toOracleKey(loanAsset?.assetGroup)
|
|
20990
|
+
const loanKey = toOracleKey(loanAsset?.assetGroup) || toGenericPriceKey(loanAddr, chainId);
|
|
20930
20991
|
const loanPrice = prices[loanKey] ?? 0;
|
|
20931
|
-
const supplyLiquidity = formatNr(
|
|
20932
|
-
|
|
20992
|
+
const supplyLiquidity = formatNr(
|
|
20993
|
+
top?.supplyDepthAssets ?? 0n,
|
|
20994
|
+
config.loanDecimals
|
|
20995
|
+
);
|
|
20996
|
+
const borrowLiquidity = formatNr(
|
|
20997
|
+
top?.borrowDepthAssets ?? 0n,
|
|
20998
|
+
config.loanDecimals
|
|
20999
|
+
);
|
|
20933
21000
|
const entry = { data: {} };
|
|
20934
21001
|
const loanUid = createMarketUid(chainId, m, loanAddr);
|
|
20935
21002
|
entry.data[loanUid] = {
|
|
@@ -20954,6 +21021,11 @@ function convertMidnightMarketsToResponse(raw, chainId, prices = {}, _additional
|
|
|
20954
21021
|
// Midnight is fixed-rate: expose the fixed borrow APR on stableBorrowRate
|
|
20955
21022
|
// too, so fixed-rate consumers pick it up like a term product.
|
|
20956
21023
|
stableBorrowRate: borrowAprPct,
|
|
21024
|
+
// Mutable per-market fees (display convenience; authoritative raw values
|
|
21025
|
+
// live on params.market). continuousFeeApr is a %/yr lender-side haircut;
|
|
21026
|
+
// settlementFee is the effective fraction at the current TTM.
|
|
21027
|
+
continuousFeeApr: continuousFeeAprPct,
|
|
21028
|
+
settlementFee,
|
|
20957
21029
|
intrinsicYield: 0,
|
|
20958
21030
|
rewards: void 0,
|
|
20959
21031
|
decimals: config.loanDecimals,
|
|
@@ -20984,7 +21056,8 @@ function convertMidnightMarketsToResponse(raw, chainId, prices = {}, _additional
|
|
|
20984
21056
|
config.collateralParams.forEach((c) => {
|
|
20985
21057
|
const collAddr = c.token.toLowerCase();
|
|
20986
21058
|
const ltv = parseLtv(c.lltv);
|
|
20987
|
-
const
|
|
21059
|
+
const cursor = toBigIntOr0(c.liquidationCursor);
|
|
21060
|
+
const liquidationPenalty = cursor > 0n ? midnightLiquidationPenaltyNumber(toBigIntOr0(c.lltv), cursor) : liquidationPenaltyFromLltv(ltv);
|
|
20988
21061
|
const collUid = createMarketUid(chainId, m, collAddr);
|
|
20989
21062
|
entry.data[collUid] = {
|
|
20990
21063
|
marketUid: collUid,
|
|
@@ -21048,6 +21121,13 @@ function convertMidnightMarketsToResponse(raw, chainId, prices = {}, _additional
|
|
|
21048
21121
|
// Midnight-specific extras (consumed by calldata / worker-api resolvers)
|
|
21049
21122
|
maturity: config.maturity,
|
|
21050
21123
|
rcfThreshold: config.rcfThreshold,
|
|
21124
|
+
// Mutable, on-chain-snapshotted fees. Raw values are authoritative for
|
|
21125
|
+
// downstream ingest (yield-tracer); the derived `continuousFeeApr` (%)
|
|
21126
|
+
// and `settlementFee` (fraction at current TTM) are convenience fields.
|
|
21127
|
+
settlementFeeCbp: config.settlementFeeCbp,
|
|
21128
|
+
continuousFee: config.continuousFee,
|
|
21129
|
+
continuousFeeApr: continuousFeeAprPct,
|
|
21130
|
+
settlementFee,
|
|
21051
21131
|
enterGate: config.enterGate,
|
|
21052
21132
|
liquidatorGate: config.liquidatorGate,
|
|
21053
21133
|
collateralParams: config.collateralParams
|