@@ -5,6 +5,7 @@ import Blockchain from "../blockchain";
5
5
import { parseFilter , parseFilterDetails } from "../helpers/filter-parsing" ;
6
6
import { Ethereum } from "../api-types" ;
7
7
import { GanacheLevelUp } from "../database" ;
8
+ type Topic = string | string [ ] ;
8
9
9
10
export default class BlockLogManager extends Manager < BlockLogs > {
10
11
#blockchain: Blockchain ;
@@ -28,6 +29,19 @@ export default class BlockLogManager extends Manager<BlockLogs> {
28
29
return log ;
29
30
}
30
31
32
+ async getRange ( fromBlockNumber : string | Buffer , toBlockNumber : string | Buffer , topics : Topic [ ] , address : String | String [ ] ) {
33
+ const blockchain = this . #blockchain;
34
+ if ( ! blockchain . fallback ) {
35
+ throw new Error ( "Not a forked instance" ) ;
36
+ }
37
+ const res = await this . #blockchain. fallback . request < any [ ] | null > (
38
+ "eth_getLogs" ,
39
+ [ { address, topics, fromBlock : Quantity . from ( fromBlockNumber ) , toBlock : Quantity . from ( toBlockNumber ) } ]
40
+ ) ;
41
+ return BlockLogs . fromJSON ( res ) ;
42
+
43
+ }
44
+
31
45
async getLogs ( filter : FilterArgs ) : Promise < Ethereum . Logs > {
32
46
const blockchain = this . #blockchain;
33
47
if ( "blockHash" in filter ) {
@@ -44,19 +58,34 @@ export default class BlockLogManager extends Manager<BlockLogs> {
44
58
filter ,
45
59
blockchain
46
60
) ;
47
-
48
- const pendingLogsPromises : Promise < BlockLogs > [ ] = [
49
- this . get ( fromBlock . toBuffer ( ) )
50
- ] ;
61
+ const pendingLogsPromises : Promise < BlockLogs > [ ] = [ ] ;
51
62
52
63
const fromBlockNumber = fromBlock . toNumber ( ) ;
53
64
// if we have a range of blocks to search, do that here:
54
65
if ( fromBlockNumber !== toBlockNumber ) {
55
- // fetch all the blockLogs in-between `fromBlock` and `toBlock` (excluding
56
- // from, because we already started fetching that one)
57
- for ( let i = fromBlockNumber + 1 , l = toBlockNumber + 1 ; i < l ; i ++ ) {
58
- pendingLogsPromises . push ( this . get ( Quantity . toBuffer ( i ) ) ) ;
66
+ if (
67
+ ! blockchain . fallback || // We're not a forked chain
68
+ blockchain . fallback . blockNumber < fromBlock // Or we are, but only querying post-fork
69
+ ) {
70
+ // fetch all the blockLogs in-between `fromBlock` and `toBlock`
71
+ for ( let i = fromBlockNumber , l = toBlockNumber + 1 ; i < l ; i ++ ) {
72
+ pendingLogsPromises . push ( this . get ( Quantity . toBuffer ( i ) ) ) ;
73
+ }
74
+ } else {
75
+ // Fetch all the logs from fromBlockNumber to forkBlock in one request
76
+ let addressesAsStrings : String [ ] | String ;
77
+ if ( Array . isArray ( addresses ) ) {
78
+ addressesAsStrings = addresses . map ( x => `0x${ x . toString ( 'hex' ) } ` )
79
+ }
80
+ pendingLogsPromises . push ( this . getRange ( Quantity . from ( fromBlockNumber ) . toString ( ) , Quantity . from ( toBlockNumber ) . toString ( ) , topics , addressesAsStrings ) ) ;
81
+ // fetch all the blockLogs in-between `forkBlock` + 1 and `toBlock` locally in the
82
+ // way that we normally do
83
+ for ( let i = blockchain . fallback . blockNumber . toNumber ( ) + 1 , l = toBlockNumber + 1 ; i < l ; i ++ ) {
84
+ pendingLogsPromises . push ( this . get ( Quantity . toBuffer ( i ) ) ) ;
85
+ }
59
86
}
87
+ } else {
88
+ pendingLogsPromises . push ( this . get ( Quantity . toBuffer ( fromBlockNumber ) ) ) ;
60
89
}
61
90
62
91
// now filter and compute all the blocks' blockLogs (in block order)
0 commit comments