@ledgerhq/coin-tester-evm 1.6.0 → 1.6.1-nightly.0

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 (55) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/lib/src/helpers.d.ts +6 -6
  3. package/lib/src/helpers.d.ts.map +1 -1
  4. package/lib/src/helpers.js +12 -11
  5. package/lib/src/helpers.js.map +1 -1
  6. package/lib/src/indexer.d.ts.map +1 -1
  7. package/lib/src/indexer.js +193 -184
  8. package/lib/src/indexer.js.map +1 -1
  9. package/lib/src/scenarii/blast.d.ts.map +1 -1
  10. package/lib/src/scenarii/blast.js +8 -8
  11. package/lib/src/scenarii/blast.js.map +1 -1
  12. package/lib/src/scenarii/ethereum.d.ts.map +1 -1
  13. package/lib/src/scenarii/ethereum.js +10 -10
  14. package/lib/src/scenarii/ethereum.js.map +1 -1
  15. package/lib/src/scenarii/polygon.d.ts.map +1 -1
  16. package/lib/src/scenarii/polygon.js +11 -11
  17. package/lib/src/scenarii/polygon.js.map +1 -1
  18. package/lib/src/scenarii/scroll.d.ts.map +1 -1
  19. package/lib/src/scenarii/scroll.js +8 -8
  20. package/lib/src/scenarii/scroll.js.map +1 -1
  21. package/lib/src/scenarii/sonic.d.ts.map +1 -1
  22. package/lib/src/scenarii/sonic.js +8 -8
  23. package/lib/src/scenarii/sonic.js.map +1 -1
  24. package/lib/tsconfig.tsbuildinfo +1 -1
  25. package/lib-es/src/helpers.d.ts +6 -6
  26. package/lib-es/src/helpers.d.ts.map +1 -1
  27. package/lib-es/src/helpers.js +12 -11
  28. package/lib-es/src/helpers.js.map +1 -1
  29. package/lib-es/src/indexer.d.ts.map +1 -1
  30. package/lib-es/src/indexer.js +194 -185
  31. package/lib-es/src/indexer.js.map +1 -1
  32. package/lib-es/src/scenarii/blast.d.ts.map +1 -1
  33. package/lib-es/src/scenarii/blast.js +9 -9
  34. package/lib-es/src/scenarii/blast.js.map +1 -1
  35. package/lib-es/src/scenarii/ethereum.d.ts.map +1 -1
  36. package/lib-es/src/scenarii/ethereum.js +11 -11
  37. package/lib-es/src/scenarii/ethereum.js.map +1 -1
  38. package/lib-es/src/scenarii/polygon.d.ts.map +1 -1
  39. package/lib-es/src/scenarii/polygon.js +12 -12
  40. package/lib-es/src/scenarii/polygon.js.map +1 -1
  41. package/lib-es/src/scenarii/scroll.d.ts.map +1 -1
  42. package/lib-es/src/scenarii/scroll.js +9 -9
  43. package/lib-es/src/scenarii/scroll.js.map +1 -1
  44. package/lib-es/src/scenarii/sonic.d.ts.map +1 -1
  45. package/lib-es/src/scenarii/sonic.js +9 -9
  46. package/lib-es/src/scenarii/sonic.js.map +1 -1
  47. package/lib-es/tsconfig.tsbuildinfo +1 -1
  48. package/package.json +6 -6
  49. package/src/helpers.ts +15 -14
  50. package/src/indexer.ts +200 -205
  51. package/src/scenarii/blast.ts +9 -11
  52. package/src/scenarii/ethereum.ts +11 -13
  53. package/src/scenarii/polygon.ts +12 -14
  54. package/src/scenarii/scroll.ts +9 -11
  55. package/src/scenarii/sonic.ts +9 -11
@@ -2,18 +2,19 @@ import BigNumber from "bignumber.js";
2
2
  import { setupServer } from "msw/node";
3
3
  import BlueBirdPromise from "bluebird";
4
4
  import { http, HttpResponse, bypass } from "msw";
5
- import { utils, providers, ethers } from "ethers";
5
+ import { AbiCoder, ethers } from "ethers";
6
6
  import { ERC20_ABI, ERC721_ABI, ERC1155_ABI } from "@ledgerhq/coin-evm/abis/index";
7
7
  import { safeEncodeEIP55 } from "@ledgerhq/coin-evm/utils";
8
8
  const MAX_BLOCK_RANGE = 1024;
9
- const ERC20Interface = new utils.Interface(ERC20_ABI);
10
- const ERC721Interface = new utils.Interface(ERC721_ABI);
11
- const ERC1155Interface = new utils.Interface(ERC1155_ABI);
9
+ const ERC20Interface = new ethers.Interface(ERC20_ABI);
10
+ const ERC721Interface = new ethers.Interface(ERC721_ABI);
11
+ const ERC1155Interface = new ethers.Interface(ERC1155_ABI);
12
12
  const TRANSFER_EVENTS_TOPICS = {
13
- ERC20: ERC20Interface.getEventTopic("Transfer"),
14
- ERC721: ERC721Interface.getEventTopic("Transfer"),
15
- ERC1155: ERC1155Interface.getEventTopic("TransferSingle"),
13
+ ERC20: ERC20Interface.getEvent("Transfer")?.topicHash || "",
14
+ ERC721: ERC721Interface.getEvent("Transfer")?.topicHash || "",
15
+ ERC1155: ERC1155Interface.getEvent("TransferSingle")?.topicHash || "",
16
16
  };
17
+ const abiCoder = new AbiCoder();
17
18
  const explorerEtherscanOperationByAddress = {};
18
19
  const explorerEtherscanERC20EventsByAddress = {};
19
20
  const explorerEtherscanERC721EventsByAddress = {};
@@ -43,11 +44,21 @@ export const resetIndexer = () => {
43
44
  }
44
45
  };
45
46
  const handleLog = async (log, provider) => {
46
- const contractDecimals = await provider
47
- .call({ to: log.address, data: ERC20Interface.encodeFunctionData("decimals") })
48
- .then(res => (!res || res === "0x" ? false : true));
49
- const isERC20 = log.topics[0] === TRANSFER_EVENTS_TOPICS.ERC20 && contractDecimals;
50
- const isERC721 = log.topics[0] === TRANSFER_EVENTS_TOPICS.ERC721 && !contractDecimals;
47
+ let hasDecimals = false;
48
+ try {
49
+ const res = await provider.call({
50
+ to: log.address,
51
+ data: ERC20Interface.encodeFunctionData("decimals"),
52
+ });
53
+ // if call didn’t revert and returned something valid
54
+ hasDecimals = !!(res && res !== "0x");
55
+ }
56
+ catch {
57
+ // execution reverted → no decimals()
58
+ hasDecimals = false;
59
+ }
60
+ const isERC20 = log.topics[0] === TRANSFER_EVENTS_TOPICS.ERC20 && hasDecimals;
61
+ const isERC721 = log.topics[0] === TRANSFER_EVENTS_TOPICS.ERC721 && !hasDecimals;
51
62
  const isERC1155 = log.topics[0] === TRANSFER_EVENTS_TOPICS.ERC1155;
52
63
  if (isERC20) {
53
64
  return handleERC20Log(log, provider);
@@ -63,10 +74,10 @@ const handleERC20Log = async (log, provider) => {
63
74
  const [name, ticker, decimals, block, tx, receipt] = await Promise.all([
64
75
  provider
65
76
  .call({ to: log.address, data: ERC20Interface.encodeFunctionData("name") })
66
- .then(res => ethers.utils.defaultAbiCoder.decode(["string"], res)[0]),
77
+ .then(res => abiCoder.decode(["string"], res)[0]),
67
78
  provider
68
79
  .call({ to: log.address, data: ERC20Interface.encodeFunctionData("symbol") })
69
- .then(res => ethers.utils.defaultAbiCoder.decode(["string"], res)[0]),
80
+ .then(res => abiCoder.decode(["string"], res)[0]),
70
81
  provider
71
82
  .call({ to: log.address, data: ERC20Interface.encodeFunctionData("decimals") })
72
83
  .then(res => new BigNumber(res).toString()),
@@ -74,29 +85,29 @@ const handleERC20Log = async (log, provider) => {
74
85
  provider.getTransaction(log.transactionHash),
75
86
  provider.getTransactionReceipt(log.transactionHash),
76
87
  ]);
77
- const from = safeEncodeEIP55(ethers.utils.defaultAbiCoder.decode(["address"], log.topics[1])[0]);
78
- const to = safeEncodeEIP55(ethers.utils.defaultAbiCoder.decode(["address"], log.topics[2])[0]);
79
- const amount = ethers.BigNumber.from(log.data === "0x" ? 0 : log.data).toString();
88
+ const from = safeEncodeEIP55(abiCoder.decode(["address"], log.topics[1])[0]);
89
+ const to = safeEncodeEIP55(abiCoder.decode(["address"], log.topics[2])[0]);
90
+ const amount = BigInt(log.data === "0x" ? 0 : log.data).toString();
80
91
  const etherscanErc20Event = {
81
- blockNumber: block.number.toString(),
82
- timeStamp: block.timestamp.toString(),
92
+ blockNumber: block?.number.toString() || "0",
93
+ timeStamp: block?.timestamp.toString() || "0",
83
94
  hash: log.transactionHash,
84
- nonce: tx.nonce.toString(),
85
- blockHash: block.hash,
95
+ nonce: tx?.nonce.toString() || "0",
96
+ blockHash: block?.hash || "",
86
97
  from,
87
98
  to,
88
99
  value: amount,
89
100
  tokenName: name,
90
101
  tokenSymbol: ticker,
91
102
  tokenDecimal: decimals,
92
- transactionIndex: block.transactions.indexOf(log.transactionHash).toString(),
93
- gas: tx.gasLimit.toString(),
94
- gasPrice: tx.gasPrice?.toString() || "",
95
- cumulativeGasUsed: receipt.cumulativeGasUsed.toString(),
103
+ transactionIndex: block?.transactions.indexOf(log.transactionHash).toString() || "0",
104
+ gas: tx?.gasLimit.toString() || "0",
105
+ gasPrice: tx?.gasPrice?.toString() || "",
106
+ cumulativeGasUsed: receipt?.cumulativeGasUsed.toString() || "0",
96
107
  gasUsed: receipt?.gasUsed?.toString() || "0",
97
- input: tx.data,
98
- confirmations: tx.confirmations.toString(),
99
- contractAddress: tx.to.toLowerCase(),
108
+ input: tx?.data || "0x",
109
+ confirmations: tx?.confirmations.toString() || "0",
110
+ contractAddress: tx?.to.toLowerCase() || "",
100
111
  };
101
112
  if (!explorerEtherscanERC20EventsByAddress[from]) {
102
113
  explorerEtherscanERC20EventsByAddress[from] = new Map();
@@ -112,8 +123,9 @@ const handleERC20Log = async (log, provider) => {
112
123
  if (!explorerLedgerOperationByAddress[to]) {
113
124
  explorerLedgerOperationByAddress[to] = new Map();
114
125
  }
115
- const alreadyExistingOperation = explorerLedgerOperationByAddress[from].get(tx.hash) ||
116
- explorerLedgerOperationByAddress[to].get(tx.hash);
126
+ const txHash = tx?.hash;
127
+ const alreadyExistingOperation = (txHash && explorerLedgerOperationByAddress[from].get(txHash)) ||
128
+ (txHash && explorerLedgerOperationByAddress[to].get(txHash));
117
129
  const ledgerOperation = alreadyExistingOperation
118
130
  ? {
119
131
  ...alreadyExistingOperation,
@@ -128,16 +140,16 @@ const handleERC20Log = async (log, provider) => {
128
140
  }
129
141
  : {
130
142
  hash: log.transactionHash,
131
- transaction_type: receipt.type,
143
+ transaction_type: receipt?.type ?? 0,
132
144
  nonce: "",
133
145
  nonce_value: -1,
134
- value: tx.value.toString(),
135
- gas: tx.gasLimit.toString(),
136
- gas_price: receipt.effectiveGasPrice.toString(),
137
- max_fee_per_gas: tx.type === 2 ? tx.maxFeePerGas.toString() : null,
138
- max_priority_fee_per_gas: tx.type === 2 ? tx.maxPriorityFeePerGas.toString() : null,
139
- from: tx.from,
140
- to: tx.to,
146
+ value: tx?.value.toString() ?? "0",
147
+ gas: tx?.gasLimit.toString() ?? "0",
148
+ gas_price: receipt?.gasPrice.toString() ?? "0",
149
+ max_fee_per_gas: tx?.type === 2 ? tx.maxFeePerGas.toString() : null,
150
+ max_priority_fee_per_gas: tx?.type === 2 ? tx.maxPriorityFeePerGas.toString() : null,
151
+ from: tx?.from ?? "0x",
152
+ to: tx?.to ?? "0x0000000000000000000000000000000000000000",
141
153
  transfer_events: [
142
154
  {
143
155
  contract: log.address,
@@ -150,16 +162,16 @@ const handleERC20Log = async (log, provider) => {
150
162
  erc1155_transfer_events: [],
151
163
  approval_events: [],
152
164
  actions: [],
153
- confirmations: tx.confirmations,
165
+ confirmations: tx?.confirmations ? await tx.confirmations() : 0,
154
166
  input: null,
155
- gas_used: receipt.gasUsed.toString(),
156
- cumulative_gas_used: receipt.cumulativeGasUsed.toString(),
157
- status: receipt.status,
158
- received_at: new Date(block.timestamp * 1000).toISOString(),
167
+ gas_used: receipt?.gasUsed.toString() ?? "0",
168
+ cumulative_gas_used: receipt?.cumulativeGasUsed.toString() ?? "0",
169
+ status: receipt?.status ?? 0,
170
+ received_at: new Date((block?.timestamp ?? 0) * 1000).toISOString(),
159
171
  block: {
160
172
  hash: log.blockHash,
161
173
  height: log.blockNumber,
162
- time: new Date(block.timestamp * 1000).toISOString(),
174
+ time: new Date((block?.timestamp ?? 0) * 1000).toISOString(),
163
175
  },
164
176
  };
165
177
  explorerLedgerOperationByAddress[from].set(ledgerOperation.hash, ledgerOperation);
@@ -171,25 +183,25 @@ const handleERC721Log = async (log, provider) => {
171
183
  provider.getTransaction(log.transactionHash),
172
184
  provider.getTransactionReceipt(log.transactionHash),
173
185
  ]);
174
- const from = safeEncodeEIP55(ethers.utils.defaultAbiCoder.decode(["address"], log.topics[1])[0]);
175
- const to = safeEncodeEIP55(ethers.utils.defaultAbiCoder.decode(["address"], log.topics[2])[0]);
176
- const tokenID = ethers.utils.defaultAbiCoder.decode(["uint256"], log.topics[3])[0].toString();
186
+ const from = safeEncodeEIP55(abiCoder.decode(["address"], log.topics[1])[0]);
187
+ const to = safeEncodeEIP55(abiCoder.decode(["address"], log.topics[2])[0]);
188
+ const tokenID = abiCoder.decode(["uint256"], log.topics[3])[0].toString();
177
189
  const erc721Event = {
178
- blockNumber: block.number.toString(),
179
- timeStamp: block.timestamp.toString(),
180
- hash: tx.hash,
181
- nonce: tx.nonce.toString(),
182
- blockHash: block.hash,
190
+ blockNumber: block?.number.toString() || "0",
191
+ timeStamp: block?.timestamp.toString() || "0",
192
+ hash: tx?.hash || "",
193
+ nonce: tx?.nonce.toString() || "0",
194
+ blockHash: block?.hash || "",
183
195
  from,
184
196
  to,
185
- transactionIndex: block.transactions.indexOf(log.transactionHash).toString(),
186
- gas: tx.gasLimit.toString(),
187
- gasPrice: tx.gasPrice?.toString() || "",
188
- cumulativeGasUsed: receipt.cumulativeGasUsed.toString(),
197
+ transactionIndex: block?.transactions.indexOf(log.transactionHash).toString() || "0",
198
+ gas: tx?.gasLimit.toString() || "0",
199
+ gasPrice: tx?.gasPrice?.toString() || "",
200
+ cumulativeGasUsed: receipt?.cumulativeGasUsed.toString() || "0",
189
201
  gasUsed: receipt?.gasUsed?.toString() || "0",
190
- input: tx.data,
191
- confirmations: tx.confirmations.toString(),
192
- contractAddress: tx.to,
202
+ input: tx?.data || "0x",
203
+ confirmations: tx?.confirmations.toString() || "0",
204
+ contractAddress: tx?.to ?? "0x0000000000000000000000000000000000000000",
193
205
  tokenID,
194
206
  tokenName: "tokenName",
195
207
  tokenSymbol: "tokenSymbol",
@@ -209,8 +221,9 @@ const handleERC721Log = async (log, provider) => {
209
221
  if (!explorerLedgerOperationByAddress[to]) {
210
222
  explorerLedgerOperationByAddress[to] = new Map();
211
223
  }
212
- const alreadyExistingOperation = explorerLedgerOperationByAddress[from].get(tx.hash) ||
213
- explorerLedgerOperationByAddress[to].get(tx.hash);
224
+ const txHash = tx?.hash;
225
+ const alreadyExistingOperation = (txHash && explorerLedgerOperationByAddress[from].get(txHash)) ||
226
+ (txHash && explorerLedgerOperationByAddress[to].get(txHash));
214
227
  const ledgerOperation = alreadyExistingOperation
215
228
  ? {
216
229
  ...alreadyExistingOperation,
@@ -225,16 +238,16 @@ const handleERC721Log = async (log, provider) => {
225
238
  }
226
239
  : {
227
240
  hash: log.transactionHash,
228
- transaction_type: receipt.type,
241
+ transaction_type: receipt?.type ?? 0,
229
242
  nonce: "",
230
243
  nonce_value: -1,
231
- value: tx.value.toString(),
232
- gas: tx.gasLimit.toString(),
233
- gas_price: receipt.effectiveGasPrice.toString(),
234
- max_fee_per_gas: tx.type === 2 ? tx.maxFeePerGas.toString() : null,
235
- max_priority_fee_per_gas: tx.type === 2 ? tx.maxPriorityFeePerGas.toString() : null,
236
- from: tx.from,
237
- to: tx.to,
244
+ value: tx?.value.toString() ?? "0",
245
+ gas: tx?.gasLimit.toString() ?? "0",
246
+ gas_price: receipt?.gasPrice.toString() ?? "0",
247
+ max_fee_per_gas: tx?.type === 2 ? tx?.maxFeePerGas.toString() : null,
248
+ max_priority_fee_per_gas: tx?.type === 2 ? tx?.maxPriorityFeePerGas.toString() : null,
249
+ from: tx?.from ?? "0x",
250
+ to: tx?.to ?? "0x0000000000000000000000000000000000000000",
238
251
  transfer_events: [],
239
252
  erc721_transfer_events: [
240
253
  {
@@ -247,16 +260,16 @@ const handleERC721Log = async (log, provider) => {
247
260
  erc1155_transfer_events: [],
248
261
  approval_events: [],
249
262
  actions: [],
250
- confirmations: tx.confirmations,
263
+ confirmations: tx?.confirmations ? await tx.confirmations() : 0,
251
264
  input: null,
252
- gas_used: receipt.gasUsed.toString(),
253
- cumulative_gas_used: receipt.cumulativeGasUsed.toString(),
254
- status: receipt.status,
255
- received_at: new Date(block.timestamp * 1000).toISOString(),
265
+ gas_used: receipt?.gasUsed.toString() ?? "0",
266
+ cumulative_gas_used: receipt?.cumulativeGasUsed.toString() ?? "0",
267
+ status: receipt?.status ?? 0,
268
+ received_at: new Date((block?.timestamp ?? 0) * 1000).toISOString(),
256
269
  block: {
257
270
  hash: log.blockHash,
258
271
  height: log.blockNumber,
259
- time: new Date(block.timestamp * 1000).toISOString(),
272
+ time: new Date((block?.timestamp ?? 0) * 1000).toISOString(),
260
273
  },
261
274
  };
262
275
  explorerLedgerOperationByAddress[from].set(ledgerOperation.hash, ledgerOperation);
@@ -268,28 +281,28 @@ const handleERC1155Log = async (log, provider) => {
268
281
  provider.getTransaction(log.transactionHash),
269
282
  provider.getTransactionReceipt(log.transactionHash),
270
283
  ]);
271
- const from = safeEncodeEIP55(ethers.utils.defaultAbiCoder.decode(["address"], log.topics[2])[0]);
272
- const to = safeEncodeEIP55(ethers.utils.defaultAbiCoder.decode(["address"], log.topics[3])[0]);
273
- const operator = safeEncodeEIP55(ethers.utils.defaultAbiCoder.decode(["address"], log.topics[1])[0]);
274
- const transfersMap = ethers.utils.defaultAbiCoder
284
+ const from = safeEncodeEIP55(abiCoder.decode(["address"], log.topics[2])[0]);
285
+ const to = safeEncodeEIP55(abiCoder.decode(["address"], log.topics[3])[0]);
286
+ const operator = safeEncodeEIP55(abiCoder.decode(["address"], log.topics[1])[0]);
287
+ const transfersMap = abiCoder
275
288
  .decode(["uint256", "uint256"], log.data)
276
289
  .map((value, index) => [index === 0 ? "id" : "value", value.toString()]);
277
290
  const etherscanERC1155Events = transfersMap.map(([id, value]) => ({
278
- blockNumber: block.number.toString(),
279
- timeStamp: block.timestamp.toString(),
280
- hash: tx.hash,
281
- nonce: tx.nonce.toString(),
282
- blockHash: block.hash,
291
+ blockNumber: block?.number.toString() || "0",
292
+ timeStamp: block?.timestamp.toString() || "0",
293
+ hash: tx?.hash || "",
294
+ nonce: tx?.nonce.toString() || "0",
295
+ blockHash: block?.hash || "",
283
296
  from,
284
297
  to,
285
- transactionIndex: block.transactions.indexOf(log.transactionHash).toString(),
286
- gas: tx.gasLimit.toString(),
287
- gasPrice: tx.gasPrice?.toString() || "",
288
- cumulativeGasUsed: receipt.cumulativeGasUsed.toString(),
298
+ transactionIndex: block?.transactions.indexOf(log.transactionHash).toString() || "0",
299
+ gas: tx?.gasLimit.toString() || "0",
300
+ gasPrice: tx?.gasPrice?.toString() || "",
301
+ cumulativeGasUsed: receipt?.cumulativeGasUsed.toString() || "0",
289
302
  gasUsed: receipt?.gasUsed?.toString() || "0",
290
- input: tx.data,
291
- confirmations: tx.confirmations.toString(),
292
- contractAddress: tx.to,
303
+ input: tx?.data || "0x",
304
+ confirmations: tx?.confirmations.toString() || "0",
305
+ contractAddress: tx?.to ?? "0x0000000000000000000000000000000000000000",
293
306
  tokenID: id,
294
307
  tokenValue: value,
295
308
  tokenName: "tokenName",
@@ -311,8 +324,9 @@ const handleERC1155Log = async (log, provider) => {
311
324
  if (!explorerLedgerOperationByAddress[to]) {
312
325
  explorerLedgerOperationByAddress[to] = new Map();
313
326
  }
314
- const alreadyExistingOperation = explorerLedgerOperationByAddress[from].get(tx.hash) ||
315
- explorerLedgerOperationByAddress[to].get(tx.hash);
327
+ const txHash = tx?.hash;
328
+ const alreadyExistingOperation = (txHash && explorerLedgerOperationByAddress[from].get(txHash)) ||
329
+ (txHash && explorerLedgerOperationByAddress[to].get(txHash));
316
330
  const ledgerOperation = alreadyExistingOperation
317
331
  ? {
318
332
  ...alreadyExistingOperation,
@@ -327,17 +341,17 @@ const handleERC1155Log = async (log, provider) => {
327
341
  ],
328
342
  }
329
343
  : {
330
- hash: log.transactionHash,
331
- transaction_type: receipt.type,
344
+ hash: log.transactionHash || "",
345
+ transaction_type: receipt?.type ?? 0,
332
346
  nonce: "",
333
347
  nonce_value: -1,
334
- value: tx.value.toString(),
335
- gas: tx.gasLimit.toString(),
336
- gas_price: receipt.effectiveGasPrice.toString(),
337
- max_fee_per_gas: tx.type === 2 ? tx.maxFeePerGas.toString() : null,
338
- max_priority_fee_per_gas: tx.type === 2 ? tx.maxPriorityFeePerGas.toString() : null,
339
- from: tx.from,
340
- to: tx.to,
348
+ value: tx?.value.toString() || "0",
349
+ gas: tx?.gasLimit.toString() || "0",
350
+ gas_price: receipt?.gasPrice.toString() || "0",
351
+ max_fee_per_gas: tx?.type === 2 ? tx?.maxFeePerGas.toString() : null,
352
+ max_priority_fee_per_gas: tx?.type === 2 ? tx?.maxPriorityFeePerGas.toString() : null,
353
+ from: tx?.from ?? "0x",
354
+ to: tx?.to ?? "0x0000000000000000000000000000000000000000",
341
355
  transfer_events: [],
342
356
  erc721_transfer_events: [],
343
357
  erc1155_transfer_events: [
@@ -351,52 +365,52 @@ const handleERC1155Log = async (log, provider) => {
351
365
  ],
352
366
  approval_events: [],
353
367
  actions: [],
354
- confirmations: tx.confirmations,
368
+ confirmations: tx?.confirmations ? await tx.confirmations() : 0,
355
369
  input: null,
356
- gas_used: receipt.gasUsed.toString(),
357
- cumulative_gas_used: receipt.cumulativeGasUsed.toString(),
358
- status: receipt.status,
359
- received_at: new Date(block.timestamp * 1000).toISOString(),
370
+ gas_used: receipt?.gasUsed.toString() || "0",
371
+ cumulative_gas_used: receipt?.cumulativeGasUsed.toString() || "0",
372
+ status: receipt?.status ?? 0,
373
+ received_at: new Date((block?.timestamp ?? 0) * 1000).toISOString(),
360
374
  block: {
361
375
  hash: log.blockHash,
362
376
  height: log.blockNumber,
363
- time: new Date(block.timestamp * 1000).toISOString(),
377
+ time: new Date((block?.timestamp ?? 0) * 1000).toISOString(),
364
378
  },
365
379
  };
366
380
  explorerLedgerOperationByAddress[from].set(ledgerOperation.hash, ledgerOperation);
367
381
  explorerLedgerOperationByAddress[to].set(ledgerOperation.hash, ledgerOperation);
368
382
  };
369
383
  const handleBlock = async (blockNumber, provider) => {
370
- const block = await provider.getBlockWithTransactions(blockNumber);
384
+ const block = await provider.getBlock(blockNumber, true);
371
385
  for (const transaction of block?.transactions || []) {
372
386
  const [tx, receipt, traces] = await Promise.all([
373
- provider.getTransaction(transaction.hash),
374
- provider.getTransactionReceipt(transaction.hash),
375
- provider.send("trace_transaction", [transaction.hash]).catch(() => []),
387
+ provider.getTransaction(transaction),
388
+ provider.getTransactionReceipt(transaction),
389
+ provider.send("trace_transaction", [transaction]).catch(() => []),
376
390
  ]);
377
- const code = transaction.to ? await provider.getCode(transaction.to) : false;
378
- const from = safeEncodeEIP55(transaction.from);
379
- const to = safeEncodeEIP55(transaction.to || "");
391
+ const code = tx?.to ? await provider.getCode(tx?.to) : false;
392
+ const from = safeEncodeEIP55(tx?.from || "");
393
+ const to = safeEncodeEIP55(tx?.to || "");
380
394
  const etherscanOperation = {
381
- blockNumber: block.number.toString(),
382
- timeStamp: block.timestamp.toString(),
383
- hash: transaction.hash,
384
- nonce: transaction.nonce.toString(),
385
- blockHash: block.hash,
386
- transactionIndex: block.transactions.indexOf(transaction).toString(),
395
+ blockNumber: block?.number.toString() || "0",
396
+ timeStamp: block?.timestamp.toString() || "0",
397
+ hash: tx?.hash || "",
398
+ nonce: tx?.nonce.toString() || "0",
399
+ blockHash: block?.hash || "",
400
+ transactionIndex: block?.transactions.indexOf(transaction).toString() || "0",
387
401
  from,
388
402
  to,
389
- value: transaction.value.toBigInt().toString(),
390
- gas: transaction.gasLimit.toString(),
391
- gasPrice: transaction.gasPrice?.toString() || "",
392
- isError: receipt.status === 1 ? "0" : "1",
393
- txreceipt_status: receipt.status.toString(),
394
- input: transaction.data,
395
- contractAddress: code === "0x" ? "" : transaction.to,
396
- cumulativeGasUsed: receipt.cumulativeGasUsed.toString(),
403
+ value: tx?.value.toString() || "0",
404
+ gas: tx?.gasLimit.toString() || "0",
405
+ gasPrice: tx?.gasPrice?.toString() || "",
406
+ isError: receipt?.status === 1 ? "0" : "1",
407
+ txreceipt_status: receipt?.status.toString() || "0",
408
+ input: tx?.data,
409
+ contractAddress: code === "0x" ? "" : tx?.to ?? "0x0000000000000000000000000000000000000000",
410
+ cumulativeGasUsed: receipt?.cumulativeGasUsed.toString() || "0",
397
411
  gasUsed: receipt?.gasUsed?.toString() || "0",
398
- confirmations: transaction.confirmations.toString(),
399
- methodId: transaction.data?.length > 10 ? transaction.data.slice(0, 10) : "",
412
+ confirmations: tx?.confirmations.toString() || "0",
413
+ methodId: tx?.data && tx.data.length > 10 ? tx.data.slice(0, 10) : "",
400
414
  functionName: "",
401
415
  };
402
416
  if (!explorerEtherscanOperationByAddress[from]) {
@@ -414,32 +428,32 @@ const handleBlock = async (blockNumber, provider) => {
414
428
  explorerLedgerOperationByAddress[to] = new Map();
415
429
  }
416
430
  const ledgerOperation = {
417
- hash: receipt.transactionHash,
418
- transaction_type: receipt.type,
431
+ hash: receipt?.hash || "",
432
+ transaction_type: receipt?.type || 0,
419
433
  nonce: "",
420
434
  nonce_value: -1,
421
- value: tx.value.toString(),
422
- gas: tx.gasLimit.toString(),
423
- gas_price: receipt.effectiveGasPrice.toString(),
424
- max_fee_per_gas: tx.type === 2 ? tx.maxFeePerGas.toString() : null,
425
- max_priority_fee_per_gas: tx.type === 2 ? tx.maxPriorityFeePerGas.toString() : null,
426
- from: tx.from,
427
- to: tx.to,
435
+ value: tx?.value.toString() || "0",
436
+ gas: tx?.gasLimit.toString() || "0",
437
+ gas_price: receipt?.gasPrice.toString() || "",
438
+ max_fee_per_gas: tx?.type === 2 ? tx?.maxFeePerGas.toString() : null,
439
+ max_priority_fee_per_gas: tx?.type === 2 ? tx?.maxPriorityFeePerGas.toString() : null,
440
+ from: tx?.from || "",
441
+ to: tx?.to ?? "0x0000000000000000000000000000000000000000",
428
442
  transfer_events: [],
429
443
  erc721_transfer_events: [],
430
444
  erc1155_transfer_events: [],
431
445
  approval_events: [],
432
446
  actions: [],
433
- confirmations: tx.confirmations,
447
+ confirmations: tx?.confirmations ? await tx.confirmations() : 0,
434
448
  input: null,
435
- gas_used: receipt.gasUsed.toString(),
436
- cumulative_gas_used: receipt.cumulativeGasUsed.toString(),
437
- status: receipt.status,
438
- received_at: new Date(block.timestamp * 1000).toISOString(),
449
+ gas_used: receipt?.gasUsed.toString() || "0",
450
+ cumulative_gas_used: receipt?.cumulativeGasUsed.toString() || "0",
451
+ status: receipt?.status ?? 0,
452
+ received_at: new Date((block?.timestamp ?? 0) * 1000).toISOString(),
439
453
  block: {
440
- hash: receipt.blockHash,
441
- height: receipt.blockNumber,
442
- time: new Date(block.timestamp * 1000).toISOString(),
454
+ hash: receipt?.blockHash || "",
455
+ height: receipt?.blockNumber || 0,
456
+ time: new Date((block?.timestamp ?? 0) * 1000).toISOString(),
443
457
  },
444
458
  };
445
459
  explorerLedgerOperationByAddress[from].set(ledgerOperation.hash, ledgerOperation);
@@ -452,20 +466,18 @@ const handleBlock = async (blockNumber, provider) => {
452
466
  const to = safeEncodeEIP55(action.to || "");
453
467
  const etherscanInternalTransaction = {
454
468
  blockNumber: blockNumber.toString(),
455
- timeStamp: block.timestamp.toString(),
469
+ timeStamp: block?.timestamp.toString() || "0",
456
470
  hash: transactionHash,
457
471
  from,
458
472
  to,
459
- value: ethers.BigNumber.from(action.value).toBigInt().toString(),
473
+ value: BigInt(action.value).toString() || "0",
460
474
  contractAddress: code === "0x" ? "" : action.to,
461
475
  input: action.input || "0x",
462
476
  type,
463
- gas: ethers.BigNumber.from(action.gas).toBigInt().toString(),
464
- gasUsed: ethers.BigNumber.from(result?.gasUsed || "0")
465
- .toBigInt()
466
- .toString(),
477
+ gas: BigInt(action.gas).toString(),
478
+ gasUsed: BigInt(result?.gasUsed || "0").toString(),
467
479
  traceId: transactionPosition.toString(),
468
- isError: receipt.status === 1 ? "0" : "1",
480
+ isError: receipt?.status === 1 ? "0" : "1",
469
481
  errCode: "",
470
482
  };
471
483
  if (!explorerEtherscanInternalByAddress[from]) {
@@ -482,8 +494,9 @@ const handleBlock = async (blockNumber, provider) => {
482
494
  if (!explorerLedgerOperationByAddress[to]) {
483
495
  explorerLedgerOperationByAddress[to] = new Map();
484
496
  }
485
- const alreadyExistingOperation = explorerLedgerOperationByAddress[from].get(tx.hash) ||
486
- explorerLedgerOperationByAddress[to].get(tx.hash);
497
+ const txHash = tx?.hash;
498
+ const alreadyExistingOperation = (txHash && explorerLedgerOperationByAddress[from].get(txHash)) ||
499
+ (txHash && explorerLedgerOperationByAddress[to].get(txHash));
487
500
  const ledgerOperation = alreadyExistingOperation
488
501
  ? {
489
502
  ...alreadyExistingOperation,
@@ -493,27 +506,25 @@ const handleBlock = async (blockNumber, provider) => {
493
506
  from,
494
507
  to,
495
508
  input: null,
496
- value: ethers.BigNumber.from(action.value).toBigInt().toString(),
497
- gas: ethers.BigNumber.from(action.gas).toBigInt().toString(),
498
- gas_used: ethers.BigNumber.from(result?.gasUsed || "0")
499
- .toBigInt()
500
- .toString(),
509
+ value: BigInt(action.value).toString(),
510
+ gas: BigInt(action.gas).toString(),
511
+ gas_used: BigInt(result?.gasUsed || "0").toString(),
501
512
  error: null,
502
513
  },
503
514
  ],
504
515
  }
505
516
  : {
506
- hash: receipt.transactionHash,
507
- transaction_type: receipt.type,
517
+ hash: receipt?.hash || "",
518
+ transaction_type: receipt?.type ?? 0,
508
519
  nonce: "",
509
520
  nonce_value: -1,
510
- value: tx.value.toString(),
511
- gas: tx.gasLimit.toString(),
512
- gas_price: receipt.effectiveGasPrice.toString(),
513
- max_fee_per_gas: tx.type === 2 ? tx.maxFeePerGas.toString() : null,
514
- max_priority_fee_per_gas: tx.type === 2 ? tx.maxPriorityFeePerGas.toString() : null,
515
- from: tx.from,
516
- to: tx.to,
521
+ value: tx?.value.toString() || "0",
522
+ gas: tx?.gasLimit.toString() || "0",
523
+ gas_price: receipt?.gasPrice.toString() || "0",
524
+ max_fee_per_gas: tx?.type === 2 ? tx?.maxFeePerGas.toString() : null,
525
+ max_priority_fee_per_gas: tx?.type === 2 ? tx?.maxPriorityFeePerGas.toString() : null,
526
+ from: tx?.from || "0x",
527
+ to: tx?.to ?? "0x0000000000000000000000000000000000000000",
517
528
  transfer_events: [],
518
529
  erc721_transfer_events: [],
519
530
  erc1155_transfer_events: [],
@@ -523,24 +534,22 @@ const handleBlock = async (blockNumber, provider) => {
523
534
  from,
524
535
  to,
525
536
  input: null,
526
- value: ethers.BigNumber.from(action.value).toBigInt().toString(),
527
- gas: ethers.BigNumber.from(action.gas).toBigInt().toString(),
528
- gas_used: ethers.BigNumber.from(result?.gasUsed || "0")
529
- .toBigInt()
530
- .toString(),
537
+ value: BigInt(action.value).toString(),
538
+ gas: BigInt(action.gas).toString(),
539
+ gas_used: BigInt(result?.gasUsed || "0").toString(),
531
540
  error: null,
532
541
  },
533
542
  ],
534
- confirmations: tx.confirmations,
543
+ confirmations: tx?.confirmations ? await tx.confirmations() : 0,
535
544
  input: null,
536
- gas_used: receipt.gasUsed.toString(),
537
- cumulative_gas_used: receipt.cumulativeGasUsed.toString(),
538
- status: receipt.status,
539
- received_at: new Date(block.timestamp * 1000).toISOString(),
545
+ gas_used: receipt?.gasUsed.toString() || "0",
546
+ cumulative_gas_used: receipt?.cumulativeGasUsed.toString() || "0",
547
+ status: receipt?.status ?? 0,
548
+ received_at: new Date((block?.timestamp ?? 0) * 1000).toISOString(),
540
549
  block: {
541
- hash: receipt.blockHash,
542
- height: receipt.blockNumber,
543
- time: new Date(block.timestamp * 1000).toISOString(),
550
+ hash: receipt?.blockHash || "",
551
+ height: receipt?.blockNumber || 0,
552
+ time: new Date((block?.timestamp ?? 0) * 1000).toISOString(),
544
553
  },
545
554
  };
546
555
  explorerLedgerOperationByAddress[from].set(ledgerOperation.hash, ledgerOperation);
@@ -555,7 +564,7 @@ export const indexBlocks = async () => {
555
564
  if (!fromBlock) {
556
565
  throw new Error("fromBlock is not set");
557
566
  }
558
- const provider = new providers.StaticJsonRpcProvider(process.env.RPC);
567
+ const provider = new ethers.JsonRpcProvider(process.env.RPC);
559
568
  let latestBlockNumber = await provider.getBlockNumber();
560
569
  const toBlock = Math.min(fromBlock + MAX_BLOCK_RANGE, latestBlockNumber);
561
570
  const rangeSize = toBlock - fromBlock + 1;