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
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
type Hash,
|
|
5
5
|
type Hex,
|
|
6
6
|
hexToNumber,
|
|
7
|
-
type LogTopic,
|
|
8
7
|
numberToHex,
|
|
9
8
|
type RpcError,
|
|
10
9
|
toHex,
|
|
@@ -37,7 +36,7 @@ import {
|
|
|
37
36
|
validateTracesAndBlock,
|
|
38
37
|
validateTransactionsAndBlock,
|
|
39
38
|
} from "@/rpc/actions.js";
|
|
40
|
-
import {
|
|
39
|
+
import type { RequestParameters, Rpc } from "@/rpc/index.js";
|
|
41
40
|
import {
|
|
42
41
|
getChildAddress,
|
|
43
42
|
isAddressFactory,
|
|
@@ -49,6 +48,7 @@ import {
|
|
|
49
48
|
isTraceFilterMatched,
|
|
50
49
|
isTransactionFilterMatched,
|
|
51
50
|
isTransferFilterMatched,
|
|
51
|
+
mergeLogFiltersToRequests,
|
|
52
52
|
} from "@/runtime/filter.js";
|
|
53
53
|
import type {
|
|
54
54
|
ChildAddresses,
|
|
@@ -79,6 +79,7 @@ export type HistoricalSync = {
|
|
|
79
79
|
}): Promise<SyncLog[]>;
|
|
80
80
|
/**
|
|
81
81
|
* Sync block data that must be queried for a single block (block, transactions, receipts, traces).
|
|
82
|
+
* @returns Closest-to-tip synced block.
|
|
82
83
|
*/
|
|
83
84
|
syncBlockData(params: {
|
|
84
85
|
interval: Interval;
|
|
@@ -120,48 +121,37 @@ export const createHistoricalSync = (
|
|
|
120
121
|
// Helper functions for sync tasks
|
|
121
122
|
////////
|
|
122
123
|
|
|
123
|
-
type EthGetLogsParams = {
|
|
124
|
-
address: Address | Address[] | undefined;
|
|
125
|
-
topic0?: LogTopic;
|
|
126
|
-
topic1?: LogTopic;
|
|
127
|
-
topic2?: LogTopic;
|
|
128
|
-
topic3?: LogTopic;
|
|
129
|
-
interval: Interval;
|
|
130
|
-
};
|
|
131
|
-
|
|
132
124
|
/**
|
|
133
125
|
* Split "eth_getLogs" requests into ranges inferred from errors
|
|
134
126
|
* and batch requests.
|
|
135
127
|
*/
|
|
136
128
|
const syncLogsDynamic = async (
|
|
137
|
-
|
|
129
|
+
params: Extract<RequestParameters, { method: "eth_getLogs" }>["params"][0],
|
|
138
130
|
context?: Parameters<Rpc["request"]>[1],
|
|
139
131
|
): Promise<SyncLog[]> => {
|
|
132
|
+
const { address, topics } = params;
|
|
133
|
+
|
|
140
134
|
const intervals = getChunks({
|
|
141
|
-
interval
|
|
135
|
+
interval: [
|
|
136
|
+
hexToNumber(params.fromBlock as Hex),
|
|
137
|
+
hexToNumber(params.toBlock as Hex),
|
|
138
|
+
],
|
|
142
139
|
maxChunkSize:
|
|
143
140
|
args.chain.ethGetLogsBlockRange ??
|
|
144
141
|
logsRequestMetadata.confirmedRange ??
|
|
145
142
|
logsRequestMetadata.estimatedRange,
|
|
146
143
|
});
|
|
147
144
|
|
|
148
|
-
const topics = sanitizeLogTopics([
|
|
149
|
-
topic0 ?? null,
|
|
150
|
-
topic1 ?? null,
|
|
151
|
-
topic2 ?? null,
|
|
152
|
-
topic3 ?? null,
|
|
153
|
-
])!;
|
|
154
|
-
|
|
155
145
|
const logs = await Promise.all(
|
|
156
|
-
intervals.map((
|
|
146
|
+
intervals.map(([fromBlock, toBlock]) =>
|
|
157
147
|
eth_getLogs(
|
|
158
148
|
args.rpc,
|
|
159
149
|
[
|
|
160
150
|
{
|
|
161
151
|
address,
|
|
162
152
|
topics,
|
|
163
|
-
fromBlock: numberToHex(
|
|
164
|
-
toBlock: numberToHex(
|
|
153
|
+
fromBlock: numberToHex(fromBlock),
|
|
154
|
+
toBlock: numberToHex(toBlock),
|
|
165
155
|
},
|
|
166
156
|
],
|
|
167
157
|
context,
|
|
@@ -177,8 +167,8 @@ export const createHistoricalSync = (
|
|
|
177
167
|
{
|
|
178
168
|
address,
|
|
179
169
|
topics,
|
|
180
|
-
fromBlock: toHex(
|
|
181
|
-
toBlock: toHex(
|
|
170
|
+
fromBlock: toHex(fromBlock),
|
|
171
|
+
toBlock: toHex(toBlock),
|
|
182
172
|
},
|
|
183
173
|
],
|
|
184
174
|
error: error as RpcError,
|
|
@@ -205,7 +195,12 @@ export const createHistoricalSync = (
|
|
|
205
195
|
};
|
|
206
196
|
|
|
207
197
|
return syncLogsDynamic(
|
|
208
|
-
{
|
|
198
|
+
{
|
|
199
|
+
address,
|
|
200
|
+
topics,
|
|
201
|
+
fromBlock: numberToHex(fromBlock),
|
|
202
|
+
toBlock: numberToHex(toBlock),
|
|
203
|
+
},
|
|
209
204
|
context,
|
|
210
205
|
);
|
|
211
206
|
}),
|
|
@@ -318,14 +313,15 @@ export const createHistoricalSync = (
|
|
|
318
313
|
const logs = await syncLogsDynamic(
|
|
319
314
|
{
|
|
320
315
|
address: factory.address,
|
|
321
|
-
|
|
322
|
-
interval,
|
|
316
|
+
topics: [factory.eventSelector],
|
|
317
|
+
fromBlock: numberToHex(interval[0]),
|
|
318
|
+
toBlock: numberToHex(interval[1]),
|
|
323
319
|
},
|
|
324
320
|
context,
|
|
325
321
|
);
|
|
326
322
|
|
|
327
323
|
const childAddresses = new Map<Address, number>();
|
|
328
|
-
const
|
|
324
|
+
const factoryChildAddresses = args.childAddresses.get(factory.id)!;
|
|
329
325
|
|
|
330
326
|
const childAddressDecodeFailureIds = new Set<string>();
|
|
331
327
|
let childAddressDecodeFailureCount = 0;
|
|
@@ -358,7 +354,7 @@ export const createHistoricalSync = (
|
|
|
358
354
|
throw error;
|
|
359
355
|
}
|
|
360
356
|
}
|
|
361
|
-
const existingBlockNumber =
|
|
357
|
+
const existingBlockNumber = factoryChildAddresses.get(address);
|
|
362
358
|
const newBlockNumber = hexToNumber(log.blockNumber);
|
|
363
359
|
|
|
364
360
|
if (
|
|
@@ -366,7 +362,7 @@ export const createHistoricalSync = (
|
|
|
366
362
|
existingBlockNumber > newBlockNumber
|
|
367
363
|
) {
|
|
368
364
|
childAddresses.set(address, newBlockNumber);
|
|
369
|
-
|
|
365
|
+
factoryChildAddresses.set(address, newBlockNumber);
|
|
370
366
|
}
|
|
371
367
|
}
|
|
372
368
|
}
|
|
@@ -428,132 +424,17 @@ export const createHistoricalSync = (
|
|
|
428
424
|
}),
|
|
429
425
|
);
|
|
430
426
|
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
if (filter.type !== "log") continue;
|
|
436
|
-
|
|
437
|
-
const hasAddress = filter.address !== undefined;
|
|
438
|
-
const hasTopic1 = filter.topic1 !== undefined && filter.topic1 !== null;
|
|
439
|
-
const hasTopic2 = filter.topic2 !== undefined && filter.topic2 !== null;
|
|
440
|
-
const hasTopic3 = filter.topic3 !== undefined && filter.topic3 !== null;
|
|
441
|
-
|
|
442
|
-
if (hasAddress === false || hasTopic1 || hasTopic2 || hasTopic3) {
|
|
443
|
-
if (isAddressFactory(filter.address)) {
|
|
444
|
-
const childAddresses = args.childAddresses.get(filter.address.id)!;
|
|
445
|
-
|
|
446
|
-
if (childAddresses.size === 0) {
|
|
447
|
-
continue;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
singleEthGetLogsParams.push({
|
|
451
|
-
address:
|
|
452
|
-
childAddresses.size >=
|
|
453
|
-
args.common.options.factoryAddressCountThreshold
|
|
454
|
-
? undefined
|
|
455
|
-
: Array.from(childAddresses.keys()),
|
|
456
|
-
topic0: filter.topic0,
|
|
457
|
-
topic1: filter.topic1,
|
|
458
|
-
topic2: filter.topic2,
|
|
459
|
-
topic3: filter.topic3,
|
|
460
|
-
interval,
|
|
461
|
-
});
|
|
462
|
-
} else {
|
|
463
|
-
singleEthGetLogsParams.push({
|
|
464
|
-
address: filter.address,
|
|
465
|
-
topic0: filter.topic0,
|
|
466
|
-
topic1: filter.topic1,
|
|
467
|
-
topic2: filter.topic2,
|
|
468
|
-
topic3: filter.topic3,
|
|
469
|
-
interval,
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
continue;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
let addressKey: string;
|
|
477
|
-
if (isAddressFactory(filter.address)) {
|
|
478
|
-
addressKey = filter.address.id;
|
|
479
|
-
} else if (Array.isArray(filter.address)) {
|
|
480
|
-
addressKey = filter.address.join("_");
|
|
481
|
-
} else {
|
|
482
|
-
addressKey = filter.address as Address;
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
if (mergedEthGetLogsParams.has(addressKey) === false) {
|
|
486
|
-
if (isAddressFactory(filter.address)) {
|
|
487
|
-
const childAddresses = args.childAddresses.get(filter.address.id)!;
|
|
488
|
-
|
|
489
|
-
if (childAddresses.size === 0) {
|
|
490
|
-
continue;
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
mergedEthGetLogsParams.set(addressKey, {
|
|
494
|
-
address:
|
|
495
|
-
childAddresses.size >=
|
|
496
|
-
args.common.options.factoryAddressCountThreshold
|
|
497
|
-
? undefined
|
|
498
|
-
: Array.from(childAddresses.keys()),
|
|
499
|
-
topic0: filter.topic0,
|
|
500
|
-
topic1: filter.topic1,
|
|
501
|
-
topic2: filter.topic2,
|
|
502
|
-
topic3: filter.topic3,
|
|
503
|
-
interval,
|
|
504
|
-
});
|
|
505
|
-
} else {
|
|
506
|
-
mergedEthGetLogsParams.set(addressKey, {
|
|
507
|
-
address: filter.address,
|
|
508
|
-
topic0: filter.topic0,
|
|
509
|
-
topic1: filter.topic1,
|
|
510
|
-
topic2: filter.topic2,
|
|
511
|
-
topic3: filter.topic3,
|
|
512
|
-
interval,
|
|
513
|
-
});
|
|
514
|
-
}
|
|
515
|
-
} else {
|
|
516
|
-
const existingInterval =
|
|
517
|
-
mergedEthGetLogsParams.get(addressKey)!.interval;
|
|
518
|
-
const existingTopic0 = mergedEthGetLogsParams.get(addressKey)!
|
|
519
|
-
.topic0 as Hex | Hex[];
|
|
520
|
-
|
|
521
|
-
if (Array.isArray(existingTopic0)) {
|
|
522
|
-
if (existingTopic0.includes(filter.topic0) === false) {
|
|
523
|
-
mergedEthGetLogsParams.get(addressKey)!.topic0 = [
|
|
524
|
-
...existingTopic0,
|
|
525
|
-
filter.topic0,
|
|
526
|
-
];
|
|
527
|
-
}
|
|
528
|
-
} else {
|
|
529
|
-
if (existingTopic0 !== filter.topic0) {
|
|
530
|
-
mergedEthGetLogsParams.get(addressKey)!.topic0 = [
|
|
531
|
-
existingTopic0,
|
|
532
|
-
filter.topic0,
|
|
533
|
-
];
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
mergedEthGetLogsParams.get(addressKey)!.interval = intervalBounds([
|
|
538
|
-
existingInterval,
|
|
539
|
-
interval,
|
|
540
|
-
]);
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
const ethGetLogsParams = dedupe(
|
|
545
|
-
[
|
|
546
|
-
...singleEthGetLogsParams,
|
|
547
|
-
...Array.from(mergedEthGetLogsParams.values()),
|
|
548
|
-
],
|
|
549
|
-
(params) => JSON.stringify(params),
|
|
427
|
+
const ethGetLogsRequests = mergeLogFiltersToRequests(
|
|
428
|
+
requiredIntervals,
|
|
429
|
+
args.childAddresses,
|
|
430
|
+
args.common.options.factoryAddressCountThreshold,
|
|
550
431
|
);
|
|
551
432
|
|
|
552
433
|
let logs: SyncLog[] = [];
|
|
553
434
|
|
|
554
435
|
await Promise.all(
|
|
555
|
-
|
|
556
|
-
const _logs = await syncLogsDynamic(params, context);
|
|
436
|
+
ethGetLogsRequests.map(async (request) => {
|
|
437
|
+
const _logs = await syncLogsDynamic(request.params[0], context);
|
|
557
438
|
for (const log of _logs) {
|
|
558
439
|
logs.push(log);
|
|
559
440
|
}
|
package/src/utils/sql-parse.ts
CHANGED
|
@@ -152,17 +152,12 @@ export const isReadonlySQLQuery = async (sql: string): Promise<boolean> => {
|
|
|
152
152
|
export const getSQLQueryRelations = async (
|
|
153
153
|
sql: string,
|
|
154
154
|
): Promise<Set<string>> => {
|
|
155
|
-
const crypto = await import(/* webpackIgnore: true */ "node:crypto");
|
|
156
|
-
|
|
157
155
|
if (sql.length > 5_000) {
|
|
158
156
|
throw new Error("Invalid query");
|
|
159
157
|
}
|
|
160
158
|
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
.update(sql)
|
|
164
|
-
.digest("hex")
|
|
165
|
-
.slice(0, 10);
|
|
159
|
+
const crypto = await import(/* webpackIgnore: true */ "node:crypto");
|
|
160
|
+
const hash = crypto.createHash("sha256").update(sql).digest("hex");
|
|
166
161
|
|
|
167
162
|
if (RELATIONS_CACHE.has(hash)) {
|
|
168
163
|
const result = RELATIONS_CACHE.get(hash)!;
|