envio 3.7.0 → 3.9.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/README.md +2 -2
- package/index.d.ts +399 -156
- package/package.json +6 -6
- package/src/AddressRows.res +121 -0
- package/src/AddressRows.res.mjs +143 -0
- package/src/Batch.res +2 -0
- package/src/Batch.res.mjs +2 -1
- package/src/ChainState.res +82 -68
- package/src/ChainState.res.mjs +81 -65
- package/src/ChainState.resi +14 -9
- package/src/Config.res +41 -91
- package/src/Config.res.mjs +34 -68
- package/src/ContractMapping.res +66 -0
- package/src/ContractMapping.res.mjs +73 -0
- package/src/Core.res +20 -0
- package/src/Core.res.mjs +4 -0
- package/src/Envio.res +54 -76
- package/src/EventConfigBuilder.res +157 -30
- package/src/EventConfigBuilder.res.mjs +118 -24
- package/src/FetchState.res +59 -67
- package/src/FetchState.res.mjs +34 -44
- package/src/HandlerRegister.res +20 -11
- package/src/HandlerRegister.res.mjs +22 -5
- package/src/Hasura.res +30 -22
- package/src/Hasura.res.mjs +11 -5
- package/src/InMemoryStore.res +18 -36
- package/src/InMemoryStore.res.mjs +12 -26
- package/src/IndexerState.res +21 -1
- package/src/IndexerState.res.mjs +9 -3
- package/src/IndexerState.resi +1 -0
- package/src/Internal.res +33 -13
- package/src/Internal.res.mjs +12 -16
- package/src/Main.res +27 -20
- package/src/Main.res.mjs +19 -14
- package/src/MemoryStorage.res +78 -73
- package/src/MemoryStorage.res.mjs +66 -81
- package/src/Metrics.res +15 -1
- package/src/Metrics.res.mjs +5 -1
- package/src/Persistence.res +34 -18
- package/src/Persistence.res.mjs +8 -5
- package/src/PgStorage.res +189 -66
- package/src/PgStorage.res.mjs +93 -59
- package/src/Rollback.res +14 -10
- package/src/Rollback.res.mjs +4 -2
- package/src/SimulateItems.res +254 -9
- package/src/SimulateItems.res.mjs +214 -47
- package/src/TestIndexer.res +119 -121
- package/src/TestIndexer.res.mjs +95 -100
- package/src/Utils.res +7 -0
- package/src/Utils.res.mjs +9 -2
- package/src/Writing.res +2 -0
- package/src/Writing.res.mjs +2 -1
- package/src/bindings/ClickHouse.res +39 -6
- package/src/bindings/ClickHouse.res.mjs +29 -4
- package/src/bindings/NodeJs.res +9 -0
- package/src/bindings/NodeJs.res.mjs +8 -1
- package/src/bindings/Postgres.res +9 -0
- package/src/bindings/Postgres.res.mjs +3 -0
- package/src/db/EntityHistory.res +12 -18
- package/src/db/EntityHistory.res.mjs +3 -14
- package/src/db/InternalTable.res +182 -65
- package/src/db/InternalTable.res.mjs +183 -73
- package/src/db/Table.res +24 -0
- package/src/db/Table.res.mjs +20 -1
- package/src/sources/AddressSet.res +0 -22
- package/src/sources/AddressStore.res +48 -88
- package/src/sources/AddressStore.res.mjs +11 -22
- package/src/sources/EvmHyperSyncSource.res +3 -2
- package/src/sources/SimulateSource.res +8 -4
- package/src/sources/SimulateSource.res.mjs +7 -3
- package/src/sources/Svm.res +34 -7
- package/src/sources/Svm.res.mjs +32 -4
- package/src/sources/SvmHyperSyncClient.res +24 -30
- package/src/sources/SvmHyperSyncClient.res.mjs +3 -2
- package/src/sources/SvmHyperSyncSource.res +88 -36
- package/src/sources/SvmHyperSyncSource.res.mjs +71 -39
- package/src/sources/TransactionStore.res +38 -0
- package/src/sources/TransactionStore.res.mjs +5 -0
- package/svm.schema.json +37 -82
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "envio",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.9.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
|
|
6
6
|
"bin": "./bin.mjs",
|
|
@@ -69,10 +69,10 @@
|
|
|
69
69
|
"tsx": "4.21.0"
|
|
70
70
|
},
|
|
71
71
|
"optionalDependencies": {
|
|
72
|
-
"envio-linux-x64": "3.
|
|
73
|
-
"envio-linux-x64-musl": "3.
|
|
74
|
-
"envio-linux-arm64": "3.
|
|
75
|
-
"envio-darwin-x64": "3.
|
|
76
|
-
"envio-darwin-arm64": "3.
|
|
72
|
+
"envio-linux-x64": "3.9.0",
|
|
73
|
+
"envio-linux-x64-musl": "3.9.0",
|
|
74
|
+
"envio-linux-arm64": "3.9.0",
|
|
75
|
+
"envio-darwin-x64": "3.9.0",
|
|
76
|
+
"envio-darwin-arm64": "3.9.0"
|
|
77
77
|
}
|
|
78
78
|
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
type key = {
|
|
2
|
+
chainId: ChainId.t,
|
|
3
|
+
address: NodeJs.Buffer.t,
|
|
4
|
+
contractId: int,
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
type row = {
|
|
8
|
+
chainId: ChainId.t,
|
|
9
|
+
address: NodeJs.Buffer.t,
|
|
10
|
+
contractId: int,
|
|
11
|
+
registrationBlock: int,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type staged = {
|
|
15
|
+
row: row,
|
|
16
|
+
checkpointId: Internal.checkpointId,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type seedRows = {
|
|
20
|
+
addresses: array<NodeJs.Buffer.t>,
|
|
21
|
+
contractIds: array<int>,
|
|
22
|
+
registrationBlocks: array<int>,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let emptySeedRows = (): seedRows => {
|
|
26
|
+
addresses: [],
|
|
27
|
+
contractIds: [],
|
|
28
|
+
registrationBlocks: [],
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Config addresses are registered by no event. Rollback never reaches them.
|
|
32
|
+
let configRegistrationBlock = -1
|
|
33
|
+
|
|
34
|
+
let keyOf = (row: row): key => {
|
|
35
|
+
chainId: row.chainId,
|
|
36
|
+
address: row.address,
|
|
37
|
+
contractId: row.contractId,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let packBuffers = (addresses: array<NodeJs.Buffer.t>) => (
|
|
41
|
+
NodeJs.Buffer.concat(addresses),
|
|
42
|
+
addresses->Array.map(address => address->NodeJs.Buffer.length),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
let packKeys = (rows: array<row>) => packBuffers(rows->Array.map(row => row.address))
|
|
46
|
+
|
|
47
|
+
let seedRowsOf = (rows: array<row>): seedRows => {
|
|
48
|
+
let addresses = []
|
|
49
|
+
let contractIds = []
|
|
50
|
+
let registrationBlocks = []
|
|
51
|
+
rows->Array.forEach(row => {
|
|
52
|
+
addresses->Array.push(row.address)->ignore
|
|
53
|
+
contractIds->Array.push(row.contractId)->ignore
|
|
54
|
+
registrationBlocks->Array.push(row.registrationBlock)->ignore
|
|
55
|
+
})
|
|
56
|
+
{addresses, contractIds, registrationBlocks}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Rows arrive clustered per chain. Normalizing a chain id is a schema parse.
|
|
60
|
+
let group = (rows: array<row>): dict<seedRows> => {
|
|
61
|
+
let rowsByChain: dict<array<row>> = Dict.make()
|
|
62
|
+
let runChainId = ref(None)
|
|
63
|
+
let runKey = ref("")
|
|
64
|
+
rows->Array.forEach(row => {
|
|
65
|
+
if runChainId.contents !== Some(row.chainId) {
|
|
66
|
+
runChainId := Some(row.chainId)
|
|
67
|
+
runKey := row.chainId->ChainId.normalizeOrThrow->ChainId.toString
|
|
68
|
+
}
|
|
69
|
+
rowsByChain->Utils.Dict.push(runKey.contents, row)
|
|
70
|
+
})
|
|
71
|
+
rowsByChain->Utils.Dict.mapValues(seedRowsOf)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
module Table = {
|
|
75
|
+
type t = dict<row>
|
|
76
|
+
|
|
77
|
+
let dictKey = (key: key) =>
|
|
78
|
+
`${key.chainId->ChainId.toString}|${key.contractId->Int.toString}|${key.address->NodeJs.Buffer.toBase64}`
|
|
79
|
+
|
|
80
|
+
let make = (): t => Dict.make()
|
|
81
|
+
|
|
82
|
+
let clear = (table: t) => table->Utils.Dict.clearInPlace
|
|
83
|
+
|
|
84
|
+
let insert = (table: t, row: row) => {
|
|
85
|
+
let key = row->keyOf->dictKey
|
|
86
|
+
switch table->Utils.Dict.dangerouslyGetNonOption(key) {
|
|
87
|
+
| Some(_) => ()
|
|
88
|
+
| None => table->Dict.set(key, row)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
let insertMany = (table: t, rows: array<row>) => rows->Array.forEach(row => table->insert(row))
|
|
93
|
+
|
|
94
|
+
let delete = (table: t, key: key) => table->Utils.Dict.deleteInPlace(key->dictKey)
|
|
95
|
+
|
|
96
|
+
let rows = (table: t): array<row> => table->Dict.valuesToArray
|
|
97
|
+
|
|
98
|
+
let groupByChain = (table: t) => table->rows->group
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let render = (rows: array<row>, ~ecosystem: string, ~shouldChecksum: bool) => {
|
|
102
|
+
let (bytes, lengths) = rows->packKeys
|
|
103
|
+
Core.getAddon().renderAddresses(~ecosystem, ~shouldChecksum, ~bytes, ~lengths)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
let renderOfContract = (
|
|
107
|
+
rows: seedRows,
|
|
108
|
+
~ecosystem: string,
|
|
109
|
+
~shouldChecksum: bool,
|
|
110
|
+
~contractId: int,
|
|
111
|
+
) => {
|
|
112
|
+
let (bytes, lengths) = packBuffers(rows.addresses)
|
|
113
|
+
Core.getAddon().renderContractAddresses(
|
|
114
|
+
~ecosystem,
|
|
115
|
+
~shouldChecksum,
|
|
116
|
+
~bytes,
|
|
117
|
+
~lengths,
|
|
118
|
+
~contractIds=rows.contractIds,
|
|
119
|
+
~contractId,
|
|
120
|
+
)
|
|
121
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Core from "./Core.res.mjs";
|
|
4
|
+
import * as Utils from "./Utils.res.mjs";
|
|
5
|
+
import * as ChainId from "./ChainId.res.mjs";
|
|
6
|
+
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
7
|
+
|
|
8
|
+
function emptySeedRows() {
|
|
9
|
+
return {
|
|
10
|
+
addresses: [],
|
|
11
|
+
contractIds: [],
|
|
12
|
+
registrationBlocks: []
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function keyOf(row) {
|
|
17
|
+
return {
|
|
18
|
+
chainId: row.chainId,
|
|
19
|
+
address: row.address,
|
|
20
|
+
contractId: row.contractId
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function packBuffers(addresses) {
|
|
25
|
+
return [
|
|
26
|
+
Buffer.concat(addresses),
|
|
27
|
+
addresses.map(address => address.length)
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function packKeys(rows) {
|
|
32
|
+
return packBuffers(rows.map(row => row.address));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function seedRowsOf(rows) {
|
|
36
|
+
let addresses = [];
|
|
37
|
+
let contractIds = [];
|
|
38
|
+
let registrationBlocks = [];
|
|
39
|
+
rows.forEach(row => {
|
|
40
|
+
addresses.push(row.address);
|
|
41
|
+
contractIds.push(row.contractId);
|
|
42
|
+
registrationBlocks.push(row.registrationBlock);
|
|
43
|
+
});
|
|
44
|
+
return {
|
|
45
|
+
addresses: addresses,
|
|
46
|
+
contractIds: contractIds,
|
|
47
|
+
registrationBlocks: registrationBlocks
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function group(rows) {
|
|
52
|
+
let rowsByChain = {};
|
|
53
|
+
let runChainId = {
|
|
54
|
+
contents: undefined
|
|
55
|
+
};
|
|
56
|
+
let runKey = {
|
|
57
|
+
contents: ""
|
|
58
|
+
};
|
|
59
|
+
rows.forEach(row => {
|
|
60
|
+
if (runChainId.contents !== Primitive_option.some(row.chainId)) {
|
|
61
|
+
runChainId.contents = Primitive_option.some(row.chainId);
|
|
62
|
+
runKey.contents = ChainId.toString(ChainId.normalizeOrThrow(row.chainId));
|
|
63
|
+
}
|
|
64
|
+
Utils.Dict.push(rowsByChain, runKey.contents, row);
|
|
65
|
+
});
|
|
66
|
+
return Utils.Dict.mapValues(rowsByChain, seedRowsOf);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function dictKey(key) {
|
|
70
|
+
return ChainId.toString(key.chainId) + `|` + key.contractId.toString() + `|` + key.address.toString("base64");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function make() {
|
|
74
|
+
return {};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function clear(table) {
|
|
78
|
+
Utils.Dict.clearInPlace(table);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function insert(table, row) {
|
|
82
|
+
let key = dictKey(keyOf(row));
|
|
83
|
+
let match = table[key];
|
|
84
|
+
if (match !== undefined) {
|
|
85
|
+
return;
|
|
86
|
+
} else {
|
|
87
|
+
table[key] = row;
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function insertMany(table, rows) {
|
|
93
|
+
rows.forEach(row => insert(table, row));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function $$delete(table, key) {
|
|
97
|
+
Utils.Dict.deleteInPlace(table, dictKey(key));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function rows(table) {
|
|
101
|
+
return Object.values(table);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function groupByChain(table) {
|
|
105
|
+
return group(Object.values(table));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
let Table = {
|
|
109
|
+
dictKey: dictKey,
|
|
110
|
+
make: make,
|
|
111
|
+
clear: clear,
|
|
112
|
+
insert: insert,
|
|
113
|
+
insertMany: insertMany,
|
|
114
|
+
$$delete: $$delete,
|
|
115
|
+
rows: rows,
|
|
116
|
+
groupByChain: groupByChain
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
function render(rows, ecosystem, shouldChecksum) {
|
|
120
|
+
let match = packKeys(rows);
|
|
121
|
+
return Core.getAddon().renderAddresses(ecosystem, shouldChecksum, match[0], match[1]);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function renderOfContract(rows, ecosystem, shouldChecksum, contractId) {
|
|
125
|
+
let match = packBuffers(rows.addresses);
|
|
126
|
+
return Core.getAddon().renderContractAddresses(ecosystem, shouldChecksum, match[0], match[1], rows.contractIds, contractId);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
let configRegistrationBlock = -1;
|
|
130
|
+
|
|
131
|
+
export {
|
|
132
|
+
emptySeedRows,
|
|
133
|
+
configRegistrationBlock,
|
|
134
|
+
keyOf,
|
|
135
|
+
packBuffers,
|
|
136
|
+
packKeys,
|
|
137
|
+
seedRowsOf,
|
|
138
|
+
group,
|
|
139
|
+
Table,
|
|
140
|
+
render,
|
|
141
|
+
renderOfContract,
|
|
142
|
+
}
|
|
143
|
+
/* Core Not a pure module */
|
package/src/Batch.res
CHANGED
|
@@ -43,6 +43,7 @@ type t = {
|
|
|
43
43
|
checkpointBlockNumbers: array<int>,
|
|
44
44
|
checkpointBlockHashes: array<Null.t<string>>,
|
|
45
45
|
checkpointEventsProcessed: array<int>,
|
|
46
|
+
registeredAddresses: array<AddressRows.staged>,
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
let getProgressedChainsById = {
|
|
@@ -326,6 +327,7 @@ let prepareBatch = (
|
|
|
326
327
|
checkpointBlockNumbers,
|
|
327
328
|
checkpointBlockHashes,
|
|
328
329
|
checkpointEventsProcessed,
|
|
330
|
+
registeredAddresses: [],
|
|
329
331
|
}
|
|
330
332
|
}
|
|
331
333
|
|
package/src/Batch.res.mjs
CHANGED
|
@@ -185,7 +185,8 @@ function prepareBatch(checkpointIdBeforeBatch, chainsBeforeBatch, batchSizeTarge
|
|
|
185
185
|
checkpointChainIds: checkpointChainIds,
|
|
186
186
|
checkpointBlockNumbers: checkpointBlockNumbers,
|
|
187
187
|
checkpointBlockHashes: checkpointBlockHashes,
|
|
188
|
-
checkpointEventsProcessed: checkpointEventsProcessed
|
|
188
|
+
checkpointEventsProcessed: checkpointEventsProcessed,
|
|
189
|
+
registeredAddresses: []
|
|
189
190
|
};
|
|
190
191
|
}
|
|
191
192
|
|
package/src/ChainState.res
CHANGED
|
@@ -62,20 +62,48 @@ type t = {
|
|
|
62
62
|
mutable progressLatencyMs: option<int>,
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
// The chain's config-declared addresses as storage rows: what a clean run
|
|
66
|
+
// writes into `envio_addresses`. The keys are encoded by the Rust codec, so the
|
|
67
|
+
// bytes a clean run writes are exactly the bytes a resume seeds from.
|
|
68
|
+
let configStorageRows = (
|
|
69
|
+
chainConfig: Config.chain,
|
|
70
|
+
~ecosystem: Ecosystem.name,
|
|
71
|
+
~contractMapping: ContractMapping.t,
|
|
72
|
+
): array<AddressRows.row> => {
|
|
66
73
|
let addresses = []
|
|
74
|
+
let contractIds = []
|
|
67
75
|
chainConfig.contracts->Array.forEach(contract => {
|
|
76
|
+
let contractId = contractMapping->ContractMapping.idOfOrThrow(contract.name)
|
|
68
77
|
contract.addresses->Array.forEach(address => {
|
|
69
|
-
addresses->Array.push(
|
|
70
|
-
|
|
71
|
-
contractName: contract.name,
|
|
72
|
-
registrationBlock: -1,
|
|
73
|
-
})
|
|
78
|
+
addresses->Array.push(address)->ignore
|
|
79
|
+
contractIds->Array.push(contractId)->ignore
|
|
74
80
|
})
|
|
75
81
|
})
|
|
76
|
-
|
|
82
|
+
Core.getAddon().encodeAddresses(
|
|
83
|
+
~ecosystem=(ecosystem :> string),
|
|
84
|
+
~addresses,
|
|
85
|
+
)->Array.mapWithIndex((address, idx) => {
|
|
86
|
+
AddressRows.chainId: chainConfig.id,
|
|
87
|
+
address,
|
|
88
|
+
contractId: contractIds->Array.getUnsafe(idx),
|
|
89
|
+
registrationBlock: AddressRows.configRegistrationBlock,
|
|
90
|
+
})
|
|
77
91
|
}
|
|
78
92
|
|
|
93
|
+
// Seeds an in-memory address table with every chain's config-declared
|
|
94
|
+
// addresses, the twin of what `PgStorage.initialize` writes in one insert.
|
|
95
|
+
let seedConfigAddresses = (
|
|
96
|
+
table: AddressRows.Table.t,
|
|
97
|
+
~chainConfigs: array<Config.chain>,
|
|
98
|
+
~ecosystem: Ecosystem.name,
|
|
99
|
+
~contractMapping: ContractMapping.t,
|
|
100
|
+
) =>
|
|
101
|
+
chainConfigs->Array.forEach(chainConfig =>
|
|
102
|
+
table->AddressRows.Table.insertMany(
|
|
103
|
+
chainConfig->configStorageRows(~ecosystem, ~contractMapping),
|
|
104
|
+
)
|
|
105
|
+
)
|
|
106
|
+
|
|
79
107
|
let validateOnEventRegistrations = (
|
|
80
108
|
~chainId: ChainId.t,
|
|
81
109
|
registrations: array<Internal.onEventRegistration>,
|
|
@@ -142,22 +170,12 @@ let make = (
|
|
|
142
170
|
}
|
|
143
171
|
}
|
|
144
172
|
|
|
145
|
-
// Every chain's contracts, not just one chain's: `context.chain.X.add` accepts
|
|
146
|
-
// any config contract, whichever chain declared it, so every chain's address
|
|
147
|
-
// store has to hold the whole set.
|
|
148
|
-
let configContractNames = (config: Config.t) => {
|
|
149
|
-
let names = Utils.Set.make()
|
|
150
|
-
config.chainMap
|
|
151
|
-
->ChainMap.values
|
|
152
|
-
->Array.forEach(chain =>
|
|
153
|
-
chain.contracts->Array.forEach(contract => names->Utils.Set.add(contract.name)->ignore)
|
|
154
|
-
)
|
|
155
|
-
names->Utils.Set.toArray
|
|
156
|
-
}
|
|
157
|
-
|
|
158
173
|
let makeInternal = (
|
|
159
174
|
~chainConfig: Config.chain,
|
|
160
|
-
~
|
|
175
|
+
~addressRows: AddressRows.seedRows,
|
|
176
|
+
// Passed rather than read off `config`, because a resume must use the mapping
|
|
177
|
+
// storage holds: the ids stored rows carry, not the ids this config derives.
|
|
178
|
+
~contractMapping: ContractMapping.t,
|
|
161
179
|
~startBlock,
|
|
162
180
|
~endBlock,
|
|
163
181
|
~firstEventBlock=None,
|
|
@@ -199,16 +217,13 @@ let makeInternal = (
|
|
|
199
217
|
let addressStore = AddressStore.make(
|
|
200
218
|
~ecosystem=config.ecosystem.name,
|
|
201
219
|
~shouldChecksum=!lowercaseAddresses,
|
|
202
|
-
~contracts=AddressStore.contractsOf(
|
|
203
|
-
~onEventRegistrations,
|
|
204
|
-
~configContractNames=config->configContractNames,
|
|
205
|
-
),
|
|
220
|
+
~contracts=AddressStore.contractsOf(~onEventRegistrations, ~contractMapping),
|
|
206
221
|
)
|
|
207
222
|
|
|
208
223
|
let fetchState = FetchState.make(
|
|
209
224
|
~maxAddrInPartition=config.maxAddrInPartition,
|
|
210
225
|
~addressStore,
|
|
211
|
-
~
|
|
226
|
+
~addressRows,
|
|
212
227
|
~progressBlockNumber,
|
|
213
228
|
~startBlock,
|
|
214
229
|
~endBlock,
|
|
@@ -301,13 +316,15 @@ let makeInternal = (
|
|
|
301
316
|
}),
|
|
302
317
|
]
|
|
303
318
|
}
|
|
304
|
-
| Config.SimulateSourceConfig({items, endBlock}) => [
|
|
319
|
+
| Config.SimulateSourceConfig({items, endBlock, ?transactionStore, ?blockStore}) => [
|
|
305
320
|
SimulateSource.make(
|
|
306
321
|
~items,
|
|
307
322
|
~endBlock,
|
|
308
323
|
~chainId,
|
|
309
324
|
~addressStore,
|
|
310
325
|
~ecosystem=config.ecosystem.name,
|
|
326
|
+
~transactionStore,
|
|
327
|
+
~blockStore,
|
|
311
328
|
),
|
|
312
329
|
]
|
|
313
330
|
// For tests: use ready-to-use sources directly
|
|
@@ -357,7 +374,7 @@ let makeInternal = (
|
|
|
357
374
|
~chainReorgCheckpoints,
|
|
358
375
|
),
|
|
359
376
|
~committedProgressBlockNumber=progressBlockNumber,
|
|
360
|
-
~perChainEntities=config.
|
|
377
|
+
~perChainEntities=config.userEntities->EntityTables.perChain,
|
|
361
378
|
~timestampCaughtUpToHeadOrEndblock,
|
|
362
379
|
~numEventsProcessed,
|
|
363
380
|
~transactionStore=TransactionStore.make(
|
|
@@ -371,33 +388,6 @@ let makeInternal = (
|
|
|
371
388
|
)
|
|
372
389
|
}
|
|
373
390
|
|
|
374
|
-
let makeFromConfig = (
|
|
375
|
-
chainConfig: Config.chain,
|
|
376
|
-
~config,
|
|
377
|
-
~registrationsByChainId,
|
|
378
|
-
~knownHeight,
|
|
379
|
-
) => {
|
|
380
|
-
let logger = Logging.createChild(~params={"chainId": chainConfig.id})
|
|
381
|
-
|
|
382
|
-
makeInternal(
|
|
383
|
-
~chainConfig,
|
|
384
|
-
~config,
|
|
385
|
-
~registrationsByChainId,
|
|
386
|
-
~startBlock=chainConfig.startBlock,
|
|
387
|
-
~endBlock=chainConfig.endBlock,
|
|
388
|
-
~reorgCheckpoints=[],
|
|
389
|
-
~maxReorgDepth=chainConfig.maxReorgDepth,
|
|
390
|
-
~progressBlockNumber=-1,
|
|
391
|
-
~timestampCaughtUpToHeadOrEndblock=None,
|
|
392
|
-
~numEventsProcessed=0.,
|
|
393
|
-
~logger,
|
|
394
|
-
~indexingAddresses=configAddresses(chainConfig),
|
|
395
|
-
~isInReorgThreshold=false,
|
|
396
|
-
~isRealtime=false,
|
|
397
|
-
~knownHeight,
|
|
398
|
-
)
|
|
399
|
-
}
|
|
400
|
-
|
|
401
391
|
/**
|
|
402
392
|
* This function allows a chain state to be created from metadata, in particular this is useful for restarting an indexer and making sure it fetches blocks from the same place.
|
|
403
393
|
*/
|
|
@@ -408,6 +398,7 @@ let makeFromDbState = (
|
|
|
408
398
|
~isInReorgThreshold,
|
|
409
399
|
~isRealtime,
|
|
410
400
|
~config,
|
|
401
|
+
~contractMapping,
|
|
411
402
|
~registrationsByChainId,
|
|
412
403
|
~reducedPollingInterval=?,
|
|
413
404
|
) => {
|
|
@@ -421,7 +412,8 @@ let makeFromDbState = (
|
|
|
421
412
|
: resumedChainState.startBlock - 1
|
|
422
413
|
|
|
423
414
|
makeInternal(
|
|
424
|
-
~
|
|
415
|
+
~addressRows=resumedChainState.addressRows,
|
|
416
|
+
~contractMapping,
|
|
425
417
|
~chainConfig,
|
|
426
418
|
~startBlock=resumedChainState.startBlock,
|
|
427
419
|
~endBlock=resumedChainState.endBlock,
|
|
@@ -505,7 +497,7 @@ let contractAddresses = (cs: t, ~contractName) =>
|
|
|
505
497
|
|
|
506
498
|
// Hands over the dynamically registered addresses the database hasn't seen yet,
|
|
507
499
|
// up to the block the caller is about to commit, each paired with the checkpoint
|
|
508
|
-
// that
|
|
500
|
+
// that registered it. Destructive: the caller must persist them or take the
|
|
509
501
|
// indexer down. Throws with nothing consumed when a registration's block has no
|
|
510
502
|
// checkpoint in the batch.
|
|
511
503
|
let drainAddressesForWrite = (cs: t, ~toBlockInclusive, ~checkpointBlockNumbers) =>
|
|
@@ -852,6 +844,12 @@ let applyTransactionGroups = async (store: TransactionStore.t, g: transactionGro
|
|
|
852
844
|
g.payloadGroups->Array.forEachWithIndex((payloads, i) => {
|
|
853
845
|
let tx = txs->Array.getUnsafe(i)
|
|
854
846
|
payloads->Array.forEach(payload => payload->Internal.setPayloadTransaction(tx))
|
|
847
|
+
switch tx
|
|
848
|
+
->(Utils.magic: Internal.eventTransaction => dict<unknown>)
|
|
849
|
+
->Dict.get("accountActivities") {
|
|
850
|
+
| Some(_) => payloads->Array.forEach(payload => Svm.attachAccountActivities(payload, tx))
|
|
851
|
+
| None => ()
|
|
852
|
+
}
|
|
855
853
|
})
|
|
856
854
|
} else {
|
|
857
855
|
g.payloadGroups->Array.forEach(payloads =>
|
|
@@ -1019,6 +1017,9 @@ let toMetrics = (cs: t): Metrics.chainMetrics => {
|
|
|
1019
1017
|
startBlock: cs.fetchState.startBlock,
|
|
1020
1018
|
endBlock: cs.fetchState.endBlock,
|
|
1021
1019
|
numAddresses: cs.addressStore->AddressStore.size,
|
|
1020
|
+
addressesByContract: cs.addressStore
|
|
1021
|
+
->AddressStore.contractCounts
|
|
1022
|
+
->Array.map(({contractName, count}) => (contractName, count)),
|
|
1022
1023
|
isReady: cs->isReady,
|
|
1023
1024
|
sourceBlockNumber: cs.fetchState.knownHeight,
|
|
1024
1025
|
progressBlockNumber: cs.committedProgressBlockNumber,
|
|
@@ -1209,13 +1210,30 @@ let markReady = (cs: t, ~readyAt) =>
|
|
|
1209
1210
|
// with no diff entry still rewinds fetch state + stores to the target -
|
|
1210
1211
|
// otherwise the stale block hash stays in the store and re-triggers the same
|
|
1211
1212
|
// reorg.
|
|
1213
|
+
// Returns the address registrations the storage has to delete along with it —
|
|
1214
|
+
// the store is what decides which ones died, so the two halves of a rollback
|
|
1215
|
+
// can't disagree.
|
|
1212
1216
|
let rollback = (
|
|
1213
1217
|
cs: t,
|
|
1214
1218
|
~newProgressBlockNumber,
|
|
1215
1219
|
~eventsProcessedDiff,
|
|
1216
1220
|
~rollbackTargetBlockNumber,
|
|
1217
1221
|
~isReorgChain,
|
|
1218
|
-
) => {
|
|
1222
|
+
): array<AddressRows.key> => {
|
|
1223
|
+
let rollbackTo = targetBlockNumber => {
|
|
1224
|
+
let {fetchState, rolledBackAddresses} =
|
|
1225
|
+
cs.fetchState->FetchState.rollback(
|
|
1226
|
+
~rolledBackAddressStore=cs.addressStore,
|
|
1227
|
+
~targetBlockNumber,
|
|
1228
|
+
)
|
|
1229
|
+
cs.fetchState = fetchState
|
|
1230
|
+
rolledBackAddresses->Array.map(({address, contractId}): AddressRows.key => {
|
|
1231
|
+
chainId: cs.chainConfig.id,
|
|
1232
|
+
address,
|
|
1233
|
+
contractId,
|
|
1234
|
+
})
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1219
1237
|
switch newProgressBlockNumber {
|
|
1220
1238
|
| Some(newProgressBlockNumber) =>
|
|
1221
1239
|
let newTotalEventsProcessed =
|
|
@@ -1235,23 +1253,16 @@ let rollback = (
|
|
|
1235
1253
|
)
|
|
1236
1254
|
| None => ()
|
|
1237
1255
|
}
|
|
1238
|
-
|
|
1239
|
-
cs.fetchState->FetchState.rollback(
|
|
1240
|
-
~addressStore=cs.addressStore,
|
|
1241
|
-
~targetBlockNumber=newProgressBlockNumber,
|
|
1242
|
-
)
|
|
1256
|
+
let rolledBackAddresses = rollbackTo(newProgressBlockNumber)
|
|
1243
1257
|
cs.transactionStore->TransactionStore.rollback(newProgressBlockNumber)
|
|
1244
1258
|
cs.blockStore->BlockStore.rollback(newProgressBlockNumber)
|
|
1245
1259
|
cs.committedProgressBlockNumber = newProgressBlockNumber
|
|
1246
1260
|
cs.processingBlockNumber = newProgressBlockNumber
|
|
1247
1261
|
cs.numEventsProcessed = newTotalEventsProcessed
|
|
1262
|
+
rolledBackAddresses
|
|
1248
1263
|
| None =>
|
|
1249
1264
|
if isReorgChain {
|
|
1250
|
-
|
|
1251
|
-
cs.fetchState->FetchState.rollback(
|
|
1252
|
-
~addressStore=cs.addressStore,
|
|
1253
|
-
~targetBlockNumber=rollbackTargetBlockNumber,
|
|
1254
|
-
)
|
|
1265
|
+
let rolledBackAddresses = rollbackTo(rollbackTargetBlockNumber)
|
|
1255
1266
|
cs.transactionStore->TransactionStore.rollback(rollbackTargetBlockNumber)
|
|
1256
1267
|
cs.blockStore->BlockStore.rollback(rollbackTargetBlockNumber)
|
|
1257
1268
|
cs.committedProgressBlockNumber = Pervasives.min(
|
|
@@ -1259,6 +1270,9 @@ let rollback = (
|
|
|
1259
1270
|
rollbackTargetBlockNumber,
|
|
1260
1271
|
)
|
|
1261
1272
|
cs.processingBlockNumber = Pervasives.min(cs.processingBlockNumber, rollbackTargetBlockNumber)
|
|
1273
|
+
rolledBackAddresses
|
|
1274
|
+
} else {
|
|
1275
|
+
[]
|
|
1262
1276
|
}
|
|
1263
1277
|
}
|
|
1264
1278
|
}
|