envio 3.8.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 +158 -104
- 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 +76 -70
- package/src/ChainState.res.mjs +76 -65
- package/src/ChainState.resi +14 -9
- package/src/Config.res +23 -82
- package/src/Config.res.mjs +19 -63
- 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/EventConfigBuilder.res +0 -2
- package/src/EventConfigBuilder.res.mjs +0 -2
- package/src/FetchState.res +59 -67
- package/src/FetchState.res.mjs +34 -44
- package/src/InMemoryStore.res +17 -30
- package/src/InMemoryStore.res.mjs +11 -23
- package/src/IndexerState.res +21 -1
- package/src/IndexerState.res.mjs +9 -3
- package/src/IndexerState.resi +1 -0
- package/src/Main.res +25 -15
- package/src/Main.res.mjs +19 -14
- package/src/MemoryStorage.res +39 -66
- package/src/MemoryStorage.res.mjs +28 -65
- package/src/Metrics.res +15 -1
- package/src/Metrics.res.mjs +5 -1
- package/src/Persistence.res +30 -16
- package/src/Persistence.res.mjs +8 -5
- package/src/PgStorage.res +183 -65
- package/src/PgStorage.res.mjs +92 -58
- package/src/Rollback.res +14 -10
- package/src/Rollback.res.mjs +4 -2
- package/src/SimulateItems.res +5 -12
- package/src/SimulateItems.res.mjs +6 -10
- package/src/TestIndexer.res +93 -111
- package/src/TestIndexer.res.mjs +61 -88
- 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 +6 -0
- package/src/bindings/ClickHouse.res.mjs +4 -0
- 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 +171 -65
- package/src/db/InternalTable.res.mjs +176 -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/SvmHyperSyncClient.res +17 -21
- package/src/sources/SvmHyperSyncSource.res +4 -9
- package/src/sources/SvmHyperSyncSource.res.mjs +5 -13
- package/svm.schema.json +10 -4
|
@@ -2,15 +2,150 @@
|
|
|
2
2
|
|
|
3
3
|
import * as Table from "./Table.res.mjs";
|
|
4
4
|
import * as Utils from "../Utils.res.mjs";
|
|
5
|
-
import * as Config from "../Config.res.mjs";
|
|
6
5
|
import * as Address from "../Address.res.mjs";
|
|
7
6
|
import * as ChainId from "../ChainId.res.mjs";
|
|
7
|
+
import * as Postgres from "../bindings/Postgres.res.mjs";
|
|
8
|
+
import * as AddressRows from "../AddressRows.res.mjs";
|
|
8
9
|
import * as Stdlib_Null from "@rescript/runtime/lib/es6/Stdlib_Null.js";
|
|
9
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";
|
|
13
14
|
|
|
15
|
+
let undefinedTableSqlState = "42P01";
|
|
16
|
+
|
|
17
|
+
function isUndefinedTable(exn) {
|
|
18
|
+
let e = Primitive_exceptions.internalToException(exn);
|
|
19
|
+
if (e.RE_EXN_ID === "JsExn") {
|
|
20
|
+
return e._1.code === undefinedTableSqlState;
|
|
21
|
+
} else {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function chainIdArrayType(pgSchema, chainIdMode) {
|
|
27
|
+
return Table.getPgFieldType("ChainId", pgSchema, true, false, false, chainIdMode);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let table = Table.mkTable("envio_contracts", undefined, [
|
|
31
|
+
Table.mkField("id", "SmallInt", S$RescriptSchema.int, undefined, undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
32
|
+
Table.mkField("name", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined)
|
|
33
|
+
], undefined);
|
|
34
|
+
|
|
35
|
+
function makeInsertQuery(pgSchema) {
|
|
36
|
+
return `INSERT INTO "` + pgSchema + `"."` + table.tableName + `" ("id", "name")
|
|
37
|
+
SELECT * FROM unnest($1::` + "SMALLINT" + `[],$2::` + "TEXT" + `[]);`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function insert(sql, pgSchema, contractNames) {
|
|
41
|
+
return sql.unsafe(makeInsertQuery(pgSchema), [
|
|
42
|
+
contractNames.map((param, idx) => idx),
|
|
43
|
+
contractNames
|
|
44
|
+
], {prepare: true});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function read(sql, pgSchema) {
|
|
48
|
+
try {
|
|
49
|
+
let rows = await sql.unsafe(`SELECT "name" FROM "` + pgSchema + `"."` + table.tableName + `" ORDER BY "id";`);
|
|
50
|
+
return rows.map(row => row.name);
|
|
51
|
+
} catch (raw_exn) {
|
|
52
|
+
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
53
|
+
if (isUndefinedTable(exn)) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
throw exn;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let EnvioContracts = {
|
|
61
|
+
table: table,
|
|
62
|
+
makeInsertQuery: makeInsertQuery,
|
|
63
|
+
insert: insert,
|
|
64
|
+
read: read
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
let name = "envio_addresses";
|
|
68
|
+
|
|
69
|
+
let table$1 = Table.mkTable(name, undefined, [
|
|
70
|
+
Table.mkField("chain_id", "ChainId", ChainId.schema, undefined, undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
71
|
+
Table.mkField("address", "Bytea", S$RescriptSchema.string, undefined, undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
72
|
+
Table.mkField("contract_id", "SmallInt", S$RescriptSchema.int, undefined, undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
73
|
+
Table.mkField("registration_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined)
|
|
74
|
+
], undefined);
|
|
75
|
+
|
|
76
|
+
function makeInsertQuery$1(pgSchema, chainIdModeOpt) {
|
|
77
|
+
let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
|
|
78
|
+
let chainIdArrayType$1 = chainIdArrayType(pgSchema, chainIdMode);
|
|
79
|
+
return `INSERT INTO "` + pgSchema + `"."` + table$1.tableName + `" ("chain_id", "address", "contract_id", "registration_block")
|
|
80
|
+
SELECT * FROM unnest($1::` + chainIdArrayType$1 + `,$2::` + "BYTEA" + `[],$3::` + "SMALLINT" + `[],$4::` + "INTEGER" + `[])
|
|
81
|
+
ON CONFLICT ("chain_id", "address", "contract_id") DO NOTHING;`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function insert$1(sql, pgSchema, rows, chainIdModeOpt) {
|
|
85
|
+
let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
|
|
86
|
+
let chainIds = [];
|
|
87
|
+
let addresses = [];
|
|
88
|
+
let contractIds = [];
|
|
89
|
+
let registrationBlocks = [];
|
|
90
|
+
rows.forEach(row => {
|
|
91
|
+
chainIds.push(row.chainId);
|
|
92
|
+
addresses.push(row.address);
|
|
93
|
+
contractIds.push(row.contractId);
|
|
94
|
+
registrationBlocks.push(row.registrationBlock);
|
|
95
|
+
});
|
|
96
|
+
return sql.unsafe(makeInsertQuery$1(pgSchema, chainIdMode), [
|
|
97
|
+
chainIds,
|
|
98
|
+
sql.typed(addresses, Postgres.byteaArrayOid),
|
|
99
|
+
contractIds,
|
|
100
|
+
registrationBlocks
|
|
101
|
+
], {prepare: true});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function makeDeleteQuery(pgSchema, chainIdModeOpt) {
|
|
105
|
+
let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
|
|
106
|
+
let chainIdArrayType$1 = chainIdArrayType(pgSchema, chainIdMode);
|
|
107
|
+
return `DELETE FROM "` + pgSchema + `"."` + table$1.tableName + `"
|
|
108
|
+
USING unnest($1::` + chainIdArrayType$1 + `,$2::` + "BYTEA" + `[],$3::` + "SMALLINT" + `[]) AS dead(chain_id, address, contract_id)
|
|
109
|
+
WHERE "` + table$1.tableName + `"."chain_id" = dead.chain_id
|
|
110
|
+
AND "` + table$1.tableName + `"."address" = dead.address
|
|
111
|
+
AND "` + table$1.tableName + `"."contract_id" = dead.contract_id;`;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function $$delete(sql, pgSchema, keys, chainIdModeOpt) {
|
|
115
|
+
let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
|
|
116
|
+
let chainIds = [];
|
|
117
|
+
let addresses = [];
|
|
118
|
+
let contractIds = [];
|
|
119
|
+
keys.forEach(key => {
|
|
120
|
+
chainIds.push(key.chainId);
|
|
121
|
+
addresses.push(key.address);
|
|
122
|
+
contractIds.push(key.contractId);
|
|
123
|
+
});
|
|
124
|
+
return sql.unsafe(makeDeleteQuery(pgSchema, chainIdMode), [
|
|
125
|
+
chainIds,
|
|
126
|
+
sql.typed(addresses, Postgres.byteaArrayOid),
|
|
127
|
+
contractIds
|
|
128
|
+
], {prepare: true});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function makeGetRowsQuery(pgSchema) {
|
|
132
|
+
return `SELECT "chain_id" as "chainId",
|
|
133
|
+
"address" as "address",
|
|
134
|
+
"contract_id" as "contractId",
|
|
135
|
+
"registration_block" as "registrationBlock"
|
|
136
|
+
FROM "` + pgSchema + `"."` + table$1.tableName + `";`;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
let EnvioAddresses = {
|
|
140
|
+
name: name,
|
|
141
|
+
table: table$1,
|
|
142
|
+
makeInsertQuery: makeInsertQuery$1,
|
|
143
|
+
insert: insert$1,
|
|
144
|
+
makeDeleteQuery: makeDeleteQuery,
|
|
145
|
+
$$delete: $$delete,
|
|
146
|
+
makeGetRowsQuery: makeGetRowsQuery
|
|
147
|
+
};
|
|
148
|
+
|
|
14
149
|
let fields = [
|
|
15
150
|
"id",
|
|
16
151
|
"ecosystem",
|
|
@@ -26,7 +161,7 @@ let fields = [
|
|
|
26
161
|
"_is_hyper_sync"
|
|
27
162
|
];
|
|
28
163
|
|
|
29
|
-
let table = Table.mkTable("envio_chains", undefined, [
|
|
164
|
+
let table$2 = Table.mkTable("envio_chains", undefined, [
|
|
30
165
|
Table.mkField("id", "ChainId", ChainId.schema, undefined, undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
31
166
|
Table.mkField("ecosystem", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
32
167
|
Table.mkField("start_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
@@ -86,7 +221,7 @@ function makeInitialValuesQuery(pgSchema, chainConfigs) {
|
|
|
86
221
|
});
|
|
87
222
|
return `(` + values.join(", ") + `)`;
|
|
88
223
|
});
|
|
89
|
-
return `INSERT INTO "` + pgSchema + `"."` + table.tableName + `" (` + columnNames.join(", ") + `)
|
|
224
|
+
return `INSERT INTO "` + pgSchema + `"."` + table$2.tableName + `" (` + columnNames.join(", ") + `)
|
|
90
225
|
VALUES ` + valuesRows.join(",\n ") + `;`;
|
|
91
226
|
}
|
|
92
227
|
|
|
@@ -102,13 +237,13 @@ function makeMetaFieldsUpdateQuery(pgSchema) {
|
|
|
102
237
|
let paramIndex = index + 2 | 0;
|
|
103
238
|
return `"` + field + `" = $` + paramIndex.toString();
|
|
104
239
|
});
|
|
105
|
-
return `UPDATE "` + pgSchema + `"."` + table.tableName + `"
|
|
240
|
+
return `UPDATE "` + pgSchema + `"."` + table$2.tableName + `"
|
|
106
241
|
SET ` + setClauses.join(",\n ") + `
|
|
107
242
|
WHERE "` + "id" + `" = $1;`;
|
|
108
243
|
}
|
|
109
244
|
|
|
110
245
|
function makeSetReadyAtQuery(pgSchema) {
|
|
111
|
-
return `UPDATE "` + pgSchema + `"."` + table.tableName + `"
|
|
246
|
+
return `UPDATE "` + pgSchema + `"."` + table$2.tableName + `"
|
|
112
247
|
SET "` + "ready_at" + `" = $1
|
|
113
248
|
WHERE "` + "id" + `" = $2
|
|
114
249
|
AND "` + "ready_at" + `" IS NULL;`;
|
|
@@ -124,40 +259,15 @@ function makeGetInitialStateQuery(pgSchema) {
|
|
|
124
259
|
"` + "events_processed" + `"::float8 as "numEventsProcessed",
|
|
125
260
|
"` + "progress_block" + `" as "progressBlockNumber",
|
|
126
261
|
"` + "source_block" + `" as "sourceBlockNumber"
|
|
127
|
-
FROM "` + pgSchema + `"."` + table.tableName + `";`;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function makeGetIndexingAddressesQuery(pgSchema) {
|
|
131
|
-
return `SELECT "chain_id" as "chainId",
|
|
132
|
-
SUBSTRING("id" FROM POSITION('-' IN "id") + 1) as "address",
|
|
133
|
-
"contract_name" as "contractName",
|
|
134
|
-
"registration_block" as "registrationBlock"
|
|
135
|
-
FROM "` + pgSchema + `"."` + Config.EnvioAddresses.table.tableName + `";`;
|
|
262
|
+
FROM "` + pgSchema + `"."` + table$2.tableName + `";`;
|
|
136
263
|
}
|
|
137
264
|
|
|
138
265
|
async function getInitialState(sql, pgSchema) {
|
|
139
266
|
let match = await Promise.all([
|
|
140
267
|
sql.unsafe(makeGetInitialStateQuery(pgSchema)),
|
|
141
|
-
sql.unsafe(
|
|
268
|
+
sql.unsafe(makeGetRowsQuery(pgSchema))
|
|
142
269
|
]);
|
|
143
|
-
let
|
|
144
|
-
match[1].forEach(row => {
|
|
145
|
-
let key = ChainId.toString(ChainId.normalizeOrThrow(row.chainId));
|
|
146
|
-
let addresses = indexingAddressesByChainId[key];
|
|
147
|
-
let addresses$1;
|
|
148
|
-
if (addresses !== undefined) {
|
|
149
|
-
addresses$1 = addresses;
|
|
150
|
-
} else {
|
|
151
|
-
let addresses$2 = [];
|
|
152
|
-
indexingAddressesByChainId[key] = addresses$2;
|
|
153
|
-
addresses$1 = addresses$2;
|
|
154
|
-
}
|
|
155
|
-
addresses$1.push({
|
|
156
|
-
address: row.address,
|
|
157
|
-
contractName: row.contractName,
|
|
158
|
-
registrationBlock: row.registrationBlock
|
|
159
|
-
});
|
|
160
|
-
});
|
|
270
|
+
let addressRowsByChainId = AddressRows.group(match[1]);
|
|
161
271
|
return match[0].map(rawInitialState => {
|
|
162
272
|
let id = ChainId.normalizeOrThrow(rawInitialState.id);
|
|
163
273
|
return {
|
|
@@ -169,7 +279,7 @@ async function getInitialState(sql, pgSchema) {
|
|
|
169
279
|
timestampCaughtUpToHeadOrEndblock: rawInitialState.timestampCaughtUpToHeadOrEndblock,
|
|
170
280
|
numEventsProcessed: rawInitialState.numEventsProcessed,
|
|
171
281
|
progressBlockNumber: rawInitialState.progressBlockNumber,
|
|
172
|
-
|
|
282
|
+
addressRows: Stdlib_Option.getOr(addressRowsByChainId[ChainId.toString(id)], AddressRows.emptySeedRows()),
|
|
173
283
|
sourceBlockNumber: rawInitialState.sourceBlockNumber
|
|
174
284
|
};
|
|
175
285
|
});
|
|
@@ -186,7 +296,7 @@ function makeProgressFieldsUpdateQuery(pgSchema) {
|
|
|
186
296
|
let paramIndex = index + 2 | 0;
|
|
187
297
|
return `"` + field + `" = $` + paramIndex.toString();
|
|
188
298
|
});
|
|
189
|
-
return `UPDATE "` + pgSchema + `"."` + table.tableName + `"
|
|
299
|
+
return `UPDATE "` + pgSchema + `"."` + table$2.tableName + `"
|
|
190
300
|
SET ` + setClauses.join(",\n ") + `
|
|
191
301
|
WHERE "id" = $1;`;
|
|
192
302
|
}
|
|
@@ -224,14 +334,13 @@ function setProgressedChains(sql, pgSchema, progressedChains) {
|
|
|
224
334
|
|
|
225
335
|
let Chains = {
|
|
226
336
|
fields: fields,
|
|
227
|
-
table: table,
|
|
337
|
+
table: table$2,
|
|
228
338
|
initialFromConfig: initialFromConfig,
|
|
229
339
|
makeInitialValuesQuery: makeInitialValuesQuery,
|
|
230
340
|
metaFields: metaFields,
|
|
231
341
|
makeMetaFieldsUpdateQuery: makeMetaFieldsUpdateQuery,
|
|
232
342
|
makeSetReadyAtQuery: makeSetReadyAtQuery,
|
|
233
343
|
makeGetInitialStateQuery: makeGetInitialStateQuery,
|
|
234
|
-
makeGetIndexingAddressesQuery: makeGetIndexingAddressesQuery,
|
|
235
344
|
getInitialState: getInitialState,
|
|
236
345
|
progressFields: progressFields,
|
|
237
346
|
makeProgressFieldsUpdateQuery: makeProgressFieldsUpdateQuery,
|
|
@@ -239,26 +348,19 @@ let Chains = {
|
|
|
239
348
|
setProgressedChains: setProgressedChains
|
|
240
349
|
};
|
|
241
350
|
|
|
242
|
-
let table$
|
|
351
|
+
let table$3 = Table.mkTable("envio_info", undefined, [
|
|
243
352
|
Table.mkField("id", "Int32", S$RescriptSchema.int, "1", undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
244
353
|
Table.mkField("config", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined)
|
|
245
354
|
], undefined);
|
|
246
355
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
async function read(sql, pgSchema) {
|
|
356
|
+
async function read$1(sql, pgSchema) {
|
|
250
357
|
let rows;
|
|
251
358
|
try {
|
|
252
|
-
rows = await sql.unsafe(`SELECT "config" FROM "` + pgSchema + `"."` + table$
|
|
359
|
+
rows = await sql.unsafe(`SELECT "config" FROM "` + pgSchema + `"."` + table$3.tableName + `" LIMIT 1;`);
|
|
253
360
|
} catch (raw_exn) {
|
|
254
361
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
if (e._1.code === undefinedTableSqlState) {
|
|
258
|
-
rows = [];
|
|
259
|
-
} else {
|
|
260
|
-
throw exn;
|
|
261
|
-
}
|
|
362
|
+
if (isUndefinedTable(exn)) {
|
|
363
|
+
rows = [];
|
|
262
364
|
} else {
|
|
263
365
|
throw exn;
|
|
264
366
|
}
|
|
@@ -267,13 +369,12 @@ async function read(sql, pgSchema) {
|
|
|
267
369
|
}
|
|
268
370
|
|
|
269
371
|
function write(sql, pgSchema, envioInfo) {
|
|
270
|
-
return sql.unsafe(`INSERT INTO "` + pgSchema + `"."` + table$
|
|
372
|
+
return sql.unsafe(`INSERT INTO "` + pgSchema + `"."` + table$3.tableName + `" ("id", "config") VALUES (1, $1) ON CONFLICT ("id") DO UPDATE SET "config" = EXCLUDED."config";`, [JSON.stringify(envioInfo)], {prepare: true});
|
|
271
373
|
}
|
|
272
374
|
|
|
273
375
|
let EnvioInfo = {
|
|
274
|
-
table: table$
|
|
275
|
-
|
|
276
|
-
read: read,
|
|
376
|
+
table: table$3,
|
|
377
|
+
read: read$1,
|
|
277
378
|
write: write
|
|
278
379
|
};
|
|
279
380
|
|
|
@@ -288,7 +389,7 @@ let dbSchema = S$RescriptSchema.object(s => ({
|
|
|
288
389
|
events_processed: s.f("events_processed", S$RescriptSchema.int)
|
|
289
390
|
}));
|
|
290
391
|
|
|
291
|
-
let table$
|
|
392
|
+
let table$4 = Table.mkTable("envio_checkpoints", undefined, [
|
|
292
393
|
Table.mkField("id", "UInt64", S$RescriptSchema.bigint, undefined, undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
293
394
|
Table.mkField("chain_id", "ChainId", ChainId.schema, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
294
395
|
Table.mkField("block_number", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
@@ -301,7 +402,7 @@ function makeGetReorgCheckpointsQuery(pgSchema) {
|
|
|
301
402
|
SELECT
|
|
302
403
|
"` + "id" + `" as id,
|
|
303
404
|
"` + "source_block" + `" - "` + "max_reorg_depth" + `" AS safe_block
|
|
304
|
-
FROM "` + pgSchema + `"."` + table.tableName + `"
|
|
405
|
+
FROM "` + pgSchema + `"."` + table$2.tableName + `"
|
|
305
406
|
WHERE "` + "max_reorg_depth" + `" > 0
|
|
306
407
|
AND "` + "progress_block" + `" > "` + "source_block" + `" - "` + "max_reorg_depth" + `"
|
|
307
408
|
)
|
|
@@ -310,7 +411,7 @@ SELECT
|
|
|
310
411
|
cp."` + "chain_id" + `",
|
|
311
412
|
cp."` + "block_number" + `",
|
|
312
413
|
cp."` + "block_hash" + `"
|
|
313
|
-
FROM "` + pgSchema + `"."` + table$
|
|
414
|
+
FROM "` + pgSchema + `"."` + table$4.tableName + `" cp
|
|
314
415
|
INNER JOIN reorg_chains rc
|
|
315
416
|
ON cp."` + "chain_id" + `" = rc.id
|
|
316
417
|
WHERE cp."` + "block_hash" + `" IS NOT NULL
|
|
@@ -318,17 +419,17 @@ WHERE cp."` + "block_hash" + `" IS NOT NULL
|
|
|
318
419
|
}
|
|
319
420
|
|
|
320
421
|
function makeCommitedCheckpointIdQuery(pgSchema) {
|
|
321
|
-
return `SELECT COALESCE(MAX(` + "id" + `), ` + (0n).toString() + `) AS id FROM "` + pgSchema + `"."` + table$
|
|
422
|
+
return `SELECT COALESCE(MAX(` + "id" + `), ` + (0n).toString() + `) AS id FROM "` + pgSchema + `"."` + table$4.tableName + `";`;
|
|
322
423
|
}
|
|
323
424
|
|
|
324
425
|
function makeInsertCheckpointQuery(pgSchema, chainIdModeOpt) {
|
|
325
426
|
let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
|
|
326
|
-
let chainIdArrayType =
|
|
327
|
-
return `INSERT INTO "` + pgSchema + `"."` + table$
|
|
328
|
-
SELECT * FROM unnest($1::` + "BIGINT" + `[],$2::` + chainIdArrayType + `,$3::` + "INTEGER" + `[],$4::` + "TEXT" + `[],$5::` + "INTEGER" + `[]);`;
|
|
427
|
+
let chainIdArrayType$1 = chainIdArrayType(pgSchema, chainIdMode);
|
|
428
|
+
return `INSERT INTO "` + pgSchema + `"."` + table$4.tableName + `" ("` + "id" + `", "` + "chain_id" + `", "` + "block_number" + `", "` + "block_hash" + `", "` + "events_processed" + `")
|
|
429
|
+
SELECT * FROM unnest($1::` + "BIGINT" + `[],$2::` + chainIdArrayType$1 + `,$3::` + "INTEGER" + `[],$4::` + "TEXT" + `[],$5::` + "INTEGER" + `[]);`;
|
|
329
430
|
}
|
|
330
431
|
|
|
331
|
-
function insert(sql, pgSchema, checkpointIds, checkpointChainIds, checkpointBlockNumbers, checkpointBlockHashes, checkpointEventsProcessed, chainIdModeOpt) {
|
|
432
|
+
function insert$2(sql, pgSchema, checkpointIds, checkpointChainIds, checkpointBlockNumbers, checkpointBlockHashes, checkpointEventsProcessed, chainIdModeOpt) {
|
|
332
433
|
let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
|
|
333
434
|
let query = makeInsertCheckpointQuery(pgSchema, chainIdMode);
|
|
334
435
|
let checkpointIdStrings = Utils.$$BigInt.arrayToStringArray(checkpointIds);
|
|
@@ -342,11 +443,11 @@ function insert(sql, pgSchema, checkpointIds, checkpointChainIds, checkpointBloc
|
|
|
342
443
|
}
|
|
343
444
|
|
|
344
445
|
function rollback(sql, pgSchema, rollbackTargetCheckpointId) {
|
|
345
|
-
return sql.unsafe(`DELETE FROM "` + pgSchema + `"."` + table$
|
|
446
|
+
return sql.unsafe(`DELETE FROM "` + pgSchema + `"."` + table$4.tableName + `" WHERE "` + "id" + `" > $1;`, [rollbackTargetCheckpointId.toString()], {prepare: true});
|
|
346
447
|
}
|
|
347
448
|
|
|
348
449
|
function makePruneStaleCheckpointsQuery(pgSchema) {
|
|
349
|
-
return `DELETE FROM "` + pgSchema + `"."` + table$
|
|
450
|
+
return `DELETE FROM "` + pgSchema + `"."` + table$4.tableName + `" WHERE "` + "id" + `" < $1;`;
|
|
350
451
|
}
|
|
351
452
|
|
|
352
453
|
function pruneStaleCheckpoints(sql, pgSchema, safeCheckpointId) {
|
|
@@ -354,7 +455,7 @@ function pruneStaleCheckpoints(sql, pgSchema, safeCheckpointId) {
|
|
|
354
455
|
}
|
|
355
456
|
|
|
356
457
|
function makeGetRollbackTargetCheckpointQuery(pgSchema) {
|
|
357
|
-
return `SELECT "` + "id" + `" FROM "` + pgSchema + `"."` + table$
|
|
458
|
+
return `SELECT "` + "id" + `" FROM "` + pgSchema + `"."` + table$4.tableName + `"
|
|
358
459
|
WHERE
|
|
359
460
|
"` + "chain_id" + `" = $1 AND
|
|
360
461
|
"` + "block_number" + `" <= $2
|
|
@@ -375,7 +476,7 @@ function makeGetRollbackProgressDiffQuery(pgSchema) {
|
|
|
375
476
|
"` + "chain_id" + `"::float8 as "` + "chain_id" + `",
|
|
376
477
|
SUM("` + "events_processed" + `") as events_processed_diff,
|
|
377
478
|
MIN("` + "block_number" + `") - 1 as new_progress_block_number
|
|
378
|
-
FROM "` + pgSchema + `"."` + table$
|
|
479
|
+
FROM "` + pgSchema + `"."` + table$4.tableName + `"
|
|
379
480
|
WHERE "` + "id" + `" > $1
|
|
380
481
|
GROUP BY "` + "chain_id" + `";`;
|
|
381
482
|
}
|
|
@@ -387,11 +488,11 @@ function getRollbackProgressDiff(sql, pgSchema, rollbackTargetCheckpointId) {
|
|
|
387
488
|
let Checkpoints = {
|
|
388
489
|
dbSchema: dbSchema,
|
|
389
490
|
initialCheckpointId: 0n,
|
|
390
|
-
table: table$
|
|
491
|
+
table: table$4,
|
|
391
492
|
makeGetReorgCheckpointsQuery: makeGetReorgCheckpointsQuery,
|
|
392
493
|
makeCommitedCheckpointIdQuery: makeCommitedCheckpointIdQuery,
|
|
393
494
|
makeInsertCheckpointQuery: makeInsertCheckpointQuery,
|
|
394
|
-
insert: insert,
|
|
495
|
+
insert: insert$2,
|
|
395
496
|
rollback: rollback,
|
|
396
497
|
makePruneStaleCheckpointsQuery: makePruneStaleCheckpointsQuery,
|
|
397
498
|
pruneStaleCheckpoints: pruneStaleCheckpoints,
|
|
@@ -416,7 +517,7 @@ let schema = S$RescriptSchema.schema(s => ({
|
|
|
416
517
|
params: s.m(S$RescriptSchema.json(false))
|
|
417
518
|
}));
|
|
418
519
|
|
|
419
|
-
let table$
|
|
520
|
+
let table$5 = Table.mkTable("raw_events", undefined, [
|
|
420
521
|
Table.mkField("chain_id", "ChainId", ChainId.schema, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
421
522
|
Table.mkField("event_id", "UInt64", S$RescriptSchema.bigint, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
422
523
|
Table.mkField("event_name", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
@@ -434,7 +535,7 @@ let table$3 = Table.mkTable("raw_events", undefined, [
|
|
|
434
535
|
|
|
435
536
|
let RawEvents = {
|
|
436
537
|
schema: schema,
|
|
437
|
-
table: table$
|
|
538
|
+
table: table$5
|
|
438
539
|
};
|
|
439
540
|
|
|
440
541
|
let metaViewName = "_meta";
|
|
@@ -455,7 +556,7 @@ SELECT
|
|
|
455
556
|
"` + "source_block" + `" AS "sourceBlock",
|
|
456
557
|
"` + "ready_at" + `" AS "readyAt",
|
|
457
558
|
("` + "ready_at" + `" IS NOT NULL) AS "isReady"
|
|
458
|
-
FROM "` + pgSchema + `"."` + table.tableName + `"
|
|
559
|
+
FROM "` + pgSchema + `"."` + table$2.tableName + `"
|
|
459
560
|
ORDER BY "` + "id" + `";`;
|
|
460
561
|
}
|
|
461
562
|
|
|
@@ -474,7 +575,7 @@ SELECT
|
|
|
474
575
|
"` + "events_processed" + `"::float4 AS "num_events_processed",
|
|
475
576
|
"` + "start_block" + `" AS "start_block",
|
|
476
577
|
"` + "ready_at" + `" AS "timestamp_caught_up_to_head_or_endblock"
|
|
477
|
-
FROM "` + pgSchema + `"."` + table.tableName + `";`;
|
|
578
|
+
FROM "` + pgSchema + `"."` + table$2.tableName + `";`;
|
|
478
579
|
}
|
|
479
580
|
|
|
480
581
|
let Views = {
|
|
@@ -490,12 +591,14 @@ let isNullable = true;
|
|
|
490
591
|
|
|
491
592
|
let isIndex = true;
|
|
492
593
|
|
|
493
|
-
let EnvioAddresses;
|
|
494
|
-
|
|
495
594
|
export {
|
|
496
595
|
isPrimaryKey,
|
|
497
596
|
isNullable,
|
|
498
597
|
isIndex,
|
|
598
|
+
undefinedTableSqlState,
|
|
599
|
+
isUndefinedTable,
|
|
600
|
+
chainIdArrayType,
|
|
601
|
+
EnvioContracts,
|
|
499
602
|
EnvioAddresses,
|
|
500
603
|
Chains,
|
|
501
604
|
EnvioInfo,
|
package/src/db/Table.res
CHANGED
|
@@ -21,6 +21,10 @@ type fieldType =
|
|
|
21
21
|
| Boolean
|
|
22
22
|
| Uint32
|
|
23
23
|
| UInt52
|
|
24
|
+
| SmallInt
|
|
25
|
+
// Raw bytes. Only the internal tables use it — the one column that stores an
|
|
26
|
+
// address in the binary form the Rust address store keys on.
|
|
27
|
+
| Bytea
|
|
24
28
|
| UInt64
|
|
25
29
|
| Int32
|
|
26
30
|
// Resolved to Int32 or UInt64 storage from the config's `ChainId.mode`, so
|
|
@@ -141,6 +145,20 @@ let getPgFieldName = fieldOrDerived =>
|
|
|
141
145
|
|
|
142
146
|
let idFieldName = "id"
|
|
143
147
|
|
|
148
|
+
let maxPgTableNameLength = 63
|
|
149
|
+
|
|
150
|
+
// Postgres truncates identifiers past its limit on its own, which would collapse
|
|
151
|
+
// two long names onto one. Cutting the readable half and keeping `uniqueSuffix`
|
|
152
|
+
// whole makes every generated name distinct by construction, so the suffix has
|
|
153
|
+
// to be something already unique to the table it names.
|
|
154
|
+
let fitPgTableName = (fullName, ~uniqueSuffix) =>
|
|
155
|
+
if fullName->String.length > maxPgTableNameLength {
|
|
156
|
+
fullName->String.slice(~start=0, ~end=maxPgTableNameLength - uniqueSuffix->String.length) ++
|
|
157
|
+
uniqueSuffix
|
|
158
|
+
} else {
|
|
159
|
+
fullName
|
|
160
|
+
}
|
|
161
|
+
|
|
144
162
|
let getPgFieldType = (
|
|
145
163
|
~fieldType: fieldType,
|
|
146
164
|
~pgSchema,
|
|
@@ -160,6 +178,8 @@ let getPgFieldType = (
|
|
|
160
178
|
}
|
|
161
179
|
| Uint32 => (Postgres.BigInt :> string)
|
|
162
180
|
| UInt52 => (Postgres.BigInt :> string)
|
|
181
|
+
| SmallInt => (Postgres.SmallInt :> string)
|
|
182
|
+
| Bytea => (Postgres.Bytea :> string)
|
|
163
183
|
| UInt64 => (Postgres.BigInt :> string)
|
|
164
184
|
| Number => (Postgres.DoublePrecision :> string)
|
|
165
185
|
| BigInt({?precision}) =>
|
|
@@ -327,6 +347,9 @@ type queryField = {
|
|
|
327
347
|
// Loads are served by Postgres only (ClickHouse is a write-only sink), so
|
|
328
348
|
// no ClickHouse counterpart is needed here.
|
|
329
349
|
pgDbFieldName: string,
|
|
350
|
+
// The chain-id column a per-chain entity's table is partitioned by, which a
|
|
351
|
+
// filter has to write into the SQL rather than bind. See `makeFilterCondition`.
|
|
352
|
+
isChainId: bool,
|
|
330
353
|
}
|
|
331
354
|
let queryFields: table => dict<queryField> = Utils.WeakMap.memoize(table => {
|
|
332
355
|
let dict = Dict.make()
|
|
@@ -339,6 +362,7 @@ let queryFields: table => dict<queryField> = Utils.WeakMap.memoize(table => {
|
|
|
339
362
|
fieldSchema: field.fieldSchema,
|
|
340
363
|
arrayFieldSchema: S.array(field.fieldSchema)->S.toUnknown,
|
|
341
364
|
pgDbFieldName: field->getPgDbFieldName,
|
|
365
|
+
isChainId: field.isChainId,
|
|
342
366
|
},
|
|
343
367
|
)
|
|
344
368
|
| DerivedFrom(_) => ()
|
package/src/db/Table.res.mjs
CHANGED
|
@@ -98,6 +98,14 @@ function getPgFieldName(fieldOrDerived) {
|
|
|
98
98
|
|
|
99
99
|
let idFieldName = "id";
|
|
100
100
|
|
|
101
|
+
function fitPgTableName(fullName, uniqueSuffix) {
|
|
102
|
+
if (fullName.length > 63) {
|
|
103
|
+
return fullName.slice(0, 63 - uniqueSuffix.length | 0) + uniqueSuffix;
|
|
104
|
+
} else {
|
|
105
|
+
return fullName;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
101
109
|
function getPgFieldType(fieldType, pgSchema, isArray, isNumericArrayAsText, isNullable, chainIdModeOpt) {
|
|
102
110
|
let chainIdMode = chainIdModeOpt !== undefined ? chainIdModeOpt : "int32";
|
|
103
111
|
let columnType;
|
|
@@ -109,6 +117,12 @@ function getPgFieldType(fieldType, pgSchema, isArray, isNumericArrayAsText, isNu
|
|
|
109
117
|
case "Boolean" :
|
|
110
118
|
columnType = "BOOLEAN";
|
|
111
119
|
break;
|
|
120
|
+
case "SmallInt" :
|
|
121
|
+
columnType = "SMALLINT";
|
|
122
|
+
break;
|
|
123
|
+
case "Bytea" :
|
|
124
|
+
columnType = "BYTEA";
|
|
125
|
+
break;
|
|
112
126
|
case "Int32" :
|
|
113
127
|
columnType = "INTEGER";
|
|
114
128
|
break;
|
|
@@ -296,7 +310,8 @@ let queryFields = Utils.$$WeakMap.memoize(table => {
|
|
|
296
310
|
dict[getApiFieldName(field$1)] = {
|
|
297
311
|
fieldSchema: field$1.fieldSchema,
|
|
298
312
|
arrayFieldSchema: S$RescriptSchema.array(field$1.fieldSchema),
|
|
299
|
-
pgDbFieldName: getPgDbFieldName(field$1)
|
|
313
|
+
pgDbFieldName: getPgDbFieldName(field$1),
|
|
314
|
+
isChainId: field$1.isChainId
|
|
300
315
|
};
|
|
301
316
|
});
|
|
302
317
|
return dict;
|
|
@@ -467,6 +482,8 @@ function getCompositeIndexes(table) {
|
|
|
467
482
|
return getUnfilteredCompositeIndexesUnsafe(table).filter(ind => ind.length > 1);
|
|
468
483
|
}
|
|
469
484
|
|
|
485
|
+
let maxPgTableNameLength = 63;
|
|
486
|
+
|
|
470
487
|
export {
|
|
471
488
|
makeEnumConfig,
|
|
472
489
|
mkField,
|
|
@@ -478,6 +495,8 @@ export {
|
|
|
478
495
|
getClickHouseDbFieldName,
|
|
479
496
|
getPgFieldName,
|
|
480
497
|
idFieldName,
|
|
498
|
+
maxPgTableNameLength,
|
|
499
|
+
fitPgTableName,
|
|
481
500
|
getPgFieldType,
|
|
482
501
|
mkTable,
|
|
483
502
|
getPgPrimaryKeyFieldNames,
|
|
@@ -1,47 +1,25 @@
|
|
|
1
|
-
// Binding to the Rust `AddressSet` napi class: an immutable, ordered snapshot
|
|
2
|
-
// of some of a chain's indexed addresses, handed to a fetch-state partition
|
|
3
|
-
// instead of a JS address array. Sets are ordered by
|
|
4
|
-
// `(effectiveStartBlock, address)`, so the same addresses always produce the
|
|
5
|
-
// same set however they were registered or restored. Everything a query derives
|
|
6
|
-
// from one (padded topics, the routing owner index, per-contract counts) is
|
|
7
|
-
// built once inside Rust and shared by every query the partition makes.
|
|
8
1
|
type t
|
|
9
2
|
|
|
10
3
|
type startBlockGroup = {startBlock: int, count: int}
|
|
11
4
|
|
|
12
5
|
@send external size: t => int = "size"
|
|
13
6
|
|
|
14
|
-
// Live addresses of one contract, derived once per set inside Rust — so the
|
|
15
|
-
// fetch state can size and split partitions without ever walking the addresses.
|
|
16
7
|
@send external countFor: (t, string) => int = "countFor"
|
|
17
8
|
|
|
18
|
-
// This set holds the address under the contract and it has already started at
|
|
19
|
-
// the block — the gate a real source's router applies to a server-side
|
|
20
|
-
// address-filtered query. The temporal half still comes from the store: a
|
|
21
|
-
// merged partition's addresses don't all start at the same block.
|
|
22
9
|
@send external containsAt: (t, Address.t, string, int) => bool = "containsAt"
|
|
23
10
|
|
|
24
11
|
@send external contractNames: t => array<string> = "contractNames"
|
|
25
12
|
|
|
26
|
-
// Distinct effective start blocks in this set, ascending — how partition
|
|
27
|
-
// creation decides where one partition ends and the next begins.
|
|
28
13
|
@send external startBlockGroups: t => array<startBlockGroup> = "startBlockGroups"
|
|
29
14
|
|
|
30
15
|
@send external slice: (t, ~offset: int, ~limit: option<int>) => t = "slice"
|
|
31
16
|
|
|
32
|
-
// Keeps only the named contracts' addresses, in set order.
|
|
33
17
|
@send external filterByContracts: (t, array<string>) => t = "filterByContracts"
|
|
34
18
|
|
|
35
|
-
// Drops addresses registered after the target block, and any the store has
|
|
36
|
-
// tombstoned since this set was built.
|
|
37
19
|
@send external filterByRegistrationBlock: (t, int) => t = "filterByRegistrationBlock"
|
|
38
20
|
|
|
39
|
-
// Union with another set of the same store, keeping set order; duplicates
|
|
40
|
-
// collapse.
|
|
41
21
|
@send external merge: (t, t) => t = "merge"
|
|
42
22
|
|
|
43
|
-
// Canonical address strings in set order. Not on a query path — queries read
|
|
44
|
-
// the set's cached slices inside Rust.
|
|
45
23
|
@send external addresses: t => array<Address.t> = "addresses"
|
|
46
24
|
|
|
47
25
|
@send external entries: t => array<Internal.indexingContract> = "entries"
|