@1delta/margin-fetcher 5.0.6 → 5.0.8
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 +21 -3
- package/dist/index.js +43 -10
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -8416,7 +8416,16 @@ interface TermAssetRef {
|
|
|
8416
8416
|
* `tags.ts` — never hand-written per lender, so they cannot drift from the
|
|
8417
8417
|
* numbers they summarize.
|
|
8418
8418
|
*/
|
|
8419
|
-
type TermTag = Open<'fixed-rate' | 'variable-rate' | 'user-set-rate' | 'zero-interest' | 'prepaid-interest' | 'nav-accrual' | 'has-maturity' | 'perpetual' | 'rolling-duration' | 'static-debt' | 'accruing-debt' | 'time-liquidation' | 'price-liquidation' | 'redeemable' | 'no-liquidation' | 'full-collateral-seizure' | 'early-exit-free' | 'early-exit-penalty' | 'early-exit-discount' | 'exit-instant' | 'exit-capped' | 'exit-cooldown'
|
|
8419
|
+
type TermTag = Open<'fixed-rate' | 'variable-rate' | 'user-set-rate' | 'zero-interest' | 'prepaid-interest' | 'nav-accrual' | 'has-maturity' | 'perpetual' | 'rolling-duration' | 'static-debt' | 'accruing-debt' | 'time-liquidation' | 'price-liquidation' | 'redeemable' | 'no-liquidation' | 'full-collateral-seizure' | 'early-exit-free' | 'early-exit-penalty' | 'early-exit-discount' | 'exit-instant' | 'exit-capped' | 'exit-cooldown'
|
|
8420
|
+
/**
|
|
8421
|
+
* The DEBT cannot be repaid for a period after opening or topping up.
|
|
8422
|
+
*
|
|
8423
|
+
* Deliberately distinct from `exit-cooldown` (a supply-side withdrawal
|
|
8424
|
+
* delay): this one means the position cannot be closed, deleveraged or
|
|
8425
|
+
* migrated out — and, on the lender that has it, that an incoming
|
|
8426
|
+
* liquidation cannot be averted by repaying.
|
|
8427
|
+
*/
|
|
8428
|
+
| 'repay-locked' | 'exit-queued' | 'exit-market-sale' | 'exit-may-be-impossible' | 'permissioned' | 'capped' | 'cap-full' | 'first-loss' | 'socialized-loss' | 'physical-delivery' | 'undercollateralized' | 'nav-attested' | 'immutable' | 'no-timelock' | 'eoa-controlled' | 'points-rewards'
|
|
8420
8429
|
/**
|
|
8421
8430
|
* The headline yield is MOSTLY the asset's own (staking / RWA / savings)
|
|
8422
8431
|
* yield, not interest this market pays. Set at >= 50 % of `aprTotal`.
|
|
@@ -8799,8 +8808,17 @@ interface LiquidationTerms {
|
|
|
8799
8808
|
ltv?: number;
|
|
8800
8809
|
/** Threshold at which liquidation becomes possible. */
|
|
8801
8810
|
liquidationLtv?: number;
|
|
8802
|
-
/**
|
|
8803
|
-
|
|
8811
|
+
/**
|
|
8812
|
+
* Fraction of repaid debt paid to the liquidator on top of par.
|
|
8813
|
+
*
|
|
8814
|
+
* OPTIONAL, and the distinction is load-bearing: `0` means "the liquidator
|
|
8815
|
+
* gets no bonus", `undefined` means "we do not know it". The first cut
|
|
8816
|
+
* defaulted the unknown case to `0` and every market on `/lending/latest`
|
|
8817
|
+
* rendered a confident "Liquidator takes debt repaid + 0%" — the origin's
|
|
8818
|
+
* `market_config` had no penalty column at all, so NOTHING was known. A row
|
|
8819
|
+
* we cannot fill must be absent, not zero.
|
|
8820
|
+
*/
|
|
8821
|
+
penalty?: number;
|
|
8804
8822
|
closeFactor: number;
|
|
8805
8823
|
targetHealthFactor?: number;
|
|
8806
8824
|
/**
|
package/dist/index.js
CHANGED
|
@@ -62293,9 +62293,11 @@ function deriveBorrowTags(borrow, market = {}) {
|
|
|
62293
62293
|
if (borrow.liquidation.redeemable) push(out, "redeemable");
|
|
62294
62294
|
if (borrow.liquidation.seizure === "full-collateral")
|
|
62295
62295
|
push(out, "full-collateral-seizure");
|
|
62296
|
+
const repayLocked = (borrow.exit.cooldownSecs ?? 0) > 0;
|
|
62297
|
+
if (repayLocked) push(out, "repay-locked");
|
|
62296
62298
|
switch (borrow.exit.earlyRepay) {
|
|
62297
62299
|
case "free":
|
|
62298
|
-
push(out, "early-exit-free");
|
|
62300
|
+
if (!repayLocked) push(out, "early-exit-free");
|
|
62299
62301
|
break;
|
|
62300
62302
|
case "penalty":
|
|
62301
62303
|
push(out, "early-exit-penalty");
|
|
@@ -62451,6 +62453,9 @@ function borrowHeadline(b) {
|
|
|
62451
62453
|
) : `${rateLabel(b)} ${pct(b.rate.apr)}`;
|
|
62452
62454
|
const mat = b.maturity.kind === "perpetual" ? "" : ` ${maturityPhrase(b.maturity)}`;
|
|
62453
62455
|
const exit = earlyRepayPhrase[String(b.exit.earlyRepay)] ?? "see repay terms";
|
|
62456
|
+
if (b.exit.cooldownSecs) {
|
|
62457
|
+
return `${rate}${mat} \xB7 no repayment for ${duration(b.exit.cooldownSecs)}, then ${exit}`;
|
|
62458
|
+
}
|
|
62454
62459
|
return `${rate}${mat} \xB7 ${exit}`;
|
|
62455
62460
|
}
|
|
62456
62461
|
function supplyDescription(s, sheet = {}) {
|
|
@@ -62535,8 +62540,9 @@ function borrowDescription(b) {
|
|
|
62535
62540
|
"Liquidation here is triggered by TIME, not price \u2014 being late is the trigger, and being over-collateralised does not protect you."
|
|
62536
62541
|
);
|
|
62537
62542
|
} else if (b.liquidation.liquidationLtv != null) {
|
|
62543
|
+
const pen = b.liquidation.penalty;
|
|
62538
62544
|
parts.push(
|
|
62539
|
-
`Liquidation starts at ${pct(b.liquidation.liquidationLtv * 100)} LTV
|
|
62545
|
+
`Liquidation starts at ${pct(b.liquidation.liquidationLtv * 100)} LTV` + (pen != null ? `, with a ${pct(pen * 100)} penalty` : "") + "."
|
|
62540
62546
|
);
|
|
62541
62547
|
}
|
|
62542
62548
|
return parts.join(" ");
|
|
@@ -63162,7 +63168,20 @@ function buildConstraints(input, siblings, acceptedCollateral) {
|
|
|
63162
63168
|
}
|
|
63163
63169
|
};
|
|
63164
63170
|
}
|
|
63165
|
-
function
|
|
63171
|
+
function marketLltv(input) {
|
|
63172
|
+
const raw = input.market?.lltv;
|
|
63173
|
+
if (raw == null) return void 0;
|
|
63174
|
+
const n = Number(raw);
|
|
63175
|
+
if (!Number.isFinite(n) || n <= 0) return void 0;
|
|
63176
|
+
return n / 1e18;
|
|
63177
|
+
}
|
|
63178
|
+
function liquidationFrom(cfg, input, acceptedCollateral) {
|
|
63179
|
+
const lltv = marketLltv(input);
|
|
63180
|
+
const soleCollateral = acceptedCollateral?.count === 1 ? acceptedCollateral.items[0] : void 0;
|
|
63181
|
+
const isolated = lltv != null || !hasCrossMarginRisk(input.lender) && soleCollateral != null;
|
|
63182
|
+
const ownLtv = cfg?.borrowCollateralFactor;
|
|
63183
|
+
const ownLiqLtv = cfg?.collateralFactor;
|
|
63184
|
+
const ownPenalty = cfg?.liquidationPenalty;
|
|
63166
63185
|
return {
|
|
63167
63186
|
// The ordinary model: a liquidator repays part of the debt and takes
|
|
63168
63187
|
// collateral plus a bonus. Adapters override for the four lenders where
|
|
@@ -63170,9 +63189,11 @@ function liquidationFrom(cfg, input) {
|
|
|
63170
63189
|
model: "repay-seize",
|
|
63171
63190
|
absorber: "liquidator",
|
|
63172
63191
|
trigger: "price",
|
|
63173
|
-
ltv:
|
|
63174
|
-
liquidationLtv:
|
|
63175
|
-
penalty
|
|
63192
|
+
ltv: ownLtv || (isolated ? soleCollateral?.ltv ?? lltv : void 0) || ownLtv,
|
|
63193
|
+
liquidationLtv: ownLiqLtv || (isolated ? soleCollateral?.liquidationLtv ?? lltv : void 0) || ownLiqLtv,
|
|
63194
|
+
// No `?? 0` — see `LiquidationTerms.penalty`. An unknown penalty is
|
|
63195
|
+
// undefined so the row is omitted rather than rendered as "+0%".
|
|
63196
|
+
penalty: ownPenalty || (isolated ? soleCollateral?.liquidationPenalty : void 0) || ownPenalty,
|
|
63176
63197
|
closeFactor: cfg?.closeFactor ?? input.closeFactor ?? 1,
|
|
63177
63198
|
targetHealthFactor: cfg?.targetHealthFactor ?? input.targetHealthFactor,
|
|
63178
63199
|
seizure: "proportional",
|
|
@@ -63199,7 +63220,8 @@ function buildModes(input) {
|
|
|
63199
63220
|
liquidation: {
|
|
63200
63221
|
ltv: c.borrowCollateralFactor,
|
|
63201
63222
|
liquidationLtv: c.collateralFactor,
|
|
63202
|
-
penalty:
|
|
63223
|
+
// Same rule as the top-level penalty: unknown stays unknown.
|
|
63224
|
+
penalty: c.liquidationPenalty,
|
|
63203
63225
|
closeFactor: c.closeFactor ?? input.closeFactor ?? 1,
|
|
63204
63226
|
targetHealthFactor: c.targetHealthFactor ?? input.targetHealthFactor
|
|
63205
63227
|
},
|
|
@@ -63294,6 +63316,7 @@ function buildBorrow(input, now, siblings) {
|
|
|
63294
63316
|
const rate = buildRate(input, "borrow");
|
|
63295
63317
|
const maturity = buildMaturity(input, now);
|
|
63296
63318
|
const fees = buildFees(input, "borrow");
|
|
63319
|
+
const acceptedCollateral = buildExposures2(input, siblings, "accepted");
|
|
63297
63320
|
const borrow = {
|
|
63298
63321
|
rate,
|
|
63299
63322
|
maturity,
|
|
@@ -63308,8 +63331,8 @@ function buildBorrow(input, now, siblings) {
|
|
|
63308
63331
|
minDebt: resolveMinDebt(input),
|
|
63309
63332
|
fees: fees.filter((f) => f.when === "exit" || f.when === "late")
|
|
63310
63333
|
},
|
|
63311
|
-
liquidation: liquidationFrom(cfg, input),
|
|
63312
|
-
acceptedCollateral
|
|
63334
|
+
liquidation: liquidationFrom(cfg, input, acceptedCollateral),
|
|
63335
|
+
acceptedCollateral,
|
|
63313
63336
|
modes: buildModes(input),
|
|
63314
63337
|
fees,
|
|
63315
63338
|
counterparty: { kind: "pool", solvency: "overcollateralized" },
|
|
@@ -63633,6 +63656,16 @@ function supplyFindings(supply) {
|
|
|
63633
63656
|
function borrowFindings(borrow) {
|
|
63634
63657
|
const out = [];
|
|
63635
63658
|
const liq = borrow.liquidation;
|
|
63659
|
+
if (borrow.exit.cooldownSecs) {
|
|
63660
|
+
out.push({
|
|
63661
|
+
severity: "critical",
|
|
63662
|
+
id: "repay-locked",
|
|
63663
|
+
side: "borrow",
|
|
63664
|
+
message: `The debt CANNOT be repaid for ${fmtSecs(
|
|
63665
|
+
borrow.exit.cooldownSecs
|
|
63666
|
+
)} after opening or topping up: the position cannot be closed, deleveraged or migrated out in that window, and an incoming liquidation cannot be averted by repaying (adding collateral still works).`
|
|
63667
|
+
});
|
|
63668
|
+
}
|
|
63636
63669
|
if (liq.seizure === "full-collateral") {
|
|
63637
63670
|
out.push({
|
|
63638
63671
|
severity: "critical",
|
|
@@ -64924,7 +64957,7 @@ function validateTermSheet(sheet) {
|
|
|
64924
64957
|
"full-collateral seizure must surface a tag or an implication"
|
|
64925
64958
|
);
|
|
64926
64959
|
}
|
|
64927
|
-
if (l.penalty < 0 || l.penalty > 1)
|
|
64960
|
+
if (l.penalty != null && (l.penalty < 0 || l.penalty > 1))
|
|
64928
64961
|
fail("penalty-range", `liquidation.penalty ${l.penalty} outside 0..1`);
|
|
64929
64962
|
if (l.closeFactor <= 0 || l.closeFactor > 1)
|
|
64930
64963
|
fail(
|