@@ -21,6 +21,9 @@ import type { FetchRequest } from "../utils/index.js";
21
21
import type { BlockParams , TransactionReceiptParams , TransactionResponseParams } from "./formatting.js" ;
22
22
import type { Fragment } from "../abi/index.js" ;
23
23
24
+ // Maximum page size for Otterscan queries - API limitation
25
+ const OTS_MAX_PAGE_SIZE = 25 ;
26
+
24
27
// Formatted Otterscan receipt (extends standard receipt with timestamp)
25
28
export interface OtsTransactionReceiptParams extends TransactionReceiptParams {
26
29
timestamp : number ; // Otterscan adds a Unix timestamp
@@ -357,39 +360,43 @@ export class OtterscanProvider extends JsonRpcProvider {
357
360
}
358
361
359
362
/**
360
- * Iterate through transaction history for an address
363
+ * Iterate through transaction history for an address between block ranges
361
364
* @param address - Address to search
362
- * @param direction - Search direction ("before" or "after")
363
- * @param startBlock - Starting block number
364
- * @param pageSize - Soft limit on results per page (default: 25, actual results may exceed this if a block contains more transactions)
365
- * @yields Object with tx and receipt for each transaction
365
+ * @param startBlock - Starting block number (inclusive)
366
+ * @param endBlock - Ending block number (inclusive)
367
+ * @yields Object with tx and receipt for each transaction in ascending block order
366
368
*/
367
369
async * iterateAddressHistory (
368
370
address : string ,
369
- direction : "before" | "after" ,
370
371
startBlock : number ,
371
- pageSize : number = 25
372
+ endBlock : number
372
373
) : AsyncGenerator < { tx : TransactionResponseParams ; receipt : OtsTransactionReceiptParams } , void , unknown > {
373
374
let currentBlock = startBlock ;
374
375
375
- while ( true ) {
376
- const page =
377
- direction === "before"
378
- ? await this . searchTransactionsBefore ( address , currentBlock , pageSize )
379
- : await this . searchTransactionsAfter ( address , currentBlock , pageSize ) ;
376
+ while ( currentBlock <= endBlock ) {
377
+ const page = await this . searchTransactionsAfter ( address , currentBlock , OTS_MAX_PAGE_SIZE ) ;
380
378
381
- // Yield each transaction with its receipt
379
+ // Filter and yield transactions within our range
382
380
for ( let i = 0 ; i < page . txs . length ; i ++ ) {
383
- yield {
384
- tx : page . txs [ i ] ,
385
- receipt : page . receipts [ i ]
386
- } ;
381
+ const tx = page . txs [ i ] ;
382
+ const blockNum = Number ( tx . blockNumber ) ;
383
+
384
+ // Only yield transactions within the specified range
385
+ if ( blockNum >= startBlock && blockNum <= endBlock ) {
386
+ yield {
387
+ tx : tx ,
388
+ receipt : page . receipts [ i ]
389
+ } ;
390
+ }
391
+
392
+ // Stop if we've gone past the end block
393
+ if ( blockNum > endBlock ) return ;
387
394
}
388
395
389
- // Check if we've reached the end
390
- if ( direction === "before" ? page . lastPage : page . firstPage ) break ;
396
+ // Check if we've reached the end of available data
397
+ if ( page . lastPage ) break ;
391
398
392
- // Update block cursor for next iteration
399
+ // Move to the next block after the last transaction we saw
393
400
const lastTx = page . txs [ page . txs . length - 1 ] ;
394
401
if ( ! lastTx ) break ;
395
402
@@ -400,7 +407,8 @@ export class OtterscanProvider extends JsonRpcProvider {
400
407
throw new Error ( `Iterator stuck on block ${ currentBlock } . API returned same block number.` ) ;
401
408
}
402
409
403
- currentBlock = nextBlock ;
410
+ // Move cursor forward
411
+ currentBlock = nextBlock + 1 ;
404
412
}
405
413
}
406
414
}
0 commit comments