envio 3.10.0-subgraph → 3.11.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/evm.schema.json +21 -4
- package/fuel.schema.json +21 -4
- package/index.d.ts +1 -1
- package/package.json +6 -6
- package/src/ChainState.res +9 -73
- package/src/ChainState.res.mjs +6 -58
- package/src/Config.res +73 -27
- package/src/Config.res.mjs +71 -21
- package/src/Core.res +0 -15
- package/src/Core.res.mjs +0 -11
- package/src/EventConfigBuilder.res +14 -10
- package/src/EventConfigBuilder.res.mjs +6 -4
- package/src/EventProcessing.res +6 -6
- package/src/EventProcessing.res.mjs +6 -8
- package/src/HandlerLoader.res +8 -20
- package/src/HandlerLoader.res.mjs +2 -11
- package/src/HandlerRegister.res +12 -11
- package/src/HandlerRegister.res.mjs +6 -5
- package/src/Internal.res +20 -4
- package/src/Internal.res.mjs +9 -0
- package/src/Main.res +8 -1
- package/src/Main.res.mjs +3 -3
- package/src/Persistence.res +11 -1
- package/src/Persistence.res.mjs +6 -2
- package/src/PgStorage.res +1 -1
- package/src/PgStorage.res.mjs +1 -1
- package/src/SimulateItems.res +13 -6
- package/src/SimulateItems.res.mjs +7 -6
- package/src/TestIndexer.res +6 -5
- package/src/TestIndexer.res.mjs +5 -4
- package/src/UserContext.res +51 -358
- package/src/UserContext.res.mjs +35 -271
- package/src/db/InternalTable.res +1 -1
- package/src/db/InternalTable.res.mjs +2 -1
- package/src/sources/ChainSources.res +72 -0
- package/src/sources/ChainSources.res.mjs +55 -0
- package/src/sources/EvmHyperSyncSource.res +10 -22
- package/src/sources/EvmHyperSyncSource.res.mjs +9 -41
- package/src/sources/FuelHyperSyncSource.res +10 -18
- package/src/sources/FuelHyperSyncSource.res.mjs +8 -38
- package/src/sources/HyperSync.res +31 -0
- package/src/sources/HyperSync.res.mjs +31 -0
- package/src/sources/HyperSync.resi +16 -0
- package/src/sources/StartBlockResolver.res +173 -0
- package/src/sources/StartBlockResolver.res.mjs +134 -0
- package/src/sources/Svm.res +0 -51
- package/src/sources/Svm.res.mjs +0 -46
- package/src/sources/SvmHyperSyncSource.res +20 -9
- package/src/sources/SvmHyperSyncSource.res.mjs +34 -12
- package/svm.schema.json +78 -63
- package/src/subgraph/blocks.ts +0 -176
- package/src/subgraph/calls.ts +0 -217
- package/src/subgraph/conformance.ts +0 -102
- package/src/subgraph/division.ts +0 -133
- package/src/subgraph/errors.ts +0 -90
- package/src/subgraph/graph-ts-types/VERSION +0 -2
- package/src/subgraph/graph-ts-types/chain/arweave.d.ts +0 -70
- package/src/subgraph/graph-ts-types/chain/cosmos.d.ts +0 -327
- package/src/subgraph/graph-ts-types/chain/ethereum.d.ts +0 -233
- package/src/subgraph/graph-ts-types/chain/near.d.ts +0 -253
- package/src/subgraph/graph-ts-types/chain/starknet.d.ts +0 -32
- package/src/subgraph/graph-ts-types/common/collections.d.ts +0 -136
- package/src/subgraph/graph-ts-types/common/conversion.d.ts +0 -11
- package/src/subgraph/graph-ts-types/common/datasource.d.ts +0 -30
- package/src/subgraph/graph-ts-types/common/eager-offset.d.ts +0 -0
- package/src/subgraph/graph-ts-types/common/json.d.ts +0 -17
- package/src/subgraph/graph-ts-types/common/numbers.d.ts +0 -120
- package/src/subgraph/graph-ts-types/common/value.d.ts +0 -120
- package/src/subgraph/graph-ts-types/common/yaml.d.ts +0 -90
- package/src/subgraph/graph-ts-types/global/global.d.ts +0 -194
- package/src/subgraph/graph-ts-types/helper-functions.d.ts +0 -22
- package/src/subgraph/graph-ts-types/index.d.ts +0 -102
- package/src/subgraph/graph-ts.ts +0 -1948
- package/src/subgraph/hosts.ts +0 -148
- package/src/subgraph/runtime.ts +0 -863
- package/src/subgraph/scope.ts +0 -66
package/src/UserContext.res.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Utils from "./Utils.res.mjs";
|
|
4
|
-
import * as ChainId from "./ChainId.res.mjs";
|
|
5
4
|
import * as Logging from "./Logging.res.mjs";
|
|
6
5
|
import * as Internal from "./Internal.res.mjs";
|
|
7
6
|
import * as Ecosystem from "./Ecosystem.res.mjs";
|
|
@@ -13,70 +12,8 @@ import * as InMemoryStore from "./InMemoryStore.res.mjs";
|
|
|
13
12
|
import * as InMemoryTable from "./InMemoryTable.res.mjs";
|
|
14
13
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
15
14
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
16
|
-
import * as Stdlib_Promise from "@rescript/runtime/lib/es6/Stdlib_Promise.js";
|
|
17
15
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
18
16
|
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
19
|
-
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
20
|
-
|
|
21
|
-
let Suspend = /* @__PURE__ */Primitive_exceptions.create("UserContext.Suspend");
|
|
22
|
-
|
|
23
|
-
function isSuspend(exn) {
|
|
24
|
-
return exn.RE_EXN_ID === Suspend;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function makeSyncState() {
|
|
28
|
-
return {
|
|
29
|
-
status: "Active",
|
|
30
|
-
pending: undefined,
|
|
31
|
-
memo: undefined
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function getPending(sync) {
|
|
36
|
-
let pending = sync.pending;
|
|
37
|
-
if (pending !== undefined) {
|
|
38
|
-
return pending;
|
|
39
|
-
}
|
|
40
|
-
let pending$1 = [];
|
|
41
|
-
sync.pending = pending$1;
|
|
42
|
-
return pending$1;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function getMemo(sync) {
|
|
46
|
-
let memo = sync.memo;
|
|
47
|
-
if (memo !== undefined) {
|
|
48
|
-
return memo;
|
|
49
|
-
}
|
|
50
|
-
let memo$1 = {};
|
|
51
|
-
sync.memo = memo$1;
|
|
52
|
-
return memo$1;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function checkStatusOrThrow(params, access) {
|
|
56
|
-
let exn = params.sync.status;
|
|
57
|
-
if (typeof exn !== "object") {
|
|
58
|
-
if (exn === "Active") {
|
|
59
|
-
return;
|
|
60
|
-
} else {
|
|
61
|
-
return ErrorHandling.mkLogAndRaise(Ecosystem.getItemLogger(params.item, params.config.ecosystem), undefined, new Error(`Impossible to access ` + access + ` after the handler is resolved. Make sure you didn't miss an await in the handler.`));
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
throw exn._0;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function scheduleAndSuspend(params, promise) {
|
|
68
|
-
getPending(params.sync).push(promise);
|
|
69
|
-
params.sync.status = {
|
|
70
|
-
TAG: "Aborted",
|
|
71
|
-
_0: {
|
|
72
|
-
RE_EXN_ID: Suspend
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
throw {
|
|
76
|
-
RE_EXN_ID: Suspend,
|
|
77
|
-
Error: new Error()
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
17
|
|
|
81
18
|
let paramsByThis = new WeakMap();
|
|
82
19
|
|
|
@@ -110,69 +47,28 @@ var EffectContext = function(params, chainId, effectName, defaultShouldCache, ca
|
|
|
110
47
|
EffectContext.prototype = effectContextPrototype;
|
|
111
48
|
;
|
|
112
49
|
|
|
113
|
-
function prepareEffectCall(params, effect, input, caller) {
|
|
114
|
-
let isCrossChain = effect => Stdlib_Option.getOr(effect.crossChain, params.config.defaultCrossChain);
|
|
115
|
-
let scope = isCrossChain(effect) ? "crossChain" : Internal.getItemChainId(params.item);
|
|
116
|
-
if (caller !== undefined && isCrossChain(caller) && !isCrossChain(effect)) {
|
|
117
|
-
Stdlib_JsError.throwWithMessage(`The cross-chain effect "` + caller.name + `" cannot call the chain-scoped effect "` + effect.name + `", because a cross-chain effect isn't tied to a single chain. Make "` + effect.name + `" cross-chain (\`crossChain: true\`), or make "` + caller.name + `" chain-scoped (\`crossChain: false\`).`);
|
|
118
|
-
}
|
|
119
|
-
let tmp;
|
|
120
|
-
tmp = scope === "crossChain" ? undefined : Primitive_option.some(scope);
|
|
121
|
-
let effectContext = new EffectContext(params, tmp, effect.name, effect.defaultShouldCache, (nested, nestedInput) => callEffectAsync(params, nested, nestedInput, effect));
|
|
122
|
-
let effectArgs_cacheKey = Utils.Hash.makeOrThrow(S$RescriptSchema.reverseConvertOrThrow(input, effect.input));
|
|
123
|
-
let effectArgs_checkpointId = params.checkpointId;
|
|
124
|
-
let effectArgs = {
|
|
125
|
-
input: input,
|
|
126
|
-
context: effectContext,
|
|
127
|
-
cacheKey: effectArgs_cacheKey,
|
|
128
|
-
checkpointId: effectArgs_checkpointId
|
|
129
|
-
};
|
|
130
|
-
return [
|
|
131
|
-
scope,
|
|
132
|
-
effectArgs
|
|
133
|
-
];
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function callEffectAsync(params, effect, input, caller) {
|
|
137
|
-
let match = prepareEffectCall(params, effect, input, caller);
|
|
138
|
-
return LoadLayer.loadEffect(params.loadManager, params.persistence, effect, match[1], match[0], params.indexerState, params.isPreload, params.item, params.config.ecosystem);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
50
|
function initEffect(params) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
function effectMemoKey(effect, scope, cacheKey) {
|
|
149
|
-
if (scope === "crossChain") {
|
|
150
|
-
return effect.name + `.` + cacheKey;
|
|
151
|
-
} else {
|
|
152
|
-
return effect.name + `.` + ChainId.toString(scope) + `.` + cacheKey;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function initEffectSync(params) {
|
|
157
|
-
return (effect, input) => {
|
|
158
|
-
checkStatusOrThrow(params, "context.effectSync");
|
|
159
|
-
let match = prepareEffectCall(params, effect, input, undefined);
|
|
160
|
-
let effectArgs = match[1];
|
|
161
|
-
let scope = match[0];
|
|
162
|
-
let memo = getMemo(params.sync);
|
|
163
|
-
let memoKey = effectMemoKey(effect, scope, effectArgs.cacheKey);
|
|
164
|
-
let output = memo[memoKey];
|
|
165
|
-
if (output !== undefined) {
|
|
166
|
-
return Primitive_option.valFromOption(output);
|
|
167
|
-
}
|
|
168
|
-
let inMemTable = InMemoryStore.getEffectInMemTable(params.indexerState, effect, scope);
|
|
169
|
-
if (!InMemoryStore.hasEffectOutput(inMemTable, effectArgs.cacheKey)) {
|
|
170
|
-
return scheduleAndSuspend(params, LoadLayer.loadEffect(params.loadManager, params.persistence, effect, effectArgs, scope, params.indexerState, params.isPreload, params.item, params.config.ecosystem));
|
|
51
|
+
let handlerChainId = Internal.getItemChainId(params.item);
|
|
52
|
+
let isCrossChain = effect => Stdlib_Option.getOr(effect.crossChain, params.config.defaultCrossChain);
|
|
53
|
+
let makeCaller = caller => ((effect, input) => {
|
|
54
|
+
let scope = isCrossChain(effect) ? "crossChain" : handlerChainId;
|
|
55
|
+
if (caller !== undefined && isCrossChain(caller) && !isCrossChain(effect)) {
|
|
56
|
+
Stdlib_JsError.throwWithMessage(`The cross-chain effect "` + caller.name + `" cannot call the chain-scoped effect "` + effect.name + `", because a cross-chain effect isn't tied to a single chain. Make "` + effect.name + `" cross-chain (\`crossChain: true\`), or make "` + caller.name + `" chain-scoped (\`crossChain: false\`).`);
|
|
171
57
|
}
|
|
172
|
-
let
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
58
|
+
let tmp;
|
|
59
|
+
tmp = scope === "crossChain" ? undefined : Primitive_option.some(scope);
|
|
60
|
+
let effectContext = new EffectContext(params, tmp, effect.name, effect.defaultShouldCache, makeCaller(effect));
|
|
61
|
+
let effectArgs_cacheKey = Utils.Hash.makeOrThrow(S$RescriptSchema.reverseConvertOrThrow(input, effect.input));
|
|
62
|
+
let effectArgs_checkpointId = params.checkpointId;
|
|
63
|
+
let effectArgs = {
|
|
64
|
+
input: input,
|
|
65
|
+
context: effectContext,
|
|
66
|
+
cacheKey: effectArgs_cacheKey,
|
|
67
|
+
checkpointId: effectArgs_checkpointId
|
|
68
|
+
};
|
|
69
|
+
return LoadLayer.loadEffect(params.loadManager, params.persistence, effect, effectArgs, scope, params.indexerState, params.isPreload, params.item, params.config.ecosystem);
|
|
70
|
+
});
|
|
71
|
+
return makeCaller(undefined);
|
|
176
72
|
}
|
|
177
73
|
|
|
178
74
|
function entityScope(params) {
|
|
@@ -201,83 +97,24 @@ function throwClickHouseReadOnly(entityConfig, op) {
|
|
|
201
97
|
return Stdlib_JsError.throwWithMessage(`context.` + entityConfig.name + `.` + op + `() is unavailable: ClickHouse storage is currently write-only. Follow Envio releases to be notified when ClickHouse supports both reads and writes from handlers.`);
|
|
202
98
|
}
|
|
203
99
|
|
|
204
|
-
function getSyncHandler(params, entityId) {
|
|
205
|
-
let inMemTable = InMemoryStore.getInMemTable(params.indexerState, params.entityConfig, entityScope(params));
|
|
206
|
-
if (entityId in inMemTable.latestEntityChangeById) {
|
|
207
|
-
return InMemoryTable.Entity.getUnsafe(inMemTable)(entityId);
|
|
208
|
-
} else {
|
|
209
|
-
return scheduleAndSuspend(params, LoadLayer.loadById(params.loadManager, params.persistence, params.entityConfig, entityScope(params), params.indexerState, params.isPreload, params.item, params.config.ecosystem, entityId));
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
function getWhereSyncHandler(params, filter) {
|
|
214
|
-
let entityConfig = params.entityConfig;
|
|
215
|
-
let inMemTable = InMemoryStore.getInMemTable(params.indexerState, entityConfig, entityScope(params));
|
|
216
|
-
let hasIndex = InMemoryTable.Entity.hasIndex(inMemTable);
|
|
217
|
-
let getOnIndex = InMemoryTable.Entity.getUnsafeOnIndex(inMemTable);
|
|
218
|
-
let filters = EntityFilter.parseGetWhereOrThrow(filter, entityConfig.name, entityConfig.table);
|
|
219
|
-
let missing = [];
|
|
220
|
-
let entities = [];
|
|
221
|
-
filters.forEach(filter => {
|
|
222
|
-
let filterKey = EntityFilter.toString(filter);
|
|
223
|
-
if (hasIndex(filterKey)) {
|
|
224
|
-
entities.push(...getOnIndex(filterKey));
|
|
225
|
-
} else {
|
|
226
|
-
missing.push(LoadLayer.loadByFilter(params.loadManager, params.persistence, entityConfig, entityScope(params), params.indexerState, params.isPreload, params.item, params.config.ecosystem, filter));
|
|
227
|
-
}
|
|
228
|
-
});
|
|
229
|
-
if (Utils.$$Array.notEmpty(missing)) {
|
|
230
|
-
let pending = getPending(params.sync);
|
|
231
|
-
missing.forEach(promise => {
|
|
232
|
-
pending.push(promise);
|
|
233
|
-
});
|
|
234
|
-
params.sync.status = {
|
|
235
|
-
TAG: "Aborted",
|
|
236
|
-
_0: {
|
|
237
|
-
RE_EXN_ID: Suspend
|
|
238
|
-
}
|
|
239
|
-
};
|
|
240
|
-
throw {
|
|
241
|
-
RE_EXN_ID: Suspend,
|
|
242
|
-
Error: new Error()
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
return entities;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
function getInBlockSyncHandler(params, entityId) {
|
|
249
|
-
let inMemTable = InMemoryStore.getInMemTable(params.indexerState, params.entityConfig, entityScope(params));
|
|
250
|
-
let change = inMemTable.latestEntityChangeById[entityId];
|
|
251
|
-
if (change !== undefined && change.checkpointId === params.checkpointId) {
|
|
252
|
-
return InMemoryTable.Entity.mapChangeToEntity(change);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
100
|
let entityTraps_get = (params, prop) => {
|
|
257
|
-
checkStatusOrThrow(params, `context.` + params.entityConfig.name + `.` + prop);
|
|
258
101
|
let isClickHouseOnly = !params.entityConfig.storage.postgres;
|
|
259
|
-
let set = params.isPreload ? noopSet : entity => {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
checkpointId: params.checkpointId
|
|
266
|
-
});
|
|
267
|
-
};
|
|
102
|
+
let set = params.isPreload ? noopSet : entity => InMemoryTable.Entity.set(InMemoryStore.getInMemTable(params.indexerState, params.entityConfig, entityScope(params)), IndexerState.committedCheckpointId(params.indexerState), {
|
|
103
|
+
type: "SET",
|
|
104
|
+
entityId: entity.id,
|
|
105
|
+
entity: entity,
|
|
106
|
+
checkpointId: params.checkpointId
|
|
107
|
+
});
|
|
268
108
|
switch (prop) {
|
|
269
109
|
case "deleteUnsafe" :
|
|
270
110
|
if (params.isPreload) {
|
|
271
111
|
return noopDeleteUnsafe;
|
|
272
112
|
} else {
|
|
273
|
-
return entityId => {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
checkpointId: params.checkpointId
|
|
279
|
-
});
|
|
280
|
-
};
|
|
113
|
+
return entityId => InMemoryTable.Entity.set(InMemoryStore.getInMemTable(params.indexerState, params.entityConfig, entityScope(params)), IndexerState.committedCheckpointId(params.indexerState), {
|
|
114
|
+
type: "DELETE",
|
|
115
|
+
entityId: entityId,
|
|
116
|
+
checkpointId: params.checkpointId
|
|
117
|
+
});
|
|
281
118
|
}
|
|
282
119
|
case "get" :
|
|
283
120
|
if (isClickHouseOnly) {
|
|
@@ -285,8 +122,6 @@ let entityTraps_get = (params, prop) => {
|
|
|
285
122
|
} else {
|
|
286
123
|
return entityId => LoadLayer.loadById(params.loadManager, params.persistence, params.entityConfig, entityScope(params), params.indexerState, params.isPreload, params.item, params.config.ecosystem, entityId);
|
|
287
124
|
}
|
|
288
|
-
case "getInBlockSync" :
|
|
289
|
-
return entityId => getInBlockSyncHandler(params, entityId);
|
|
290
125
|
case "getOrCreate" :
|
|
291
126
|
if (isClickHouseOnly) {
|
|
292
127
|
return _entity => throwClickHouseReadOnly(params.entityConfig, "getOrCreate");
|
|
@@ -312,16 +147,12 @@ let entityTraps_get = (params, prop) => {
|
|
|
312
147
|
}
|
|
313
148
|
});
|
|
314
149
|
}
|
|
315
|
-
case "getSync" :
|
|
316
|
-
return entityId => getSyncHandler(params, entityId);
|
|
317
150
|
case "getWhere" :
|
|
318
151
|
if (isClickHouseOnly) {
|
|
319
152
|
return _filter => throwClickHouseReadOnly(params.entityConfig, "getWhere");
|
|
320
153
|
} else {
|
|
321
154
|
return filter => getWhereHandler(params, filter);
|
|
322
155
|
}
|
|
323
|
-
case "getWhereSync" :
|
|
324
|
-
return filter => getWhereSyncHandler(params, filter);
|
|
325
156
|
case "set" :
|
|
326
157
|
return set;
|
|
327
158
|
default:
|
|
@@ -333,63 +164,16 @@ let entityTraps = {
|
|
|
333
164
|
get: entityTraps_get
|
|
334
165
|
};
|
|
335
166
|
|
|
336
|
-
async function runSyncRound(params, fn, round) {
|
|
337
|
-
if (round > 10000) {
|
|
338
|
-
Stdlib_JsError.throwWithMessage(`The handler suspended on a synchronous read too many times: gave up after ` + (10000).toString() + ` rounds. This usually means the code isn't deterministic across reruns.`);
|
|
339
|
-
}
|
|
340
|
-
params.sync.status = "Active";
|
|
341
|
-
params.sync.pending = undefined;
|
|
342
|
-
let suspended;
|
|
343
|
-
try {
|
|
344
|
-
fn();
|
|
345
|
-
suspended = false;
|
|
346
|
-
} catch (raw_exn) {
|
|
347
|
-
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
348
|
-
if (exn.RE_EXN_ID === Suspend) {
|
|
349
|
-
suspended = true;
|
|
350
|
-
} else {
|
|
351
|
-
let pending = params.sync.pending;
|
|
352
|
-
if (pending !== undefined) {
|
|
353
|
-
params.sync.pending = undefined;
|
|
354
|
-
pending.forEach(promise => {
|
|
355
|
-
Utils.$$Promise.silentCatch(promise);
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
throw exn;
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
let pending$1 = params.sync.pending;
|
|
362
|
-
if (pending$1 === undefined) {
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
params.sync.pending = undefined;
|
|
366
|
-
if (suspended) {
|
|
367
|
-
let errors = [];
|
|
368
|
-
await Promise.all(pending$1.map(promise => Stdlib_Promise.$$catch(promise, exn => {
|
|
369
|
-
errors.push(exn);
|
|
370
|
-
return Promise.resolve();
|
|
371
|
-
})));
|
|
372
|
-
let exn$1 = errors[0];
|
|
373
|
-
if (exn$1 !== undefined) {
|
|
374
|
-
throw exn$1;
|
|
375
|
-
}
|
|
376
|
-
return await runSyncRound(params, fn, round + 1 | 0);
|
|
377
|
-
}
|
|
378
|
-
pending$1.forEach(promise => {
|
|
379
|
-
Utils.$$Promise.silentCatch(promise);
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
|
|
383
167
|
let handlerTraps_get = (params, prop) => {
|
|
384
|
-
|
|
168
|
+
if (params.isResolved) {
|
|
169
|
+
ErrorHandling.mkLogAndRaise(Ecosystem.getItemLogger(params.item, params.config.ecosystem), undefined, new Error(`Impossible to access context.` + prop + ` after the handler is resolved. Make sure you didn't miss an await in the handler.`));
|
|
170
|
+
}
|
|
385
171
|
switch (prop) {
|
|
386
172
|
case "chain" :
|
|
387
173
|
let chainId = Internal.getItemChainId(params.item);
|
|
388
174
|
return params.chains[chainId];
|
|
389
175
|
case "effect" :
|
|
390
176
|
return initEffect(params);
|
|
391
|
-
case "effectSync" :
|
|
392
|
-
return initEffectSync(params);
|
|
393
177
|
case "isPreload" :
|
|
394
178
|
return params.isPreload;
|
|
395
179
|
case "log" :
|
|
@@ -398,8 +182,6 @@ let handlerTraps_get = (params, prop) => {
|
|
|
398
182
|
} else {
|
|
399
183
|
return Ecosystem.getItemUserLogger(params.item, params.config.ecosystem);
|
|
400
184
|
}
|
|
401
|
-
case "runSync" :
|
|
402
|
-
return fn => runSyncRound(params, fn, 1);
|
|
403
185
|
default:
|
|
404
186
|
let entityConfig = params.config.userEntitiesByName[prop];
|
|
405
187
|
if (entityConfig !== undefined) {
|
|
@@ -412,7 +194,7 @@ let handlerTraps_get = (params, prop) => {
|
|
|
412
194
|
isPreload: params.isPreload,
|
|
413
195
|
chains: params.chains,
|
|
414
196
|
config: params.config,
|
|
415
|
-
|
|
197
|
+
isResolved: params.isResolved,
|
|
416
198
|
entityConfig: entityConfig
|
|
417
199
|
}, entityTraps);
|
|
418
200
|
} else {
|
|
@@ -429,34 +211,16 @@ function getHandlerContext(params) {
|
|
|
429
211
|
return new Proxy(params, handlerTraps);
|
|
430
212
|
}
|
|
431
213
|
|
|
432
|
-
let maxSyncRounds = 10000;
|
|
433
|
-
|
|
434
214
|
export {
|
|
435
|
-
Suspend,
|
|
436
|
-
isSuspend,
|
|
437
|
-
makeSyncState,
|
|
438
|
-
getPending,
|
|
439
|
-
getMemo,
|
|
440
|
-
checkStatusOrThrow,
|
|
441
|
-
scheduleAndSuspend,
|
|
442
215
|
paramsByThis,
|
|
443
216
|
effectContextPrototype,
|
|
444
|
-
prepareEffectCall,
|
|
445
|
-
callEffectAsync,
|
|
446
217
|
initEffect,
|
|
447
|
-
effectMemoKey,
|
|
448
|
-
initEffectSync,
|
|
449
218
|
entityScope,
|
|
450
219
|
getWhereHandler,
|
|
451
220
|
noopSet,
|
|
452
221
|
noopDeleteUnsafe,
|
|
453
222
|
throwClickHouseReadOnly,
|
|
454
|
-
getSyncHandler,
|
|
455
|
-
getWhereSyncHandler,
|
|
456
|
-
getInBlockSyncHandler,
|
|
457
223
|
entityTraps,
|
|
458
|
-
maxSyncRounds,
|
|
459
|
-
runSyncRound,
|
|
460
224
|
handlerTraps,
|
|
461
225
|
getHandlerContext,
|
|
462
226
|
}
|
package/src/db/InternalTable.res
CHANGED
|
@@ -272,7 +272,7 @@ module Chains = {
|
|
|
272
272
|
{
|
|
273
273
|
id: chainConfig.id,
|
|
274
274
|
ecosystem: (chainConfig.ecosystem: Ecosystem.name :> string),
|
|
275
|
-
startBlock: chainConfig.
|
|
275
|
+
startBlock: chainConfig->Config.startBlockOrThrow,
|
|
276
276
|
endBlock: chainConfig.endBlock->Null.fromOption,
|
|
277
277
|
maxReorgDepth: chainConfig.maxReorgDepth,
|
|
278
278
|
blockHeight: 0,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as Table from "./Table.res.mjs";
|
|
4
4
|
import * as Utils from "../Utils.res.mjs";
|
|
5
|
+
import * as Config from "../Config.res.mjs";
|
|
5
6
|
import * as Address from "../Address.res.mjs";
|
|
6
7
|
import * as ChainId from "../ChainId.res.mjs";
|
|
7
8
|
import * as Postgres from "../bindings/Postgres.res.mjs";
|
|
@@ -181,7 +182,7 @@ function initialFromConfig(chainConfig) {
|
|
|
181
182
|
return {
|
|
182
183
|
id: chainConfig.id,
|
|
183
184
|
ecosystem: chainConfig.ecosystem,
|
|
184
|
-
start_block: chainConfig
|
|
185
|
+
start_block: Config.startBlockOrThrow(chainConfig),
|
|
185
186
|
end_block: Stdlib_Null.fromOption(chainConfig.endBlock),
|
|
186
187
|
max_reorg_depth: chainConfig.maxReorgDepth,
|
|
187
188
|
source_block: 0,
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// Sits below `ChainState`/`Persistence` in the module graph so that
|
|
2
|
+
// `StartBlockResolver` (called from `Persistence.init`) can build a chain's
|
|
3
|
+
// sources without a dependency cycle.
|
|
4
|
+
let make = (
|
|
5
|
+
~chainConfig: Config.chain,
|
|
6
|
+
~onEventRegistrations: array<Internal.onEventRegistration>,
|
|
7
|
+
~addressStore: AddressStore.t,
|
|
8
|
+
~lowercaseAddresses: bool,
|
|
9
|
+
): array<Source.t> => {
|
|
10
|
+
let chainId = chainConfig.id
|
|
11
|
+
switch chainConfig.sourceConfig {
|
|
12
|
+
| Config.EvmSourceConfig({hypersync, rpcs}) =>
|
|
13
|
+
let evmRpcs: array<EvmChain.rpc> = rpcs->Array.map((rpc): EvmChain.rpc => {
|
|
14
|
+
let syncConfig = rpc.syncConfig
|
|
15
|
+
let ws = rpc.ws
|
|
16
|
+
let headers = rpc.headers
|
|
17
|
+
{
|
|
18
|
+
url: rpc.url,
|
|
19
|
+
sourceFor: rpc.sourceFor,
|
|
20
|
+
?syncConfig,
|
|
21
|
+
?ws,
|
|
22
|
+
?headers,
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
EvmChain.makeSources(
|
|
26
|
+
~chainId,
|
|
27
|
+
~onEventRegistrations=onEventRegistrations->(
|
|
28
|
+
Utils.magic: array<Internal.onEventRegistration> => array<Internal.evmOnEventRegistration>
|
|
29
|
+
),
|
|
30
|
+
~hyperSync=hypersync,
|
|
31
|
+
~rpcs=evmRpcs,
|
|
32
|
+
~lowercaseAddresses,
|
|
33
|
+
~addressStore,
|
|
34
|
+
)
|
|
35
|
+
| Config.FuelSourceConfig({hypersync}) => [
|
|
36
|
+
FuelHyperSyncSource.make({
|
|
37
|
+
chainId,
|
|
38
|
+
endpointUrl: hypersync,
|
|
39
|
+
apiToken: Env.envioApiToken,
|
|
40
|
+
onEventRegistrations,
|
|
41
|
+
addressStore,
|
|
42
|
+
}),
|
|
43
|
+
]
|
|
44
|
+
| Config.SvmSourceConfig({hypersync}) => [
|
|
45
|
+
SvmHyperSyncSource.make({
|
|
46
|
+
chainId,
|
|
47
|
+
endpointUrl: hypersync,
|
|
48
|
+
apiToken: Env.envioApiToken,
|
|
49
|
+
onEventRegistrations: onEventRegistrations->(
|
|
50
|
+
Utils.magic: array<Internal.onEventRegistration> => array<
|
|
51
|
+
Internal.svmOnEventRegistration,
|
|
52
|
+
>
|
|
53
|
+
),
|
|
54
|
+
clientTimeoutMillis: Env.hyperSyncClientTimeoutMillis,
|
|
55
|
+
addressStore,
|
|
56
|
+
}),
|
|
57
|
+
]
|
|
58
|
+
| Config.SimulateSourceConfig({items, endBlock, ?transactionStore, ?blockStore}) => [
|
|
59
|
+
SimulateSource.make(
|
|
60
|
+
~items,
|
|
61
|
+
~endBlock,
|
|
62
|
+
~chainId,
|
|
63
|
+
~addressStore,
|
|
64
|
+
~ecosystem=chainConfig.ecosystem,
|
|
65
|
+
~transactionStore,
|
|
66
|
+
~blockStore,
|
|
67
|
+
),
|
|
68
|
+
]
|
|
69
|
+
// For tests: use ready-to-use sources directly
|
|
70
|
+
| Config.CustomSources(sources) => sources
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Env from "../Env.res.mjs";
|
|
4
|
+
import * as EvmChain from "./EvmChain.res.mjs";
|
|
5
|
+
import * as SimulateSource from "./SimulateSource.res.mjs";
|
|
6
|
+
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
7
|
+
import * as SvmHyperSyncSource from "./SvmHyperSyncSource.res.mjs";
|
|
8
|
+
import * as FuelHyperSyncSource from "./FuelHyperSyncSource.res.mjs";
|
|
9
|
+
|
|
10
|
+
function make(chainConfig, onEventRegistrations, addressStore, lowercaseAddresses) {
|
|
11
|
+
let chainId = chainConfig.id;
|
|
12
|
+
let sources = chainConfig.sourceConfig;
|
|
13
|
+
switch (sources.TAG) {
|
|
14
|
+
case "EvmSourceConfig" :
|
|
15
|
+
let evmRpcs = sources.rpcs.map(rpc => {
|
|
16
|
+
let syncConfig = rpc.syncConfig;
|
|
17
|
+
let ws = rpc.ws;
|
|
18
|
+
let headers = rpc.headers;
|
|
19
|
+
return {
|
|
20
|
+
url: rpc.url,
|
|
21
|
+
sourceFor: rpc.sourceFor,
|
|
22
|
+
syncConfig: syncConfig,
|
|
23
|
+
ws: ws,
|
|
24
|
+
headers: headers
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
return EvmChain.makeSources(chainId, onEventRegistrations, sources.hypersync, evmRpcs, lowercaseAddresses, addressStore);
|
|
28
|
+
case "FuelSourceConfig" :
|
|
29
|
+
return [FuelHyperSyncSource.make({
|
|
30
|
+
chainId: chainId,
|
|
31
|
+
endpointUrl: sources.hypersync,
|
|
32
|
+
apiToken: Env.envioApiToken,
|
|
33
|
+
onEventRegistrations: onEventRegistrations,
|
|
34
|
+
addressStore: addressStore
|
|
35
|
+
})];
|
|
36
|
+
case "SvmSourceConfig" :
|
|
37
|
+
return [SvmHyperSyncSource.make({
|
|
38
|
+
chainId: chainId,
|
|
39
|
+
endpointUrl: sources.hypersync,
|
|
40
|
+
apiToken: Env.envioApiToken,
|
|
41
|
+
onEventRegistrations: onEventRegistrations,
|
|
42
|
+
clientTimeoutMillis: Env.hyperSyncClientTimeoutMillis,
|
|
43
|
+
addressStore: addressStore
|
|
44
|
+
})];
|
|
45
|
+
case "SimulateSourceConfig" :
|
|
46
|
+
return [SimulateSource.make(sources.items, sources.endBlock, chainId, addressStore, chainConfig.ecosystem, Primitive_option.some(sources.transactionStore), Primitive_option.some(sources.blockStore))];
|
|
47
|
+
case "CustomSources" :
|
|
48
|
+
return sources._0;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
make,
|
|
54
|
+
}
|
|
55
|
+
/* Env Not a pure module */
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
open Source
|
|
2
2
|
|
|
3
|
-
// Surfaced by the HyperSync client (Rust) when HyperSync rejects the API
|
|
4
|
-
// token. The corrupted-token test feeds the real server error (from the query
|
|
5
|
-
// endpoint; the edge no longer 401s malformed tokens on /height) through this
|
|
6
|
-
// check so it can't silently drift away from what getHeightOrThrow guards on.
|
|
7
|
-
let isUnauthorizedError = (message: string) => message->String.includes("401 Unauthorized")
|
|
8
|
-
|
|
9
3
|
type options = {
|
|
10
4
|
chainId: ChainId.t,
|
|
11
5
|
endpointUrl: string,
|
|
@@ -37,13 +31,11 @@ let make = (
|
|
|
37
31
|
): t => {
|
|
38
32
|
let name = "HyperSync"
|
|
39
33
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
46
|
-
}
|
|
34
|
+
// Per source, so one rejected token is reported once rather than on every
|
|
35
|
+
// height retry for the life of the process.
|
|
36
|
+
let unauthorizedWarned = ref(false)
|
|
37
|
+
|
|
38
|
+
let apiToken = apiToken->HyperSync.requireApiToken
|
|
47
39
|
|
|
48
40
|
let client = switch HyperSyncClient.make(
|
|
49
41
|
~url=endpointUrl,
|
|
@@ -213,15 +205,11 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
213
205
|
let height = try {
|
|
214
206
|
await client.getHeight()
|
|
215
207
|
} catch {
|
|
216
|
-
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
let _ = await Promise.make((_, _) => ())
|
|
222
|
-
0
|
|
223
|
-
| _ => throw(JsExn(e))
|
|
224
|
-
}
|
|
208
|
+
| exn =>
|
|
209
|
+
exn->HyperSync.rethrowLoggingUnauthorized(
|
|
210
|
+
~warned=unauthorizedWarned,
|
|
211
|
+
~product="HyperSync",
|
|
212
|
+
)
|
|
225
213
|
}
|
|
226
214
|
let seconds = timerRef->Performance.secondsSince
|
|
227
215
|
{height, requestStats: [{method: "getHeight", seconds}]}
|