@defillama/sdk 5.0.219 → 5.0.220

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/README.md CHANGED
@@ -20,6 +20,20 @@ ETHEREUM_RPC="https://..."
20
20
  BSC_RPC="https://..."
21
21
  ```
22
22
 
23
+ ### Environment variables
24
+
25
+ Most settings can be overridden per chain via environment variables. The chain
26
+ name is uppercased and used as a prefix, e.g. `ETHEREUM_RPC`, `BSC_RPC_MULTICALL_V3`.
27
+ Every key is also resolved with an `SDK_` or `LLAMA_SDK_` prefix (checked in the
28
+ order `LLAMA_SDK_<KEY>` → `SDK_<KEY>` → `<KEY>`), so `SDK_ETHEREUM_RPC` works too.
29
+
30
+ | Variable | Description |
31
+ | --- | --- |
32
+ | `<CHAIN>_RPC` | RPC URL(s) for the chain (comma-separated for multiple). |
33
+ | `<CHAIN>_RPC_MULTICALL_V3` | Address of a Multicall3 contract for the chain. Setting it enables the Multicall3 code path for that chain (even if the chain is not in the built-in registry) and uses this address. Takes precedence over the built-in registry and the deployment-block gating. |
34
+ | `<CHAIN>_RPC_MULTICALL` | Address of a legacy (v2) multicall contract, used only when Multicall3 is not available for the chain. |
35
+ | `<CHAIN>_MULTICALL_CHUNK_SIZE` | Max number of calls per multicall batch for the chain. |
36
+
23
37
  ## Chain RPC PR
24
38
 
25
39
  Before putting up a PR for new chain, check if we already support it here: https://unpkg.com/@defillama/sdk@latest/build/providers.json
package/build/Balances.js CHANGED
@@ -195,7 +195,7 @@ class Balances {
195
195
  }
196
196
  async getUSDValue() {
197
197
  let { usdTvl } = await (0, computeTVL_1.default)(this.getBalances(), this.timestamp);
198
- usdTvl = Object.values(this._usdBalances).reduce((a, b) => a + b, usdTvl);
198
+ usdTvl = Object.values(this._usdBalances).reduce((a, b) => a + Number(b), usdTvl);
199
199
  return usdTvl;
200
200
  }
201
201
  async getUSDString() {
package/build/ChainApi.js CHANGED
@@ -193,8 +193,8 @@ class ChainApi {
193
193
  tokens.forEach((i) => tokensAndOwners.push([i, owner]));
194
194
  if (skipDuplicates)
195
195
  tokensAndOwners = getUniqueTokensAndOwners(tokensAndOwners, this.chain);
196
- blacklistedOwners = (0, common_1.getUniqueAddresses)(blacklistedOwners);
197
- blacklistedTokens = (0, common_1.getUniqueAddresses)(blacklistedTokens);
196
+ blacklistedOwners = (0, common_1.getUniqueAddresses)(blacklistedOwners, this.chain);
197
+ blacklistedTokens = (0, common_1.getUniqueAddresses)(blacklistedTokens, this.chain);
198
198
  tokensAndOwners = tokensAndOwners.filter(i => !blacklistedTokens.includes(i[0]) && !blacklistedOwners.includes(i[1]));
199
199
  const tokenBalances = [];
200
200
  const erc20TokensResponseIndex = [];
package/build/abi/abi2.js CHANGED
@@ -63,7 +63,7 @@ async function call(params) {
63
63
  for (let i = 0; i < abis.length - 1; i++) {
64
64
  const res = await call({ ...restParams, abi: abis[i], permitFailure: true, withMetadata: true });
65
65
  const response = params.withMetadata ? res : res.output;
66
- if (res.success)
66
+ if (res.success !== false)
67
67
  return response;
68
68
  }
69
69
  const lastAbi = abis[abis.length - 1];
@@ -195,13 +195,34 @@ async function multiCall(params) {
195
195
  if (!params.skipCache)
196
196
  return cachedMultiCall(params);
197
197
  const abi = resolveABI(params.abi);
198
+ const chunkedCalls = (0, util_1.sliceIntoChunks)(contractCalls, chunkSize);
198
199
  const results = await (0, util_1.runInPromisePool)({
199
- items: (0, util_1.sliceIntoChunks)(contractCalls, chunkSize),
200
+ items: chunkedCalls,
200
201
  concurrency: 10,
201
202
  processor: (calls) => (0, multicall3_1.default)(abi, calls, chain, params.block),
202
203
  permitFailure: params.permitFailure,
203
204
  });
204
- const flatResults = [].concat.apply([], results);
205
+ // When an entire chunk's processor call throws (e.g. a chunk-level RPC
206
+ // failure, as opposed to an individual call within it), runInPromisePool
207
+ // returns `undefined` for that chunk's slot instead of the expected array
208
+ // of one result per call. If permitFailure is set, that undefined flows
209
+ // straight through here uncaught, and both the .filter(r => !r.success)
210
+ // below and the flatResults[i].output access further down crash on it -
211
+ // and even without the crash, replacing a whole chunk's many calls with a
212
+ // single slot silently shortens and misaligns the array against
213
+ // contractCalls. Reconstruct a properly-shaped failure entry per call in
214
+ // any failed chunk instead, matching what makeMultiCall itself returns on
215
+ // an individual call failure, so length/order stay correct either way.
216
+ const resultsWithFailedChunksExpanded = results.map((chunkResult, i) => {
217
+ if (chunkResult !== undefined)
218
+ return chunkResult;
219
+ return chunkedCalls[i].map((call) => ({
220
+ input: { params: call.params, target: call.contract },
221
+ success: false,
222
+ output: null,
223
+ }));
224
+ });
225
+ const flatResults = [].concat.apply([], resultsWithFailedChunksExpanded);
205
226
  const failedQueries = flatResults.filter(r => !r.success);
206
227
  if (failedQueries.length) {
207
228
  // debugLog(`[chain: ${params.chain ?? "ethereum"}] [abi: ${params.abi}] Failed multicalls:`, failedQueries.map(r => r.input))
@@ -4,4 +4,4 @@ export default function makeMultiCall(functionABI: any, calls: {
4
4
  params: any[];
5
5
  }[], chain: Chain, block?: string | number): Promise<any>;
6
6
  export declare function isMulticallV3Supported(chain: Chain, block?: string | number): boolean;
7
- export declare function getMulticallAddress(chain: Chain, block?: string | number): string | null;
7
+ export declare function getMulticallAddress(chain: Chain, block?: string | number): any;
@@ -10,6 +10,7 @@ const ethers_1 = require("ethers");
10
10
  const convertResults_1 = __importDefault(require("./convertResults"));
11
11
  const multicall_1 = __importDefault(require("./multicall"));
12
12
  const index_1 = require("./index");
13
+ const env_1 = require("../util/env");
13
14
  // https://github.com/mds1/multicall
14
15
  // https://www.multicall3.com/deployments
15
16
  const MULTICALL_V3_ADDRESS = '0xca11bde05977b3631167028862be2a173976ca11';
@@ -222,6 +223,8 @@ const DEPLOYMENT_BLOCK = {
222
223
  srx: 1,
223
224
  xo: 1,
224
225
  rls: 1,
226
+ quai: 1,
227
+ adi: 1,
225
228
  };
226
229
  async function makeMultiCall(functionABI, calls, chain, block) {
227
230
  if (!functionABI)
@@ -236,16 +239,17 @@ async function makeMultiCall(functionABI, calls, chain, block) {
236
239
  const goodEncodingIndexes = [];
237
240
  const goodCalls = [];
238
241
  const contractCalls = calls.map((call, idx) => {
239
- var _a;
240
242
  try {
241
243
  const data = contractInterface.encodeFunctionData(fd, call.params);
242
- if ((_a = call.contract) === null || _a === void 0 ? void 0 : _a.startsWith('0x')) {
243
- const _isValidAddress = ethers_1.ethers.getAddress(call.contract); // Validates and checksums the address
244
+ let contract = call.contract;
245
+ if (contract === null || contract === void 0 ? void 0 : contract.startsWith('0x')) {
246
+ contract = contract.toLowerCase(); // lowercase so a bad EIP-55 checksum does not reject the call - single `call` passes the target as-is to eth_call, so multiCall should accept the same input
247
+ const _isValidAddress = ethers_1.ethers.getAddress(contract); // Validates the address
244
248
  }
245
249
  goodCalls.push(call);
246
250
  goodEncodingIndexes.push(idx);
247
251
  return {
248
- to: call.contract,
252
+ to: contract,
249
253
  data,
250
254
  };
251
255
  }
@@ -300,7 +304,18 @@ async function makeMultiCall(functionABI, calls, chain, block) {
300
304
  returnValues = returnData;
301
305
  }
302
306
  }
307
+ const envMulticallCache = {};
308
+ function getMulticallV3ContractFromEnv(chain) {
309
+ var _a;
310
+ if (!envMulticallCache.hasOwnProperty(chain)) {
311
+ envMulticallCache[chain] = (_a = (0, env_1.getEnvValue)(`${chain}_RPC_MULTICALL_V3`)) !== null && _a !== void 0 ? _a : null;
312
+ }
313
+ return envMulticallCache[chain];
314
+ }
303
315
  function isMulticallV3Supported(chain, block) {
316
+ const contractFromEnv = getMulticallV3ContractFromEnv(chain);
317
+ if (contractFromEnv)
318
+ return true;
304
319
  const startBlock = DEPLOYMENT_BLOCK[chain];
305
320
  if (!startBlock)
306
321
  return false;
@@ -312,6 +327,9 @@ function isMulticallV3Supported(chain, block) {
312
327
  }
313
328
  function getMulticallAddress(chain, block) {
314
329
  var _a;
330
+ const contractFromEnv = getMulticallV3ContractFromEnv(chain);
331
+ if (contractFromEnv)
332
+ return contractFromEnv;
315
333
  if (!isMulticallV3Supported(chain, block))
316
334
  return null;
317
335
  return (_a = CUSTOM_MULTICALL_ADDRESSES[chain]) !== null && _a !== void 0 ? _a : MULTICALL_V3_ADDRESS;
@@ -354,4 +372,6 @@ const CUSTOM_MULTICALL_ADDRESSES = {
354
372
  'anubi': '0x2BaB36196519Ce9Cc31Bc4899FCBB8124A413b02',
355
373
  'srx': '0xFd4b34b5763f54a580a0d9f7997A2A993ef9ceE9',
356
374
  'xo': '0x7c6d6eAafF566E3B8a6D072ca1825E8F18141fDb',
375
+ 'quai': '0x00567637197E6554e2CF47a3988Cb7B819f4E92C',
376
+ 'adi': '0xcC5fae7aF4A6684d05D92Db59279B70e827F31BE',
357
377
  };