@1delta/margin-fetcher 0.0.335 → 0.0.337

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 CHANGED
@@ -6,7 +6,7 @@ export { isAaveType, isAaveV2Type, isAaveV32Type, isAaveV3Type, isCompoundV3, is
6
6
  import { fetchTokenLists, fetchTokenList, aavePools, compoundV3Pools, initConfig, morphoPools, compoundV2Pools, eulerVaults, siloMarkets, siloV2LenderKey, siloMarketsV3, siloV3LenderKey, aaveV4Spokes, aaveV4SpokeLenderKey, fluidResolvers, gearboxResolvers, dolomiteConfigs, midnightConfig, termConfig, termMarketsByChain, exactlyConfig, liquityLendersByChain, riverLendersByChain, tellerConfigByChain, tellerPoolsByChain, aaveReserves, compoundV3Reserves, liquityConfigFor, liquityBranchesByChain, riverConfigFor, riverChainData, morphoTypeMarkets, resolveMidnightApiBase, resolveTermApiBase, getSiloV2MarketEntry, getSiloV3MarketEntry, dolomiteEmode, aaveTokens, morphoTypeVaults, eulerConfigs, gearboxMarketCompressor, gearboxMarketConfigurators, gearboxV3LenderKey, midnightMarketsByChain, parseAaveV4SpokeLenderKey, gearboxAccountCompressor, compoundV2Tokens, exactlyMarketsByChain, aaveOracles, aaveOraclesConfig, compoundV2Oracles, compoundV2TokenArray, compoundV2OraclesConfig, compoundV3OraclesData, compoundV3BaseData, compoundV2Reserves, aaveV4Oracles } from '@1delta/data-sdk';
7
7
  import lodash from 'lodash';
8
8
  import { getEvmClient, multicallRetryUniversal, getEvmChain, getEvmClientUniversal } from '@1delta/providers';
9
- import { LiquityTroveManagerAbi, LiquityActivePoolAbi, LiquityStabilityPoolAbi, LiquityPriceFeedAbi, LiquitySortedTrovesAbi, RiverTroveManagerAbi, RiverStabilityPoolAbi, MetaMorphoAbi, ExactlyPreviewerAbi, ExactlyAuditorAbi, LenderCommitmentGroupAbi, TellerMarketRegistryAbi, TellerV2Abi, FluidLendingResolverAbi, FluidVaultResolverAbi, FluidLiquidityResolverAbi, MoolahVaultAbi, MorphoLensAbi, AaveV4SpokeAbi, AaveV4OracleAbi, AaveV4HubAbi, DolomiteMarginAbi, GearboxMarketCompressorV310Abi, MorphoBlueAbi, MidnightAbi, TermRepoTokenAbi, TermRepoServicerAbi, TermRepoCollateralManagerAbi, LiquityTroveNFTAbi, LiquityCollSurplusPoolAbi, TellerCollateralManagerAbi, GearboxCreditAccountCompressorV310Abi, TermPriceConsumerAbi } from '@1delta/abis';
9
+ import { LiquityTroveManagerAbi, LiquityActivePoolAbi, LiquityStabilityPoolAbi, LiquityPriceFeedAbi, LiquitySortedTrovesAbi, RiverTroveManagerAbi, RiverStabilityPoolAbi, TellerMarketRegistryAbi, TellerV2Abi, MetaMorphoAbi, ExactlyPreviewerAbi, ExactlyAuditorAbi, LenderCommitmentGroupAbi, FluidLendingResolverAbi, FluidVaultResolverAbi, FluidLiquidityResolverAbi, MoolahVaultAbi, MorphoLensAbi, AaveV4SpokeAbi, AaveV4OracleAbi, AaveV4HubAbi, DolomiteMarginAbi, GearboxMarketCompressorV310Abi, MorphoBlueAbi, MidnightAbi, TermRepoTokenAbi, TermRepoServicerAbi, TermRepoCollateralManagerAbi, LiquityTroveNFTAbi, LiquityCollSurplusPoolAbi, TellerCollateralManagerAbi, GearboxCreditAccountCompressorV310Abi, TermPriceConsumerAbi } from '@1delta/abis';
10
10
  export { MorphoLensAbi } from '@1delta/abis';
11
11
  import { prepareDebitDataMulticall, prepareLenderDebitMulticall, parseDebitDataResult, parseLenderDebitResult, getPermit2ContractAddress, getCompoundV3CometAddress as getCompoundV3CometAddress$1, getMorphoAddress, getAaveCollateralTokenAddress, getSiloHalfForUnderlying, InitMarginAddresses, getLstAcceptedInputs } from '@1delta/calldata-sdk';
12
12
  import { proxyNativeFetch } from '@1delta/proxy-fetch';
@@ -20464,6 +20464,16 @@ var getGearboxV3PublicDataConverter = (_lender, chainId, prices, additionalYield
20464
20464
  0
20465
20465
  );
20466
20466
  const poolUtilization = poolExpectedLiquidity > 0 ? poolIrmDebt / poolExpectedLiquidity : 0;
20467
+ const quotaRatePctByToken = {};
20468
+ const quotaSrc = Array.isArray(m?.quotaKeeper?.quotas) && m.quotaKeeper.quotas || Array.isArray(m?.rateKeeper?.rates) && m.rateKeeper.rates || [];
20469
+ for (const q of quotaSrc) {
20470
+ const t = (q?.token ?? "").toString().toLowerCase();
20471
+ if (!t) continue;
20472
+ if (q?.isActive === false) continue;
20473
+ const rate = Number(q?.rate ?? 0);
20474
+ if (!(rate > 0)) continue;
20475
+ quotaRatePctByToken[t] = rate / 100;
20476
+ }
20467
20477
  for (const cm of m.creditManagers ?? []) {
20468
20478
  const facade = cm?.creditFacade;
20469
20479
  const manager = cm?.creditManager;
@@ -20561,6 +20571,8 @@ var getGearboxV3PublicDataConverter = (_lender, chainId, prices, additionalYield
20561
20571
  const ctPriceKey = toOracleKey(ctMeta?.assetGroup) ?? toGenericPriceKey(token, chainId);
20562
20572
  const colMarketUid = createMarketUid(chainId, lender, token);
20563
20573
  if (colMarketUid === loanMarketUid) continue;
20574
+ const quotaRate = quotaRatePctByToken[token] ?? 0;
20575
+ const grossIntrinsic = additionalYields?.intrinsicYields?.[ctPriceKey] ?? 0;
20564
20576
  data2[colMarketUid] = {
20565
20577
  marketUid: colMarketUid,
20566
20578
  name: "Collateral " + (ctMeta?.symbol ?? ""),
@@ -20581,7 +20593,8 @@ var getGearboxV3PublicDataConverter = (_lender, chainId, prices, additionalYield
20581
20593
  depositRate: 0,
20582
20594
  variableBorrowRate: 0,
20583
20595
  stableBorrowRate: 0,
20584
- intrinsicYield: additionalYields?.intrinsicYields?.[ctPriceKey] ?? 0,
20596
+ intrinsicYield: grossIntrinsic - quotaRate,
20597
+ quotaRate,
20585
20598
  rewards: [],
20586
20599
  decimals: ctDecimals,
20587
20600
  config: {
@@ -22667,7 +22680,8 @@ function convertRiverMarketsToResponse(raw, chainId, prices = {}, _additionalYie
22667
22680
  return out;
22668
22681
  }
22669
22682
  var READS_PER_POOL = 7;
22670
- var READS_PER_MARKET = 2;
22683
+ var READS_PER_MARKET = 4;
22684
+ var MARKET_PHASE_ABI = [...TellerMarketRegistryAbi, ...TellerV2Abi];
22671
22685
  async function fetchTellerMarkets(chainId) {
22672
22686
  const pools = tellerPoolsByChain(chainId);
22673
22687
  if (pools.length === 0) return { chainId, pools: [] };
@@ -22734,6 +22748,8 @@ async function fetchTellerMarkets(chainId) {
22734
22748
  };
22735
22749
  });
22736
22750
  const attByMarket = /* @__PURE__ */ new Map();
22751
+ let protocolFeeBps;
22752
+ const proto = tellerConfigByChain(chainId);
22737
22753
  if (marketRegistry) {
22738
22754
  const uniqueMarkets = [
22739
22755
  ...new Set(
@@ -22741,28 +22757,45 @@ async function fetchTellerMarkets(chainId) {
22741
22757
  )
22742
22758
  ];
22743
22759
  if (uniqueMarkets.length > 0) {
22744
- const mCalls = uniqueMarkets.flatMap((m) => [
22745
- {
22746
- address: marketRegistry,
22747
- name: "getMarketAttestationRequirements",
22748
- params: [BigInt(m)]
22749
- },
22750
- { address: marketRegistry, name: "isMarketOpen", params: [BigInt(m)] }
22751
- ]);
22760
+ const mCalls = [
22761
+ { address: proto?.tellerV2 ?? marketRegistry, name: "protocolFee", params: [] },
22762
+ ...uniqueMarkets.flatMap((m) => [
22763
+ {
22764
+ address: marketRegistry,
22765
+ name: "getMarketAttestationRequirements",
22766
+ params: [BigInt(m)]
22767
+ },
22768
+ { address: marketRegistry, name: "isMarketOpen", params: [BigInt(m)] },
22769
+ { address: marketRegistry, name: "getMarketplaceFee", params: [BigInt(m)] },
22770
+ {
22771
+ address: marketRegistry,
22772
+ name: "getPaymentDefaultDuration",
22773
+ params: [BigInt(m)]
22774
+ }
22775
+ ])
22776
+ ];
22752
22777
  try {
22753
22778
  const mRes = await multicallRetryUniversal({
22754
22779
  chain: chainId,
22755
22780
  calls: mCalls,
22756
- abi: TellerMarketRegistryAbi,
22781
+ abi: MARKET_PHASE_ABI,
22757
22782
  allowFailure: true
22758
22783
  });
22784
+ const pf = mRes[0];
22785
+ protocolFeeBps = typeof pf === "bigint" || typeof pf === "number" ? Number(pf) : void 0;
22759
22786
  uniqueMarkets.forEach((m, i) => {
22760
- const att = mRes[i * READS_PER_MARKET];
22761
- const open = mRes[i * READS_PER_MARKET + 1];
22787
+ const base = 1 + i * READS_PER_MARKET;
22788
+ const att = mRes[base];
22789
+ const open = mRes[base + 1];
22790
+ const fee = mRes[base + 2];
22791
+ const dur = mRes[base + 3];
22762
22792
  const borrowerRequired = (att?.borrowerAttestationRequired ?? att?.[1]) === true;
22793
+ const asNum = (v) => typeof v === "bigint" || typeof v === "number" ? Number(v) : void 0;
22763
22794
  attByMarket.set(m, {
22764
22795
  requiresBorrowerAttestation: borrowerRequired,
22765
- marketOpen: open === false ? false : true
22796
+ marketOpen: open === false ? false : true,
22797
+ marketFeeBps: asNum(fee),
22798
+ paymentDefaultDuration: asNum(dur)
22766
22799
  });
22767
22800
  });
22768
22801
  } catch {
@@ -22774,7 +22807,10 @@ async function fetchTellerMarkets(chainId) {
22774
22807
  return {
22775
22808
  ...p,
22776
22809
  requiresBorrowerAttestation: att?.requiresBorrowerAttestation,
22777
- marketOpen: att?.marketOpen
22810
+ marketOpen: att?.marketOpen,
22811
+ marketFeeBps: att?.marketFeeBps,
22812
+ protocolFeeBps,
22813
+ paymentDefaultDuration: att?.paymentDefaultDuration
22778
22814
  };
22779
22815
  });
22780
22816
  return { chainId, pools: out };
@@ -22812,6 +22848,12 @@ function currencyFor6(address, decimals, symbol, tokens) {
22812
22848
  const lower = address.toLowerCase();
22813
22849
  return tokens[lower] ?? { address: lower, symbol, name: symbol, decimals };
22814
22850
  }
22851
+ function fmtDuration(sec) {
22852
+ if (sec == null || sec <= 0) return "a short window";
22853
+ if (sec < 3600) return `${Math.round(sec / 60)} minute${sec < 120 ? "" : "s"}`;
22854
+ if (sec < 86400) return `${Math.round(sec / 3600)} hour${sec < 7200 ? "" : "s"}`;
22855
+ return `${Math.round(sec / 86400)} day${sec < 172800 ? "" : "s"}`;
22856
+ }
22815
22857
  function priceFor(address, chainId, tokens, prices) {
22816
22858
  const lower = address.toLowerCase();
22817
22859
  const token = tokens[lower];
@@ -22967,11 +23009,31 @@ function convertTellerMarketsToResponse(raw, chainId, prices = {}, _additionalYi
22967
23009
  isActive: true,
22968
23010
  isFrozen: false
22969
23011
  };
22970
- const implications = [
22971
- "Fixed-term, fixed-APR loan: the rate is locked at borrow time for a duration you choose (up to the pool max).",
22972
- "TIME-based liquidation only \u2014 collateral is seized if a payment is missed past the market window. There is NO price-based liquidation and NO margin call.",
22973
- "Closing is a FULL repayment: it repays principal + interest and releases ALL collateral in one tx (no partial collateral withdrawal; a partial repay keeps the collateral escrowed)."
22974
- ];
23012
+ const marketFeeBps = p.marketFeeBps ?? 0;
23013
+ const protocolFeeBps = p.protocolFeeBps ?? 0;
23014
+ const originationFeeBps = marketFeeBps + protocolFeeBps;
23015
+ const originationFeePercent = originationFeeBps / 100;
23016
+ const graceSec = p.paymentDefaultDuration;
23017
+ const graceHuman = fmtDuration(graceSec);
23018
+ const ltvPct = ltv > 0 ? Math.round(ltv * 100) : void 0;
23019
+ const lossX = ltv > 0 ? (1 / ltv).toFixed(1) : void 0;
23020
+ const implications = [];
23021
+ implications.push(
23022
+ graceSec != null ? `\u26A0 FULL-COLLATERAL liquidation: after the loan term you have only a SHORT grace window (~${graceHuman}) to roll over or repay. Miss it and the loan DEFAULTS \u2014 a liquidator can seize your ENTIRE escrowed collateral, not just the amount owed.${lossX ? ` At ${ltvPct}% LTV that is ~${lossX}\xD7 the borrowed value lost.` : ""}` : `\u26A0 FULL-COLLATERAL liquidation: if you miss the rollover/repay deadline past the market's grace window, the loan DEFAULTS and your ENTIRE collateral can be seized \u2014 not just the amount owed.`
23023
+ );
23024
+ implications.push(
23025
+ "TIME-based liquidation only \u2014 NO price-based liquidation and NO margin call; the ONLY trigger is a missed payment past the deadline. Set a reminder to roll over or repay on time."
23026
+ );
23027
+ if (originationFeeBps > 0)
23028
+ implications.push(
23029
+ `Upfront origination fee of ${originationFeePercent}% is charged on the borrow (market ${marketFeeBps / 100}% + protocol ${protocolFeeBps / 100}%).`
23030
+ );
23031
+ implications.push(
23032
+ "Fixed-term, fixed-APR: the rate is locked at borrow time for a duration you choose (up to the pool max)."
23033
+ );
23034
+ implications.push(
23035
+ "Closing is a FULL repayment: it repays principal + interest and releases ALL collateral in one tx (a partial repay keeps the collateral escrowed)."
23036
+ );
22975
23037
  if (p.requiresBorrowerAttestation)
22976
23038
  implications.push(
22977
23039
  "This market requires borrower ATTESTATION \u2014 the borrower must be whitelisted by the market owner before borrowing."
@@ -22999,7 +23061,7 @@ function convertTellerMarketsToResponse(raw, chainId, prices = {}, _additionalYi
22999
23061
  fixedTerm: {
23000
23062
  model: "teller",
23001
23063
  maturity: void 0,
23002
- fees: {},
23064
+ fees: originationFeeBps > 0 ? { originationFeePercent } : {},
23003
23065
  earlyRepay: { kind: "none" },
23004
23066
  provider: { kind: "pool", address: cfg.pool.toLowerCase() }
23005
23067
  },
@@ -23015,6 +23077,13 @@ function convertTellerMarketsToResponse(raw, chainId, prices = {}, _additionalYi
23015
23077
  // UI/allocator). `marketOpen` = MarketRegistry.isMarketOpen.
23016
23078
  requiresBorrowerAttestation: p.requiresBorrowerAttestation,
23017
23079
  marketOpen: p.marketOpen,
23080
+ // Fees (bps + combined percent) — upfront origination fee on the borrow.
23081
+ marketFeeBps: p.marketFeeBps,
23082
+ protocolFeeBps: p.protocolFeeBps,
23083
+ originationFeePercent: originationFeeBps > 0 ? originationFeePercent : void 0,
23084
+ /** Grace window (secs) after the term before DEFAULT + full-collateral
23085
+ * liquidation. Can be very short (observed 300s = 5 min). */
23086
+ paymentDefaultDuration: p.paymentDefaultDuration,
23018
23087
  /** Human-readable caveats for the UI to surface (see above). */
23019
23088
  implications,
23020
23089
  minInterestRateBps: p.minRateBps ?? void 0,