envio 2.27.6 → 2.28.0-alpha.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "envio",
3
- "version": "v2.27.6",
3
+ "version": "v2.28.0-alpha.1",
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.27.6",
29
- "envio-linux-arm64": "v2.27.6",
30
- "envio-darwin-x64": "v2.27.6",
31
- "envio-darwin-arm64": "v2.27.6"
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"
32
32
  },
33
33
  "dependencies": {
34
34
  "@envio-dev/hypersync-client": "0.6.5",
package/rescript.json CHANGED
@@ -13,6 +13,9 @@
13
13
  "in-source": true
14
14
  },
15
15
  "gentypeconfig": {
16
+ "shims": {
17
+ "Js": "Js"
18
+ },
16
19
  "generatedFileExtension": ".gen.ts"
17
20
  },
18
21
  "bs-dependencies": ["rescript-schema"],
package/src/Hasura.res CHANGED
@@ -218,28 +218,149 @@ 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
+
221
327
  let trackDatabase = async (
222
328
  ~endpoint,
223
329
  ~auth,
224
330
  ~pgSchema,
225
- ~allStaticTables,
226
- ~allEntityTables,
331
+ ~userEntities: array<Internal.entityConfig>,
227
332
  ~aggregateEntities,
228
333
  ~responseLimit,
229
334
  ~schema,
230
335
  ) => {
336
+ let trackOnlyInternalTableNames = [
337
+ InternalTable.Chains.table.tableName,
338
+ InternalTable.EventSyncState.table.tableName,
339
+ InternalTable.PersistedState.table.tableName,
340
+ InternalTable.EndOfBlockRangeScannedData.table.tableName,
341
+ InternalTable.DynamicContractRegistry.table.tableName,
342
+ ]
343
+ let exposedInternalTableNames = [InternalTable.RawEvents.table.tableName]
344
+ let userTableNames = userEntities->Js.Array2.map(entity => entity.table.tableName)
345
+
231
346
  Logging.info("Tracking tables in Hasura")
232
347
 
233
348
  let _ = await clearHasuraMetadata(~endpoint, ~auth)
234
- let tableNames =
235
- [allStaticTables, allEntityTables]
236
- ->Belt.Array.concatMany
237
- ->Js.Array2.map(({tableName}: Table.table) => tableName)
238
349
 
239
- await trackTables(~endpoint, ~auth, ~pgSchema, ~tableNames)
350
+ await trackTables(
351
+ ~endpoint,
352
+ ~auth,
353
+ ~pgSchema,
354
+ ~tableNames=[
355
+ exposedInternalTableNames,
356
+ trackOnlyInternalTableNames,
357
+ userTableNames,
358
+ ]->Belt.Array.concatMany,
359
+ )
240
360
 
241
361
  let _ =
242
- await tableNames
362
+ await [exposedInternalTableNames, userTableNames]
363
+ ->Belt.Array.concatMany
243
364
  ->Js.Array2.map(tableName =>
244
365
  createSelectPermissions(
245
366
  ~endpoint,
@@ -251,11 +372,11 @@ let trackDatabase = async (
251
372
  )
252
373
  )
253
374
  ->Js.Array2.concatMany(
254
- allEntityTables->Js.Array2.map(table => {
255
- let {tableName} = table
375
+ userEntities->Js.Array2.map(entityConfig => {
376
+ let {tableName} = entityConfig.table
256
377
  [
257
378
  //Set array relationships
258
- table
379
+ entityConfig.table
259
380
  ->Table.getDerivedFromFields
260
381
  ->Js.Array2.map(derivedFromField => {
261
382
  //determines the actual name of the underlying relational field (if it's an entity mapping then suffixes _id for eg.)
@@ -275,7 +396,7 @@ let trackDatabase = async (
275
396
  )
276
397
  }),
277
398
  //Set object relationships
278
- table
399
+ entityConfig.table
279
400
  ->Table.getLinkedEntityFields
280
401
  ->Js.Array2.map(((field, linkedEntityName)) => {
281
402
  createEntityRelationship(
@@ -294,4 +415,6 @@ let trackDatabase = async (
294
415
  }),
295
416
  )
296
417
  ->Promise.all
418
+
419
+ await trackMeta(~auth, ~endpoint, ~pgSchema)
297
420
  }
package/src/Hasura.res.js CHANGED
@@ -7,6 +7,7 @@ var Utils = require("./Utils.res.js");
7
7
  var Schema = require("./db/Schema.res.js");
8
8
  var Logging = require("./Logging.res.js");
9
9
  var Belt_Array = require("rescript/lib/js/belt_Array.js");
10
+ var InternalTable = require("./db/InternalTable.res.js");
10
11
  var Caml_splice_call = require("rescript/lib/js/caml_splice_call.js");
11
12
  var S$RescriptSchema = require("rescript-schema/src/S.res.js");
12
13
  var Caml_js_exceptions = require("rescript/lib/js/caml_js_exceptions.js");
@@ -203,31 +204,111 @@ async function createEntityRelationship(pgSchema, endpoint, auth, tableName, rel
203
204
  }
204
205
  }
205
206
 
206
- async function trackDatabase(endpoint, auth, pgSchema, allStaticTables, allEntityTables, aggregateEntities, responseLimit, schema) {
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
+ async function trackDatabase(endpoint, auth, pgSchema, userEntities, aggregateEntities, responseLimit, schema) {
274
+ var trackOnlyInternalTableNames = [
275
+ InternalTable.Chains.table.tableName,
276
+ InternalTable.EventSyncState.table.tableName,
277
+ InternalTable.PersistedState.table.tableName,
278
+ InternalTable.EndOfBlockRangeScannedData.table.tableName,
279
+ InternalTable.DynamicContractRegistry.table.tableName
280
+ ];
281
+ var exposedInternalTableNames = [InternalTable.RawEvents.table.tableName];
282
+ var userTableNames = userEntities.map(function (entity) {
283
+ return entity.table.tableName;
284
+ });
207
285
  Logging.info("Tracking tables in Hasura");
208
286
  await clearHasuraMetadata(endpoint, auth);
209
- var tableNames = Belt_Array.concatMany([
210
- allStaticTables,
211
- allEntityTables
212
- ]).map(function (param) {
213
- return param.tableName;
214
- });
215
- await trackTables(endpoint, auth, pgSchema, tableNames);
216
- await Promise.all(Caml_splice_call.spliceObjApply(tableNames.map(function (tableName) {
287
+ await trackTables(endpoint, auth, pgSchema, Belt_Array.concatMany([
288
+ exposedInternalTableNames,
289
+ trackOnlyInternalTableNames,
290
+ userTableNames
291
+ ]));
292
+ await Promise.all(Caml_splice_call.spliceObjApply(Belt_Array.concatMany([
293
+ exposedInternalTableNames,
294
+ userTableNames
295
+ ]).map(function (tableName) {
217
296
  return createSelectPermissions(auth, endpoint, tableName, pgSchema, responseLimit, aggregateEntities);
218
- }), "concat", [allEntityTables.map(function (table) {
219
- var tableName = table.tableName;
297
+ }), "concat", [userEntities.map(function (entityConfig) {
298
+ var match = entityConfig.table;
299
+ var tableName = match.tableName;
220
300
  return [
221
- Table.getDerivedFromFields(table).map(function (derivedFromField) {
301
+ Table.getDerivedFromFields(entityConfig.table).map(function (derivedFromField) {
222
302
  var relationalFieldName = Utils.unwrapResultExn(Schema.getDerivedFromFieldName(schema, derivedFromField));
223
303
  return createEntityRelationship(pgSchema, endpoint, auth, tableName, "array", relationalFieldName, derivedFromField.fieldName, derivedFromField.derivedFromEntity, true);
224
304
  }),
225
- Table.getLinkedEntityFields(table).map(function (param) {
305
+ Table.getLinkedEntityFields(entityConfig.table).map(function (param) {
226
306
  var field = param[0];
227
307
  return createEntityRelationship(pgSchema, endpoint, auth, tableName, "object", field.fieldName, field.fieldName, param[1], false);
228
308
  })
229
309
  ].flat(1);
230
310
  })]));
311
+ return await trackMeta(auth, endpoint, pgSchema);
231
312
  }
232
313
 
233
314
  exports.auth = auth;
@@ -240,5 +321,6 @@ exports.clearHasuraMetadata = clearHasuraMetadata;
240
321
  exports.trackTables = trackTables;
241
322
  exports.createSelectPermissions = createSelectPermissions;
242
323
  exports.createEntityRelationship = createEntityRelationship;
324
+ exports.trackMeta = trackMeta;
243
325
  exports.trackDatabase = trackDatabase;
244
326
  /* Rest Not a pure module */
package/src/Internal.res CHANGED
@@ -176,13 +176,16 @@ let fuelTransferParamsSchema = S.schema(s => {
176
176
  })
177
177
 
178
178
  type entity = private {id: string}
179
- type entityConfig = {
179
+ type genericEntityConfig<'entity> = {
180
180
  name: string,
181
- schema: S.t<entity>,
182
- rowsSchema: S.t<array<entity>>,
181
+ schema: S.t<'entity>,
182
+ rowsSchema: S.t<array<'entity>>,
183
183
  table: Table.table,
184
- entityHistory: EntityHistory.t<entity>,
184
+ entityHistory: EntityHistory.t<'entity>,
185
185
  }
186
+ type entityConfig = genericEntityConfig<entity>
187
+ external fromGenericEntityConfig: genericEntityConfig<'entity> => entityConfig = "%identity"
188
+
186
189
  type enum
187
190
  type enumConfig<'enum> = {
188
191
  name: string,
@@ -0,0 +1,20 @@
1
+ // TODO: rename the file to Config.res after finishing the migration from codegen
2
+ // And turn it into PublicConfig instead
3
+ // For internal use we should create Indexer.res with a stateful type
4
+
5
+ type contract = {
6
+ name: string,
7
+ abi: EvmTypes.Abi.t,
8
+ addresses: array<Address.t>,
9
+ events: array<Internal.eventConfig>,
10
+ startBlock: option<int>,
11
+ }
12
+
13
+ type chain = {
14
+ id: int,
15
+ startBlock: int,
16
+ endBlock?: int,
17
+ confirmedBlockThreshold: int,
18
+ contracts: array<contract>,
19
+ sources: array<Source.t>,
20
+ }
@@ -0,0 +1,2 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
package/src/Js.shim.ts ADDED
@@ -0,0 +1,11 @@
1
+ export type Json_t =
2
+ | string
3
+ | boolean
4
+ | number
5
+ | null
6
+ | { [key: string]: Json_t }
7
+ | Json_t[];
8
+
9
+ export type t = unknown;
10
+
11
+ export type Exn_t = Error;
@@ -66,9 +66,10 @@ let schedule = async loadManager => {
66
66
  }
67
67
  })
68
68
 
69
- if inputsToLoad->Utils.Array.isEmpty->not {
69
+ let isSuccess = if inputsToLoad->Utils.Array.isEmpty->not {
70
70
  try {
71
71
  await group.load(inputsToLoad)
72
+ true
72
73
  } catch {
73
74
  | exn => {
74
75
  let exn = exn->Utils.prettifyExn
@@ -76,16 +77,21 @@ let schedule = async loadManager => {
76
77
  let call = calls->Js.Dict.unsafeGet(inputKey)
77
78
  call.reject(exn)
78
79
  })
80
+ false
79
81
  }
80
82
  }
83
+ } else {
84
+ true
81
85
  }
82
86
 
83
87
  if currentInputKeys->Utils.Array.isEmpty->not {
84
- currentInputKeys->Js.Array2.forEach(inputKey => {
85
- let call = calls->Js.Dict.unsafeGet(inputKey)
86
- calls->Utils.Dict.deleteInPlace(inputKey)
87
- call.resolve(group.getUnsafeInMemory(inputKey))
88
- })
88
+ if isSuccess {
89
+ currentInputKeys->Js.Array2.forEach(inputKey => {
90
+ let call = calls->Js.Dict.unsafeGet(inputKey)
91
+ calls->Utils.Dict.deleteInPlace(inputKey)
92
+ call.resolve(group.getUnsafeInMemory(inputKey))
93
+ })
94
+ }
89
95
 
90
96
  // Clean up executed batch to reset
91
97
  // provided load function which
@@ -40,9 +40,13 @@ async function schedule(loadManager) {
40
40
  }
41
41
 
42
42
  });
43
- if (!Utils.$$Array.isEmpty(inputsToLoad)) {
43
+ var isSuccess;
44
+ if (Utils.$$Array.isEmpty(inputsToLoad)) {
45
+ isSuccess = true;
46
+ } else {
44
47
  try {
45
48
  await group.load(inputsToLoad);
49
+ isSuccess = true;
46
50
  }
47
51
  catch (raw_exn){
48
52
  var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
@@ -51,16 +55,19 @@ async function schedule(loadManager) {
51
55
  var call = calls[inputKey];
52
56
  call.reject(exn$1);
53
57
  }));
58
+ isSuccess = false;
54
59
  }
55
60
  }
56
61
  if (Utils.$$Array.isEmpty(currentInputKeys)) {
57
62
  return ;
58
63
  }
59
- currentInputKeys.forEach(function (inputKey) {
60
- var call = calls[inputKey];
61
- Utils.Dict.deleteInPlace(calls, inputKey);
62
- call.resolve(group.getUnsafeInMemory(inputKey));
63
- });
64
+ if (isSuccess) {
65
+ currentInputKeys.forEach(function (inputKey) {
66
+ var call = calls[inputKey];
67
+ Utils.Dict.deleteInPlace(calls, inputKey);
68
+ call.resolve(group.getUnsafeInMemory(inputKey));
69
+ });
70
+ }
64
71
  var latestGroup = groups[key];
65
72
  if (Utils.$$Array.isEmpty(Object.keys(latestGroup.calls))) {
66
73
  return Utils.Dict.deleteInPlace(groups, key);
@@ -13,6 +13,12 @@ type effectCacheRecord = {
13
13
  mutable count: int,
14
14
  }
15
15
 
16
+ type initialState = {
17
+ cleanRun: bool,
18
+ cache: dict<effectCacheRecord>,
19
+ chains: array<InternalTable.Chains.t>,
20
+ }
21
+
16
22
  type operator = [#">" | #"="]
17
23
 
18
24
  type storage = {
@@ -22,10 +28,11 @@ type storage = {
22
28
  // Should initialize the storage so we can start interacting with it
23
29
  // Eg create connection, schema, tables, etc.
24
30
  initialize: (
31
+ ~chainConfigs: array<InternalConfig.chain>=?,
25
32
  ~entities: array<Internal.entityConfig>=?,
26
- ~generalTables: array<Table.table>=?,
27
33
  ~enums: array<Internal.enumConfig<Internal.enum>>=?,
28
- ) => promise<unit>,
34
+ ) => promise<initialState>,
35
+ loadInitialState: unit => promise<initialState>,
29
36
  @raises("StorageError")
30
37
  loadByIdsOrThrow: 'item. (
31
38
  ~ids: array<string>,
@@ -55,10 +62,6 @@ type storage = {
55
62
  ) => promise<unit>,
56
63
  // This is to download cache from the database to .envio/cache
57
64
  dumpEffectCache: unit => promise<unit>,
58
- // This is not good, but the function does two things:
59
- // - Gets info about existing cache tables
60
- // - if withUpload is true, it also populates the cache from .envio/cache to the database
61
- restoreEffectCache: (~withUpload: bool) => promise<array<effectCacheRecord>>,
62
65
  }
63
66
 
64
67
  exception StorageError({message: string, reason: exn})
@@ -66,11 +69,10 @@ exception StorageError({message: string, reason: exn})
66
69
  type storageStatus =
67
70
  | Unknown
68
71
  | Initializing(promise<unit>)
69
- | Ready({cleanRun: bool, cache: dict<effectCacheRecord>})
72
+ | Ready(initialState)
70
73
 
71
74
  type t = {
72
75
  userEntities: array<Internal.entityConfig>,
73
- staticTables: array<Table.table>,
74
76
  allEntities: array<Internal.entityConfig>,
75
77
  allEnums: array<Internal.enumConfig<Internal.enum>>,
76
78
  mutable storageStatus: storageStatus,
@@ -86,18 +88,15 @@ let entityHistoryActionEnumConfig: Internal.enumConfig<EntityHistory.RowAction.t
86
88
 
87
89
  let make = (
88
90
  ~userEntities,
89
- ~dcRegistryEntityConfig,
90
91
  // TODO: Should only pass userEnums and create internal config in runtime
91
92
  ~allEnums,
92
- ~staticTables,
93
93
  ~storage,
94
94
  ) => {
95
- let allEntities = userEntities->Js.Array2.concat([dcRegistryEntityConfig])
95
+ let allEntities = userEntities->Js.Array2.concat([InternalTable.DynamicContractRegistry.config])
96
96
  let allEnums =
97
97
  allEnums->Js.Array2.concat([entityHistoryActionEnumConfig->Internal.fromGenericEnumConfig])
98
98
  {
99
99
  userEntities,
100
- staticTables,
101
100
  allEntities,
102
101
  allEnums,
103
102
  storageStatus: Unknown,
@@ -106,17 +105,7 @@ let make = (
106
105
  }
107
106
 
108
107
  let init = {
109
- let loadInitialCache = async (persistence, ~withUpload) => {
110
- let effectCacheRecords = await persistence.storage.restoreEffectCache(~withUpload)
111
- let cache = Js.Dict.empty()
112
- effectCacheRecords->Js.Array2.forEach(record => {
113
- Prometheus.EffectCacheCount.set(~count=record.count, ~effectName=record.effectName)
114
- cache->Js.Dict.set(record.effectName, record)
115
- })
116
- cache
117
- }
118
-
119
- async (persistence, ~reset=false) => {
108
+ async (persistence, ~chainConfigs, ~reset=false) => {
120
109
  try {
121
110
  let shouldRun = switch persistence.storageStatus {
122
111
  | Unknown => true
@@ -135,17 +124,14 @@ let init = {
135
124
  if reset || !(await persistence.storage.isInitialized()) {
136
125
  Logging.info(`Initializing the indexer storage...`)
137
126
 
138
- await persistence.storage.initialize(
127
+ let initialState = await persistence.storage.initialize(
139
128
  ~entities=persistence.allEntities,
140
- ~generalTables=persistence.staticTables,
141
129
  ~enums=persistence.allEnums,
130
+ ~chainConfigs,
142
131
  )
143
132
 
144
133
  Logging.info(`The indexer storage is ready. Uploading cache...`)
145
- persistence.storageStatus = Ready({
146
- cleanRun: true,
147
- cache: await loadInitialCache(persistence, ~withUpload=true),
148
- })
134
+ persistence.storageStatus = Ready(initialState)
149
135
  } else if (
150
136
  // In case of a race condition,
151
137
  // we want to set the initial status to Ready only once.
@@ -155,10 +141,7 @@ let init = {
155
141
  }
156
142
  ) {
157
143
  Logging.info(`The indexer storage is ready.`)
158
- persistence.storageStatus = Ready({
159
- cleanRun: false,
160
- cache: await loadInitialCache(persistence, ~withUpload=false),
161
- })
144
+ persistence.storageStatus = Ready(await persistence.storage.loadInitialState())
162
145
  }
163
146
  resolveRef.contents()
164
147
  }
@@ -178,6 +161,15 @@ let getInitializedStorageOrThrow = persistence => {
178
161
  }
179
162
  }
180
163
 
164
+ let getInitializedState = persistence => {
165
+ switch persistence.storageStatus {
166
+ | Unknown
167
+ | Initializing(_) =>
168
+ Js.Exn.raiseError(`Failed to access the initial state. The Persistence layer is not initialized.`)
169
+ | Ready(initialState) => initialState
170
+ }
171
+ }
172
+
181
173
  let setEffectCacheOrThrow = async (persistence, ~effect: Internal.effect, ~items) => {
182
174
  switch persistence.storageStatus {
183
175
  | Unknown