@defillama/sdk 5.0.240 → 5.0.244

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 (133) hide show
  1. package/build/Balances.d.ts +139 -0
  2. package/build/Balances.js +363 -0
  3. package/build/ChainApi.d.ts +142 -0
  4. package/build/ChainApi.js +310 -0
  5. package/build/abi/abi2.d.ts +5 -0
  6. package/build/abi/abi2.js +215 -0
  7. package/build/abi/cachedABIs.d.ts +4 -0
  8. package/build/abi/cachedABIs.js +8 -0
  9. package/build/abi/convertResults.d.ts +5 -0
  10. package/build/abi/convertResults.js +60 -0
  11. package/build/abi/index.d.ts +31 -0
  12. package/build/abi/index.js +327 -0
  13. package/build/abi/multicall.d.ts +23 -0
  14. package/build/abi/multicall.js +383 -0
  15. package/build/abi/multicall3.d.ts +7 -0
  16. package/build/abi/multicall3.js +405 -0
  17. package/build/abi/rpcCall.d.ts +4 -0
  18. package/build/abi/rpcCall.js +62 -0
  19. package/build/abi/tron.d.ts +33 -0
  20. package/build/abi/tron.js +118 -0
  21. package/build/api.d.ts +10 -0
  22. package/build/api.js +45 -0
  23. package/build/api2.d.ts +5 -0
  24. package/build/api2.js +41 -0
  25. package/build/chains/algorand.d.ts +277 -0
  26. package/build/chains/algorand.js +618 -0
  27. package/build/chains/aptos.d.ts +269 -0
  28. package/build/chains/aptos.js +700 -0
  29. package/build/chains/cardano.d.ts +242 -0
  30. package/build/chains/cardano.js +407 -0
  31. package/build/chains/cosmos.d.ts +252 -0
  32. package/build/chains/cosmos.js +623 -0
  33. package/build/chains/icp.d.ts +235 -0
  34. package/build/chains/icp.js +1040 -0
  35. package/build/chains/index.d.ts +23 -0
  36. package/build/chains/index.js +59 -0
  37. package/build/chains/near.d.ts +192 -0
  38. package/build/chains/near.js +446 -0
  39. package/build/chains/rpc.d.ts +125 -0
  40. package/build/chains/rpc.js +332 -0
  41. package/build/chains/starknet.d.ts +205 -0
  42. package/build/chains/starknet.js +886 -0
  43. package/build/chains/stellar.d.ts +410 -0
  44. package/build/chains/stellar.js +1082 -0
  45. package/build/chains/substrate.d.ts +333 -0
  46. package/build/chains/substrate.js +1042 -0
  47. package/build/chains/sui.d.ts +392 -0
  48. package/build/chains/sui.js +1213 -0
  49. package/build/chains/svm.d.ts +340 -0
  50. package/build/chains/svm.js +764 -0
  51. package/build/chains/tezos.d.ts +225 -0
  52. package/build/chains/tezos.js +412 -0
  53. package/build/chains/ton.d.ts +353 -0
  54. package/build/chains/ton.js +788 -0
  55. package/build/chains/tron.d.ts +45 -0
  56. package/build/chains/tron.js +110 -0
  57. package/build/chains/utxo.d.ts +210 -0
  58. package/build/chains/utxo.js +678 -0
  59. package/build/chains/xrpl.d.ts +179 -0
  60. package/build/chains/xrpl.js +467 -0
  61. package/build/computeTVL/blocks.d.ts +1 -0
  62. package/build/computeTVL/blocks.js +12 -0
  63. package/build/computeTVL/humanizeNumber.d.ts +1 -0
  64. package/build/computeTVL/humanizeNumber.js +19 -0
  65. package/build/erc20/index.d.ts +31 -0
  66. package/build/erc20/index.js +56 -0
  67. package/build/eth/index.d.ts +22 -0
  68. package/build/eth/index.js +118 -0
  69. package/build/general.d.ts +5 -0
  70. package/build/general.js +20 -0
  71. package/build/generalUtil.d.ts +8 -0
  72. package/build/generalUtil.js +73 -0
  73. package/build/index.d.ts +33 -0
  74. package/build/index.js +75 -0
  75. package/build/providers.json +1 -0
  76. package/build/types.d.ts +76 -0
  77. package/build/types.js +2 -0
  78. package/build/util/LlamaProvider.d.ts +46 -0
  79. package/build/util/LlamaProvider.js +343 -0
  80. package/build/util/blocks.d.ts +36 -0
  81. package/build/util/blocks.js +500 -0
  82. package/build/util/cache.d.ts +45 -0
  83. package/build/util/cache.js +309 -0
  84. package/build/util/callStats.d.ts +74 -0
  85. package/build/util/callStats.js +385 -0
  86. package/build/util/chainUtils/data.json +1459 -0
  87. package/build/util/chainUtils/index.d.ts +11 -0
  88. package/build/util/chainUtils/index.js +136 -0
  89. package/build/util/coins.d.ts +19 -0
  90. package/build/util/coins.js +124 -0
  91. package/build/util/common.d.ts +34 -0
  92. package/build/util/common.js +376 -0
  93. package/build/util/computeTVL.d.ts +19 -0
  94. package/build/util/computeTVL.js +102 -0
  95. package/build/util/cosmos.d.ts +1 -0
  96. package/build/util/cosmos.js +8 -0
  97. package/build/util/debugLog.d.ts +4 -0
  98. package/build/util/debugLog.js +18 -0
  99. package/build/util/discord.d.ts +1 -0
  100. package/build/util/discord.js +33 -0
  101. package/build/util/elastic.d.ts +43 -0
  102. package/build/util/elastic.js +113 -0
  103. package/build/util/env.d.ts +20 -0
  104. package/build/util/env.js +176 -0
  105. package/build/util/graph.d.ts +8 -0
  106. package/build/util/graph.js +50 -0
  107. package/build/util/index.d.ts +32 -0
  108. package/build/util/index.js +227 -0
  109. package/build/util/indexer.compatibility.d.ts +6 -0
  110. package/build/util/indexer.compatibility.js +64 -0
  111. package/build/util/indexer.d.ts +92 -0
  112. package/build/util/indexer.js +854 -0
  113. package/build/util/indexerSql.d.ts +9 -0
  114. package/build/util/indexerSql.js +102 -0
  115. package/build/util/internal-cache.d.ts +11 -0
  116. package/build/util/internal-cache.js +77 -0
  117. package/build/util/logs.d.ts +58 -0
  118. package/build/util/logs.decode.shared.d.ts +8 -0
  119. package/build/util/logs.decode.shared.js +289 -0
  120. package/build/util/logs.js +432 -0
  121. package/build/util/promisePool.d.ts +8 -0
  122. package/build/util/promisePool.js +31 -0
  123. package/build/util/r2.d.ts +4 -0
  124. package/build/util/r2.js +52 -0
  125. package/build/util/removeRedundantRPCs.d.ts +1 -0
  126. package/build/util/removeRedundantRPCs.js +49 -0
  127. package/build/util/transactions.d.ts +35 -0
  128. package/build/util/transactions.js +22 -0
  129. package/build/util/updateChainLabels.d.ts +1 -0
  130. package/build/util/updateChainLabels.js +5 -0
  131. package/build/util/updateProviderList.d.ts +1 -0
  132. package/build/util/updateProviderList.js +275 -0
  133. package/package.json +3 -2
@@ -0,0 +1,76 @@
1
+ export type Address = string;
2
+ export type StringNumber = string;
3
+ export type Block = number | string;
4
+ export type Balances = {
5
+ [address: string]: StringNumber | number;
6
+ };
7
+ type CallParams = string | number | (string | number)[] | undefined;
8
+ export type CallsParams = {
9
+ target?: Address;
10
+ params?: CallParams;
11
+ };
12
+ export type CallOptions = {
13
+ target: Address;
14
+ abi?: string | any;
15
+ abis?: string[];
16
+ block?: Block;
17
+ params?: CallParams;
18
+ chain?: Chain | string;
19
+ withMetadata?: boolean;
20
+ skipCache?: boolean;
21
+ logArray?: LogArray;
22
+ permitFailure?: boolean;
23
+ field?: string;
24
+ };
25
+ export type Chain = string;
26
+ export type MulticallOptions = {
27
+ abi?: string | any;
28
+ abis?: string[];
29
+ calls: CallsParams[] | (string | number)[];
30
+ block?: Block;
31
+ target?: Address;
32
+ chain?: Chain | string;
33
+ requery?: boolean;
34
+ withMetadata?: boolean;
35
+ skipCache?: boolean;
36
+ permitFailure?: boolean;
37
+ excludeFailed?: boolean;
38
+ logArray?: LogArray;
39
+ field?: string;
40
+ };
41
+ export type FetchListOptions = {
42
+ lengthAbi?: string | any;
43
+ itemAbi: string | any;
44
+ itemAbi2?: string | any;
45
+ block?: Block;
46
+ startFrom?: number;
47
+ target?: Address;
48
+ calls?: Address[];
49
+ targets?: Address[];
50
+ chain?: Chain | string;
51
+ withMetadata?: boolean;
52
+ startFromOne?: boolean;
53
+ itemCount?: number;
54
+ permitFailure?: boolean;
55
+ logArray?: LogArray;
56
+ groupedByInput?: boolean;
57
+ excludeFailed?: boolean;
58
+ field?: string;
59
+ field2?: string;
60
+ };
61
+ export type ByteCodeCallOptions = {
62
+ bytecode: string;
63
+ inputTypes: string[];
64
+ inputs: any[];
65
+ block?: number | string;
66
+ chain?: Chain | string;
67
+ outputTypes: string[];
68
+ withMetadata?: boolean;
69
+ };
70
+ export type LogArray = {
71
+ token: Address;
72
+ holder: Address;
73
+ chain: Chain;
74
+ amount: any;
75
+ }[];
76
+ export {};
package/build/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,46 @@
1
+ import { AbstractProvider, AddressLike, Block, BlockTag, FallbackProvider, Filter, FilterByBlockHash, Log, TransactionRequest } from "ethers";
2
+ import { Chain } from "../types";
3
+ type ProviderWithURL = {
4
+ url: string;
5
+ provider: AbstractProvider;
6
+ };
7
+ type ProviderConfigMap = {
8
+ [chain: string]: {
9
+ rpc?: string[];
10
+ chainId?: number;
11
+ explorer?: string;
12
+ };
13
+ };
14
+ export declare class LlamaProvider extends FallbackProvider {
15
+ isCustomLlamaProvider: boolean;
16
+ rpcs: ProviderWithURL[];
17
+ archivalRPCs: ProviderWithURL[];
18
+ _isReady: Promise<void>;
19
+ chainName: string;
20
+ chainId: number;
21
+ constructor({ providers, chainId, chainName, archivalRPCs, }: {
22
+ providers: ProviderWithURL[];
23
+ archivalRPCs: ProviderWithURL[];
24
+ chainId: number;
25
+ chainName: string;
26
+ }, fallbackConfig?: any);
27
+ getNetwork(): any;
28
+ _removeProvider(rpc: string): void;
29
+ _ready(): Promise<void>;
30
+ call(_tx: TransactionRequest): Promise<string>;
31
+ getBalance(address: AddressLike, blockTag?: BlockTag): Promise<bigint>;
32
+ getBlock(block: BlockTag, prefetchTxs?: boolean | undefined): Promise<Block | null>;
33
+ getLogs(_filter: Filter | FilterByBlockHash): Promise<Log[]>;
34
+ getTransaction(_hash: string): Promise<any>;
35
+ getTransactionReceipt(_hash: string): Promise<any>;
36
+ _performAction(method: string, params: any, attempts?: number): Promise<any>;
37
+ }
38
+ export declare function getEVMProvidersConfigMap(): ProviderConfigMap;
39
+ export declare function getEVMChainSet(): Set<string>;
40
+ export declare function isEvmChain(chain: string): boolean;
41
+ export declare const providers: {
42
+ [chain: string]: AbstractProvider;
43
+ };
44
+ export declare function setProvider(chain: Chain, provider: AbstractProvider): void;
45
+ export declare function getProvider(chain?: Chain, _getArchivalNode?: boolean): AbstractProvider;
46
+ export {};
@@ -0,0 +1,343 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.providers = exports.LlamaProvider = void 0;
7
+ exports.getEVMProvidersConfigMap = getEVMProvidersConfigMap;
8
+ exports.getEVMChainSet = getEVMChainSet;
9
+ exports.isEvmChain = isEvmChain;
10
+ exports.setProvider = setProvider;
11
+ exports.getProvider = getProvider;
12
+ const ethers_1 = require("ethers");
13
+ const providers_json_1 = __importDefault(require("../providers.json"));
14
+ const env_1 = require("./env");
15
+ const debugLog_1 = require("./debugLog");
16
+ const axios_1 = __importDefault(require("axios"));
17
+ const callStats_1 = require("./callStats");
18
+ let buildProviders = undefined;
19
+ if (process.env['TEST_MODE']) {
20
+ buildProviders = require('../../build/providers.json');
21
+ }
22
+ const rpcRequestCounter = {};
23
+ class LlamaProvider extends ethers_1.FallbackProvider {
24
+ constructor({ providers, chainId, chainName, archivalRPCs, }, fallbackConfig) {
25
+ const networkish = { name: chainName, chainId };
26
+ super(providers.map(i => i.provider), networkish, fallbackConfig);
27
+ this.isCustomLlamaProvider = true;
28
+ this.rpcs = providers;
29
+ this.archivalRPCs = archivalRPCs;
30
+ this.chainName = chainName;
31
+ this.chainId = chainId;
32
+ this._isReady = this._ready();
33
+ }
34
+ getNetwork() {
35
+ return { chainId: this.chainId, name: this.chainName };
36
+ }
37
+ _removeProvider(rpc) {
38
+ this.rpcs = this.rpcs.filter(i => i.url !== rpc);
39
+ this.archivalRPCs = this.archivalRPCs.filter(i => i.url !== rpc);
40
+ }
41
+ async _ready() {
42
+ if (process.env["SKIP_RPC_CHECK"] === "true") {
43
+ return;
44
+ }
45
+ const outOfSyncLimit = 1000;
46
+ const _this = this;
47
+ const currentBlocks = {};
48
+ await Promise.all(this.rpcs.map(checkRPCWorks));
49
+ if (this.archivalRPCs.length) {
50
+ await Promise.all(this.archivalRPCs.map(checkRPCWorks));
51
+ }
52
+ // we are doing this because I noticed that one of the rpcs can go rouge and return very high block number
53
+ const medianBlockValue = getMedianBlockValue(Object.values(currentBlocks));
54
+ Object.entries(currentBlocks).forEach(([url, block]) => {
55
+ if (medianBlockValue - block > outOfSyncLimit) {
56
+ (0, debugLog_1.debugLog)(`RPC ${url} is out of sync by ${medianBlockValue - block} blocks`);
57
+ _this.rpcs = _this.rpcs.filter(i => i.url !== url);
58
+ _this.archivalRPCs = _this.archivalRPCs.filter(i => i.url !== url);
59
+ }
60
+ });
61
+ async function checkRPCWorks({ url, provider }) {
62
+ try {
63
+ const block = await httpRPC.getBlockNumber(url);
64
+ currentBlocks[url] = block;
65
+ }
66
+ catch (e) {
67
+ if (env_1.ENV_CONSTANTS.LOG_LLAMA_PROVIDER_CALLS)
68
+ (0, debugLog_1.debugLog)(`${_this.chainName} skipping RPC ${url} is not working, error: ${e.message}`);
69
+ _this._removeProvider(url);
70
+ }
71
+ }
72
+ }
73
+ async call(_tx) {
74
+ var _a;
75
+ return this._performAction('call', [{ to: _tx.to, data: _tx.data }, (_a = _tx.blockTag) !== null && _a !== void 0 ? _a : 'latest']);
76
+ }
77
+ async getBalance(address, blockTag = 'latest') {
78
+ return this._performAction('getBalance', [address, blockTag]);
79
+ }
80
+ async getBlock(block, prefetchTxs) {
81
+ return this._performAction('getBlock', [block, false]);
82
+ }
83
+ async getLogs(_filter) {
84
+ return this._performAction('getLogs', [_filter], 7);
85
+ }
86
+ async getTransaction(_hash) {
87
+ return this._performAction('getTransaction', [_hash]);
88
+ }
89
+ async getTransactionReceipt(_hash) {
90
+ return this._performAction('getTransactionReceipt', [_hash]);
91
+ }
92
+ async _performAction(method, params, attempts = 7) {
93
+ var _a;
94
+ if (!rpcRequestCounter[this.chainName])
95
+ rpcRequestCounter[this.chainName] = 0;
96
+ rpcRequestCounter[this.chainName]++;
97
+ await this._isReady;
98
+ let runners = [...this.rpcs];
99
+ if (method === 'getLogs') {
100
+ runners = [...this.archivalRPCs];
101
+ this.rpcs.filter(i => !runners.map(i => i.url).includes(i.url)).forEach(i => runners.push(i)); // ensure that there are no duplicates
102
+ runners = runners.filter(i => !i.url.includes('llamarpc.com'));
103
+ }
104
+ if (!runners.length)
105
+ throw new Error('No RPCs available for ' + this.chainName);
106
+ let primaryRunner = runners[0];
107
+ let errors = [];
108
+ if (method === 'getLogs') {
109
+ runners = runners.slice(1).concat(this.rpcs);
110
+ runners = runners.sort(() => Math.random() - 0.5); // randomize order of runners
111
+ }
112
+ else
113
+ runners = runners.slice(1).sort(() => Math.random() - 0.5); // randomize order of runners
114
+ const isArchivalRequest = ['call', 'getBalance'].includes(method) && params[1] !== 'latest';
115
+ // check if domain name of primaryRunner.url is llama
116
+ const isLlamaRPC = primaryRunner.url.includes('llama');
117
+ let noPlayingAround = (0, env_1.getEnvValue)('RPC_NO_PLAYING_AROUND') === 'true' || isLlamaRPC || method === 'getLogs' || isArchivalRequest;
118
+ if (noPlayingAround) {
119
+ // if primary runner is llama.fi or alchemy, then try it first
120
+ runners.unshift(primaryRunner);
121
+ }
122
+ else {
123
+ // add it as second runner
124
+ runners.splice(1, 0, primaryRunner);
125
+ }
126
+ runners = runners.slice(0, attempts);
127
+ // print stats every 5 minutes
128
+ let currentTimeMS = Date.now();
129
+ if (currentTimeMS - lastPrintTimeMS > 1000 * 60 * 5) {
130
+ lastPrintTimeMS = currentTimeMS;
131
+ printRPCCallStats();
132
+ }
133
+ // if (this.chainName === 'rsk' && method === 'getLogs') {
134
+ // const hostString = getEnvValue('RSK_ARCHIVAL_RPC')
135
+ // if (!hostString)
136
+ // throw new Error('RSK public nodes dont support getLogs. need to set RSK_ARCHIVAL_RPC');
137
+ // (runners as any) = hostString.split(',').map(host => ({ url: host }))
138
+ // }
139
+ for (const runner of runners) {
140
+ try {
141
+ (0, callStats_1.recordMethod)(method, this.chainName); // per attempt: call stats count requests, not successes
142
+ const result = await httpRPC[method](runner.url, params);
143
+ return result;
144
+ }
145
+ catch (e) {
146
+ // console.log('failed', runner.url, (e as any).message)
147
+ errors.push({ host: runner.url, error: ((_a = e === null || e === void 0 ? void 0 : e.message) !== null && _a !== void 0 ? _a : e) });
148
+ }
149
+ }
150
+ throw { llamaRPCError: true, errors, method, };
151
+ }
152
+ }
153
+ exports.LlamaProvider = LlamaProvider;
154
+ function getEVMProvidersConfigMap() {
155
+ return buildProviders !== null && buildProviders !== void 0 ? buildProviders : providers_json_1.default;
156
+ }
157
+ let evmChainSet = null;
158
+ function getEVMChainSet() {
159
+ if (!evmChainSet) {
160
+ const pList = getEVMProvidersConfigMap();
161
+ evmChainSet = new Set(Object.keys(pList));
162
+ }
163
+ return evmChainSet;
164
+ }
165
+ function isEvmChain(chain) {
166
+ const pList = getEVMProvidersConfigMap();
167
+ if (pList[chain])
168
+ return true;
169
+ // check if we have RPC config for this chain via env variable
170
+ // let rpcList: (string | undefined) = getChainRPCs(chain, undefined) // skip this check as it can be true for non-evm chains like solana as well
171
+ return false;
172
+ }
173
+ function createProvider(name, rpcString, chainId = 400069, archivalRPCList = []) {
174
+ chainId = (0, env_1.getChainId)(name, chainId);
175
+ const networkish = { name, chainId };
176
+ let rpcList = rpcString.split(',');
177
+ if ((0, env_1.getEnvValue)('HISTORICAL')) {
178
+ if (chainId === 1) {
179
+ (0, debugLog_1.debugLog)("RPC providers set to historical, only the first RPC provider will be used");
180
+ }
181
+ // return getProviderObject(rpcList[0], name)
182
+ rpcList = [rpcList[0]];
183
+ }
184
+ (0, callStats_1.registerEndpoints)(name, [...rpcList, ...archivalRPCList]); // so http level call stats are attributed to this chain
185
+ try {
186
+ const fallbackConfig = { cacheTimeout: 5 * 1000, quorum: 1, eventQuorum: 1, };
187
+ const getProviderWithURL = (url) => ({ url, provider: getProviderObject(url, name) });
188
+ const providers = rpcList.map(getProviderWithURL);
189
+ const archivalRPCs = archivalRPCList.map(getProviderWithURL);
190
+ return new LlamaProvider({ providers, archivalRPCs, chainId, chainName: name, }, fallbackConfig);
191
+ // return new FallbackProvider(providers, networkish, fallbackConfig)
192
+ }
193
+ catch (e) {
194
+ // debugLog(`Error creating provider for ${name} with RPCs: ${rpcList.join(', ')}`)
195
+ // we dont throw errors for chains not present in providers.json, these can be non-evm chains like solana
196
+ if (providers_json_1.default[name])
197
+ throw e;
198
+ return null;
199
+ }
200
+ function getProviderObject(url, chain) {
201
+ const jsonRpcApiProviderOptions = { staticNetwork: true, batchMaxCount: 1, };
202
+ if (url.startsWith('wss://')) {
203
+ return null; // websocket provider is not supported
204
+ // return new WebSocketProvider(url, networkish, jsonRpcApiProviderOptions)
205
+ }
206
+ return new ethers_1.JsonRpcProvider(url, networkish, jsonRpcApiProviderOptions);
207
+ }
208
+ }
209
+ exports.providers = {};
210
+ function setProvider(chain, provider) {
211
+ exports.providers[chain] = provider;
212
+ }
213
+ function getProvider(chain = "ethereum", _getArchivalNode = false) {
214
+ var _a, _b;
215
+ const rpcKey = chain === 'tron' ? 'tron_evm' : chain;
216
+ let chainKey = chain;
217
+ if ((0, env_1.getEnvValue)('HISTORICAL'))
218
+ chainKey = chain + '_historical';
219
+ if (exports.providers[chainKey])
220
+ return exports.providers[chainKey];
221
+ const pList = getEVMProvidersConfigMap();
222
+ // use RPC from env variable if set else use RPC from providers.json
223
+ let rpcList = (0, env_1.getChainRPCs)(rpcKey, (_a = pList[chain]) === null || _a === void 0 ? void 0 : _a.rpc);
224
+ let archivalRPCList = (0, env_1.getArchivalRPCs)(rpcKey);
225
+ let whitelistedRPCList = (0, env_1.getWhitelistedRPCs)(rpcKey);
226
+ if (whitelistedRPCList === null || whitelistedRPCList === void 0 ? void 0 : whitelistedRPCList.length) {
227
+ rpcList = [...whitelistedRPCList].join(',');
228
+ archivalRPCList = whitelistedRPCList;
229
+ }
230
+ if (!rpcList) {
231
+ // @ts-ignore (throwing error here would alter function behavior and have side effects)
232
+ return null;
233
+ }
234
+ if (!exports.providers[chainKey])
235
+ exports.providers[chainKey] = createProvider(chain, rpcList, (_b = providers_json_1.default[chain]) === null || _b === void 0 ? void 0 : _b.chainId, archivalRPCList);
236
+ return exports.providers[chainKey];
237
+ }
238
+ function toHex(n) {
239
+ if (typeof n === 'string')
240
+ return n;
241
+ return '0x' + n.toString(16);
242
+ }
243
+ // A public RPC behind a dead or re-routed domain can answer HTTP 200 with an HTML page, an empty body or a JSON object without `result`
244
+ // (seen on mainnet.telos.net/evm). Reading `data.result` off that gave `undefined`, which the caller treated as a successful
245
+ // call and handed to the ABI decoder, so the error surfaced as "invalid BytesLike value null" / a multicall failure instead of the
246
+ // provider moving on to the next RPC. Anything that is not a JSON-RPC envelope with a `result` is therefore thrown here.
247
+ async function rpcPost(rpc, method, params, timeoutEnvKey, defaultTimeout) {
248
+ const { data } = await axios_1.default.post(rpc, { jsonrpc: '2.0', id: 1, params, method }, {
249
+ timeout: +(0, env_1.getEnvValue)(timeoutEnvKey, defaultTimeout)
250
+ });
251
+ if (!data || typeof data !== 'object' || Array.isArray(data))
252
+ throw new Error(`${method} on ${rpc}: not a JSON-RPC response: ${String(data).slice(0, 120)}`);
253
+ if (data.error)
254
+ throw data.error;
255
+ if (!Object.prototype.hasOwnProperty.call(data, 'result'))
256
+ throw new Error(`${method} on ${rpc}: response has no result field: ${JSON.stringify(data).slice(0, 120)}`);
257
+ return data.result;
258
+ }
259
+ const httpRPC = {
260
+ getBlockNumber: async (rpc) => {
261
+ const getData = async () => {
262
+ const result = await rpcPost(rpc, 'eth_blockNumber', [], 'LLAMA_PROVIDER_RPC_GET_BLOCKNUMBER_TIMEOUT', '30000');
263
+ const block = parseInt(result);
264
+ if (isNaN(block))
265
+ throw new Error(`eth_blockNumber on ${rpc}: bad result ${JSON.stringify(result)}`);
266
+ return block;
267
+ };
268
+ try {
269
+ return await getData();
270
+ }
271
+ catch (e) {
272
+ // try again
273
+ return await getData();
274
+ }
275
+ },
276
+ getBlock: async (rpc, params) => {
277
+ params[0] = toHex(params[0]);
278
+ const result = await rpcPost(rpc, 'eth_getBlockByNumber', params, 'LLAMA_PROVIDER_RPC_GET_BLOCK_TIMEOUT', '60000');
279
+ if (!result)
280
+ throw new Error(`block ${params[0]} not found`); // pruned or not yet synced, let callers recognise it
281
+ result.number = parseInt(result.number);
282
+ result.timestamp = parseInt(result.timestamp);
283
+ return result;
284
+ },
285
+ getBalance: async (rpc, params) => {
286
+ params[1] = toHex(params[1]);
287
+ const result = await rpcPost(rpc, 'eth_getBalance', params, 'LLAMA_PROVIDER_RPC_GET_BALANCE_TIMEOUT', '30000');
288
+ return BigInt(result).toString();
289
+ },
290
+ call: async (rpc, params) => {
291
+ params[1] = toHex(params[1]);
292
+ const result = await rpcPost(rpc, 'eth_call', params, 'LLAMA_PROVIDER_RPC_CALL_TIMEOUT', '30000');
293
+ // eth_call always returns hex data (`0x` when the target has no code); a null here is a broken node, not an empty return
294
+ if (typeof result !== 'string')
295
+ throw new Error(`eth_call on ${rpc}: bad result ${JSON.stringify(result)}`);
296
+ return result;
297
+ },
298
+ getLogs: async (rpc, params) => {
299
+ params[0].fromBlock = toHex(params[0].fromBlock);
300
+ params[0].toBlock = toHex(params[0].toBlock);
301
+ const result = await rpcPost(rpc, 'eth_getLogs', params, 'LLAMA_PROVIDER_RPC_GET_LOGS_TIMEOUT', '30000');
302
+ if (!Array.isArray(result))
303
+ throw new Error(`eth_getLogs on ${rpc}: bad result ${JSON.stringify(result)}`);
304
+ result.forEach((i) => {
305
+ i.blockNumber = parseInt(i.blockNumber);
306
+ i.transactionIndex = parseInt(i.transactionIndex);
307
+ i.logIndex = parseInt(i.logIndex);
308
+ i.index = i.logIndex;
309
+ });
310
+ return result;
311
+ },
312
+ getTransaction: async (rpc, params) => {
313
+ const result = await rpcPost(rpc, 'eth_getTransactionByHash', params, 'LLAMA_PROVIDER_RPC_GET_TRANSACTION_TIMEOUT', '180000');
314
+ if (!result)
315
+ return null;
316
+ result.blockNumber = parseInt(result.blockNumber);
317
+ result.transactionIndex = parseInt(result.transactionIndex);
318
+ result.data = result.input;
319
+ return result;
320
+ },
321
+ getTransactionReceipt: async (rpc, params) => {
322
+ const result = await rpcPost(rpc, 'eth_getTransactionReceipt', params, 'LLAMA_PROVIDER_RPC_GET_TXN_RECEIPT_TIMEOUT', '180000');
323
+ if (!result)
324
+ return null;
325
+ result.blockNumber = parseInt(result.blockNumber);
326
+ result.transactionIndex = parseInt(result.transactionIndex);
327
+ return result;
328
+ }
329
+ };
330
+ function getMedianBlockValue(blocks) {
331
+ blocks.sort((a, b) => a - b);
332
+ const mid = Math.floor(blocks.length / 3);
333
+ return blocks.length % 2 !== 0 ? blocks[mid] : (blocks[mid - 1] + blocks[mid]) / 2;
334
+ }
335
+ let lastPrintTimeMS = Date.now();
336
+ function printRPCCallStats() {
337
+ const entries = Object.entries(rpcRequestCounter).map(([chain, count]) => ({ chain, count })).filter(i => i.count > 50);
338
+ if (entries.length > 7) {
339
+ (0, debugLog_1.debugLog)('RPC request count per chain (only over 100)');
340
+ (0, debugLog_1.debugTable)(entries);
341
+ }
342
+ }
343
+ process.on('exit', printRPCCallStats);
@@ -0,0 +1,36 @@
1
+ import { Chain } from "../general";
2
+ export declare const chainsForBlocks: string[];
3
+ export declare function getChainBlocks(timestamp: number | undefined, chains?: Chain[]): Promise<{
4
+ [chain: string]: number;
5
+ }>;
6
+ export declare function getBlocks(timestamp: number, chains?: Chain[] | undefined): Promise<{
7
+ ethereumBlock: number;
8
+ chainBlocks: {
9
+ [chain: string]: number;
10
+ };
11
+ }>;
12
+ export declare function getCurrentBlocks(chains?: Chain[] | undefined): Promise<{
13
+ timestamp: number;
14
+ ethereumBlock: number;
15
+ chainBlocks: {
16
+ [chain: string]: number;
17
+ };
18
+ }>;
19
+ export declare function getBlock(chain: Chain, timestamp?: number, options?: LookupBlockOptionalParams): Promise<Block>;
20
+ export declare function getBlockNumber(chain: Chain, timestamp?: number): Promise<number>;
21
+ export declare function getCurrentChainBlock(chain?: Chain): Promise<Block>;
22
+ export declare const getLatestBlock: typeof getCurrentChainBlock;
23
+ type LookupBlockOptionalParams = {
24
+ chain?: Chain | "kava" | "algorand";
25
+ allowedTimeRange?: number;
26
+ acceptableBlockImprecision?: number;
27
+ };
28
+ export declare function lookupBlock(timestamp: number, extraParams?: LookupBlockOptionalParams): Promise<Block>;
29
+ export declare function getTimestamp(height: number, chain: Chain): Promise<number>;
30
+ export type Block = {
31
+ timestamp: number;
32
+ block: number;
33
+ hash?: string;
34
+ number: number;
35
+ };
36
+ export {};