@1delta/margin-fetcher 0.0.261 → 0.0.262

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -35072,9 +35072,29 @@ var EULER_EARN_VAULTS_QUERY = `
35072
35072
  totalAssets
35073
35073
  totalShares
35074
35074
  totalSupply
35075
+ strategies {
35076
+ id
35077
+ strategy
35078
+ allocatedAssets
35079
+ }
35075
35080
  }
35076
35081
  }
35077
35082
  `;
35083
+ var EVK_BY_ASSETS_QUERY = `
35084
+ query EvkByAssets($assets: [Bytes!]!) {
35085
+ eulerVaults(first: 1000, where: { asset_in: $assets }) {
35086
+ id
35087
+ decimals
35088
+ asset
35089
+ state {
35090
+ supplyApy
35091
+ cash
35092
+ }
35093
+ }
35094
+ }
35095
+ `;
35096
+ var ZERO = 0n;
35097
+ var RAY_TO_PERCENT3 = 1e25;
35078
35098
  function readAddress2(field5) {
35079
35099
  if (!field5) return void 0;
35080
35100
  return field5.toLowerCase();
@@ -35087,19 +35107,84 @@ function parseVaultFee(v) {
35087
35107
  if (n > 100) return n / 1e16;
35088
35108
  return n;
35089
35109
  }
35090
- function parseVault7(v, chainId, prices, tokenList) {
35110
+ function safeBigInt(v) {
35111
+ if (v == null || v === "") return ZERO;
35112
+ try {
35113
+ return BigInt(v);
35114
+ } catch {
35115
+ return ZERO;
35116
+ }
35117
+ }
35118
+ function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent, evkIndex) {
35119
+ if (!strategies?.length) return 0;
35120
+ const totalAssets = safeBigInt(totalAssetsRaw);
35121
+ if (totalAssets === ZERO) return 0;
35122
+ let weightedRay = ZERO;
35123
+ for (const s of strategies) {
35124
+ const evk = s.strategy?.toLowerCase();
35125
+ if (!evk) continue;
35126
+ const apyRay = evkIndex.bySupplyApyRay.get(evk);
35127
+ if (apyRay == null) continue;
35128
+ const allocated = safeBigInt(s.allocatedAssets);
35129
+ if (allocated === ZERO) continue;
35130
+ weightedRay += allocated * apyRay;
35131
+ }
35132
+ if (weightedRay === ZERO) return 0;
35133
+ const apyRayPerAsset = weightedRay / totalAssets;
35134
+ const grossPercent = Number(apyRayPerAsset) / RAY_TO_PERCENT3;
35135
+ const netPercent = grossPercent * (1 - feePercent / 100);
35136
+ return Number.isFinite(netPercent) ? netPercent : 0;
35137
+ }
35138
+ function computeRealLiquidity(strategies, totalAssetsRaw, evkIndex) {
35139
+ const totalAssets = safeBigInt(totalAssetsRaw);
35140
+ if (totalAssets === ZERO) return ZERO;
35141
+ if (evkIndex.byCash.size === 0 && evkIndex.bySupplyApyRay.size === 0) {
35142
+ return totalAssets;
35143
+ }
35144
+ if (!strategies?.length) {
35145
+ return totalAssets;
35146
+ }
35147
+ let allocSum = ZERO;
35148
+ let withdrawable = ZERO;
35149
+ for (const s of strategies) {
35150
+ const alloc = safeBigInt(s.allocatedAssets);
35151
+ if (alloc === ZERO) continue;
35152
+ allocSum += alloc;
35153
+ const evk = s.strategy?.toLowerCase();
35154
+ const cash = evk ? evkIndex.byCash.get(evk) : void 0;
35155
+ withdrawable += cash == null ? alloc : alloc < cash ? alloc : cash;
35156
+ }
35157
+ const idle = totalAssets > allocSum ? totalAssets - allocSum : ZERO;
35158
+ const result = idle + withdrawable;
35159
+ return result > totalAssets ? totalAssets : result;
35160
+ }
35161
+ function parseVault7(v, chainId, prices, tokenList, evkIndex) {
35091
35162
  const address = (v?.id ?? "").toLowerCase();
35092
35163
  const assetAddr = (v?.asset ?? "").toLowerCase();
35093
35164
  if (!address || !assetAddr) return null;
35094
35165
  const assetMeta = tokenList[assetAddr];
35095
- const decimals = Number(assetMeta?.decimals ?? 18);
35166
+ const decimals = Number(
35167
+ evkIndex.decimalsByAsset.get(assetAddr) ?? assetMeta?.decimals ?? 18
35168
+ );
35096
35169
  const totalAssetsRaw = v.totalAssets?.toString() ?? "0";
35097
35170
  const totalAssetsFormatted = Number(parseRawAmount(totalAssetsRaw, decimals));
35098
35171
  const oracleKey = toOracleKey(assetMeta?.assetGroup) ?? toGenericPriceKey(assetAddr, chainId);
35099
35172
  const priceUsd = prices[oracleKey] ?? prices[assetAddr] ?? 0;
35100
35173
  const fee = parseVaultFee(v);
35101
- const supplyRate = 0;
35174
+ const supplyRate = computeWeightedSupplyApy(
35175
+ v.strategies,
35176
+ totalAssetsRaw,
35177
+ fee,
35178
+ evkIndex
35179
+ );
35102
35180
  const totalSupplyRaw = v.totalSupply?.toString() ?? v.totalShares?.toString() ?? "0";
35181
+ const liquidityBig = computeRealLiquidity(
35182
+ v.strategies,
35183
+ totalAssetsRaw,
35184
+ evkIndex
35185
+ );
35186
+ const liquidityRaw = liquidityBig.toString();
35187
+ const liquidityFormatted = Number(parseRawAmount(liquidityRaw, decimals));
35103
35188
  return {
35104
35189
  address,
35105
35190
  underlying: assetAddr,
@@ -35120,31 +35205,75 @@ function parseVault7(v, chainId, prices, tokenList) {
35120
35205
  priceUsd: priceUsd || void 0,
35121
35206
  totalAssetsFormatted,
35122
35207
  totalAssetsUsd: totalAssetsFormatted * priceUsd,
35123
- // Subgraph doesn't expose immediate-withdraw — same optimistic
35124
- // ceiling as Morpho/Silo earn-vault fetchers.
35125
- liquidity: totalAssetsRaw,
35126
- liquidityFormatted: totalAssetsFormatted,
35127
- liquidityUsd: totalAssetsFormatted * priceUsd
35208
+ liquidity: liquidityRaw,
35209
+ liquidityFormatted,
35210
+ liquidityUsd: liquidityFormatted * priceUsd
35128
35211
  };
35129
35212
  }
35130
- async function fetchEulerEarnVaultsFromSubgraph(chainId, prices = {}, tokenList = {}) {
35131
- const url = EULER_EARN_SUBGRAPH_URLS[chainId];
35132
- if (!url) return {};
35213
+ async function postQuery(url, body) {
35133
35214
  const response = await fetch(url, {
35134
35215
  method: "POST",
35135
35216
  headers: { "Content-Type": "application/json" },
35136
- body: JSON.stringify({ query: EULER_EARN_VAULTS_QUERY })
35217
+ body: JSON.stringify(body)
35137
35218
  });
35138
35219
  if (!response.ok) {
35139
35220
  throw new Error(
35140
- `Euler Earn vaults subgraph failed for chain ${chainId}: ${response.status} - ${response.statusText}`
35221
+ `Euler Earn vaults subgraph failed: ${response.status} - ${response.statusText}`
35141
35222
  );
35142
35223
  }
35143
- const json = await response.json();
35224
+ return response.json();
35225
+ }
35226
+ async function fetchEvkIndex(url, assets) {
35227
+ const empty = {
35228
+ bySupplyApyRay: /* @__PURE__ */ new Map(),
35229
+ byCash: /* @__PURE__ */ new Map(),
35230
+ decimalsByAsset: /* @__PURE__ */ new Map()
35231
+ };
35232
+ if (assets.length === 0) return empty;
35233
+ let json;
35234
+ try {
35235
+ json = await postQuery(url, {
35236
+ query: EVK_BY_ASSETS_QUERY,
35237
+ variables: { assets }
35238
+ });
35239
+ } catch {
35240
+ return empty;
35241
+ }
35242
+ const items = json?.data?.eulerVaults ?? [];
35243
+ for (const e of items) {
35244
+ const id = e?.id?.toLowerCase();
35245
+ const asset = e?.asset?.toLowerCase();
35246
+ if (!id || !asset) continue;
35247
+ const decimals = Number(e.decimals ?? NaN);
35248
+ if (Number.isFinite(decimals) && !empty.decimalsByAsset.has(asset)) {
35249
+ empty.decimalsByAsset.set(asset, decimals);
35250
+ }
35251
+ const apyRaw = e.state?.supplyApy;
35252
+ if (apyRaw != null) {
35253
+ empty.bySupplyApyRay.set(id, safeBigInt(apyRaw));
35254
+ }
35255
+ const cashRaw = e.state?.cash;
35256
+ if (cashRaw != null) {
35257
+ empty.byCash.set(id, safeBigInt(cashRaw));
35258
+ }
35259
+ }
35260
+ return empty;
35261
+ }
35262
+ async function fetchEulerEarnVaultsFromSubgraph(chainId, prices = {}, tokenList = {}) {
35263
+ const url = EULER_EARN_SUBGRAPH_URLS[chainId];
35264
+ if (!url) return {};
35265
+ const json = await postQuery(url, { query: EULER_EARN_VAULTS_QUERY });
35144
35266
  const items = json?.data?.eulerEarnVaults ?? [];
35267
+ if (items.length === 0) return {};
35268
+ const assets = /* @__PURE__ */ new Set();
35269
+ for (const v of items) {
35270
+ const a = v?.asset?.toLowerCase();
35271
+ if (a) assets.add(a);
35272
+ }
35273
+ const evkIndex = await fetchEvkIndex(url, [...assets]);
35145
35274
  const out = {};
35146
35275
  for (const v of items) {
35147
- const parsed = parseVault7(v, chainId, prices, tokenList);
35276
+ const parsed = parseVault7(v, chainId, prices, tokenList, evkIndex);
35148
35277
  if (parsed) out[parsed.address] = parsed;
35149
35278
  }
35150
35279
  return out;