@1delta/margin-fetcher 0.0.231 → 0.0.233

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.
Files changed (36) hide show
  1. package/dist/abis/silo-v2/InterestRateModelV2.d.ts +52 -0
  2. package/dist/abis/silo-v2/InterestRateModelV2.d.ts.map +1 -0
  3. package/dist/index.js +471 -69
  4. package/dist/index.js.map +1 -1
  5. package/dist/lending/margin/e-mode/index.d.ts +10 -1
  6. package/dist/lending/margin/e-mode/index.d.ts.map +1 -1
  7. package/dist/lending/public-data/fetchLender.d.ts.map +1 -1
  8. package/dist/lending/public-data/fetchLenderAll.d.ts.map +1 -1
  9. package/dist/lending/public-data/fetchLenderExt.d.ts.map +1 -1
  10. package/dist/lending/public-data/silo-v2/irmRates.d.ts +38 -0
  11. package/dist/lending/public-data/silo-v2/irmRates.d.ts.map +1 -0
  12. package/dist/lending/public-data/silo-v2/publicCallBuild.d.ts +15 -13
  13. package/dist/lending/public-data/silo-v2/publicCallBuild.d.ts.map +1 -1
  14. package/dist/lending/public-data/silo-v2/publicCallParse.d.ts.map +1 -1
  15. package/dist/lending/public-data/silo-v3/publicCallBuild.d.ts +10 -7
  16. package/dist/lending/public-data/silo-v3/publicCallBuild.d.ts.map +1 -1
  17. package/dist/lending/public-data/silo-v3/publicCallParse.d.ts.map +1 -1
  18. package/dist/lending/user-data/abis.d.ts.map +1 -1
  19. package/dist/lending/user-data/fetch-balances/parse.d.ts.map +1 -1
  20. package/dist/lending/user-data/fetch-balances/prepare.d.ts.map +1 -1
  21. package/dist/lending/user-data/silo-v2/userCallParse.d.ts.map +1 -1
  22. package/dist/lending/user-data/silo-v3/userCallBuild.d.ts +5 -0
  23. package/dist/lending/user-data/silo-v3/userCallBuild.d.ts.map +1 -0
  24. package/dist/lending/user-data/silo-v3/userCallParse.d.ts +30 -0
  25. package/dist/lending/user-data/silo-v3/userCallParse.d.ts.map +1 -0
  26. package/dist/lending/user-data/with-permissions/evaluate.d.ts +2 -0
  27. package/dist/lending/user-data/with-permissions/evaluate.d.ts.map +1 -1
  28. package/dist/lending/user-data/with-permissions/types.d.ts +2 -0
  29. package/dist/lending/user-data/with-permissions/types.d.ts.map +1 -1
  30. package/dist/prices/oracle-prices/fetchers/compoundV2.d.ts +2 -0
  31. package/dist/prices/oracle-prices/fetchers/compoundV2.d.ts.map +1 -1
  32. package/dist/types/lenderTypes.d.ts +6 -0
  33. package/dist/types/lenderTypes.d.ts.map +1 -1
  34. package/dist/utils/index.d.ts +1 -1
  35. package/dist/utils/index.d.ts.map +1 -1
  36. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import lodash from 'lodash';
7
7
  import { getEvmChain, getEvmClient, getEvmClientUniversal, multicallRetryUniversal } from '@1delta/providers';
8
8
  import { MorphoLensAbi, AaveV4SpokeAbi, AaveV4OracleAbi, AaveV4HubAbi, MorphoBlueAbi } from '@1delta/abis';
9
9
  export { MorphoLensAbi } from '@1delta/abis';
10
- import { prepareDebitDataMulticall, prepareLenderDebitMulticall, parseDebitDataResult, parseLenderDebitResult, getPermit2ContractAddress, getCompoundV3CometAddress as getCompoundV3CometAddress$1, getMorphoAddress, getAaveCollateralTokenAddress, InitMarginAddresses } from '@1delta/calldata-sdk';
10
+ import { prepareDebitDataMulticall, prepareLenderDebitMulticall, parseDebitDataResult, parseLenderDebitResult, getPermit2ContractAddress, getCompoundV3CometAddress as getCompoundV3CometAddress$1, getMorphoAddress, getAaveCollateralTokenAddress, getSiloHalfForUnderlying, InitMarginAddresses } from '@1delta/calldata-sdk';
11
11
  import { BALANCER_V2_FORKS, BALANCER_V3_FORKS, UNISWAP_V4_FORKS, FLASH_LOAN_IDS } from '@1delta/dex-registry';
12
12
 
13
13
  // src/abis/aave-v2/ProtocolDataProvider.ts
@@ -13449,7 +13449,7 @@ function getCompoundV2Lens(chainId, lender) {
13449
13449
  return COMPOUND_V2_LENS[lender]?.[chainId];
13450
13450
  }
13451
13451
  function getCompoundV2Tokens(chainId, lender = Lender.VENUS) {
13452
- return compoundV2TokenArray()?.[lender]?.[chainId];
13452
+ return compoundV2TokenArray()?.[lender]?.[chainId] ?? [];
13453
13453
  }
13454
13454
 
13455
13455
  // src/abis/compound-v2/VenusLensLegacy.ts
@@ -18709,8 +18709,36 @@ var SiloLensAbi = [
18709
18709
  }
18710
18710
  ];
18711
18711
 
18712
+ // src/abis/silo-v2/InterestRateModelV2.ts
18713
+ var InterestRateModelV2Abi = [
18714
+ {
18715
+ type: "function",
18716
+ name: "getConfig",
18717
+ stateMutability: "view",
18718
+ inputs: [{ name: "_silo", type: "address" }],
18719
+ outputs: [
18720
+ {
18721
+ name: "",
18722
+ type: "tuple",
18723
+ components: [
18724
+ { name: "uopt", type: "int256" },
18725
+ { name: "ucrit", type: "int256" },
18726
+ { name: "ulow", type: "int256" },
18727
+ { name: "klin", type: "int256" },
18728
+ { name: "ki", type: "int256" },
18729
+ { name: "kcrit", type: "int256" },
18730
+ { name: "klow", type: "int256" },
18731
+ { name: "beta", type: "int256" },
18732
+ { name: "ri", type: "int256" },
18733
+ { name: "Tcrit", type: "int256" }
18734
+ ]
18735
+ }
18736
+ ]
18737
+ }
18738
+ ];
18739
+
18712
18740
  // src/lending/public-data/silo-v2/publicCallBuild.ts
18713
- var SILO_V2_CALLS_PER_SIDE = 2;
18741
+ var SILO_V2_CALLS_PER_SIDE = 3;
18714
18742
  var SILO_V2_CALLS_PER_PAIR = SILO_V2_CALLS_PER_SIDE * 2;
18715
18743
  function buildSiloV2LenderReserveCall(_chainId, lender) {
18716
18744
  const market = getSiloV2MarketEntry(_chainId, lender);
@@ -18729,13 +18757,96 @@ function buildSiloV2LenderReserveCall(_chainId, lender) {
18729
18757
  name: "getDebtAssets",
18730
18758
  params: [],
18731
18759
  abi: SiloAbi
18760
+ },
18761
+ {
18762
+ address: half.interestRateModel,
18763
+ name: "getConfig",
18764
+ params: [half.silo],
18765
+ abi: InterestRateModelV2Abi
18732
18766
  }
18733
18767
  );
18734
18768
  }
18735
18769
  return calls;
18736
18770
  }
18737
18771
 
18772
+ // src/lending/public-data/silo-v2/irmRates.ts
18773
+ var DP = 1e18;
18774
+ var WAD = 1e18;
18775
+ var SECONDS_PER_YEAR4 = 365 * 24 * 3600;
18776
+ function toBigIntSafe(val) {
18777
+ if (typeof val === "bigint") return val;
18778
+ if (val == null || val === "0x") return 0n;
18779
+ try {
18780
+ return BigInt(val);
18781
+ } catch {
18782
+ return 0n;
18783
+ }
18784
+ }
18785
+ function parseIRMConfig(raw, half) {
18786
+ if (!raw || raw === "0x") return null;
18787
+ try {
18788
+ const uopt = toBigIntSafe(raw.uopt ?? raw[0]);
18789
+ const ucrit = toBigIntSafe(raw.ucrit ?? raw[1]);
18790
+ const ulow = toBigIntSafe(raw.ulow ?? raw[2]);
18791
+ const klin = toBigIntSafe(raw.klin ?? raw[3]);
18792
+ const ki = toBigIntSafe(raw.ki ?? raw[4]);
18793
+ const kcrit = toBigIntSafe(raw.kcrit ?? raw[5]);
18794
+ const klow = toBigIntSafe(raw.klow ?? raw[6]);
18795
+ const beta = toBigIntSafe(raw.beta ?? raw[7]);
18796
+ const ri = toBigIntSafe(raw.ri ?? raw[8]);
18797
+ const Tcrit = toBigIntSafe(raw.Tcrit ?? raw[9]);
18798
+ const daoFee = half.daoFee != null ? Number(BigInt(half.daoFee)) / WAD : void 0;
18799
+ const deployerFee = half.deployerFee != null ? Number(BigInt(half.deployerFee)) / WAD : void 0;
18800
+ return {
18801
+ uopt,
18802
+ ucrit,
18803
+ ulow,
18804
+ klin,
18805
+ ki,
18806
+ kcrit,
18807
+ klow,
18808
+ beta,
18809
+ ri,
18810
+ Tcrit,
18811
+ ...daoFee != null ? { daoFee } : {},
18812
+ ...deployerFee != null ? { deployerFee } : {}
18813
+ };
18814
+ } catch {
18815
+ return null;
18816
+ }
18817
+ }
18818
+ function calculateBorrowRate(utilization, params) {
18819
+ const uopt = Number(params.uopt) / DP;
18820
+ const ucrit = Number(params.ucrit) / DP;
18821
+ const ulow = Number(params.ulow) / DP;
18822
+ const klin = Number(params.klin) / DP;
18823
+ const ki = Number(params.ki) / DP;
18824
+ const kcrit = Number(params.kcrit) / DP;
18825
+ const klow = Number(params.klow) / DP;
18826
+ const ri = Number(params.ri) / DP;
18827
+ const Tcrit = Number(params.Tcrit) / DP;
18828
+ const beta = Number(params.beta) / DP;
18829
+ const u = utilization;
18830
+ const T = 0;
18831
+ const rp = u > ucrit ? kcrit * (1 + Tcrit + beta * T) * (u - ucrit) : Math.min(0, klow * (u - ulow));
18832
+ const rlin = klin * u;
18833
+ let riEff = Math.max(ri, rlin);
18834
+ riEff = Math.max(riEff + ki * (u - uopt) * T, rlin);
18835
+ const rcurPerSecond = Math.max(riEff + rp, rlin);
18836
+ const rcurAnnual = rcurPerSecond * SECONDS_PER_YEAR4;
18837
+ return Math.min(Math.max(rcurAnnual * 100, 0), 1e4);
18838
+ }
18839
+ function calculateSiloRates(utilization, params) {
18840
+ const borrowRate = calculateBorrowRate(utilization, params);
18841
+ const daoFee = params.daoFee ?? 0;
18842
+ const deployerFee = params.deployerFee ?? 0;
18843
+ const totalFee = daoFee + deployerFee;
18844
+ const depositRate = borrowRate / 100 * utilization * (1 - totalFee) * 100;
18845
+ return { borrowRate, depositRate };
18846
+ }
18847
+
18738
18848
  // src/lending/public-data/silo-v2/publicCallParse.ts
18849
+ var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
18739
18850
  var getSiloV2ReservesDataConverter = (lender, chainId, prices, additionalYields, tokenList = {}) => {
18740
18851
  const market = getSiloV2MarketEntry(chainId, lender);
18741
18852
  if (!market) return [() => void 0, 0];
@@ -18747,7 +18858,7 @@ var getSiloV2ReservesDataConverter = (lender, chainId, prices, additionalYields,
18747
18858
  { self: market.silo0, other: market.silo1 },
18748
18859
  { self: market.silo1, other: market.silo0 }
18749
18860
  ];
18750
- const toBigInt6 = (v) => {
18861
+ const toBigInt7 = (v) => {
18751
18862
  if (v === void 0 || v === null || v === "0x") return 0n;
18752
18863
  if (typeof v === "bigint") return v;
18753
18864
  try {
@@ -18759,15 +18870,25 @@ var getSiloV2ReservesDataConverter = (lender, chainId, prices, additionalYields,
18759
18870
  for (let s = 0; s < 2; s++) {
18760
18871
  const { self, other } = sides[s];
18761
18872
  const slot = s * SILO_V2_CALLS_PER_SIDE;
18762
- const totalAssetsRaw = toBigInt6(data[slot]);
18763
- const debtAssetsRaw = toBigInt6(data[slot + 1]);
18873
+ const totalAssetsRaw = toBigInt7(data[slot]);
18874
+ const debtAssetsRaw = toBigInt7(data[slot + 1]);
18875
+ const irmConfigRaw = data[slot + 2];
18764
18876
  const decimals = self.decimals;
18765
18877
  const totalDeposits = Number(formatUnits(totalAssetsRaw, decimals));
18766
18878
  const totalDebt = Number(formatUnits(debtAssetsRaw, decimals));
18767
18879
  const totalLiquidity = totalDeposits - totalDebt;
18768
18880
  const utilization = totalDeposits > 0 ? totalDebt / totalDeposits : 0;
18769
- const depositRatePct = 0;
18770
- const variableBorrowRatePct = 0;
18881
+ let depositRatePct = 0;
18882
+ let variableBorrowRatePct = 0;
18883
+ const irmParams = parseIRMConfig(irmConfigRaw, self);
18884
+ if (irmParams) {
18885
+ try {
18886
+ const rates = calculateSiloRates(utilization, irmParams);
18887
+ variableBorrowRatePct = rates.borrowRate;
18888
+ depositRatePct = rates.depositRate;
18889
+ } catch {
18890
+ }
18891
+ }
18771
18892
  const tokenAddrLc = self.token.toLowerCase();
18772
18893
  const assetMeta = tokenList[tokenAddrLc];
18773
18894
  const oracleKey = toOracleKey(assetMeta?.assetGroup ?? null) || toGenericPriceKey(tokenAddrLc, chainId);
@@ -18837,8 +18958,8 @@ var getSiloV2ReservesDataConverter = (lender, chainId, prices, additionalYields,
18837
18958
  silo: self.silo,
18838
18959
  counterpartySilo: other.silo,
18839
18960
  siloConfig: market.siloConfig,
18840
- oracle: self.solvencyOracle,
18841
- irm: self.interestRateModel,
18961
+ oracle: self.solvencyOracle || ZERO_ADDRESS,
18962
+ irm: self.interestRateModel || ZERO_ADDRESS,
18842
18963
  shareTokens: {
18843
18964
  collateral: self.collateralShareToken,
18844
18965
  protected: self.protectedShareToken,
@@ -18861,7 +18982,7 @@ var getSiloV2ReservesDataConverter = (lender, chainId, prices, additionalYields,
18861
18982
  };
18862
18983
 
18863
18984
  // src/lending/public-data/silo-v3/publicCallBuild.ts
18864
- var SILO_V3_CALLS_PER_SIDE = 2;
18985
+ var SILO_V3_CALLS_PER_SIDE = 3;
18865
18986
  var SILO_V3_CALLS_PER_PAIR = SILO_V3_CALLS_PER_SIDE * 2;
18866
18987
  function buildSiloV3LenderReserveCall(_chainId, lender) {
18867
18988
  const market = getSiloV3MarketEntry(_chainId, lender);
@@ -18880,6 +19001,12 @@ function buildSiloV3LenderReserveCall(_chainId, lender) {
18880
19001
  name: "getDebtAssets",
18881
19002
  params: [],
18882
19003
  abi: SiloAbi
19004
+ },
19005
+ {
19006
+ address: half.interestRateModel,
19007
+ name: "getConfig",
19008
+ params: [half.silo],
19009
+ abi: InterestRateModelV2Abi
18883
19010
  }
18884
19011
  );
18885
19012
  }
@@ -18887,7 +19014,7 @@ function buildSiloV3LenderReserveCall(_chainId, lender) {
18887
19014
  }
18888
19015
 
18889
19016
  // src/lending/public-data/silo-v3/publicCallParse.ts
18890
- var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
19017
+ var ZERO_ADDRESS2 = "0x0000000000000000000000000000000000000000";
18891
19018
  var getSiloV3ReservesDataConverter = (lender, chainId, prices, additionalYields, tokenList = {}) => {
18892
19019
  const market = getSiloV3MarketEntry(chainId, lender);
18893
19020
  if (!market) return [() => void 0, 0];
@@ -18899,7 +19026,7 @@ var getSiloV3ReservesDataConverter = (lender, chainId, prices, additionalYields,
18899
19026
  { self: market.silo0, other: market.silo1 },
18900
19027
  { self: market.silo1, other: market.silo0 }
18901
19028
  ];
18902
- const toBigInt6 = (v) => {
19029
+ const toBigInt7 = (v) => {
18903
19030
  if (v === void 0 || v === null || v === "0x") return 0n;
18904
19031
  if (typeof v === "bigint") return v;
18905
19032
  try {
@@ -18911,15 +19038,25 @@ var getSiloV3ReservesDataConverter = (lender, chainId, prices, additionalYields,
18911
19038
  for (let s = 0; s < 2; s++) {
18912
19039
  const { self, other } = sides[s];
18913
19040
  const slot = s * SILO_V3_CALLS_PER_SIDE;
18914
- const totalAssetsRaw = toBigInt6(data[slot]);
18915
- const debtAssetsRaw = toBigInt6(data[slot + 1]);
19041
+ const totalAssetsRaw = toBigInt7(data[slot]);
19042
+ const debtAssetsRaw = toBigInt7(data[slot + 1]);
19043
+ const irmConfigRaw = data[slot + 2];
18916
19044
  const decimals = self.decimals;
18917
19045
  const totalDeposits = Number(formatUnits(totalAssetsRaw, decimals));
18918
19046
  const totalDebt = Number(formatUnits(debtAssetsRaw, decimals));
18919
19047
  const totalLiquidity = totalDeposits - totalDebt;
18920
19048
  const utilization = totalDeposits > 0 ? totalDebt / totalDeposits : 0;
18921
- const depositRatePct = 0;
18922
- const variableBorrowRatePct = 0;
19049
+ let depositRatePct = 0;
19050
+ let variableBorrowRatePct = 0;
19051
+ const irmParams = parseIRMConfig(irmConfigRaw, self);
19052
+ if (irmParams) {
19053
+ try {
19054
+ const rates = calculateSiloRates(utilization, irmParams);
19055
+ variableBorrowRatePct = rates.borrowRate;
19056
+ depositRatePct = rates.depositRate;
19057
+ } catch {
19058
+ }
19059
+ }
18923
19060
  const tokenAddrLc = self.token.toLowerCase();
18924
19061
  const assetMeta = tokenList[tokenAddrLc];
18925
19062
  const oracleKey = toOracleKey(assetMeta?.assetGroup ?? null) || toGenericPriceKey(tokenAddrLc, chainId);
@@ -18981,8 +19118,8 @@ var getSiloV3ReservesDataConverter = (lender, chainId, prices, additionalYields,
18981
19118
  silo: self.silo,
18982
19119
  counterpartySilo: other.silo,
18983
19120
  siloConfig: market.siloConfig,
18984
- oracle: self.solvencyOracle || ZERO_ADDRESS,
18985
- irm: self.interestRateModel || ZERO_ADDRESS,
19121
+ oracle: self.solvencyOracle || ZERO_ADDRESS2,
19122
+ irm: self.interestRateModel || ZERO_ADDRESS2,
18986
19123
  shareTokens: {
18987
19124
  collateral: self.collateralShareToken,
18988
19125
  protected: self.protectedShareToken,
@@ -19145,8 +19282,10 @@ var getAbi = (lender) => {
19145
19282
  if (isMorphoType(lender)) return MorphoLensAbi;
19146
19283
  if (isEulerType(lender)) return vaultLensAbi;
19147
19284
  if (isAaveV4Type(lender)) return [...AaveV4SpokeAbi, ...AaveV4OracleAbi, ...AaveV4HubAbi];
19148
- if (isSiloV2Type(lender)) return [...SiloAbi, ...SiloLensAbi];
19149
- if (isSiloV3Type(lender)) return [...SiloAbi, ...SiloLensAbi];
19285
+ if (isSiloV2Type(lender))
19286
+ return [...SiloAbi, ...SiloLensAbi, ...InterestRateModelV2Abi];
19287
+ if (isSiloV3Type(lender))
19288
+ return [...SiloAbi, ...SiloLensAbi, ...InterestRateModelV2Abi];
19150
19289
  if (isSumerType(lender)) return [...SumerLensAbi, ...SumerComptrollerAbi];
19151
19290
  if (lender === Lender.TAKARA) return [...TakaraMarketStateAbi];
19152
19291
  if (isCompoundV2Type(lender)) return VenusLensAbi;
@@ -19200,7 +19339,6 @@ var getLenderPublicData = async (chainId, lenders, prices, additionalYields, mul
19200
19339
  }
19201
19340
  }
19202
19341
  } catch {
19203
- console.log("error for chain/lender", chainId, lender);
19204
19342
  }
19205
19343
  currentSlice += sliceLength;
19206
19344
  }
@@ -19530,7 +19668,7 @@ function bigintToLtv(v) {
19530
19668
  }
19531
19669
 
19532
19670
  // src/lending/public-data/silo-v3/convertPublic.ts
19533
- var ZERO_ADDRESS2 = "0x0000000000000000000000000000000000000000";
19671
+ var ZERO_ADDRESS3 = "0x0000000000000000000000000000000000000000";
19534
19672
  function convertSiloV3MarketsToPublicResponse(apiItems, chainId, prices, additionalYields = {
19535
19673
  intrinsicYields: {},
19536
19674
  lenderRewards: {},
@@ -19627,8 +19765,8 @@ function convertSiloV3MarketsToPublicResponse(apiItems, chainId, prices, additio
19627
19765
  silo: self.silo.toLowerCase(),
19628
19766
  counterpartySilo: other.silo.toLowerCase(),
19629
19767
  siloConfig: registryEntry.siloConfig.toLowerCase(),
19630
- oracle: (api.solvencyOracleAddress || self.solvencyOracle || ZERO_ADDRESS2).toLowerCase(),
19631
- irm: (api.interestRateModelId || self.interestRateModel || ZERO_ADDRESS2).toLowerCase(),
19768
+ oracle: (api.solvencyOracleAddress || self.solvencyOracle || ZERO_ADDRESS3).toLowerCase(),
19769
+ irm: (api.interestRateModelId || self.interestRateModel || ZERO_ADDRESS3).toLowerCase(),
19632
19770
  shareTokens: {
19633
19771
  collateral: self.collateralShareToken,
19634
19772
  protected: self.protectedShareToken,
@@ -19662,8 +19800,8 @@ function bigintToLtv2(v) {
19662
19800
  return Number.isFinite(n) ? n / 1e18 : 0;
19663
19801
  }
19664
19802
  }
19665
-
19666
- // src/lending/public-data/fetchLenderExt.ts
19803
+ var warn = (...args) => {
19804
+ };
19667
19805
  async function getLenderDataFromApi(lender, chainId, prices, additionalYields, includeUnlisted = false) {
19668
19806
  if (isMorphoType(lender))
19669
19807
  return await fetchMorphoMarkets(chainId, includeUnlisted);
@@ -19709,7 +19847,7 @@ var getLenderPublicDataViaApi = async (chainId, lenders, prices, additionalYield
19709
19847
  const listResult = settled[0];
19710
19848
  const list = listResult.status === "fulfilled" ? listResult.value : {};
19711
19849
  if (listResult.status === "rejected") {
19712
- console.warn(
19850
+ warn(
19713
19851
  `[lending] tokenList fetch failed on chain ${chainId}:`,
19714
19852
  listResult.reason
19715
19853
  );
@@ -19731,13 +19869,13 @@ var getLenderPublicDataViaApi = async (chainId, lenders, prices, additionalYield
19731
19869
  if (converted[lk]) lenderData[lk] = converted[lk];
19732
19870
  }
19733
19871
  } catch (e) {
19734
- console.warn(
19872
+ warn(
19735
19873
  `[lending] Silo v2 API convert failed on chain ${chainId}:`,
19736
19874
  e?.message ?? e
19737
19875
  );
19738
19876
  }
19739
19877
  } else {
19740
- console.warn(
19878
+ warn(
19741
19879
  `[lending] Silo v2 API fetch failed on chain ${chainId}:`,
19742
19880
  siloV2Result.reason?.message ?? siloV2Result.reason
19743
19881
  );
@@ -19759,13 +19897,13 @@ var getLenderPublicDataViaApi = async (chainId, lenders, prices, additionalYield
19759
19897
  if (converted[lk]) lenderData[lk] = converted[lk];
19760
19898
  }
19761
19899
  } catch (e) {
19762
- console.warn(
19900
+ warn(
19763
19901
  `[lending] Silo v3 API convert failed on chain ${chainId}:`,
19764
19902
  e?.message ?? e
19765
19903
  );
19766
19904
  }
19767
19905
  } else {
19768
- console.warn(
19906
+ warn(
19769
19907
  `[lending] Silo v3 API fetch failed on chain ${chainId}:`,
19770
19908
  siloV3Result.reason?.message ?? siloV3Result.reason
19771
19909
  );
@@ -19775,7 +19913,7 @@ var getLenderPublicDataViaApi = async (chainId, lenders, prices, additionalYield
19775
19913
  try {
19776
19914
  const result = settled[i + 3];
19777
19915
  if (result.status === "rejected") {
19778
- console.warn(
19916
+ warn(
19779
19917
  `[lending] API fetch failed for ${otherLenders[i]} on chain ${chainId}:`,
19780
19918
  result.reason?.message ?? result.reason
19781
19919
  );
@@ -19804,11 +19942,12 @@ var getLenderPublicDataViaApi = async (chainId, lenders, prices, additionalYield
19804
19942
  );
19805
19943
  }
19806
19944
  } catch (e) {
19807
- console.log("error fetching from API on", chainId, ":", e);
19808
19945
  }
19809
19946
  }
19810
19947
  return lenderData;
19811
19948
  };
19949
+ var warn2 = (...args) => {
19950
+ };
19812
19951
  function lenderApiOnly(lender, chainId) {
19813
19952
  if (lender === Lender.MORPHO_BLUE) {
19814
19953
  if (chainId === Chain.SONEIUM) return false;
@@ -19842,7 +19981,7 @@ var getLenderPublicDataAll = async (chainId, lenders, prices, additionalYields,
19842
19981
  includeUnlistedMorphoMarkets
19843
19982
  );
19844
19983
  } catch (e) {
19845
- console.warn(
19984
+ warn2(
19846
19985
  `[lending] API fetch failed for chain ${chainId}:`,
19847
19986
  e?.message ?? e
19848
19987
  );
@@ -19865,7 +20004,7 @@ var getLenderPublicDataAll = async (chainId, lenders, prices, additionalYields,
19865
20004
  tokenList
19866
20005
  );
19867
20006
  } catch (e) {
19868
- console.warn(
20007
+ warn2(
19869
20008
  `[lending] on-chain fetch failed for chain ${chainId}:`,
19870
20009
  e?.message ?? e
19871
20010
  );
@@ -20310,6 +20449,55 @@ var buildSiloV2UserCall = (chainId, lender, account) => {
20310
20449
  return calls;
20311
20450
  };
20312
20451
 
20452
+ // src/lending/user-data/silo-v3/userCallBuild.ts
20453
+ var ASSET_TYPE_PROTECTED2 = 0;
20454
+ var ASSET_TYPE_COLLATERAL2 = 1;
20455
+ var SILO_V3_USER_CALLS_PER_SIDE = 5;
20456
+ var SILO_V3_USER_CALLS_PER_PAIR = SILO_V3_USER_CALLS_PER_SIDE * 2;
20457
+ var buildSiloV3UserCall = (chainId, lender, account) => {
20458
+ const market = getSiloV3MarketEntry(chainId, lender);
20459
+ if (!market) return [];
20460
+ const calls = [];
20461
+ for (const half of [market.silo0, market.silo1]) {
20462
+ const oneUnit = BigInt(10) ** BigInt(half.decimals);
20463
+ calls.push(
20464
+ // [0] collateral shares (silo IS the collateral share token)
20465
+ {
20466
+ address: half.silo,
20467
+ name: "balanceOf",
20468
+ params: [account]
20469
+ },
20470
+ // [1] protected shares (separate ERC-20)
20471
+ {
20472
+ address: half.protectedShareToken,
20473
+ name: "balanceOf",
20474
+ params: [account]
20475
+ },
20476
+ // [2] collateral rate: assets per unit of collateral shares
20477
+ {
20478
+ address: half.silo,
20479
+ name: "convertToAssets",
20480
+ params: [oneUnit, ASSET_TYPE_COLLATERAL2],
20481
+ abi: SiloConvertToAssetsTypedAbi
20482
+ },
20483
+ // [3] protected rate: assets per unit of protected shares
20484
+ {
20485
+ address: half.silo,
20486
+ name: "convertToAssets",
20487
+ params: [oneUnit, ASSET_TYPE_PROTECTED2],
20488
+ abi: SiloConvertToAssetsTypedAbi
20489
+ },
20490
+ // [4] debt position (already in assets, includes accrued interest)
20491
+ {
20492
+ address: half.silo,
20493
+ name: "maxRepay",
20494
+ params: [account]
20495
+ }
20496
+ );
20497
+ }
20498
+ return calls;
20499
+ };
20500
+
20313
20501
  // src/lending/user-data/fetch-balances/prepare.ts
20314
20502
  async function buildUserCall(chainId, lender, account, params) {
20315
20503
  if (isAaveV4Type(lender)) return buildAaveV4UserCall(chainId, lender, account);
@@ -20324,7 +20512,11 @@ async function buildUserCall(chainId, lender, account, params) {
20324
20512
  return buildEulerUserCall(chainId, lender, account, params?.subAccountIndexes);
20325
20513
  if (isSiloV2Type(lender))
20326
20514
  return buildSiloV2UserCall(chainId, lender, account);
20327
- return buildCompoundV2UserCall(chainId, lender, account);
20515
+ if (isSiloV3Type(lender))
20516
+ return buildSiloV3UserCall(chainId, lender, account);
20517
+ if (isCompoundV2Type(lender))
20518
+ return buildCompoundV2UserCall(chainId, lender, account);
20519
+ return [];
20328
20520
  }
20329
20521
  function organizeUserQueries(queries) {
20330
20522
  const morphos = queries.filter((q) => isMorphoType(q.lender));
@@ -21864,6 +22056,14 @@ var getSiloV2UserDataConverter = (lender, chainId, account, metaMap) => {
21864
22056
  depositAssetsRaw.toString(),
21865
22057
  metaDecimals
21866
22058
  );
22059
+ const depositsStandardStr = parseRawAmount(
22060
+ collateralAssets.toString(),
22061
+ metaDecimals
22062
+ );
22063
+ const depositsProtectedStr = parseRawAmount(
22064
+ protectedAssets.toString(),
22065
+ metaDecimals
22066
+ );
21867
22067
  const debtStr = parseRawAmount(repayRaw.toString(), metaDecimals);
21868
22068
  const depositsNum = Number(depositsStr);
21869
22069
  const debtNum = Number(debtStr);
@@ -21882,8 +22082,15 @@ var getSiloV2UserDataConverter = (lender, chainId, account, metaMap) => {
21882
22082
  marketUid,
21883
22083
  underlying: self.token.toLowerCase(),
21884
22084
  deposits: depositsStr,
22085
+ depositsStandard: depositsStandardStr,
22086
+ depositsProtected: depositsProtectedStr,
21885
22087
  debt: debtStr,
21886
22088
  debtStable: "0",
22089
+ // Raw share balances (stringified bigints, not decimal-formatted).
22090
+ // Used by the leverage close flow to approve the exact share count
22091
+ // and avoid rounding errors on "withdraw all".
22092
+ depositShares: collateralShares.toString(),
22093
+ protectedDepositShares: protectedShares.toString(),
21887
22094
  depositsUSD,
21888
22095
  debtUSD,
21889
22096
  debtStableUSD: 0,
@@ -21892,6 +22099,7 @@ var getSiloV2UserDataConverter = (lender, chainId, account, metaMap) => {
21892
22099
  debtStableUSDOracle: 0,
21893
22100
  stableBorrowRate: "0",
21894
22101
  collateralEnabled,
22102
+ collateralRate: collateralRate.toString(),
21895
22103
  claimableRewards: 0
21896
22104
  };
21897
22105
  }
@@ -21924,6 +22132,118 @@ function toBigInt5(v) {
21924
22132
  }
21925
22133
  }
21926
22134
 
22135
+ // src/lending/user-data/silo-v3/userCallParse.ts
22136
+ var getSiloV3UserDataConverter = (lender, chainId, account, metaMap) => {
22137
+ const market = getSiloV3MarketEntry(chainId, lender);
22138
+ if (!market) return [() => void 0, 0];
22139
+ return [
22140
+ (data) => {
22141
+ if (!data || data.length !== SILO_V3_USER_CALLS_PER_PAIR)
22142
+ return void 0;
22143
+ const sides = [
22144
+ { self: market.silo0, other: market.silo1 },
22145
+ { self: market.silo1, other: market.silo0 }
22146
+ ];
22147
+ const lendingPositions = {};
22148
+ let addedDeposits = 0;
22149
+ let addedDebt = 0;
22150
+ let hasAnyPosition = false;
22151
+ for (let s = 0; s < 2; s++) {
22152
+ const { self } = sides[s];
22153
+ const slot = s * SILO_V3_USER_CALLS_PER_SIDE;
22154
+ const collateralShares = toBigInt6(data[slot]);
22155
+ const protectedShares = toBigInt6(data[slot + 1]);
22156
+ const collateralRate = toBigInt6(data[slot + 2]);
22157
+ const protectedRate = toBigInt6(data[slot + 3]);
22158
+ const repayRaw = toBigInt6(data[slot + 4]);
22159
+ const decimals = self.decimals;
22160
+ const oneUnit = BigInt(10) ** BigInt(decimals);
22161
+ const collateralAssets = oneUnit > 0n ? collateralShares * collateralRate / oneUnit : 0n;
22162
+ const protectedAssets = oneUnit > 0n ? protectedShares * protectedRate / oneUnit : 0n;
22163
+ const depositAssetsRaw = collateralAssets + protectedAssets;
22164
+ if (depositAssetsRaw === 0n && repayRaw === 0n) continue;
22165
+ hasAnyPosition = true;
22166
+ const marketUid = createMarketUid(chainId, lender, self.silo);
22167
+ const meta = metaMap?.[marketUid];
22168
+ const metaDecimals = meta?.asset?.decimals ?? decimals;
22169
+ const depositsStr = parseRawAmount(
22170
+ depositAssetsRaw.toString(),
22171
+ metaDecimals
22172
+ );
22173
+ const depositsStandardStr = parseRawAmount(
22174
+ collateralAssets.toString(),
22175
+ metaDecimals
22176
+ );
22177
+ const depositsProtectedStr = parseRawAmount(
22178
+ protectedAssets.toString(),
22179
+ metaDecimals
22180
+ );
22181
+ const debtStr = parseRawAmount(repayRaw.toString(), metaDecimals);
22182
+ const depositsNum = Number(depositsStr);
22183
+ const debtNum = Number(debtStr);
22184
+ const displayPrice = meta ? getDisplayPrice(meta) : 0;
22185
+ const oraclePrice = meta ? getOraclePrice(meta) : 0;
22186
+ const priceHist = meta?.price?.priceUsd24h ?? displayPrice;
22187
+ const depositsUSD = depositsNum * displayPrice;
22188
+ const debtUSD = debtNum * displayPrice;
22189
+ const depositsUSDOracle = depositsNum * oraclePrice;
22190
+ const debtUSDOracle = debtNum * oraclePrice;
22191
+ addedDeposits += depositsNum * priceHist;
22192
+ addedDebt += debtNum * priceHist;
22193
+ const selfLt = Number(self.lt) / 1e18;
22194
+ const collateralEnabled = selfLt > 0 && depositAssetsRaw > 0n;
22195
+ lendingPositions[marketUid] = {
22196
+ marketUid,
22197
+ underlying: self.token.toLowerCase(),
22198
+ deposits: depositsStr,
22199
+ depositsStandard: depositsStandardStr,
22200
+ depositsProtected: depositsProtectedStr,
22201
+ debt: debtStr,
22202
+ debtStable: "0",
22203
+ // Raw share balances (stringified bigints, not decimal-formatted).
22204
+ depositShares: collateralShares.toString(),
22205
+ protectedDepositShares: protectedShares.toString(),
22206
+ depositsUSD,
22207
+ debtUSD,
22208
+ debtStableUSD: 0,
22209
+ depositsUSDOracle,
22210
+ debtUSDOracle,
22211
+ debtStableUSDOracle: 0,
22212
+ stableBorrowRate: "0",
22213
+ collateralEnabled,
22214
+ collateralRate: collateralRate.toString(),
22215
+ claimableRewards: 0
22216
+ };
22217
+ }
22218
+ if (!hasAnyPosition) return void 0;
22219
+ const payload = {
22220
+ chainId,
22221
+ account,
22222
+ lendingPositions,
22223
+ rewards: [],
22224
+ userEMode: 0
22225
+ };
22226
+ return createBaseTypeUserState(
22227
+ payload,
22228
+ metaMap,
22229
+ addedDeposits,
22230
+ addedDebt,
22231
+ lender
22232
+ );
22233
+ },
22234
+ SILO_V3_USER_CALLS_PER_PAIR
22235
+ ];
22236
+ };
22237
+ function toBigInt6(v) {
22238
+ if (v === void 0 || v === null || v === "0x") return 0n;
22239
+ if (typeof v === "bigint") return v;
22240
+ try {
22241
+ return BigInt(v);
22242
+ } catch {
22243
+ return 0n;
22244
+ }
22245
+ }
22246
+
21927
22247
  // src/lending/user-data/fetch-balances/parse.ts
21928
22248
  function getUserDataConverter(lender, chainId, account, params, meta) {
21929
22249
  if (isAaveV4Type(lender))
@@ -21960,6 +22280,8 @@ function getUserDataConverter(lender, chainId, account, params, meta) {
21960
22280
  return getEulerUserDataConverter(lender, chainId, account, meta?.[lender], params?.subAccountIndexes);
21961
22281
  if (isSiloV2Type(lender))
21962
22282
  return getSiloV2UserDataConverter(lender, chainId, account, meta?.[lender]);
22283
+ if (isSiloV3Type(lender))
22284
+ return getSiloV3UserDataConverter(lender, chainId, account, meta?.[lender]);
21963
22285
  return getCompoundV2UserDataConverter(
21964
22286
  lender,
21965
22287
  chainId,
@@ -26639,7 +26961,8 @@ var getAbi2 = (lender) => {
26639
26961
  if (isEulerType(lender)) return accountLensAbi;
26640
26962
  if (isCompoundV2Type(lender))
26641
26963
  return [...ComptrollerAbi, ...CompoundV2CollateralToken];
26642
- if (isSiloV2Type(lender)) return [...SiloAbi];
26964
+ if (isSiloV2Type(lender) || isSiloV3Type(lender))
26965
+ return [...SiloAbi];
26643
26966
  return [];
26644
26967
  };
26645
26968
 
@@ -27047,7 +27370,21 @@ function toCompoundV2Shares(entry, amount) {
27047
27370
  return amount;
27048
27371
  }
27049
27372
  }
27050
- function resolveDebitDataKey(chainId, lender, tokenAddress, cToken) {
27373
+ function toSiloShares(entry, amount, chainId, lender, tokenAddress) {
27374
+ const raw = entry.params?.collateralRate;
27375
+ if (!raw || raw === "0x") return amount;
27376
+ try {
27377
+ const rate = BigInt(raw);
27378
+ if (rate === 0n) return amount;
27379
+ const half = getSiloHalfForUnderlying(chainId, lender, tokenAddress);
27380
+ if (!half) return amount;
27381
+ const oneUnit = BigInt(10) ** BigInt(half.decimals);
27382
+ return amount * oneUnit / rate * 1001n / 1000n;
27383
+ } catch {
27384
+ return amount;
27385
+ }
27386
+ }
27387
+ function resolveDebitDataKey(chainId, lender, tokenAddress, cToken, isProtected) {
27051
27388
  if (isCompoundV2Type(lender) || isVenusType(lender)) {
27052
27389
  if (cToken) return cToken.toLowerCase();
27053
27390
  const tokenMap = getCompoundV2CollateralTokens(chainId, lender);
@@ -27071,10 +27408,16 @@ function resolveDebitDataKey(chainId, lender, tokenAddress, cToken) {
27071
27408
  const aToken = getAaveCollateralTokenAddress(chainId, lender, tokenAddress);
27072
27409
  if (aToken) return aToken;
27073
27410
  }
27411
+ if (isSiloV2Type(lender) || isSiloV3Type(lender)) {
27412
+ const half = getSiloHalfForUnderlying(chainId, lender, tokenAddress);
27413
+ if (half) {
27414
+ return isProtected ? half.protectedShareToken.toLowerCase() : half.collateralShareToken.toLowerCase();
27415
+ }
27416
+ }
27074
27417
  return tokenAddress.toLowerCase();
27075
27418
  }
27076
27419
  function needsLenderApproval(params) {
27077
- const { lender, lenderDebitData, tokenAddress, amount, chainId, cToken } = params;
27420
+ const { lender, lenderDebitData, tokenAddress, amount, chainId, cToken, isProtected } = params;
27078
27421
  if (!lenderDebitData) return true;
27079
27422
  if (isAaveV4Type(lender)) {
27080
27423
  const key2 = (params.aaveV4Spoke ?? tokenAddress).toLowerCase();
@@ -27087,13 +27430,17 @@ function needsLenderApproval(params) {
27087
27430
  if (!entry2 || entry2.amount === void 0) return true;
27088
27431
  return entry2.amount === 0n;
27089
27432
  }
27090
- const key = resolveDebitDataKey(chainId, lender, tokenAddress, cToken);
27433
+ const key = resolveDebitDataKey(chainId, lender, tokenAddress, cToken, isProtected);
27091
27434
  const entry = lenderDebitData[key];
27092
27435
  if (!entry || entry.amount === void 0) return true;
27093
27436
  if (isCompoundV2Type(lender) || isVenusType(lender)) {
27094
27437
  const requiredShares = toCompoundV2Shares(entry, amount);
27095
27438
  return entry.amount < requiredShares;
27096
27439
  }
27440
+ if (isSiloV2Type(lender) || isSiloV3Type(lender)) {
27441
+ const requiredShares = toSiloShares(entry, amount, chainId, lender, tokenAddress);
27442
+ return entry.amount < requiredShares;
27443
+ }
27097
27444
  if (isCompoundV3(lender)) {
27098
27445
  return entry.amount === 0n;
27099
27446
  }
@@ -29968,6 +30315,12 @@ var morphoFetcher = {
29968
30315
  var SCALING_DECIMALS_OVERRIDES = {
29969
30316
  [Lender.SUMER]: 18
29970
30317
  };
30318
+ var BASE_ASSET_OVERRIDES = {
30319
+ [Lender.CREAM_FINANCE]: {
30320
+ [Chain.BNB_SMART_CHAIN_MAINNET]: { baseAsset: zeroAddress }
30321
+ // BNB
30322
+ }
30323
+ };
29971
30324
  var CompoundV2OracleAbi = [
29972
30325
  {
29973
30326
  inputs: [{ internalType: "address", name: "cToken", type: "address" }],
@@ -29987,6 +30340,7 @@ function getCompoundV2Calls(chainId) {
29987
30340
  if (!oracleAddress || tokens.length === 0) continue;
29988
30341
  const calls = [];
29989
30342
  const meta = [];
30343
+ const baseAssetOverride = BASE_ASSET_OVERRIDES[lender]?.[chainId]?.baseAsset;
29990
30344
  for (const token of tokens) {
29991
30345
  calls.push({
29992
30346
  address: oracleAddress,
@@ -29996,7 +30350,8 @@ function getCompoundV2Calls(chainId) {
29996
30350
  meta.push({
29997
30351
  cToken: token.cToken,
29998
30352
  underlying: token.underlying,
29999
- lender
30353
+ lender,
30354
+ baseAssetOverride
30000
30355
  });
30001
30356
  }
30002
30357
  if (calls.length > 0) {
@@ -30010,7 +30365,7 @@ function getCompoundV2Calls(chainId) {
30010
30365
  return results;
30011
30366
  }
30012
30367
  function parseCompoundV2Results(data, meta, context) {
30013
- const { tokenList } = context;
30368
+ const { chainId, tokenList, usdPrices } = context;
30014
30369
  const entries = [];
30015
30370
  data.forEach((rawResult, index) => {
30016
30371
  const queryMeta = meta[index];
@@ -30019,14 +30374,25 @@ function parseCompoundV2Results(data, meta, context) {
30019
30374
  const underlyingLc = queryMeta.underlying.toLowerCase();
30020
30375
  const underlyingDecimals = tokenList?.[underlyingLc]?.decimals ?? 18;
30021
30376
  const scalingDecimals = SCALING_DECIMALS_OVERRIDES[queryMeta.lender] ?? 36 - underlyingDecimals;
30022
- const priceUSD = Number(formatUnits(BigInt(rawResult.toString()), scalingDecimals));
30023
- if (isNaN(priceUSD) || priceUSD === 0) return;
30377
+ const rawPriceNum = Number(
30378
+ formatUnits(BigInt(rawResult.toString()), scalingDecimals)
30379
+ );
30380
+ if (isNaN(rawPriceNum) || rawPriceNum === 0) return;
30381
+ let baseAssetUSD = 1;
30382
+ if (queryMeta.baseAssetOverride) {
30383
+ const baseAssetLc = queryMeta.baseAssetOverride.toLowerCase();
30384
+ const baseOracleKey = tokenList?.[baseAssetLc]?.assetGroup ?? `${chainId}-${baseAssetLc}`;
30385
+ baseAssetUSD = usdPrices[baseOracleKey] ?? usdPrices[baseAssetLc] ?? 1;
30386
+ }
30387
+ const priceUSD = rawPriceNum * baseAssetUSD;
30388
+ const isBaseAsset = queryMeta.baseAssetOverride && underlyingLc === queryMeta.baseAssetOverride.toLowerCase();
30024
30389
  entries.push({
30025
30390
  asset: underlyingLc,
30026
- price: priceUSD,
30027
- // For Compound V2, raw price is already USD denominated
30391
+ price: rawPriceNum,
30028
30392
  priceUSD,
30029
- marketUid: createMarketUid(context.chainId, queryMeta.lender, queryMeta.cToken)
30393
+ marketUid: createMarketUid(chainId, queryMeta.lender, queryMeta.cToken),
30394
+ staticBase: isBaseAsset || void 0,
30395
+ baseAsset: queryMeta.baseAssetOverride
30030
30396
  });
30031
30397
  } catch {
30032
30398
  }
@@ -30521,7 +30887,7 @@ var SiloOracleAbi = [
30521
30887
  type: "function"
30522
30888
  }
30523
30889
  ];
30524
- var ZERO_ADDRESS3 = "0x0000000000000000000000000000000000000000";
30890
+ var ZERO_ADDRESS4 = "0x0000000000000000000000000000000000000000";
30525
30891
  function lookupUSD(context, asset) {
30526
30892
  const lc = asset.toLowerCase();
30527
30893
  const groupKey = context.tokenList?.[lc]?.assetGroup ?? `${context.chainId}-${lc}`;
@@ -30533,7 +30899,7 @@ function getSiloV2Calls(chainId) {
30533
30899
  const tokensWithRealOracle = /* @__PURE__ */ new Set();
30534
30900
  for (const market of allMarkets) {
30535
30901
  for (const half of [market.silo0, market.silo1]) {
30536
- if (half.solvencyOracle && half.solvencyOracle !== ZERO_ADDRESS3) {
30902
+ if (half.solvencyOracle && half.solvencyOracle !== ZERO_ADDRESS4) {
30537
30903
  tokensWithRealOracle.add(half.token.toLowerCase());
30538
30904
  }
30539
30905
  }
@@ -30546,7 +30912,7 @@ function getSiloV2Calls(chainId) {
30546
30912
  const lenderKey = siloV2LenderKey(market.siloConfig);
30547
30913
  const halves = [market.silo0, market.silo1];
30548
30914
  const isStatic = halves.map(
30549
- (h) => !h.solvencyOracle || h.solvencyOracle === ZERO_ADDRESS3
30915
+ (h) => !h.solvencyOracle || h.solvencyOracle === ZERO_ADDRESS4
30550
30916
  );
30551
30917
  if (isStatic[0] && isStatic[1]) {
30552
30918
  const t0 = halves[0].token.toLowerCase();
@@ -30566,7 +30932,7 @@ function getSiloV2Calls(chainId) {
30566
30932
  decimals: half.decimals,
30567
30933
  silo: half.silo.toLowerCase(),
30568
30934
  lenderKey,
30569
- oracle: ZERO_ADDRESS3,
30935
+ oracle: ZERO_ADDRESS4,
30570
30936
  partnerToken: partnerLc,
30571
30937
  isStatic: true
30572
30938
  });
@@ -30692,7 +31058,7 @@ var SiloOracleAbi2 = [
30692
31058
  type: "function"
30693
31059
  }
30694
31060
  ];
30695
- var ZERO_ADDRESS4 = "0x0000000000000000000000000000000000000000";
31061
+ var ZERO_ADDRESS5 = "0x0000000000000000000000000000000000000000";
30696
31062
  function lookupUSD2(context, asset) {
30697
31063
  const lc = asset.toLowerCase();
30698
31064
  const groupKey = context.tokenList?.[lc]?.assetGroup ?? `${context.chainId}-${lc}`;
@@ -30704,7 +31070,7 @@ function getSiloV3Calls(chainId) {
30704
31070
  const tokensWithRealOracle = /* @__PURE__ */ new Set();
30705
31071
  for (const market of allMarkets) {
30706
31072
  for (const half of [market.silo0, market.silo1]) {
30707
- if (half.solvencyOracle && half.solvencyOracle !== ZERO_ADDRESS4) {
31073
+ if (half.solvencyOracle && half.solvencyOracle !== ZERO_ADDRESS5) {
30708
31074
  tokensWithRealOracle.add(half.token.toLowerCase());
30709
31075
  }
30710
31076
  }
@@ -30717,7 +31083,7 @@ function getSiloV3Calls(chainId) {
30717
31083
  const lenderKey = siloV3LenderKey(market.siloConfig);
30718
31084
  const halves = [market.silo0, market.silo1];
30719
31085
  const isStatic = halves.map(
30720
- (h) => !h.solvencyOracle || h.solvencyOracle === ZERO_ADDRESS4
31086
+ (h) => !h.solvencyOracle || h.solvencyOracle === ZERO_ADDRESS5
30721
31087
  );
30722
31088
  if (isStatic[0] && isStatic[1]) {
30723
31089
  const t0 = halves[0].token.toLowerCase();
@@ -30737,7 +31103,7 @@ function getSiloV3Calls(chainId) {
30737
31103
  decimals: half.decimals,
30738
31104
  silo: half.silo.toLowerCase(),
30739
31105
  lenderKey,
30740
- oracle: ZERO_ADDRESS4,
31106
+ oracle: ZERO_ADDRESS5,
30741
31107
  partnerToken: partnerLc,
30742
31108
  isStatic: true
30743
31109
  });
@@ -30913,7 +31279,7 @@ function lookupUSD3(context, asset) {
30913
31279
  return context.usdPrices[groupKey] ?? context.usdPrices[lc] ?? 0;
30914
31280
  }
30915
31281
  function parseSiloV2GraphQLResults(items, context) {
30916
- const ZERO_ADDRESS5 = "0x0000000000000000000000000000000000000000";
31282
+ const ZERO_ADDRESS6 = "0x0000000000000000000000000000000000000000";
30917
31283
  const out = [];
30918
31284
  const seen = /* @__PURE__ */ new Set();
30919
31285
  for (const item of items) {
@@ -30936,8 +31302,8 @@ function parseSiloV2GraphQLResults(items, context) {
30936
31302
  const partnerTokenLc = other.token.toLowerCase();
30937
31303
  const dedupKey = `${lenderKey}:${tokenLc}`;
30938
31304
  if (seen.has(dedupKey)) continue;
30939
- const oracleAddr = (side.solvencyOracleAddress ?? side.solvencyOracle?.id ?? self.solvencyOracle ?? ZERO_ADDRESS5).toLowerCase();
30940
- const isStatic = !oracleAddr || oracleAddr === ZERO_ADDRESS5;
31305
+ const oracleAddr = (side.solvencyOracleAddress ?? side.solvencyOracle?.id ?? self.solvencyOracle ?? ZERO_ADDRESS6).toLowerCase();
31306
+ const isStatic = !oracleAddr || oracleAddr === ZERO_ADDRESS6;
30941
31307
  const siloAddrLc = self.silo.toLowerCase();
30942
31308
  try {
30943
31309
  let priceUSD = 0;
@@ -31057,7 +31423,7 @@ function lookupUSD4(context, asset) {
31057
31423
  return context.usdPrices[groupKey] ?? context.usdPrices[lc] ?? 0;
31058
31424
  }
31059
31425
  function parseSiloV3GraphQLResults(items, context) {
31060
- const ZERO_ADDRESS5 = "0x0000000000000000000000000000000000000000";
31426
+ const ZERO_ADDRESS6 = "0x0000000000000000000000000000000000000000";
31061
31427
  const out = [];
31062
31428
  const seen = /* @__PURE__ */ new Set();
31063
31429
  for (const item of items) {
@@ -31080,8 +31446,8 @@ function parseSiloV3GraphQLResults(items, context) {
31080
31446
  const partnerTokenLc = other.token.toLowerCase();
31081
31447
  const dedupKey = `${lenderKey}:${tokenLc}`;
31082
31448
  if (seen.has(dedupKey)) continue;
31083
- const oracleAddr = (side.solvencyOracleAddress ?? side.solvencyOracle?.id ?? self.solvencyOracle ?? ZERO_ADDRESS5).toLowerCase();
31084
- const isStatic = !oracleAddr || oracleAddr === ZERO_ADDRESS5;
31449
+ const oracleAddr = (side.solvencyOracleAddress ?? side.solvencyOracle?.id ?? self.solvencyOracle ?? ZERO_ADDRESS6).toLowerCase();
31450
+ const isStatic = !oracleAddr || oracleAddr === ZERO_ADDRESS6;
31085
31451
  const siloAddrLc = self.silo.toLowerCase();
31086
31452
  try {
31087
31453
  let priceUSD = 0;
@@ -32158,16 +32524,48 @@ function getSupportedAssets(lenderMeta, targetMode) {
32158
32524
  }
32159
32525
  return { collateral, borrow };
32160
32526
  }
32527
+ function isCollateralBlockedInMode(config) {
32528
+ if (!config) return true;
32529
+ if (config.collateralDisabled) return true;
32530
+ if ((config.borrowCollateralFactor ?? 0) === 0) return true;
32531
+ return false;
32532
+ }
32161
32533
  function canSwitchToEMode(positions, lenderMeta, targetMode, healthFactor) {
32162
- if (healthFactor !== null && healthFactor <= 1) return false;
32534
+ if (healthFactor !== null && healthFactor <= 1) {
32535
+ return { canSwitch: false, blockReason: "health_factor", blockingAssets: [] };
32536
+ }
32537
+ const collateralBlocking = [];
32538
+ const debtBlocking = [];
32163
32539
  for (let i = 0; i < positions.length; i++) {
32164
32540
  const pos = positions[i];
32165
- const totalDebt = pos.debtUSD + pos.debtStableUSD;
32166
- if (totalDebt <= 0) continue;
32167
32541
  const config = lenderMeta[pos.marketUid]?.configs?.[targetMode];
32168
- if (!config || config.debtDisabled) return false;
32542
+ if (pos.collateralEnabled && pos.depositsUSD > 0) {
32543
+ if (isCollateralBlockedInMode(config)) {
32544
+ collateralBlocking.push(pos.marketUid);
32545
+ }
32546
+ }
32547
+ const totalDebt = pos.debtUSD + pos.debtStableUSD;
32548
+ if (totalDebt > 0) {
32549
+ if (!config || config.debtDisabled) {
32550
+ debtBlocking.push(pos.marketUid);
32551
+ }
32552
+ }
32169
32553
  }
32170
- return true;
32554
+ if (collateralBlocking.length > 0) {
32555
+ return {
32556
+ canSwitch: false,
32557
+ blockReason: "collateral_not_supported",
32558
+ blockingAssets: [...collateralBlocking, ...debtBlocking]
32559
+ };
32560
+ }
32561
+ if (debtBlocking.length > 0) {
32562
+ return {
32563
+ canSwitch: false,
32564
+ blockReason: "debt_not_supported",
32565
+ blockingAssets: debtBlocking
32566
+ };
32567
+ }
32568
+ return { canSwitch: true };
32171
32569
  }
32172
32570
  function computeEModeAnalysis(subAccount, lenderMeta, eModes) {
32173
32571
  const { positions, balanceData: balanceData2, userConfig } = subAccount;
@@ -32183,18 +32581,22 @@ function computeEModeAnalysis(subAccount, lenderMeta, eModes) {
32183
32581
  targetMode
32184
32582
  );
32185
32583
  const supportedAssets = getSupportedAssets(lenderMeta, targetMode);
32186
- const canSwitch = canSwitchToEMode(
32584
+ const { canSwitch, blockReason, blockingAssets } = canSwitchToEMode(
32187
32585
  positions,
32188
32586
  lenderMeta,
32189
32587
  targetMode,
32190
32588
  healthFactor
32191
32589
  );
32192
32590
  return {
32591
+ modeId: eMode.category,
32193
32592
  category: eMode.category,
32593
+ // backward-compat alias
32194
32594
  label: eMode.label,
32195
32595
  healthFactor,
32196
32596
  supportedAssets,
32197
- canSwitch
32597
+ canSwitch,
32598
+ ...blockReason ? { blockReason } : {},
32599
+ ...blockingAssets ? { blockingAssets } : {}
32198
32600
  };
32199
32601
  });
32200
32602
  }