envio 2.28.0-alpha.1 → 2.28.0-alpha.3

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 CHANGED
@@ -19,7 +19,7 @@ HyperIndex is a fast, developer-friendly multichain indexer, optimized for both
19
19
  - **[Reorg support](https://docs.envio.dev/docs/HyperIndex/reorgs-support)** – Graceful handling of blockchain reorganizations
20
20
  - **GraphQL API** – Easy-to-query indexed data
21
21
  - **Flexible language support** – JavaScript, TypeScript, and ReScript
22
- - **Factory contract support** – Index data from 100,000+ factory contracts seamlessly
22
+ - **Factory contract support** – Index data from 1M+ dynamically registered contracts seamlessly
23
23
  - **On-chain & off-chain data integration** – Easily combine multiple data sources
24
24
  - **[Self-hosted & managed options](https://docs.envio.dev/docs/HyperIndex/hosted-service)** – Run your own setup or use HyperIndex hosted services
25
25
  - **Detailed logging & error reporting** – Debug and optimize with clarity
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "envio",
3
- "version": "v2.28.0-alpha.1",
3
+ "version": "v2.28.0-alpha.3",
4
4
  "description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
5
5
  "bin": "./bin.js",
6
6
  "main": "./index.js",
@@ -25,10 +25,10 @@
25
25
  },
26
26
  "homepage": "https://envio.dev",
27
27
  "optionalDependencies": {
28
- "envio-linux-x64": "v2.28.0-alpha.1",
29
- "envio-linux-arm64": "v2.28.0-alpha.1",
30
- "envio-darwin-x64": "v2.28.0-alpha.1",
31
- "envio-darwin-arm64": "v2.28.0-alpha.1"
28
+ "envio-linux-x64": "v2.28.0-alpha.3",
29
+ "envio-linux-arm64": "v2.28.0-alpha.3",
30
+ "envio-darwin-x64": "v2.28.0-alpha.3",
31
+ "envio-darwin-arm64": "v2.28.0-alpha.3"
32
32
  },
33
33
  "dependencies": {
34
34
  "@envio-dev/hypersync-client": "0.6.5",
@@ -818,20 +818,27 @@ let getNextQuery = (
818
818
  if (
819
819
  p->checkIsFetchingPartition->not && p.latestFetchedBlock.blockNumber < maxQueryBlockNumber
820
820
  ) {
821
- switch p->makePartitionQuery(
822
- ~indexingContracts,
823
- ~endBlock=switch blockLag {
824
- | 0 => endBlock
825
- | _ =>
826
- switch endBlock {
827
- | Some(endBlock) => Some(Pervasives.min(headBlock, endBlock))
828
- // Force head block as an endBlock when blockLag is set
829
- // because otherwise HyperSync might return bigger range
830
- | None => Some(headBlock)
831
- }
832
- },
833
- ~mergeTarget,
834
- ) {
821
+ let endBlock = switch blockLag {
822
+ | 0 => endBlock
823
+ | _ =>
824
+ switch endBlock {
825
+ | Some(endBlock) => Some(Pervasives.min(headBlock, endBlock))
826
+ // Force head block as an endBlock when blockLag is set
827
+ // because otherwise HyperSync might return bigger range
828
+ | None => Some(headBlock)
829
+ }
830
+ }
831
+ // Enforce the respose range up until target block
832
+ // Otherwise for indexers with 100+ partitions
833
+ // we might blow up the buffer size to more than 600k events
834
+ // simply because of HyperSync returning extra blocks
835
+ let endBlock = switch (endBlock, maxQueryBlockNumber < currentBlockHeight) {
836
+ | (Some(endBlock), true) => Some(Pervasives.min(maxQueryBlockNumber, endBlock))
837
+ | (None, true) => Some(maxQueryBlockNumber)
838
+ | (_, false) => endBlock
839
+ }
840
+
841
+ switch p->makePartitionQuery(~indexingContracts, ~endBlock, ~mergeTarget) {
835
842
  | Some(q) => queries->Array.push(q)
836
843
  | None => ()
837
844
  }
@@ -571,11 +571,20 @@ function getNextQuery(param, concurrencyLimit, targetBufferSize, currentBlockHei
571
571
  if (!(!checkIsFetchingPartition(p) && p.latestFetchedBlock.blockNumber < maxQueryBlockNumber)) {
572
572
  return ;
573
573
  }
574
- var q = makePartitionQuery(p, indexingContracts, blockLag !== 0 ? (
575
- endBlock !== undefined ? (
576
- headBlock < endBlock ? headBlock : endBlock
577
- ) : headBlock
578
- ) : endBlock, mergeTarget);
574
+ var endBlock$1 = blockLag !== 0 ? (
575
+ endBlock !== undefined ? (
576
+ headBlock < endBlock ? headBlock : endBlock
577
+ ) : headBlock
578
+ ) : endBlock;
579
+ var match = maxQueryBlockNumber < currentBlockHeight;
580
+ var endBlock$2 = endBlock$1 !== undefined ? (
581
+ match ? (
582
+ maxQueryBlockNumber < endBlock$1 ? maxQueryBlockNumber : endBlock$1
583
+ ) : endBlock$1
584
+ ) : (
585
+ match ? maxQueryBlockNumber : endBlock$1
586
+ );
587
+ var q = makePartitionQuery(p, indexingContracts, endBlock$2, mergeTarget);
579
588
  if (q !== undefined) {
580
589
  queries.push(q);
581
590
  return ;
package/src/Hasura.res CHANGED
@@ -218,112 +218,6 @@ let createEntityRelationship = async (
218
218
  }
219
219
  }
220
220
 
221
- let trackMeta = async (~auth, ~endpoint, ~pgSchema) => {
222
- try {
223
- // Track EnvioMeta logical model with scalar fields
224
- let result = await rawBodyRoute->Rest.fetch(
225
- {
226
- "auth": auth,
227
- "bodyString": `{"type": "pg_track_logical_model","args": {"source": "default","name":"EnvioMeta","fields":[{"name":"chainId","type":"int"},{"name":"startBlock","type":"int"},{"name":"endBlock","type":"int","nullable":true},{"name":"bufferBlock","type":"int"},{"name":"readyAt","type":"timestamptz","nullable":true},{"name":"firstEventBlock","type":"int","nullable":true},{"name":"eventsProcessed","type":"int"},{"name":"isReady","type":"bool"}]}}`,
228
- },
229
- ~client=Rest.client(endpoint),
230
- )
231
- let msg = switch result {
232
- | QuerySucceeded => `Hasura EnvioMeta logical model created`
233
- | AlreadyDone => `Hasura EnvioMeta logical model already created`
234
- }
235
- Logging.trace({
236
- "msg": msg,
237
- })
238
-
239
- // Update _meta native query to return hardcoded block object
240
- let result = await rawBodyRoute->Rest.fetch(
241
- {
242
- "auth": auth,
243
- "bodyString": `{"type":"pg_track_native_query","args":{"type":"query","source":"default","root_field_name":"_meta","arguments":{},"returns":"EnvioMeta","code":"SELECT \\\"${(#id: InternalTable.Chains.field :> string)}\\\" AS \\\"chainId\\\", \\\"${(#start_block: InternalTable.Chains.field :> string)}\\\" AS \\\"startBlock\\\", \\\"${(#end_block: InternalTable.Chains.field :> string)}\\\" AS \\\"endBlock\\\", \\\"${(#buffer_block: InternalTable.Chains.field :> string)}\\\" AS \\\"bufferBlock\\\", \\\"${(#ready_at: InternalTable.Chains.field :> string)}\\\" AS \\\"readyAt\\\", \\\"${(#first_event_block: InternalTable.Chains.field :> string)}\\\" AS \\\"firstEventBlock\\\", \\\"${(#events_processed: InternalTable.Chains.field :> string)}\\\" AS \\\"eventsProcessed\\\", (\\\"${(#ready_at: InternalTable.Chains.field :> string)}\\\" IS NOT NULL) AS \\\"isReady\\\" FROM \\\"${pgSchema}\\\".\\\"${InternalTable.Chains.table.tableName}\\\" ORDER BY \\\"id\\\""}}`,
244
- },
245
- ~client=Rest.client(endpoint),
246
- )
247
- let msg = switch result {
248
- | QuerySucceeded => `Hasura _meta native query created`
249
- | AlreadyDone => `Hasura _meta native query already created`
250
- }
251
- Logging.trace({
252
- "msg": msg,
253
- })
254
-
255
- // Add public select permissions for EnvioMeta logical model
256
- let result = await rawBodyRoute->Rest.fetch(
257
- {
258
- "auth": auth,
259
- "bodyString": `{"type": "pg_create_logical_model_select_permission", "args": {"source": "default", "name": "EnvioMeta", "role": "public", "permission": {"columns": "*", "filter": {}}}}`,
260
- },
261
- ~client=Rest.client(endpoint),
262
- )
263
- let msg = switch result {
264
- | QuerySucceeded => `Hasura _meta public select permission created`
265
- | AlreadyDone => `Hasura _meta public select permission already exists`
266
- }
267
- Logging.trace({
268
- "msg": msg,
269
- })
270
-
271
- let result = await rawBodyRoute->Rest.fetch(
272
- {
273
- "auth": auth,
274
- "bodyString": `{"type": "pg_track_logical_model","args": {"source": "default","name":"chain_metadata","fields":[{"name":"block_height","type":"int"},{"name":"chain_id","type":"int"},{"name":"end_block","type":"int"},{"name":"first_event_block_number","type":"int"},{"name":"is_hyper_sync","type":"boolean"},{"name":"latest_fetched_block_number","type":"int"},{"name":"latest_processed_block","type":"int"},{"name":"num_batches_fetched","type":"int"},{"name":"num_events_processed","type":"int"},{"name":"start_block","type":"int"},{"name":"timestamp_caught_up_to_head_or_endblock","type":"timestamptz"}]}}`,
275
- },
276
- ~client=Rest.client(endpoint),
277
- )
278
- let msg = switch result {
279
- | QuerySucceeded => `Hasura chain_metadata logical model created`
280
- | AlreadyDone => `Hasura chain_metadata logical model already created`
281
- }
282
- Logging.trace({
283
- "msg": msg,
284
- })
285
-
286
- // Need this to keep backwards compatibility,
287
- // since it's used on Hosted Service
288
- let result = await rawBodyRoute->Rest.fetch(
289
- {
290
- "auth": auth,
291
- "bodyString": `{"type":"pg_track_native_query","args":{"type":"query","source":"default","root_field_name":"chain_metadata","arguments":{},"returns":"chain_metadata","code":"SELECT \\\"${(#source_block: InternalTable.Chains.field :> string)}\\\" AS \\\"block_height\\\", \\\"${(#id: InternalTable.Chains.field :> string)}\\\" AS \\\"chain_id\\\", \\\"${(#end_block: InternalTable.Chains.field :> string)}\\\", \\\"${(#first_event_block: InternalTable.Chains.field :> string)}\\\" AS \\\"first_event_block_number\\\", \\\"${(#_is_hyper_sync: InternalTable.Chains.field :> string)}\\\" AS \\\"is_hyper_sync\\\", \\\"${(#buffer_block: InternalTable.Chains.field :> string)}\\\" AS \\\"latest_fetched_block_number\\\", \\\"${(#_latest_processed_block: InternalTable.Chains.field :> string)}\\\" AS \\\"latest_processed_block\\\", \\\"${(#_num_batches_fetched: InternalTable.Chains.field :> string)}\\\" AS \\\"num_batches_fetched\\\", \\\"${(#events_processed: InternalTable.Chains.field :> string)}\\\" AS \\\"num_events_processed\\\", \\\"${(#start_block: InternalTable.Chains.field :> string)}\\\", \\\"${(#ready_at: InternalTable.Chains.field :> string)}\\\" AS \\\"timestamp_caught_up_to_head_or_endblock\\\" FROM \\\"${pgSchema}\\\".\\\"${InternalTable.Chains.table.tableName}\\\""}}`,
292
- },
293
- ~client=Rest.client(endpoint),
294
- )
295
- let msg = switch result {
296
- | QuerySucceeded => `Hasura chain_metadata native query created`
297
- | AlreadyDone => `Hasura chain_metadata native query already created`
298
- }
299
- Logging.trace({
300
- "msg": msg,
301
- })
302
-
303
- // Add public select permissions for chain_metadata logical model
304
- let result = await rawBodyRoute->Rest.fetch(
305
- {
306
- "auth": auth,
307
- "bodyString": `{"type": "pg_create_logical_model_select_permission", "args": {"source": "default", "name": "chain_metadata", "role": "public", "permission": {"columns": "*", "filter": {}}}}`,
308
- },
309
- ~client=Rest.client(endpoint),
310
- )
311
- let msg = switch result {
312
- | QuerySucceeded => `Hasura chain_metadata public select permission created`
313
- | AlreadyDone => `Hasura chain_metadata public select permission already exists`
314
- }
315
- Logging.trace({
316
- "msg": msg,
317
- })
318
- } catch {
319
- | exn =>
320
- Logging.error({
321
- "msg": `EE808: There was an issue setting up _meta field in hasura - indexing may still work - but you may have issues querying the data in hasura.`,
322
- "err": exn->Utils.prettifyExn,
323
- })
324
- }
325
- }
326
-
327
221
  let trackDatabase = async (
328
222
  ~endpoint,
329
223
  ~auth,
@@ -340,7 +234,11 @@ let trackDatabase = async (
340
234
  InternalTable.EndOfBlockRangeScannedData.table.tableName,
341
235
  InternalTable.DynamicContractRegistry.table.tableName,
342
236
  ]
343
- let exposedInternalTableNames = [InternalTable.RawEvents.table.tableName]
237
+ let exposedInternalTableNames = [
238
+ InternalTable.RawEvents.table.tableName,
239
+ InternalTable.Views.metaViewName,
240
+ InternalTable.Views.chainMetadataViewName,
241
+ ]
344
242
  let userTableNames = userEntities->Js.Array2.map(entity => entity.table.tableName)
345
243
 
346
244
  Logging.info("Tracking tables in Hasura")
@@ -415,6 +313,4 @@ let trackDatabase = async (
415
313
  }),
416
314
  )
417
315
  ->Promise.all
418
-
419
- await trackMeta(~auth, ~endpoint, ~pgSchema)
420
316
  }
package/src/Hasura.res.js CHANGED
@@ -204,72 +204,6 @@ async function createEntityRelationship(pgSchema, endpoint, auth, tableName, rel
204
204
  }
205
205
  }
206
206
 
207
- async function trackMeta(auth, endpoint, pgSchema) {
208
- try {
209
- var result = await Rest.$$fetch(rawBodyRoute, {
210
- auth: auth,
211
- bodyString: "{\"type\": \"pg_track_logical_model\",\"args\": {\"source\": \"default\",\"name\":\"EnvioMeta\",\"fields\":[{\"name\":\"chainId\",\"type\":\"int\"},{\"name\":\"startBlock\",\"type\":\"int\"},{\"name\":\"endBlock\",\"type\":\"int\",\"nullable\":true},{\"name\":\"bufferBlock\",\"type\":\"int\"},{\"name\":\"readyAt\",\"type\":\"timestamptz\",\"nullable\":true},{\"name\":\"firstEventBlock\",\"type\":\"int\",\"nullable\":true},{\"name\":\"eventsProcessed\",\"type\":\"int\"},{\"name\":\"isReady\",\"type\":\"bool\"}]}}"
212
- }, Rest.client(endpoint, undefined));
213
- var msg;
214
- msg = result === "QuerySucceeded" ? "Hasura EnvioMeta logical model created" : "Hasura EnvioMeta logical model already created";
215
- Logging.trace({
216
- msg: msg
217
- });
218
- var result$1 = await Rest.$$fetch(rawBodyRoute, {
219
- auth: auth,
220
- bodyString: "{\"type\":\"pg_track_native_query\",\"args\":{\"type\":\"query\",\"source\":\"default\",\"root_field_name\":\"_meta\",\"arguments\":{},\"returns\":\"EnvioMeta\",\"code\":\"SELECT \\\"" + "id" + "\\\" AS \\\"chainId\\\", \\\"" + "start_block" + "\\\" AS \\\"startBlock\\\", \\\"" + "end_block" + "\\\" AS \\\"endBlock\\\", \\\"" + "buffer_block" + "\\\" AS \\\"bufferBlock\\\", \\\"" + "ready_at" + "\\\" AS \\\"readyAt\\\", \\\"" + "first_event_block" + "\\\" AS \\\"firstEventBlock\\\", \\\"" + "events_processed" + "\\\" AS \\\"eventsProcessed\\\", (\\\"" + "ready_at" + "\\\" IS NOT NULL) AS \\\"isReady\\\" FROM \\\"" + pgSchema + "\\\".\\\"" + InternalTable.Chains.table.tableName + "\\\" ORDER BY \\\"id\\\"\"}}"
221
- }, Rest.client(endpoint, undefined));
222
- var msg$1;
223
- msg$1 = result$1 === "QuerySucceeded" ? "Hasura _meta native query created" : "Hasura _meta native query already created";
224
- Logging.trace({
225
- msg: msg$1
226
- });
227
- var result$2 = await Rest.$$fetch(rawBodyRoute, {
228
- auth: auth,
229
- bodyString: "{\"type\": \"pg_create_logical_model_select_permission\", \"args\": {\"source\": \"default\", \"name\": \"EnvioMeta\", \"role\": \"public\", \"permission\": {\"columns\": \"*\", \"filter\": {}}}}"
230
- }, Rest.client(endpoint, undefined));
231
- var msg$2;
232
- msg$2 = result$2 === "QuerySucceeded" ? "Hasura _meta public select permission created" : "Hasura _meta public select permission already exists";
233
- Logging.trace({
234
- msg: msg$2
235
- });
236
- var result$3 = await Rest.$$fetch(rawBodyRoute, {
237
- auth: auth,
238
- bodyString: "{\"type\": \"pg_track_logical_model\",\"args\": {\"source\": \"default\",\"name\":\"chain_metadata\",\"fields\":[{\"name\":\"block_height\",\"type\":\"int\"},{\"name\":\"chain_id\",\"type\":\"int\"},{\"name\":\"end_block\",\"type\":\"int\"},{\"name\":\"first_event_block_number\",\"type\":\"int\"},{\"name\":\"is_hyper_sync\",\"type\":\"boolean\"},{\"name\":\"latest_fetched_block_number\",\"type\":\"int\"},{\"name\":\"latest_processed_block\",\"type\":\"int\"},{\"name\":\"num_batches_fetched\",\"type\":\"int\"},{\"name\":\"num_events_processed\",\"type\":\"int\"},{\"name\":\"start_block\",\"type\":\"int\"},{\"name\":\"timestamp_caught_up_to_head_or_endblock\",\"type\":\"timestamptz\"}]}}"
239
- }, Rest.client(endpoint, undefined));
240
- var msg$3;
241
- msg$3 = result$3 === "QuerySucceeded" ? "Hasura chain_metadata logical model created" : "Hasura chain_metadata logical model already created";
242
- Logging.trace({
243
- msg: msg$3
244
- });
245
- var result$4 = await Rest.$$fetch(rawBodyRoute, {
246
- auth: auth,
247
- bodyString: "{\"type\":\"pg_track_native_query\",\"args\":{\"type\":\"query\",\"source\":\"default\",\"root_field_name\":\"chain_metadata\",\"arguments\":{},\"returns\":\"chain_metadata\",\"code\":\"SELECT \\\"" + "source_block" + "\\\" AS \\\"block_height\\\", \\\"" + "id" + "\\\" AS \\\"chain_id\\\", \\\"" + "end_block" + "\\\", \\\"" + "first_event_block" + "\\\" AS \\\"first_event_block_number\\\", \\\"" + "_is_hyper_sync" + "\\\" AS \\\"is_hyper_sync\\\", \\\"" + "buffer_block" + "\\\" AS \\\"latest_fetched_block_number\\\", \\\"" + "_latest_processed_block" + "\\\" AS \\\"latest_processed_block\\\", \\\"" + "_num_batches_fetched" + "\\\" AS \\\"num_batches_fetched\\\", \\\"" + "events_processed" + "\\\" AS \\\"num_events_processed\\\", \\\"" + "start_block" + "\\\", \\\"" + "ready_at" + "\\\" AS \\\"timestamp_caught_up_to_head_or_endblock\\\" FROM \\\"" + pgSchema + "\\\".\\\"" + InternalTable.Chains.table.tableName + "\\\"\"}}"
248
- }, Rest.client(endpoint, undefined));
249
- var msg$4;
250
- msg$4 = result$4 === "QuerySucceeded" ? "Hasura chain_metadata native query created" : "Hasura chain_metadata native query already created";
251
- Logging.trace({
252
- msg: msg$4
253
- });
254
- var result$5 = await Rest.$$fetch(rawBodyRoute, {
255
- auth: auth,
256
- bodyString: "{\"type\": \"pg_create_logical_model_select_permission\", \"args\": {\"source\": \"default\", \"name\": \"chain_metadata\", \"role\": \"public\", \"permission\": {\"columns\": \"*\", \"filter\": {}}}}"
257
- }, Rest.client(endpoint, undefined));
258
- var msg$5;
259
- msg$5 = result$5 === "QuerySucceeded" ? "Hasura chain_metadata public select permission created" : "Hasura chain_metadata public select permission already exists";
260
- return Logging.trace({
261
- msg: msg$5
262
- });
263
- }
264
- catch (raw_exn){
265
- var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
266
- return Logging.error({
267
- msg: "EE808: There was an issue setting up _meta field in hasura - indexing may still work - but you may have issues querying the data in hasura.",
268
- err: Utils.prettifyExn(exn)
269
- });
270
- }
271
- }
272
-
273
207
  async function trackDatabase(endpoint, auth, pgSchema, userEntities, aggregateEntities, responseLimit, schema) {
274
208
  var trackOnlyInternalTableNames = [
275
209
  InternalTable.Chains.table.tableName,
@@ -278,7 +212,11 @@ async function trackDatabase(endpoint, auth, pgSchema, userEntities, aggregateEn
278
212
  InternalTable.EndOfBlockRangeScannedData.table.tableName,
279
213
  InternalTable.DynamicContractRegistry.table.tableName
280
214
  ];
281
- var exposedInternalTableNames = [InternalTable.RawEvents.table.tableName];
215
+ var exposedInternalTableNames = [
216
+ InternalTable.RawEvents.table.tableName,
217
+ InternalTable.Views.metaViewName,
218
+ InternalTable.Views.chainMetadataViewName
219
+ ];
282
220
  var userTableNames = userEntities.map(function (entity) {
283
221
  return entity.table.tableName;
284
222
  });
@@ -308,7 +246,6 @@ async function trackDatabase(endpoint, auth, pgSchema, userEntities, aggregateEn
308
246
  })
309
247
  ].flat(1);
310
248
  })]));
311
- return await trackMeta(auth, endpoint, pgSchema);
312
249
  }
313
250
 
314
251
  exports.auth = auth;
@@ -321,6 +258,5 @@ exports.clearHasuraMetadata = clearHasuraMetadata;
321
258
  exports.trackTables = trackTables;
322
259
  exports.createSelectPermissions = createSelectPermissions;
323
260
  exports.createEntityRelationship = createEntityRelationship;
324
- exports.trackMeta = trackMeta;
325
261
  exports.trackDatabase = trackDatabase;
326
262
  /* Rest Not a pure module */
package/src/PgStorage.res CHANGED
@@ -140,6 +140,10 @@ GRANT ALL ON SCHEMA "${pgSchema}" TO public;`,
140
140
  })
141
141
  })
142
142
 
143
+ // Create views for Hasura integration
144
+ query := query.contents ++ "\n" ++ InternalTable.Views.makeMetaViewQuery(~pgSchema)
145
+ query := query.contents ++ "\n" ++ InternalTable.Views.makeChainMetadataViewQuery(~pgSchema)
146
+
143
147
  // Populate initial chain data
144
148
  switch InternalTable.Chains.makeInitialValuesQuery(~pgSchema, ~chainConfigs) {
145
149
  | Some(initialChainsValuesQuery) => query := query.contents ++ "\n" ++ initialChainsValuesQuery
@@ -686,7 +690,9 @@ let make = (
686
690
  )
687
691
  // Execute all queries within a single transaction for integrity
688
692
  let _ = await sql->Postgres.beginSql(sql => {
689
- queries->Js.Array2.map(query => sql->Postgres.unsafe(query))
693
+ // Promise.all might be not safe to use here,
694
+ // but it's just how it worked before.
695
+ Promise.all(queries->Js.Array2.map(query => sql->Postgres.unsafe(query)))
690
696
  })
691
697
 
692
698
  let cache = await restoreEffectCache(~withUpload=true)
@@ -121,6 +121,8 @@ function makeInitializeTransaction(pgSchema, pgUser, chainConfigsOpt, entitiesOp
121
121
  query.contents = query.contents + "\n" + makeCreateIndexQuery(derivedFromField.derivedFromEntity, [indexField], pgSchema);
122
122
  });
123
123
  });
124
+ query.contents = query.contents + "\n" + InternalTable.Views.makeMetaViewQuery(pgSchema);
125
+ query.contents = query.contents + "\n" + InternalTable.Views.makeChainMetadataViewQuery(pgSchema);
124
126
  var initialChainsValuesQuery = InternalTable.Chains.makeInitialValuesQuery(pgSchema, chainConfigs);
125
127
  if (initialChainsValuesQuery !== undefined) {
126
128
  query.contents = query.contents + "\n" + initialChainsValuesQuery;
@@ -486,9 +488,9 @@ function make(sql, pgHost, pgSchema, pgPort, pgUser, pgDatabase, pgPassword, onI
486
488
  }
487
489
  var queries = makeInitializeTransaction(pgSchema, pgUser, chainConfigs, entities, enums, Utils.$$Array.isEmpty(schemaTableNames));
488
490
  await sql.begin(function (sql) {
489
- return queries.map(function (query) {
490
- return sql.unsafe(query);
491
- });
491
+ return Promise.all(queries.map(function (query) {
492
+ return sql.unsafe(query);
493
+ }));
492
494
  });
493
495
  var cache = await restoreEffectCache(true);
494
496
  if (onInitialize !== undefined) {
@@ -89,7 +89,7 @@ type poolConfig = {
89
89
  @module
90
90
  external makeSql: (~config: poolConfig) => sql = "postgres"
91
91
 
92
- @send external beginSql: (sql, sql => array<promise<unit>>) => promise<unit> = "begin"
92
+ @send external beginSql: (sql, sql => promise<'result>) => promise<'result> = "begin"
93
93
 
94
94
  // TODO: can explore this approach (https://forum.rescript-lang.org/t/rfc-support-for-tagged-template-literals/3744)
95
95
  // @send @variadic
@@ -325,6 +325,44 @@ module RawEvents = {
325
325
  )
326
326
  }
327
327
 
328
+ // View names for Hasura integration
329
+ module Views = {
330
+ let metaViewName = "_meta"
331
+ let chainMetadataViewName = "chain_metadata"
332
+
333
+ let makeMetaViewQuery = (~pgSchema) => {
334
+ `CREATE VIEW "${pgSchema}"."${metaViewName}" AS
335
+ SELECT
336
+ "${(#id: Chains.field :> string)}" AS "chainId",
337
+ "${(#start_block: Chains.field :> string)}" AS "startBlock",
338
+ "${(#end_block: Chains.field :> string)}" AS "endBlock",
339
+ "${(#buffer_block: Chains.field :> string)}" AS "bufferBlock",
340
+ "${(#ready_at: Chains.field :> string)}" AS "readyAt",
341
+ "${(#first_event_block: Chains.field :> string)}" AS "firstEventBlock",
342
+ "${(#events_processed: Chains.field :> string)}" AS "eventsProcessed",
343
+ ("${(#ready_at: Chains.field :> string)}" IS NOT NULL) AS "isReady"
344
+ FROM "${pgSchema}"."${Chains.table.tableName}"
345
+ ORDER BY "${(#id: Chains.field :> string)}";`
346
+ }
347
+
348
+ let makeChainMetadataViewQuery = (~pgSchema) => {
349
+ `CREATE VIEW "${pgSchema}"."${chainMetadataViewName}" AS
350
+ SELECT
351
+ "${(#source_block: Chains.field :> string)}" AS "block_height",
352
+ "${(#id: Chains.field :> string)}" AS "chain_id",
353
+ "${(#end_block: Chains.field :> string)}" AS "end_block",
354
+ "${(#first_event_block: Chains.field :> string)}" AS "first_event_block_number",
355
+ "${(#_is_hyper_sync: Chains.field :> string)}" AS "is_hyper_sync",
356
+ "${(#buffer_block: Chains.field :> string)}" AS "latest_fetched_block_number",
357
+ "${(#_latest_processed_block: Chains.field :> string)}" AS "latest_processed_block",
358
+ "${(#_num_batches_fetched: Chains.field :> string)}" AS "num_batches_fetched",
359
+ "${(#events_processed: Chains.field :> string)}" AS "num_events_processed",
360
+ "${(#start_block: Chains.field :> string)}" AS "start_block",
361
+ "${(#ready_at: Chains.field :> string)}" AS "timestamp_caught_up_to_head_or_endblock"
362
+ FROM "${pgSchema}"."${Chains.table.tableName}";`
363
+ }
364
+ }
365
+
328
366
  module DynamicContractRegistry = {
329
367
  let name = "dynamic_contract_registry"
330
368
 
@@ -221,6 +221,25 @@ var RawEvents = {
221
221
  table: table$4
222
222
  };
223
223
 
224
+ var metaViewName = "_meta";
225
+
226
+ var chainMetadataViewName = "chain_metadata";
227
+
228
+ function makeMetaViewQuery(pgSchema) {
229
+ return "CREATE VIEW \"" + pgSchema + "\".\"" + metaViewName + "\" AS \n SELECT \n \"" + "id" + "\" AS \"chainId\",\n \"" + "start_block" + "\" AS \"startBlock\", \n \"" + "end_block" + "\" AS \"endBlock\",\n \"" + "buffer_block" + "\" AS \"bufferBlock\",\n \"" + "ready_at" + "\" AS \"readyAt\",\n \"" + "first_event_block" + "\" AS \"firstEventBlock\",\n \"" + "events_processed" + "\" AS \"eventsProcessed\",\n (\"" + "ready_at" + "\" IS NOT NULL) AS \"isReady\"\n FROM \"" + pgSchema + "\".\"" + table$1.tableName + "\"\n ORDER BY \"" + "id" + "\";";
230
+ }
231
+
232
+ function makeChainMetadataViewQuery(pgSchema) {
233
+ return "CREATE VIEW \"" + pgSchema + "\".\"" + chainMetadataViewName + "\" AS \n SELECT \n \"" + "source_block" + "\" AS \"block_height\",\n \"" + "id" + "\" AS \"chain_id\",\n \"" + "end_block" + "\" AS \"end_block\", \n \"" + "first_event_block" + "\" AS \"first_event_block_number\",\n \"" + "_is_hyper_sync" + "\" AS \"is_hyper_sync\",\n \"" + "buffer_block" + "\" AS \"latest_fetched_block_number\",\n \"" + "_latest_processed_block" + "\" AS \"latest_processed_block\",\n \"" + "_num_batches_fetched" + "\" AS \"num_batches_fetched\",\n \"" + "events_processed" + "\" AS \"num_events_processed\",\n \"" + "start_block" + "\" AS \"start_block\",\n \"" + "ready_at" + "\" AS \"timestamp_caught_up_to_head_or_endblock\"\n FROM \"" + pgSchema + "\".\"" + table$1.tableName + "\";";
234
+ }
235
+
236
+ var Views = {
237
+ metaViewName: metaViewName,
238
+ chainMetadataViewName: chainMetadataViewName,
239
+ makeMetaViewQuery: makeMetaViewQuery,
240
+ makeChainMetadataViewQuery: makeChainMetadataViewQuery
241
+ };
242
+
224
243
  var name = "dynamic_contract_registry";
225
244
 
226
245
  function makeId(chainId, contractAddress) {
@@ -291,5 +310,6 @@ exports.Chains = Chains;
291
310
  exports.PersistedState = PersistedState;
292
311
  exports.EndOfBlockRangeScannedData = EndOfBlockRangeScannedData;
293
312
  exports.RawEvents = RawEvents;
313
+ exports.Views = Views;
294
314
  exports.DynamicContractRegistry = DynamicContractRegistry;
295
315
  /* table Not a pure module */