@@ -18,6 +18,8 @@ import type {
18
18
} from '../types' ;
19
19
import { TransactionStatus , TransactionType } from '../types' ;
20
20
21
+ const RECENT_HISTORY_DURATION_MS = 1000 * 60 * 60 * 24 ; // 1 Day
22
+
21
23
export const SUPPORTED_CHAIN_IDS : Hex [ ] = [
22
24
CHAIN_IDS . MAINNET ,
23
25
CHAIN_IDS . POLYGON ,
@@ -84,32 +86,49 @@ export class AccountsApiRemoteTransactionSource
84
86
85
87
const cursor = this . #getCacheCursor( cache , SUPPORTED_CHAIN_IDS , address ) ;
86
88
89
+ const timestamp = this . #getCacheTimestamp(
90
+ cache ,
91
+ SUPPORTED_CHAIN_IDS ,
92
+ address ,
93
+ ) ;
94
+
87
95
if ( cursor ) {
88
96
log ( 'Using cached cursor' , cursor ) ;
97
+ } else if ( timestamp ) {
98
+ log ( 'Using cached timestamp' , timestamp ) ;
99
+ } else {
100
+ log ( 'No cached cursor or timestamp found' ) ;
89
101
}
90
102
91
- return await this . #queryTransactions( request , SUPPORTED_CHAIN_IDS , cursor ) ;
103
+ return await this . #queryTransactions(
104
+ request ,
105
+ SUPPORTED_CHAIN_IDS ,
106
+ cursor ,
107
+ timestamp ,
108
+ ) ;
92
109
}
93
110
94
111
async #queryTransactions(
95
112
request : RemoteTransactionSourceRequest ,
96
113
chainIds : Hex [ ] ,
97
114
cursor ?: string ,
115
+ timestamp ?: number ,
98
116
) : Promise < TransactionResponse [ ] > {
99
- const { address, queryEntireHistory, updateCache } = request ;
117
+ const { address, queryEntireHistory } = request ;
100
118
const transactions : TransactionResponse [ ] = [ ] ;
101
119
102
120
let hasNextPage = true ;
103
121
let currentCursor = cursor ;
104
122
let pageCount = 0 ;
105
123
106
- const startTimestamp =
107
- queryEntireHistory || cursor
108
- ? undefined
109
- : this . #getTimestampSeconds( Date . now ( ) ) ;
110
-
111
124
while ( hasNextPage ) {
112
125
try {
126
+ const startTimestamp = this . #getStartTimestamp( {
127
+ cursor : currentCursor ,
128
+ queryEntireHistory,
129
+ timestamp,
130
+ } ) ;
131
+
113
132
const response = await getAccountTransactions ( {
114
133
address,
115
134
chainIds,
@@ -127,15 +146,12 @@ export class AccountsApiRemoteTransactionSource
127
146
hasNextPage = response ?. pageInfo ?. hasNextPage ;
128
147
currentCursor = response ?. pageInfo ?. cursor ;
129
148
130
- if ( currentCursor ) {
131
- // eslint-disable-next-line no-loop-func
132
- updateCache ( ( cache ) => {
133
- const key = this . #getCacheKey( chainIds , address ) ;
134
- cache [ key ] = currentCursor ;
135
-
136
- log ( 'Updated cache' , { key, newCursor : currentCursor } ) ;
137
- } ) ;
138
- }
149
+ this . #updateCache( {
150
+ chainIds,
151
+ cursor : currentCursor ,
152
+ request,
153
+ startTimestamp,
154
+ } ) ;
139
155
} catch ( error ) {
140
156
log ( 'Error while fetching transactions' , error ) ;
141
157
break ;
@@ -248,7 +264,64 @@ export class AccountsApiRemoteTransactionSource
248
264
} ;
249
265
}
250
266
251
- #getCacheKey( chainIds : Hex [ ] , address : Hex ) : string {
267
+ #updateCache( {
268
+ chainIds,
269
+ cursor,
270
+ request,
271
+ startTimestamp,
272
+ } : {
273
+ chainIds : Hex [ ] ;
274
+ cursor ?: string ;
275
+ request : RemoteTransactionSourceRequest ;
276
+ startTimestamp ?: number ;
277
+ } ) {
278
+ if ( ! cursor && ! startTimestamp ) {
279
+ log ( 'Cache not updated' ) ;
280
+ return ;
281
+ }
282
+
283
+ const { address, updateCache } = request ;
284
+ const cursorCacheKey = this . #getCursorCacheKey( chainIds , address ) ;
285
+ const timestampCacheKey = this . #getTimestampCacheKey( chainIds , address ) ;
286
+
287
+ updateCache ( ( cache ) => {
288
+ if ( cursor ) {
289
+ cache [ cursorCacheKey ] = cursor ;
290
+ delete cache [ timestampCacheKey ] ;
291
+
292
+ log ( 'Updated cursor in cache' , { cursorCacheKey, newCursor : cursor } ) ;
293
+ } else {
294
+ cache [ timestampCacheKey ] = startTimestamp ;
295
+
296
+ log ( 'Updated timestamp in cache' , {
297
+ timestampCacheKey,
298
+ newTimestamp : startTimestamp ,
299
+ } ) ;
300
+ }
301
+ } ) ;
302
+ }
303
+
304
+ #getStartTimestamp( {
305
+ cursor,
306
+ queryEntireHistory,
307
+ timestamp,
308
+ } : {
309
+ cursor ?: string ;
310
+ queryEntireHistory : boolean ;
311
+ timestamp ?: number ;
312
+ } ) : number | undefined {
313
+ if ( queryEntireHistory || cursor ) {
314
+ return undefined ;
315
+ }
316
+
317
+ if ( timestamp ) {
318
+ return timestamp ;
319
+ }
320
+
321
+ return this . #getTimestampSeconds( Date . now ( ) - RECENT_HISTORY_DURATION_MS ) ;
322
+ }
323
+
324
+ #getCursorCacheKey( chainIds : Hex [ ] , address : Hex ) : string {
252
325
return `accounts-api#${ chainIds . join ( ',' ) } #${ address } ` ;
253
326
}
254
327
@@ -257,10 +330,23 @@ export class AccountsApiRemoteTransactionSource
257
330
chainIds : Hex [ ] ,
258
331
address : Hex ,
259
332
) : string | undefined {
260
- const key = this . #getCacheKey ( chainIds , address ) ;
333
+ const key = this . #getCursorCacheKey ( chainIds , address ) ;
261
334
return cache [ key ] as string | undefined ;
262
335
}
263
336
337
+ #getTimestampCacheKey( chainIds : Hex [ ] , address : Hex ) : string {
338
+ return `accounts-api#timestamp#${ chainIds . join ( ',' ) } #${ address } ` ;
339
+ }
340
+
341
+ #getCacheTimestamp(
342
+ cache : Record < string , unknown > ,
343
+ chainIds : Hex [ ] ,
344
+ address : Hex ,
345
+ ) : number | undefined {
346
+ const key = this . #getTimestampCacheKey( chainIds , address ) ;
347
+ return cache [ key ] as number | undefined ;
348
+ }
349
+
264
350
#getTimestampSeconds( timestampMs : number ) : number {
265
351
return Math . floor ( timestampMs / 1000 ) ;
266
352
}
0 commit comments