ponder 0.17.7 → 0.17.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.
- package/CHANGELOG.md +16 -0
- package/dist/esm/client/index.js +95 -81
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/database/actions.js +4 -3
- package/dist/esm/database/actions.js.map +1 -1
- package/dist/esm/runtime/filter.js +121 -1
- package/dist/esm/runtime/filter.js.map +1 -1
- package/dist/esm/sync-historical/index.js +30 -131
- package/dist/esm/sync-historical/index.js.map +1 -1
- package/dist/esm/utils/sql-parse.js +2 -6
- package/dist/esm/utils/sql-parse.js.map +1 -1
- package/dist/types/client/index.d.ts.map +1 -1
- package/dist/types/database/actions.d.ts.map +1 -1
- package/dist/types/indexing/index.d.ts +1 -1
- package/dist/types/runtime/filter.d.ts +33 -1
- package/dist/types/runtime/filter.d.ts.map +1 -1
- package/dist/types/sync-historical/index.d.ts +2 -1
- package/dist/types/sync-historical/index.d.ts.map +1 -1
- package/dist/types/utils/sql-parse.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/client/index.ts +95 -84
- package/src/database/actions.ts +4 -8
- package/src/runtime/filter.ts +177 -1
- package/src/sync-historical/index.ts +33 -152
- package/src/utils/sql-parse.ts +2 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../src/database/actions.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../src/database/actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -62,7 +62,7 @@ export declare const createIndexing: ({ common, indexingBuild: { eventCallbacks,
|
|
|
62
62
|
[eventName: string]: number;
|
|
63
63
|
};
|
|
64
64
|
}) => Indexing;
|
|
65
|
-
export declare const createEventProxy: <T extends Block | Transaction | TransactionReceipt
|
|
65
|
+
export declare const createEventProxy: <T extends Trace | Block | Transaction | TransactionReceipt>(columnAccessPattern: ColumnAccessPattern, type: "block" | "trace" | "transaction" | "transactionReceipt", indexingErrorHandler: IndexingErrorHandler, resetFilterInclude: (eventName: string) => void) => {
|
|
66
66
|
proxy: T;
|
|
67
67
|
underlying: T;
|
|
68
68
|
eventName: string;
|
|
@@ -1,8 +1,39 @@
|
|
|
1
|
-
import { type Address } from "viem";
|
|
1
|
+
import { type Address, type Hex } from "viem";
|
|
2
2
|
import type { BlockFilter, Factory, Filter, InternalBlock, InternalLog, InternalTrace, InternalTransaction, LogFactory, LogFilter, RequiredBlockColumns, RequiredLogColumns, RequiredTraceColumns, RequiredTransactionColumns, RequiredTransactionReceiptColumns, SyncBlock, SyncBlockHeader, SyncLog, SyncTrace, SyncTransaction, TraceFilter, TransactionFilter, TransferFilter } from '../internal/types.js';
|
|
3
|
+
import { type RequestParameters } from '../rpc/index.js';
|
|
4
|
+
import type { ChildAddresses, IntervalWithFilter } from './index.js';
|
|
3
5
|
import type { Block, Log, Trace, Transaction, TransactionReceipt } from '../types/eth.js';
|
|
4
6
|
/** Returns true if `address` is an address filter. */
|
|
5
7
|
export declare const isAddressFactory: (address: Address | Address[] | Factory | undefined | null) => address is LogFactory;
|
|
8
|
+
type EthGetLogsRequest = Extract<RequestParameters, {
|
|
9
|
+
method: "eth_getLogs";
|
|
10
|
+
}> & {
|
|
11
|
+
params: [
|
|
12
|
+
Extract<Extract<RequestParameters, {
|
|
13
|
+
method: "eth_getLogs";
|
|
14
|
+
}>["params"][0], {
|
|
15
|
+
blockHash?: undefined;
|
|
16
|
+
}> & {
|
|
17
|
+
fromBlock: Hex;
|
|
18
|
+
toBlock: Hex;
|
|
19
|
+
}
|
|
20
|
+
];
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Merge `LogFilter`s into the smallest possible set of "eth_getLogs" requests.
|
|
24
|
+
*
|
|
25
|
+
* @dev Two filters are merged into a single request when:
|
|
26
|
+
* 1. their required intervals overlap by at least 80% (of the smaller
|
|
27
|
+
* interval's length), and
|
|
28
|
+
* 2. at most one of `address`, `topic0`, `topic1`, `topic2`, or `topic3`
|
|
29
|
+
* differs between them.
|
|
30
|
+
* The one differing dimension (if any) is unioned into an array.
|
|
31
|
+
*
|
|
32
|
+
* @dev Factory addresses are resolved into concrete child addresses (or
|
|
33
|
+
* `undefined`, above `factoryAddressCountThreshold`) before merging, so
|
|
34
|
+
* requests originating from different factories can still be merged.
|
|
35
|
+
*/
|
|
36
|
+
export declare const mergeLogFiltersToRequests: (filters: IntervalWithFilter[], childAddresses: ChildAddresses, factoryAddressCountThreshold: number) => EthGetLogsRequest[];
|
|
6
37
|
export declare const getChildAddress: ({ log, factory, }: {
|
|
7
38
|
log: SyncLog;
|
|
8
39
|
factory: Factory;
|
|
@@ -84,4 +115,5 @@ export declare const unionFilterIncludeBlock: (filters: Filter[]) => (keyof Bloc
|
|
|
84
115
|
export declare const unionFilterIncludeTransaction: (filters: Filter[]) => (keyof Transaction)[];
|
|
85
116
|
export declare const unionFilterIncludeTransactionReceipt: (filters: Filter[]) => (keyof TransactionReceipt)[];
|
|
86
117
|
export declare const unionFilterIncludeTrace: (filters: Filter[]) => (keyof Trace)[];
|
|
118
|
+
export {};
|
|
87
119
|
//# sourceMappingURL=filter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../../src/runtime/filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,
|
|
1
|
+
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../../src/runtime/filter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Address } from "viem";
|
|
2
2
|
import type { Common } from '../internal/common.js';
|
|
3
3
|
import type { Chain, FactoryId, SyncBlock, SyncLog } from '../internal/types.js';
|
|
4
|
-
import {
|
|
4
|
+
import type { Rpc } from '../rpc/index.js';
|
|
5
5
|
import type { IntervalWithFactory, IntervalWithFilter } from '../runtime/index.js';
|
|
6
6
|
import type { SyncStore } from '../sync-store/index.js';
|
|
7
7
|
import { type Interval } from '../utils/interval.js';
|
|
@@ -17,6 +17,7 @@ export type HistoricalSync = {
|
|
|
17
17
|
}): Promise<SyncLog[]>;
|
|
18
18
|
/**
|
|
19
19
|
* Sync block data that must be queried for a single block (block, transactions, receipts, traces).
|
|
20
|
+
* @returns Closest-to-tip synced block.
|
|
20
21
|
*/
|
|
21
22
|
syncBlockData(params: {
|
|
22
23
|
interval: Interval;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sync-historical/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sync-historical/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,OAAO,EAQb,MAAM,MAAM,CAAC;AACd,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAEV,KAAK,EAEL,SAAS,EAET,SAAS,EACT,OAAO,EAOR,MAAM,qBAAqB,CAAC;AAY7B,OAAO,KAAK,EAAqB,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAc7D,OAAO,KAAK,EAEV,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAEL,KAAK,QAAQ,EAGd,MAAM,qBAAqB,CAAC;AAK7B,MAAM,MAAM,cAAc,GAAG;IAC3B;;OAEG;IACH,kBAAkB,CAAC,MAAM,EAAE;QACzB,QAAQ,EAAE,QAAQ,CAAC;QACnB,iBAAiB,EAAE,kBAAkB,EAAE,CAAC;QACxC,wBAAwB,EAAE,mBAAmB,EAAE,CAAC;QAChD,SAAS,EAAE,SAAS,CAAC;KACtB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACvB;;;OAGG;IACH,aAAa,CAAC,MAAM,EAAE;QACpB,QAAQ,EAAE,QAAQ,CAAC;QACnB,iBAAiB,EAAE,kBAAkB,EAAE,CAAC;QACxC,IAAI,EAAE,OAAO,EAAE,CAAC;QAChB,SAAS,EAAE,SAAS,CAAC;KACtB,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;CACpC,CAAC;AAEF,KAAK,8BAA8B,GAAG;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,GAAG,CAAC;IACT,cAAc,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;CACtD,CAAC;AAEF,eAAO,MAAM,oBAAoB,SACzB,8BAA8B,KACnC,cAgzBF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql-parse.d.ts","sourceRoot":"","sources":["../../../src/utils/sql-parse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAqB,MAAM,cAAc,CAAC;AAe5D,eAAO,MAAM,aAAa,QAAe,MAAM,KAAG,QAAQ,IAAI,CAiC7D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,QAAe,MAAM,kBAuD1D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,QAAe,MAAM,KAAG,QAAQ,OAAO,CA2BrE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,QAC1B,MAAM,KACV,QAAQ,IAAI,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"sql-parse.d.ts","sourceRoot":"","sources":["../../../src/utils/sql-parse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAqB,MAAM,cAAc,CAAC;AAe5D,eAAO,MAAM,aAAa,QAAe,MAAM,KAAG,QAAQ,IAAI,CAiC7D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,QAAe,MAAM,kBAuD1D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,QAAe,MAAM,KAAG,QAAQ,OAAO,CA2BrE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,QAC1B,MAAM,KACV,QAAQ,IAAI,MAAM,CAAC,CA+CrB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ponder",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.9",
|
|
4
4
|
"description": "An open-source TypeScript framework for EVM data indexing",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
"rimraf": "^5.0.5",
|
|
103
103
|
"tsx": "^4.19.2",
|
|
104
104
|
"vitest": "1.6.1",
|
|
105
|
-
"@ponder/client": "0.17.
|
|
105
|
+
"@ponder/client": "0.17.9"
|
|
106
106
|
},
|
|
107
107
|
"engines": {
|
|
108
108
|
"node": ">=22"
|
package/src/client/index.ts
CHANGED
|
@@ -439,116 +439,127 @@ export const client = ({
|
|
|
439
439
|
}
|
|
440
440
|
|
|
441
441
|
liveQueryCount++;
|
|
442
|
+
let hasLiveQuerySlot = true;
|
|
443
|
+
let isStreaming = false;
|
|
444
|
+
const releaseLiveQuerySlot = () => {
|
|
445
|
+
if (hasLiveQuerySlot === false) return;
|
|
446
|
+
hasLiveQuerySlot = false;
|
|
447
|
+
liveQueryCount--;
|
|
448
|
+
};
|
|
442
449
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
450
|
+
try {
|
|
451
|
+
c.header("Content-Type", "text/event-stream");
|
|
452
|
+
c.header("Cache-Control", "no-cache");
|
|
453
|
+
c.header("Connection", "keep-alive");
|
|
446
454
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
455
|
+
const queryString = c.req.query("sql");
|
|
456
|
+
if (queryString === undefined) {
|
|
457
|
+
return c.text('Missing "sql" query parameter', 400);
|
|
458
|
+
}
|
|
459
|
+
const query = superjson.parse(queryString) as QueryWithTypings;
|
|
452
460
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
461
|
+
try {
|
|
462
|
+
await validateAllowableSQLQuery(query.sql);
|
|
463
|
+
} catch (error) {
|
|
464
|
+
(error as Error).stack = undefined;
|
|
465
|
+
return c.text((error as Error).message, 500);
|
|
466
|
+
}
|
|
459
467
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
+
const relations = await getSQLQueryRelations(query.sql);
|
|
469
|
+
const referencedTables = new Set<string>();
|
|
470
|
+
for (const relation of relations) {
|
|
471
|
+
if (tableNames.has(relation)) {
|
|
472
|
+
referencedTables.add(relation);
|
|
473
|
+
} else if (viewNames.has(relation)) {
|
|
474
|
+
for (const tableName of perViewTables.get(relation)!) {
|
|
475
|
+
referencedTables.add(tableName);
|
|
476
|
+
}
|
|
468
477
|
}
|
|
469
478
|
}
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
let result: QueryResult;
|
|
473
|
-
if (cache.has(queryString)) {
|
|
474
|
-
const resultRef = cache.get(queryString)!.deref();
|
|
475
479
|
|
|
476
|
-
|
|
477
|
-
|
|
480
|
+
let result: QueryResult;
|
|
481
|
+
if (cache.has(queryString)) {
|
|
482
|
+
const resultRef = cache.get(queryString)!.deref();
|
|
483
|
+
|
|
484
|
+
if (resultRef === undefined) {
|
|
485
|
+
cache.delete(queryString);
|
|
486
|
+
const resultPromise = getQueryResult(query);
|
|
487
|
+
cache.set(queryString, new WeakRef(resultPromise));
|
|
488
|
+
perQueryReferences.set(queryString, referencedTables);
|
|
489
|
+
registry.register(resultPromise, queryString);
|
|
490
|
+
result = await resultPromise;
|
|
491
|
+
} else {
|
|
492
|
+
result = await resultRef;
|
|
493
|
+
}
|
|
494
|
+
} else {
|
|
478
495
|
const resultPromise = getQueryResult(query);
|
|
479
496
|
cache.set(queryString, new WeakRef(resultPromise));
|
|
480
497
|
perQueryReferences.set(queryString, referencedTables);
|
|
481
498
|
registry.register(resultPromise, queryString);
|
|
482
499
|
result = await resultPromise;
|
|
483
|
-
} else {
|
|
484
|
-
result = await resultRef;
|
|
485
500
|
}
|
|
486
|
-
} else {
|
|
487
|
-
const resultPromise = getQueryResult(query);
|
|
488
|
-
cache.set(queryString, new WeakRef(resultPromise));
|
|
489
|
-
perQueryReferences.set(queryString, referencedTables);
|
|
490
|
-
registry.register(resultPromise, queryString);
|
|
491
|
-
result = await resultPromise;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
let resultHash = crypto
|
|
495
|
-
.createHash("MD5")
|
|
496
|
-
// @ts-expect-error
|
|
497
|
-
.update(JSON.stringify(result.rows))
|
|
498
|
-
.digest("hex")
|
|
499
|
-
.slice(0, 10);
|
|
500
501
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
)
|
|
502
|
+
let resultHash = crypto
|
|
503
|
+
.createHash("MD5")
|
|
504
|
+
// @ts-expect-error
|
|
505
|
+
.update(JSON.stringify(result.rows))
|
|
506
|
+
.digest("hex")
|
|
507
|
+
.slice(0, 10);
|
|
508
|
+
|
|
509
|
+
const response = streamSSE(c, async (stream) => {
|
|
510
|
+
stream.onAbort(releaseLiveQuerySlot);
|
|
511
|
+
|
|
512
|
+
while (stream.closed === false && stream.aborted === false) {
|
|
513
|
+
await Promise.race(
|
|
514
|
+
Array.from(referencedTables).map(
|
|
515
|
+
(relation) => perTableResolver.get(relation)!.promise,
|
|
516
|
+
),
|
|
517
|
+
);
|
|
512
518
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
519
|
+
try {
|
|
520
|
+
let resultPromise: Promise<unknown>;
|
|
521
|
+
if (cache.has(queryString)) {
|
|
522
|
+
const resultRef = cache.get(queryString)!.deref();
|
|
517
523
|
|
|
518
|
-
|
|
519
|
-
|
|
524
|
+
if (resultRef === undefined) {
|
|
525
|
+
cache.delete(queryString);
|
|
526
|
+
resultPromise = getQueryResult(query);
|
|
527
|
+
cache.set(queryString, new WeakRef(resultPromise));
|
|
528
|
+
perQueryReferences.set(queryString, referencedTables);
|
|
529
|
+
registry.register(resultPromise, queryString);
|
|
530
|
+
} else {
|
|
531
|
+
resultPromise = resultRef;
|
|
532
|
+
}
|
|
533
|
+
} else {
|
|
520
534
|
resultPromise = getQueryResult(query);
|
|
521
535
|
cache.set(queryString, new WeakRef(resultPromise));
|
|
522
536
|
perQueryReferences.set(queryString, referencedTables);
|
|
523
537
|
registry.register(resultPromise, queryString);
|
|
524
|
-
} else {
|
|
525
|
-
resultPromise = resultRef;
|
|
526
538
|
}
|
|
527
|
-
} else {
|
|
528
|
-
resultPromise = getQueryResult(query);
|
|
529
|
-
cache.set(queryString, new WeakRef(resultPromise));
|
|
530
|
-
perQueryReferences.set(queryString, referencedTables);
|
|
531
|
-
registry.register(resultPromise, queryString);
|
|
532
|
-
}
|
|
533
539
|
|
|
534
|
-
|
|
540
|
+
const result = await resultPromise;
|
|
535
541
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
+
const _resultHash = crypto
|
|
543
|
+
.createHash("MD5")
|
|
544
|
+
// @ts-expect-error
|
|
545
|
+
.update(JSON.stringify(result.rows))
|
|
546
|
+
.digest("hex")
|
|
547
|
+
.slice(0, 10);
|
|
542
548
|
|
|
543
|
-
|
|
544
|
-
|
|
549
|
+
if (_resultHash === resultHash) continue;
|
|
550
|
+
resultHash = _resultHash;
|
|
545
551
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
552
|
+
await stream.writeSSE({ data: JSON.stringify(result) });
|
|
553
|
+
} catch {
|
|
554
|
+
stream.abort();
|
|
555
|
+
}
|
|
549
556
|
}
|
|
550
|
-
}
|
|
551
|
-
|
|
557
|
+
});
|
|
558
|
+
isStreaming = true;
|
|
559
|
+
return response;
|
|
560
|
+
} finally {
|
|
561
|
+
if (isStreaming === false) releaseLiveQuerySlot();
|
|
562
|
+
}
|
|
552
563
|
}
|
|
553
564
|
|
|
554
565
|
return next();
|
package/src/database/actions.ts
CHANGED
|
@@ -599,14 +599,15 @@ export const finalizeMultichain = async (
|
|
|
599
599
|
context?: { logger?: Logger },
|
|
600
600
|
) => {
|
|
601
601
|
const PONDER_CHECKPOINT = getPonderCheckpointTable(namespaceBuild.schema);
|
|
602
|
+
const chainId = Number(decodeCheckpoint(checkpoint).chainId);
|
|
602
603
|
|
|
603
|
-
// TODO(kyle) is this breaking an invariant?
|
|
604
604
|
if (tables.length === 0) {
|
|
605
605
|
await qb.wrap(
|
|
606
606
|
(db) =>
|
|
607
607
|
db
|
|
608
608
|
.update(PONDER_CHECKPOINT)
|
|
609
|
-
.set({ finalizedCheckpoint: checkpoint, safeCheckpoint: checkpoint })
|
|
609
|
+
.set({ finalizedCheckpoint: checkpoint, safeCheckpoint: checkpoint })
|
|
610
|
+
.where(eq(PONDER_CHECKPOINT.chainId, chainId)),
|
|
610
611
|
context,
|
|
611
612
|
);
|
|
612
613
|
return;
|
|
@@ -621,12 +622,7 @@ export const finalizeMultichain = async (
|
|
|
621
622
|
tx
|
|
622
623
|
.update(PONDER_CHECKPOINT)
|
|
623
624
|
.set({ finalizedCheckpoint: checkpoint })
|
|
624
|
-
.where(
|
|
625
|
-
eq(
|
|
626
|
-
PONDER_CHECKPOINT.chainId,
|
|
627
|
-
Number(decodeCheckpoint(checkpoint).chainId),
|
|
628
|
-
),
|
|
629
|
-
),
|
|
625
|
+
.where(eq(PONDER_CHECKPOINT.chainId, chainId)),
|
|
630
626
|
);
|
|
631
627
|
|
|
632
628
|
const minOperationId = await tx
|
package/src/runtime/filter.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Address, hexToNumber } from "viem";
|
|
1
|
+
import { type Address, type Hex, hexToNumber, numberToHex } from "viem";
|
|
2
2
|
import type {
|
|
3
3
|
BlockFilter,
|
|
4
4
|
Factory,
|
|
@@ -23,6 +23,8 @@ import type {
|
|
|
23
23
|
TransactionFilter,
|
|
24
24
|
TransferFilter,
|
|
25
25
|
} from "@/internal/types.js";
|
|
26
|
+
import { type RequestParameters, sanitizeLogTopics } from "@/rpc/index.js";
|
|
27
|
+
import type { ChildAddresses, IntervalWithFilter } from "@/runtime/index.js";
|
|
26
28
|
import type {
|
|
27
29
|
Block,
|
|
28
30
|
Log,
|
|
@@ -30,6 +32,7 @@ import type {
|
|
|
30
32
|
Transaction,
|
|
31
33
|
TransactionReceipt,
|
|
32
34
|
} from "@/types/eth.js";
|
|
35
|
+
import type { Interval } from "@/utils/interval.js";
|
|
33
36
|
import { toLowerCase } from "@/utils/lowercase.js";
|
|
34
37
|
|
|
35
38
|
/** Returns true if `address` is an address filter. */
|
|
@@ -46,6 +49,179 @@ export const isAddressFactory = (
|
|
|
46
49
|
return Array.isArray(address) ? isAddressFactory(address[0]) : true;
|
|
47
50
|
};
|
|
48
51
|
|
|
52
|
+
type EthGetLogsRequest = Extract<
|
|
53
|
+
RequestParameters,
|
|
54
|
+
{ method: "eth_getLogs" }
|
|
55
|
+
> & {
|
|
56
|
+
params: [
|
|
57
|
+
Extract<
|
|
58
|
+
Extract<RequestParameters, { method: "eth_getLogs" }>["params"][0],
|
|
59
|
+
{ blockHash?: undefined }
|
|
60
|
+
> & { fromBlock: Hex; toBlock: Hex },
|
|
61
|
+
];
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const logRequestKeys = [
|
|
65
|
+
"address",
|
|
66
|
+
"topic0",
|
|
67
|
+
"topic1",
|
|
68
|
+
"topic2",
|
|
69
|
+
"topic3",
|
|
70
|
+
] as const;
|
|
71
|
+
|
|
72
|
+
const getLogRequestValue = (
|
|
73
|
+
request: EthGetLogsRequest,
|
|
74
|
+
key: (typeof logRequestKeys)[number],
|
|
75
|
+
): Hex | Hex[] | undefined => {
|
|
76
|
+
if (key === "address") return request.params[0].address;
|
|
77
|
+
|
|
78
|
+
const topic = request.params[0].topics?.[Number(key.slice(-1))];
|
|
79
|
+
return topic === null ? undefined : topic;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/** Returns `true` if `left` and `right` overlap by at least 80% of the smaller interval's length. */
|
|
83
|
+
const hasSufficientLogIntervalOverlap = (
|
|
84
|
+
left: Interval,
|
|
85
|
+
right: Interval,
|
|
86
|
+
): boolean => {
|
|
87
|
+
const overlapStart = Math.max(left[0], right[0]);
|
|
88
|
+
const overlapEnd = Math.min(left[1], right[1]);
|
|
89
|
+
if (overlapStart > overlapEnd) return false;
|
|
90
|
+
|
|
91
|
+
const overlapLength = overlapEnd - overlapStart + 1;
|
|
92
|
+
const smallerIntervalLength = Math.min(
|
|
93
|
+
left[1] - left[0] + 1,
|
|
94
|
+
right[1] - right[0] + 1,
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
return overlapLength / smallerIntervalLength >= 0.8;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const mergeLogFilterValue = <value extends Hex>(
|
|
101
|
+
left: value | value[] | undefined,
|
|
102
|
+
right: value | value[] | undefined,
|
|
103
|
+
): value[] | undefined =>
|
|
104
|
+
left === undefined || right === undefined
|
|
105
|
+
? undefined
|
|
106
|
+
: [
|
|
107
|
+
...new Set([
|
|
108
|
+
...(Array.isArray(left) ? left : [left]),
|
|
109
|
+
...(Array.isArray(right) ? right : [right]),
|
|
110
|
+
]),
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Merge `LogFilter`s into the smallest possible set of "eth_getLogs" requests.
|
|
115
|
+
*
|
|
116
|
+
* @dev Two filters are merged into a single request when:
|
|
117
|
+
* 1. their required intervals overlap by at least 80% (of the smaller
|
|
118
|
+
* interval's length), and
|
|
119
|
+
* 2. at most one of `address`, `topic0`, `topic1`, `topic2`, or `topic3`
|
|
120
|
+
* differs between them.
|
|
121
|
+
* The one differing dimension (if any) is unioned into an array.
|
|
122
|
+
*
|
|
123
|
+
* @dev Factory addresses are resolved into concrete child addresses (or
|
|
124
|
+
* `undefined`, above `factoryAddressCountThreshold`) before merging, so
|
|
125
|
+
* requests originating from different factories can still be merged.
|
|
126
|
+
*/
|
|
127
|
+
export const mergeLogFiltersToRequests = (
|
|
128
|
+
filters: IntervalWithFilter[],
|
|
129
|
+
childAddresses: ChildAddresses,
|
|
130
|
+
factoryAddressCountThreshold: number,
|
|
131
|
+
): EthGetLogsRequest[] => {
|
|
132
|
+
const requests: EthGetLogsRequest[] = [];
|
|
133
|
+
|
|
134
|
+
for (const { filter, interval } of filters) {
|
|
135
|
+
if (filter.type !== "log") continue;
|
|
136
|
+
|
|
137
|
+
let address: Hex | Hex[] | undefined;
|
|
138
|
+
if (isAddressFactory(filter.address)) {
|
|
139
|
+
const addresses = childAddresses.get(filter.address.id)!;
|
|
140
|
+
if (addresses.size === 0) continue;
|
|
141
|
+
|
|
142
|
+
address =
|
|
143
|
+
addresses.size >= factoryAddressCountThreshold
|
|
144
|
+
? undefined
|
|
145
|
+
: Array.from(addresses.keys());
|
|
146
|
+
} else {
|
|
147
|
+
address = filter.address;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const candidate: EthGetLogsRequest = {
|
|
151
|
+
method: "eth_getLogs",
|
|
152
|
+
params: [
|
|
153
|
+
{
|
|
154
|
+
address,
|
|
155
|
+
topics: sanitizeLogTopics([
|
|
156
|
+
filter.topic0,
|
|
157
|
+
filter.topic1 ?? null,
|
|
158
|
+
filter.topic2 ?? null,
|
|
159
|
+
filter.topic3 ?? null,
|
|
160
|
+
]),
|
|
161
|
+
fromBlock: numberToHex(interval[0]),
|
|
162
|
+
toBlock: numberToHex(interval[1]),
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
let isMerged = false;
|
|
168
|
+
|
|
169
|
+
for (const request of requests) {
|
|
170
|
+
if (
|
|
171
|
+
hasSufficientLogIntervalOverlap(
|
|
172
|
+
[
|
|
173
|
+
hexToNumber(request.params[0].fromBlock),
|
|
174
|
+
hexToNumber(request.params[0].toBlock),
|
|
175
|
+
],
|
|
176
|
+
interval,
|
|
177
|
+
) === false
|
|
178
|
+
) {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const numberOfDifferences = logRequestKeys.filter(
|
|
183
|
+
(key) =>
|
|
184
|
+
JSON.stringify(getLogRequestValue(request, key)) !==
|
|
185
|
+
JSON.stringify(getLogRequestValue(candidate, key)),
|
|
186
|
+
).length;
|
|
187
|
+
if (numberOfDifferences > 1) continue;
|
|
188
|
+
|
|
189
|
+
const requestParams = request.params[0];
|
|
190
|
+
for (const key of logRequestKeys) {
|
|
191
|
+
const requestValue = getLogRequestValue(request, key);
|
|
192
|
+
const candidateValue = getLogRequestValue(candidate, key);
|
|
193
|
+
if (JSON.stringify(requestValue) === JSON.stringify(candidateValue)) {
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const mergedValue = mergeLogFilterValue(requestValue, candidateValue);
|
|
198
|
+
if (key === "address") {
|
|
199
|
+
requestParams.address = mergedValue;
|
|
200
|
+
} else {
|
|
201
|
+
const topics = [...(requestParams.topics ?? [])];
|
|
202
|
+
topics[Number(key.slice(-1))] = mergedValue ?? null;
|
|
203
|
+
requestParams.topics = sanitizeLogTopics(topics);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
requestParams.fromBlock = numberToHex(
|
|
208
|
+
Math.min(hexToNumber(requestParams.fromBlock), interval[0]),
|
|
209
|
+
);
|
|
210
|
+
requestParams.toBlock = numberToHex(
|
|
211
|
+
Math.max(hexToNumber(requestParams.toBlock), interval[1]),
|
|
212
|
+
);
|
|
213
|
+
isMerged = true;
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (isMerged === false) {
|
|
218
|
+
requests.push(candidate);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return requests;
|
|
223
|
+
};
|
|
224
|
+
|
|
49
225
|
export const getChildAddress = ({
|
|
50
226
|
log,
|
|
51
227
|
factory,
|