@1delta/margin-fetcher 0.0.335 → 0.0.336

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';
@@ -22667,7 +22667,8 @@ function convertRiverMarketsToResponse(raw, chainId, prices = {}, _additionalYie
22667
22667
  return out;
22668
22668
  }
22669
22669
  var READS_PER_POOL = 7;
22670
- var READS_PER_MARKET = 2;
22670
+ var READS_PER_MARKET = 4;
22671
+ var MARKET_PHASE_ABI = [...TellerMarketRegistryAbi, ...TellerV2Abi];
22671
22672
  async function fetchTellerMarkets(chainId) {
22672
22673
  const pools = tellerPoolsByChain(chainId);
22673
22674
  if (pools.length === 0) return { chainId, pools: [] };
@@ -22734,6 +22735,8 @@ async function fetchTellerMarkets(chainId) {
22734
22735
  };
22735
22736
  });
22736
22737
  const attByMarket = /* @__PURE__ */ new Map();
22738
+ let protocolFeeBps;
22739
+ const proto = tellerConfigByChain(chainId);
22737
22740
  if (marketRegistry) {
22738
22741
  const uniqueMarkets = [
22739
22742
  ...new Set(
@@ -22741,28 +22744,45 @@ async function fetchTellerMarkets(chainId) {
22741
22744
  )
22742
22745
  ];
22743
22746
  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
- ]);
22747
+ const mCalls = [
22748
+ { address: proto?.tellerV2 ?? marketRegistry, name: "protocolFee", params: [] },
22749
+ ...uniqueMarkets.flatMap((m) => [
22750
+ {
22751
+ address: marketRegistry,
22752
+ name: "getMarketAttestationRequirements",
22753
+ params: [BigInt(m)]
22754
+ },
22755
+ { address: marketRegistry, name: "isMarketOpen", params: [BigInt(m)] },
22756
+ { address: marketRegistry, name: "getMarketplaceFee", params: [BigInt(m)] },
22757
+ {
22758
+ address: marketRegistry,
22759
+ name: "getPaymentDefaultDuration",
22760
+ params: [BigInt(m)]
22761
+ }
22762
+ ])
22763
+ ];
22752
22764
  try {
22753
22765
  const mRes = await multicallRetryUniversal({
22754
22766
  chain: chainId,
22755
22767
  calls: mCalls,
22756
- abi: TellerMarketRegistryAbi,
22768
+ abi: MARKET_PHASE_ABI,
22757
22769
  allowFailure: true
22758
22770
  });
22771
+ const pf = mRes[0];
22772
+ protocolFeeBps = typeof pf === "bigint" || typeof pf === "number" ? Number(pf) : void 0;
22759
22773
  uniqueMarkets.forEach((m, i) => {
22760
- const att = mRes[i * READS_PER_MARKET];
22761
- const open = mRes[i * READS_PER_MARKET + 1];
22774
+ const base = 1 + i * READS_PER_MARKET;
22775
+ const att = mRes[base];
22776
+ const open = mRes[base + 1];
22777
+ const fee = mRes[base + 2];
22778
+ const dur = mRes[base + 3];
22762
22779
  const borrowerRequired = (att?.borrowerAttestationRequired ?? att?.[1]) === true;
22780
+ const asNum = (v) => typeof v === "bigint" || typeof v === "number" ? Number(v) : void 0;
22763
22781
  attByMarket.set(m, {
22764
22782
  requiresBorrowerAttestation: borrowerRequired,
22765
- marketOpen: open === false ? false : true
22783
+ marketOpen: open === false ? false : true,
22784
+ marketFeeBps: asNum(fee),
22785
+ paymentDefaultDuration: asNum(dur)
22766
22786
  });
22767
22787
  });
22768
22788
  } catch {
@@ -22774,7 +22794,10 @@ async function fetchTellerMarkets(chainId) {
22774
22794
  return {
22775
22795
  ...p,
22776
22796
  requiresBorrowerAttestation: att?.requiresBorrowerAttestation,
22777
- marketOpen: att?.marketOpen
22797
+ marketOpen: att?.marketOpen,
22798
+ marketFeeBps: att?.marketFeeBps,
22799
+ protocolFeeBps,
22800
+ paymentDefaultDuration: att?.paymentDefaultDuration
22778
22801
  };
22779
22802
  });
22780
22803
  return { chainId, pools: out };
@@ -22812,6 +22835,12 @@ function currencyFor6(address, decimals, symbol, tokens) {
22812
22835
  const lower = address.toLowerCase();
22813
22836
  return tokens[lower] ?? { address: lower, symbol, name: symbol, decimals };
22814
22837
  }
22838
+ function fmtDuration(sec) {
22839
+ if (sec == null || sec <= 0) return "a short window";
22840
+ if (sec < 3600) return `${Math.round(sec / 60)} minute${sec < 120 ? "" : "s"}`;
22841
+ if (sec < 86400) return `${Math.round(sec / 3600)} hour${sec < 7200 ? "" : "s"}`;
22842
+ return `${Math.round(sec / 86400)} day${sec < 172800 ? "" : "s"}`;
22843
+ }
22815
22844
  function priceFor(address, chainId, tokens, prices) {
22816
22845
  const lower = address.toLowerCase();
22817
22846
  const token = tokens[lower];
@@ -22967,11 +22996,31 @@ function convertTellerMarketsToResponse(raw, chainId, prices = {}, _additionalYi
22967
22996
  isActive: true,
22968
22997
  isFrozen: false
22969
22998
  };
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
- ];
22999
+ const marketFeeBps = p.marketFeeBps ?? 0;
23000
+ const protocolFeeBps = p.protocolFeeBps ?? 0;
23001
+ const originationFeeBps = marketFeeBps + protocolFeeBps;
23002
+ const originationFeePercent = originationFeeBps / 100;
23003
+ const graceSec = p.paymentDefaultDuration;
23004
+ const graceHuman = fmtDuration(graceSec);
23005
+ const ltvPct = ltv > 0 ? Math.round(ltv * 100) : void 0;
23006
+ const lossX = ltv > 0 ? (1 / ltv).toFixed(1) : void 0;
23007
+ const implications = [];
23008
+ implications.push(
23009
+ 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.`
23010
+ );
23011
+ implications.push(
23012
+ "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."
23013
+ );
23014
+ if (originationFeeBps > 0)
23015
+ implications.push(
23016
+ `Upfront origination fee of ${originationFeePercent}% is charged on the borrow (market ${marketFeeBps / 100}% + protocol ${protocolFeeBps / 100}%).`
23017
+ );
23018
+ implications.push(
23019
+ "Fixed-term, fixed-APR: the rate is locked at borrow time for a duration you choose (up to the pool max)."
23020
+ );
23021
+ implications.push(
23022
+ "Closing is a FULL repayment: it repays principal + interest and releases ALL collateral in one tx (a partial repay keeps the collateral escrowed)."
23023
+ );
22975
23024
  if (p.requiresBorrowerAttestation)
22976
23025
  implications.push(
22977
23026
  "This market requires borrower ATTESTATION \u2014 the borrower must be whitelisted by the market owner before borrowing."
@@ -22999,7 +23048,7 @@ function convertTellerMarketsToResponse(raw, chainId, prices = {}, _additionalYi
22999
23048
  fixedTerm: {
23000
23049
  model: "teller",
23001
23050
  maturity: void 0,
23002
- fees: {},
23051
+ fees: originationFeeBps > 0 ? { originationFeePercent } : {},
23003
23052
  earlyRepay: { kind: "none" },
23004
23053
  provider: { kind: "pool", address: cfg.pool.toLowerCase() }
23005
23054
  },
@@ -23015,6 +23064,13 @@ function convertTellerMarketsToResponse(raw, chainId, prices = {}, _additionalYi
23015
23064
  // UI/allocator). `marketOpen` = MarketRegistry.isMarketOpen.
23016
23065
  requiresBorrowerAttestation: p.requiresBorrowerAttestation,
23017
23066
  marketOpen: p.marketOpen,
23067
+ // Fees (bps + combined percent) — upfront origination fee on the borrow.
23068
+ marketFeeBps: p.marketFeeBps,
23069
+ protocolFeeBps: p.protocolFeeBps,
23070
+ originationFeePercent: originationFeeBps > 0 ? originationFeePercent : void 0,
23071
+ /** Grace window (secs) after the term before DEFAULT + full-collateral
23072
+ * liquidation. Can be very short (observed 300s = 5 min). */
23073
+ paymentDefaultDuration: p.paymentDefaultDuration,
23018
23074
  /** Human-readable caveats for the UI to surface (see above). */
23019
23075
  implications,
23020
23076
  minInterestRateBps: p.minRateBps ?? void 0,