envio 3.3.2 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -6
- package/src/Api.res +1 -8
- package/src/Api.res.mjs +1 -5
- package/src/ChainState.res +6 -1
- package/src/ChainState.res.mjs +4 -3
- package/src/Config.res +33 -4
- package/src/Config.res.mjs +34 -5
- package/src/Core.res +30 -19
- package/src/Core.res.mjs +5 -5
- package/src/EnvioGlobal.res +0 -2
- package/src/EnvioGlobal.res.mjs +0 -1
- package/src/ExitOnCaughtUp.res +6 -2
- package/src/ExitOnCaughtUp.res.mjs +4 -0
- package/src/FetchState.res +3 -3
- package/src/HandlerRegister.res +357 -434
- package/src/HandlerRegister.res.mjs +202 -242
- package/src/HandlerRegister.resi +7 -15
- package/src/IndexerState.res +10 -0
- package/src/IndexerState.res.mjs +9 -3
- package/src/IndexerState.resi +3 -0
- package/src/Internal.res +10 -1
- package/src/Main.res.mjs +4 -4
- package/src/PgStorage.res +16 -1
- package/src/PgStorage.res.mjs +9 -1
- package/src/SimulateItems.res +61 -40
- package/src/SimulateItems.res.mjs +37 -21
- package/src/TestIndexer.res +446 -453
- package/src/TestIndexer.res.mjs +320 -343
- package/src/bindings/ClickHouse.res +68 -2
- package/src/bindings/ClickHouse.res.mjs +47 -2
- package/src/sources/EvmChain.res +1 -1
- package/src/sources/EvmChain.res.mjs +2 -2
- package/src/sources/FuelHyperSync.res +74 -0
- package/src/sources/FuelHyperSync.res.mjs +80 -0
- package/src/sources/FuelHyperSync.resi +22 -0
- package/src/sources/FuelHyperSyncClient.res +120 -0
- package/src/sources/FuelHyperSyncClient.res.mjs +71 -0
- package/src/sources/FuelHyperSyncSource.res +257 -0
- package/src/sources/FuelHyperSyncSource.res.mjs +252 -0
- package/src/sources/HyperSyncClient.res +2 -2
- package/src/sources/HyperSyncClient.res.mjs +1 -1
- package/src/sources/SvmHyperSyncClient.res +139 -102
- package/src/sources/SvmHyperSyncClient.res.mjs +45 -5
- package/src/sources/SvmHyperSyncSource.res +60 -440
- package/src/sources/SvmHyperSyncSource.res.mjs +42 -363
- package/src/TestIndexerProxyStorage.res +0 -196
- package/src/TestIndexerProxyStorage.res.mjs +0 -121
- package/src/TestIndexerWorker.res +0 -4
- package/src/TestIndexerWorker.res.mjs +0 -7
- package/src/sources/EventRouter.res +0 -165
- package/src/sources/EventRouter.res.mjs +0 -153
- package/src/sources/HyperFuel.res +0 -179
- package/src/sources/HyperFuel.res.mjs +0 -146
- package/src/sources/HyperFuel.resi +0 -36
- package/src/sources/HyperFuelClient.res +0 -127
- package/src/sources/HyperFuelClient.res.mjs +0 -20
- package/src/sources/HyperFuelSource.res +0 -502
- package/src/sources/HyperFuelSource.res.mjs +0 -481
- /package/src/sources/{HyperSyncSource.res → EvmHyperSyncSource.res} +0 -0
- /package/src/sources/{HyperSyncSource.res.mjs → EvmHyperSyncSource.res.mjs} +0 -0
package/src/TestIndexer.res.mjs
CHANGED
|
@@ -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
|
|
59
|
-
if (
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
|
97
|
-
entityDict[change.entityId] =
|
|
98
|
-
|
|
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
|
-
|
|
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
|
});
|
|
@@ -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
|
|
347
|
-
return
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
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
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
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
|
-
|
|
390
|
-
}
|
|
379
|
+
envioAddressesDict[entity_id] = entity;
|
|
380
|
+
});
|
|
391
381
|
});
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
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:
|
|
407
|
-
}), "
|
|
435
|
+
value: contract.name
|
|
436
|
+
}), "abi", {
|
|
408
437
|
enumerable: true,
|
|
409
|
-
value:
|
|
410
|
-
}), "
|
|
438
|
+
value: contract.abi
|
|
439
|
+
}), "addresses", {
|
|
411
440
|
enumerable: true,
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
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
|
-
|
|
436
|
-
|
|
437
|
-
|
|
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(
|
|
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
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
let result = {};
|
|
470
|
+
result["chainIds"] = chainIds;
|
|
471
|
+
result["chains"] = chains;
|
|
472
|
+
Object.entries(entityOpsDict).forEach(param => {
|
|
473
|
+
result[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
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
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
|
-
|
|
459
|
-
|
|
460
|
-
|
|
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
|
|
463
|
-
|
|
464
|
-
|
|
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
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
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
|
-
|
|
479
|
-
|
|
480
|
-
|
|
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
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
649
|
-
|
|
622
|
+
makeInMemoryStorage,
|
|
623
|
+
cloneRegistrations,
|
|
624
|
+
registrationsRef,
|
|
625
|
+
getRegistrations,
|
|
626
|
+
createTestIndexer,
|
|
650
627
|
}
|
|
651
628
|
/* rawChainConfigSchema Not a pure module */
|