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.
Files changed (64) hide show
  1. package/README.md +2 -2
  2. package/index.d.ts +158 -104
  3. package/package.json +6 -6
  4. package/src/AddressRows.res +121 -0
  5. package/src/AddressRows.res.mjs +143 -0
  6. package/src/Batch.res +2 -0
  7. package/src/Batch.res.mjs +2 -1
  8. package/src/ChainState.res +76 -70
  9. package/src/ChainState.res.mjs +76 -65
  10. package/src/ChainState.resi +14 -9
  11. package/src/Config.res +23 -82
  12. package/src/Config.res.mjs +19 -63
  13. package/src/ContractMapping.res +66 -0
  14. package/src/ContractMapping.res.mjs +73 -0
  15. package/src/Core.res +20 -0
  16. package/src/Core.res.mjs +4 -0
  17. package/src/EventConfigBuilder.res +0 -2
  18. package/src/EventConfigBuilder.res.mjs +0 -2
  19. package/src/FetchState.res +59 -67
  20. package/src/FetchState.res.mjs +34 -44
  21. package/src/InMemoryStore.res +17 -30
  22. package/src/InMemoryStore.res.mjs +11 -23
  23. package/src/IndexerState.res +21 -1
  24. package/src/IndexerState.res.mjs +9 -3
  25. package/src/IndexerState.resi +1 -0
  26. package/src/Main.res +25 -15
  27. package/src/Main.res.mjs +19 -14
  28. package/src/MemoryStorage.res +39 -66
  29. package/src/MemoryStorage.res.mjs +28 -65
  30. package/src/Metrics.res +15 -1
  31. package/src/Metrics.res.mjs +5 -1
  32. package/src/Persistence.res +30 -16
  33. package/src/Persistence.res.mjs +8 -5
  34. package/src/PgStorage.res +183 -65
  35. package/src/PgStorage.res.mjs +92 -58
  36. package/src/Rollback.res +14 -10
  37. package/src/Rollback.res.mjs +4 -2
  38. package/src/SimulateItems.res +5 -12
  39. package/src/SimulateItems.res.mjs +6 -10
  40. package/src/TestIndexer.res +93 -111
  41. package/src/TestIndexer.res.mjs +61 -88
  42. package/src/Utils.res +7 -0
  43. package/src/Utils.res.mjs +9 -2
  44. package/src/Writing.res +2 -0
  45. package/src/Writing.res.mjs +2 -1
  46. package/src/bindings/ClickHouse.res +6 -0
  47. package/src/bindings/ClickHouse.res.mjs +4 -0
  48. package/src/bindings/NodeJs.res +9 -0
  49. package/src/bindings/NodeJs.res.mjs +8 -1
  50. package/src/bindings/Postgres.res +9 -0
  51. package/src/bindings/Postgres.res.mjs +3 -0
  52. package/src/db/EntityHistory.res +12 -18
  53. package/src/db/EntityHistory.res.mjs +3 -14
  54. package/src/db/InternalTable.res +171 -65
  55. package/src/db/InternalTable.res.mjs +176 -73
  56. package/src/db/Table.res +24 -0
  57. package/src/db/Table.res.mjs +20 -1
  58. package/src/sources/AddressSet.res +0 -22
  59. package/src/sources/AddressStore.res +48 -88
  60. package/src/sources/AddressStore.res.mjs +11 -22
  61. package/src/sources/SvmHyperSyncClient.res +17 -21
  62. package/src/sources/SvmHyperSyncSource.res +4 -9
  63. package/src/sources/SvmHyperSyncSource.res.mjs +5 -13
  64. 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(makeGetIndexingAddressesQuery(pgSchema))
268
+ sql.unsafe(makeGetRowsQuery(pgSchema))
142
269
  ]);
143
- let indexingAddressesByChainId = {};
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
- indexingAddresses: Stdlib_Option.getOr(indexingAddressesByChainId[ChainId.toString(id)], []),
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$1 = Table.mkTable("envio_info", undefined, [
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
- let undefinedTableSqlState = "42P01";
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$1.tableName + `" LIMIT 1;`);
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
- let e = Primitive_exceptions.internalToException(exn);
256
- if (e.RE_EXN_ID === "JsExn") {
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$1.tableName + `" ("id", "config") VALUES (1, $1) ON CONFLICT ("id") DO UPDATE SET "config" = EXCLUDED."config";`, [JSON.stringify(envioInfo)], {prepare: true});
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$1,
275
- undefinedTableSqlState: undefinedTableSqlState,
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$2 = Table.mkTable("envio_checkpoints", undefined, [
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$2.tableName + `" cp
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$2.tableName + `";`;
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 = Table.getPgFieldType("ChainId", pgSchema, true, false, false, chainIdMode);
327
- return `INSERT INTO "` + pgSchema + `"."` + table$2.tableName + `" ("` + "id" + `", "` + "chain_id" + `", "` + "block_number" + `", "` + "block_hash" + `", "` + "events_processed" + `")
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$2.tableName + `" WHERE "` + "id" + `" > $1;`, [rollbackTargetCheckpointId.toString()], {prepare: true});
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$2.tableName + `" WHERE "` + "id" + `" < $1;`;
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$2.tableName + `"
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$2.tableName + `"
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$2,
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$3 = Table.mkTable("raw_events", undefined, [
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$3
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(_) => ()
@@ -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"