@1delta/margin-fetcher 0.0.337 → 0.0.338

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
@@ -24149,6 +24149,244 @@ var buildCompoundV2UserCall = (chainId, lender, account) => {
24149
24149
  ];
24150
24150
  return calls;
24151
24151
  };
24152
+
24153
+ // src/utils/constants.ts
24154
+ var MULTICALL_DEFAULT_BATCH_SIZE = 4096;
24155
+ var CELO_MULTICALL_ADDRESS = "0x633987602DE5C4F337e3DbF265303A1080324204";
24156
+ var BNB_MULTICALL_ADDRESS = "0x963Df249eD09c358A4819E39d9Cd5736c3087184";
24157
+ var MANTLE_MULTICALL_ADDRESS = "0x2A51f2F647E1883F88C992244dEd171238693107";
24158
+ var ARBITRUM_ONE_MULTICALL_ADDRESS = "0xadF885960B47eA2CD9B55E6DAc6B42b7Cb2806dB";
24159
+ var LINEA_MULTICALL_ADDRESS = "0xac1cE734566f390A94b00eb9bf561c2625BF44ea";
24160
+ var AVALANCHE_MULTICALL_ADDRESS = "0x0139141Cd4Ee88dF3Cdb65881D411bAE271Ef0C2";
24161
+ var BASE_MULTICALL_ADDRESS = "0x091e99cb1C49331a94dD62755D168E941AbD0693";
24162
+ var BLAST_MULTICALL_ADDRESS = "0xdC7f370de7631cE9e2c2e1DCDA6B3B5744Cf4705";
24163
+ var TAIKO_MULTICALL_ADDRESS = "0x8E24CfC19c6C00c524353CB8816f5f1c2F33c201";
24164
+ var HEMI_MULTICALL_ADDRESS = "0x352A86168e6988A1aDF9A15Cb00017AAd3B67155";
24165
+ var GNOSIS_MULTICALL_ADDRESS = "0x4dfa9a980efE4802E969AC33968E3d6E59B8a19e";
24166
+ var MODE_MULTICALL_ADDRESS = "0xAB39cE30D98a59DFDa40A630b074170800bfF179";
24167
+ var FANTOM_MULTICALL_ADDRESS = "0xDb51CffFf3B989d0cB6b58AbF173371b6F2d0D24";
24168
+ var SCROLL_MULTICALL_ADDRESS = "0x3b615B1AC55bc34e51a81D3dea67467F32bcb8C2";
24169
+ var SHAPE_MULTICALL_ADDRESS = "0x356A450B32f5030ae7083702b86FaFbBe7490411";
24170
+ var SONIC_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
24171
+ var INK_MULTICALL_ADDRESS = "0xA0fCec583AeE6176527C07B198e5561722332014";
24172
+ var METIS_MULTICALL_ADDRESS = "0x7a59ddbB76521E8982Fa3A08598C9a83b14A6C07";
24173
+ var IOTA_MULTICALL_ADDRESS = "0x9683D433621A83aA7dd290106e1da85251317F55";
24174
+ var KAVA_MULTICALL_ADDRESS = "0x8B741B0D79BE80E135C880F7583d427B4D41F015";
24175
+ var CORN_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
24176
+ var SAGA_MULTICALL_ADDRESS = "0x743E03cceB4af2efA3CC76838f6E8B50B63F184c";
24177
+ var CYBER_MULTICALL_ADDRESS = "0x906d6eB9CF8f64e100e44f8f491b833a8d40B530";
24178
+ var METAL_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
24179
+ var ZERO_MULTICALL_ADDRESS = "0x9CA4dcb2505fbf536F6c54AA0a77C79f4fBC35C0";
24180
+ var BOB_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
24181
+ var WORLDCHAIN_MULTICALL_ADDRESS = "0x0a22c04215c97E3F532F4eF30e0aD9458792dAB9";
24182
+ var LISK_MULTICALL_ADDRESS = "0xE3dbcD53f4Ce1b06Ab200f4912BD35672e68f1FA";
24183
+ var REDSTONE_MULTICALL_ADDRESS = "0xd57B52452a0FDfE3ff8e0A40Bd10D00D0bfe0723";
24184
+ var MANTA_MULTICALL_ADDRESS = "0x52dFC0D9960F11A9Ca9FF616e791B91188446a60";
24185
+ var ZORA_MULTICALL_ADDRESS = "0xA51c76bEE6746cB487a7e9312E43e2b8f4A37C15";
24186
+ var CORE_MULTICALL_ADDRESS = "0xFe9F82D820757787895Da00B1dBD35c3B8b04894";
24187
+ var MORPH_MULTICALL_ADDRESS = "0xAcD82113982479B25E7c1D09858F0130921Dbbca";
24188
+ var TELOS_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
24189
+ var MULTICALL_ADDRESS = {
24190
+ [Chain.OP_MAINNET]: "0x1F98415757620B543A52E61c46B32eB19261F984",
24191
+ [Chain.POLYGON_MAINNET]: "0x1F98415757620B543A52E61c46B32eB19261F984",
24192
+ [Chain.ETHEREUM_MAINNET]: "0x1F98415757620B543A52E61c46B32eB19261F984",
24193
+ [Chain.ARBITRUM_ONE]: ARBITRUM_ONE_MULTICALL_ADDRESS,
24194
+ [Chain.BASE]: BASE_MULTICALL_ADDRESS,
24195
+ [Chain.CELO_MAINNET]: CELO_MULTICALL_ADDRESS,
24196
+ [Chain.BNB_SMART_CHAIN_MAINNET]: BNB_MULTICALL_ADDRESS,
24197
+ [Chain.MANTLE]: MANTLE_MULTICALL_ADDRESS,
24198
+ [Chain.BLAST]: BLAST_MULTICALL_ADDRESS,
24199
+ [Chain.LINEA]: LINEA_MULTICALL_ADDRESS,
24200
+ [Chain.AVALANCHE_C_CHAIN]: AVALANCHE_MULTICALL_ADDRESS,
24201
+ [Chain.TAIKO_ALETHIA]: TAIKO_MULTICALL_ADDRESS,
24202
+ [Chain.HEMI_NETWORK]: HEMI_MULTICALL_ADDRESS,
24203
+ [Chain.GNOSIS]: GNOSIS_MULTICALL_ADDRESS,
24204
+ [Chain.CORE_BLOCKCHAIN_MAINNET]: CORE_MULTICALL_ADDRESS,
24205
+ [Chain.METIS_ANDROMEDA_MAINNET]: METIS_MULTICALL_ADDRESS,
24206
+ [Chain.MODE]: MODE_MULTICALL_ADDRESS,
24207
+ [Chain.INK]: INK_MULTICALL_ADDRESS,
24208
+ [Chain.IOTA_EVM]: IOTA_MULTICALL_ADDRESS,
24209
+ [Chain.CORN]: CORN_MULTICALL_ADDRESS,
24210
+ [Chain.SONIC_MAINNET]: SONIC_MULTICALL_ADDRESS,
24211
+ [Chain.FANTOM_OPERA]: FANTOM_MULTICALL_ADDRESS,
24212
+ [Chain.SCROLL]: SCROLL_MULTICALL_ADDRESS,
24213
+ [Chain.SHAPE]: SHAPE_MULTICALL_ADDRESS,
24214
+ [Chain.CYBER_MAINNET]: CYBER_MULTICALL_ADDRESS,
24215
+ [Chain.ZORA]: ZORA_MULTICALL_ADDRESS,
24216
+ [Chain.MANTA_PACIFIC_MAINNET]: MANTA_MULTICALL_ADDRESS,
24217
+ [Chain.REDSTONE]: REDSTONE_MULTICALL_ADDRESS,
24218
+ [Chain.KAVA]: KAVA_MULTICALL_ADDRESS,
24219
+ [Chain.METAL_L2]: METAL_MULTICALL_ADDRESS,
24220
+ [Chain.LISK]: LISK_MULTICALL_ADDRESS,
24221
+ [Chain.BOB]: BOB_MULTICALL_ADDRESS,
24222
+ [Chain.ZERO_NETWORK]: ZERO_MULTICALL_ADDRESS,
24223
+ [Chain.SAGA]: SAGA_MULTICALL_ADDRESS,
24224
+ [Chain.MORPH]: MORPH_MULTICALL_ADDRESS,
24225
+ [Chain.TELOS_EVM_MAINNET]: TELOS_MULTICALL_ADDRESS,
24226
+ [Chain.WORLD_CHAIN]: WORLDCHAIN_MULTICALL_ADDRESS
24227
+ };
24228
+
24229
+ // src/utils/multicall.ts
24230
+ var { isArray } = lodash;
24231
+ var maxRetries = 3;
24232
+ var MULTICALL_FAILURE = "0x";
24233
+ var isFailedCall = (value) => value === void 0 || value === null || value === MULTICALL_FAILURE;
24234
+ var retryFailedSlots = async (chainId, contracts, mapped, getEvmClient18, nextRpcId, batchSize, logs) => {
24235
+ const failedIdx = [];
24236
+ for (let i = 0; i < mapped.length; i++) {
24237
+ if (isFailedCall(mapped[i])) failedIdx.push(i);
24238
+ }
24239
+ if (failedIdx.length === 0) return mapped;
24240
+ try {
24241
+ const provider = getEvmClient18(chainId, nextRpcId);
24242
+ const returnData = await provider.multicall({
24243
+ allowFailure: true,
24244
+ batchSize,
24245
+ contracts: failedIdx.map((i) => contracts[i])
24246
+ });
24247
+ returnData.forEach((entry, k) => {
24248
+ if (entry?.status === "success") mapped[failedIdx[k]] = entry.result;
24249
+ });
24250
+ } catch (error) {
24251
+ if (logs) console.log("error in multicall failure-retry", error);
24252
+ }
24253
+ return mapped;
24254
+ };
24255
+ var multicallViemAbiArray = async (chainId, abi, calls, getEvmClient18, retry = true, providerId = 0, retries = maxRetries, allowFailure = true, batchSize = MULTICALL_DEFAULT_BATCH_SIZE, logs = false, retryFailed = false) => {
24256
+ try {
24257
+ const provider = getEvmClient18(chainId, providerId);
24258
+ const abiIsArray = isArray(abi[0]);
24259
+ const contracts = calls.map(({ address, name, params }, i) => ({
24260
+ abi: abiIsArray ? abi?.[i] : abi,
24261
+ address,
24262
+ functionName: name,
24263
+ args: params
24264
+ }));
24265
+ const returnData = await provider.multicall({
24266
+ allowFailure,
24267
+ batchSize,
24268
+ contracts
24269
+ });
24270
+ if (!allowFailure) return returnData;
24271
+ const res = returnData.map(
24272
+ ({ result, status }) => status !== "success" ? MULTICALL_FAILURE : result
24273
+ );
24274
+ if (!retryFailed) return res;
24275
+ return retryFailedSlots(
24276
+ chainId,
24277
+ contracts,
24278
+ res,
24279
+ getEvmClient18,
24280
+ providerId + 1,
24281
+ batchSize,
24282
+ logs
24283
+ );
24284
+ } catch (error) {
24285
+ if (logs) console.log("error in multicall", error);
24286
+ retries--;
24287
+ if (retries < 0) throw new Error("Failed too often");
24288
+ providerId++;
24289
+ return multicallViemAbiArray(
24290
+ chainId,
24291
+ abi,
24292
+ calls,
24293
+ getEvmClient18,
24294
+ retry,
24295
+ providerId,
24296
+ retries,
24297
+ allowFailure,
24298
+ batchSize,
24299
+ logs,
24300
+ retryFailed
24301
+ );
24302
+ }
24303
+ };
24304
+ var multicallShardedAbiArray = async (chainId, abi, calls, getEvmClient18, poolSize, retries = maxRetries, allowFailure = true, batchSize = MULTICALL_DEFAULT_BATCH_SIZE, logs = false, retryFailed = false) => {
24305
+ if (poolSize <= 1) {
24306
+ return multicallViemAbiArray(
24307
+ chainId,
24308
+ abi,
24309
+ calls,
24310
+ getEvmClient18,
24311
+ true,
24312
+ 0,
24313
+ retries,
24314
+ allowFailure,
24315
+ batchSize,
24316
+ logs,
24317
+ retryFailed
24318
+ );
24319
+ }
24320
+ const abiIsArray = isArray(abi[0]);
24321
+ const contracts = calls.map(({ address, name, params }, i) => ({
24322
+ abi: abiIsArray ? abi?.[i] : abi,
24323
+ address,
24324
+ functionName: name,
24325
+ args: params
24326
+ }));
24327
+ const shardSize = Math.max(1, Math.ceil(contracts.length / poolSize));
24328
+ const batches = [];
24329
+ for (let i = 0; i < contracts.length; i += shardSize) {
24330
+ batches.push({ start: i, items: contracts.slice(i, i + shardSize) });
24331
+ }
24332
+ const results = new Array(contracts.length);
24333
+ const runBatch = async (batch, rpcId, attemptsLeft, size) => {
24334
+ try {
24335
+ const provider = getEvmClient18(chainId, rpcId);
24336
+ const returnData = await provider.multicall({
24337
+ allowFailure,
24338
+ batchSize: size,
24339
+ contracts: batch.items
24340
+ });
24341
+ let mapped = allowFailure ? returnData.map(
24342
+ ({ result, status }) => status !== "success" ? MULTICALL_FAILURE : result
24343
+ ) : returnData;
24344
+ if (allowFailure && retryFailed) {
24345
+ mapped = await retryFailedSlots(
24346
+ chainId,
24347
+ batch.items,
24348
+ mapped,
24349
+ getEvmClient18,
24350
+ rpcId + 1,
24351
+ size,
24352
+ logs
24353
+ );
24354
+ }
24355
+ for (let j = 0; j < mapped.length; j++) {
24356
+ results[batch.start + j] = mapped[j];
24357
+ }
24358
+ } catch (error) {
24359
+ if (logs) console.log("error in sharded multicall batch", error);
24360
+ if (attemptsLeft <= 0) throw error;
24361
+ return runBatch(
24362
+ batch,
24363
+ rpcId + 1,
24364
+ attemptsLeft - 1,
24365
+ Math.max(1, Math.floor(size / 2))
24366
+ );
24367
+ }
24368
+ };
24369
+ const workers = Math.max(1, Math.min(poolSize, batches.length));
24370
+ let cursor = 0;
24371
+ const worker = async (workerId) => {
24372
+ while (true) {
24373
+ const idx = cursor++;
24374
+ if (idx >= batches.length) break;
24375
+ await runBatch(batches[idx], workerId, retries, batchSize);
24376
+ }
24377
+ };
24378
+ await Promise.all(Array.from({ length: workers }, (_3, w) => worker(w)));
24379
+ return results;
24380
+ };
24381
+ function prepareMulticallInputs(abi, calls) {
24382
+ const abiIsArray = isArray(abi[0]);
24383
+ return calls.map(({ address, name, params }, i) => ({
24384
+ address,
24385
+ functionName: name,
24386
+ params: params || [],
24387
+ abi: abiIsArray ? abi[i] : abi
24388
+ }));
24389
+ }
24152
24390
  var getCompoundV2UserDataConverter = (lender, chainId, account, metaMap) => {
24153
24391
  switch (lender) {
24154
24392
  default: {
@@ -24203,10 +24441,15 @@ var getCompoundV2UserDataConverter = (lender, chainId, account, metaMap) => {
24203
24441
  }
24204
24442
  };
24205
24443
  function createCompoundV2Entry(i, data, key, assetsIn, vToken, meta, claimableRewards) {
24206
- const _depositsRaw = data[3 * i].toString();
24207
- const _borrowsRaw = data[3 * i + 1].toString();
24208
- const depositsRaw = _depositsRaw === "0x" ? "0" : _depositsRaw;
24209
- const borrowsRaw = _borrowsRaw === "0x" ? "0" : _borrowsRaw;
24444
+ if (isFailedCall(data[3 * i]) || isFailedCall(data[3 * i + 1])) {
24445
+ return {
24446
+ dataForAsset: void 0,
24447
+ addedDeposits: 0,
24448
+ addedDebt: 0
24449
+ };
24450
+ }
24451
+ const depositsRaw = data[3 * i].toString();
24452
+ const borrowsRaw = data[3 * i + 1].toString();
24210
24453
  const depositShares = data[3 * i + 2].toString();
24211
24454
  const collateralEnabled = Boolean(assetsIn?.includes(vToken));
24212
24455
  if (!collateralEnabled && depositsRaw === "0" && borrowsRaw === "0") {
@@ -25143,6 +25386,9 @@ var getAaveV2UserDataConverter = (lender, chainId, account, metaMap) => {
25143
25386
  };
25144
25387
  function createAaveV2Entry(i, data, key, meta, claimableRewards) {
25145
25388
  const reserveData = data[i];
25389
+ if (isFailedCall(reserveData)) {
25390
+ return { dataForAsset: void 0, addedDeposits: 0, addedDebt: 0 };
25391
+ }
25146
25392
  const currentATokenBalanceRaw = reserveData[0 /* currentATokenBalance */]?.toString();
25147
25393
  const currentStableDebtRaw = reserveData[1 /* currentStableDebt */]?.toString();
25148
25394
  const currentVariableDebtRaw = reserveData[2 /* currentVariableDebt */]?.toString();
@@ -25236,6 +25482,9 @@ var getAaveV3UserDataConverter = (lender, chainId, account, metaMap) => {
25236
25482
  };
25237
25483
  function createAaveV3Entry(i, data, key, meta) {
25238
25484
  const reserveData = data[i];
25485
+ if (isFailedCall(reserveData)) {
25486
+ return { dataForAsset: void 0, addedDeposits: 0, addedDebt: 0 };
25487
+ }
25239
25488
  const currentATokenBalanceRaw = reserveData[0 /* currentATokenBalance */]?.toString();
25240
25489
  const currentStableDebtRaw = reserveData[1 /* currentStableDebt */]?.toString();
25241
25490
  const currentVariableDebtRaw = reserveData[2 /* currentVariableDebt */]?.toString();
@@ -25279,6 +25528,9 @@ function createAaveV3Entry(i, data, key, meta) {
25279
25528
  };
25280
25529
  }
25281
25530
  function parseSingleBrokerData(data, validOwner, brokerAddress, lender, chainId, metaMap) {
25531
+ if (isFailedCall(data)) {
25532
+ return { result: {}, modes: {}, histData: {} };
25533
+ }
25282
25534
  const indexes = data[0 /* posMeta */].map((e, i) => ({ e, i })).filter((a) => a.e.owner.toLowerCase() === validOwner).map((a) => a.i);
25283
25535
  const histData = {};
25284
25536
  const modes = {};
@@ -25435,6 +25687,7 @@ var getCompoundV3UserDataConverter = (lender, chainId, account, metaMap) => {
25435
25687
  const metaEntity2 = metaMap?.[key2];
25436
25688
  const assetMeta = metaEntity2.asset;
25437
25689
  const decimals = assetMeta?.decimals ?? 18;
25690
+ if (isFailedCall(data[i])) continue;
25438
25691
  const depositsRaw2 = data[i][0]?.toString();
25439
25692
  if (depositsRaw2 === "0") continue;
25440
25693
  const deposits2 = parseRawAmount(depositsRaw2, decimals);
@@ -25457,20 +25710,21 @@ var getCompoundV3UserDataConverter = (lender, chainId, account, metaMap) => {
25457
25710
  collateralEnabled: true
25458
25711
  };
25459
25712
  }
25713
+ const baseFailed = isFailedCall(data[assetsNoBase.length]) || isFailedCall(data[assetsNoBase.length + 1]);
25460
25714
  const depositsRaw = data[assetsNoBase.length]?.toString();
25461
25715
  const debtRaw = data[assetsNoBase.length + 1]?.toString();
25462
25716
  const key = createMarketUid(chainId, lender, baseAsset);
25463
25717
  const metaEntity = metaMap?.[key];
25464
25718
  const baseMeta = metaEntity.asset;
25465
25719
  const baseDecimals = baseMeta.decimals ?? 18;
25466
- const deposits = parseRawAmount(depositsRaw, baseDecimals);
25467
- const debt = parseRawAmount(debtRaw, baseDecimals);
25720
+ const deposits = baseFailed ? "0" : parseRawAmount(depositsRaw, baseDecimals);
25721
+ const debt = baseFailed ? "0" : parseRawAmount(debtRaw, baseDecimals);
25468
25722
  const price2 = getDisplayPrice(metaEntity);
25469
25723
  const oPrice = getOraclePrice(metaEntity);
25470
25724
  const priceHist = metaEntity?.price?.priceUsd24h ?? price2;
25471
25725
  totalDebt24h += Number(debt) * priceHist;
25472
25726
  totalDeposits24h += Number(deposits) * priceHist;
25473
- const resultBase = depositsRaw === "0" && debtRaw === "0" ? {} : {
25727
+ const resultBase = baseFailed || depositsRaw === "0" && debtRaw === "0" ? {} : {
25474
25728
  [key]: {
25475
25729
  marketUid: key,
25476
25730
  underlying: baseAsset,
@@ -25564,6 +25818,9 @@ var getYldrUserDataConverter = (lender, chainId, account, metaMap) => {
25564
25818
  };
25565
25819
  function createAaveV3Entry2(i, data, key, meta) {
25566
25820
  const reserveData = data[i];
25821
+ if (isFailedCall(reserveData)) {
25822
+ return { dataForAsset: void 0, addedDeposits: 0, addedDebt: 0 };
25823
+ }
25567
25824
  const currentATokenBalanceRaw = reserveData[0 /* currentYTokenBalance */]?.toString();
25568
25825
  const currentVariableDebtRaw = reserveData[1 /* currentVariableDebt */]?.toString();
25569
25826
  if (currentATokenBalanceRaw === "0" && currentVariableDebtRaw === "0") {
@@ -26223,7 +26480,7 @@ var getEulerUserDataConverter = (lender, chainId, account, metaMap, subAccountIn
26223
26480
  const histData = {};
26224
26481
  for (let idx = 0; idx < sortedIndices.length; idx++) {
26225
26482
  const result = _data[idx];
26226
- if (!result) continue;
26483
+ if (isFailedCall(result) || !result) continue;
26227
26484
  const evcInfo = result.evcAccountInfo ?? result[0];
26228
26485
  const vaultAccounts = result.vaultAccountInfo ?? result[1] ?? [];
26229
26486
  const subAccountId = String(sortedIndices[idx]);
@@ -27205,6 +27462,7 @@ var getDolomiteUserDataConverter = (lender, chainId, account, metaMap) => {
27205
27462
  const lendingPositions = {};
27206
27463
  const modes = {};
27207
27464
  _data.forEach((res, i) => {
27465
+ if (isFailedCall(res)) return;
27208
27466
  const id = numbers[i];
27209
27467
  histData[id] = { totalDebt24h: 0, totalDeposits24h: 0 };
27210
27468
  lendingPositions[id] = {};
@@ -27929,6 +28187,7 @@ var getRiverUserDataConverter = (lender, chainId, account, meta) => {
27929
28187
  markets.forEach((market, i) => {
27930
28188
  const base = i * RIVER_CALLS_PER_MARKET;
27931
28189
  const entire = data[base];
28190
+ if (isFailedCall(entire) || isFailedCall(data[base + 1])) return;
27932
28191
  const status = Number(big2(data[base + 1]));
27933
28192
  const surplus = big2(data[base + 2]);
27934
28193
  const lenderKey = riverLenderKey(lender, chainId, market.index);
@@ -28065,7 +28324,7 @@ var getTellerUserDataConverter = (_lender, chainId, account, meta) => {
28065
28324
  const owed = data[base + 1];
28066
28325
  const collAmount = big3(data[base + 2]);
28067
28326
  const defaulted = !!data[base + 3];
28068
- if (!bidRes) return;
28327
+ if (isFailedCall(bidRes) || isFailedCall(owed) || !bidRes) return;
28069
28328
  const pool = b.pool;
28070
28329
  const lenderKey = tellerLenderKey(pool.pool);
28071
28330
  const metaMap = meta?.[lenderKey];
@@ -28090,7 +28349,9 @@ var getTellerUserDataConverter = (_lender, chainId, account, meta) => {
28090
28349
  if (owedTotal === 0n && collAmount === 0n) return;
28091
28350
  const loanDetails = field8(bidRes, "loanDetails", 5);
28092
28351
  const terms = field8(bidRes, "terms", 6);
28093
- const acceptedTs = Number(big3(field8(loanDetails, "acceptedTimestamp", 4)));
28352
+ const acceptedTs = Number(
28353
+ big3(field8(loanDetails, "acceptedTimestamp", 4))
28354
+ );
28094
28355
  const loanDuration = Number(big3(field8(loanDetails, "loanDuration", 6)));
28095
28356
  const aprBps = Number(big3(field8(terms, "APR", 2)));
28096
28357
  const maturity = acceptedTs > 0 ? acceptedTs + loanDuration : void 0;
@@ -28263,7 +28524,7 @@ var filterEmptyUserData = (userData, keepActiveControllerMode = false) => {
28263
28524
  if (filteredData.length === 0) return null;
28264
28525
  return { ...userData, data: filteredData };
28265
28526
  };
28266
- var convertLenderUserDataResult = (chainId, queriesRaw, rawResults, lenderState) => {
28527
+ var convertLenderUserDataResult = (chainId, queriesRaw, rawResults, lenderState, options) => {
28267
28528
  const queries = organizeUserQueries(queriesRaw);
28268
28529
  const lenderData = {};
28269
28530
  let currentSlice = 0;
@@ -28277,6 +28538,21 @@ var convertLenderUserDataResult = (chainId, queriesRaw, rawResults, lenderState)
28277
28538
  );
28278
28539
  try {
28279
28540
  const data = rawResults.slice(currentSlice, currentSlice + sliceLength);
28541
+ let failedCalls = 0;
28542
+ for (const entry of data) if (isFailedCall(entry)) failedCalls++;
28543
+ const allFailed = data.length > 0 && failedCalls === data.length;
28544
+ if (failedCalls > 0) {
28545
+ options?.onIncomplete?.({
28546
+ lender: query3.lender,
28547
+ failedCalls,
28548
+ totalCalls: data.length,
28549
+ dropped: allFailed
28550
+ });
28551
+ }
28552
+ if (allFailed) {
28553
+ currentSlice += sliceLength;
28554
+ continue;
28555
+ }
28280
28556
  const convertedData = converter(data);
28281
28557
  if (convertedData) {
28282
28558
  if (isMultiMarket(query3.lender)) {
@@ -28284,6 +28560,7 @@ var convertLenderUserDataResult = (chainId, queriesRaw, rawResults, lenderState)
28284
28560
  const filtered = filterEmptyUserData(convertedData[market]);
28285
28561
  if (filtered) {
28286
28562
  filtered.lender = market;
28563
+ if (failedCalls > 0) filtered.incomplete = true;
28287
28564
  lenderData[market] = filtered;
28288
28565
  }
28289
28566
  });
@@ -28296,6 +28573,7 @@ var convertLenderUserDataResult = (chainId, queriesRaw, rawResults, lenderState)
28296
28573
  );
28297
28574
  if (filtered) {
28298
28575
  filtered.lender = query3.lender;
28576
+ if (failedCalls > 0) filtered.incomplete = true;
28299
28577
  lenderData[query3.lender] = filtered;
28300
28578
  }
28301
28579
  }
@@ -28307,199 +28585,6 @@ var convertLenderUserDataResult = (chainId, queriesRaw, rawResults, lenderState)
28307
28585
  return lenderData;
28308
28586
  };
28309
28587
 
28310
- // src/utils/constants.ts
28311
- var MULTICALL_DEFAULT_BATCH_SIZE = 4096;
28312
- var CELO_MULTICALL_ADDRESS = "0x633987602DE5C4F337e3DbF265303A1080324204";
28313
- var BNB_MULTICALL_ADDRESS = "0x963Df249eD09c358A4819E39d9Cd5736c3087184";
28314
- var MANTLE_MULTICALL_ADDRESS = "0x2A51f2F647E1883F88C992244dEd171238693107";
28315
- var ARBITRUM_ONE_MULTICALL_ADDRESS = "0xadF885960B47eA2CD9B55E6DAc6B42b7Cb2806dB";
28316
- var LINEA_MULTICALL_ADDRESS = "0xac1cE734566f390A94b00eb9bf561c2625BF44ea";
28317
- var AVALANCHE_MULTICALL_ADDRESS = "0x0139141Cd4Ee88dF3Cdb65881D411bAE271Ef0C2";
28318
- var BASE_MULTICALL_ADDRESS = "0x091e99cb1C49331a94dD62755D168E941AbD0693";
28319
- var BLAST_MULTICALL_ADDRESS = "0xdC7f370de7631cE9e2c2e1DCDA6B3B5744Cf4705";
28320
- var TAIKO_MULTICALL_ADDRESS = "0x8E24CfC19c6C00c524353CB8816f5f1c2F33c201";
28321
- var HEMI_MULTICALL_ADDRESS = "0x352A86168e6988A1aDF9A15Cb00017AAd3B67155";
28322
- var GNOSIS_MULTICALL_ADDRESS = "0x4dfa9a980efE4802E969AC33968E3d6E59B8a19e";
28323
- var MODE_MULTICALL_ADDRESS = "0xAB39cE30D98a59DFDa40A630b074170800bfF179";
28324
- var FANTOM_MULTICALL_ADDRESS = "0xDb51CffFf3B989d0cB6b58AbF173371b6F2d0D24";
28325
- var SCROLL_MULTICALL_ADDRESS = "0x3b615B1AC55bc34e51a81D3dea67467F32bcb8C2";
28326
- var SHAPE_MULTICALL_ADDRESS = "0x356A450B32f5030ae7083702b86FaFbBe7490411";
28327
- var SONIC_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
28328
- var INK_MULTICALL_ADDRESS = "0xA0fCec583AeE6176527C07B198e5561722332014";
28329
- var METIS_MULTICALL_ADDRESS = "0x7a59ddbB76521E8982Fa3A08598C9a83b14A6C07";
28330
- var IOTA_MULTICALL_ADDRESS = "0x9683D433621A83aA7dd290106e1da85251317F55";
28331
- var KAVA_MULTICALL_ADDRESS = "0x8B741B0D79BE80E135C880F7583d427B4D41F015";
28332
- var CORN_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
28333
- var SAGA_MULTICALL_ADDRESS = "0x743E03cceB4af2efA3CC76838f6E8B50B63F184c";
28334
- var CYBER_MULTICALL_ADDRESS = "0x906d6eB9CF8f64e100e44f8f491b833a8d40B530";
28335
- var METAL_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
28336
- var ZERO_MULTICALL_ADDRESS = "0x9CA4dcb2505fbf536F6c54AA0a77C79f4fBC35C0";
28337
- var BOB_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
28338
- var WORLDCHAIN_MULTICALL_ADDRESS = "0x0a22c04215c97E3F532F4eF30e0aD9458792dAB9";
28339
- var LISK_MULTICALL_ADDRESS = "0xE3dbcD53f4Ce1b06Ab200f4912BD35672e68f1FA";
28340
- var REDSTONE_MULTICALL_ADDRESS = "0xd57B52452a0FDfE3ff8e0A40Bd10D00D0bfe0723";
28341
- var MANTA_MULTICALL_ADDRESS = "0x52dFC0D9960F11A9Ca9FF616e791B91188446a60";
28342
- var ZORA_MULTICALL_ADDRESS = "0xA51c76bEE6746cB487a7e9312E43e2b8f4A37C15";
28343
- var CORE_MULTICALL_ADDRESS = "0xFe9F82D820757787895Da00B1dBD35c3B8b04894";
28344
- var MORPH_MULTICALL_ADDRESS = "0xAcD82113982479B25E7c1D09858F0130921Dbbca";
28345
- var TELOS_MULTICALL_ADDRESS = "0x5d6b0f5335ec95cD2aB7E52f2A0750dd86502435";
28346
- var MULTICALL_ADDRESS = {
28347
- [Chain.OP_MAINNET]: "0x1F98415757620B543A52E61c46B32eB19261F984",
28348
- [Chain.POLYGON_MAINNET]: "0x1F98415757620B543A52E61c46B32eB19261F984",
28349
- [Chain.ETHEREUM_MAINNET]: "0x1F98415757620B543A52E61c46B32eB19261F984",
28350
- [Chain.ARBITRUM_ONE]: ARBITRUM_ONE_MULTICALL_ADDRESS,
28351
- [Chain.BASE]: BASE_MULTICALL_ADDRESS,
28352
- [Chain.CELO_MAINNET]: CELO_MULTICALL_ADDRESS,
28353
- [Chain.BNB_SMART_CHAIN_MAINNET]: BNB_MULTICALL_ADDRESS,
28354
- [Chain.MANTLE]: MANTLE_MULTICALL_ADDRESS,
28355
- [Chain.BLAST]: BLAST_MULTICALL_ADDRESS,
28356
- [Chain.LINEA]: LINEA_MULTICALL_ADDRESS,
28357
- [Chain.AVALANCHE_C_CHAIN]: AVALANCHE_MULTICALL_ADDRESS,
28358
- [Chain.TAIKO_ALETHIA]: TAIKO_MULTICALL_ADDRESS,
28359
- [Chain.HEMI_NETWORK]: HEMI_MULTICALL_ADDRESS,
28360
- [Chain.GNOSIS]: GNOSIS_MULTICALL_ADDRESS,
28361
- [Chain.CORE_BLOCKCHAIN_MAINNET]: CORE_MULTICALL_ADDRESS,
28362
- [Chain.METIS_ANDROMEDA_MAINNET]: METIS_MULTICALL_ADDRESS,
28363
- [Chain.MODE]: MODE_MULTICALL_ADDRESS,
28364
- [Chain.INK]: INK_MULTICALL_ADDRESS,
28365
- [Chain.IOTA_EVM]: IOTA_MULTICALL_ADDRESS,
28366
- [Chain.CORN]: CORN_MULTICALL_ADDRESS,
28367
- [Chain.SONIC_MAINNET]: SONIC_MULTICALL_ADDRESS,
28368
- [Chain.FANTOM_OPERA]: FANTOM_MULTICALL_ADDRESS,
28369
- [Chain.SCROLL]: SCROLL_MULTICALL_ADDRESS,
28370
- [Chain.SHAPE]: SHAPE_MULTICALL_ADDRESS,
28371
- [Chain.CYBER_MAINNET]: CYBER_MULTICALL_ADDRESS,
28372
- [Chain.ZORA]: ZORA_MULTICALL_ADDRESS,
28373
- [Chain.MANTA_PACIFIC_MAINNET]: MANTA_MULTICALL_ADDRESS,
28374
- [Chain.REDSTONE]: REDSTONE_MULTICALL_ADDRESS,
28375
- [Chain.KAVA]: KAVA_MULTICALL_ADDRESS,
28376
- [Chain.METAL_L2]: METAL_MULTICALL_ADDRESS,
28377
- [Chain.LISK]: LISK_MULTICALL_ADDRESS,
28378
- [Chain.BOB]: BOB_MULTICALL_ADDRESS,
28379
- [Chain.ZERO_NETWORK]: ZERO_MULTICALL_ADDRESS,
28380
- [Chain.SAGA]: SAGA_MULTICALL_ADDRESS,
28381
- [Chain.MORPH]: MORPH_MULTICALL_ADDRESS,
28382
- [Chain.TELOS_EVM_MAINNET]: TELOS_MULTICALL_ADDRESS,
28383
- [Chain.WORLD_CHAIN]: WORLDCHAIN_MULTICALL_ADDRESS
28384
- };
28385
-
28386
- // src/utils/multicall.ts
28387
- var { isArray } = lodash;
28388
- var maxRetries = 3;
28389
- var multicallViemAbiArray = async (chainId, abi, calls, getEvmClient18, retry = true, providerId = 0, retries = maxRetries, allowFailure = true, batchSize = MULTICALL_DEFAULT_BATCH_SIZE, logs = false) => {
28390
- try {
28391
- const provider = getEvmClient18(chainId, providerId);
28392
- const abiIsArray = isArray(abi[0]);
28393
- const returnData = await provider.multicall({
28394
- allowFailure,
28395
- batchSize,
28396
- contracts: calls.map(({ address, name, params }, i) => ({
28397
- abi: abiIsArray ? abi?.[i] : abi,
28398
- address,
28399
- functionName: name,
28400
- args: params
28401
- }))
28402
- });
28403
- if (!allowFailure) return returnData;
28404
- const res = returnData.map(
28405
- ({ result, status }) => status !== "success" ? "0x" : result
28406
- );
28407
- return res;
28408
- } catch (error) {
28409
- if (logs) console.log("error in multicall", error);
28410
- retries--;
28411
- if (retries < 0) throw new Error("Failed too often");
28412
- providerId++;
28413
- return multicallViemAbiArray(
28414
- chainId,
28415
- abi,
28416
- calls,
28417
- getEvmClient18,
28418
- retry,
28419
- providerId,
28420
- retries,
28421
- allowFailure,
28422
- batchSize,
28423
- logs
28424
- );
28425
- }
28426
- };
28427
- var multicallShardedAbiArray = async (chainId, abi, calls, getEvmClient18, poolSize, retries = maxRetries, allowFailure = true, batchSize = MULTICALL_DEFAULT_BATCH_SIZE, logs = false) => {
28428
- if (poolSize <= 1) {
28429
- return multicallViemAbiArray(
28430
- chainId,
28431
- abi,
28432
- calls,
28433
- getEvmClient18,
28434
- true,
28435
- 0,
28436
- retries,
28437
- allowFailure,
28438
- batchSize,
28439
- logs
28440
- );
28441
- }
28442
- const abiIsArray = isArray(abi[0]);
28443
- const contracts = calls.map(({ address, name, params }, i) => ({
28444
- abi: abiIsArray ? abi?.[i] : abi,
28445
- address,
28446
- functionName: name,
28447
- args: params
28448
- }));
28449
- const batches = [];
28450
- for (let i = 0; i < contracts.length; i += batchSize) {
28451
- batches.push({ start: i, items: contracts.slice(i, i + batchSize) });
28452
- }
28453
- const results = new Array(contracts.length);
28454
- const runBatch = async (batch, rpcId, attemptsLeft, size) => {
28455
- try {
28456
- const provider = getEvmClient18(chainId, rpcId);
28457
- const returnData = await provider.multicall({
28458
- allowFailure,
28459
- batchSize: size,
28460
- contracts: batch.items
28461
- });
28462
- const mapped = allowFailure ? returnData.map(
28463
- ({ result, status }) => status !== "success" ? "0x" : result
28464
- ) : returnData;
28465
- for (let j = 0; j < mapped.length; j++) {
28466
- results[batch.start + j] = mapped[j];
28467
- }
28468
- } catch (error) {
28469
- if (logs) console.log("error in sharded multicall batch", error);
28470
- if (attemptsLeft <= 0) throw error;
28471
- return runBatch(
28472
- batch,
28473
- rpcId + 1,
28474
- attemptsLeft - 1,
28475
- Math.max(1, Math.floor(size / 2))
28476
- );
28477
- }
28478
- };
28479
- const workers = Math.max(1, Math.min(poolSize, batches.length));
28480
- let cursor = 0;
28481
- const worker = async (workerId) => {
28482
- while (true) {
28483
- const idx = cursor++;
28484
- if (idx >= batches.length) break;
28485
- await runBatch(batches[idx], workerId, retries, batchSize);
28486
- }
28487
- };
28488
- await Promise.all(
28489
- Array.from({ length: workers }, (_3, w) => worker(w))
28490
- );
28491
- return results;
28492
- };
28493
- function prepareMulticallInputs(abi, calls) {
28494
- const abiIsArray = isArray(abi[0]);
28495
- return calls.map(({ address, name, params }, i) => ({
28496
- address,
28497
- functionName: name,
28498
- params: params || [],
28499
- abi: abiIsArray ? abi[i] : abi
28500
- }));
28501
- }
28502
-
28503
28588
  // src/utils/rpcCall.ts
28504
28589
  var multicall3Abi = [
28505
28590
  {
@@ -33124,7 +33209,10 @@ var getLenderUserDataResult = async (chainId, queriesRaw, getEvmClient18, allowF
33124
33209
  retries,
33125
33210
  allowFailure,
33126
33211
  batchSize,
33127
- logs
33212
+ logs,
33213
+ // Retry individual failed slots: a dropped call here is indistinguishable
33214
+ // from "user has no position" downstream, so it is worth one extra pass.
33215
+ true
33128
33216
  );
33129
33217
  };
33130
33218
  var prepareLenderUserDataRpcCalls = async (chainId, queriesRaw, batchSize = MULTICALL_DEFAULT_BATCH_SIZE, blockTag = "latest", allowFailure = true) => {
@@ -38877,15 +38965,16 @@ function createMerklRewardFetcher(config) {
38877
38965
  );
38878
38966
  for (const { chainId, opps } of chainResults) {
38879
38967
  for (const opp of opps) {
38880
- if (opp.action !== "LEND" && opp.action !== "BORROW") continue;
38881
38968
  if (!opp.apr || opp.apr <= 0) continue;
38882
38969
  const resolved2 = resolve(opp);
38883
38970
  if (!resolved2) continue;
38971
+ const bucket = resolved2.bucket ?? (opp.action === "LEND" ? "deposit" : opp.action === "BORROW" ? "borrow" : void 0);
38972
+ if (!bucket) continue;
38884
38973
  const lender = resolved2.lender ?? config.lenderKey;
38885
38974
  const reward = ensureReward(result, chainId, lender, resolved2.asset);
38886
38975
  const breakdowns = extractRewardBreakdowns(opp);
38887
38976
  reward.link = getMerkleUrl(opp);
38888
- if (opp.action === "LEND") {
38977
+ if (bucket === "deposit") {
38889
38978
  reward.deposit += opp.apr;
38890
38979
  reward.additionalDepositData.push(...breakdowns);
38891
38980
  } else {
@@ -38929,6 +39018,71 @@ var aaveMerklRewardFetcher = createMerklRewardFetcher({
38929
39018
  lenderKey: "AAVE_V3",
38930
39019
  chainIds: AAVE_V3_MERKL_CHAINS
38931
39020
  });
39021
+ var EULER_MERKL_CHAINS = [
39022
+ "1",
39023
+ // Ethereum
39024
+ "10",
39025
+ // Optimism
39026
+ "56",
39027
+ // BSC
39028
+ "130",
39029
+ // Unichain
39030
+ "137",
39031
+ // Polygon
39032
+ "8453",
39033
+ // Base
39034
+ "42161",
39035
+ // Arbitrum
39036
+ "43114",
39037
+ // Avalanche
39038
+ "80094"
39039
+ // Berachain
39040
+ ];
39041
+ var eulerMerklRewardFetcher = createMerklRewardFetcher({
39042
+ merklProtocolId: "euler",
39043
+ lenderKey: "EULER_V2",
39044
+ chainIds: EULER_MERKL_CHAINS,
39045
+ resolveAsset: (opp) => {
39046
+ const vault = opp.explorerAddress?.toLowerCase();
39047
+ if (!vault) return void 0;
39048
+ return { asset: vault };
39049
+ }
39050
+ });
39051
+ var MORPHO_MERKL_CHAINS = [
39052
+ "1",
39053
+ // Ethereum
39054
+ "130",
39055
+ // Unichain
39056
+ "137",
39057
+ // Polygon
39058
+ "8453",
39059
+ // Base
39060
+ "42161",
39061
+ // Arbitrum
39062
+ "4663"
39063
+ // Robinhood chain
39064
+ ];
39065
+ function parseMorphoUniqueKey(depositUrl) {
39066
+ if (!depositUrl) return void 0;
39067
+ const m = depositUrl.match(/\/market\/(0x[0-9a-fA-F]{64})/);
39068
+ return m?.[1]?.toLowerCase();
39069
+ }
39070
+ var morphoCollateralMerklRewardFetcher = createMerklRewardFetcher({
39071
+ merklProtocolId: "morpho",
39072
+ lenderKey: "MORPHO_BLUE",
39073
+ chainIds: MORPHO_MERKL_CHAINS,
39074
+ resolveAsset: (opp) => {
39075
+ if (opp.type !== "MORPHOCOLLATERAL") return void 0;
39076
+ const uniqueKey = parseMorphoUniqueKey(opp.depositUrl);
39077
+ const collateral = opp.explorerAddress?.toLowerCase();
39078
+ if (!uniqueKey || !collateral) return void 0;
39079
+ return {
39080
+ asset: collateral,
39081
+ lender: `MORPHO_BLUE_${uniqueKey.slice(2).toUpperCase()}`,
39082
+ bucket: "deposit"
39083
+ };
39084
+ }
39085
+ });
38932
39086
 
38933
39087
  // src/yields/rewards/fetchLenderRewards.ts
38934
39088
  function mergeRewardResults(target, source) {
@@ -38940,7 +39094,11 @@ function mergeRewardResults(target, source) {
38940
39094
  }
38941
39095
  }
38942
39096
  }
38943
- var rewardFetchers = [aaveMerklRewardFetcher];
39097
+ var rewardFetchers = [
39098
+ aaveMerklRewardFetcher,
39099
+ eulerMerklRewardFetcher,
39100
+ morphoCollateralMerklRewardFetcher
39101
+ ];
38944
39102
  async function fetchLenderRewards() {
38945
39103
  const results = await Promise.all(
38946
39104
  rewardFetchers.map((f) => safeFetch(f.label, f.fetch))