@0xtorch/evm 0.0.8 → 0.0.9

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 (38) hide show
  1. package/_cjs/decoder/tests.js +9 -0
  2. package/_cjs/decoder/tests.js.map +1 -1
  3. package/_cjs/explorers/definitions/blockscout.js +97 -0
  4. package/_cjs/explorers/definitions/blockscout.js.map +1 -1
  5. package/_cjs/explorers/definitions/etherscan.js +152 -0
  6. package/_cjs/explorers/definitions/etherscan.js.map +1 -1
  7. package/_cjs/explorers/definitions/roninExplorer.js +70 -0
  8. package/_cjs/explorers/definitions/roninExplorer.js.map +1 -1
  9. package/_cjs/explorers/definitions/routescan.js +12 -0
  10. package/_cjs/explorers/definitions/routescan.js.map +1 -1
  11. package/_esm/decoder/tests.js +9 -0
  12. package/_esm/decoder/tests.js.map +1 -1
  13. package/_esm/explorers/definitions/blockscout.js +99 -1
  14. package/_esm/explorers/definitions/blockscout.js.map +1 -1
  15. package/_esm/explorers/definitions/etherscan.js +155 -0
  16. package/_esm/explorers/definitions/etherscan.js.map +1 -1
  17. package/_esm/explorers/definitions/roninExplorer.js +70 -0
  18. package/_esm/explorers/definitions/roninExplorer.js.map +1 -1
  19. package/_esm/explorers/definitions/routescan.js +15 -0
  20. package/_esm/explorers/definitions/routescan.js.map +1 -1
  21. package/_types/decoder/tests.d.ts.map +1 -1
  22. package/_types/explorers/definitions/blockscout.d.ts +28 -1
  23. package/_types/explorers/definitions/blockscout.d.ts.map +1 -1
  24. package/_types/explorers/definitions/etherscan.d.ts +28 -1
  25. package/_types/explorers/definitions/etherscan.d.ts.map +1 -1
  26. package/_types/explorers/definitions/roninExplorer.d.ts +26 -0
  27. package/_types/explorers/definitions/roninExplorer.d.ts.map +1 -1
  28. package/_types/explorers/definitions/routescan.d.ts +3 -0
  29. package/_types/explorers/definitions/routescan.d.ts.map +1 -1
  30. package/_types/explorers/types.d.ts +30 -0
  31. package/_types/explorers/types.d.ts.map +1 -1
  32. package/decoder/tests.ts +9 -0
  33. package/explorers/definitions/blockscout.ts +141 -1
  34. package/explorers/definitions/etherscan.ts +211 -0
  35. package/explorers/definitions/roninExplorer.ts +99 -0
  36. package/explorers/definitions/routescan.ts +15 -0
  37. package/explorers/types.ts +37 -0
  38. package/package.json +1 -1
@@ -5,8 +5,11 @@ export type Explorer = {
5
5
  readonly url: string;
6
6
  readonly apiUrl: string;
7
7
  readonly getAddressTransactionHashes: FunctionGetAddressTransactionHashes;
8
+ readonly getAddressTransactionHashesWithTimestamp: FunctionGetAddressTransactionHashesWithTimestamp;
8
9
  readonly getAddressInternalTransactions: FunctionGetAddressInternalTransactions;
10
+ readonly getAddressInternalTransactionsWithTimestamp: FunctionGetAddressInternalTransactionsWithTimestamp;
9
11
  readonly getAddressTokenTransferHashes: FunctionGetAddressTokenTransferHashes;
12
+ readonly getAddressTokenTransferHashesWithTimestamp: FunctionGetAddressTokenTransferHashesWithTimestamp;
10
13
  readonly getBlockNumberOfTimestamp: (timestamp: number, logger?: Logger) => Promise<bigint>;
11
14
  readonly getContract: FunctionGetContract;
12
15
  readonly getInternalTransactionOfTransaction: FunctionGetInternalTransactionOfTransaction;
@@ -17,6 +20,15 @@ type FunctionGetAddressTransactionHashes = (parameters: {
17
20
  readonly endBlock?: bigint;
18
21
  readonly logger?: Logger;
19
22
  }) => Promise<readonly Hex[]>;
23
+ type FunctionGetAddressTransactionHashesWithTimestamp = (parameters: {
24
+ readonly address: Hex;
25
+ readonly startBlock?: bigint;
26
+ readonly endBlock?: bigint;
27
+ readonly logger?: Logger;
28
+ }) => Promise<readonly {
29
+ readonly hash: Hex;
30
+ readonly timestamp: number;
31
+ }[]>;
20
32
  type FunctionGetAddressInternalTransactions = (parameters: {
21
33
  readonly address: Hex;
22
34
  readonly startBlock?: bigint;
@@ -24,12 +36,30 @@ type FunctionGetAddressInternalTransactions = (parameters: {
24
36
  readonly nativeCurrency: CryptoCurrency;
25
37
  readonly logger?: Logger;
26
38
  }) => Promise<readonly InternalTransaction<undefined>[]>;
39
+ type FunctionGetAddressInternalTransactionsWithTimestamp = (parameters: {
40
+ readonly address: Hex;
41
+ readonly startBlock?: bigint;
42
+ readonly endBlock?: bigint;
43
+ readonly nativeCurrency: CryptoCurrency;
44
+ readonly logger?: Logger;
45
+ }) => Promise<readonly (InternalTransaction<undefined> & {
46
+ readonly timestamp: number;
47
+ })[]>;
27
48
  type FunctionGetAddressTokenTransferHashes = (parameters: {
28
49
  readonly address: Hex;
29
50
  readonly startBlock?: bigint;
30
51
  readonly endBlock?: bigint;
31
52
  readonly logger?: Logger;
32
53
  }) => Promise<readonly Hex[]>;
54
+ type FunctionGetAddressTokenTransferHashesWithTimestamp = (parameters: {
55
+ readonly address: Hex;
56
+ readonly startBlock?: bigint;
57
+ readonly endBlock?: bigint;
58
+ readonly logger?: Logger;
59
+ }) => Promise<readonly {
60
+ readonly hash: Hex;
61
+ readonly timestamp: number;
62
+ }[]>;
33
63
  type FunctionGetContract = (address: Hex, logger?: Logger) => Promise<{
34
64
  readonly name: string;
35
65
  readonly abi: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../explorers/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAC3D,OAAO,KAAK,EAAE,GAAG,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAExD,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,2BAA2B,EAAE,mCAAmC,CAAA;IACzE,QAAQ,CAAC,8BAA8B,EAAE,sCAAsC,CAAA;IAC/E,QAAQ,CAAC,6BAA6B,EAAE,qCAAqC,CAAA;IAC7E,QAAQ,CAAC,yBAAyB,EAAE,CAClC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,KACZ,OAAO,CAAC,MAAM,CAAC,CAAA;IACpB,QAAQ,CAAC,WAAW,EAAE,mBAAmB,CAAA;IACzC,QAAQ,CAAC,mCAAmC,EAAE,2CAA2C,CAAA;CAC1F,CAAA;AAED,KAAK,mCAAmC,GAAG,CAAC,UAAU,EAAE;IACtD,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAA;IACrB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB,KAAK,OAAO,CAAC,SAAS,GAAG,EAAE,CAAC,CAAA;AAE7B,KAAK,sCAAsC,GAAG,CAAC,UAAU,EAAE;IACzD,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAA;IACrB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAA;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB,KAAK,OAAO,CAAC,SAAS,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;AAExD,KAAK,qCAAqC,GAAG,CAAC,UAAU,EAAE;IACxD,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAA;IACrB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB,KAAK,OAAO,CAAC,SAAS,GAAG,EAAE,CAAC,CAAA;AAE7B,KAAK,mBAAmB,GAAG,CACzB,OAAO,EAAE,GAAG,EACZ,MAAM,CAAC,EAAE,MAAM,KACZ,OAAO,CACR;IACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB,GACD,SAAS,CACZ,CAAA;AAED,KAAK,2CAA2C,GAAG,CAAC,UAAU,EAAE;IAC9D,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAA;IAClB,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAA;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB,KAAK,OAAO,CAAC,SAAS,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../explorers/types.ts"],"names":[],"mappings":"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"}
package/decoder/tests.ts CHANGED
@@ -73,6 +73,15 @@ const testExplorer: Explorer = {
73
73
  getInternalTransactionOfTransaction: () => {
74
74
  throw new Error('Not implemented')
75
75
  },
76
+ getAddressTransactionHashesWithTimestamp: () => {
77
+ throw new Error('not implemented')
78
+ },
79
+ getAddressInternalTransactionsWithTimestamp: () => {
80
+ throw new Error('not implemented')
81
+ },
82
+ getAddressTokenTransferHashesWithTimestamp: () => {
83
+ throw new Error('not implemented')
84
+ },
76
85
  }
77
86
 
78
87
  export const testChain = createEthereumChainCustom({
@@ -133,7 +133,7 @@ export const createBlockscout = <
133
133
  const loop = true
134
134
  const hashSet = new Set<LowerHex>()
135
135
 
136
- // erc20 transfer
136
+ // token transfer
137
137
  let mut_startBlock = startBlock
138
138
  while (loop) {
139
139
  const transfers = await getTokenTransfersByAddress({
@@ -202,4 +202,144 @@ export const createBlockscout = <
202
202
  price: undefined,
203
203
  }))
204
204
  },
205
+ getAddressTransactionHashesWithTimestamp: async ({
206
+ address,
207
+ startBlock,
208
+ endBlock,
209
+ logger,
210
+ }) => {
211
+ const loop = true
212
+ const mut_hashesWithTimestamp: {
213
+ readonly hash: LowerHex
214
+ readonly timestamp: number
215
+ }[] = []
216
+ let mut_startBlock = startBlock
217
+ while (loop) {
218
+ const transactions = await getNormalTransactionsByAddress({
219
+ apiEndpoint: apiUrl,
220
+ address,
221
+ startBlock: mut_startBlock,
222
+ endBlock,
223
+ logger,
224
+ })
225
+ for (const { hash, timeStamp } of transactions) {
226
+ if (mut_hashesWithTimestamp.every(({ hash: h }) => h !== hash)) {
227
+ mut_hashesWithTimestamp.push({ hash, timestamp: timeStamp })
228
+ }
229
+ }
230
+ if (transactions.length < 10_000) {
231
+ break
232
+ }
233
+ const maxTxBlockNumber = transactions.reduce(
234
+ (max, { blockNumber }) =>
235
+ max < BigInt(blockNumber) ? BigInt(blockNumber) : max,
236
+ 0n,
237
+ )
238
+ if (maxTxBlockNumber === 0n || maxTxBlockNumber === mut_startBlock) {
239
+ break
240
+ }
241
+ mut_startBlock = maxTxBlockNumber
242
+ }
243
+ return mut_hashesWithTimestamp
244
+ },
245
+ getAddressInternalTransactionsWithTimestamp: async ({
246
+ address,
247
+ startBlock,
248
+ endBlock,
249
+ nativeCurrency,
250
+ logger,
251
+ }) => {
252
+ const loop = true
253
+ const mut_internalTransactionsWithTimestamp: (InternalTransaction<undefined> & {
254
+ readonly timestamp: number
255
+ })[] = []
256
+ let mut_startBlock = startBlock
257
+ while (loop) {
258
+ const transactions = await getInternalTransactionsByAddress({
259
+ apiEndpoint: apiUrl,
260
+ address,
261
+ startBlock: mut_startBlock,
262
+ endBlock,
263
+ logger,
264
+ })
265
+ for (const transaction of transactions) {
266
+ if (
267
+ mut_internalTransactionsWithTimestamp.some(
268
+ ({ transactionHash, from, to, value }) =>
269
+ transaction.transactionHash === transactionHash &&
270
+ transaction.from === from &&
271
+ transaction.to === to &&
272
+ transaction.value === value,
273
+ )
274
+ ) {
275
+ continue
276
+ }
277
+ mut_internalTransactionsWithTimestamp.push({
278
+ ...transaction,
279
+ type: 'InternalTransaction',
280
+ to: transaction.to,
281
+ contractAddress: transaction.contractAddress,
282
+ txType: transaction.type,
283
+ currency: nativeCurrency,
284
+ price: undefined,
285
+ timestamp: transaction.timeStamp,
286
+ })
287
+ }
288
+ if (transactions.length < 10_000) {
289
+ break
290
+ }
291
+ const maxTxBlockNumber = transactions.reduce(
292
+ (max, { blockNumber }) =>
293
+ max < BigInt(blockNumber) ? BigInt(blockNumber) : max,
294
+ 0n,
295
+ )
296
+ if (maxTxBlockNumber === 0n || maxTxBlockNumber === mut_startBlock) {
297
+ break
298
+ }
299
+ mut_startBlock = maxTxBlockNumber
300
+ }
301
+ return mut_internalTransactionsWithTimestamp
302
+ },
303
+ getAddressTokenTransferHashesWithTimestamp: async ({
304
+ address,
305
+ startBlock,
306
+ endBlock,
307
+ logger,
308
+ }) => {
309
+ const loop = true
310
+ const mut_hashesWithTimestamp: {
311
+ readonly hash: LowerHex
312
+ readonly timestamp: number
313
+ }[] = []
314
+
315
+ // token transfer
316
+ let mut_startBlock = startBlock
317
+ while (loop) {
318
+ const transfers = await getTokenTransfersByAddress({
319
+ apiEndpoint: apiUrl,
320
+ address,
321
+ startBlock: mut_startBlock,
322
+ endBlock,
323
+ logger,
324
+ })
325
+ for (const { hash, timeStamp } of transfers) {
326
+ if (mut_hashesWithTimestamp.every(({ hash: h }) => h !== hash)) {
327
+ mut_hashesWithTimestamp.push({ hash, timestamp: timeStamp })
328
+ }
329
+ }
330
+ if (transfers.length < 10_000) {
331
+ break
332
+ }
333
+ const maxTxBlockNumber = transfers.reduce(
334
+ (max, { blockNumber }) =>
335
+ max < BigInt(blockNumber) ? BigInt(blockNumber) : max,
336
+ 0n,
337
+ )
338
+ if (maxTxBlockNumber === 0n || maxTxBlockNumber === mut_startBlock) {
339
+ break
340
+ }
341
+ mut_startBlock = maxTxBlockNumber
342
+ }
343
+ return mut_hashesWithTimestamp
344
+ },
205
345
  })
@@ -276,4 +276,215 @@ export const createEtherscan = <
276
276
  price: undefined,
277
277
  }))
278
278
  },
279
+ getAddressTransactionHashesWithTimestamp: async ({
280
+ address,
281
+ startBlock,
282
+ endBlock,
283
+ logger,
284
+ }) => {
285
+ const loop = true
286
+ const mut_hashesWithTimestamp: {
287
+ readonly hash: LowerHex
288
+ readonly timestamp: number
289
+ }[] = []
290
+ let mut_startBlock = startBlock
291
+ while (loop) {
292
+ const transactions = await getNormalTransactionsByAddress({
293
+ apiEndpoint: apiUrl,
294
+ apiKey,
295
+ address,
296
+ startBlock: mut_startBlock,
297
+ endBlock,
298
+ logger,
299
+ })
300
+ for (const { hash, timeStamp } of transactions) {
301
+ if (mut_hashesWithTimestamp.every(({ hash: h }) => h !== hash)) {
302
+ mut_hashesWithTimestamp.push({ hash, timestamp: timeStamp })
303
+ }
304
+ }
305
+ if (transactions.length < 10_000) {
306
+ break
307
+ }
308
+ const maxTxBlockNumber = transactions.reduce(
309
+ (max, { blockNumber }) =>
310
+ max < BigInt(blockNumber) ? BigInt(blockNumber) : max,
311
+ 0n,
312
+ )
313
+ if (maxTxBlockNumber === 0n || maxTxBlockNumber === mut_startBlock) {
314
+ break
315
+ }
316
+ mut_startBlock = maxTxBlockNumber
317
+ }
318
+ return mut_hashesWithTimestamp
319
+ },
320
+ getAddressInternalTransactionsWithTimestamp: async ({
321
+ address,
322
+ startBlock,
323
+ endBlock,
324
+ nativeCurrency,
325
+ logger,
326
+ }) => {
327
+ const loop = true
328
+ const mut_internalTransactionsWithTimestamp: (InternalTransaction<undefined> & {
329
+ readonly timestamp: number
330
+ })[] = []
331
+ let mut_startBlock = startBlock
332
+ while (loop) {
333
+ const transactions = await getInternalTransactionsByAddress({
334
+ apiEndpoint: apiUrl,
335
+ apiKey,
336
+ address,
337
+ startBlock: mut_startBlock,
338
+ endBlock,
339
+ logger,
340
+ })
341
+ for (const transaction of transactions) {
342
+ if (
343
+ mut_internalTransactionsWithTimestamp.some(
344
+ ({ transactionHash, from, to, value }) =>
345
+ transaction.hash === transactionHash &&
346
+ transaction.from === from &&
347
+ transaction.to === to &&
348
+ transaction.value === value,
349
+ )
350
+ ) {
351
+ continue
352
+ }
353
+ mut_internalTransactionsWithTimestamp.push({
354
+ ...transaction,
355
+ type: 'InternalTransaction',
356
+ transactionHash: transaction.hash,
357
+ to: transaction.to,
358
+ contractAddress: transaction.contractAddress,
359
+ txType: transaction.type,
360
+ currency: nativeCurrency,
361
+ price: undefined,
362
+ timestamp: transaction.timeStamp,
363
+ })
364
+ }
365
+ if (transactions.length < 10_000) {
366
+ break
367
+ }
368
+ const maxTxBlockNumber = transactions.reduce(
369
+ (max, { blockNumber }) =>
370
+ max < BigInt(blockNumber) ? BigInt(blockNumber) : max,
371
+ 0n,
372
+ )
373
+ if (maxTxBlockNumber === 0n || maxTxBlockNumber === mut_startBlock) {
374
+ break
375
+ }
376
+ mut_startBlock = maxTxBlockNumber
377
+ }
378
+ return mut_internalTransactionsWithTimestamp
379
+ },
380
+ getAddressTokenTransferHashesWithTimestamp: async ({
381
+ address,
382
+ startBlock,
383
+ endBlock,
384
+ logger,
385
+ }) => {
386
+ const loop = true
387
+ const mut_hashesWithTimestamp: {
388
+ readonly hash: LowerHex
389
+ readonly timestamp: number
390
+ }[] = []
391
+
392
+ // erc20 transfer
393
+ let mut_erc20StartBlock = startBlock
394
+ while (loop) {
395
+ const transfers = await getErc20TokenTransfersByAddress({
396
+ apiEndpoint: apiUrl,
397
+ apiKey,
398
+ address,
399
+ startBlock: mut_erc20StartBlock,
400
+ endBlock,
401
+ logger,
402
+ })
403
+ for (const { hash, timeStamp } of transfers) {
404
+ if (mut_hashesWithTimestamp.every(({ hash: h }) => h !== hash)) {
405
+ mut_hashesWithTimestamp.push({ hash, timestamp: timeStamp })
406
+ }
407
+ }
408
+ if (transfers.length < 10_000) {
409
+ break
410
+ }
411
+ const maxTxBlockNumber = transfers.reduce(
412
+ (max, { blockNumber }) =>
413
+ max < BigInt(blockNumber) ? BigInt(blockNumber) : max,
414
+ 0n,
415
+ )
416
+ if (
417
+ maxTxBlockNumber === 0n ||
418
+ maxTxBlockNumber === mut_erc20StartBlock
419
+ ) {
420
+ break
421
+ }
422
+ mut_erc20StartBlock = maxTxBlockNumber
423
+ }
424
+ // erc721 transfer
425
+ let mut_erc721StartBlock = startBlock
426
+ while (loop) {
427
+ const transfers = await getErc721TokenTransfersByAddress({
428
+ apiEndpoint: apiUrl,
429
+ apiKey,
430
+ address,
431
+ startBlock: mut_erc721StartBlock,
432
+ endBlock,
433
+ logger,
434
+ })
435
+ for (const { hash, timeStamp } of transfers) {
436
+ if (mut_hashesWithTimestamp.every(({ hash: h }) => h !== hash)) {
437
+ mut_hashesWithTimestamp.push({ hash, timestamp: timeStamp })
438
+ }
439
+ }
440
+ if (transfers.length < 10_000) {
441
+ break
442
+ }
443
+ const maxTxBlockNumber = transfers.reduce(
444
+ (max, { blockNumber }) =>
445
+ max < BigInt(blockNumber) ? BigInt(blockNumber) : max,
446
+ 0n,
447
+ )
448
+ if (
449
+ maxTxBlockNumber === 0n ||
450
+ maxTxBlockNumber === mut_erc721StartBlock
451
+ ) {
452
+ break
453
+ }
454
+ mut_erc721StartBlock = maxTxBlockNumber
455
+ }
456
+ // erc1155 transfer
457
+ let mut_erc1155StartBlock = startBlock
458
+ while (loop) {
459
+ const transfers = await getErc1155TokenTransfersByAddress({
460
+ apiEndpoint: apiUrl,
461
+ apiKey,
462
+ address,
463
+ startBlock: mut_erc1155StartBlock,
464
+ endBlock,
465
+ logger,
466
+ })
467
+ for (const { hash, timeStamp } of transfers) {
468
+ if (mut_hashesWithTimestamp.every(({ hash: h }) => h !== hash)) {
469
+ mut_hashesWithTimestamp.push({ hash, timestamp: timeStamp })
470
+ }
471
+ }
472
+ if (transfers.length < 10_000) {
473
+ break
474
+ }
475
+ const maxTxBlockNumber = transfers.reduce(
476
+ (max, { blockNumber }) =>
477
+ max < BigInt(blockNumber) ? BigInt(blockNumber) : max,
478
+ 0n,
479
+ )
480
+ if (
481
+ maxTxBlockNumber === 0n ||
482
+ maxTxBlockNumber === mut_erc1155StartBlock
483
+ ) {
484
+ break
485
+ }
486
+ mut_erc1155StartBlock = maxTxBlockNumber
487
+ }
488
+ return mut_hashesWithTimestamp
489
+ },
279
490
  })
@@ -1,4 +1,5 @@
1
1
  import type { Hex } from 'viem'
2
+ import type { LowerHex } from '../../types'
2
3
  import {
3
4
  getInternalTransactionByHash,
4
5
  getNormalTransactionsByAddress,
@@ -147,4 +148,102 @@ export const createRoninExplorer = <
147
148
  price: undefined,
148
149
  }))
149
150
  },
151
+ getAddressTransactionHashesWithTimestamp: async ({
152
+ address,
153
+ startBlock,
154
+ endBlock,
155
+ logger,
156
+ }) => {
157
+ const mut_hashesWithTimestamp: {
158
+ readonly hash: LowerHex
159
+ readonly timestamp: number
160
+ }[] = []
161
+ let mut_from = 0
162
+ while (mut_from >= 0) {
163
+ const { total, transactions } = await getNormalTransactionsByAddress({
164
+ apiEndpoint: explorerApiUrl,
165
+ address,
166
+ size: 100,
167
+ from: mut_from,
168
+ logger,
169
+ })
170
+ for (const transaction of transactions) {
171
+ if (
172
+ startBlock !== undefined &&
173
+ BigInt(transaction.block_number) < startBlock
174
+ ) {
175
+ return mut_hashesWithTimestamp
176
+ }
177
+ if (
178
+ (endBlock === undefined ||
179
+ BigInt(transaction.block_number) <= endBlock) &&
180
+ mut_hashesWithTimestamp.every(
181
+ ({ hash }) => hash !== transaction.hash,
182
+ )
183
+ ) {
184
+ mut_hashesWithTimestamp.push({
185
+ hash: transaction.hash,
186
+ timestamp: transaction.timestamp,
187
+ })
188
+ }
189
+ }
190
+ mut_from += transactions.length
191
+ if (mut_from + transactions.length >= total) {
192
+ break
193
+ }
194
+ }
195
+ return mut_hashesWithTimestamp
196
+ },
197
+ getAddressInternalTransactionsWithTimestamp: ({ logger }) => {
198
+ if (logger !== undefined) {
199
+ logger.info('getAddressInternalTransactions is not implemented')
200
+ }
201
+ return Promise.resolve([])
202
+ },
203
+ getAddressTokenTransferHashesWithTimestamp: async ({
204
+ address,
205
+ startBlock,
206
+ endBlock,
207
+ logger,
208
+ }) => {
209
+ const mut_hashesWithTimestamp: {
210
+ readonly hash: LowerHex
211
+ readonly timestamp: number
212
+ }[] = []
213
+ let mut_from = 0
214
+ while (mut_from >= 0) {
215
+ const { total, transfers } = await getTokenTransfersByAddress({
216
+ apiEndpoint: explorerApiUrl,
217
+ address,
218
+ size: 100,
219
+ from: mut_from,
220
+ logger,
221
+ })
222
+ for (const transfer of transfers) {
223
+ if (
224
+ startBlock !== undefined &&
225
+ BigInt(transfer.block_number) < startBlock
226
+ ) {
227
+ return mut_hashesWithTimestamp
228
+ }
229
+ if (
230
+ (endBlock === undefined ||
231
+ BigInt(transfer.block_number) <= endBlock) &&
232
+ mut_hashesWithTimestamp.every(
233
+ ({ hash }) => hash !== transfer.tx_hash,
234
+ )
235
+ ) {
236
+ mut_hashesWithTimestamp.push({
237
+ hash: transfer.tx_hash,
238
+ timestamp: transfer.timestamp,
239
+ })
240
+ }
241
+ }
242
+ mut_from += transfers.length
243
+ if (mut_from + transfers.length >= total) {
244
+ break
245
+ }
246
+ }
247
+ return mut_hashesWithTimestamp
248
+ },
150
249
  })
@@ -54,4 +54,19 @@ export const createRoutescan = <
54
54
  await new Promise((resolve) => setTimeout(resolve))
55
55
  throw new Error('not implemented')
56
56
  },
57
+ getAddressTransactionHashesWithTimestamp: async () => {
58
+ // TODO implement
59
+ await new Promise((resolve) => setTimeout(resolve))
60
+ throw new Error('not implemented')
61
+ },
62
+ getAddressInternalTransactionsWithTimestamp: async () => {
63
+ // TODO implement
64
+ await new Promise((resolve) => setTimeout(resolve))
65
+ throw new Error('not implemented')
66
+ },
67
+ getAddressTokenTransferHashesWithTimestamp: async () => {
68
+ // TODO implement
69
+ await new Promise((resolve) => setTimeout(resolve))
70
+ throw new Error('not implemented')
71
+ },
57
72
  })
@@ -6,8 +6,11 @@ export type Explorer = {
6
6
  readonly url: string
7
7
  readonly apiUrl: string
8
8
  readonly getAddressTransactionHashes: FunctionGetAddressTransactionHashes
9
+ readonly getAddressTransactionHashesWithTimestamp: FunctionGetAddressTransactionHashesWithTimestamp
9
10
  readonly getAddressInternalTransactions: FunctionGetAddressInternalTransactions
11
+ readonly getAddressInternalTransactionsWithTimestamp: FunctionGetAddressInternalTransactionsWithTimestamp
10
12
  readonly getAddressTokenTransferHashes: FunctionGetAddressTokenTransferHashes
13
+ readonly getAddressTokenTransferHashesWithTimestamp: FunctionGetAddressTokenTransferHashesWithTimestamp
11
14
  readonly getBlockNumberOfTimestamp: (
12
15
  timestamp: number,
13
16
  logger?: Logger,
@@ -23,6 +26,18 @@ type FunctionGetAddressTransactionHashes = (parameters: {
23
26
  readonly logger?: Logger
24
27
  }) => Promise<readonly Hex[]>
25
28
 
29
+ type FunctionGetAddressTransactionHashesWithTimestamp = (parameters: {
30
+ readonly address: Hex
31
+ readonly startBlock?: bigint
32
+ readonly endBlock?: bigint
33
+ readonly logger?: Logger
34
+ }) => Promise<
35
+ readonly {
36
+ readonly hash: Hex
37
+ readonly timestamp: number
38
+ }[]
39
+ >
40
+
26
41
  type FunctionGetAddressInternalTransactions = (parameters: {
27
42
  readonly address: Hex
28
43
  readonly startBlock?: bigint
@@ -31,6 +46,16 @@ type FunctionGetAddressInternalTransactions = (parameters: {
31
46
  readonly logger?: Logger
32
47
  }) => Promise<readonly InternalTransaction<undefined>[]>
33
48
 
49
+ type FunctionGetAddressInternalTransactionsWithTimestamp = (parameters: {
50
+ readonly address: Hex
51
+ readonly startBlock?: bigint
52
+ readonly endBlock?: bigint
53
+ readonly nativeCurrency: CryptoCurrency
54
+ readonly logger?: Logger
55
+ }) => Promise<
56
+ readonly (InternalTransaction<undefined> & { readonly timestamp: number })[]
57
+ >
58
+
34
59
  type FunctionGetAddressTokenTransferHashes = (parameters: {
35
60
  readonly address: Hex
36
61
  readonly startBlock?: bigint
@@ -38,6 +63,18 @@ type FunctionGetAddressTokenTransferHashes = (parameters: {
38
63
  readonly logger?: Logger
39
64
  }) => Promise<readonly Hex[]>
40
65
 
66
+ type FunctionGetAddressTokenTransferHashesWithTimestamp = (parameters: {
67
+ readonly address: Hex
68
+ readonly startBlock?: bigint
69
+ readonly endBlock?: bigint
70
+ readonly logger?: Logger
71
+ }) => Promise<
72
+ readonly {
73
+ readonly hash: Hex
74
+ readonly timestamp: number
75
+ }[]
76
+ >
77
+
41
78
  type FunctionGetContract = (
42
79
  address: Hex,
43
80
  logger?: Logger,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xtorch/evm",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "Cryptorch EVM extension",
5
5
  "keywords": [
6
6
  "cryptorch",