@hugomrdias/foxer 0.1.9 → 0.1.11
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/README.md +71 -1
- package/dist/config/env.d.ts +1 -1
- package/dist/config/env.d.ts.map +1 -1
- package/dist/config/env.js +2 -2
- package/dist/config/env.js.map +1 -1
- package/dist/db/actions/blocks.d.ts +9 -6
- package/dist/db/actions/blocks.d.ts.map +1 -1
- package/dist/db/actions/blocks.js +39 -43
- package/dist/db/actions/blocks.js.map +1 -1
- package/dist/db/client.d.ts +1 -1
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +5 -1
- package/dist/db/client.js.map +1 -1
- package/dist/db/column-types.d.ts +2 -2
- package/dist/db/column-types.d.ts.map +1 -1
- package/dist/db/column-types.js +11 -3
- package/dist/db/column-types.js.map +1 -1
- package/dist/db/schema/blocks.d.ts +16 -16
- package/dist/db/schema/index.d.ts +44 -44
- package/dist/db/schema/transactions.d.ts +6 -6
- package/dist/db/schema/transactions.d.ts.map +1 -1
- package/dist/db/schema/transactions.js +3 -1
- package/dist/db/schema/transactions.js.map +1 -1
- package/dist/hooks/registry.d.ts +3 -3
- package/dist/hooks/registry.d.ts.map +1 -1
- package/dist/indexer/backfill.d.ts.map +1 -1
- package/dist/indexer/backfill.js +19 -12
- package/dist/indexer/backfill.js.map +1 -1
- package/dist/indexer/process-block.d.ts +4 -4
- package/dist/indexer/process-block.d.ts.map +1 -1
- package/dist/indexer/process-block.js +4 -29
- package/dist/indexer/process-block.js.map +1 -1
- package/dist/indexer/queue-block.d.ts.map +1 -1
- package/dist/indexer/queue-block.js +19 -1
- package/dist/indexer/queue-block.js.map +1 -1
- package/dist/indexer/reorg.d.ts +2 -2
- package/dist/indexer/reorg.d.ts.map +1 -1
- package/dist/rpc/get-logs.js +1 -1
- package/dist/rpc/get-logs.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +11 -9
- package/src/config/env.ts +2 -2
- package/src/db/actions/blocks.ts +51 -51
- package/src/db/client.ts +5 -1
- package/src/db/column-types.ts +17 -6
- package/src/db/schema/transactions.ts +3 -1
- package/src/hooks/registry.ts +3 -3
- package/src/indexer/backfill.ts +28 -10
- package/src/indexer/process-block.ts +10 -39
- package/src/indexer/queue-block.ts +24 -1
- package/src/indexer/reorg.ts +2 -2
- package/src/rpc/get-logs.ts +1 -1
- package/src/types.ts +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-block.js","sourceRoot":"","sources":["../../src/indexer/process-block.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAA;AAGnE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"process-block.js","sourceRoot":"","sources":["../../src/indexer/process-block.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAA;AAGnE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAItD,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAMnD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAWlC;IACC,MAAM,EACJ,MAAM,EACN,MAAM,EACN,EAAE,EACF,MAAM,EACN,QAAQ,EACR,KAAK,EACL,eAAe,EACf,IAAI,EACJ,IAAI,EACJ,SAAS,GACV,GAAG,IAAI,CAAA;IAER,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,MAAM,QAAQ,GAAG,MAAM,sBAAsB,CAAC;YAC5C,MAAM;YACN,EAAE;YACF,MAAM;YACN,KAAK;SACN,CAAC,CAAA;QACF,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;YACrB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAA;QACtC,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,EAAE,EAA6C,EAAE,EAAE;QACpE,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,MAAM,yBAAyB,CAAC;gBAC9B,EAAE,EAAE,EAAE;gBACN,MAAM,EAAE,CAAC,KAAK,CAAC;gBACf,YAAY,EAAE,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC;gBAClD,MAAM;aACP,CAAC,CAAA;QACJ,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,YAAY,GAAG,SAAS,CAAC,qBAAqB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YAEjE,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,MAAM,CAAC,KAAK,CACV,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,EACxB,gDAAgD,CACjD,CAAA;gBACD,SAAQ;YACV,CAAC;YACD,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,CAAA;YAE/B,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBACzC,SAAQ;YACV,CAAC;YACD,MAAM,WAAW,GAAG,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;YAE5D,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,MAAM,CAAC,KAAK,CACV,EAAE,eAAe,EAAE,GAAG,CAAC,eAAe,EAAE,EAExC,iDAAiD,CAClD,CAAA;gBACD,SAAQ;YACV,CAAC;YACD,MAAM,QAAQ,CAAC,QAAQ,CAAC;gBACtB,GAAG,EAAE,GAAG,YAAY,IAAI,SAAS,EAAW;gBAC5C,IAAI,EAAE,GAAG,CAAC,IAAa;gBACvB,GAAG,EAAE,GAAY;gBACjB,KAAK;gBACL,WAAW;gBACX,OAAO,EAAE;oBACP,EAAE,EAAE,EAAE;oBACN,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;oBAC/B,MAAM;iBACP;aACF,CAAC,CAAA;QACJ,CAAC;IACH,CAAC,CAAA;IAED,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QACxB,MAAM,KAAK,CAAC,EAAE,CAAC,CAAA;IACjB,CAAC;SAAM,CAAC;QACN,MAAM,eAAe,CAAC,EAAE,EAAE,KAAK,CAAC,CAAA;IAClC,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAA;AAChC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue-block.d.ts","sourceRoot":"","sources":["../../src/indexer/queue-block.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAClC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AAExC,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"queue-block.d.ts","sourceRoot":"","sources":["../../src/indexer/queue-block.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAClC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AAExC,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAMxD,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,MAAM,EAAE,cAAc,CAAA;IACtB,EAAE,EAAE,QAAQ,CAAC,OAAO,MAAM,EAAE,OAAO,SAAS,CAAC,CAAA;IAC7C,MAAM,EAAE,YAAY,CAAA;IACpB,QAAQ,EAAE,YAAY,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA0EpE"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { filterContracts } from "../config/config.js";
|
|
2
|
+
import { safeGetBlock } from "../rpc/get-block.js";
|
|
2
3
|
import { startClock } from "../utils/timer.js";
|
|
3
4
|
import { processBlock } from "./process-block.js";
|
|
4
5
|
export async function queueBlock(args) {
|
|
@@ -6,15 +7,32 @@ export async function queueBlock(args) {
|
|
|
6
7
|
const endClock = startClock();
|
|
7
8
|
try {
|
|
8
9
|
const contracts = filterContracts(config, blockNumber, blockNumber);
|
|
10
|
+
const [blockResult, logsResult] = await Promise.all([
|
|
11
|
+
safeGetBlock({ client, blockNumber, db }),
|
|
12
|
+
client.getLogs({
|
|
13
|
+
address: contracts.addresses,
|
|
14
|
+
events: contracts.eventAbis,
|
|
15
|
+
fromBlock: blockNumber,
|
|
16
|
+
toBlock: blockNumber,
|
|
17
|
+
}),
|
|
18
|
+
]);
|
|
19
|
+
const { transactions, ..._block } = blockResult;
|
|
20
|
+
const block = _block;
|
|
21
|
+
const transactionsMap = new Map();
|
|
22
|
+
for (const tx of transactions) {
|
|
23
|
+
transactionsMap.set(tx.hash, tx);
|
|
24
|
+
}
|
|
9
25
|
const result = await processBlock({
|
|
10
26
|
logger,
|
|
11
27
|
config,
|
|
12
28
|
db,
|
|
13
29
|
client,
|
|
14
30
|
registry,
|
|
15
|
-
blockNumber,
|
|
16
31
|
type: 'live',
|
|
17
32
|
contracts,
|
|
33
|
+
block,
|
|
34
|
+
transactionsMap,
|
|
35
|
+
logs: logsResult,
|
|
18
36
|
});
|
|
19
37
|
if (result.status === 'reorg') {
|
|
20
38
|
logger.warn({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue-block.js","sourceRoot":"","sources":["../../src/indexer/queue-block.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAuB,MAAM,qBAAqB,CAAA;AAI1E,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAajD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAoB;IACnD,MAAM,EACJ,MAAM,EACN,EAAE,EACF,MAAM,EACN,QAAQ,EACR,WAAW,EACX,MAAM,EACN,QAAQ,EACR,SAAS,GACV,GAAG,IAAI,CAAA;IAER,MAAM,QAAQ,GAAG,UAAU,EAAE,CAAA;IAC7B,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,WAAW,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"queue-block.js","sourceRoot":"","sources":["../../src/indexer/queue-block.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAuB,MAAM,qBAAqB,CAAA;AAI1E,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAajD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAoB;IACnD,MAAM,EACJ,MAAM,EACN,EAAE,EACF,MAAM,EACN,QAAQ,EACR,WAAW,EACX,MAAM,EACN,QAAQ,EACR,SAAS,GACV,GAAG,IAAI,CAAA;IAER,MAAM,QAAQ,GAAG,UAAU,EAAE,CAAA;IAC7B,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,WAAW,CAAC,CAAA;QAEnE,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAClD,YAAY,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;YACzC,MAAM,CAAC,OAAO,CAAC;gBACb,OAAO,EAAE,SAAS,CAAC,SAAS;gBAC5B,MAAM,EAAE,SAAS,CAAC,SAAS;gBAC3B,SAAS,EAAE,WAAW;gBACtB,OAAO,EAAE,WAAW;aACrB,CAAC;SACH,CAAC,CAAA;QAEF,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,EAAE,GAAG,WAAW,CAAA;QAC/C,MAAM,KAAK,GAAiB,MAAM,CAAA;QAClC,MAAM,eAAe,GAAG,IAAI,GAAG,EAAqC,CAAA;QAEpE,KAAK,MAAM,EAAE,IAAI,YAAY,EAAE,CAAC;YAC9B,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;QAClC,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;YAChC,MAAM;YACN,MAAM;YACN,EAAE;YACF,MAAM;YACN,QAAQ;YACR,IAAI,EAAE,MAAM;YACZ,SAAS;YACT,KAAK;YACL,eAAe;YACf,IAAI,EAAE,UAAU;SACjB,CAAC,CAAA;QAEF,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;YAC9B,MAAM,CAAC,IAAI,CACT;gBACE,WAAW,EAAE,WAAW,CAAC,QAAQ,EAAE;gBACnC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE;aACrC,EACD,kDAAkD,CACnD,CAAA;YACD,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;YACzB,OAAM;QACR,CAAC;QAED,MAAM,CAAC,IAAI,CACT;YACE,QAAQ,EAAE,QAAQ,EAAE;YACpB,WAAW,EAAE,WAAW,CAAC,QAAQ,EAAE;YACnC,SAAS;SACV,EACD,sBAAsB,CACvB,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CACV,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,CAAC,QAAQ,EAAE,EAAE,EAC9C,oCAAoC,CACrC,CAAA;QACD,QAAQ,CAAC,WAAW,GAAG,EAAE,CAAC,CAAA;IAC5B,CAAC;AACH,CAAC"}
|
package/dist/indexer/reorg.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PublicClient } from 'viem';
|
|
2
2
|
import type { Database } from '../db/client.ts';
|
|
3
|
-
import type {
|
|
3
|
+
import type { EncodedBlock } from '../types';
|
|
4
4
|
import type { Logger } from '../utils/logger.ts';
|
|
5
5
|
/**
|
|
6
6
|
* Verifies parent-hash continuity and rolls back divergent canonical rows if needed.
|
|
@@ -10,7 +10,7 @@ export declare function ensureParentContinuity(args: {
|
|
|
10
10
|
logger: Logger;
|
|
11
11
|
db: Database;
|
|
12
12
|
client: PublicClient;
|
|
13
|
-
block:
|
|
13
|
+
block: EncodedBlock;
|
|
14
14
|
}): Promise<bigint | null>;
|
|
15
15
|
/**
|
|
16
16
|
* Validates recent indexed blocks against chain state on startup.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reorg.d.ts","sourceRoot":"","sources":["../../src/indexer/reorg.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AAGxC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAE/C,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"reorg.d.ts","sourceRoot":"","sources":["../../src/indexer/reorg.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AAGxC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAE/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAE5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAGhD;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IACjD,MAAM,EAAE,MAAM,CAAA;IACd,EAAE,EAAE,QAAQ,CAAA;IACZ,MAAM,EAAE,YAAY,CAAA;IACpB,KAAK,EAAE,YAAY,CAAA;CACpB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA2DzB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,MAAM,EAAE,MAAM,CAAA;IACd,EAAE,EAAE,QAAQ,CAAA;IACZ,MAAM,EAAE,YAAY,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;CACd,GAAG,OAAO,CAAC,IAAI,CAAC,CAgChB"}
|
package/dist/rpc/get-logs.js
CHANGED
package/dist/rpc/get-logs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-logs.js","sourceRoot":"","sources":["../../src/rpc/get-logs.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAOpC;IACC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAEtE,MAAM,QAAQ,GAAG,UAAU,EAAE,CAAA;IAE7B,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkD,CAAA;IAC7E,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;QAChC,OAAO,EAAE,SAAS;QAClB,MAAM,EAAE,MAAM;QACd,SAAS,EAAE,SAAS;QACpB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAA;IAEF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAA;QACtD,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACjB,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;IAC3C,CAAC;IACD,MAAM,CAAC,KAAK,CACV;QACE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"get-logs.js","sourceRoot":"","sources":["../../src/rpc/get-logs.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAOpC;IACC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAEtE,MAAM,QAAQ,GAAG,UAAU,EAAE,CAAA;IAE7B,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkD,CAAA;IAC7E,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;QAChC,OAAO,EAAE,SAAS;QAClB,MAAM,EAAE,MAAM;QACd,SAAS,EAAE,SAAS;QACpB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAA;IAEF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAA;QACtD,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACjB,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;IAC3C,CAAC;IACD,MAAM,CAAC,KAAK,CACV;QACE,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,QAAQ,EAAE,QAAQ,EAAE;KACrB,EACD,UAAU,CACX,CAAA;IACD,OAAO,WAAW,CAAA;AACpB,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -19,4 +19,6 @@ export type EncodedTransaction = Schema['transactions']['$inferInsert'];
|
|
|
19
19
|
export type EncodedBlockWithTransactions = Simplify<EncodedBlock & {
|
|
20
20
|
transactions: EncodedTransaction[];
|
|
21
21
|
}>;
|
|
22
|
+
export type TransactionsMap = Map<`0x${string}`, EncodedTransaction>;
|
|
23
|
+
export type BlocksMap = Map<bigint, EncodedBlock>;
|
|
22
24
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,MAAM,CAAA;AAE9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/C;;GAEG;AACH,MAAM,MAAM,WAAW,CAAC,UAAU,GAAG,OAAO,EAAE,SAAS,GAAG,KAAK,IAC3D;IACE,KAAK,EAAE,SAAS,CAAA;IAChB,MAAM,CAAC,EAAE,SAAS,CAAA;CACnB,GACD;IACE,MAAM,EAAE,UAAU,CAAA;IAClB,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB,CAAA;AAEL,MAAM,MAAM,aAAa,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;AAEhD,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAA;AACjE,MAAM,MAAM,UAAU,GAAG,KAAK,CAC5B,MAAM,EACN,IAAI,EACJ,QAAQ,GAAG,MAAM,GAAG,WAAW,EAC/B,gBAAgB,CACjB,CAAA;AACD,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,CAAA;AAC3D,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC,cAAc,CAAC,CAAA;AACvE,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CACjD,YAAY,GAAG;IACb,YAAY,EAAE,kBAAkB,EAAE,CAAA;CACnC,CACF,CAAA"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,MAAM,CAAA;AAE9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/C;;GAEG;AACH,MAAM,MAAM,WAAW,CAAC,UAAU,GAAG,OAAO,EAAE,SAAS,GAAG,KAAK,IAC3D;IACE,KAAK,EAAE,SAAS,CAAA;IAChB,MAAM,CAAC,EAAE,SAAS,CAAA;CACnB,GACD;IACE,MAAM,EAAE,UAAU,CAAA;IAClB,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB,CAAA;AAEL,MAAM,MAAM,aAAa,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;AAEhD,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAA;AACjE,MAAM,MAAM,UAAU,GAAG,KAAK,CAC5B,MAAM,EACN,IAAI,EACJ,QAAQ,GAAG,MAAM,GAAG,WAAW,EAC/B,gBAAgB,CACjB,CAAA;AACD,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,CAAA;AAC3D,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC,cAAc,CAAC,CAAA;AACvE,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CACjD,YAAY,GAAG;IACb,YAAY,EAAE,kBAAkB,EAAE,CAAA;CACnC,CACF,CAAA;AACD,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC,KAAK,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAAA;AACpE,MAAM,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hugomrdias/foxer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "Foxer is a all-in-one application server for Filecoin.",
|
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
|
6
6
|
"author": "Hugo Dias <hugomrdias@gmail.com>",
|
|
@@ -51,22 +51,24 @@
|
|
|
51
51
|
"prepublishOnly": "bun run build"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@bluwy/giget-core": "^0.1.
|
|
54
|
+
"@bluwy/giget-core": "^0.1.7",
|
|
55
55
|
"@clack/prompts": "^1.1.0",
|
|
56
|
-
"@electric-sql/pglite": "^0.
|
|
56
|
+
"@electric-sql/pglite": "^0.4.1",
|
|
57
57
|
"@hono/node-server": "^1.19.11",
|
|
58
58
|
"@libpg-query/parser": "^17.6.3",
|
|
59
59
|
"@pgsql/traverse": "^17.2.4",
|
|
60
60
|
"abitype": "^1.2.3",
|
|
61
61
|
"cleye": "^2.3.0",
|
|
62
62
|
"dotenv": "^17.2.3",
|
|
63
|
-
"drizzle-orm": "1.0.0-beta.
|
|
63
|
+
"drizzle-orm": "1.0.0-beta.17-67b1795",
|
|
64
64
|
"exit-hook": "^5.1.0",
|
|
65
|
-
"hono": "^4.12.
|
|
65
|
+
"hono": "^4.12.9",
|
|
66
66
|
"hono-pino": "^0.10.3",
|
|
67
67
|
"http-shutdown": "^1.2.2",
|
|
68
|
+
"iso-base": "^4.3.1",
|
|
68
69
|
"p-queue": "^9.1.0",
|
|
69
70
|
"pg": "^8.20.0",
|
|
71
|
+
"pgserve": "^1.1.6",
|
|
70
72
|
"picocolors": "^1.1.1",
|
|
71
73
|
"pino": "^10.3.1",
|
|
72
74
|
"postgres": "^3.4.8",
|
|
@@ -77,12 +79,12 @@
|
|
|
77
79
|
"devDependencies": {
|
|
78
80
|
"@pgsql/types": "^17.6.2",
|
|
79
81
|
"@types/node": "^25.5.0",
|
|
80
|
-
"@types/pg": "^8.
|
|
81
|
-
"type-fest": "^5.
|
|
82
|
+
"@types/pg": "^8.20.0",
|
|
83
|
+
"type-fest": "^5.5.0",
|
|
82
84
|
"typescript": "^5.9.2"
|
|
83
85
|
},
|
|
84
86
|
"peerDependencies": {
|
|
85
|
-
"hono": ">=4.
|
|
86
|
-
"viem": "2.
|
|
87
|
+
"hono": ">=4.12.9",
|
|
88
|
+
"viem": "2.47.6"
|
|
87
89
|
}
|
|
88
90
|
}
|
package/src/config/env.ts
CHANGED
|
@@ -17,7 +17,7 @@ const envSchema = z.object({
|
|
|
17
17
|
LOG_MODE: z.enum(['pretty', 'json']).default('pretty'),
|
|
18
18
|
})
|
|
19
19
|
|
|
20
|
-
export function createEnv(
|
|
20
|
+
export function createEnv(_logger: Logger) {
|
|
21
21
|
const parsed = envSchema.safeParse(process.env)
|
|
22
22
|
|
|
23
23
|
if (!parsed.success) {
|
|
@@ -25,6 +25,6 @@ export function createEnv(logger: Logger) {
|
|
|
25
25
|
`Failed to parse environment variables: \n ${z.prettifyError(parsed.error)}`
|
|
26
26
|
)
|
|
27
27
|
}
|
|
28
|
-
logger.debug({ env: parsed.data }, 'env parsed')
|
|
28
|
+
// logger.debug({ env: parsed.data }, 'env parsed')
|
|
29
29
|
return parsed.data
|
|
30
30
|
}
|
package/src/db/actions/blocks.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** biome-ignore-all lint/style/noNonNullAssertion: its ok */
|
|
2
2
|
|
|
3
|
-
import { gte } from 'drizzle-orm'
|
|
3
|
+
import { and, gte, inArray } from 'drizzle-orm'
|
|
4
4
|
import {
|
|
5
5
|
getTableConfig,
|
|
6
6
|
type PgAsyncTransaction,
|
|
@@ -8,14 +8,15 @@ import {
|
|
|
8
8
|
type PgQueryResultHKT,
|
|
9
9
|
type PgTable,
|
|
10
10
|
} from 'drizzle-orm/pg-core'
|
|
11
|
-
import type { PublicClient } from 'viem'
|
|
11
|
+
import type { Hash, PublicClient } from 'viem'
|
|
12
12
|
|
|
13
|
-
import type { FilteredContracts } from '../../config/config.ts'
|
|
14
13
|
import { MAX_QUERY_PARAMS } from '../../contants.ts'
|
|
15
14
|
import { safeGetBlock } from '../../rpc/get-block.ts'
|
|
16
15
|
import type {
|
|
17
|
-
|
|
16
|
+
BlocksMap,
|
|
17
|
+
EncodedBlock,
|
|
18
18
|
EncodedTransaction,
|
|
19
|
+
TransactionsMap,
|
|
19
20
|
} from '../../types.ts'
|
|
20
21
|
import type { Logger } from '../../utils/logger.ts'
|
|
21
22
|
import { startClock } from '../../utils/timer.ts'
|
|
@@ -73,19 +74,20 @@ function getTablesWithBlockNumberColumn(fullSchema: Record<string, unknown>) {
|
|
|
73
74
|
*/
|
|
74
75
|
export async function cacheBlockAndTransactions(args: {
|
|
75
76
|
db: Database<typeof schema, typeof relations>
|
|
76
|
-
|
|
77
|
+
blocks: EncodedBlock[]
|
|
78
|
+
transactions: EncodedTransaction[]
|
|
77
79
|
logger: Logger
|
|
78
80
|
}): Promise<void> {
|
|
79
|
-
const { db,
|
|
81
|
+
const { db, blocks, transactions } = args
|
|
80
82
|
|
|
81
83
|
await db.transaction(async (tx) => {
|
|
82
84
|
await insertBlocksInChunks({
|
|
83
85
|
db: tx,
|
|
84
|
-
blocks
|
|
86
|
+
blocks,
|
|
85
87
|
})
|
|
86
88
|
await insertTransactionsInChunks({
|
|
87
89
|
db: tx,
|
|
88
|
-
transactions
|
|
90
|
+
transactions,
|
|
89
91
|
})
|
|
90
92
|
})
|
|
91
93
|
}
|
|
@@ -105,8 +107,8 @@ export async function getBlocksInRange(
|
|
|
105
107
|
db: Database<typeof schema, typeof relations>,
|
|
106
108
|
blockNumbers: bigint[],
|
|
107
109
|
client: PublicClient,
|
|
108
|
-
|
|
109
|
-
): Promise<
|
|
110
|
+
logsTxs: Hash[]
|
|
111
|
+
): Promise<{ blocks: BlocksMap; transactions: TransactionsMap }> {
|
|
110
112
|
const endClock = startClock()
|
|
111
113
|
const firstBlockNumber = blockNumbers[0]!
|
|
112
114
|
const lastBlockNumber = blockNumbers[blockNumbers.length - 1]!
|
|
@@ -117,74 +119,72 @@ export async function getBlocksInRange(
|
|
|
117
119
|
// contractAddresses: contracts.addresses,
|
|
118
120
|
// })
|
|
119
121
|
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
{
|
|
128
|
-
to: {
|
|
129
|
-
in: contracts.addresses,
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
],
|
|
133
|
-
},
|
|
122
|
+
const [blocks, txs] = await Promise.all([
|
|
123
|
+
db.query.blocks.findMany({
|
|
124
|
+
where: {
|
|
125
|
+
AND: [
|
|
126
|
+
{ number: { gte: firstBlockNumber } },
|
|
127
|
+
{ number: { lte: lastBlockNumber } },
|
|
128
|
+
],
|
|
134
129
|
},
|
|
135
|
-
},
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
})
|
|
130
|
+
}),
|
|
131
|
+
db
|
|
132
|
+
.select()
|
|
133
|
+
.from(schema.transactions)
|
|
134
|
+
.where(and(inArray(schema.transactions.hash, logsTxs))),
|
|
135
|
+
])
|
|
136
|
+
|
|
137
|
+
const transactionByHash = new Map<`0x${string}`, EncodedTransaction>()
|
|
138
|
+
for (const tx of txs) {
|
|
139
|
+
transactionByHash.set(tx.hash, tx)
|
|
140
|
+
}
|
|
143
141
|
|
|
144
|
-
const blocksByNumber = new Map<bigint,
|
|
142
|
+
const blocksByNumber = new Map<bigint, EncodedBlock>()
|
|
145
143
|
const missing = new Set(blockNumbers)
|
|
146
144
|
|
|
147
|
-
for (const block of
|
|
145
|
+
for (const block of blocks) {
|
|
148
146
|
blocksByNumber.set(block.number, block)
|
|
149
147
|
missing.delete(block.number)
|
|
150
148
|
}
|
|
151
149
|
|
|
152
150
|
const missingBlockNumbers = [...missing]
|
|
153
|
-
const newBlocks:
|
|
151
|
+
const newBlocks: EncodedBlock[] = []
|
|
154
152
|
const newTransactions: EncodedTransaction[] = []
|
|
155
153
|
|
|
156
154
|
await Promise.all(
|
|
157
155
|
missingBlockNumbers.map(async (blockNumber) => {
|
|
158
156
|
const block = await safeGetBlock({ client, blockNumber, db })
|
|
159
|
-
const transactions = block.transactions
|
|
160
157
|
blocksByNumber.set(blockNumber, block)
|
|
161
|
-
|
|
158
|
+
const { transactions, ..._block } = block
|
|
159
|
+
newBlocks.push(_block)
|
|
160
|
+
|
|
162
161
|
if (transactions.length > 0) {
|
|
163
162
|
newTransactions.push(...transactions)
|
|
164
163
|
}
|
|
164
|
+
for (const tx of transactions) {
|
|
165
|
+
transactionByHash.set(tx.hash, tx)
|
|
166
|
+
}
|
|
165
167
|
})
|
|
166
168
|
)
|
|
167
169
|
|
|
168
|
-
await
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
await insertTransactionsInChunks({
|
|
174
|
-
db: tx,
|
|
175
|
-
transactions: newTransactions,
|
|
176
|
-
})
|
|
170
|
+
await cacheBlockAndTransactions({
|
|
171
|
+
db,
|
|
172
|
+
blocks: newBlocks,
|
|
173
|
+
transactions: newTransactions,
|
|
174
|
+
logger,
|
|
177
175
|
})
|
|
178
176
|
|
|
179
177
|
logger.trace(
|
|
180
178
|
{
|
|
181
|
-
blocks:
|
|
182
|
-
|
|
179
|
+
blocks: blocks.length,
|
|
180
|
+
txs: txs.length,
|
|
181
|
+
newBlocks: newBlocks.length,
|
|
182
|
+
newTxs: newTransactions.length,
|
|
183
183
|
duration: endClock(),
|
|
184
184
|
},
|
|
185
|
-
'get blocks'
|
|
185
|
+
'get blocks and txs'
|
|
186
186
|
)
|
|
187
|
-
return blocksByNumber
|
|
187
|
+
return { blocks: blocksByNumber, transactions: transactionByHash }
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
/**
|
|
@@ -192,7 +192,7 @@ export async function getBlocksInRange(
|
|
|
192
192
|
*/
|
|
193
193
|
export async function insertBlocksInChunks(args: {
|
|
194
194
|
db: PgAsyncTransaction<PgQueryResultHKT, typeof schema>
|
|
195
|
-
blocks:
|
|
195
|
+
blocks: EncodedBlock[]
|
|
196
196
|
}): Promise<void> {
|
|
197
197
|
const { db, blocks } = args
|
|
198
198
|
if (blocks.length === 0) return
|
package/src/db/client.ts
CHANGED
|
@@ -84,8 +84,12 @@ export function createDatabase<
|
|
|
84
84
|
// Postgres
|
|
85
85
|
if (driver === 'postgres' && url) {
|
|
86
86
|
const pool = new Pool({
|
|
87
|
-
|
|
87
|
+
application_name: 'foxer',
|
|
88
|
+
connectionTimeoutMillis: 5_000,
|
|
89
|
+
idleTimeoutMillis: 30_000,
|
|
90
|
+
max: 10,
|
|
88
91
|
connectionString: url,
|
|
92
|
+
...options,
|
|
89
93
|
})
|
|
90
94
|
const db = drizzleNodePostgres({
|
|
91
95
|
client: pool,
|
package/src/db/column-types.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { customType } from 'drizzle-orm/pg-core'
|
|
2
|
+
import { hex as hexCodec } from 'iso-base/rfc4648'
|
|
2
3
|
import { type Address, type Hash, type Hex, stringify } from 'viem'
|
|
3
4
|
|
|
4
5
|
export const numeric78 = customType<{ data: bigint; driverData: string }>({
|
|
@@ -90,16 +91,26 @@ export const jsonb = customType<{ data: unknown; driverData: string }>({
|
|
|
90
91
|
},
|
|
91
92
|
})
|
|
92
93
|
|
|
93
|
-
export const bytea = customType<{ data: Hex; driverData:
|
|
94
|
+
export const bytea = customType<{ data: Hex; driverData: Uint8Array }>({
|
|
94
95
|
dataType() {
|
|
95
96
|
return 'bytea'
|
|
96
97
|
},
|
|
97
|
-
toDriver(value: string):
|
|
98
|
+
toDriver(value: string): Uint8Array {
|
|
98
99
|
return Buffer.from(value.slice(2), 'hex')
|
|
99
100
|
},
|
|
100
|
-
fromDriver(value:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
fromDriver(value: unknown): Hex {
|
|
102
|
+
if (typeof value === 'string') {
|
|
103
|
+
return `0x${value.slice(2)}` as Hex
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (value instanceof Buffer) {
|
|
107
|
+
return `0x${value.toString('hex')}` as Hex
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (value instanceof Uint8Array) {
|
|
111
|
+
return `0x${hexCodec.encode(value)}` as Hex
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
throw new Error('Invalid value')
|
|
104
115
|
},
|
|
105
116
|
})
|
|
@@ -35,6 +35,8 @@ export const transactions = pgTable(
|
|
|
35
35
|
},
|
|
36
36
|
(table) => [
|
|
37
37
|
index('transactions_block_number_index').on(table.blockNumber),
|
|
38
|
-
index('
|
|
38
|
+
index('transactions_to_block_number_index')
|
|
39
|
+
.on(table.to, table.blockNumber)
|
|
40
|
+
.concurrently(),
|
|
39
41
|
]
|
|
40
42
|
)
|
package/src/hooks/registry.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { GetEventArgs, Log } from 'viem'
|
|
|
3
3
|
|
|
4
4
|
import type { InternalConfig } from '../config/config'
|
|
5
5
|
import type { Database } from '../db/client'
|
|
6
|
-
import type {
|
|
6
|
+
import type { EncodedBlock, EncodedTransaction } from '../types'
|
|
7
7
|
import type { Logger } from '../utils/logger'
|
|
8
8
|
import type {
|
|
9
9
|
ContractAbiByEventKey,
|
|
@@ -34,7 +34,7 @@ export type DecodedEvent<
|
|
|
34
34
|
{ EnableUnion: false; IndexedOnly: false; Required: true }
|
|
35
35
|
>
|
|
36
36
|
log: Log<bigint, number, false, ContractAbiEventByEventKey<C, Event>>
|
|
37
|
-
block:
|
|
37
|
+
block: EncodedBlock
|
|
38
38
|
transaction: EncodedTransaction
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -81,7 +81,7 @@ export class HookRegistry<
|
|
|
81
81
|
{ EnableUnion: false; IndexedOnly: false; Required: true }
|
|
82
82
|
>
|
|
83
83
|
log: Log<bigint, number, false, ContractAbiEventByEventKey<C, K>>
|
|
84
|
-
block:
|
|
84
|
+
block: EncodedBlock
|
|
85
85
|
transaction: EncodedTransaction
|
|
86
86
|
context: HookContext<TSchema, TRelations>
|
|
87
87
|
}): Promise<void> {
|
package/src/indexer/backfill.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Hash } from 'viem'
|
|
1
2
|
import { filterContracts, type InternalConfig } from '../config/config.ts'
|
|
2
3
|
import { getBlocksInRange } from '../db/actions/blocks.ts'
|
|
3
4
|
import type { Database } from '../db/client.ts'
|
|
@@ -61,17 +62,30 @@ export async function runBackfill(args: {
|
|
|
61
62
|
blockNumber += 1n
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
const logsByBlock = await getLogsInRange({
|
|
66
|
+
logger,
|
|
67
|
+
client,
|
|
68
|
+
addresses: windowContracts.addresses,
|
|
69
|
+
events: windowContracts.eventAbis,
|
|
70
|
+
fromBlock: cursor,
|
|
71
|
+
toBlock,
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
const logsTxsSet = new Set<Hash>()
|
|
75
|
+
for (const logs of logsByBlock.values()) {
|
|
76
|
+
for (const log of logs) {
|
|
77
|
+
logsTxsSet.add(log.transactionHash)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const { blocks: blocksByNumber, transactions: transactionsMap } =
|
|
82
|
+
await getBlocksInRange(
|
|
67
83
|
logger,
|
|
84
|
+
db,
|
|
85
|
+
batchBlockNumbers,
|
|
68
86
|
client,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
fromBlock: cursor,
|
|
72
|
-
toBlock,
|
|
73
|
-
}),
|
|
74
|
-
])
|
|
87
|
+
Array.from(logsTxsSet)
|
|
88
|
+
)
|
|
75
89
|
|
|
76
90
|
let blockIndex = 0
|
|
77
91
|
|
|
@@ -81,15 +95,19 @@ export async function runBackfill(args: {
|
|
|
81
95
|
const blockNumber = batchBlockNumbers[blockIndex]
|
|
82
96
|
const prefetchedBlock = blocksByNumber.get(blockNumber)
|
|
83
97
|
|
|
98
|
+
if (!prefetchedBlock) {
|
|
99
|
+
throw new Error(`Block ${blockNumber} not found`)
|
|
100
|
+
}
|
|
101
|
+
|
|
84
102
|
await processBlock({
|
|
85
103
|
logger,
|
|
86
104
|
config,
|
|
87
105
|
db: tx,
|
|
88
106
|
client,
|
|
89
107
|
registry,
|
|
90
|
-
blockNumber,
|
|
91
108
|
logs: logsByBlock.get(blockNumber) ?? [],
|
|
92
109
|
block: prefetchedBlock,
|
|
110
|
+
transactionsMap,
|
|
93
111
|
type: 'backfill',
|
|
94
112
|
contracts: windowContracts,
|
|
95
113
|
})
|
|
@@ -6,8 +6,7 @@ import type { Database } from '../db/client.ts'
|
|
|
6
6
|
import type { relations, schema } from '../db/schema/index.ts'
|
|
7
7
|
import { withTransaction } from '../db/transaction.ts'
|
|
8
8
|
import type { HookRegistry } from '../hooks/registry.ts'
|
|
9
|
-
import {
|
|
10
|
-
import type { EncodedBlockWithTransactions, EncodedTransaction } from '../types'
|
|
9
|
+
import type { EncodedBlock, TransactionsMap } from '../types'
|
|
11
10
|
import type { Logger } from '../utils/logger.ts'
|
|
12
11
|
import { ensureParentContinuity } from './reorg.ts'
|
|
13
12
|
|
|
@@ -24,9 +23,9 @@ export async function processBlock(args: {
|
|
|
24
23
|
db: Database<typeof schema, typeof relations>
|
|
25
24
|
client: PublicClient
|
|
26
25
|
registry: HookRegistry<NonNullable<unknown>>
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
logs: Log<bigint, number, false, AbiEvent>[]
|
|
27
|
+
block: EncodedBlock
|
|
28
|
+
transactionsMap: TransactionsMap
|
|
30
29
|
type: 'backfill' | 'live'
|
|
31
30
|
contracts: FilteredContracts
|
|
32
31
|
}): Promise<ProcessBlockResult> {
|
|
@@ -36,41 +35,12 @@ export async function processBlock(args: {
|
|
|
36
35
|
db,
|
|
37
36
|
client,
|
|
38
37
|
registry,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
logs
|
|
38
|
+
block,
|
|
39
|
+
transactionsMap,
|
|
40
|
+
logs,
|
|
42
41
|
type,
|
|
43
42
|
contracts,
|
|
44
43
|
} = args
|
|
45
|
-
const transactionByHash = new Map<`0x${string}`, EncodedTransaction>()
|
|
46
|
-
|
|
47
|
-
let block: EncodedBlockWithTransactions | undefined
|
|
48
|
-
let logs: Log<bigint, number, false, AbiEvent>[] | undefined
|
|
49
|
-
|
|
50
|
-
if (prefetchedBlock) {
|
|
51
|
-
block = prefetchedBlock
|
|
52
|
-
}
|
|
53
|
-
if (prefetchedLogs) {
|
|
54
|
-
logs = prefetchedLogs
|
|
55
|
-
}
|
|
56
|
-
if (!block || !logs) {
|
|
57
|
-
const [blockResult, logsResult] = await Promise.all([
|
|
58
|
-
safeGetBlock({ client, blockNumber, db }),
|
|
59
|
-
client.getLogs({
|
|
60
|
-
address: contracts.addresses,
|
|
61
|
-
events: contracts.eventAbis,
|
|
62
|
-
fromBlock: blockNumber,
|
|
63
|
-
toBlock: blockNumber,
|
|
64
|
-
}),
|
|
65
|
-
])
|
|
66
|
-
|
|
67
|
-
block = blockResult
|
|
68
|
-
logs = logsResult
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
for (const tx of block.transactions) {
|
|
72
|
-
transactionByHash.set(tx.hash, tx)
|
|
73
|
-
}
|
|
74
44
|
|
|
75
45
|
if (type === 'live') {
|
|
76
46
|
const rewindTo = await ensureParentContinuity({
|
|
@@ -88,7 +58,8 @@ export async function processBlock(args: {
|
|
|
88
58
|
if (type === 'live') {
|
|
89
59
|
await cacheBlockAndTransactions({
|
|
90
60
|
db: tx,
|
|
91
|
-
block,
|
|
61
|
+
blocks: [block],
|
|
62
|
+
transactions: Array.from(transactionsMap.values()),
|
|
92
63
|
logger,
|
|
93
64
|
})
|
|
94
65
|
}
|
|
@@ -108,7 +79,7 @@ export async function processBlock(args: {
|
|
|
108
79
|
if (!contracts.eventNames.has(eventName)) {
|
|
109
80
|
continue
|
|
110
81
|
}
|
|
111
|
-
const transaction =
|
|
82
|
+
const transaction = transactionsMap.get(log.transactionHash)
|
|
112
83
|
|
|
113
84
|
if (!transaction) {
|
|
114
85
|
logger.debug(
|