@1delta/margin-fetcher 0.0.247 → 0.0.250

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 (34) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +531 -71
  4. package/dist/index.js.map +1 -1
  5. package/dist/lending/public-data/aave-v3-type/publicCallBuild.d.ts.map +1 -1
  6. package/dist/lending/public-data/aave-v3-type/publicCallParse.d.ts.map +1 -1
  7. package/dist/lending/user-data/aave-v4-type/createAaveV4UserState.d.ts.map +1 -1
  8. package/dist/lending/user-data/gearbox/userCallParse.d.ts.map +1 -1
  9. package/dist/types/lenderTypes.d.ts +16 -1
  10. package/dist/types/lenderTypes.d.ts.map +1 -1
  11. package/dist/utils/index.d.ts.map +1 -1
  12. package/dist/vaults/fluid/types.d.ts +9 -0
  13. package/dist/vaults/fluid/types.d.ts.map +1 -1
  14. package/dist/vaults/gearbox/types.d.ts +9 -0
  15. package/dist/vaults/gearbox/types.d.ts.map +1 -1
  16. package/dist/vaults/index.d.ts +2 -0
  17. package/dist/vaults/index.d.ts.map +1 -1
  18. package/dist/vaults/morpho/fetchFromApi.d.ts +14 -0
  19. package/dist/vaults/morpho/fetchFromApi.d.ts.map +1 -0
  20. package/dist/vaults/morpho/fetchFromSubgraph.d.ts +12 -0
  21. package/dist/vaults/morpho/fetchFromSubgraph.d.ts.map +1 -0
  22. package/dist/vaults/morpho/fetchPublic.d.ts +24 -0
  23. package/dist/vaults/morpho/fetchPublic.d.ts.map +1 -0
  24. package/dist/vaults/morpho/index.d.ts +5 -0
  25. package/dist/vaults/morpho/index.d.ts.map +1 -0
  26. package/dist/vaults/morpho/types.d.ts +82 -0
  27. package/dist/vaults/morpho/types.d.ts.map +1 -0
  28. package/dist/vaults/silo/fetchPublic.d.ts +22 -0
  29. package/dist/vaults/silo/fetchPublic.d.ts.map +1 -0
  30. package/dist/vaults/silo/index.d.ts +3 -0
  31. package/dist/vaults/silo/index.d.ts.map +1 -0
  32. package/dist/vaults/silo/types.d.ts +84 -0
  33. package/dist/vaults/silo/types.d.ts.map +1 -0
  34. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -7572,6 +7572,12 @@ var ENABLED_COMPOUNDS = [
7572
7572
  var DISABLED_COMPOUNDS = {
7573
7573
  [Chain.ETHEREUM_MAINNET]: [Lender.CREAM_FINANCE]
7574
7574
  };
7575
+ var isExcludedLender = (lender) => {
7576
+ if (lender === Lender.PLOUTOS) return true;
7577
+ if (lender?.startsWith("ZEROLEND")) return true;
7578
+ if (lender?.startsWith("TAKO_TAKO")) return true;
7579
+ return false;
7580
+ };
7575
7581
  var ENABLED_EULER_V2_CHAINS = [
7576
7582
  Chain.ETHEREUM_MAINNET,
7577
7583
  Chain.BNB_SMART_CHAIN_MAINNET,
@@ -7633,7 +7639,7 @@ var getLendersForChain = (c) => {
7633
7639
  if (gearboxResolvers()?.chains?.[c]?.marketConfigurators) {
7634
7640
  lenders.push(Lender.GEARBOX_V3);
7635
7641
  }
7636
- return lenders;
7642
+ return lenders.filter((l) => !isExcludedLender(l));
7637
7643
  };
7638
7644
  var filterLendersByProtocol = (allLenders, protocolList) => {
7639
7645
  if (!protocolList || protocolList.length === 0) {
@@ -7714,6 +7720,25 @@ var buildAaveV2StyleLenderReserveCall = (chainId, lender) => {
7714
7720
  ];
7715
7721
  }
7716
7722
  };
7723
+ var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
7724
+ var ERC20_BALANCE_OF_ABI = [
7725
+ {
7726
+ inputs: [{ name: "account", type: "address" }],
7727
+ name: "balanceOf",
7728
+ outputs: [{ name: "", type: "uint256" }],
7729
+ stateMutability: "view",
7730
+ type: "function"
7731
+ }
7732
+ ];
7733
+ function balanceOfCall(underlying, aToken) {
7734
+ return {
7735
+ // @ts-ignore — per-call abi override picked up by fetchLender.ts
7736
+ abi: ERC20_BALANCE_OF_ABI,
7737
+ address: underlying,
7738
+ name: "balanceOf",
7739
+ params: [aToken ?? ZERO_ADDRESS]
7740
+ };
7741
+ }
7717
7742
  function range(n) {
7718
7743
  return Array.from({ length: n + 1 }, (_3, i) => i);
7719
7744
  }
@@ -7733,7 +7758,7 @@ var AAVE_V3_EMODES = (chain, lender) => {
7733
7758
  }
7734
7759
  return [0, 1, 2, 3, 4, 5, 6];
7735
7760
  };
7736
- function yldrBaseline(assetsToQuery, providerAddress) {
7761
+ function yldrBaseline(assetsToQuery, providerAddress, aaveTokenMap) {
7737
7762
  return assetsToQuery.flatMap((tk) => [
7738
7763
  {
7739
7764
  address: providerAddress,
@@ -7744,10 +7769,11 @@ function yldrBaseline(assetsToQuery, providerAddress) {
7744
7769
  address: providerAddress,
7745
7770
  name: "getReserveConfigurationData",
7746
7771
  params: [tk]
7747
- }
7772
+ },
7773
+ balanceOfCall(tk, aaveTokenMap?.[tk]?.aToken)
7748
7774
  ]);
7749
7775
  }
7750
- function aaveV3baseline(assetsToQuery, providerAddress, poolAddress, legacy = false) {
7776
+ function aaveV3baseline(assetsToQuery, providerAddress, poolAddress, aaveTokenMap, legacy = false) {
7751
7777
  const callDecimals = {
7752
7778
  address: providerAddress,
7753
7779
  name: "getDebtCeilingDecimals",
@@ -7790,7 +7816,8 @@ function aaveV3baseline(assetsToQuery, providerAddress, poolAddress, legacy = fa
7790
7816
  name: "getReserveEModeCategory",
7791
7817
  params: [tk]
7792
7818
  }
7793
- ] : []
7819
+ ] : [],
7820
+ balanceOfCall(tk, aaveTokenMap?.[tk]?.aToken)
7794
7821
  ]);
7795
7822
  return {
7796
7823
  callsBase,
@@ -7802,6 +7829,7 @@ var buildAaveV3StyleLenderReserveCall = (chainId, lender) => {
7802
7829
  const providerAddress = getAaveTypePoolDataProviderAddress(chainId, lender);
7803
7830
  const assetsToQuery = getAaveAssets(chainId, lender);
7804
7831
  const poolAddress = getAaveTypePoolAddress(chainId, lender);
7832
+ const aaveTokenMap = getAaveStyleProtocolTokenMap(chainId, lender);
7805
7833
  if (isAaveV32Type(lender)) {
7806
7834
  const getEModeCategoryData = AAVE_V3_EMODES(
7807
7835
  chainId,
@@ -7828,7 +7856,8 @@ var buildAaveV3StyleLenderReserveCall = (chainId, lender) => {
7828
7856
  const { callDecimals, callReservesList, callsBase } = aaveV3baseline(
7829
7857
  assetsToQuery,
7830
7858
  providerAddress,
7831
- poolAddress
7859
+ poolAddress,
7860
+ aaveTokenMap
7832
7861
  );
7833
7862
  const calls = [
7834
7863
  ...callsBase,
@@ -7840,7 +7869,7 @@ var buildAaveV3StyleLenderReserveCall = (chainId, lender) => {
7840
7869
  }
7841
7870
  switch (lender) {
7842
7871
  case Lender.YLDR: {
7843
- const calls = yldrBaseline(assetsToQuery, providerAddress);
7872
+ const calls = yldrBaseline(assetsToQuery, providerAddress, aaveTokenMap);
7844
7873
  return calls;
7845
7874
  }
7846
7875
  default: {
@@ -7856,6 +7885,7 @@ var buildAaveV3StyleLenderReserveCall = (chainId, lender) => {
7856
7885
  assetsToQuery,
7857
7886
  providerAddress,
7858
7887
  poolAddress,
7888
+ aaveTokenMap,
7859
7889
  true
7860
7890
  );
7861
7891
  const calls = [...callsBase, ...getEModeCategoryData, callDecimals];
@@ -8367,7 +8397,8 @@ var getAaveV3ReservesDataConverter = (lender, chainId, prices, additionalYields,
8367
8397
  default: {
8368
8398
  const assetsToQuery = getAaveAssets(chainId, lender);
8369
8399
  const allModes = AAVE_V3_EMODES(chainId, lender);
8370
- const expectedNumberOfCalls = assetsToQuery.length * 6 + allModes.length + 1;
8400
+ const stride = 7;
8401
+ const expectedNumberOfCalls = assetsToQuery.length * stride + allModes.length + 1;
8371
8402
  const aaveTokenMap = getAaveStyleProtocolTokenMap(chainId, lender);
8372
8403
  return [
8373
8404
  (data) => {
@@ -8375,8 +8406,8 @@ var getAaveV3ReservesDataConverter = (lender, chainId, prices, additionalYields,
8375
8406
  return void 0;
8376
8407
  }
8377
8408
  const emodeDataResult = data.slice(
8378
- assetsToQuery.length * 6,
8379
- assetsToQuery.length * 6 + allModes.length
8409
+ assetsToQuery.length * stride,
8410
+ assetsToQuery.length * stride + allModes.length
8380
8411
  );
8381
8412
  const resultReserves = {};
8382
8413
  const decimalsCeiling = data[expectedNumberOfCalls - 1];
@@ -8395,11 +8426,12 @@ var getAaveV3ReservesDataConverter = (lender, chainId, prices, additionalYields,
8395
8426
  });
8396
8427
  for (let i = 0; i < assetsToQuery.length; i++) {
8397
8428
  const asset = assetsToQuery[i];
8398
- const reserveData = data[i * 6];
8399
- const configData = data[i * 6 + 1];
8400
- const reserveCaps = data[i * 6 + 3];
8401
- const debtCeiling = data[i * 6 + 4];
8402
- const reserveEMode = data[i * 6 + 5];
8429
+ const reserveData = data[i * stride];
8430
+ const configData = data[i * stride + 1];
8431
+ const reserveCaps = data[i * stride + 3];
8432
+ const debtCeiling = data[i * stride + 4];
8433
+ const reserveEMode = data[i * stride + 5];
8434
+ const aTokenBalanceRaw = data[i * stride + 6];
8403
8435
  const assetMeta = tokenList[asset];
8404
8436
  const decimals = assetMeta?.decimals ?? 18;
8405
8437
  const totalDeposits = parseRawAmount(
@@ -8414,7 +8446,12 @@ var getAaveV3ReservesDataConverter = (lender, chainId, prices, additionalYields,
8414
8446
  reserveData?.[4 /* totalVariableDebt */]?.toString(),
8415
8447
  decimals
8416
8448
  );
8417
- const liquidity = Number(totalDeposits) - Number(totalDebt) - Number(totalDebtStable);
8449
+ const aTokenHasAddress = !!aaveTokenMap[asset]?.aToken;
8450
+ const availableLiquidityRaw = aTokenHasAddress && aTokenBalanceRaw !== "0x" ? aTokenBalanceRaw : void 0;
8451
+ const liquidity = availableLiquidityRaw !== void 0 ? Number(parseRawAmount(availableLiquidityRaw?.toString(), decimals)) : Math.max(
8452
+ 0,
8453
+ Number(totalDeposits) - Number(totalDebt) - Number(totalDebtStable)
8454
+ );
8418
8455
  const price = prices[toOracleKey(assetMeta?.assetGroup) ?? toGenericPriceKey(asset, chainId)] ?? 0;
8419
8456
  const usageAsCollateralEnabled = configData?.[5 /* usageAsCollateralEnabled */];
8420
8457
  const borrowingEnabled = configData?.[6 /* borrowingEnabled */];
@@ -8615,7 +8652,8 @@ function isReserveEnabledOnBitmap(bitmap, reserveIndex) {
8615
8652
  function parseYLDRCall(chainId, lender, additionalYields, prices, tokenList) {
8616
8653
  const assetsToQuery = getAaveAssets(chainId, lender);
8617
8654
  const aaveTokenMap = getAaveStyleProtocolTokenMap(chainId, lender);
8618
- const expectedNumberOfCalls = assetsToQuery.length * 2;
8655
+ const stride = 3;
8656
+ const expectedNumberOfCalls = assetsToQuery.length * stride;
8619
8657
  return [
8620
8658
  (data) => {
8621
8659
  if (data.length !== expectedNumberOfCalls) {
@@ -8624,8 +8662,9 @@ function parseYLDRCall(chainId, lender, additionalYields, prices, tokenList) {
8624
8662
  const resultReserves = {};
8625
8663
  for (let i = 0; i < assetsToQuery.length; i++) {
8626
8664
  const asset = assetsToQuery[i];
8627
- const reserveData = data[i * 2];
8628
- const configData = data[i * 2 + 1];
8665
+ const reserveData = data[i * stride];
8666
+ const configData = data[i * stride + 1];
8667
+ const aTokenBalanceRaw = data[i * stride + 2];
8629
8668
  const assetMeta = tokenList[asset];
8630
8669
  const decimals = assetMeta?.decimals ?? 18;
8631
8670
  const totalVariableDebt = parseRawAmount(
@@ -8636,7 +8675,9 @@ function parseYLDRCall(chainId, lender, additionalYields, prices, tokenList) {
8636
8675
  reserveData?.[1 /* totalYToken */]?.toString(),
8637
8676
  decimals
8638
8677
  );
8639
- const liquidity = Number(totalAToken) - Number(totalVariableDebt);
8678
+ const aTokenHasAddress = !!aaveTokenMap[asset]?.aToken;
8679
+ const availableLiquidityRaw = aTokenHasAddress && aTokenBalanceRaw !== "0x" ? aTokenBalanceRaw : void 0;
8680
+ const liquidity = availableLiquidityRaw !== void 0 ? Number(parseRawAmount(availableLiquidityRaw?.toString(), decimals)) : Math.max(0, Number(totalAToken) - Number(totalVariableDebt));
8640
8681
  const oracleKey = toOracleKey(assetMeta?.assetGroup) ?? toGenericPriceKey(asset, chainId);
8641
8682
  const price = prices[oracleKey] ?? 0;
8642
8683
  const totalDepositsUSD = Number(totalAToken) * price;
@@ -8729,15 +8770,16 @@ function parseAave32(chainId, lender, prices, additionalYields, tokenList) {
8729
8770
  const assetsToQuery = getAaveAssets(chainId, lender);
8730
8771
  const aaveTokenMap = getAaveStyleProtocolTokenMap(chainId, lender);
8731
8772
  const allModes = AAVE_V3_EMODES(chainId, lender);
8732
- const expectedNumberOfCalls = assetsToQuery.length * 5 + allModes.length * 3 + 2;
8773
+ const stride = 6;
8774
+ const expectedNumberOfCalls = assetsToQuery.length * stride + allModes.length * 3 + 2;
8733
8775
  return [
8734
8776
  (data) => {
8735
8777
  if (data.length !== expectedNumberOfCalls) {
8736
8778
  return void 0;
8737
8779
  }
8738
8780
  const emodeDataResult = data.slice(
8739
- assetsToQuery.length * 5,
8740
- assetsToQuery.length * 5 + allModes.length * 3
8781
+ assetsToQuery.length * stride,
8782
+ assetsToQuery.length * stride + allModes.length * 3
8741
8783
  );
8742
8784
  const resultReserves = {};
8743
8785
  const reservesList = data[expectedNumberOfCalls - 2];
@@ -8764,10 +8806,11 @@ function parseAave32(chainId, lender, prices, additionalYields, tokenList) {
8764
8806
  );
8765
8807
  for (let i = 0; i < assetsToQuery.length; i++) {
8766
8808
  const asset = assetsToQuery[i];
8767
- const reserveData = data[i * 5];
8768
- const configData = data[i * 5 + 1];
8769
- const reserveCaps = data[i * 5 + 3];
8770
- const debtCeiling = data[i * 5 + 4];
8809
+ const reserveData = data[i * stride];
8810
+ const configData = data[i * stride + 1];
8811
+ const reserveCaps = data[i * stride + 3];
8812
+ const debtCeiling = data[i * stride + 4];
8813
+ const aTokenBalanceRaw = data[i * stride + 5];
8771
8814
  const assetMeta = tokenList[asset];
8772
8815
  const decimals = assetMeta?.decimals ?? 18;
8773
8816
  const totalDeposits = parseRawAmount(
@@ -8782,7 +8825,12 @@ function parseAave32(chainId, lender, prices, additionalYields, tokenList) {
8782
8825
  reserveData?.[4 /* totalVariableDebt */]?.toString(),
8783
8826
  decimals
8784
8827
  );
8785
- const liquidity = Number(totalDeposits) - Number(totalDebt) - Number(totalDebtStable);
8828
+ const aTokenHasAddress = !!aaveTokenMap[asset]?.aToken;
8829
+ const availableLiquidityRaw = aTokenHasAddress && aTokenBalanceRaw !== "0x" ? aTokenBalanceRaw : void 0;
8830
+ const liquidity = availableLiquidityRaw !== void 0 ? Number(parseRawAmount(availableLiquidityRaw?.toString(), decimals)) : Math.max(
8831
+ 0,
8832
+ Number(totalDeposits) - Number(totalDebt) - Number(totalDebtStable)
8833
+ );
8786
8834
  const price = prices[toOracleKey(assetMeta?.assetGroup) ?? toGenericPriceKey(asset, chainId)] ?? 0;
8787
8835
  const marketUid = createMarketUid(chainId, lender, asset);
8788
8836
  resultReserves[marketUid] = {
@@ -18879,7 +18927,7 @@ function calculateSiloRates(utilization, params) {
18879
18927
  }
18880
18928
 
18881
18929
  // src/lending/public-data/silo-v2/publicCallParse.ts
18882
- var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
18930
+ var ZERO_ADDRESS2 = "0x0000000000000000000000000000000000000000";
18883
18931
  var getSiloV2ReservesDataConverter = (lender, chainId, prices, additionalYields, tokenList = {}) => {
18884
18932
  const market = getSiloV2MarketEntry(chainId, lender);
18885
18933
  if (!market) return [() => void 0, 0];
@@ -18991,8 +19039,8 @@ var getSiloV2ReservesDataConverter = (lender, chainId, prices, additionalYields,
18991
19039
  silo: self.silo,
18992
19040
  counterpartySilo: other.silo,
18993
19041
  siloConfig: market.siloConfig,
18994
- oracle: self.solvencyOracle || ZERO_ADDRESS,
18995
- irm: self.interestRateModel || ZERO_ADDRESS,
19042
+ oracle: self.solvencyOracle || ZERO_ADDRESS2,
19043
+ irm: self.interestRateModel || ZERO_ADDRESS2,
18996
19044
  shareTokens: {
18997
19045
  collateral: self.collateralShareToken,
18998
19046
  protected: self.protectedShareToken,
@@ -19047,7 +19095,7 @@ function buildSiloV3LenderReserveCall(_chainId, lender) {
19047
19095
  }
19048
19096
 
19049
19097
  // src/lending/public-data/silo-v3/publicCallParse.ts
19050
- var ZERO_ADDRESS2 = "0x0000000000000000000000000000000000000000";
19098
+ var ZERO_ADDRESS3 = "0x0000000000000000000000000000000000000000";
19051
19099
  var getSiloV3ReservesDataConverter = (lender, chainId, prices, additionalYields, tokenList = {}) => {
19052
19100
  const market = getSiloV3MarketEntry(chainId, lender);
19053
19101
  if (!market) return [() => void 0, 0];
@@ -19151,8 +19199,8 @@ var getSiloV3ReservesDataConverter = (lender, chainId, prices, additionalYields,
19151
19199
  silo: self.silo,
19152
19200
  counterpartySilo: other.silo,
19153
19201
  siloConfig: market.siloConfig,
19154
- oracle: self.solvencyOracle || ZERO_ADDRESS2,
19155
- irm: self.interestRateModel || ZERO_ADDRESS2,
19202
+ oracle: self.solvencyOracle || ZERO_ADDRESS3,
19203
+ irm: self.interestRateModel || ZERO_ADDRESS3,
19156
19204
  shareTokens: {
19157
19205
  collateral: self.collateralShareToken,
19158
19206
  protected: self.protectedShareToken,
@@ -20162,7 +20210,7 @@ function bigintToLtv(v) {
20162
20210
  }
20163
20211
 
20164
20212
  // src/lending/public-data/silo-v3/convertPublic.ts
20165
- var ZERO_ADDRESS3 = "0x0000000000000000000000000000000000000000";
20213
+ var ZERO_ADDRESS4 = "0x0000000000000000000000000000000000000000";
20166
20214
  function convertSiloV3MarketsToPublicResponse(apiItems, chainId, prices, additionalYields = {
20167
20215
  intrinsicYields: {},
20168
20216
  lenderRewards: {},
@@ -20259,8 +20307,8 @@ function convertSiloV3MarketsToPublicResponse(apiItems, chainId, prices, additio
20259
20307
  silo: self.silo.toLowerCase(),
20260
20308
  counterpartySilo: other.silo.toLowerCase(),
20261
20309
  siloConfig: registryEntry.siloConfig.toLowerCase(),
20262
- oracle: (api.solvencyOracleAddress || self.solvencyOracle || ZERO_ADDRESS3).toLowerCase(),
20263
- irm: (api.interestRateModelId || self.interestRateModel || ZERO_ADDRESS3).toLowerCase(),
20310
+ oracle: (api.solvencyOracleAddress || self.solvencyOracle || ZERO_ADDRESS4).toLowerCase(),
20311
+ irm: (api.interestRateModelId || self.interestRateModel || ZERO_ADDRESS4).toLowerCase(),
20264
20312
  shareTokens: {
20265
20313
  collateral: self.collateralShareToken,
20266
20314
  protected: self.protectedShareToken,
@@ -21071,11 +21119,14 @@ async function buildUserCall(chainId, lender, account, params) {
21071
21119
  }
21072
21120
  function organizeUserQueries(queries) {
21073
21121
  const morphos = queries.filter((q) => isMorphoType(q.lender));
21074
- if (morphos.length === 0) return queries;
21075
- const nonMorphos = queries.filter((q) => !isMorphoType(q.lender));
21122
+ const gearbox = queries.filter((q) => isGearboxV3(q.lender));
21123
+ if (morphos.length === 0 && gearbox.length === 0) return queries;
21124
+ const others = queries.filter(
21125
+ (q) => !isMorphoType(q.lender) && !isGearboxV3(q.lender)
21126
+ );
21076
21127
  const morphoBlue = morphos.filter((q) => q.lender.startsWith("MORPHO_BLUE"));
21077
21128
  const moolah = morphos.filter((q) => q.lender.startsWith("LISTA_DAO"));
21078
- const result = [...nonMorphos];
21129
+ const result = [...others];
21079
21130
  if (morphoBlue.length > 0) {
21080
21131
  result.push({
21081
21132
  lender: Lender.MORPHO_BLUE,
@@ -21092,6 +21143,14 @@ function organizeUserQueries(queries) {
21092
21143
  assets: void 0
21093
21144
  });
21094
21145
  }
21146
+ if (gearbox.length > 0) {
21147
+ result.push({
21148
+ lender: Lender.GEARBOX_V3,
21149
+ account: gearbox[0].account,
21150
+ params: gearbox.map((p) => p.lender),
21151
+ assets: void 0
21152
+ });
21153
+ }
21095
21154
  return result;
21096
21155
  }
21097
21156
 
@@ -22257,7 +22316,7 @@ function createAaveV4UserState(payload, lenderData, totalDeposits24h = 0, totalD
22257
22316
  }
22258
22317
  let riskPremiumBps = 0;
22259
22318
  if (totalDebtForPremium > 0) {
22260
- const sorted = collaterals.slice().sort((a, b) => a.riskBps - b.riskBps);
22319
+ const sorted = collaterals.slice().sort((a, b) => a.riskBps - b.riskBps || b.valueUsd - a.valueUsd);
22261
22320
  let debtLeft = totalDebtForPremium;
22262
22321
  let weightedSum = 0;
22263
22322
  for (const c of sorted) {
@@ -22267,7 +22326,7 @@ function createAaveV4UserState(payload, lenderData, totalDeposits24h = 0, totalD
22267
22326
  debtLeft -= used;
22268
22327
  }
22269
22328
  const covered = totalDebtForPremium - debtLeft;
22270
- riskPremiumBps = covered > 0 ? weightedSum / covered : 0;
22329
+ riskPremiumBps = covered > 0 ? Math.ceil(weightedSum / covered) : 0;
22271
22330
  }
22272
22331
  let depositInterest = 0;
22273
22332
  let borrowInterest = 0;
@@ -22303,14 +22362,10 @@ function createAaveV4UserState(payload, lenderData, totalDeposits24h = 0, totalD
22303
22362
  configs,
22304
22363
  pos.userConfigKey
22305
22364
  );
22306
- const positionThresholdBps = Number(
22307
- meta.riskPremiumThresholdBps ?? 0
22308
- );
22309
- const clampedPremiumBps = positionThresholdBps > 0 ? Math.min(riskPremiumBps, positionThresholdBps) : riskPremiumBps;
22310
- const userPremiumMultiplier = 1 + clampedPremiumBps / 1e4;
22365
+ const userPremiumMultiplier = 1 + riskPremiumBps / 1e4;
22311
22366
  const effectiveVariableBorrowRate = (variableBorrowRate ?? 0) * userPremiumMultiplier;
22312
22367
  pos.variableBorrowRate = effectiveVariableBorrowRate;
22313
- pos.riskPremiumBps = clampedPremiumBps;
22368
+ pos.riskPremiumBps = riskPremiumBps;
22314
22369
  deposits += depositsUSD;
22315
22370
  debt += debtUSD + (debtStableUSD ?? 0);
22316
22371
  oracleDebt += debtUSDOracle + (pos.debtStableUSDOracle ?? debtStableUSD ?? 0);
@@ -22351,6 +22406,8 @@ function createAaveV4UserState(payload, lenderData, totalDeposits24h = 0, totalD
22351
22406
  deposits24h: totalDeposits24h,
22352
22407
  debt24h: totalDebt24h,
22353
22408
  nav24h: totalDeposits24h - totalDebt24h,
22409
+ // Spoke-level risk premium in BPS — matches Spoke.getUserAccountData().riskPremium
22410
+ riskPremiumBps,
22354
22411
  ...payload.rewards ? { rewards: payload.rewards } : {}
22355
22412
  };
22356
22413
  const aprData2 = {
@@ -22940,12 +22997,45 @@ function toBigInt8(v) {
22940
22997
  return 0n;
22941
22998
  }
22942
22999
  }
23000
+ function ensureMetaStub(metaMap, marketUid, underlying) {
23001
+ if (metaMap[marketUid]) return;
23002
+ metaMap[marketUid] = {
23003
+ marketUid,
23004
+ underlying,
23005
+ asset: { address: underlying, decimals: 18, symbol: "" },
23006
+ price: { priceUsd: 0, priceUsd24h: 0 },
23007
+ depositRate: 0,
23008
+ variableBorrowRate: 0,
23009
+ stableBorrowRate: 0,
23010
+ intrinsicYield: 0,
23011
+ rewards: [],
23012
+ configs: null,
23013
+ flags: {
23014
+ isActive: true,
23015
+ isFrozen: false,
23016
+ borrowingEnabled: false,
23017
+ collateralActive: true,
23018
+ hasStable: false
23019
+ },
23020
+ borrowLiquidity: null,
23021
+ withdrawLiquidity: null,
23022
+ depositable: null,
23023
+ params: null
23024
+ };
23025
+ }
22943
23026
  var getGearboxV3UserDataConverter = (_lender, chainId, account, meta) => {
22944
23027
  return [
22945
23028
  (data) => {
22946
23029
  if (!data || data.length !== GEARBOX_V3_USER_CALL_COUNT) return void 0;
22947
23030
  const first = data[0];
22948
- const creditAccounts = Array.isArray(first) ? first : first?.data ?? first?.[0];
23031
+ let creditAccounts;
23032
+ if (Array.isArray(first) && first.length === 2 && Array.isArray(first[0]) && (first[0].length === 0 || typeof first[0][0] === "object")) {
23033
+ creditAccounts = first[0];
23034
+ } else if (Array.isArray(first)) {
23035
+ creditAccounts = first;
23036
+ } else {
23037
+ creditAccounts = first?.data ?? first?.[0];
23038
+ }
22949
23039
  if (!Array.isArray(creditAccounts) || creditAccounts.length === 0)
22950
23040
  return void 0;
22951
23041
  const perCM = /* @__PURE__ */ new Map();
@@ -22965,12 +23055,12 @@ var getGearboxV3UserDataConverter = (_lender, chainId, account, meta) => {
22965
23055
  } catch {
22966
23056
  continue;
22967
23057
  }
22968
- const metaMap = meta?.[lenderKey];
22969
- if (!metaMap) continue;
23058
+ const metaMap = meta?.[lenderKey] ? { ...meta[lenderKey] } : {};
22970
23059
  const firstCa = accounts[0];
22971
23060
  const rawUnderlying = (firstCa.underlying ?? "").toString().toLowerCase();
22972
23061
  const underlying = rawUnderlying;
22973
23062
  const loanMarketUid = createMarketUid(chainId, lenderKey, underlying);
23063
+ ensureMetaStub(metaMap, loanMarketUid, underlying);
22974
23064
  const loanMeta = metaMap[loanMarketUid];
22975
23065
  const loanDec = loanMeta?.asset?.decimals ?? 18;
22976
23066
  const loanDisplayPrice = loanMeta ? getDisplayPrice(loanMeta) : 0;
@@ -22984,10 +23074,6 @@ var getGearboxV3UserDataConverter = (_lender, chainId, account, meta) => {
22984
23074
  if (!caAddress) continue;
22985
23075
  const debtRaw = toBigInt8(ca.debt);
22986
23076
  const tokens = Array.isArray(ca.tokens) ? ca.tokens : Array.isArray(ca.balances) ? ca.balances : [];
22987
- const hasAnyBalance = tokens.some(
22988
- (b) => toBigInt8(b?.balance) > 0n
22989
- );
22990
- if (debtRaw === 0n && !hasAnyBalance) continue;
22991
23077
  modes[caAddress] = 0;
22992
23078
  const posData = {};
22993
23079
  let totalDepositsUSD = 0;
@@ -23000,6 +23086,7 @@ var getGearboxV3UserDataConverter = (_lender, chainId, account, meta) => {
23000
23086
  const quotaRaw = toBigInt8(bal.quota);
23001
23087
  const isQuoted = quotaRaw > 0n || !!bal?.isQuoted;
23002
23088
  const colMarketUid = createMarketUid(chainId, lenderKey, token);
23089
+ ensureMetaStub(metaMap, colMarketUid, token);
23003
23090
  const colMeta = metaMap[colMarketUid];
23004
23091
  const colDec = colMeta?.asset?.decimals ?? 18;
23005
23092
  const colDisplayPrice = colMeta ? getDisplayPrice(colMeta) : 0;
@@ -31832,7 +31919,7 @@ var SiloOracleAbi = [
31832
31919
  type: "function"
31833
31920
  }
31834
31921
  ];
31835
- var ZERO_ADDRESS4 = "0x0000000000000000000000000000000000000000";
31922
+ var ZERO_ADDRESS5 = "0x0000000000000000000000000000000000000000";
31836
31923
  function lookupUSD(context, asset) {
31837
31924
  const lc = asset.toLowerCase();
31838
31925
  const groupKey = context.tokenList?.[lc]?.assetGroup ?? `${context.chainId}-${lc}`;
@@ -31844,7 +31931,7 @@ function getSiloV2Calls(chainId) {
31844
31931
  const tokensWithRealOracle = /* @__PURE__ */ new Set();
31845
31932
  for (const market of allMarkets) {
31846
31933
  for (const half of [market.silo0, market.silo1]) {
31847
- if (half.solvencyOracle && half.solvencyOracle !== ZERO_ADDRESS4) {
31934
+ if (half.solvencyOracle && half.solvencyOracle !== ZERO_ADDRESS5) {
31848
31935
  tokensWithRealOracle.add(half.token.toLowerCase());
31849
31936
  }
31850
31937
  }
@@ -31857,7 +31944,7 @@ function getSiloV2Calls(chainId) {
31857
31944
  const lenderKey = siloV2LenderKey(market.siloConfig);
31858
31945
  const halves = [market.silo0, market.silo1];
31859
31946
  const isStatic = halves.map(
31860
- (h) => !h.solvencyOracle || h.solvencyOracle === ZERO_ADDRESS4
31947
+ (h) => !h.solvencyOracle || h.solvencyOracle === ZERO_ADDRESS5
31861
31948
  );
31862
31949
  if (isStatic[0] && isStatic[1]) {
31863
31950
  const t0 = halves[0].token.toLowerCase();
@@ -31877,7 +31964,7 @@ function getSiloV2Calls(chainId) {
31877
31964
  decimals: half.decimals,
31878
31965
  silo: half.silo.toLowerCase(),
31879
31966
  lenderKey,
31880
- oracle: ZERO_ADDRESS4,
31967
+ oracle: ZERO_ADDRESS5,
31881
31968
  partnerToken: partnerLc,
31882
31969
  isStatic: true
31883
31970
  });
@@ -32003,7 +32090,7 @@ var SiloOracleAbi2 = [
32003
32090
  type: "function"
32004
32091
  }
32005
32092
  ];
32006
- var ZERO_ADDRESS5 = "0x0000000000000000000000000000000000000000";
32093
+ var ZERO_ADDRESS6 = "0x0000000000000000000000000000000000000000";
32007
32094
  function lookupUSD2(context, asset) {
32008
32095
  const lc = asset.toLowerCase();
32009
32096
  const groupKey = context.tokenList?.[lc]?.assetGroup ?? `${context.chainId}-${lc}`;
@@ -32015,7 +32102,7 @@ function getSiloV3Calls(chainId) {
32015
32102
  const tokensWithRealOracle = /* @__PURE__ */ new Set();
32016
32103
  for (const market of allMarkets) {
32017
32104
  for (const half of [market.silo0, market.silo1]) {
32018
- if (half.solvencyOracle && half.solvencyOracle !== ZERO_ADDRESS5) {
32105
+ if (half.solvencyOracle && half.solvencyOracle !== ZERO_ADDRESS6) {
32019
32106
  tokensWithRealOracle.add(half.token.toLowerCase());
32020
32107
  }
32021
32108
  }
@@ -32028,7 +32115,7 @@ function getSiloV3Calls(chainId) {
32028
32115
  const lenderKey = siloV3LenderKey(market.siloConfig);
32029
32116
  const halves = [market.silo0, market.silo1];
32030
32117
  const isStatic = halves.map(
32031
- (h) => !h.solvencyOracle || h.solvencyOracle === ZERO_ADDRESS5
32118
+ (h) => !h.solvencyOracle || h.solvencyOracle === ZERO_ADDRESS6
32032
32119
  );
32033
32120
  if (isStatic[0] && isStatic[1]) {
32034
32121
  const t0 = halves[0].token.toLowerCase();
@@ -32048,7 +32135,7 @@ function getSiloV3Calls(chainId) {
32048
32135
  decimals: half.decimals,
32049
32136
  silo: half.silo.toLowerCase(),
32050
32137
  lenderKey,
32051
- oracle: ZERO_ADDRESS5,
32138
+ oracle: ZERO_ADDRESS6,
32052
32139
  partnerToken: partnerLc,
32053
32140
  isStatic: true
32054
32141
  });
@@ -32379,7 +32466,7 @@ function lookupUSD3(context, asset) {
32379
32466
  return context.usdPrices[groupKey] ?? context.usdPrices[lc] ?? 0;
32380
32467
  }
32381
32468
  function parseSiloV2GraphQLResults(items, context) {
32382
- const ZERO_ADDRESS6 = "0x0000000000000000000000000000000000000000";
32469
+ const ZERO_ADDRESS7 = "0x0000000000000000000000000000000000000000";
32383
32470
  const out = [];
32384
32471
  const seen = /* @__PURE__ */ new Set();
32385
32472
  for (const item of items) {
@@ -32402,8 +32489,8 @@ function parseSiloV2GraphQLResults(items, context) {
32402
32489
  const partnerTokenLc = other.token.toLowerCase();
32403
32490
  const dedupKey = `${lenderKey}:${tokenLc}`;
32404
32491
  if (seen.has(dedupKey)) continue;
32405
- const oracleAddr = (side.solvencyOracleAddress ?? side.solvencyOracle?.id ?? self.solvencyOracle ?? ZERO_ADDRESS6).toLowerCase();
32406
- const isStatic = !oracleAddr || oracleAddr === ZERO_ADDRESS6;
32492
+ const oracleAddr = (side.solvencyOracleAddress ?? side.solvencyOracle?.id ?? self.solvencyOracle ?? ZERO_ADDRESS7).toLowerCase();
32493
+ const isStatic = !oracleAddr || oracleAddr === ZERO_ADDRESS7;
32407
32494
  const siloAddrLc = self.silo.toLowerCase();
32408
32495
  try {
32409
32496
  let priceUSD = 0;
@@ -32523,7 +32610,7 @@ function lookupUSD4(context, asset) {
32523
32610
  return context.usdPrices[groupKey] ?? context.usdPrices[lc] ?? 0;
32524
32611
  }
32525
32612
  function parseSiloV3GraphQLResults(items, context) {
32526
- const ZERO_ADDRESS6 = "0x0000000000000000000000000000000000000000";
32613
+ const ZERO_ADDRESS7 = "0x0000000000000000000000000000000000000000";
32527
32614
  const out = [];
32528
32615
  const seen = /* @__PURE__ */ new Set();
32529
32616
  for (const item of items) {
@@ -32546,8 +32633,8 @@ function parseSiloV3GraphQLResults(items, context) {
32546
32633
  const partnerTokenLc = other.token.toLowerCase();
32547
32634
  const dedupKey = `${lenderKey}:${tokenLc}`;
32548
32635
  if (seen.has(dedupKey)) continue;
32549
- const oracleAddr = (side.solvencyOracleAddress ?? side.solvencyOracle?.id ?? self.solvencyOracle ?? ZERO_ADDRESS6).toLowerCase();
32550
- const isStatic = !oracleAddr || oracleAddr === ZERO_ADDRESS6;
32636
+ const oracleAddr = (side.solvencyOracleAddress ?? side.solvencyOracle?.id ?? self.solvencyOracle ?? ZERO_ADDRESS7).toLowerCase();
32637
+ const isStatic = !oracleAddr || oracleAddr === ZERO_ADDRESS7;
32551
32638
  const siloAddrLc = self.silo.toLowerCase();
32552
32639
  try {
32553
32640
  let priceUSD = 0;
@@ -33677,6 +33764,8 @@ function parseFTokens(fTokens, chainId, prices, tokenList) {
33677
33764
  const priceUsd = prices[oracleKey] ?? 0;
33678
33765
  const supplyRate = scaleFluidRate2(ft.supplyRate);
33679
33766
  const rewardsRate = scaleFluidRate2(ft.rewardsRate);
33767
+ const liquidityRaw = ft.liquidityUserSupplyData?.withdrawable?.toString() ?? "0";
33768
+ const liquidityFormatted = Number(parseRawAmount(liquidityRaw, decimals));
33680
33769
  const entry = {
33681
33770
  address: ft.tokenAddress,
33682
33771
  underlying,
@@ -33695,7 +33784,10 @@ function parseFTokens(fTokens, chainId, prices, tokenList) {
33695
33784
  asset: assetMeta,
33696
33785
  priceUsd: priceUsd || void 0,
33697
33786
  totalAssetsFormatted,
33698
- totalAssetsUsd: totalAssetsFormatted * priceUsd
33787
+ totalAssetsUsd: totalAssetsFormatted * priceUsd,
33788
+ liquidity: liquidityRaw,
33789
+ liquidityFormatted,
33790
+ liquidityUsd: liquidityFormatted * priceUsd
33699
33791
  };
33700
33792
  out[underlying] = entry;
33701
33793
  }
@@ -33713,6 +33805,374 @@ var fetchFluidFTokens = async (chainId, multicallRetry, prices = {}, tokenList =
33713
33805
  return converter(raw) ?? {};
33714
33806
  };
33715
33807
 
33808
+ // src/vaults/morpho/fetchFromApi.ts
33809
+ var MORPHO_API_URL = "https://blue-api.morpho.org/graphql";
33810
+ var PAGE_SIZE = 200;
33811
+ var vaultsQuery = (first, skip, chainId) => `
33812
+ query GetVaults {
33813
+ vaults(
33814
+ first: ${first},
33815
+ skip: ${skip},
33816
+ where: { chainId_in: [${chainId}], whitelisted: true },
33817
+ orderBy: TotalAssetsUsd,
33818
+ orderDirection: Desc
33819
+ ) {
33820
+ items {
33821
+ address
33822
+ symbol
33823
+ name
33824
+ whitelisted
33825
+ asset {
33826
+ address
33827
+ name
33828
+ symbol
33829
+ decimals
33830
+ priceUsd
33831
+ }
33832
+ liquidity {
33833
+ underlying
33834
+ usd
33835
+ }
33836
+ state {
33837
+ totalAssets
33838
+ totalAssetsUsd
33839
+ totalSupply
33840
+ apy
33841
+ netApy
33842
+ fee
33843
+ timelock
33844
+ owner
33845
+ curator
33846
+ guardian
33847
+ rewards {
33848
+ supplyApr
33849
+ asset {
33850
+ address
33851
+ }
33852
+ }
33853
+ }
33854
+ }
33855
+ }
33856
+ }
33857
+ `;
33858
+ async function fetchPage(chainId, first, skip) {
33859
+ const response = await fetch(MORPHO_API_URL, {
33860
+ method: "POST",
33861
+ headers: { "Content-Type": "application/json" },
33862
+ body: JSON.stringify({ query: vaultsQuery(first, skip, chainId) })
33863
+ });
33864
+ if (!response.ok) {
33865
+ throw new Error(
33866
+ `Morpho vaults API failed: ${response.status} - ${response.statusText}`
33867
+ );
33868
+ }
33869
+ const json = await response.json();
33870
+ return json?.data?.vaults?.items ?? [];
33871
+ }
33872
+ var sumRewardsApr = (rewards) => {
33873
+ if (!rewards) return 0;
33874
+ let total = 0;
33875
+ for (const r of rewards) {
33876
+ const apr = Number(r?.supplyApr ?? 0);
33877
+ if (Number.isFinite(apr)) total += apr;
33878
+ }
33879
+ return total * 100;
33880
+ };
33881
+ function parseVault2(v, chainId, prices, tokenList) {
33882
+ const address = (v?.address ?? "").toLowerCase();
33883
+ const assetAddr = (v?.asset?.address ?? "").toLowerCase();
33884
+ if (!address || !assetAddr) return null;
33885
+ const state = v.state ?? {};
33886
+ const assetMeta = tokenList[assetAddr];
33887
+ const decimals = Number(v.asset?.decimals ?? assetMeta?.decimals ?? 18);
33888
+ const totalAssetsRaw = state.totalAssets?.toString() ?? "0";
33889
+ const totalAssetsFormatted = Number(parseRawAmount(totalAssetsRaw, decimals));
33890
+ const liquidityRaw = v.liquidity?.underlying?.toString() ?? "0";
33891
+ const liquidityFormatted = Number(parseRawAmount(liquidityRaw, decimals));
33892
+ const liquidityUsd = Number(v.liquidity?.usd ?? 0);
33893
+ const oracleKey = toOracleKey(assetMeta?.assetGroup) ?? toGenericPriceKey(assetAddr, chainId);
33894
+ const apiPriceUsd = Number(v.asset?.priceUsd ?? 0);
33895
+ const resolvedPriceUsd = prices[oracleKey] ?? prices[assetAddr] ?? apiPriceUsd ?? 0;
33896
+ const netApy = Number(state.netApy ?? state.apy ?? 0);
33897
+ const supplyRate = apyToAprPercent(netApy * 100);
33898
+ const rewardsRate = sumRewardsApr(state.rewards);
33899
+ const apiTotalAssetsUsd = Number(state.totalAssetsUsd ?? 0);
33900
+ const totalAssetsUsd = apiTotalAssetsUsd || totalAssetsFormatted * resolvedPriceUsd;
33901
+ return {
33902
+ address,
33903
+ underlying: assetAddr,
33904
+ symbol: v.symbol ?? "",
33905
+ name: v.name ?? "",
33906
+ decimals,
33907
+ totalAssets: totalAssetsRaw,
33908
+ totalSupply: state.totalSupply?.toString() ?? "0",
33909
+ supplyRate,
33910
+ rewardsRate,
33911
+ depositRate: supplyRate + rewardsRate,
33912
+ fee: Number(state.fee ?? 0) * 100,
33913
+ timelock: Number(state.timelock ?? 0),
33914
+ whitelisted: v.whitelisted ?? true,
33915
+ owner: state.owner?.toLowerCase() || void 0,
33916
+ curator: state.curator?.toLowerCase() || void 0,
33917
+ guardian: state.guardian?.toLowerCase() || void 0,
33918
+ asset: assetMeta,
33919
+ priceUsd: resolvedPriceUsd || void 0,
33920
+ totalAssetsFormatted,
33921
+ totalAssetsUsd,
33922
+ liquidity: liquidityRaw,
33923
+ liquidityFormatted,
33924
+ liquidityUsd: liquidityUsd || liquidityFormatted * resolvedPriceUsd
33925
+ };
33926
+ }
33927
+ async function fetchMorphoVaultsFromApi(chainId, prices = {}, tokenList = {}, maxItems = 600) {
33928
+ const out = {};
33929
+ let skip = 0;
33930
+ while (skip < maxItems) {
33931
+ const page = await fetchPage(chainId, PAGE_SIZE, skip);
33932
+ if (page.length === 0) break;
33933
+ for (const v of page) {
33934
+ const parsed = parseVault2(v, chainId, prices, tokenList);
33935
+ if (parsed) out[parsed.address] = parsed;
33936
+ }
33937
+ if (page.length < PAGE_SIZE) break;
33938
+ skip += PAGE_SIZE;
33939
+ }
33940
+ return out;
33941
+ }
33942
+
33943
+ // src/vaults/morpho/fetchFromSubgraph.ts
33944
+ var MORPHO_VAULT_SUBGRAPH_URLS = {
33945
+ [Chain.SEI_NETWORK]: "https://api.goldsky.com/api/public/project_cmiergfbv4vma01vb642yaeam/subgraphs/morphoblue-sei/1.0.1/gn",
33946
+ [Chain.CELO_MAINNET]: "https://api.goldsky.com/api/public/project_cmiergfbv4vma01vb642yaeam/subgraphs/morphoblue-celo/1.0.4/gn",
33947
+ [Chain.LISK]: "https://api.goldsky.com/api/public/project_cmiergfbv4vma01vb642yaeam/subgraphs/morphobluelisk/1.0.1/gn",
33948
+ [Chain.SONEIUM]: "https://api.goldsky.com/api/public/project_cmiergfbv4vma01vb642yaeam/subgraphs/morphobluesoneium/1.0.2/gn",
33949
+ [Chain.TAC_MAINNET]: "https://api.goldsky.com/api/public/project_cmiergfbv4vma01vb642yaeam/subgraphs/morphoblue-tac/1.0.0/gn",
33950
+ [Chain.HEMI_NETWORK]: "https://feather.securesecrets.org/hemi-mopho-blue/"
33951
+ };
33952
+ var hasMorphoVaultSubgraph = (chainId) => chainId in MORPHO_VAULT_SUBGRAPH_URLS;
33953
+ var META_MORPHOS_QUERY = `
33954
+ {
33955
+ metaMorphos(first: 100, skip: 0) {
33956
+ id
33957
+ name
33958
+ symbol
33959
+ decimals
33960
+ asset { id }
33961
+ curator { id }
33962
+ owner { id }
33963
+ guardian { id }
33964
+ timelock
33965
+ fee
33966
+ rate { id rate }
33967
+ lastTotalAssets
33968
+ totalShares
33969
+ }
33970
+ }
33971
+ `;
33972
+ function parseVaultRate(rate) {
33973
+ if (!rate) return 0;
33974
+ const numeric = Number(rate.rate) * 100;
33975
+ return Number.isFinite(numeric) ? numeric : 0;
33976
+ }
33977
+ function parseVault3(v, chainId, prices, tokenList) {
33978
+ const address = (v?.id ?? "").toLowerCase();
33979
+ const assetAddr = (v?.asset?.id ?? "").toLowerCase();
33980
+ if (!address || !assetAddr) return null;
33981
+ const assetMeta = tokenList[assetAddr];
33982
+ const decimals = Number(v.decimals ?? assetMeta?.decimals ?? 18);
33983
+ const totalAssetsRaw = v.lastTotalAssets?.toString() ?? "0";
33984
+ const totalAssetsFormatted = Number(parseRawAmount(totalAssetsRaw, decimals));
33985
+ const oracleKey = toOracleKey(assetMeta?.assetGroup) ?? toGenericPriceKey(assetAddr, chainId);
33986
+ const priceUsd = prices[oracleKey] ?? prices[assetAddr] ?? 0;
33987
+ const supplyRate = parseVaultRate(v.rate);
33988
+ const feeRaw = Number(v.fee ?? 0);
33989
+ const fee = Number.isFinite(feeRaw) ? feeRaw * 100 : 0;
33990
+ return {
33991
+ address,
33992
+ underlying: assetAddr,
33993
+ symbol: v.symbol ?? "",
33994
+ name: v.name ?? "",
33995
+ decimals,
33996
+ totalAssets: totalAssetsRaw,
33997
+ totalSupply: v.totalShares?.toString() ?? "0",
33998
+ supplyRate,
33999
+ // Rewards APR is not carried in the subgraph schema — surface 0 so
34000
+ // downstream math still works; callers that need rewards on
34001
+ // Goldsky-sourced chains must layer them in separately.
34002
+ rewardsRate: 0,
34003
+ depositRate: supplyRate,
34004
+ fee,
34005
+ timelock: Number(v.timelock ?? 0),
34006
+ whitelisted: true,
34007
+ owner: v.owner?.id?.toLowerCase() || void 0,
34008
+ curator: v.curator?.id?.toLowerCase() || void 0,
34009
+ guardian: v.guardian?.id?.toLowerCase() || void 0,
34010
+ asset: assetMeta,
34011
+ priceUsd: priceUsd || void 0,
34012
+ totalAssetsFormatted,
34013
+ totalAssetsUsd: totalAssetsFormatted * priceUsd,
34014
+ // Subgraph does not expose current withdrawable liquidity — default
34015
+ // to totalAssets as an optimistic upper bound so callers still get a
34016
+ // value. Users on Goldsky-sourced chains should not rely on this for
34017
+ // hard withdraw validation.
34018
+ liquidity: totalAssetsRaw,
34019
+ liquidityFormatted: totalAssetsFormatted,
34020
+ liquidityUsd: totalAssetsFormatted * priceUsd
34021
+ };
34022
+ }
34023
+ async function fetchMorphoVaultsFromSubgraph(chainId, prices = {}, tokenList = {}) {
34024
+ const url = MORPHO_VAULT_SUBGRAPH_URLS[chainId];
34025
+ if (!url) return {};
34026
+ const response = await fetch(url, {
34027
+ method: "POST",
34028
+ headers: { "Content-Type": "application/json" },
34029
+ body: JSON.stringify({ query: META_MORPHOS_QUERY })
34030
+ });
34031
+ if (!response.ok) {
34032
+ throw new Error(
34033
+ `Morpho vaults subgraph failed for chain ${chainId}: ${response.status} - ${response.statusText}`
34034
+ );
34035
+ }
34036
+ const json = await response.json();
34037
+ const items = json?.data?.metaMorphos ?? [];
34038
+ const out = {};
34039
+ for (const v of items) {
34040
+ const parsed = parseVault3(v, chainId, prices, tokenList);
34041
+ if (parsed) out[parsed.address] = parsed;
34042
+ }
34043
+ return out;
34044
+ }
34045
+
34046
+ // src/vaults/morpho/fetchPublic.ts
34047
+ var fetchMorphoVaults = async (chainId, prices = {}, tokenList = {}) => {
34048
+ if (hasMorphoVaultSubgraph(chainId)) {
34049
+ return fetchMorphoVaultsFromSubgraph(chainId, prices, tokenList);
34050
+ }
34051
+ return fetchMorphoVaultsFromApi(chainId, prices, tokenList);
34052
+ };
34053
+
34054
+ // src/vaults/silo/fetchPublic.ts
34055
+ var SILO_API_URL = "https://api-v3.silo.finance";
34056
+ var vaultsQuery2 = (chainId, limit) => `
34057
+ query GetSiloVaults {
34058
+ vaults(where: {chainId_in: [${chainId}]}, limit: ${limit}) {
34059
+ items {
34060
+ id
34061
+ chainId
34062
+ name
34063
+ symbol
34064
+ decimals
34065
+ protocolId
34066
+ protocol { id protocolVersion }
34067
+ asset { id symbol decimals }
34068
+ ownerId
34069
+ curatorId
34070
+ guardianId
34071
+ feeRecipient
34072
+ totalAssets
34073
+ totalAssetsUsd
34074
+ totalSupply
34075
+ performanceFee
34076
+ timelock
34077
+ apr
34078
+ userApr
34079
+ }
34080
+ }
34081
+ }
34082
+ `;
34083
+ var PERFORMANCE_FEE_SCALE = 1e16;
34084
+ var toRawAmount = (decimalString, decimals) => {
34085
+ if (!decimalString) return "0";
34086
+ try {
34087
+ return parseUnits(decimalString, decimals).toString();
34088
+ } catch {
34089
+ return "0";
34090
+ }
34091
+ };
34092
+ function parseVault4(v, chainId, prices, tokenList) {
34093
+ const address = (v?.id ?? "").toLowerCase();
34094
+ const assetAddr = (v?.asset?.id ?? "").toLowerCase();
34095
+ if (!address || !assetAddr) return null;
34096
+ const assetMeta = tokenList[assetAddr];
34097
+ const decimals = Number(
34098
+ v.decimals ?? v.asset?.decimals ?? assetMeta?.decimals ?? 18
34099
+ );
34100
+ const totalAssetsFormatted = Number(v.totalAssets ?? 0) || 0;
34101
+ const totalAssetsRaw = toRawAmount(v.totalAssets, decimals);
34102
+ const totalSupplyRaw = toRawAmount(v.totalSupply, decimals);
34103
+ const oracleKey = toOracleKey(assetMeta?.assetGroup) ?? toGenericPriceKey(assetAddr, chainId);
34104
+ const priceUsd = prices[oracleKey] ?? prices[assetAddr] ?? 0;
34105
+ const supplyRate = Number(v.userApr ?? 0) || 0;
34106
+ const grossRate = Number(v.apr ?? 0) || 0;
34107
+ const feeRaw = Number(v.performanceFee ?? 0);
34108
+ const fee = Number.isFinite(feeRaw) ? feeRaw / PERFORMANCE_FEE_SCALE : 0;
34109
+ const apiTotalAssetsUsd = Number(v.totalAssetsUsd ?? 0) || 0;
34110
+ const totalAssetsUsd = apiTotalAssetsUsd || totalAssetsFormatted * priceUsd;
34111
+ return {
34112
+ address,
34113
+ underlying: assetAddr,
34114
+ symbol: v.symbol ?? "",
34115
+ name: v.name ?? "",
34116
+ decimals,
34117
+ protocolVersion: v.protocol?.protocolVersion ?? "",
34118
+ protocolId: (v.protocolId ?? v.protocol?.id ?? "").toLowerCase(),
34119
+ totalAssets: totalAssetsRaw,
34120
+ totalSupply: totalSupplyRaw,
34121
+ supplyRate,
34122
+ grossRate,
34123
+ rewardsRate: 0,
34124
+ depositRate: supplyRate,
34125
+ fee,
34126
+ timelock: Number(v.timelock ?? 0),
34127
+ owner: v.ownerId?.toLowerCase() || void 0,
34128
+ curator: v.curatorId?.toLowerCase() || void 0,
34129
+ guardian: v.guardianId?.toLowerCase() || void 0,
34130
+ feeRecipient: v.feeRecipient?.toLowerCase() || void 0,
34131
+ asset: assetMeta,
34132
+ priceUsd: priceUsd || void 0,
34133
+ totalAssetsFormatted,
34134
+ totalAssetsUsd,
34135
+ // Silo's indexer doesn't expose an immediate-withdraw figure; the
34136
+ // effective cap is per-allocation silo utilisation, which would need
34137
+ // a second-pass aggregation. Fall back to `totalAssets` as an
34138
+ // optimistic ceiling so consumers still get a field for parity with
34139
+ // Morpho / Fluid / Gearbox. Not suitable for hard withdraw validation.
34140
+ liquidity: totalAssetsRaw,
34141
+ liquidityFormatted: totalAssetsFormatted,
34142
+ liquidityUsd: totalAssetsUsd
34143
+ };
34144
+ }
34145
+ var fetchSiloVaults = async (chainId, prices = {}, tokenList = {}, options) => {
34146
+ if (!SILO_API_SUPPORTED_CHAIN_IDS.has(chainId)) return {};
34147
+ const limit = options?.limit ?? 500;
34148
+ const response = await fetch(SILO_API_URL, {
34149
+ method: "POST",
34150
+ headers: { "Content-Type": "application/json" },
34151
+ body: JSON.stringify({ query: vaultsQuery2(chainId, limit) })
34152
+ });
34153
+ if (!response.ok) {
34154
+ throw new Error(
34155
+ `[silo-vaults] Network error: ${response.status} - ${response.statusText}`
34156
+ );
34157
+ }
34158
+ const payload = await response.json();
34159
+ if (payload?.errors?.length) {
34160
+ throw new Error(
34161
+ `[silo-vaults] GraphQL error: ${payload.errors.map((e) => e?.message).join("; ")}`
34162
+ );
34163
+ }
34164
+ const items = payload?.data?.vaults?.items ?? [];
34165
+ const out = {};
34166
+ for (const v of items) {
34167
+ if (options?.protocolVersion && v.protocol?.protocolVersion !== options.protocolVersion) {
34168
+ continue;
34169
+ }
34170
+ const parsed = parseVault4(v, chainId, prices, tokenList);
34171
+ if (parsed) out[parsed.address] = parsed;
34172
+ }
34173
+ return out;
34174
+ };
34175
+
33716
34176
  // src/lending/margin/e-mode/index.ts
33717
34177
  function computeEModeSwitchHealth(positions, lenderMeta, currentCollateral, currentAdjustedDebt, currentMode, targetMode) {
33718
34178
  if (currentAdjustedDebt === 0) return null;
@@ -34199,6 +34659,6 @@ async function fetchTokenBalances(chainId, account, tokens, options = {}) {
34199
34659
  return parseTokenBalanceResult(rawResult, prepared.query);
34200
34660
  }
34201
34661
 
34202
- export { EMPTY_BALANCE, MORPHO_LENS, MaxParamThresholds, applyPositionDelta, attachPricesToFlashLiquidity, buildFluidFTokensCall, buildLoopResult, buildMorphoTypeCall, buildMorphoTypeUserCallWithLens, buildPortfolioTotals, buildSumerAccumulators, buildSummaries, calculateLeverage, calculateNetApr, calculateOverallNetApr, calculateWeightedAverage, computeBorrowDelta2 as computeBorrowDelta, computeCloseTradeDeltas, computeCollateralSwapDeltas, computeDebtSwapDeltas, computeDepositDelta2 as computeDepositDelta, computeEModeAnalysis, computeOpenTradeDeltas, computePostTradeMetrics, computeRepayDelta2 as computeRepayDelta, computeSumerBorrowDelta, computeSumerDepositDelta, computeSumerRepayDelta, computeSumerWaterfall, computeSumerWithdrawDelta, computeWithdrawDelta2 as computeWithdrawDelta, computeZapTradeDeltas, convertLenderUserDataResult, createMarketUid, createMulticallRpcCall, createRawRpcCalls, decodeListaMarkets, decodeMarkets, decodePackedListaUserDataset, decodePackedMorphoUserDataset, encodeBalanceFetcherCalldata, fetchEulerSubAccountIndexes, fetchFlashLiquidityForChain, fetchFluidFTokens, fetchGeneralYields, fetchGeneralYieldsByMarketUid, fetchOraclePrices, fetchPendlePrices, fetchTokenBalances, fetchTokenMetadata, filterActiveLenders, filterLendersByProtocol, fuseLenderData, generateLendingPools, getAavesForChain, getAssetConfig, getBalanceForMarketUid, getBorrowCapacity, getFluidFTokensConverter, getHealthFactor, getLenderAssets, getLenderPublicData, getLenderPublicDataAll, getLenderPublicDataViaApi, getLenderUserDataMulti, getLenderUserDataResult, getLendersForChain, getMaxAmountClose, getMaxAmountCollateralSwap, getMaxAmountDebtSwap, getMaxAmountOpen, getMergedUserData, getMorphoTypeMarketConverter, getSubAccountAddress, getSubAccountIndex, keysFromMaps, multicall3Abi, nanTo, needsLenderApproval, needsTokenApproval, noOpResult, normalizeToBytes, parseBalanceFetcherResult, parseMergedResult, parseMulticallRpcResponses, parseRawRpcBatchResponses, parseRawRpcResponses, parseTokenBalanceResult, positivePart2 as positivePart, prepareLenderUserDataRpcCalls, prepareMergedMulticallParams, prepareMergedRpcCalls, prepareMulticallInputs, prepareTokenBalanceRpcCalls, selectAssetGroupPrices, unflattenLenderData };
34662
+ export { EMPTY_BALANCE, MORPHO_LENS, MaxParamThresholds, applyPositionDelta, attachPricesToFlashLiquidity, buildFluidFTokensCall, buildLoopResult, buildMorphoTypeCall, buildMorphoTypeUserCallWithLens, buildPortfolioTotals, buildSumerAccumulators, buildSummaries, calculateLeverage, calculateNetApr, calculateOverallNetApr, calculateWeightedAverage, computeBorrowDelta2 as computeBorrowDelta, computeCloseTradeDeltas, computeCollateralSwapDeltas, computeDebtSwapDeltas, computeDepositDelta2 as computeDepositDelta, computeEModeAnalysis, computeOpenTradeDeltas, computePostTradeMetrics, computeRepayDelta2 as computeRepayDelta, computeSumerBorrowDelta, computeSumerDepositDelta, computeSumerRepayDelta, computeSumerWaterfall, computeSumerWithdrawDelta, computeWithdrawDelta2 as computeWithdrawDelta, computeZapTradeDeltas, convertLenderUserDataResult, createMarketUid, createMulticallRpcCall, createRawRpcCalls, decodeListaMarkets, decodeMarkets, decodePackedListaUserDataset, decodePackedMorphoUserDataset, encodeBalanceFetcherCalldata, fetchEulerSubAccountIndexes, fetchFlashLiquidityForChain, fetchFluidFTokens, fetchGeneralYields, fetchGeneralYieldsByMarketUid, fetchMorphoVaults, fetchMorphoVaultsFromApi, fetchMorphoVaultsFromSubgraph, fetchOraclePrices, fetchPendlePrices, fetchSiloVaults, fetchTokenBalances, fetchTokenMetadata, filterActiveLenders, filterLendersByProtocol, fuseLenderData, generateLendingPools, getAavesForChain, getAssetConfig, getBalanceForMarketUid, getBorrowCapacity, getFluidFTokensConverter, getHealthFactor, getLenderAssets, getLenderPublicData, getLenderPublicDataAll, getLenderPublicDataViaApi, getLenderUserDataMulti, getLenderUserDataResult, getLendersForChain, getMaxAmountClose, getMaxAmountCollateralSwap, getMaxAmountDebtSwap, getMaxAmountOpen, getMergedUserData, getMorphoTypeMarketConverter, getSubAccountAddress, getSubAccountIndex, hasMorphoVaultSubgraph, keysFromMaps, multicall3Abi, nanTo, needsLenderApproval, needsTokenApproval, noOpResult, normalizeToBytes, parseBalanceFetcherResult, parseMergedResult, parseMulticallRpcResponses, parseRawRpcBatchResponses, parseRawRpcResponses, parseTokenBalanceResult, positivePart2 as positivePart, prepareLenderUserDataRpcCalls, prepareMergedMulticallParams, prepareMergedRpcCalls, prepareMulticallInputs, prepareTokenBalanceRpcCalls, selectAssetGroupPrices, unflattenLenderData };
34203
34663
  //# sourceMappingURL=index.js.map
34204
34664
  //# sourceMappingURL=index.js.map