ponder 0.14.13 → 0.15.0
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/bin/commands/createViews.js +28 -11
- package/dist/esm/bin/commands/createViews.js.map +1 -1
- package/dist/esm/bin/commands/dev.js +42 -22
- package/dist/esm/bin/commands/dev.js.map +1 -1
- package/dist/esm/bin/commands/prune.js +3 -0
- package/dist/esm/bin/commands/prune.js.map +1 -1
- package/dist/esm/bin/commands/serve.js +4 -1
- package/dist/esm/bin/commands/serve.js.map +1 -1
- package/dist/esm/bin/commands/start.js +18 -6
- package/dist/esm/bin/commands/start.js.map +1 -1
- package/dist/esm/bin/isolatedController.js +200 -0
- package/dist/esm/bin/isolatedController.js.map +1 -0
- package/dist/esm/bin/isolatedWorker.js +146 -0
- package/dist/esm/bin/isolatedWorker.js.map +1 -0
- package/dist/esm/build/config.js +322 -402
- package/dist/esm/build/config.js.map +1 -1
- package/dist/esm/build/index.js +8 -11
- package/dist/esm/build/index.js.map +1 -1
- package/dist/esm/build/pre.js +1 -4
- package/dist/esm/build/pre.js.map +1 -1
- package/dist/esm/build/schema.js +25 -3
- package/dist/esm/build/schema.js.map +1 -1
- package/dist/esm/client/index.js +306 -42
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/database/actions.js +264 -104
- package/dist/esm/database/actions.js.map +1 -1
- package/dist/esm/database/index.js +39 -33
- package/dist/esm/database/index.js.map +1 -1
- package/dist/esm/database/queryBuilder.js +1 -0
- package/dist/esm/database/queryBuilder.js.map +1 -1
- package/dist/esm/drizzle/index.js +11 -7
- package/dist/esm/drizzle/index.js.map +1 -1
- package/dist/esm/drizzle/onchain.js +18 -0
- package/dist/esm/drizzle/onchain.js.map +1 -1
- package/dist/esm/indexing/client.js +32 -25
- package/dist/esm/indexing/client.js.map +1 -1
- package/dist/esm/indexing/index.js +110 -178
- package/dist/esm/indexing/index.js.map +1 -1
- package/dist/esm/indexing/profile.js +1 -1
- package/dist/esm/indexing/profile.js.map +1 -1
- package/dist/esm/indexing-store/cache.js +196 -274
- package/dist/esm/indexing-store/cache.js.map +1 -1
- package/dist/esm/indexing-store/historical.js +17 -13
- package/dist/esm/indexing-store/historical.js.map +1 -1
- package/dist/esm/indexing-store/index.js +10 -1
- package/dist/esm/indexing-store/index.js.map +1 -1
- package/dist/esm/indexing-store/profile.js +3 -3
- package/dist/esm/indexing-store/profile.js.map +1 -1
- package/dist/esm/indexing-store/realtime.js +27 -2
- package/dist/esm/indexing-store/realtime.js.map +1 -1
- package/dist/esm/internal/errors.js +28 -0
- package/dist/esm/internal/errors.js.map +1 -1
- package/dist/esm/internal/metrics.js +279 -82
- package/dist/esm/internal/metrics.js.map +1 -1
- package/dist/esm/internal/options.js +1 -0
- package/dist/esm/internal/options.js.map +1 -1
- package/dist/esm/internal/telemetry.js +1 -1
- package/dist/esm/internal/telemetry.js.map +1 -1
- package/dist/esm/rpc/http.js +130 -0
- package/dist/esm/rpc/http.js.map +1 -0
- package/dist/esm/rpc/index.js +38 -7
- package/dist/esm/rpc/index.js.map +1 -1
- package/dist/esm/runtime/events.js +179 -212
- package/dist/esm/runtime/events.js.map +1 -1
- package/dist/esm/runtime/filter.js +71 -0
- package/dist/esm/runtime/filter.js.map +1 -1
- package/dist/esm/runtime/fragments.js +78 -73
- package/dist/esm/runtime/fragments.js.map +1 -1
- package/dist/esm/runtime/historical.js +306 -130
- package/dist/esm/runtime/historical.js.map +1 -1
- package/dist/esm/runtime/index.js +183 -58
- package/dist/esm/runtime/index.js.map +1 -1
- package/dist/esm/runtime/isolated.js +462 -0
- package/dist/esm/runtime/isolated.js.map +1 -0
- package/dist/esm/runtime/multichain.js +80 -73
- package/dist/esm/runtime/multichain.js.map +1 -1
- package/dist/esm/runtime/omnichain.js +82 -75
- package/dist/esm/runtime/omnichain.js.map +1 -1
- package/dist/esm/runtime/realtime.js +198 -66
- package/dist/esm/runtime/realtime.js.map +1 -1
- package/dist/esm/sync-historical/index.js +416 -457
- package/dist/esm/sync-historical/index.js.map +1 -1
- package/dist/esm/sync-realtime/bloom.js +3 -3
- package/dist/esm/sync-realtime/bloom.js.map +1 -1
- package/dist/esm/sync-realtime/index.js +27 -46
- package/dist/esm/sync-realtime/index.js.map +1 -1
- package/dist/esm/sync-store/index.js +112 -63
- package/dist/esm/sync-store/index.js.map +1 -1
- package/dist/esm/utils/abi.js +20 -32
- package/dist/esm/utils/abi.js.map +1 -1
- package/dist/esm/utils/chunk.js +8 -0
- package/dist/esm/utils/chunk.js.map +1 -0
- package/dist/esm/utils/promiseAllSettledWithThrow.js +19 -0
- package/dist/esm/utils/promiseAllSettledWithThrow.js.map +1 -0
- package/dist/esm/{client/parse.js → utils/sql-parse.js} +94 -80
- package/dist/esm/utils/sql-parse.js.map +1 -0
- package/dist/types/bin/commands/createViews.d.ts.map +1 -1
- package/dist/types/bin/commands/dev.d.ts.map +1 -1
- package/dist/types/bin/commands/prune.d.ts.map +1 -1
- package/dist/types/bin/commands/serve.d.ts.map +1 -1
- package/dist/types/bin/commands/start.d.ts.map +1 -1
- package/dist/types/bin/isolatedController.d.ts +13 -0
- package/dist/types/bin/isolatedController.d.ts.map +1 -0
- package/dist/types/bin/isolatedWorker.d.ts +9 -0
- package/dist/types/bin/isolatedWorker.d.ts.map +1 -0
- package/dist/types/build/config.d.ts +29 -11
- package/dist/types/build/config.d.ts.map +1 -1
- package/dist/types/build/index.d.ts +3 -2
- package/dist/types/build/index.d.ts.map +1 -1
- package/dist/types/build/pre.d.ts +1 -1
- package/dist/types/build/pre.d.ts.map +1 -1
- package/dist/types/build/schema.d.ts +5 -3
- package/dist/types/build/schema.d.ts.map +1 -1
- package/dist/types/client/index.d.ts +1 -1
- package/dist/types/client/index.d.ts.map +1 -1
- package/dist/types/config/index.d.ts +3 -3
- package/dist/types/config/index.d.ts.map +1 -1
- package/dist/types/database/actions.d.ts +53 -7
- package/dist/types/database/actions.d.ts.map +1 -1
- package/dist/types/database/index.d.ts +21 -21
- package/dist/types/database/index.d.ts.map +1 -1
- package/dist/types/database/queryBuilder.d.ts.map +1 -1
- package/dist/types/drizzle/index.d.ts +4 -5
- package/dist/types/drizzle/index.d.ts.map +1 -1
- package/dist/types/drizzle/onchain.d.ts +6 -0
- package/dist/types/drizzle/onchain.d.ts.map +1 -1
- package/dist/types/indexing/client.d.ts.map +1 -1
- package/dist/types/indexing/index.d.ts +2 -5
- package/dist/types/indexing/index.d.ts.map +1 -1
- package/dist/types/indexing-store/cache.d.ts +3 -2
- package/dist/types/indexing-store/cache.d.ts.map +1 -1
- package/dist/types/indexing-store/historical.d.ts +2 -1
- package/dist/types/indexing-store/historical.d.ts.map +1 -1
- package/dist/types/indexing-store/index.d.ts +1 -0
- package/dist/types/indexing-store/index.d.ts.map +1 -1
- package/dist/types/indexing-store/realtime.d.ts +2 -1
- package/dist/types/indexing-store/realtime.d.ts.map +1 -1
- package/dist/types/internal/errors.d.ts +5 -0
- package/dist/types/internal/errors.d.ts.map +1 -1
- package/dist/types/internal/metrics.d.ts +21 -0
- package/dist/types/internal/metrics.d.ts.map +1 -1
- package/dist/types/internal/options.d.ts +2 -0
- package/dist/types/internal/options.d.ts.map +1 -1
- package/dist/types/internal/types.d.ts +66 -58
- package/dist/types/internal/types.d.ts.map +1 -1
- package/dist/types/rpc/http.d.ts +17 -0
- package/dist/types/rpc/http.d.ts.map +1 -0
- package/dist/types/rpc/index.d.ts.map +1 -1
- package/dist/types/runtime/events.d.ts +4 -4
- package/dist/types/runtime/events.d.ts.map +1 -1
- package/dist/types/runtime/filter.d.ts +5 -1
- package/dist/types/runtime/filter.d.ts.map +1 -1
- package/dist/types/runtime/fragments.d.ts +4 -3
- package/dist/types/runtime/fragments.d.ts.map +1 -1
- package/dist/types/runtime/historical.d.ts +29 -13
- package/dist/types/runtime/historical.d.ts.map +1 -1
- package/dist/types/runtime/index.d.ts +49 -6
- package/dist/types/runtime/index.d.ts.map +1 -1
- package/dist/types/runtime/init.d.ts +5 -5
- package/dist/types/runtime/init.d.ts.map +1 -1
- package/dist/types/runtime/isolated.d.ts +14 -0
- package/dist/types/runtime/isolated.d.ts.map +1 -0
- package/dist/types/runtime/multichain.d.ts.map +1 -1
- package/dist/types/runtime/omnichain.d.ts.map +1 -1
- package/dist/types/runtime/realtime.d.ts +21 -10
- package/dist/types/runtime/realtime.d.ts.map +1 -1
- package/dist/types/sync-historical/index.d.ts +18 -8
- package/dist/types/sync-historical/index.d.ts.map +1 -1
- package/dist/types/sync-realtime/bloom.d.ts.map +1 -1
- package/dist/types/sync-realtime/index.d.ts +2 -2
- package/dist/types/sync-realtime/index.d.ts.map +1 -1
- package/dist/types/sync-store/index.d.ts +9 -9
- package/dist/types/sync-store/index.d.ts.map +1 -1
- package/dist/types/utils/abi.d.ts +3 -34
- package/dist/types/utils/abi.d.ts.map +1 -1
- package/dist/types/utils/chunk.d.ts +2 -0
- package/dist/types/utils/chunk.d.ts.map +1 -0
- package/dist/types/utils/promiseAllSettledWithThrow.d.ts +8 -0
- package/dist/types/utils/promiseAllSettledWithThrow.d.ts.map +1 -0
- package/dist/types/utils/sql-parse.d.ts +21 -0
- package/dist/types/utils/sql-parse.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/bin/commands/createViews.ts +35 -15
- package/src/bin/commands/dev.ts +43 -21
- package/src/bin/commands/prune.ts +6 -0
- package/src/bin/commands/serve.ts +4 -1
- package/src/bin/commands/start.ts +20 -5
- package/src/bin/isolatedController.ts +300 -0
- package/src/bin/isolatedWorker.ts +192 -0
- package/src/build/config.ts +570 -632
- package/src/build/index.ts +14 -14
- package/src/build/pre.ts +1 -4
- package/src/build/schema.ts +49 -4
- package/src/client/index.ts +386 -48
- package/src/config/index.ts +3 -3
- package/src/database/actions.ts +469 -120
- package/src/database/index.ts +85 -58
- package/src/database/queryBuilder.ts +1 -0
- package/src/drizzle/index.ts +15 -7
- package/src/drizzle/onchain.ts +19 -0
- package/src/indexing/client.ts +38 -25
- package/src/indexing/index.ts +137 -230
- package/src/indexing/profile.ts +1 -1
- package/src/indexing-store/cache.ts +285 -414
- package/src/indexing-store/historical.ts +20 -10
- package/src/indexing-store/index.ts +16 -0
- package/src/indexing-store/profile.ts +3 -3
- package/src/indexing-store/realtime.ts +28 -0
- package/src/internal/errors.ts +26 -0
- package/src/internal/metrics.ts +341 -111
- package/src/internal/options.ts +4 -0
- package/src/internal/telemetry.ts +1 -1
- package/src/internal/types.ts +70 -87
- package/src/rpc/http.ts +164 -0
- package/src/rpc/index.ts +39 -7
- package/src/runtime/events.ts +195 -240
- package/src/runtime/filter.ts +85 -1
- package/src/runtime/fragments.ts +109 -113
- package/src/runtime/historical.ts +467 -189
- package/src/runtime/index.ts +337 -69
- package/src/runtime/init.ts +5 -5
- package/src/runtime/isolated.ts +768 -0
- package/src/runtime/multichain.ts +137 -102
- package/src/runtime/omnichain.ts +138 -106
- package/src/runtime/realtime.ts +322 -123
- package/src/sync-historical/index.ts +556 -692
- package/src/sync-realtime/bloom.ts +7 -3
- package/src/sync-realtime/index.ts +31 -46
- package/src/sync-store/index.ts +189 -95
- package/src/utils/abi.ts +33 -90
- package/src/utils/chunk.ts +7 -0
- package/src/utils/promiseAllSettledWithThrow.ts +27 -0
- package/src/{client/parse.ts → utils/sql-parse.ts} +100 -90
- package/dist/esm/client/parse.js.map +0 -1
- package/dist/types/client/parse.d.ts +0 -14
- package/dist/types/client/parse.d.ts.map +0 -1
package/dist/esm/build/config.js
CHANGED
|
@@ -2,12 +2,12 @@ import { BuildError } from '../internal/errors.js';
|
|
|
2
2
|
import { _eth_getBlockByNumber } from '../rpc/actions.js';
|
|
3
3
|
import { createRpc } from '../rpc/index.js';
|
|
4
4
|
import { defaultBlockFilterInclude, defaultLogFilterInclude, defaultTraceFilterInclude, defaultTransactionFilterInclude, defaultTransactionReceiptInclude, defaultTransferFilterInclude, } from '../runtime/filter.js';
|
|
5
|
-
import {
|
|
5
|
+
import { buildTopics, toSafeName } from '../utils/abi.js';
|
|
6
6
|
import { hyperliquidEvm, chains as viemChains } from '../utils/chains.js';
|
|
7
7
|
import { dedupe } from '../utils/dedupe.js';
|
|
8
8
|
import { getFinalityBlockCount } from '../utils/finality.js';
|
|
9
9
|
import { toLowerCase } from '../utils/lowercase.js';
|
|
10
|
-
import { BlockNotFoundError, hexToNumber } from "viem";
|
|
10
|
+
import { BlockNotFoundError, hexToNumber, toEventSelector, toFunctionSelector, } from "viem";
|
|
11
11
|
import { buildLogFactory } from "./factory.js";
|
|
12
12
|
const flattenSources = (config) => {
|
|
13
13
|
return Object.entries(config).flatMap(([name, source]) => {
|
|
@@ -31,7 +31,7 @@ const flattenSources = (config) => {
|
|
|
31
31
|
}
|
|
32
32
|
});
|
|
33
33
|
};
|
|
34
|
-
export async function buildIndexingFunctions({ common, config,
|
|
34
|
+
export async function buildIndexingFunctions({ common, config, indexingFunctions, configBuild: { chains, rpcs }, }) {
|
|
35
35
|
const context = { logger: common.logger.child({ action: "build" }) };
|
|
36
36
|
const logs = [];
|
|
37
37
|
const perChainLatestBlockNumber = new Map();
|
|
@@ -94,9 +94,11 @@ export async function buildIndexingFunctions({ common, config, rawIndexingFuncti
|
|
|
94
94
|
sourceNames.add(source);
|
|
95
95
|
}
|
|
96
96
|
// Validate and build indexing functions
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
if (indexingFunctions.length === 0) {
|
|
98
|
+
throw new Error("Validation failed: Found 0 registered indexing functions.");
|
|
99
|
+
}
|
|
100
|
+
const eventNames = new Set();
|
|
101
|
+
for (const { name: eventName } of indexingFunctions) {
|
|
100
102
|
const eventNameComponents = eventName.includes(".")
|
|
101
103
|
? eventName.split(".")
|
|
102
104
|
: eventName.split(":");
|
|
@@ -120,9 +122,10 @@ export async function buildIndexingFunctions({ common, config, rawIndexingFuncti
|
|
|
120
122
|
else {
|
|
121
123
|
throw new Error(`Validation failed: Invalid event '${eventName}', expected format '{sourceName}:{eventName}' or '{sourceName}.{functionName}'.`);
|
|
122
124
|
}
|
|
123
|
-
if (eventName
|
|
125
|
+
if (eventNames.has(eventName)) {
|
|
124
126
|
throw new Error(`Validation failed: Multiple indexing functions registered for event '${eventName}'.`);
|
|
125
127
|
}
|
|
128
|
+
eventNames.add(eventName);
|
|
126
129
|
// Validate that the indexing function uses a sourceName that is present in the config.
|
|
127
130
|
const matchedSourceName = Object.keys({
|
|
128
131
|
...(config.contracts ?? {}),
|
|
@@ -134,11 +137,6 @@ export async function buildIndexingFunctions({ common, config, rawIndexingFuncti
|
|
|
134
137
|
.map((n) => `'${n}'`)
|
|
135
138
|
.join(", ")}].`);
|
|
136
139
|
}
|
|
137
|
-
indexingFunctions[eventName] = fn;
|
|
138
|
-
indexingFunctionCount += 1;
|
|
139
|
-
}
|
|
140
|
-
if (indexingFunctionCount === 0) {
|
|
141
|
-
logs.push({ level: "warn", msg: "No registered indexing functions" });
|
|
142
140
|
}
|
|
143
141
|
// common validation for all sources
|
|
144
142
|
for (const source of [
|
|
@@ -191,12 +189,102 @@ export async function buildIndexingFunctions({ common, config, rawIndexingFuncti
|
|
|
191
189
|
}
|
|
192
190
|
}
|
|
193
191
|
}
|
|
194
|
-
const
|
|
192
|
+
const perChainEventCallbacks = new Map();
|
|
193
|
+
const perChainSetupCallbacks = new Map();
|
|
194
|
+
const perChainContracts = new Map();
|
|
195
|
+
for (const chain of chains) {
|
|
196
|
+
perChainEventCallbacks.set(chain.id, []);
|
|
197
|
+
perChainSetupCallbacks.set(chain.id, []);
|
|
198
|
+
perChainContracts.set(chain.id, {});
|
|
199
|
+
}
|
|
200
|
+
for (const source of flattenSources(config.contracts ?? {})) {
|
|
195
201
|
const chain = chains.find((n) => n.name === source.chain);
|
|
196
|
-
|
|
202
|
+
const fromBlock = await resolveBlockNumber(source.startBlock, chain);
|
|
203
|
+
const toBlock = await resolveBlockNumber(source.endBlock, chain);
|
|
204
|
+
if (indexingFunctions.some((f) => f.name === `${source.name}:setup`)) {
|
|
205
|
+
perChainSetupCallbacks.get(chain.id).push({
|
|
206
|
+
name: `${source.name}:setup`,
|
|
207
|
+
fn: indexingFunctions.find((f) => f.name === `${source.name}:setup`)
|
|
208
|
+
.fn,
|
|
209
|
+
chain,
|
|
210
|
+
block: fromBlock,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
let address;
|
|
214
|
+
const resolvedAddress = source?.address;
|
|
215
|
+
if (typeof resolvedAddress === "object" &&
|
|
216
|
+
Array.isArray(resolvedAddress) === false) {
|
|
217
|
+
const factoryAddress = resolvedAddress;
|
|
218
|
+
const factoryFromBlock = (await resolveBlockNumber(factoryAddress.startBlock, chain)) ??
|
|
219
|
+
fromBlock;
|
|
220
|
+
const factoryToBlock = (await resolveBlockNumber(factoryAddress.endBlock, chain)) ?? toBlock;
|
|
221
|
+
// Note that this can throw.
|
|
222
|
+
const logFactory = buildLogFactory({
|
|
223
|
+
chainId: chain.id,
|
|
224
|
+
...factoryAddress,
|
|
225
|
+
fromBlock: factoryFromBlock,
|
|
226
|
+
toBlock: factoryToBlock,
|
|
227
|
+
});
|
|
228
|
+
perChainContracts.get(chain.id)[source.name] = {
|
|
229
|
+
abi: source.abi,
|
|
230
|
+
address: undefined,
|
|
231
|
+
startBlock: fromBlock,
|
|
232
|
+
endBlock: toBlock,
|
|
233
|
+
};
|
|
234
|
+
address = logFactory;
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
if (resolvedAddress !== undefined) {
|
|
238
|
+
for (const address of Array.isArray(resolvedAddress)
|
|
239
|
+
? resolvedAddress
|
|
240
|
+
: [resolvedAddress]) {
|
|
241
|
+
if (!address.startsWith("0x"))
|
|
242
|
+
throw new Error(`Validation failed: Invalid prefix for address '${address}'. Got '${address.slice(0, 2)}', expected '0x'.`);
|
|
243
|
+
if (address.length !== 42)
|
|
244
|
+
throw new Error(`Validation failed: Invalid length for address '${address}'. Got ${address.length}, expected 42 characters.`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
const validatedAddress = Array.isArray(resolvedAddress)
|
|
248
|
+
? dedupe(resolvedAddress).map((r) => toLowerCase(r))
|
|
249
|
+
: resolvedAddress !== undefined
|
|
250
|
+
? toLowerCase(resolvedAddress)
|
|
251
|
+
: undefined;
|
|
252
|
+
perChainContracts.get(chain.id)[source.name] = {
|
|
253
|
+
abi: source.abi,
|
|
254
|
+
address: validatedAddress,
|
|
255
|
+
startBlock: fromBlock,
|
|
256
|
+
endBlock: toBlock,
|
|
257
|
+
};
|
|
258
|
+
address = validatedAddress;
|
|
259
|
+
}
|
|
260
|
+
const filteredEventSelectors = new Map();
|
|
261
|
+
if (source.filter) {
|
|
262
|
+
const eventFilters = Array.isArray(source.filter)
|
|
263
|
+
? source.filter
|
|
264
|
+
: [source.filter];
|
|
265
|
+
for (const filter of eventFilters) {
|
|
266
|
+
const abiEvent = source.abi.find((item) => item.type === "event" &&
|
|
267
|
+
toSafeName({ abi: source.abi, item }) === filter.event);
|
|
268
|
+
if (!abiEvent) {
|
|
269
|
+
throw new Error(`Validation failed: Invalid filter for contract '${source.name}'. Got event name '${filter.event}', expected one of [${source.abi
|
|
270
|
+
.filter((item) => item.type === "event")
|
|
271
|
+
.map((item) => `'${toSafeName({ abi: source.abi, item })}'`)
|
|
272
|
+
.join(", ")}].`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
const topics = buildTopics(source.abi, eventFilters);
|
|
276
|
+
for (const { topic0, topic1, topic2, topic3 } of topics) {
|
|
277
|
+
const abiItem = source.abi.find((item) => item.type === "event" && toEventSelector(item) === topic0);
|
|
278
|
+
const indexingFunction = indexingFunctions.find((f) => f.name === `${source.name}:${abiItem.name}`);
|
|
279
|
+
if (indexingFunction === undefined) {
|
|
280
|
+
throw new Error(`Validation failed: Event selector '${toSafeName({ abi: source.abi, item: abiItem })}' is used in a filter but does not have a corresponding indexing function.`);
|
|
281
|
+
}
|
|
282
|
+
filteredEventSelectors.set(topic0, { topic0, topic1, topic2, topic3 });
|
|
283
|
+
}
|
|
284
|
+
}
|
|
197
285
|
const registeredLogEvents = [];
|
|
198
286
|
const registeredCallTraceEvents = [];
|
|
199
|
-
for (const eventName of
|
|
287
|
+
for (const { name: eventName } of indexingFunctions) {
|
|
200
288
|
// log event
|
|
201
289
|
if (eventName.includes(":")) {
|
|
202
290
|
const [logContractName, logEventName] = eventName.split(":");
|
|
@@ -204,228 +292,124 @@ export async function buildIndexingFunctions({ common, config, rawIndexingFuncti
|
|
|
204
292
|
registeredLogEvents.push(logEventName);
|
|
205
293
|
}
|
|
206
294
|
}
|
|
207
|
-
//
|
|
295
|
+
// trace event
|
|
208
296
|
if (eventName.includes(".")) {
|
|
209
297
|
const [functionContractName, functionName] = eventName.split(".");
|
|
298
|
+
if (source.includeCallTraces !== true) {
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
210
301
|
if (functionContractName === source.name) {
|
|
211
302
|
registeredCallTraceEvents.push(functionName);
|
|
212
303
|
}
|
|
213
304
|
}
|
|
214
305
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
const registeredEventSelectors = [];
|
|
219
|
-
// Validate that the registered log events exist in the abi
|
|
220
|
-
for (const logEvent of registeredLogEvents) {
|
|
221
|
-
const abiEvent = abiEvents.bySafeName[logEvent];
|
|
306
|
+
for (const logEventName of registeredLogEvents) {
|
|
307
|
+
const abiEvent = source.abi.find((item) => item.type === "event" &&
|
|
308
|
+
toSafeName({ abi: source.abi, item }) === logEventName);
|
|
222
309
|
if (abiEvent === undefined) {
|
|
223
|
-
throw new Error(`Validation failed: Event name for event '${
|
|
224
|
-
.
|
|
310
|
+
throw new Error(`Validation failed: Event name for event '${logEventName}' not found in the contract ABI. Got '${logEventName}', expected one of [${source.abi
|
|
311
|
+
.filter((item) => item.type === "event")
|
|
312
|
+
.map((item) => `'${toSafeName({ abi: source.abi, item })}'`)
|
|
225
313
|
.join(", ")}].`);
|
|
226
314
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
315
|
+
const eventName = `${source.name}:${logEventName}`;
|
|
316
|
+
const indexingFunction = indexingFunctions.find((f) => f.name === eventName);
|
|
317
|
+
let topic1;
|
|
318
|
+
let topic2;
|
|
319
|
+
let topic3;
|
|
320
|
+
const eventSelector = toEventSelector(abiEvent);
|
|
321
|
+
if (filteredEventSelectors.has(eventSelector)) {
|
|
322
|
+
topic1 = filteredEventSelectors.get(eventSelector).topic1;
|
|
323
|
+
topic2 = filteredEventSelectors.get(eventSelector).topic2;
|
|
324
|
+
topic3 = filteredEventSelectors.get(eventSelector).topic3;
|
|
236
325
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
const eventFilters = Array.isArray(source.filter)
|
|
242
|
-
? source.filter
|
|
243
|
-
: [source.filter];
|
|
244
|
-
for (const filter of eventFilters) {
|
|
245
|
-
const abiEvent = abiEvents.bySafeName[filter.event];
|
|
246
|
-
if (!abiEvent) {
|
|
247
|
-
throw new Error(`Validation failed: Invalid filter for contract '${source.name}'. Got event name '${filter.event}', expected one of [${Object.keys(abiEvents.bySafeName)
|
|
248
|
-
.map((n) => `'${n}'`)
|
|
249
|
-
.join(", ")}].`);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
topicsArray.push(...buildTopics(source.abi, eventFilters));
|
|
253
|
-
// event selectors that have a filter
|
|
254
|
-
const filteredEventSelectors = topicsArray.map((t) => t.topic0);
|
|
255
|
-
// event selectors that are registered but don't have a filter
|
|
256
|
-
const excludedRegisteredEventSelectors = registeredEventSelectors.filter((s) => filteredEventSelectors.includes(s) === false);
|
|
257
|
-
for (const selector of filteredEventSelectors) {
|
|
258
|
-
if (registeredEventSelectors.includes(selector) === false) {
|
|
259
|
-
throw new Error(`Validation failed: Event selector '${abiEvents.bySelector[selector]?.safeName}' is used in a filter but does not have a corresponding indexing function.`);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
if (excludedRegisteredEventSelectors.length > 0) {
|
|
263
|
-
topicsArray.push({
|
|
264
|
-
topic0: excludedRegisteredEventSelectors,
|
|
265
|
-
topic1: null,
|
|
266
|
-
topic2: null,
|
|
267
|
-
topic3: null,
|
|
268
|
-
});
|
|
326
|
+
else {
|
|
327
|
+
topic1 = null;
|
|
328
|
+
topic2 = null;
|
|
329
|
+
topic3 = null;
|
|
269
330
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
topicsArray.push({
|
|
273
|
-
topic0: registeredEventSelectors,
|
|
274
|
-
topic1: null,
|
|
275
|
-
topic2: null,
|
|
276
|
-
topic3: null,
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
const fromBlock = await resolveBlockNumber(source.startBlock, chain);
|
|
280
|
-
const toBlock = await resolveBlockNumber(source.endBlock, chain);
|
|
281
|
-
const contractMetadata = {
|
|
282
|
-
type: "contract",
|
|
283
|
-
abi: source.abi,
|
|
284
|
-
abiEvents,
|
|
285
|
-
abiFunctions,
|
|
286
|
-
name: source.name,
|
|
287
|
-
chain,
|
|
288
|
-
};
|
|
289
|
-
const resolvedAddress = source?.address;
|
|
290
|
-
if (typeof resolvedAddress === "object" &&
|
|
291
|
-
!Array.isArray(resolvedAddress)) {
|
|
292
|
-
const factoryFromBlock = (await resolveBlockNumber(resolvedAddress.startBlock, chain)) ??
|
|
293
|
-
fromBlock;
|
|
294
|
-
const factoryToBlock = (await resolveBlockNumber(resolvedAddress.endBlock, chain)) ??
|
|
295
|
-
toBlock;
|
|
296
|
-
// Note that this can throw.
|
|
297
|
-
const logFactory = buildLogFactory({
|
|
331
|
+
const filter = {
|
|
332
|
+
type: "log",
|
|
298
333
|
chainId: chain.id,
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
334
|
+
sourceId: source.name,
|
|
335
|
+
address,
|
|
336
|
+
topic0: eventSelector,
|
|
337
|
+
topic1,
|
|
338
|
+
topic2,
|
|
339
|
+
topic3,
|
|
340
|
+
fromBlock,
|
|
341
|
+
toBlock,
|
|
342
|
+
hasTransactionReceipt: source.includeTransactionReceipts ?? false,
|
|
343
|
+
include: defaultLogFilterInclude.concat(source.includeTransactionReceipts
|
|
344
|
+
? defaultTransactionReceiptInclude.map((value) => `transactionReceipt.${value}`)
|
|
345
|
+
: []),
|
|
346
|
+
};
|
|
347
|
+
const eventCallback = {
|
|
348
|
+
filter,
|
|
349
|
+
name: eventName,
|
|
350
|
+
fn: indexingFunction.fn,
|
|
351
|
+
chain,
|
|
352
|
+
type: "contract",
|
|
353
|
+
abiItem: abiEvent,
|
|
354
|
+
metadata: {
|
|
355
|
+
safeName: logEventName,
|
|
356
|
+
abi: source.abi,
|
|
319
357
|
},
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
return [
|
|
323
|
-
...logSources,
|
|
324
|
-
{
|
|
325
|
-
...contractMetadata,
|
|
326
|
-
filter: {
|
|
327
|
-
type: "trace",
|
|
328
|
-
chainId: chain.id,
|
|
329
|
-
fromAddress: undefined,
|
|
330
|
-
toAddress: logFactory,
|
|
331
|
-
callType: "CALL",
|
|
332
|
-
functionSelector: registeredFunctionSelectors,
|
|
333
|
-
includeReverted: false,
|
|
334
|
-
fromBlock,
|
|
335
|
-
toBlock,
|
|
336
|
-
hasTransactionReceipt: source.includeTransactionReceipts ?? false,
|
|
337
|
-
include: defaultTraceFilterInclude.concat(source.includeTransactionReceipts
|
|
338
|
-
? defaultTransactionReceiptInclude.map((value) => `transactionReceipt.${value}`)
|
|
339
|
-
: []),
|
|
340
|
-
},
|
|
341
|
-
},
|
|
342
|
-
];
|
|
343
|
-
}
|
|
344
|
-
return logSources;
|
|
358
|
+
};
|
|
359
|
+
perChainEventCallbacks.get(chain.id).push(eventCallback);
|
|
345
360
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
361
|
+
for (const functionEventName of registeredCallTraceEvents) {
|
|
362
|
+
const abiFunction = source.abi.find((item) => item.type === "function" &&
|
|
363
|
+
toSafeName({ abi: source.abi, item }) === functionEventName);
|
|
364
|
+
if (abiFunction === undefined) {
|
|
365
|
+
throw new Error(`Validation failed: Function name for function '${functionEventName}' not found in the contract ABI. Got '${functionEventName}', expected one of [${source.abi
|
|
366
|
+
.filter((item) => item.type === "function")
|
|
367
|
+
.map((item) => `'${toSafeName({ abi: source.abi, item })}'`)
|
|
368
|
+
.join(", ")}].`);
|
|
354
369
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
? toLowerCase(resolvedAddress)
|
|
360
|
-
: undefined;
|
|
361
|
-
const logSources = topicsArray.map((topics) => ({
|
|
362
|
-
...contractMetadata,
|
|
363
|
-
filter: {
|
|
364
|
-
type: "log",
|
|
370
|
+
const eventName = `${source.name}.${functionEventName}`;
|
|
371
|
+
const indexingFunction = indexingFunctions.find((f) => f.name === eventName);
|
|
372
|
+
const filter = {
|
|
373
|
+
type: "trace",
|
|
365
374
|
chainId: chain.id,
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
375
|
+
sourceId: source.name,
|
|
376
|
+
fromAddress: undefined,
|
|
377
|
+
toAddress: address,
|
|
378
|
+
callType: "CALL",
|
|
379
|
+
functionSelector: toFunctionSelector(abiFunction),
|
|
380
|
+
includeReverted: false,
|
|
371
381
|
fromBlock,
|
|
372
382
|
toBlock,
|
|
373
383
|
hasTransactionReceipt: source.includeTransactionReceipts ?? false,
|
|
374
|
-
include:
|
|
384
|
+
include: defaultTraceFilterInclude.concat(source.includeTransactionReceipts
|
|
375
385
|
? defaultTransactionReceiptInclude.map((value) => `transactionReceipt.${value}`)
|
|
376
386
|
: []),
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
toAddress: Array.isArray(validatedAddress)
|
|
389
|
-
? validatedAddress
|
|
390
|
-
: validatedAddress === undefined
|
|
391
|
-
? undefined
|
|
392
|
-
: [validatedAddress],
|
|
393
|
-
callType: "CALL",
|
|
394
|
-
functionSelector: registeredFunctionSelectors,
|
|
395
|
-
includeReverted: false,
|
|
396
|
-
fromBlock,
|
|
397
|
-
toBlock,
|
|
398
|
-
hasTransactionReceipt: source.includeTransactionReceipts ?? false,
|
|
399
|
-
include: defaultTraceFilterInclude.concat(source.includeTransactionReceipts
|
|
400
|
-
? defaultTransactionReceiptInclude.map((value) => `transactionReceipt.${value}`)
|
|
401
|
-
: []),
|
|
402
|
-
},
|
|
387
|
+
};
|
|
388
|
+
const eventCallback = {
|
|
389
|
+
filter,
|
|
390
|
+
name: eventName,
|
|
391
|
+
fn: indexingFunction.fn,
|
|
392
|
+
chain,
|
|
393
|
+
type: "contract",
|
|
394
|
+
abiItem: abiFunction,
|
|
395
|
+
metadata: {
|
|
396
|
+
safeName: functionEventName,
|
|
397
|
+
abi: source.abi,
|
|
403
398
|
},
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
.flat() // Remove sources with no registered indexing functions
|
|
410
|
-
.filter((source) => {
|
|
411
|
-
const hasNoRegisteredIndexingFunctions = source.filter.type === "trace"
|
|
412
|
-
? Array.isArray(source.filter.functionSelector) &&
|
|
413
|
-
source.filter.functionSelector.length === 0
|
|
414
|
-
: Array.isArray(source.filter.topic0) &&
|
|
415
|
-
source.filter.topic0?.length === 0;
|
|
416
|
-
if (hasNoRegisteredIndexingFunctions) {
|
|
399
|
+
};
|
|
400
|
+
perChainEventCallbacks.get(chain.id).push(eventCallback);
|
|
401
|
+
}
|
|
402
|
+
if (registeredLogEvents.length === 0 &&
|
|
403
|
+
registeredCallTraceEvents.length === 0) {
|
|
417
404
|
logs.push({
|
|
418
405
|
level: "warn",
|
|
419
406
|
msg: "No registered indexing functions",
|
|
420
|
-
chain: source.chain.name,
|
|
421
|
-
chain_id: source.chain.id,
|
|
422
407
|
name: source.name,
|
|
423
|
-
type:
|
|
408
|
+
type: "contract",
|
|
424
409
|
});
|
|
425
410
|
}
|
|
426
|
-
|
|
427
|
-
})
|
|
428
|
-
const accountSources = (await Promise.all(flattenSources(config.accounts ?? {}).map(async (source) => {
|
|
411
|
+
}
|
|
412
|
+
for (const source of flattenSources(config.accounts ?? {})) {
|
|
429
413
|
const chain = chains.find((n) => n.name === source.chain);
|
|
430
414
|
const fromBlock = await resolveBlockNumber(source.startBlock, chain);
|
|
431
415
|
const toBlock = await resolveBlockNumber(source.endBlock, chain);
|
|
@@ -433,12 +417,12 @@ export async function buildIndexingFunctions({ common, config, rawIndexingFuncti
|
|
|
433
417
|
if (resolvedAddress === undefined) {
|
|
434
418
|
throw new Error(`Validation failed: Account '${source.name}' must specify an 'address'.`);
|
|
435
419
|
}
|
|
420
|
+
let address;
|
|
436
421
|
if (typeof resolvedAddress === "object" &&
|
|
437
422
|
!Array.isArray(resolvedAddress)) {
|
|
438
423
|
const factoryFromBlock = (await resolveBlockNumber(resolvedAddress.startBlock, chain)) ??
|
|
439
424
|
fromBlock;
|
|
440
|
-
const factoryToBlock = (await resolveBlockNumber(resolvedAddress.endBlock, chain)) ??
|
|
441
|
-
toBlock;
|
|
425
|
+
const factoryToBlock = (await resolveBlockNumber(resolvedAddress.endBlock, chain)) ?? toBlock;
|
|
442
426
|
// Note that this can throw.
|
|
443
427
|
const logFactory = buildLogFactory({
|
|
444
428
|
chainId: chain.id,
|
|
@@ -446,184 +430,111 @@ export async function buildIndexingFunctions({ common, config, rawIndexingFuncti
|
|
|
446
430
|
fromBlock: factoryFromBlock,
|
|
447
431
|
toBlock: factoryToBlock,
|
|
448
432
|
});
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
name: source.name,
|
|
469
|
-
chain,
|
|
470
|
-
filter: {
|
|
471
|
-
type: "transaction",
|
|
472
|
-
chainId: chain.id,
|
|
473
|
-
fromAddress: logFactory,
|
|
474
|
-
toAddress: undefined,
|
|
475
|
-
includeReverted: false,
|
|
476
|
-
fromBlock,
|
|
477
|
-
toBlock,
|
|
478
|
-
hasTransactionReceipt: true,
|
|
479
|
-
include: defaultTransactionFilterInclude,
|
|
480
|
-
},
|
|
481
|
-
},
|
|
482
|
-
{
|
|
483
|
-
type: "account",
|
|
484
|
-
name: source.name,
|
|
485
|
-
chain,
|
|
486
|
-
filter: {
|
|
487
|
-
type: "transfer",
|
|
488
|
-
chainId: chain.id,
|
|
489
|
-
fromAddress: undefined,
|
|
490
|
-
toAddress: logFactory,
|
|
491
|
-
includeReverted: false,
|
|
492
|
-
fromBlock,
|
|
493
|
-
toBlock,
|
|
494
|
-
hasTransactionReceipt: source.includeTransactionReceipts ?? false,
|
|
495
|
-
include: defaultTransferFilterInclude.concat(source.includeTransactionReceipts
|
|
496
|
-
? defaultTransactionReceiptInclude.map((value) => `transactionReceipt.${value}`)
|
|
497
|
-
: []),
|
|
498
|
-
},
|
|
499
|
-
},
|
|
500
|
-
{
|
|
501
|
-
type: "account",
|
|
502
|
-
name: source.name,
|
|
503
|
-
chain,
|
|
504
|
-
filter: {
|
|
505
|
-
type: "transfer",
|
|
506
|
-
chainId: chain.id,
|
|
507
|
-
fromAddress: logFactory,
|
|
508
|
-
toAddress: undefined,
|
|
509
|
-
includeReverted: false,
|
|
510
|
-
fromBlock,
|
|
511
|
-
toBlock,
|
|
512
|
-
hasTransactionReceipt: source.includeTransactionReceipts ?? false,
|
|
513
|
-
include: defaultTransferFilterInclude.concat(source.includeTransactionReceipts
|
|
514
|
-
? defaultTransactionReceiptInclude.map((value) => `transactionReceipt.${value}`)
|
|
515
|
-
: []),
|
|
516
|
-
},
|
|
517
|
-
},
|
|
518
|
-
];
|
|
519
|
-
}
|
|
520
|
-
for (const address of Array.isArray(resolvedAddress)
|
|
521
|
-
? resolvedAddress
|
|
522
|
-
: [resolvedAddress]) {
|
|
523
|
-
if (!address.startsWith("0x"))
|
|
524
|
-
throw new Error(`Validation failed: Invalid prefix for address '${address}'. Got '${address.slice(0, 2)}', expected '0x'.`);
|
|
525
|
-
if (address.length !== 42)
|
|
526
|
-
throw new Error(`Validation failed: Invalid length for address '${address}'. Got ${address.length}, expected 42 characters.`);
|
|
527
|
-
}
|
|
528
|
-
const validatedAddress = Array.isArray(resolvedAddress)
|
|
529
|
-
? dedupe(resolvedAddress).map((r) => toLowerCase(r))
|
|
530
|
-
: resolvedAddress !== undefined
|
|
531
|
-
? toLowerCase(resolvedAddress)
|
|
532
|
-
: undefined;
|
|
533
|
-
return [
|
|
433
|
+
address = logFactory;
|
|
434
|
+
}
|
|
435
|
+
else {
|
|
436
|
+
for (const address of Array.isArray(resolvedAddress)
|
|
437
|
+
? resolvedAddress
|
|
438
|
+
: [resolvedAddress]) {
|
|
439
|
+
if (!address.startsWith("0x"))
|
|
440
|
+
throw new Error(`Validation failed: Invalid prefix for address '${address}'. Got '${address.slice(0, 2)}', expected '0x'.`);
|
|
441
|
+
if (address.length !== 42)
|
|
442
|
+
throw new Error(`Validation failed: Invalid length for address '${address}'. Got ${address.length}, expected 42 characters.`);
|
|
443
|
+
}
|
|
444
|
+
const validatedAddress = Array.isArray(resolvedAddress)
|
|
445
|
+
? dedupe(resolvedAddress).map((r) => toLowerCase(r))
|
|
446
|
+
: resolvedAddress !== undefined
|
|
447
|
+
? toLowerCase(resolvedAddress)
|
|
448
|
+
: undefined;
|
|
449
|
+
address = validatedAddress;
|
|
450
|
+
}
|
|
451
|
+
const filters = [
|
|
534
452
|
{
|
|
535
|
-
type: "
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
toBlock,
|
|
546
|
-
hasTransactionReceipt: true,
|
|
547
|
-
include: defaultTransactionFilterInclude,
|
|
548
|
-
},
|
|
453
|
+
type: "transaction",
|
|
454
|
+
chainId: chain.id,
|
|
455
|
+
sourceId: source.name,
|
|
456
|
+
fromAddress: undefined,
|
|
457
|
+
toAddress: address,
|
|
458
|
+
includeReverted: false,
|
|
459
|
+
fromBlock,
|
|
460
|
+
toBlock,
|
|
461
|
+
hasTransactionReceipt: true,
|
|
462
|
+
include: defaultTransactionFilterInclude,
|
|
549
463
|
},
|
|
550
464
|
{
|
|
551
|
-
type: "
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
toBlock,
|
|
562
|
-
hasTransactionReceipt: true,
|
|
563
|
-
include: defaultTransactionFilterInclude,
|
|
564
|
-
},
|
|
465
|
+
type: "transaction",
|
|
466
|
+
chainId: chain.id,
|
|
467
|
+
sourceId: source.name,
|
|
468
|
+
fromAddress: address,
|
|
469
|
+
toAddress: undefined,
|
|
470
|
+
includeReverted: false,
|
|
471
|
+
fromBlock,
|
|
472
|
+
toBlock,
|
|
473
|
+
hasTransactionReceipt: true,
|
|
474
|
+
include: defaultTransactionFilterInclude,
|
|
565
475
|
},
|
|
566
476
|
{
|
|
567
|
-
type: "
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
include: defaultTransferFilterInclude.concat(source.includeTransactionReceipts
|
|
580
|
-
? defaultTransactionReceiptInclude.map((value) => `transactionReceipt.${value}`)
|
|
581
|
-
: []),
|
|
582
|
-
},
|
|
477
|
+
type: "transfer",
|
|
478
|
+
chainId: chain.id,
|
|
479
|
+
sourceId: source.name,
|
|
480
|
+
fromAddress: undefined,
|
|
481
|
+
toAddress: address,
|
|
482
|
+
includeReverted: false,
|
|
483
|
+
fromBlock,
|
|
484
|
+
toBlock,
|
|
485
|
+
hasTransactionReceipt: source.includeTransactionReceipts ?? false,
|
|
486
|
+
include: defaultTransferFilterInclude.concat(source.includeTransactionReceipts
|
|
487
|
+
? defaultTransactionReceiptInclude.map((value) => `transactionReceipt.${value}`)
|
|
488
|
+
: []),
|
|
583
489
|
},
|
|
584
490
|
{
|
|
585
|
-
type: "
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
include: defaultTransferFilterInclude.concat(source.includeTransactionReceipts
|
|
598
|
-
? defaultTransactionReceiptInclude.map((value) => `transactionReceipt.${value}`)
|
|
599
|
-
: []),
|
|
600
|
-
},
|
|
491
|
+
type: "transfer",
|
|
492
|
+
chainId: chain.id,
|
|
493
|
+
sourceId: source.name,
|
|
494
|
+
fromAddress: address,
|
|
495
|
+
toAddress: undefined,
|
|
496
|
+
includeReverted: false,
|
|
497
|
+
fromBlock,
|
|
498
|
+
toBlock,
|
|
499
|
+
hasTransactionReceipt: source.includeTransactionReceipts ?? false,
|
|
500
|
+
include: defaultTransferFilterInclude.concat(source.includeTransactionReceipts
|
|
501
|
+
? defaultTransactionReceiptInclude.map((value) => `transactionReceipt.${value}`)
|
|
502
|
+
: []),
|
|
601
503
|
},
|
|
602
504
|
];
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
:
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
505
|
+
let hasRegisteredIndexingFunction = false;
|
|
506
|
+
for (const filter of filters) {
|
|
507
|
+
const eventName = filter.type === "transaction"
|
|
508
|
+
? filter.fromAddress === undefined
|
|
509
|
+
? `${source.name}:transaction:to`
|
|
510
|
+
: `${source.name}:transaction:from`
|
|
511
|
+
: filter.fromAddress === undefined
|
|
512
|
+
? `${source.name}:transfer:to`
|
|
513
|
+
: `${source.name}:transfer:from`;
|
|
514
|
+
const indexingFunction = indexingFunctions.find((f) => f.name === eventName);
|
|
515
|
+
if (indexingFunction) {
|
|
516
|
+
hasRegisteredIndexingFunction = true;
|
|
517
|
+
const eventCallback = {
|
|
518
|
+
filter,
|
|
519
|
+
name: eventName,
|
|
520
|
+
fn: indexingFunction.fn,
|
|
521
|
+
chain,
|
|
522
|
+
type: "account",
|
|
523
|
+
direction: filter.fromAddress === undefined ? "to" : "from",
|
|
524
|
+
};
|
|
525
|
+
perChainEventCallbacks.get(chain.id).push(eventCallback);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
if (hasRegisteredIndexingFunction === false) {
|
|
615
529
|
logs.push({
|
|
616
|
-
level: "
|
|
530
|
+
level: "warn",
|
|
617
531
|
msg: "No registered indexing functions",
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
name: eventName,
|
|
621
|
-
type: source.filter.type,
|
|
532
|
+
name: source.name,
|
|
533
|
+
type: "account",
|
|
622
534
|
});
|
|
623
535
|
}
|
|
624
|
-
|
|
625
|
-
})
|
|
626
|
-
const blockSources = (await Promise.all(flattenSources(config.blocks ?? {}).map(async (source) => {
|
|
536
|
+
}
|
|
537
|
+
for (const source of flattenSources(config.blocks ?? {})) {
|
|
627
538
|
const chain = chains.find((n) => n.name === source.chain);
|
|
628
539
|
const intervalMaybeNan = source.interval ?? 1;
|
|
629
540
|
const interval = Number.isNaN(intervalMaybeNan) ? 0 : intervalMaybeNan;
|
|
@@ -632,50 +543,57 @@ export async function buildIndexingFunctions({ common, config, rawIndexingFuncti
|
|
|
632
543
|
}
|
|
633
544
|
const fromBlock = await resolveBlockNumber(source.startBlock, chain);
|
|
634
545
|
const toBlock = await resolveBlockNumber(source.endBlock, chain);
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
filter: {
|
|
546
|
+
const eventName = `${source.name}:block`;
|
|
547
|
+
const indexingFunction = indexingFunctions.find((f) => f.name === eventName);
|
|
548
|
+
if (indexingFunction) {
|
|
549
|
+
const filter = {
|
|
640
550
|
type: "block",
|
|
641
551
|
chainId: chain.id,
|
|
552
|
+
sourceId: source.name,
|
|
642
553
|
interval: interval,
|
|
643
554
|
offset: (fromBlock ?? 0) % interval,
|
|
644
555
|
fromBlock,
|
|
645
556
|
toBlock,
|
|
646
557
|
hasTransactionReceipt: false,
|
|
647
558
|
include: defaultBlockFilterInclude,
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
559
|
+
};
|
|
560
|
+
const eventCallback = {
|
|
561
|
+
filter,
|
|
562
|
+
name: eventName,
|
|
563
|
+
fn: indexingFunction.fn,
|
|
564
|
+
chain,
|
|
565
|
+
type: "block",
|
|
566
|
+
};
|
|
567
|
+
perChainEventCallbacks.get(chain.id).push(eventCallback);
|
|
568
|
+
}
|
|
569
|
+
else {
|
|
655
570
|
logs.push({
|
|
656
571
|
level: "warn",
|
|
657
572
|
msg: "No registered indexing functions",
|
|
658
|
-
chain: source.chain.name,
|
|
659
|
-
chain_id: source.chain.id,
|
|
660
573
|
name: source.name,
|
|
661
574
|
type: "block",
|
|
662
575
|
});
|
|
663
576
|
}
|
|
664
|
-
|
|
665
|
-
});
|
|
666
|
-
const sources = [...contractSources, ...accountSources, ...blockSources];
|
|
577
|
+
}
|
|
667
578
|
// Filter out any chains that don't have any sources registered.
|
|
668
579
|
const chainsWithSources = [];
|
|
669
580
|
const rpcsWithSources = [];
|
|
670
581
|
const finalizedBlocksWithSources = [];
|
|
582
|
+
const eventCallbacksWithSources = [];
|
|
583
|
+
const setupCallbacksWithSources = [];
|
|
584
|
+
const contractsWithSources = [];
|
|
671
585
|
for (let i = 0; i < chains.length; i++) {
|
|
672
586
|
const chain = chains[i];
|
|
673
587
|
const rpc = rpcs[i];
|
|
674
|
-
const
|
|
675
|
-
|
|
588
|
+
const hasIndexingFunctions = perChainEventCallbacks.get(chain.id).length > 0 ||
|
|
589
|
+
perChainSetupCallbacks.get(chain.id).length > 0;
|
|
590
|
+
if (hasIndexingFunctions) {
|
|
676
591
|
chainsWithSources.push(chain);
|
|
677
592
|
rpcsWithSources.push(rpc);
|
|
678
593
|
finalizedBlocksWithSources.push(finalizedBlocks[i]);
|
|
594
|
+
eventCallbacksWithSources.push(perChainEventCallbacks.get(chain.id));
|
|
595
|
+
setupCallbacksWithSources.push(perChainSetupCallbacks.get(chain.id));
|
|
596
|
+
contractsWithSources.push(perChainContracts.get(chain.id));
|
|
679
597
|
}
|
|
680
598
|
else {
|
|
681
599
|
logs.push({
|
|
@@ -686,15 +604,16 @@ export async function buildIndexingFunctions({ common, config, rawIndexingFuncti
|
|
|
686
604
|
});
|
|
687
605
|
}
|
|
688
606
|
}
|
|
689
|
-
if (
|
|
690
|
-
throw new Error("Validation failed: Found 0 registered indexing functions.");
|
|
607
|
+
if (chainsWithSources.length === 0) {
|
|
608
|
+
throw new Error("Validation failed: Found 0 chains with registered indexing functions.");
|
|
691
609
|
}
|
|
692
610
|
return {
|
|
693
611
|
chains: chainsWithSources,
|
|
694
612
|
rpcs: rpcsWithSources,
|
|
695
613
|
finalizedBlocks: finalizedBlocksWithSources,
|
|
696
|
-
|
|
697
|
-
|
|
614
|
+
eventCallbacks: eventCallbacksWithSources,
|
|
615
|
+
setupCallbacks: setupCallbacksWithSources,
|
|
616
|
+
contracts: contractsWithSources,
|
|
698
617
|
logs,
|
|
699
618
|
};
|
|
700
619
|
}
|
|
@@ -773,21 +692,22 @@ export function buildConfig({ common, config, }) {
|
|
|
773
692
|
}));
|
|
774
693
|
return { chains, rpcs, logs };
|
|
775
694
|
}
|
|
776
|
-
export async function safeBuildIndexingFunctions({ common, config,
|
|
695
|
+
export async function safeBuildIndexingFunctions({ common, config, indexingFunctions, configBuild, }) {
|
|
777
696
|
try {
|
|
778
697
|
const result = await buildIndexingFunctions({
|
|
779
698
|
common,
|
|
780
699
|
config,
|
|
781
|
-
|
|
700
|
+
indexingFunctions,
|
|
782
701
|
configBuild,
|
|
783
702
|
});
|
|
784
703
|
return {
|
|
785
704
|
status: "success",
|
|
786
|
-
sources: result.sources,
|
|
787
705
|
chains: result.chains,
|
|
788
706
|
rpcs: result.rpcs,
|
|
789
707
|
finalizedBlocks: result.finalizedBlocks,
|
|
790
|
-
|
|
708
|
+
eventCallbacks: result.eventCallbacks,
|
|
709
|
+
setupCallbacks: result.setupCallbacks,
|
|
710
|
+
contracts: result.contracts,
|
|
791
711
|
logs: result.logs,
|
|
792
712
|
};
|
|
793
713
|
}
|