envio 3.0.2 → 3.1.0-rc.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 +0 -1
- package/evm.schema.json +15 -8
- package/fuel.schema.json +19 -12
- package/index.d.ts +0 -2
- package/package.json +6 -7
- package/rescript.json +1 -1
- package/src/Batch.res +4 -214
- package/src/Batch.res.mjs +6 -165
- package/src/ChainFetcher.res +4 -5
- package/src/ChainFetcher.res.mjs +6 -7
- package/src/ChainManager.res +10 -9
- package/src/ChainManager.res.mjs +6 -10
- package/src/Config.res +9 -25
- package/src/Config.res.mjs +17 -27
- package/src/Core.res +7 -0
- package/src/Ctx.res +1 -0
- package/src/Env.res +0 -1
- package/src/Env.res.mjs +0 -3
- package/src/EventConfigBuilder.res +13 -123
- package/src/EventConfigBuilder.res.mjs +6 -73
- package/src/EventProcessing.res +5 -29
- package/src/EventProcessing.res.mjs +11 -20
- package/src/EventUtils.res +0 -27
- package/src/EventUtils.res.mjs +0 -24
- package/src/FetchState.res +1 -11
- package/src/FetchState.res.mjs +2 -16
- package/src/GlobalState.res +23 -37
- package/src/GlobalState.res.mjs +10 -38
- package/src/HandlerLoader.res +6 -5
- package/src/HandlerLoader.res.mjs +27 -9
- package/src/HandlerRegister.res +1 -12
- package/src/HandlerRegister.res.mjs +1 -6
- package/src/HandlerRegister.resi +1 -1
- package/src/Hasura.res +96 -32
- package/src/Hasura.res.mjs +93 -38
- package/src/InMemoryStore.res +181 -45
- package/src/InMemoryStore.res.mjs +143 -40
- package/src/InMemoryTable.res +147 -247
- package/src/InMemoryTable.res.mjs +131 -230
- package/src/Internal.res +10 -34
- package/src/Internal.res.mjs +9 -3
- package/src/LoadLayer.res +5 -5
- package/src/LoadLayer.res.mjs +5 -5
- package/src/Main.res +4 -6
- package/src/Main.res.mjs +26 -15
- package/src/Persistence.res +7 -132
- package/src/Persistence.res.mjs +1 -102
- package/src/PgStorage.res +57 -40
- package/src/PgStorage.res.mjs +60 -34
- package/src/ReorgDetection.res +35 -58
- package/src/ReorgDetection.res.mjs +21 -29
- package/src/SimulateItems.res.mjs +21 -3
- package/src/Sink.res +2 -2
- package/src/Sink.res.mjs +1 -1
- package/src/TableIndices.res +9 -2
- package/src/TableIndices.res.mjs +7 -1
- package/src/TestIndexer.res +53 -60
- package/src/TestIndexer.res.mjs +77 -63
- package/src/TestIndexerProxyStorage.res +4 -14
- package/src/TestIndexerProxyStorage.res.mjs +1 -5
- package/src/UserContext.res +2 -4
- package/src/UserContext.res.mjs +4 -5
- package/src/Utils.res +0 -2
- package/src/Utils.res.mjs +0 -3
- package/src/bindings/ClickHouse.res +45 -38
- package/src/bindings/ClickHouse.res.mjs +16 -17
- package/src/bindings/Vitest.res +3 -0
- package/src/db/InternalTable.res +59 -18
- package/src/db/InternalTable.res.mjs +82 -51
- package/src/db/Table.res +9 -2
- package/src/db/Table.res.mjs +10 -7
- package/src/sources/EvmChain.res +32 -9
- package/src/sources/EvmChain.res.mjs +31 -4
- package/src/sources/HyperFuelSource.res +14 -57
- package/src/sources/HyperFuelSource.res.mjs +18 -38
- package/src/sources/HyperSync.res +36 -101
- package/src/sources/HyperSync.res.mjs +42 -96
- package/src/sources/HyperSync.resi +4 -22
- package/src/sources/HyperSyncClient.res +67 -245
- package/src/sources/HyperSyncClient.res.mjs +47 -46
- package/src/sources/HyperSyncSource.res +76 -147
- package/src/sources/HyperSyncSource.res.mjs +61 -114
- package/src/sources/RpcSource.res +43 -22
- package/src/sources/RpcSource.res.mjs +50 -35
- package/src/sources/SimulateSource.res +1 -7
- package/src/sources/SimulateSource.res.mjs +1 -7
- package/src/sources/Source.res +8 -1
- package/src/sources/SourceManager.res +9 -0
- package/src/sources/SourceManager.res.mjs +10 -0
- package/src/sources/SourceManager.resi +2 -0
- package/svm.schema.json +11 -4
package/src/db/InternalTable.res
CHANGED
|
@@ -186,26 +186,67 @@ WHERE "${(#id: field :> string)}" = $1;`
|
|
|
186
186
|
"${(#ready_at: field :> string)}" as "timestampCaughtUpToHeadOrEndblock",
|
|
187
187
|
"${(#events_processed: field :> string)}"::float8 as "numEventsProcessed",
|
|
188
188
|
"${(#progress_block: field :> string)}" as "progressBlockNumber",
|
|
189
|
-
"${(#source_block: field :> string)}" as "sourceBlockNumber"
|
|
190
|
-
|
|
191
|
-
-- envio_addresses.id is a composite "{chainId}-{address}" string produced by
|
|
192
|
-
-- Config.EnvioAddresses.makeId; extract the address by taking everything
|
|
193
|
-
-- after the first '-'. Keep in sync with makeId / getAddress.
|
|
194
|
-
SELECT COALESCE(json_agg(json_build_object(
|
|
195
|
-
'address', SUBSTRING("id" FROM POSITION('-' IN "id") + 1),
|
|
196
|
-
'contractName', "contract_name",
|
|
197
|
-
'registrationBlock', "registration_block"
|
|
198
|
-
)), '[]'::json)
|
|
199
|
-
FROM "${pgSchema}"."${EnvioAddresses.table.tableName}"
|
|
200
|
-
WHERE "chain_id" = chains."${(#id: field :> string)}"
|
|
201
|
-
) as "indexingAddresses"
|
|
202
|
-
FROM "${pgSchema}"."${table.tableName}" as chains;`
|
|
189
|
+
"${(#source_block: field :> string)}" as "sourceBlockNumber"
|
|
190
|
+
FROM "${pgSchema}"."${table.tableName}";`
|
|
203
191
|
}
|
|
204
192
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
193
|
+
type rawIndexingAddress = {
|
|
194
|
+
chainId: int,
|
|
195
|
+
address: Address.t,
|
|
196
|
+
contractName: string,
|
|
197
|
+
registrationBlock: int,
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Addresses are read as plain rows rather than aggregated per chain with
|
|
201
|
+
// json_agg: a single chain's aggregate can exceed V8's max string length
|
|
202
|
+
// (postgres.js decodes the column with Buffer.toString and throws
|
|
203
|
+
// ERR_STRING_TOO_LONG). Grouping happens in JS instead — see getInitialState.
|
|
204
|
+
let makeGetIndexingAddressesQuery = (~pgSchema) => {
|
|
205
|
+
// envio_addresses.id is a composite "{chainId}-{address}" string produced by
|
|
206
|
+
// Config.EnvioAddresses.makeId; extract the address by taking everything
|
|
207
|
+
// after the first '-'. Keep in sync with makeId / getAddress.
|
|
208
|
+
`SELECT "chain_id" as "chainId",
|
|
209
|
+
SUBSTRING("id" FROM POSITION('-' IN "id") + 1) as "address",
|
|
210
|
+
"contract_name" as "contractName",
|
|
211
|
+
"registration_block" as "registrationBlock"
|
|
212
|
+
FROM "${pgSchema}"."${EnvioAddresses.table.tableName}";`
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
let getInitialState = async (sql, ~pgSchema) => {
|
|
216
|
+
let (rawInitialStates, rawIndexingAddresses) = await Promise.all2((
|
|
217
|
+
sql
|
|
218
|
+
->Postgres.unsafe(makeGetInitialStateQuery(~pgSchema))
|
|
219
|
+
->(Utils.magic: promise<array<unknown>> => promise<array<rawInitialState>>),
|
|
220
|
+
sql
|
|
221
|
+
->Postgres.unsafe(makeGetIndexingAddressesQuery(~pgSchema))
|
|
222
|
+
->(Utils.magic: promise<array<unknown>> => promise<array<rawIndexingAddress>>),
|
|
223
|
+
))
|
|
224
|
+
|
|
225
|
+
let indexingAddressesByChainId = Dict.make()
|
|
226
|
+
rawIndexingAddresses->Array.forEach(row => {
|
|
227
|
+
let key = row.chainId->Int.toString
|
|
228
|
+
let addresses = switch indexingAddressesByChainId->Dict.get(key) {
|
|
229
|
+
| Some(addresses) => addresses
|
|
230
|
+
| None =>
|
|
231
|
+
let addresses: array<Internal.indexingAddress> = []
|
|
232
|
+
indexingAddressesByChainId->Dict.set(key, addresses)
|
|
233
|
+
addresses
|
|
234
|
+
}
|
|
235
|
+
addresses
|
|
236
|
+
->Array.push({
|
|
237
|
+
address: row.address,
|
|
238
|
+
contractName: row.contractName,
|
|
239
|
+
registrationBlock: row.registrationBlock,
|
|
240
|
+
})
|
|
241
|
+
->ignore
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
rawInitialStates->Array.map(rawInitialState => {
|
|
245
|
+
...rawInitialState,
|
|
246
|
+
indexingAddresses: indexingAddressesByChainId
|
|
247
|
+
->Dict.get(rawInitialState.id->Int.toString)
|
|
248
|
+
->Option.getOr([]),
|
|
249
|
+
})
|
|
209
250
|
}
|
|
210
251
|
|
|
211
252
|
let progressFields: array<progressFields> = [#progress_block, #events_processed, #source_block]
|
|
@@ -7,6 +7,7 @@ import * as Address from "../Address.res.mjs";
|
|
|
7
7
|
import * as Belt_Array from "@rescript/runtime/lib/es6/Belt_Array.js";
|
|
8
8
|
import * as Belt_Option from "@rescript/runtime/lib/es6/Belt_Option.js";
|
|
9
9
|
import * as Stdlib_Null from "@rescript/runtime/lib/es6/Stdlib_Null.js";
|
|
10
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
10
11
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
11
12
|
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
12
13
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
@@ -26,18 +27,18 @@ let fields = [
|
|
|
26
27
|
];
|
|
27
28
|
|
|
28
29
|
let table = Table.mkTable("envio_chains", undefined, [
|
|
29
|
-
Table.mkField("id", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, true, undefined, undefined),
|
|
30
|
-
Table.mkField("start_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
31
|
-
Table.mkField("end_block", "Int32", S$RescriptSchema.$$null(S$RescriptSchema.int), undefined, undefined, true, undefined, undefined, undefined),
|
|
32
|
-
Table.mkField("max_reorg_depth", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
33
|
-
Table.mkField("buffer_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
34
|
-
Table.mkField("source_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
35
|
-
Table.mkField("first_event_block", "Int32", S$RescriptSchema.$$null(S$RescriptSchema.int), undefined, undefined, true, undefined, undefined, undefined),
|
|
36
|
-
Table.mkField("ready_at", "Date", S$RescriptSchema.$$null(Utils.Schema.dbDate), undefined, undefined, true, undefined, undefined, undefined),
|
|
37
|
-
Table.mkField("events_processed", "UInt52", S$RescriptSchema.float, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
38
|
-
Table.mkField("_is_hyper_sync", "Boolean", S$RescriptSchema.bool, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
39
|
-
Table.mkField("progress_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined)
|
|
40
|
-
]);
|
|
30
|
+
Table.mkField("id", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, true, undefined, undefined, undefined),
|
|
31
|
+
Table.mkField("start_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
32
|
+
Table.mkField("end_block", "Int32", S$RescriptSchema.$$null(S$RescriptSchema.int), undefined, undefined, true, undefined, undefined, undefined, undefined),
|
|
33
|
+
Table.mkField("max_reorg_depth", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
34
|
+
Table.mkField("buffer_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
35
|
+
Table.mkField("source_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
36
|
+
Table.mkField("first_event_block", "Int32", S$RescriptSchema.$$null(S$RescriptSchema.int), undefined, undefined, true, undefined, undefined, undefined, undefined),
|
|
37
|
+
Table.mkField("ready_at", "Date", S$RescriptSchema.$$null(Utils.Schema.dbDate), undefined, undefined, true, undefined, undefined, undefined, undefined),
|
|
38
|
+
Table.mkField("events_processed", "UInt52", S$RescriptSchema.float, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
39
|
+
Table.mkField("_is_hyper_sync", "Boolean", S$RescriptSchema.bool, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
40
|
+
Table.mkField("progress_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined)
|
|
41
|
+
], undefined);
|
|
41
42
|
|
|
42
43
|
function initialFromConfig(chainConfig) {
|
|
43
44
|
return {
|
|
@@ -113,24 +114,53 @@ function makeGetInitialStateQuery(pgSchema) {
|
|
|
113
114
|
"` + "ready_at" + `" as "timestampCaughtUpToHeadOrEndblock",
|
|
114
115
|
"` + "events_processed" + `"::float8 as "numEventsProcessed",
|
|
115
116
|
"` + "progress_block" + `" as "progressBlockNumber",
|
|
116
|
-
"` + "source_block" + `" as "sourceBlockNumber"
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
SELECT
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
FROM "` + pgSchema + `"."` + Config.EnvioAddresses.table.tableName + `"
|
|
127
|
-
WHERE "chain_id" = chains."` + "id" + `"
|
|
128
|
-
) as "indexingAddresses"
|
|
129
|
-
FROM "` + pgSchema + `"."` + table.tableName + `" as chains;`;
|
|
117
|
+
"` + "source_block" + `" as "sourceBlockNumber"
|
|
118
|
+
FROM "` + pgSchema + `"."` + table.tableName + `";`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function makeGetIndexingAddressesQuery(pgSchema) {
|
|
122
|
+
return `SELECT "chain_id" as "chainId",
|
|
123
|
+
SUBSTRING("id" FROM POSITION('-' IN "id") + 1) as "address",
|
|
124
|
+
"contract_name" as "contractName",
|
|
125
|
+
"registration_block" as "registrationBlock"
|
|
126
|
+
FROM "` + pgSchema + `"."` + Config.EnvioAddresses.table.tableName + `";`;
|
|
130
127
|
}
|
|
131
128
|
|
|
132
|
-
function getInitialState(sql, pgSchema) {
|
|
133
|
-
|
|
129
|
+
async function getInitialState(sql, pgSchema) {
|
|
130
|
+
let match = await Promise.all([
|
|
131
|
+
sql.unsafe(makeGetInitialStateQuery(pgSchema)),
|
|
132
|
+
sql.unsafe(makeGetIndexingAddressesQuery(pgSchema))
|
|
133
|
+
]);
|
|
134
|
+
let indexingAddressesByChainId = {};
|
|
135
|
+
match[1].forEach(row => {
|
|
136
|
+
let key = row.chainId.toString();
|
|
137
|
+
let addresses = indexingAddressesByChainId[key];
|
|
138
|
+
let addresses$1;
|
|
139
|
+
if (addresses !== undefined) {
|
|
140
|
+
addresses$1 = addresses;
|
|
141
|
+
} else {
|
|
142
|
+
let addresses$2 = [];
|
|
143
|
+
indexingAddressesByChainId[key] = addresses$2;
|
|
144
|
+
addresses$1 = addresses$2;
|
|
145
|
+
}
|
|
146
|
+
addresses$1.push({
|
|
147
|
+
address: row.address,
|
|
148
|
+
contractName: row.contractName,
|
|
149
|
+
registrationBlock: row.registrationBlock
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
return match[0].map(rawInitialState => ({
|
|
153
|
+
id: rawInitialState.id,
|
|
154
|
+
startBlock: rawInitialState.startBlock,
|
|
155
|
+
endBlock: rawInitialState.endBlock,
|
|
156
|
+
maxReorgDepth: rawInitialState.maxReorgDepth,
|
|
157
|
+
firstEventBlockNumber: rawInitialState.firstEventBlockNumber,
|
|
158
|
+
timestampCaughtUpToHeadOrEndblock: rawInitialState.timestampCaughtUpToHeadOrEndblock,
|
|
159
|
+
numEventsProcessed: rawInitialState.numEventsProcessed,
|
|
160
|
+
progressBlockNumber: rawInitialState.progressBlockNumber,
|
|
161
|
+
indexingAddresses: Stdlib_Option.getOr(indexingAddressesByChainId[rawInitialState.id.toString()], []),
|
|
162
|
+
sourceBlockNumber: rawInitialState.sourceBlockNumber
|
|
163
|
+
}));
|
|
134
164
|
}
|
|
135
165
|
|
|
136
166
|
let progressFields = [
|
|
@@ -188,6 +218,7 @@ let Chains = {
|
|
|
188
218
|
metaFields: metaFields,
|
|
189
219
|
makeMetaFieldsUpdateQuery: makeMetaFieldsUpdateQuery,
|
|
190
220
|
makeGetInitialStateQuery: makeGetInitialStateQuery,
|
|
221
|
+
makeGetIndexingAddressesQuery: makeGetIndexingAddressesQuery,
|
|
191
222
|
getInitialState: getInitialState,
|
|
192
223
|
progressFields: progressFields,
|
|
193
224
|
makeProgressFieldsUpdateQuery: makeProgressFieldsUpdateQuery,
|
|
@@ -196,9 +227,9 @@ let Chains = {
|
|
|
196
227
|
};
|
|
197
228
|
|
|
198
229
|
let table$1 = Table.mkTable("envio_info", undefined, [
|
|
199
|
-
Table.mkField("id", "Int32", S$RescriptSchema.int, "1", undefined, undefined, true, undefined, undefined),
|
|
200
|
-
Table.mkField("config", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined)
|
|
201
|
-
]);
|
|
230
|
+
Table.mkField("id", "Int32", S$RescriptSchema.int, "1", undefined, undefined, true, undefined, undefined, undefined),
|
|
231
|
+
Table.mkField("config", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined, undefined)
|
|
232
|
+
], undefined);
|
|
202
233
|
|
|
203
234
|
let undefinedTableSqlState = "42P01";
|
|
204
235
|
|
|
@@ -245,12 +276,12 @@ let dbSchema = S$RescriptSchema.object(s => ({
|
|
|
245
276
|
}));
|
|
246
277
|
|
|
247
278
|
let table$2 = Table.mkTable("envio_checkpoints", undefined, [
|
|
248
|
-
Table.mkField("id", "UInt64", S$RescriptSchema.bigint, undefined, undefined, undefined, true, undefined, undefined),
|
|
249
|
-
Table.mkField("chain_id", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
250
|
-
Table.mkField("block_number", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
251
|
-
Table.mkField("block_hash", "String", S$RescriptSchema.$$null(S$RescriptSchema.string), undefined, undefined, true, undefined, undefined, undefined),
|
|
252
|
-
Table.mkField("events_processed", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined)
|
|
253
|
-
]);
|
|
279
|
+
Table.mkField("id", "UInt64", S$RescriptSchema.bigint, undefined, undefined, undefined, true, undefined, undefined, undefined),
|
|
280
|
+
Table.mkField("chain_id", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
281
|
+
Table.mkField("block_number", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
282
|
+
Table.mkField("block_hash", "String", S$RescriptSchema.$$null(S$RescriptSchema.string), undefined, undefined, true, undefined, undefined, undefined, undefined),
|
|
283
|
+
Table.mkField("events_processed", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined)
|
|
284
|
+
], undefined);
|
|
254
285
|
|
|
255
286
|
function makeGetReorgCheckpointsQuery(pgSchema) {
|
|
256
287
|
return `WITH reorg_chains AS (
|
|
@@ -370,20 +401,20 @@ let schema = S$RescriptSchema.schema(s => ({
|
|
|
370
401
|
}));
|
|
371
402
|
|
|
372
403
|
let table$3 = Table.mkTable("raw_events", undefined, [
|
|
373
|
-
Table.mkField("chain_id", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
374
|
-
Table.mkField("event_id", "UInt64", S$RescriptSchema.bigint, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
375
|
-
Table.mkField("event_name", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
376
|
-
Table.mkField("contract_name", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
377
|
-
Table.mkField("block_number", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
378
|
-
Table.mkField("log_index", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
379
|
-
Table.mkField("src_address", "String", Address.schema, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
380
|
-
Table.mkField("block_hash", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
381
|
-
Table.mkField("block_timestamp", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
382
|
-
Table.mkField("block_fields", "Json", S$RescriptSchema.json(false), undefined, undefined, undefined, undefined, undefined, undefined),
|
|
383
|
-
Table.mkField("transaction_fields", "Json", S$RescriptSchema.json(false), undefined, undefined, undefined, undefined, undefined, undefined),
|
|
384
|
-
Table.mkField("params", "Json", S$RescriptSchema.json(false), undefined, undefined, undefined, undefined, undefined, undefined),
|
|
385
|
-
Table.mkField("serial", "BigSerial", S$RescriptSchema.$$null(S$RescriptSchema.bigint), undefined, undefined, true, true, undefined, undefined)
|
|
386
|
-
]);
|
|
404
|
+
Table.mkField("chain_id", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
405
|
+
Table.mkField("event_id", "UInt64", S$RescriptSchema.bigint, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
406
|
+
Table.mkField("event_name", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
407
|
+
Table.mkField("contract_name", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
408
|
+
Table.mkField("block_number", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
409
|
+
Table.mkField("log_index", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
410
|
+
Table.mkField("src_address", "String", Address.schema, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
411
|
+
Table.mkField("block_hash", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
412
|
+
Table.mkField("block_timestamp", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
413
|
+
Table.mkField("block_fields", "Json", S$RescriptSchema.json(false), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
414
|
+
Table.mkField("transaction_fields", "Json", S$RescriptSchema.json(false), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
415
|
+
Table.mkField("params", "Json", S$RescriptSchema.json(false), undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
416
|
+
Table.mkField("serial", "BigSerial", S$RescriptSchema.$$null(S$RescriptSchema.bigint), undefined, undefined, true, true, undefined, undefined, undefined)
|
|
417
|
+
], undefined);
|
|
387
418
|
|
|
388
419
|
let RawEvents = {
|
|
389
420
|
schema: schema,
|
package/src/db/Table.res
CHANGED
|
@@ -43,12 +43,14 @@ type field = {
|
|
|
43
43
|
isIndex: bool,
|
|
44
44
|
linkedEntity: option<string>,
|
|
45
45
|
defaultValue: option<string>,
|
|
46
|
+
description: option<string>,
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
type derivedFromField = {
|
|
49
50
|
fieldName: string,
|
|
50
51
|
derivedFromEntity: string,
|
|
51
52
|
derivedFromField: string,
|
|
53
|
+
description: option<string>,
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
type fieldOrDerived = Field(field) | DerivedFrom(derivedFromField)
|
|
@@ -63,6 +65,7 @@ let mkField = (
|
|
|
63
65
|
~isPrimaryKey=false,
|
|
64
66
|
~isIndex=false,
|
|
65
67
|
~linkedEntity=?,
|
|
68
|
+
~description=?,
|
|
66
69
|
) =>
|
|
67
70
|
{
|
|
68
71
|
fieldName,
|
|
@@ -74,13 +77,15 @@ let mkField = (
|
|
|
74
77
|
isIndex,
|
|
75
78
|
linkedEntity,
|
|
76
79
|
defaultValue: default,
|
|
80
|
+
description,
|
|
77
81
|
}->Field
|
|
78
82
|
|
|
79
|
-
let mkDerivedFromField = (fieldName, ~derivedFromEntity, ~derivedFromField) =>
|
|
83
|
+
let mkDerivedFromField = (fieldName, ~derivedFromEntity, ~derivedFromField, ~description=?) =>
|
|
80
84
|
{
|
|
81
85
|
fieldName,
|
|
82
86
|
derivedFromField,
|
|
83
87
|
derivedFromEntity,
|
|
88
|
+
description,
|
|
84
89
|
}->DerivedFrom
|
|
85
90
|
|
|
86
91
|
let getUserDefinedFieldName = fieldOrDerived =>
|
|
@@ -162,12 +167,14 @@ type table = {
|
|
|
162
167
|
tableName: string,
|
|
163
168
|
fields: array<fieldOrDerived>,
|
|
164
169
|
compositeIndices: array<array<compositeIndexField>>,
|
|
170
|
+
description: option<string>,
|
|
165
171
|
}
|
|
166
172
|
|
|
167
|
-
let mkTable = (tableName, ~compositeIndices=[], ~fields) => {
|
|
173
|
+
let mkTable = (tableName, ~compositeIndices=[], ~fields, ~description=?) => {
|
|
168
174
|
tableName,
|
|
169
175
|
fields,
|
|
170
176
|
compositeIndices,
|
|
177
|
+
description,
|
|
171
178
|
}
|
|
172
179
|
|
|
173
180
|
let getPrimaryKeyFieldNames = table =>
|
package/src/db/Table.res.mjs
CHANGED
|
@@ -17,7 +17,7 @@ function makeEnumConfig(name, variants) {
|
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
function mkField(fieldName, fieldType, fieldSchema, $$default, isArrayOpt, isNullableOpt, isPrimaryKeyOpt, isIndexOpt, linkedEntity) {
|
|
20
|
+
function mkField(fieldName, fieldType, fieldSchema, $$default, isArrayOpt, isNullableOpt, isPrimaryKeyOpt, isIndexOpt, linkedEntity, description) {
|
|
21
21
|
let isArray = isArrayOpt !== undefined ? isArrayOpt : false;
|
|
22
22
|
let isNullable = isNullableOpt !== undefined ? isNullableOpt : false;
|
|
23
23
|
let isPrimaryKey = isPrimaryKeyOpt !== undefined ? isPrimaryKeyOpt : false;
|
|
@@ -33,18 +33,20 @@ function mkField(fieldName, fieldType, fieldSchema, $$default, isArrayOpt, isNul
|
|
|
33
33
|
isPrimaryKey: isPrimaryKey,
|
|
34
34
|
isIndex: isIndex,
|
|
35
35
|
linkedEntity: linkedEntity,
|
|
36
|
-
defaultValue: $$default
|
|
36
|
+
defaultValue: $$default,
|
|
37
|
+
description: description
|
|
37
38
|
}
|
|
38
39
|
};
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
function mkDerivedFromField(fieldName, derivedFromEntity, derivedFromField) {
|
|
42
|
+
function mkDerivedFromField(fieldName, derivedFromEntity, derivedFromField, description) {
|
|
42
43
|
return {
|
|
43
44
|
TAG: "DerivedFrom",
|
|
44
45
|
_0: {
|
|
45
46
|
fieldName: fieldName,
|
|
46
47
|
derivedFromEntity: derivedFromEntity,
|
|
47
|
-
derivedFromField: derivedFromField
|
|
48
|
+
derivedFromField: derivedFromField,
|
|
49
|
+
description: description
|
|
48
50
|
}
|
|
49
51
|
};
|
|
50
52
|
}
|
|
@@ -133,12 +135,13 @@ function getPgFieldType(fieldType, pgSchema, isArray, isNumericArrayAsText, isNu
|
|
|
133
135
|
);
|
|
134
136
|
}
|
|
135
137
|
|
|
136
|
-
function mkTable(tableName, compositeIndicesOpt, fields) {
|
|
138
|
+
function mkTable(tableName, compositeIndicesOpt, fields, description) {
|
|
137
139
|
let compositeIndices = compositeIndicesOpt !== undefined ? compositeIndicesOpt : [];
|
|
138
140
|
return {
|
|
139
141
|
tableName: tableName,
|
|
140
142
|
fields: fields,
|
|
141
|
-
compositeIndices: compositeIndices
|
|
143
|
+
compositeIndices: compositeIndices,
|
|
144
|
+
description: description
|
|
142
145
|
};
|
|
143
146
|
}
|
|
144
147
|
|
|
@@ -209,7 +212,7 @@ function getNonDefaultFieldNames(table) {
|
|
|
209
212
|
}
|
|
210
213
|
|
|
211
214
|
function getFieldByName(table, fieldName) {
|
|
212
|
-
return table.fields.find(field => field
|
|
215
|
+
return table.fields.find(field => getUserDefinedFieldName(field) === fieldName);
|
|
213
216
|
}
|
|
214
217
|
|
|
215
218
|
function getFieldByDbName(table, dbFieldName) {
|
package/src/sources/EvmChain.res
CHANGED
|
@@ -22,33 +22,53 @@ let getSyncConfig = (
|
|
|
22
22
|
initialBlockInterval: Env.Configurable.SyncConfig.initialBlockInterval->Option.getOr(
|
|
23
23
|
initialBlockInterval->Option.getOr(10_000),
|
|
24
24
|
),
|
|
25
|
-
// After an RPC error, how much to scale back the number of blocks requested at once
|
|
26
25
|
backoffMultiplicative: Env.Configurable.SyncConfig.backoffMultiplicative->Option.getOr(
|
|
27
26
|
backoffMultiplicative->Option.getOr(0.8),
|
|
28
27
|
),
|
|
29
|
-
// Without RPC errors or timeouts, how much to increase the number of blocks requested by for the next batch
|
|
30
28
|
accelerationAdditive: Env.Configurable.SyncConfig.accelerationAdditive->Option.getOr(
|
|
31
29
|
accelerationAdditive->Option.getOr(500),
|
|
32
30
|
),
|
|
33
|
-
// Do not further increase the block interval past this limit
|
|
34
31
|
intervalCeiling: Env.Configurable.SyncConfig.intervalCeiling->Option.getOr(
|
|
35
32
|
intervalCeiling->Option.getOr(10_000),
|
|
36
33
|
),
|
|
37
|
-
// After an error, how long to wait before retrying
|
|
38
34
|
backoffMillis: backoffMillis->Option.getOr(5000),
|
|
39
|
-
// How long to wait before cancelling an RPC request
|
|
40
35
|
queryTimeoutMillis,
|
|
41
36
|
fallbackStallTimeout: fallbackStallTimeout->Option.getOr(queryTimeoutMillis / 2),
|
|
42
|
-
// How frequently to check for new blocks in realtime (default: 1000ms)
|
|
43
37
|
pollingInterval: pollingInterval->Option.getOr(1000),
|
|
44
38
|
}
|
|
45
39
|
}
|
|
46
40
|
|
|
41
|
+
let collectEventParams = (contracts: array<Internal.evmContractConfig>): array<
|
|
42
|
+
HyperSyncClient.Decoder.eventParamsInput,
|
|
43
|
+
> => {
|
|
44
|
+
let seen = Dict.make()
|
|
45
|
+
let result = []
|
|
46
|
+
contracts->Array.forEach(contract => {
|
|
47
|
+
contract.events->Array.forEach(event => {
|
|
48
|
+
let key = event.sighash ++ "_" ++ event.topicCount->Int.toString
|
|
49
|
+
switch seen->Dict.get(key) {
|
|
50
|
+
| Some(_) => ()
|
|
51
|
+
| None => {
|
|
52
|
+
seen->Dict.set(key, true)
|
|
53
|
+
result
|
|
54
|
+
->Array.push({
|
|
55
|
+
HyperSyncClient.Decoder.sighash: event.sighash,
|
|
56
|
+
topicCount: event.topicCount,
|
|
57
|
+
eventName: event.name,
|
|
58
|
+
params: event.paramsMetadata,
|
|
59
|
+
})
|
|
60
|
+
->ignore
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
result
|
|
66
|
+
}
|
|
67
|
+
|
|
47
68
|
let makeSources = (
|
|
48
69
|
~chain,
|
|
49
70
|
~contracts: array<Internal.evmContractConfig>,
|
|
50
71
|
~hyperSync,
|
|
51
|
-
~allEventSignatures,
|
|
52
72
|
~rpcs: array<rpc>,
|
|
53
73
|
~lowercaseAddresses,
|
|
54
74
|
) => {
|
|
@@ -57,12 +77,14 @@ let makeSources = (
|
|
|
57
77
|
->Belt.Array.flatMap(contract => contract.events)
|
|
58
78
|
->EventRouter.fromEvmEventModsOrThrow(~chain)
|
|
59
79
|
|
|
80
|
+
let allEventParams = collectEventParams(contracts)
|
|
81
|
+
|
|
60
82
|
let sources = switch hyperSync {
|
|
61
83
|
| Some(endpointUrl) => [
|
|
62
84
|
HyperSyncSource.make({
|
|
63
85
|
chain,
|
|
64
86
|
endpointUrl,
|
|
65
|
-
|
|
87
|
+
allEventParams,
|
|
66
88
|
eventRouter,
|
|
67
89
|
apiToken: Env.envioApiToken,
|
|
68
90
|
clientMaxRetries: Env.hyperSyncClientMaxRetries,
|
|
@@ -70,6 +92,7 @@ let makeSources = (
|
|
|
70
92
|
lowercaseAddresses,
|
|
71
93
|
serializationFormat: Env.hypersyncClientSerializationFormat,
|
|
72
94
|
enableQueryCaching: Env.hypersyncClientEnableQueryCaching,
|
|
95
|
+
logLevel: Env.hypersyncLogLevel,
|
|
73
96
|
}),
|
|
74
97
|
]
|
|
75
98
|
| _ => []
|
|
@@ -81,7 +104,7 @@ let makeSources = (
|
|
|
81
104
|
syncConfig: getSyncConfig(syncConfig->Option.getOr({})),
|
|
82
105
|
url,
|
|
83
106
|
eventRouter,
|
|
84
|
-
|
|
107
|
+
allEventParams,
|
|
85
108
|
lowercaseAddresses,
|
|
86
109
|
?ws,
|
|
87
110
|
})
|
|
@@ -21,19 +21,45 @@ function getSyncConfig(param) {
|
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
function
|
|
24
|
+
function collectEventParams(contracts) {
|
|
25
|
+
let seen = {};
|
|
26
|
+
let result = [];
|
|
27
|
+
contracts.forEach(contract => {
|
|
28
|
+
contract.events.forEach(event => {
|
|
29
|
+
let key = event.sighash + "_" + event.topicCount.toString();
|
|
30
|
+
let match = seen[key];
|
|
31
|
+
if (match !== undefined) {
|
|
32
|
+
return;
|
|
33
|
+
} else {
|
|
34
|
+
seen[key] = true;
|
|
35
|
+
result.push({
|
|
36
|
+
sighash: event.sighash,
|
|
37
|
+
topicCount: event.topicCount,
|
|
38
|
+
eventName: event.name,
|
|
39
|
+
params: event.paramsMetadata
|
|
40
|
+
});
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function makeSources(chain, contracts, hyperSync, rpcs, lowercaseAddresses) {
|
|
25
49
|
let eventRouter = EventRouter.fromEvmEventModsOrThrow(Belt_Array.flatMap(contracts, contract => contract.events), chain);
|
|
50
|
+
let allEventParams = collectEventParams(contracts);
|
|
26
51
|
let sources = hyperSync !== undefined ? [HyperSyncSource.make({
|
|
27
52
|
chain: chain,
|
|
28
53
|
endpointUrl: hyperSync,
|
|
29
|
-
|
|
54
|
+
allEventParams: allEventParams,
|
|
30
55
|
eventRouter: eventRouter,
|
|
31
56
|
apiToken: Env.envioApiToken,
|
|
32
57
|
clientMaxRetries: Env.hyperSyncClientMaxRetries,
|
|
33
58
|
clientTimeoutMillis: Env.hyperSyncClientTimeoutMillis,
|
|
34
59
|
lowercaseAddresses: lowercaseAddresses,
|
|
35
60
|
serializationFormat: Env.hypersyncClientSerializationFormat,
|
|
36
|
-
enableQueryCaching: Env.hypersyncClientEnableQueryCaching
|
|
61
|
+
enableQueryCaching: Env.hypersyncClientEnableQueryCaching,
|
|
62
|
+
logLevel: Env.hypersyncLogLevel
|
|
37
63
|
})] : [];
|
|
38
64
|
rpcs.forEach(param => {
|
|
39
65
|
let source = RpcSource.make({
|
|
@@ -42,7 +68,7 @@ function makeSources(chain, contracts, hyperSync, allEventSignatures, rpcs, lowe
|
|
|
42
68
|
url: param.url,
|
|
43
69
|
chain: chain,
|
|
44
70
|
eventRouter: eventRouter,
|
|
45
|
-
|
|
71
|
+
allEventParams: allEventParams,
|
|
46
72
|
lowercaseAddresses: lowercaseAddresses,
|
|
47
73
|
ws: param.ws
|
|
48
74
|
});
|
|
@@ -53,6 +79,7 @@ function makeSources(chain, contracts, hyperSync, allEventSignatures, rpcs, lowe
|
|
|
53
79
|
|
|
54
80
|
export {
|
|
55
81
|
getSyncConfig,
|
|
82
|
+
collectEventParams,
|
|
56
83
|
makeSources,
|
|
57
84
|
}
|
|
58
85
|
/* Env Not a pure module */
|
|
@@ -225,7 +225,6 @@ let make = ({chain, endpointUrl}: options): t => {
|
|
|
225
225
|
~retry,
|
|
226
226
|
~logger,
|
|
227
227
|
) => {
|
|
228
|
-
let mkLogAndRaise = ErrorHandling.mkLogAndRaise(~logger, ...)
|
|
229
228
|
let totalTimeRef = Hrtime.makeTimer()
|
|
230
229
|
|
|
231
230
|
let selectionConfig = getSelectionConfig(selection)
|
|
@@ -299,55 +298,6 @@ let make = ({chain, endpointUrl}: options): t => {
|
|
|
299
298
|
//In the query
|
|
300
299
|
let heighestBlockQueried = pageUnsafe.nextBlock - 1
|
|
301
300
|
|
|
302
|
-
let lastBlockQueriedPromise = // switch pageUnsafe.rollbackGuard {
|
|
303
|
-
// //In the case a rollbackGuard is returned (this only happens at the head for unconfirmed blocks)
|
|
304
|
-
// //use these values
|
|
305
|
-
// | Some({blockNumber, timestamp, hash}) =>
|
|
306
|
-
// {
|
|
307
|
-
// ReorgDetection.blockNumber,
|
|
308
|
-
// blockTimestamp: timestamp,
|
|
309
|
-
// blockHash: hash,
|
|
310
|
-
// }->Promise.resolve
|
|
311
|
-
// | None =>
|
|
312
|
-
//The optional block and timestamp of the last item returned by the query
|
|
313
|
-
//(Optional in the case that there are no logs returned in the query)
|
|
314
|
-
switch pageUnsafe.items->Belt.Array.get(pageUnsafe.items->Belt.Array.length - 1) {
|
|
315
|
-
| Some({block}) if block.height == heighestBlockQueried =>
|
|
316
|
-
//If the last log item in the current page is equal to the
|
|
317
|
-
//heighest block acounted for in the query. Simply return this
|
|
318
|
-
//value without making an extra query
|
|
319
|
-
|
|
320
|
-
(
|
|
321
|
-
{
|
|
322
|
-
blockNumber: block.height,
|
|
323
|
-
blockTimestamp: block.time,
|
|
324
|
-
blockHash: block.id,
|
|
325
|
-
}: ReorgDetection.blockDataWithTimestamp
|
|
326
|
-
)->Promise.resolve
|
|
327
|
-
//If it does not match it means that there were no matching logs in the last
|
|
328
|
-
//block so we should fetch the block data
|
|
329
|
-
| Some(_)
|
|
330
|
-
| None =>
|
|
331
|
-
//If there were no logs at all in the current page query then fetch the
|
|
332
|
-
//timestamp of the heighest block accounted for
|
|
333
|
-
HyperFuel.queryBlockData(~serverUrl=endpointUrl, ~blockNumber=heighestBlockQueried, ~logger)
|
|
334
|
-
->Promise.thenResolve(res => {
|
|
335
|
-
switch res {
|
|
336
|
-
| Some(blockData) => blockData
|
|
337
|
-
| None =>
|
|
338
|
-
mkLogAndRaise(
|
|
339
|
-
Not_found,
|
|
340
|
-
~msg=`Failure, blockData for block ${heighestBlockQueried->Int.toString} unexpectedly returned None`,
|
|
341
|
-
)
|
|
342
|
-
}
|
|
343
|
-
})
|
|
344
|
-
->Promise.catch(exn => {
|
|
345
|
-
exn->mkLogAndRaise(
|
|
346
|
-
~msg=`Failed to query blockData for block ${heighestBlockQueried->Int.toString}`,
|
|
347
|
-
)
|
|
348
|
-
})
|
|
349
|
-
}
|
|
350
|
-
|
|
351
301
|
let parsingTimeRef = Hrtime.makeTimer()
|
|
352
302
|
|
|
353
303
|
let parsedQueueItems = pageUnsafe.items->Array.map(item => {
|
|
@@ -463,11 +413,18 @@ let make = ({chain, endpointUrl}: options): t => {
|
|
|
463
413
|
|
|
464
414
|
let parsingTimeElapsed = parsingTimeRef->Hrtime.timeSince->Hrtime.toSecondsFloat
|
|
465
415
|
|
|
466
|
-
|
|
416
|
+
// Fuel never rolls back on reorg, so block hashes here are purely informational
|
|
417
|
+
// for detect-only logging via ReorgDetection.
|
|
418
|
+
let blockHashes = pageUnsafe.items->Array.map(({block}) => {
|
|
419
|
+
ReorgDetection.blockNumber: block.height,
|
|
420
|
+
blockHash: block.id,
|
|
421
|
+
})
|
|
467
422
|
|
|
468
|
-
let
|
|
469
|
-
|
|
470
|
-
|
|
423
|
+
let latestFetchedBlockTimestamp = switch pageUnsafe.items->Belt.Array.get(
|
|
424
|
+
pageUnsafe.items->Belt.Array.length - 1,
|
|
425
|
+
) {
|
|
426
|
+
| Some({block}) if block.height == heighestBlockQueried => block.time
|
|
427
|
+
| _ => 0
|
|
471
428
|
}
|
|
472
429
|
|
|
473
430
|
let totalTimeElapsed = totalTimeRef->Hrtime.timeSince->Hrtime.toSecondsFloat
|
|
@@ -479,12 +436,12 @@ let make = ({chain, endpointUrl}: options): t => {
|
|
|
479
436
|
}
|
|
480
437
|
|
|
481
438
|
{
|
|
482
|
-
latestFetchedBlockTimestamp
|
|
439
|
+
latestFetchedBlockTimestamp,
|
|
483
440
|
parsedQueueItems,
|
|
484
|
-
latestFetchedBlockNumber:
|
|
441
|
+
latestFetchedBlockNumber: heighestBlockQueried,
|
|
485
442
|
stats,
|
|
486
443
|
knownHeight,
|
|
487
|
-
|
|
444
|
+
blockHashes,
|
|
488
445
|
fromBlockQueried: fromBlock,
|
|
489
446
|
}
|
|
490
447
|
}
|