envio 3.3.2 → 3.5.0-alpha.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 (61) hide show
  1. package/package.json +6 -6
  2. package/src/Api.res +1 -8
  3. package/src/Api.res.mjs +1 -5
  4. package/src/Bin.res +2 -2
  5. package/src/ChainState.res +6 -1
  6. package/src/ChainState.res.mjs +4 -3
  7. package/src/Config.res +38 -5
  8. package/src/Config.res.mjs +35 -6
  9. package/src/Core.res +65 -20
  10. package/src/Core.res.mjs +36 -6
  11. package/src/EnvioGlobal.res +0 -2
  12. package/src/EnvioGlobal.res.mjs +0 -1
  13. package/src/ExitOnCaughtUp.res +6 -2
  14. package/src/ExitOnCaughtUp.res.mjs +4 -0
  15. package/src/FetchState.res +3 -3
  16. package/src/HandlerRegister.res +357 -434
  17. package/src/HandlerRegister.res.mjs +202 -242
  18. package/src/HandlerRegister.resi +7 -15
  19. package/src/IndexerState.res +10 -0
  20. package/src/IndexerState.res.mjs +9 -3
  21. package/src/IndexerState.resi +3 -0
  22. package/src/Internal.res +10 -1
  23. package/src/Main.res.mjs +4 -4
  24. package/src/PgStorage.res +16 -1
  25. package/src/PgStorage.res.mjs +9 -1
  26. package/src/SimulateItems.res +61 -40
  27. package/src/SimulateItems.res.mjs +37 -21
  28. package/src/TestIndexer.res +453 -454
  29. package/src/TestIndexer.res.mjs +321 -344
  30. package/src/bindings/ClickHouse.res +68 -2
  31. package/src/bindings/ClickHouse.res.mjs +47 -2
  32. package/src/sources/EvmChain.res +1 -1
  33. package/src/sources/EvmChain.res.mjs +2 -2
  34. package/src/sources/FuelHyperSync.res +74 -0
  35. package/src/sources/FuelHyperSync.res.mjs +80 -0
  36. package/src/sources/FuelHyperSync.resi +22 -0
  37. package/src/sources/FuelHyperSyncClient.res +120 -0
  38. package/src/sources/FuelHyperSyncClient.res.mjs +71 -0
  39. package/src/sources/FuelHyperSyncSource.res +257 -0
  40. package/src/sources/FuelHyperSyncSource.res.mjs +252 -0
  41. package/src/sources/HyperSyncClient.res +2 -2
  42. package/src/sources/HyperSyncClient.res.mjs +1 -1
  43. package/src/sources/SvmHyperSyncClient.res +139 -102
  44. package/src/sources/SvmHyperSyncClient.res.mjs +45 -5
  45. package/src/sources/SvmHyperSyncSource.res +60 -440
  46. package/src/sources/SvmHyperSyncSource.res.mjs +42 -363
  47. package/src/TestIndexerProxyStorage.res +0 -196
  48. package/src/TestIndexerProxyStorage.res.mjs +0 -121
  49. package/src/TestIndexerWorker.res +0 -4
  50. package/src/TestIndexerWorker.res.mjs +0 -7
  51. package/src/sources/EventRouter.res +0 -165
  52. package/src/sources/EventRouter.res.mjs +0 -153
  53. package/src/sources/HyperFuel.res +0 -179
  54. package/src/sources/HyperFuel.res.mjs +0 -146
  55. package/src/sources/HyperFuel.resi +0 -36
  56. package/src/sources/HyperFuelClient.res +0 -127
  57. package/src/sources/HyperFuelClient.res.mjs +0 -20
  58. package/src/sources/HyperFuelSource.res +0 -502
  59. package/src/sources/HyperFuelSource.res.mjs +0 -481
  60. /package/src/sources/{HyperSyncSource.res → EvmHyperSyncSource.res} +0 -0
  61. /package/src/sources/{HyperSyncSource.res.mjs → EvmHyperSyncSource.res.mjs} +0 -0
@@ -1,29 +1,28 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as Env from "./Env.res.mjs";
4
- import * as Main from "./Main.res.mjs";
5
- import * as Table from "./db/Table.res.mjs";
6
4
  import * as Utils from "./Utils.res.mjs";
7
5
  import * as Config from "./Config.res.mjs";
8
6
  import * as Logging from "./Logging.res.mjs";
9
- import * as Process from "process";
10
7
  import * as ChainMap from "./ChainMap.res.mjs";
11
8
  import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
9
+ import * as IndexerLoop from "./IndexerLoop.res.mjs";
12
10
  import * as Persistence from "./Persistence.res.mjs";
13
11
  import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
14
12
  import * as EntityFilter from "./db/EntityFilter.res.mjs";
13
+ import * as IndexerState from "./IndexerState.res.mjs";
15
14
  import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
15
+ import * as ErrorHandling from "./ErrorHandling.res.mjs";
16
+ import * as HandlerLoader from "./HandlerLoader.res.mjs";
16
17
  import * as InternalTable from "./db/InternalTable.res.mjs";
17
18
  import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
18
19
  import * as SimulateItems from "./SimulateItems.res.mjs";
19
20
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
20
21
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
21
22
  import * as Stdlib_Promise from "@rescript/runtime/lib/es6/Stdlib_Promise.js";
22
- import * as Worker_threads from "worker_threads";
23
23
  import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
24
24
  import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
25
25
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
26
- import * as TestIndexerProxyStorage from "./TestIndexerProxyStorage.res.mjs";
27
26
 
28
27
  function toIndexingAddress(dc) {
29
28
  return {
@@ -55,32 +54,18 @@ function getIndexingAddressesByChain(state) {
55
54
  }
56
55
 
57
56
  function handleLoad(state, tableName, filter) {
58
- let entityConfig = state.entityConfigs[tableName];
59
- if (entityConfig === undefined) {
57
+ let match = state.entityConfigs[tableName];
58
+ if (match === undefined) {
60
59
  return [];
61
60
  }
62
61
  let entityDict = Stdlib_Option.getOr(state.entities[tableName], {});
63
- let results = [];
64
- let parseLeaf = (fieldName, fieldValue, isArray) => {
65
- let queryField = Table.queryFields(entityConfig.table)[fieldName];
66
- let queryField$1 = queryField !== undefined ? queryField : Stdlib_JsError.throwWithMessage(`Field ` + fieldName + ` not found in entity ` + tableName);
67
- return S$RescriptSchema.convertOrThrow(fieldValue, isArray ? queryField$1.arrayFieldSchema : queryField$1.fieldSchema);
68
- };
69
- let filter$1 = EntityFilter.mapValues(filter, parseLeaf);
70
- Object.values(entityDict).forEach(entity => {
71
- if (!EntityFilter.matches(filter$1, entity)) {
72
- return;
73
- }
74
- let jsonEntity = S$RescriptSchema.reverseConvertToJsonOrThrow(entity, entityConfig.schema);
75
- results.push(jsonEntity);
76
- });
77
- return results;
62
+ return Object.values(entityDict).filter(entity => EntityFilter.matches(filter, entity));
78
63
  }
79
64
 
80
65
  function handleWriteBatch(state, updatedEntities, checkpointIds, checkpointChainIds, checkpointBlockNumbers, checkpointEventsProcessed) {
81
66
  let changesByCheckpoint = {};
82
67
  updatedEntities.forEach(param => {
83
- let entityName = param.entityName;
68
+ let entityName = param.entityConfig.name;
84
69
  let dict = state.entities[entityName];
85
70
  let entityDict;
86
71
  if (dict !== undefined) {
@@ -90,65 +75,40 @@ function handleWriteBatch(state, updatedEntities, checkpointIds, checkpointChain
90
75
  state.entities[entityName] = dict$1;
91
76
  entityDict = dict$1;
92
77
  }
93
- let entityConfig = state.entityConfigs[entityName];
78
+ let entityChangeFor = checkpointId => {
79
+ let checkpointKey = checkpointId.toString();
80
+ let changes = changesByCheckpoint[checkpointKey];
81
+ let entityChanges;
82
+ if (changes !== undefined) {
83
+ entityChanges = changes;
84
+ } else {
85
+ let changes$1 = {};
86
+ changesByCheckpoint[checkpointKey] = changes$1;
87
+ entityChanges = changes$1;
88
+ }
89
+ let change = entityChanges[entityName];
90
+ if (change !== undefined) {
91
+ return change;
92
+ }
93
+ let change_sets = [];
94
+ let change_deleted = [];
95
+ let change$1 = {
96
+ sets: change_sets,
97
+ deleted: change_deleted
98
+ };
99
+ entityChanges[entityName] = change$1;
100
+ return change$1;
101
+ };
94
102
  let processChange = change => {
95
103
  if (change.type === "SET") {
96
- let parsedEntity = S$RescriptSchema.parseOrThrow(change.entity, entityConfig.schema);
97
- entityDict[change.entityId] = parsedEntity;
98
- let checkpointKey = change.checkpointId.toString();
99
- let changes = changesByCheckpoint[checkpointKey];
100
- let entityChanges;
101
- if (changes !== undefined) {
102
- entityChanges = changes;
103
- } else {
104
- let changes$1 = {};
105
- changesByCheckpoint[checkpointKey] = changes$1;
106
- entityChanges = changes$1;
107
- }
108
- let change$1 = entityChanges[entityName];
109
- let entityChange;
110
- if (change$1 !== undefined) {
111
- entityChange = change$1;
112
- } else {
113
- let change_sets = [];
114
- let change_deleted = [];
115
- let change$2 = {
116
- sets: change_sets,
117
- deleted: change_deleted
118
- };
119
- entityChanges[entityName] = change$2;
120
- entityChange = change$2;
121
- }
122
- entityChange.sets.push(parsedEntity);
104
+ let entity = change.entity;
105
+ entityDict[change.entityId] = entity;
106
+ entityChangeFor(change.checkpointId).sets.push(entity);
123
107
  return;
124
108
  }
125
109
  let entityId = change.entityId;
126
110
  Stdlib_Dict.$$delete(entityDict, entityId);
127
- let checkpointKey$1 = change.checkpointId.toString();
128
- let changes$2 = changesByCheckpoint[checkpointKey$1];
129
- let entityChanges$1;
130
- if (changes$2 !== undefined) {
131
- entityChanges$1 = changes$2;
132
- } else {
133
- let changes$3 = {};
134
- changesByCheckpoint[checkpointKey$1] = changes$3;
135
- entityChanges$1 = changes$3;
136
- }
137
- let change$3 = entityChanges$1[entityName];
138
- let entityChange$1;
139
- if (change$3 !== undefined) {
140
- entityChange$1 = change$3;
141
- } else {
142
- let change_sets$1 = [];
143
- let change_deleted$1 = [];
144
- let change$4 = {
145
- sets: change_sets$1,
146
- deleted: change_deleted$1
147
- };
148
- entityChanges$1[entityName] = change$4;
149
- entityChange$1 = change$4;
150
- }
151
- entityChange$1.deleted.push(entityId);
111
+ entityChangeFor(change.checkpointId).deleted.push(entityId);
152
112
  };
153
113
  param.changes.forEach(processChange);
154
114
  });
@@ -186,7 +146,7 @@ function handleWriteBatch(state, updatedEntities, checkpointIds, checkpointChain
186
146
  if (deleted.length !== 0) {
187
147
  entityObj$1["deleted"] = deleted;
188
148
  }
189
- change[entityName] = entityObj$1;
149
+ change[Utils.$$String.capitalize(entityName)] = entityObj$1;
190
150
  });
191
151
  }
192
152
  state.processChanges.push(change);
@@ -292,12 +252,16 @@ function parseBlockRange(chainIdStr, config, rawChainConfig, progressBlock) {
292
252
  };
293
253
  }
294
254
 
255
+ function copyEntity(entity) {
256
+ return Utils.Dict.shallowCopy(entity);
257
+ }
258
+
295
259
  function getEntityFromState(state, entityConfig, entityId, methodName) {
296
260
  if (state.processInProgress) {
297
261
  Stdlib_JsError.throwWithMessage(`Cannot call ` + entityConfig.name + `.` + methodName + `() while indexer.process() is running. ` + "Wait for process() to complete before accessing entities directly.");
298
262
  }
299
263
  let entityDict = Stdlib_Option.getOr(state.entities[entityConfig.name], {});
300
- return entityDict[entityId];
264
+ return Stdlib_Option.map(entityDict[entityId], copyEntity);
301
265
  }
302
266
 
303
267
  function makeEntityGet(state, entityConfig) {
@@ -329,7 +293,7 @@ function makeEntitySet(state, entityConfig) {
329
293
  state.entities[entityConfig.name] = dict$1;
330
294
  entityDict = dict$1;
331
295
  }
332
- entityDict[entity.id] = entity;
296
+ entityDict[entity.id] = Utils.Dict.shallowCopy(entity);
333
297
  };
334
298
  }
335
299
 
@@ -339,295 +303,304 @@ function makeEntityGetAll(state, entityConfig) {
339
303
  Stdlib_JsError.throwWithMessage(`Cannot call ` + entityConfig.name + `.getAll() while indexer.process() is running. ` + "Wait for process() to complete before accessing entities directly.");
340
304
  }
341
305
  let entityDict = Stdlib_Option.getOr(state.entities[entityConfig.name], {});
342
- return Promise.resolve(Object.values(entityDict));
306
+ return Promise.resolve(Object.values(entityDict).map(copyEntity));
343
307
  };
344
308
  }
345
309
 
346
- function makeCreateTestIndexer(config, workerPath) {
347
- return () => {
348
- let allEntities = config.allEntities;
349
- let entities = {};
350
- let entityConfigs = {};
351
- allEntities.forEach(entityConfig => {
352
- entities[entityConfig.name] = {};
353
- entityConfigs[entityConfig.name] = entityConfig;
354
- });
355
- let envioAddressesDict = entities[Config.EnvioAddresses.name];
356
- ChainMap.values(config.chainMap).forEach(chainConfig => {
357
- chainConfig.contracts.forEach(contract => {
358
- contract.addresses.forEach(address => {
359
- let entity_id = Config.EnvioAddresses.makeId(chainConfig.id, address);
360
- let entity_chain_id = chainConfig.id;
361
- let entity_contract_name = contract.name;
362
- let entity = {
363
- id: entity_id,
364
- chain_id: entity_chain_id,
365
- registration_block: -1,
366
- registration_log_index: -1,
367
- contract_name: entity_contract_name
368
- };
369
- envioAddressesDict[entity_id] = entity;
370
- });
371
- });
372
- });
373
- let state = {
374
- processInProgress: false,
375
- progressBlockByChain: {},
376
- entities: entities,
377
- entityConfigs: entityConfigs,
378
- processChanges: []
310
+ function makeInMemoryStorage(state) {
311
+ return {
312
+ name: "test-inmemory",
313
+ isInitialized: async () => true,
314
+ initialize: async (param, param$1, param$2, param$3) => Stdlib_JsError.throwWithMessage("TestIndexer: initialize should not be called; the initial state is derived from config."),
315
+ resumeInitialState: async () => Stdlib_JsError.throwWithMessage("TestIndexer: resumeInitialState should not be called; the initial state is derived from config."),
316
+ loadOrThrow: async (filter, table) => handleLoad(state, table.tableName, filter),
317
+ dumpEffectCache: async () => {},
318
+ reset: async () => {},
319
+ setChainMeta: async param => {},
320
+ pruneStaleCheckpoints: async param => {},
321
+ pruneStaleEntityHistory: async (param, param$1, param$2) => {},
322
+ getRollbackTargetCheckpoint: async (param, param$1) => Stdlib_JsError.throwWithMessage("TestIndexer: Rollback is not supported. The runner forces rollbackOnReorg off, so this should be unreachable."),
323
+ getRollbackProgressDiff: async param => Stdlib_JsError.throwWithMessage("TestIndexer: Rollback is not supported. The runner forces rollbackOnReorg off, so this should be unreachable."),
324
+ getRollbackData: async (param, param$1) => Stdlib_JsError.throwWithMessage("TestIndexer: Rollback is not supported. The runner forces rollbackOnReorg off, so this should be unreachable."),
325
+ writeBatch: async (batch, param, param$1, param$2, param$3, param$4, updatedEntities, param$5, param$6) => handleWriteBatch(state, updatedEntities, batch.checkpointIds, batch.checkpointChainIds, batch.checkpointBlockNumbers, batch.checkpointEventsProcessed),
326
+ close: async () => {}
327
+ };
328
+ }
329
+
330
+ function cloneRegistrations(base) {
331
+ let clone = {};
332
+ Object.entries(base).forEach(param => {
333
+ let chainRegistrations = param[1];
334
+ clone[param[0]] = {
335
+ onEventRegistrations: chainRegistrations.onEventRegistrations.slice(),
336
+ onBlockRegistrations: chainRegistrations.onBlockRegistrations.slice()
379
337
  };
380
- let entityOpsDict = {};
381
- allEntities.forEach(entityConfig => {
382
- if (entityConfig.name !== Config.EnvioAddresses.name) {
383
- entityOpsDict[entityConfig.name] = {
384
- get: makeEntityGet(state, entityConfig),
385
- getAll: makeEntityGetAll(state, entityConfig),
386
- getOrThrow: makeEntityGetOrThrow(state, entityConfig),
387
- set: makeEntitySet(state, entityConfig)
338
+ });
339
+ return clone;
340
+ }
341
+
342
+ let registrationsRef = {
343
+ contents: undefined
344
+ };
345
+
346
+ function getRegistrations(config) {
347
+ let promise = registrationsRef.contents;
348
+ if (promise !== undefined) {
349
+ return promise;
350
+ }
351
+ let promise$1 = HandlerLoader.registerAllHandlers(config);
352
+ registrationsRef.contents = promise$1;
353
+ return promise$1;
354
+ }
355
+
356
+ function createTestIndexer() {
357
+ let config = Config.load();
358
+ let allEntities = config.allEntities;
359
+ let entities = {};
360
+ let entityConfigs = {};
361
+ allEntities.forEach(entityConfig => {
362
+ entities[entityConfig.name] = {};
363
+ entityConfigs[entityConfig.name] = entityConfig;
364
+ });
365
+ let envioAddressesDict = entities[Config.EnvioAddresses.name];
366
+ ChainMap.values(config.chainMap).forEach(chainConfig => {
367
+ chainConfig.contracts.forEach(contract => {
368
+ contract.addresses.forEach(address => {
369
+ let entity_id = Config.EnvioAddresses.makeId(chainConfig.id, address);
370
+ let entity_chain_id = chainConfig.id;
371
+ let entity_contract_name = contract.name;
372
+ let entity = {
373
+ id: entity_id,
374
+ chain_id: entity_chain_id,
375
+ registration_block: -1,
376
+ registration_log_index: -1,
377
+ contract_name: entity_contract_name
388
378
  };
389
- return;
390
- }
379
+ envioAddressesDict[entity_id] = entity;
380
+ });
391
381
  });
392
- let chainIds = [];
393
- let chains = Object.create(null);
394
- ChainMap.values(config.chainMap).forEach(chainConfig => {
395
- let chainIdStr = chainConfig.id.toString();
396
- chainIds.push(chainConfig.id);
397
- let chainObj = Object.create(null);
398
- Object.defineProperty(Object.defineProperty(Object.defineProperty(Object.defineProperty(Object.defineProperty(chainObj, "id", {
399
- enumerable: true,
400
- value: chainConfig.id
401
- }), "startBlock", {
402
- enumerable: true,
403
- value: chainConfig.startBlock
404
- }), "endBlock", {
382
+ });
383
+ let state = {
384
+ processInProgress: false,
385
+ progressBlockByChain: {},
386
+ entities: entities,
387
+ entityConfigs: entityConfigs,
388
+ processChanges: []
389
+ };
390
+ let storage = makeInMemoryStorage(state);
391
+ let persistence = Persistence.make(config.userEntities, config.allEnums, storage);
392
+ if (Env.userLogLevel !== undefined) {
393
+
394
+ } else {
395
+ Logging.setLogLevel("silent");
396
+ }
397
+ let entityOpsDict = {};
398
+ allEntities.forEach(entityConfig => {
399
+ if (entityConfig.name !== Config.EnvioAddresses.name) {
400
+ entityOpsDict[entityConfig.name] = {
401
+ get: makeEntityGet(state, entityConfig),
402
+ getAll: makeEntityGetAll(state, entityConfig),
403
+ getOrThrow: makeEntityGetOrThrow(state, entityConfig),
404
+ set: makeEntitySet(state, entityConfig)
405
+ };
406
+ return;
407
+ }
408
+ });
409
+ let chainIds = [];
410
+ let chains = Object.create(null);
411
+ ChainMap.values(config.chainMap).forEach(chainConfig => {
412
+ let chainIdStr = chainConfig.id.toString();
413
+ chainIds.push(chainConfig.id);
414
+ let chainObj = Object.create(null);
415
+ Object.defineProperty(Object.defineProperty(Object.defineProperty(Object.defineProperty(Object.defineProperty(chainObj, "id", {
416
+ enumerable: true,
417
+ value: chainConfig.id
418
+ }), "startBlock", {
419
+ enumerable: true,
420
+ value: chainConfig.startBlock
421
+ }), "endBlock", {
422
+ enumerable: true,
423
+ value: chainConfig.endBlock
424
+ }), "name", {
425
+ enumerable: true,
426
+ value: chainConfig.name
427
+ }), "isRealtime", {
428
+ enumerable: true,
429
+ value: false
430
+ });
431
+ chainConfig.contracts.forEach(contract => {
432
+ let contractObj = Object.create(null);
433
+ Object.defineProperty(Object.defineProperty(Object.defineProperty(contractObj, "name", {
405
434
  enumerable: true,
406
- value: chainConfig.endBlock
407
- }), "name", {
435
+ value: contract.name
436
+ }), "abi", {
408
437
  enumerable: true,
409
- value: chainConfig.name
410
- }), "isRealtime", {
438
+ value: contract.abi
439
+ }), "addresses", {
411
440
  enumerable: true,
412
- value: false
413
- });
414
- chainConfig.contracts.forEach(contract => {
415
- let contractObj = Object.create(null);
416
- Object.defineProperty(Object.defineProperty(Object.defineProperty(contractObj, "name", {
417
- enumerable: true,
418
- value: contract.name
419
- }), "abi", {
420
- enumerable: true,
421
- value: contract.abi
422
- }), "addresses", {
423
- enumerable: true,
424
- get: () => {
425
- if (state.processInProgress) {
426
- Stdlib_JsError.throwWithMessage(`Cannot access ` + contract.name + `.addresses while indexer.process() is running. ` + "Wait for process() to complete before reading contract addresses.");
427
- }
428
- return Stdlib_Array.filterMap(Stdlib_Option.getOr(getIndexingAddressesByChain(state)[chainConfig.id.toString()], []), ia => {
429
- if (ia.contractName === contract.name) {
430
- return Primitive_option.some(ia.address);
431
- }
432
- });
441
+ get: () => {
442
+ if (state.processInProgress) {
443
+ Stdlib_JsError.throwWithMessage(`Cannot access ` + contract.name + `.addresses while indexer.process() is running. ` + "Wait for process() to complete before reading contract addresses.");
433
444
  }
434
- });
435
- Object.defineProperty(chainObj, contract.name, {
436
- enumerable: true,
437
- value: contractObj
438
- });
445
+ return Stdlib_Array.filterMap(Stdlib_Option.getOr(getIndexingAddressesByChain(state)[chainConfig.id.toString()], []), ia => {
446
+ if (ia.contractName === contract.name) {
447
+ return Primitive_option.some(ia.address);
448
+ }
449
+ });
450
+ }
439
451
  });
440
- Object.defineProperty(chains, chainIdStr, {
452
+ Object.defineProperty(chainObj, contract.name, {
441
453
  enumerable: true,
454
+ value: contractObj
455
+ });
456
+ });
457
+ Object.defineProperty(chains, chainIdStr, {
458
+ enumerable: true,
459
+ value: chainObj
460
+ });
461
+ if (chainConfig.name !== chainIdStr) {
462
+ Object.defineProperty(chains, chainConfig.name, {
463
+ enumerable: false,
442
464
  value: chainObj
443
465
  });
444
- if (chainConfig.name !== chainIdStr) {
445
- Object.defineProperty(chains, chainConfig.name, {
446
- enumerable: false,
447
- value: chainObj
448
- });
449
- return;
466
+ return;
467
+ }
468
+ });
469
+ let result = {};
470
+ result["chainIds"] = chainIds;
471
+ result["chains"] = chains;
472
+ Object.entries(entityOpsDict).forEach(param => {
473
+ result[Utils.$$String.capitalize(param[0])] = param[1];
474
+ });
475
+ result["process"] = processConfig => {
476
+ if (state.processInProgress) {
477
+ Stdlib_JsError.throwWithMessage("createTestIndexer process is already running. Only one process call is allowed at a time");
478
+ }
479
+ let parsedConfig;
480
+ try {
481
+ parsedConfig = S$RescriptSchema.parseOrThrow(processConfig, processConfigSchema);
482
+ } catch (raw_exn) {
483
+ let exn = Primitive_exceptions.internalToException(raw_exn);
484
+ if (exn.RE_EXN_ID === S$RescriptSchema.Raised) {
485
+ parsedConfig = Stdlib_JsError.throwWithMessage(`Invalid processConfig: ` + Utils.prettifyExn(exn._1));
486
+ } else {
487
+ throw exn;
450
488
  }
489
+ }
490
+ let rawChains = parsedConfig.chains;
491
+ let chainKeys = Object.keys(rawChains);
492
+ if (chainKeys.length === 0) {
493
+ Stdlib_JsError.throwWithMessage("createTestIndexer requires at least one chain to be defined");
494
+ }
495
+ let sortedChainKeys = chainKeys.slice();
496
+ sortedChainKeys.sort((a, b) => {
497
+ let aId = Stdlib_Option.getOr(Stdlib_Int.fromString(a, undefined), 0);
498
+ let bId = Stdlib_Option.getOr(Stdlib_Int.fromString(b, undefined), 0);
499
+ return Primitive_int.compare(aId, bId);
451
500
  });
452
- let result = {};
453
- result["chainIds"] = chainIds;
454
- result["chains"] = chains;
455
- Object.entries(entityOpsDict).forEach(param => {
456
- result[param[0]] = param[1];
501
+ let chainEntries = sortedChainKeys.map(chainIdStr => {
502
+ let rawChainConfig = rawChains[chainIdStr];
503
+ if (Stdlib_Option.isNone(Stdlib_Int.fromString(chainIdStr, undefined))) {
504
+ Stdlib_JsError.throwWithMessage(`Invalid chain ID "` + chainIdStr + `": expected a numeric chain ID`);
505
+ }
506
+ let processChainConfig = parseBlockRange(chainIdStr, config, rawChainConfig, state.progressBlockByChain[chainIdStr]);
507
+ return [
508
+ chainIdStr,
509
+ rawChainConfig,
510
+ processChainConfig
511
+ ];
457
512
  });
458
- result["process"] = processConfig => {
459
- if (state.processInProgress) {
460
- Stdlib_JsError.throwWithMessage("createTestIndexer process is already running. Only one process call is allowed at a time");
513
+ state.processChanges = [];
514
+ let runChainInProcess = async param => {
515
+ let processChainConfig = param[2];
516
+ let chainIdStr = param[0];
517
+ let chains = {};
518
+ chains[chainIdStr] = processChainConfig;
519
+ let indexingAddressesByChain = getIndexingAddressesByChain(state);
520
+ let initialState = makeInitialState(config, chains, indexingAddressesByChain);
521
+ let exitAfterFirstEventBlock = Stdlib_Option.isNone(processChainConfig.endBlock);
522
+ let resolvedChainDict = {};
523
+ resolvedChainDict["startBlock"] = processChainConfig.startBlock;
524
+ let eb = processChainConfig.endBlock;
525
+ if (eb !== undefined) {
526
+ resolvedChainDict["endBlock"] = eb;
461
527
  }
462
- let parsedConfig;
463
- try {
464
- parsedConfig = S$RescriptSchema.parseOrThrow(processConfig, processConfigSchema);
465
- } catch (raw_exn) {
466
- let exn = Primitive_exceptions.internalToException(raw_exn);
467
- if (exn.RE_EXN_ID === S$RescriptSchema.Raised) {
468
- parsedConfig = Stdlib_JsError.throwWithMessage(`Invalid processConfig: ` + Utils.prettifyExn(exn._1));
469
- } else {
470
- throw exn;
471
- }
528
+ let s = param[1].simulate;
529
+ if (s !== undefined) {
530
+ resolvedChainDict["simulate"] = s;
472
531
  }
473
- let rawChains = parsedConfig.chains;
474
- let chainKeys = Object.keys(rawChains);
475
- if (chainKeys.length === 0) {
476
- Stdlib_JsError.throwWithMessage("createTestIndexer requires at least one chain to be defined");
532
+ let resolvedChainsDict = {};
533
+ resolvedChainsDict[chainIdStr] = resolvedChainDict;
534
+ let processConfigJson = {
535
+ chains: resolvedChainsDict
536
+ };
537
+ let registrationsByChainId = cloneRegistrations(await getRegistrations(config));
538
+ let patchedConfig = SimulateItems.patchConfig(config, processConfigJson, registrationsByChainId);
539
+ let newrecord = {...patchedConfig};
540
+ newrecord.shouldRollbackOnReorg = false;
541
+ let runConfig;
542
+ if (exitAfterFirstEventBlock) {
543
+ let newrecord$1 = {...newrecord};
544
+ newrecord$1.batchSize = 1;
545
+ runConfig = newrecord$1;
546
+ } else {
547
+ runConfig = newrecord;
477
548
  }
478
- let sortedChainKeys = chainKeys.slice();
479
- sortedChainKeys.sort((a, b) => {
480
- let aId = Stdlib_Option.getOr(Stdlib_Int.fromString(a, undefined), 0);
481
- let bId = Stdlib_Option.getOr(Stdlib_Int.fromString(b, undefined), 0);
482
- return Primitive_int.compare(aId, bId);
483
- });
484
- let chainEntries = sortedChainKeys.map(chainIdStr => {
485
- let rawChainConfig = rawChains[chainIdStr];
486
- let id = Stdlib_Int.fromString(chainIdStr, undefined);
487
- let chainId = id !== undefined ? id : Stdlib_JsError.throwWithMessage(`Invalid chain ID "` + chainIdStr + `": expected a numeric chain ID`);
488
- let processChainConfig = parseBlockRange(chainIdStr, config, rawChainConfig, state.progressBlockByChain[chainIdStr]);
489
- return [
490
- chainIdStr,
491
- chainId,
492
- rawChainConfig,
493
- processChainConfig
494
- ];
495
- });
496
- state.processChanges = [];
497
- let runChainWorker = param => {
498
- let processChainConfig = param[3];
499
- let rawChainConfig = param[2];
500
- let chainId = param[1];
501
- let chains = {};
502
- chains[param[0]] = processChainConfig;
503
- let indexingAddressesByChain = getIndexingAddressesByChain(state);
504
- let initialState = makeInitialState(config, chains, indexingAddressesByChain);
505
- return new Promise((resolve, reject) => {
506
- let workerData_startBlock = processChainConfig.startBlock;
507
- let workerData_endBlock = processChainConfig.endBlock;
508
- let workerData_simulate = rawChainConfig.simulate;
509
- let workerData = {
510
- chainId: chainId,
511
- startBlock: workerData_startBlock,
512
- endBlock: workerData_endBlock,
513
- simulate: workerData_simulate,
514
- initialState: initialState
515
- };
516
- let worker;
517
- try {
518
- worker = new Worker_threads.Worker(workerPath, {
519
- workerData: workerData,
520
- env: process.env
521
- });
522
- } catch (raw_exn) {
523
- let exn = Primitive_exceptions.internalToException(raw_exn);
524
- reject(exn);
525
- throw exn;
526
- }
527
- worker.on("message", msg => {
528
- let respond = data => {
529
- worker.postMessage({
530
- id: msg.id,
531
- payload: {
532
- type: "response",
533
- data: data
534
- }
535
- });
536
- };
537
- let match = msg.payload;
538
- if (match.type === "load") {
539
- return respond(handleLoad(state, match.tableName, match.filter));
540
- }
541
- handleWriteBatch(state, match.updatedEntities, match.checkpointIds, match.checkpointChainIds, match.checkpointBlockNumbers, match.checkpointEventsProcessed);
542
- respond(null);
543
- });
544
- worker.on("error", err => {
545
- worker.terminate();
546
- reject(err);
547
- });
548
- worker.on("exit", code => {
549
- if (code !== 0) {
550
- return reject(new Error(`Worker exited with code ` + code.toString()));
551
- } else {
552
- return resolve();
553
- }
554
- });
555
- });
549
+ persistence.storageStatus = {
550
+ TAG: "Ready",
551
+ _0: initialState
556
552
  };
557
- state.processInProgress = true;
558
- let runChains = idx => {
559
- if (idx >= chainEntries.length) {
560
- state.processInProgress = false;
561
- return Promise.resolve({
562
- changes: state.processChanges
563
- });
564
- } else {
565
- return runChainWorker(chainEntries[idx]).then(() => runChains(idx + 1 | 0));
553
+ let indexerStateRef = {
554
+ contents: undefined
555
+ };
556
+ let cleanup = async () => {
557
+ let indexerState = indexerStateRef.contents;
558
+ if (indexerState === undefined) {
559
+ return;
566
560
  }
561
+ let indexerState$1 = Primitive_option.valFromOption(indexerState);
562
+ IndexerState.stop(indexerState$1);
563
+ while (IndexerState.isProcessing(indexerState$1) || Stdlib_Option.isSome(IndexerState.writeFiber(indexerState$1))) {
564
+ let fiber = IndexerState.writeFiber(indexerState$1);
565
+ if (fiber !== undefined) {
566
+ await fiber;
567
+ } else {
568
+ await Utils.delay(0);
569
+ }
570
+ };
567
571
  };
568
- return Stdlib_Promise.$$catch(runChains(0), err => {
572
+ try {
573
+ await new Promise((resolve, reject) => {
574
+ let indexerState = IndexerState.makeFromDbState(runConfig, persistence, initialState, registrationsByChainId, undefined, undefined, exitAfterFirstEventBlock, undefined, undefined, errHandler => {
575
+ ErrorHandling.log(errHandler);
576
+ reject(Utils.prettifyExn(errHandler.exn));
577
+ }, () => resolve());
578
+ indexerStateRef.contents = Primitive_option.some(indexerState);
579
+ IndexerLoop.start(indexerState);
580
+ });
581
+ return await cleanup();
582
+ } catch (exn) {
583
+ await cleanup();
584
+ throw exn;
585
+ }
586
+ };
587
+ state.processInProgress = true;
588
+ let runChains = idx => {
589
+ if (idx >= chainEntries.length) {
569
590
  state.processInProgress = false;
570
- return Promise.reject(Utils.prettifyExn(err));
571
- });
591
+ return Promise.resolve({
592
+ changes: state.processChanges
593
+ });
594
+ } else {
595
+ return runChainInProcess(chainEntries[idx]).then(() => runChains(idx + 1 | 0));
596
+ }
572
597
  };
573
- return result;
574
- };
575
- }
576
-
577
- function initTestWorker() {
578
- if (Worker_threads.isMainThread) {
579
- Stdlib_JsError.throwWithMessage("initTestWorker must be called from a worker thread");
580
- }
581
- let port = Worker_threads.parentPort;
582
- let parentPort = (port == null) ? Stdlib_JsError.throwWithMessage("initTestWorker: No parent port available") : port;
583
- let workerData = Worker_threads.workerData;
584
- if (workerData == null) {
585
- Logging.error("TestIndexerWorker: No worker data provided");
586
- Process.exit(1);
587
- return;
588
- }
589
- let simulate = workerData.simulate;
590
- let endBlock = workerData.endBlock;
591
- let chainIdStr = workerData.chainId.toString();
592
- let exitAfterFirstEventBlock = Stdlib_Option.isNone(endBlock);
593
- let resolvedChainDict = {};
594
- resolvedChainDict["startBlock"] = workerData.startBlock;
595
- if (endBlock !== undefined) {
596
- resolvedChainDict["endBlock"] = endBlock;
597
- }
598
- if (simulate !== undefined) {
599
- resolvedChainDict["simulate"] = simulate;
600
- }
601
- let resolvedChainsDict = {};
602
- resolvedChainsDict[chainIdStr] = resolvedChainDict;
603
- let processConfig = {
604
- chains: resolvedChainsDict
605
- };
606
- let proxy = TestIndexerProxyStorage.make(parentPort, workerData.initialState);
607
- let storage = TestIndexerProxyStorage.makeStorage(proxy);
608
- let config = Config.load();
609
- let persistence = Persistence.make(config.userEntities, config.allEnums, storage);
610
- if (Env.userLogLevel !== undefined) {
611
-
612
- } else {
613
- Logging.setLogLevel("silent");
614
- }
615
- let patchConfig = (config, registrationsByChainId) => {
616
- let config$1 = SimulateItems.patchConfig(config, processConfig, registrationsByChainId);
617
- if (!exitAfterFirstEventBlock) {
618
- return config$1;
619
- }
620
- let newrecord = {...config$1};
621
- newrecord.batchSize = 1;
622
- return newrecord;
623
- };
624
- Stdlib_Promise.$$catch(Main.start(persistence, undefined, true, exitAfterFirstEventBlock, patchConfig), exn => {
625
- let toThrow = exn.RE_EXN_ID === Main.FatalError ? exn._1 : Utils.prettifyExn(exn);
626
- setImmediate(() => {
627
- throw toThrow;
598
+ return Stdlib_Promise.$$catch(runChains(0), err => {
599
+ state.processInProgress = false;
600
+ return Promise.reject(Utils.prettifyExn(err));
628
601
  });
629
- return Promise.resolve();
630
- });
602
+ };
603
+ return result;
631
604
  }
632
605
 
633
606
  export {
@@ -640,12 +613,16 @@ export {
640
613
  processConfigSchema,
641
614
  getSimulateEndBlock,
642
615
  parseBlockRange,
616
+ copyEntity,
643
617
  getEntityFromState,
644
618
  makeEntityGet,
645
619
  makeEntityGetOrThrow,
646
620
  makeEntitySet,
647
621
  makeEntityGetAll,
648
- makeCreateTestIndexer,
649
- initTestWorker,
622
+ makeInMemoryStorage,
623
+ cloneRegistrations,
624
+ registrationsRef,
625
+ getRegistrations,
626
+ createTestIndexer,
650
627
  }
651
628
  /* rawChainConfigSchema Not a pure module */