envio 3.0.0-alpha.1 → 3.0.0-alpha.2
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 +19 -15
- package/fuel.schema.json +3 -10
- package/package.json +14 -11
- package/rescript.json +1 -1
- package/src/Config.res +4 -7
- package/src/Config.res.mjs +4 -6
- package/src/{Platform.res → Ecosystem.res} +3 -3
- package/src/{Platform.res.mjs → Ecosystem.res.mjs} +2 -2
- package/src/Env.res +244 -0
- package/src/Env.res.mjs +273 -0
- package/src/EventRegister.res +4 -15
- package/src/EventRegister.res.mjs +3 -9
- package/src/EventRegister.resi +2 -8
- package/src/Internal.gen.ts +3 -14
- package/src/Internal.res +2 -11
- package/src/bindings/EventSource.res +13 -0
- package/src/bindings/EventSource.res.mjs +2 -0
- package/src/sources/HyperSyncHeightStream.res +179 -0
- package/src/sources/HyperSyncHeightStream.res.mjs +127 -0
- package/src/sources/HyperSyncSource.res +2 -60
- package/src/sources/HyperSyncSource.res.mjs +5 -61
package/src/Env.res.mjs
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as EnvSafe from "rescript-envsafe/src/EnvSafe.res.mjs";
|
|
4
|
+
import * as Logging from "./Logging.res.mjs";
|
|
5
|
+
import * as Postgres from "./bindings/Postgres.res.mjs";
|
|
6
|
+
import * as Caml_option from "rescript/lib/es6/caml_option.js";
|
|
7
|
+
import * as HyperSyncClient from "./sources/HyperSyncClient.res.mjs";
|
|
8
|
+
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
9
|
+
|
|
10
|
+
import 'dotenv/config'
|
|
11
|
+
;
|
|
12
|
+
|
|
13
|
+
var envSafe = EnvSafe.make(undefined);
|
|
14
|
+
|
|
15
|
+
function getLogLevelConfig(name, $$default) {
|
|
16
|
+
return EnvSafe.get(envSafe, name, S$RescriptSchema.$$enum([
|
|
17
|
+
"trace",
|
|
18
|
+
"debug",
|
|
19
|
+
"info",
|
|
20
|
+
"warn",
|
|
21
|
+
"error",
|
|
22
|
+
"fatal",
|
|
23
|
+
"udebug",
|
|
24
|
+
"uinfo",
|
|
25
|
+
"uwarn",
|
|
26
|
+
"uerror"
|
|
27
|
+
]), undefined, $$default, undefined, undefined);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
var updateSyncTimeOnRestart = EnvSafe.get(envSafe, "UPDATE_SYNC_TIME_ON_RESTART", S$RescriptSchema.bool, undefined, true, undefined, undefined);
|
|
31
|
+
|
|
32
|
+
var batchSize = EnvSafe.get(envSafe, "MAX_BATCH_SIZE", S$RescriptSchema.option(S$RescriptSchema.$$int), undefined, undefined, undefined, undefined);
|
|
33
|
+
|
|
34
|
+
var targetBufferSize = EnvSafe.get(envSafe, "ENVIO_INDEXING_MAX_BUFFER_SIZE", S$RescriptSchema.option(S$RescriptSchema.$$int), undefined, undefined, undefined, undefined);
|
|
35
|
+
|
|
36
|
+
var maxAddrInPartition = EnvSafe.get(envSafe, "MAX_PARTITION_SIZE", S$RescriptSchema.$$int, undefined, 5000, undefined, undefined);
|
|
37
|
+
|
|
38
|
+
var maxPartitionConcurrency = EnvSafe.get(envSafe, "ENVIO_MAX_PARTITION_CONCURRENCY", S$RescriptSchema.$$int, undefined, 10, undefined, undefined);
|
|
39
|
+
|
|
40
|
+
var indexingBlockLag = EnvSafe.get(envSafe, "ENVIO_INDEXING_BLOCK_LAG", S$RescriptSchema.option(S$RescriptSchema.$$int), undefined, undefined, undefined, undefined);
|
|
41
|
+
|
|
42
|
+
var serverPort = EnvSafe.get(envSafe, "ENVIO_INDEXER_PORT", S$RescriptSchema.port(S$RescriptSchema.$$int, undefined), undefined, EnvSafe.get(envSafe, "METRICS_PORT", S$RescriptSchema.port(S$RescriptSchema.$$int, undefined), undefined, 9898, undefined, undefined), undefined, undefined);
|
|
43
|
+
|
|
44
|
+
var tuiOffEnvVar = EnvSafe.get(envSafe, "TUI_OFF", S$RescriptSchema.bool, undefined, false, undefined, undefined);
|
|
45
|
+
|
|
46
|
+
var logFilePath = EnvSafe.get(envSafe, "LOG_FILE", S$RescriptSchema.string, undefined, "logs/envio.log", undefined, undefined);
|
|
47
|
+
|
|
48
|
+
var userLogLevel = getLogLevelConfig("LOG_LEVEL", "info");
|
|
49
|
+
|
|
50
|
+
var defaultFileLogLevel = getLogLevelConfig("FILE_LOG_LEVEL", "trace");
|
|
51
|
+
|
|
52
|
+
var prodEnvioAppUrl = "https://envio.dev";
|
|
53
|
+
|
|
54
|
+
var envioAppUrl = EnvSafe.get(envSafe, "ENVIO_APP", S$RescriptSchema.string, undefined, prodEnvioAppUrl, undefined, undefined);
|
|
55
|
+
|
|
56
|
+
var envioApiToken = EnvSafe.get(envSafe, "ENVIO_API_TOKEN", S$RescriptSchema.option(S$RescriptSchema.string), undefined, undefined, undefined, undefined);
|
|
57
|
+
|
|
58
|
+
var hyperSyncClientTimeoutMillis = EnvSafe.get(envSafe, "ENVIO_HYPERSYNC_CLIENT_TIMEOUT_MILLIS", S$RescriptSchema.$$int, undefined, 120000, undefined, undefined);
|
|
59
|
+
|
|
60
|
+
var hyperSyncClientMaxRetries = EnvSafe.get(envSafe, "ENVIO_HYPERSYNC_CLIENT_MAX_RETRIES", S$RescriptSchema.$$int, undefined, 0, undefined, undefined);
|
|
61
|
+
|
|
62
|
+
var hypersyncClientSerializationFormat = EnvSafe.get(envSafe, "ENVIO_HYPERSYNC_CLIENT_SERIALIZATION_FORMAT", HyperSyncClient.serializationFormatSchema, undefined, "CapnProto", undefined, undefined);
|
|
63
|
+
|
|
64
|
+
var hypersyncClientEnableQueryCaching = EnvSafe.get(envSafe, "ENVIO_HYPERSYNC_CLIENT_ENABLE_QUERY_CACHING", S$RescriptSchema.bool, undefined, true, undefined, undefined);
|
|
65
|
+
|
|
66
|
+
var schema = S$RescriptSchema.$$enum([
|
|
67
|
+
true,
|
|
68
|
+
false,
|
|
69
|
+
"json-file",
|
|
70
|
+
"prometheus"
|
|
71
|
+
]);
|
|
72
|
+
|
|
73
|
+
var $$default = false;
|
|
74
|
+
|
|
75
|
+
function shouldSaveJsonFile(self) {
|
|
76
|
+
if (typeof self !== "boolean") {
|
|
77
|
+
if (self === "json-file") {
|
|
78
|
+
return true;
|
|
79
|
+
} else {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
} else if (self) {
|
|
83
|
+
return true;
|
|
84
|
+
} else {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function shouldSavePrometheus(param) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function shouldSaveData(self) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
var SaveDataStrategy = {
|
|
98
|
+
schema: schema,
|
|
99
|
+
$$default: $$default,
|
|
100
|
+
shouldSaveJsonFile: shouldSaveJsonFile,
|
|
101
|
+
shouldSavePrometheus: shouldSavePrometheus,
|
|
102
|
+
shouldSaveData: shouldSaveData
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
var saveDataStrategy = EnvSafe.get(envSafe, "ENVIO_SAVE_BENCHMARK_DATA", schema, undefined, Caml_option.some($$default), undefined, undefined);
|
|
106
|
+
|
|
107
|
+
var shouldSaveData$1 = shouldSaveData(saveDataStrategy);
|
|
108
|
+
|
|
109
|
+
var shouldSaveStdDev = shouldSaveJsonFile(saveDataStrategy);
|
|
110
|
+
|
|
111
|
+
var Benchmark = {
|
|
112
|
+
SaveDataStrategy: SaveDataStrategy,
|
|
113
|
+
saveDataStrategy: saveDataStrategy,
|
|
114
|
+
shouldSaveData: shouldSaveData$1,
|
|
115
|
+
shouldSaveStdDev: shouldSaveStdDev
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
var logStrategy = EnvSafe.get(envSafe, "LOG_STRATEGY", S$RescriptSchema.$$enum([
|
|
119
|
+
"ecs-file",
|
|
120
|
+
"ecs-console",
|
|
121
|
+
"ecs-console-multistream",
|
|
122
|
+
"file-only",
|
|
123
|
+
"console-raw",
|
|
124
|
+
"console-pretty",
|
|
125
|
+
"both-prettyconsole"
|
|
126
|
+
]), undefined, "console-pretty", undefined, undefined);
|
|
127
|
+
|
|
128
|
+
Logging.setLogger(Logging.makeLogger(logStrategy, logFilePath, defaultFileLogLevel, userLogLevel));
|
|
129
|
+
|
|
130
|
+
var host = EnvSafe.get(envSafe, "ENVIO_PG_HOST", S$RescriptSchema.string, undefined, undefined, "localhost", undefined);
|
|
131
|
+
|
|
132
|
+
var port = EnvSafe.get(envSafe, "ENVIO_PG_PORT", S$RescriptSchema.port(S$RescriptSchema.$$int, undefined), undefined, undefined, 5433, undefined);
|
|
133
|
+
|
|
134
|
+
var user = EnvSafe.get(envSafe, "ENVIO_PG_USER", S$RescriptSchema.string, undefined, undefined, "postgres", undefined);
|
|
135
|
+
|
|
136
|
+
var password = EnvSafe.get(envSafe, "ENVIO_PG_PASSWORD", S$RescriptSchema.string, undefined, EnvSafe.get(envSafe, "ENVIO_POSTGRES_PASSWORD", S$RescriptSchema.string, undefined, "testing", undefined, undefined), undefined, undefined);
|
|
137
|
+
|
|
138
|
+
var database = EnvSafe.get(envSafe, "ENVIO_PG_DATABASE", S$RescriptSchema.string, undefined, undefined, "envio-dev", undefined);
|
|
139
|
+
|
|
140
|
+
var publicSchema = EnvSafe.get(envSafe, "ENVIO_PG_PUBLIC_SCHEMA", S$RescriptSchema.string, undefined, "public", undefined, undefined);
|
|
141
|
+
|
|
142
|
+
var ssl = EnvSafe.get(envSafe, "ENVIO_PG_SSL_MODE", Postgres.sslOptionsSchema, undefined, undefined, false, undefined);
|
|
143
|
+
|
|
144
|
+
var Db = {
|
|
145
|
+
host: host,
|
|
146
|
+
port: port,
|
|
147
|
+
user: user,
|
|
148
|
+
password: password,
|
|
149
|
+
database: database,
|
|
150
|
+
publicSchema: publicSchema,
|
|
151
|
+
ssl: ssl
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
var host$1 = EnvSafe.get(envSafe, "ENVIO_CLICKHOUSE_SINK_HOST", S$RescriptSchema.option(S$RescriptSchema.string), undefined, undefined, undefined, undefined);
|
|
155
|
+
|
|
156
|
+
var database$1 = EnvSafe.get(envSafe, "ENVIO_CLICKHOUSE_SINK_DATABASE", S$RescriptSchema.option(S$RescriptSchema.string), undefined, undefined, undefined, undefined);
|
|
157
|
+
|
|
158
|
+
var username = host$1 !== undefined ? EnvSafe.get(envSafe, "ENVIO_CLICKHOUSE_SINK_USERNAME", S$RescriptSchema.string, undefined, undefined, undefined, undefined) : "";
|
|
159
|
+
|
|
160
|
+
var password$1 = host$1 !== undefined ? EnvSafe.get(envSafe, "ENVIO_CLICKHOUSE_SINK_PASSWORD", S$RescriptSchema.string, undefined, undefined, undefined, undefined) : "";
|
|
161
|
+
|
|
162
|
+
var ClickHouseSink = {
|
|
163
|
+
host: host$1,
|
|
164
|
+
database: database$1,
|
|
165
|
+
username: username,
|
|
166
|
+
password: password$1
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
var enabled = EnvSafe.get(envSafe, "ENVIO_HASURA", S$RescriptSchema.bool, undefined, true, undefined, undefined);
|
|
170
|
+
|
|
171
|
+
var s = EnvSafe.get(envSafe, "ENVIO_HASURA_RESPONSE_LIMIT", S$RescriptSchema.option(S$RescriptSchema.$$int), undefined, undefined, undefined, undefined);
|
|
172
|
+
|
|
173
|
+
var responseLimit = s !== undefined ? s : EnvSafe.get(envSafe, "HASURA_RESPONSE_LIMIT", S$RescriptSchema.option(S$RescriptSchema.$$int), undefined, undefined, undefined, undefined);
|
|
174
|
+
|
|
175
|
+
var graphqlEndpoint = EnvSafe.get(envSafe, "HASURA_GRAPHQL_ENDPOINT", S$RescriptSchema.string, undefined, undefined, "http://localhost:8080/v1/metadata", undefined);
|
|
176
|
+
|
|
177
|
+
var url = graphqlEndpoint.slice(0, -"/v1/metadata".length | 0);
|
|
178
|
+
|
|
179
|
+
var role = EnvSafe.get(envSafe, "HASURA_GRAPHQL_ROLE", S$RescriptSchema.string, undefined, undefined, "admin", undefined);
|
|
180
|
+
|
|
181
|
+
var secret = EnvSafe.get(envSafe, "HASURA_GRAPHQL_ADMIN_SECRET", S$RescriptSchema.string, undefined, undefined, "testing", undefined);
|
|
182
|
+
|
|
183
|
+
var aggregateEntities = EnvSafe.get(envSafe, "ENVIO_HASURA_PUBLIC_AGGREGATE", S$RescriptSchema.union([
|
|
184
|
+
S$RescriptSchema.array(S$RescriptSchema.string),
|
|
185
|
+
S$RescriptSchema.transform(S$RescriptSchema.string, (function (s) {
|
|
186
|
+
return {
|
|
187
|
+
p: (function (string) {
|
|
188
|
+
var entities = string.split("&");
|
|
189
|
+
var len = entities.length;
|
|
190
|
+
if (len !== 1 && len !== 0) {
|
|
191
|
+
return entities;
|
|
192
|
+
} else {
|
|
193
|
+
return s.fail("Provide an array of entities in the JSON format.", undefined);
|
|
194
|
+
}
|
|
195
|
+
})
|
|
196
|
+
};
|
|
197
|
+
}))
|
|
198
|
+
]), undefined, [], undefined, undefined);
|
|
199
|
+
|
|
200
|
+
var Hasura = {
|
|
201
|
+
enabled: enabled,
|
|
202
|
+
responseLimit: responseLimit,
|
|
203
|
+
graphqlEndpoint: graphqlEndpoint,
|
|
204
|
+
url: url,
|
|
205
|
+
role: role,
|
|
206
|
+
secret: secret,
|
|
207
|
+
aggregateEntities: aggregateEntities
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
var initialBlockInterval = EnvSafe.get(envSafe, "ENVIO_RPC_INITIAL_BLOCK_INTERVAL", S$RescriptSchema.option(S$RescriptSchema.$$int), undefined, undefined, undefined, undefined);
|
|
211
|
+
|
|
212
|
+
var backoffMultiplicative = EnvSafe.get(envSafe, "ENVIO_RPC_BACKOFF_MULTIPLICATIVE", S$RescriptSchema.option(S$RescriptSchema.$$float), undefined, undefined, undefined, undefined);
|
|
213
|
+
|
|
214
|
+
var accelerationAdditive = EnvSafe.get(envSafe, "ENVIO_RPC_ACCELERATION_ADDITIVE", S$RescriptSchema.option(S$RescriptSchema.$$int), undefined, undefined, undefined, undefined);
|
|
215
|
+
|
|
216
|
+
var intervalCeiling = EnvSafe.get(envSafe, "ENVIO_RPC_INTERVAL_CEILING", S$RescriptSchema.option(S$RescriptSchema.$$int), undefined, undefined, undefined, undefined);
|
|
217
|
+
|
|
218
|
+
var SyncConfig = {
|
|
219
|
+
initialBlockInterval: initialBlockInterval,
|
|
220
|
+
backoffMultiplicative: backoffMultiplicative,
|
|
221
|
+
accelerationAdditive: accelerationAdditive,
|
|
222
|
+
intervalCeiling: intervalCeiling
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
var Configurable = {
|
|
226
|
+
SyncConfig: SyncConfig
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
var chainMetadataIntervalMillis = EnvSafe.get(envSafe, "ENVIO_THROTTLE_CHAIN_METADATA_INTERVAL_MILLIS", S$RescriptSchema.$$int, undefined, undefined, 500, undefined);
|
|
230
|
+
|
|
231
|
+
var pruneStaleDataIntervalMillis = EnvSafe.get(envSafe, "ENVIO_THROTTLE_PRUNE_STALE_DATA_INTERVAL_MILLIS", S$RescriptSchema.$$int, undefined, undefined, 30000, undefined);
|
|
232
|
+
|
|
233
|
+
var liveMetricsBenchmarkIntervalMillis = EnvSafe.get(envSafe, "ENVIO_THROTTLE_LIVE_METRICS_BENCHMARK_INTERVAL_MILLIS", S$RescriptSchema.$$int, undefined, undefined, 1000, undefined);
|
|
234
|
+
|
|
235
|
+
var jsonFileBenchmarkIntervalMillis = EnvSafe.get(envSafe, "ENVIO_THROTTLE_JSON_FILE_BENCHMARK_INTERVAL_MILLIS", S$RescriptSchema.$$int, undefined, undefined, 500, undefined);
|
|
236
|
+
|
|
237
|
+
var ThrottleWrites = {
|
|
238
|
+
chainMetadataIntervalMillis: chainMetadataIntervalMillis,
|
|
239
|
+
pruneStaleDataIntervalMillis: pruneStaleDataIntervalMillis,
|
|
240
|
+
liveMetricsBenchmarkIntervalMillis: liveMetricsBenchmarkIntervalMillis,
|
|
241
|
+
jsonFileBenchmarkIntervalMillis: jsonFileBenchmarkIntervalMillis
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
EnvSafe.close(envSafe);
|
|
245
|
+
|
|
246
|
+
export {
|
|
247
|
+
updateSyncTimeOnRestart ,
|
|
248
|
+
batchSize ,
|
|
249
|
+
targetBufferSize ,
|
|
250
|
+
maxAddrInPartition ,
|
|
251
|
+
maxPartitionConcurrency ,
|
|
252
|
+
indexingBlockLag ,
|
|
253
|
+
serverPort ,
|
|
254
|
+
tuiOffEnvVar ,
|
|
255
|
+
logFilePath ,
|
|
256
|
+
userLogLevel ,
|
|
257
|
+
defaultFileLogLevel ,
|
|
258
|
+
prodEnvioAppUrl ,
|
|
259
|
+
envioAppUrl ,
|
|
260
|
+
envioApiToken ,
|
|
261
|
+
hyperSyncClientTimeoutMillis ,
|
|
262
|
+
hyperSyncClientMaxRetries ,
|
|
263
|
+
hypersyncClientSerializationFormat ,
|
|
264
|
+
hypersyncClientEnableQueryCaching ,
|
|
265
|
+
Benchmark ,
|
|
266
|
+
logStrategy ,
|
|
267
|
+
Db ,
|
|
268
|
+
ClickHouseSink ,
|
|
269
|
+
Hasura ,
|
|
270
|
+
Configurable ,
|
|
271
|
+
ThrottleWrites ,
|
|
272
|
+
}
|
|
273
|
+
/* Not a pure module */
|
package/src/EventRegister.res
CHANGED
|
@@ -4,9 +4,8 @@ type registrations = {
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
type activeRegistration = {
|
|
7
|
-
|
|
7
|
+
ecosystem: Ecosystem.t,
|
|
8
8
|
multichain: Config.multichain,
|
|
9
|
-
preloadHandlers: bool,
|
|
10
9
|
registrations: registrations,
|
|
11
10
|
mutable finished: bool,
|
|
12
11
|
}
|
|
@@ -36,11 +35,10 @@ let withRegistration = (fn: activeRegistration => unit) => {
|
|
|
36
35
|
}
|
|
37
36
|
}
|
|
38
37
|
|
|
39
|
-
let startRegistration = (~
|
|
38
|
+
let startRegistration = (~ecosystem, ~multichain) => {
|
|
40
39
|
let r = {
|
|
41
|
-
|
|
40
|
+
ecosystem,
|
|
42
41
|
multichain,
|
|
43
|
-
preloadHandlers,
|
|
44
42
|
registrations: {
|
|
45
43
|
onBlockByChainId: Js.Dict.empty(),
|
|
46
44
|
hasEvents: false,
|
|
@@ -92,16 +90,7 @@ let onBlock = (rawOptions: unknown, handler: Internal.onBlockArgs => promise<uni
|
|
|
92
90
|
| Unordered => ()
|
|
93
91
|
| Ordered =>
|
|
94
92
|
Js.Exn.raiseError(
|
|
95
|
-
"Block Handlers are not supported for ordered multichain mode. Please reach out to the Envio team if you need this feature
|
|
96
|
-
)
|
|
97
|
-
}
|
|
98
|
-
// So we encourage users to upgrade to preload optimization
|
|
99
|
-
// otherwise block handlers will be extremely slow
|
|
100
|
-
switch registration.preloadHandlers {
|
|
101
|
-
| true => ()
|
|
102
|
-
| false =>
|
|
103
|
-
Js.Exn.raiseError(
|
|
104
|
-
"Block Handlers require the Preload Optimization feature. Enable it by setting the `preload_handlers` option to `true` in your config.",
|
|
93
|
+
"Block Handlers are not supported for ordered multichain mode. Please reach out to the Envio team if you need this feature. Or enable unordered multichain mode by removing `multichain: ordered` from the config.yaml file.",
|
|
105
94
|
)
|
|
106
95
|
}
|
|
107
96
|
|
|
@@ -27,11 +27,10 @@ function withRegistration(fn) {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
function startRegistration(
|
|
30
|
+
function startRegistration(ecosystem, multichain) {
|
|
31
31
|
var r = {
|
|
32
|
-
|
|
32
|
+
ecosystem: ecosystem,
|
|
33
33
|
multichain: multichain,
|
|
34
|
-
preloadHandlers: preloadHandlers,
|
|
35
34
|
registrations: {
|
|
36
35
|
onBlockByChainId: {},
|
|
37
36
|
hasEvents: false
|
|
@@ -81,12 +80,7 @@ function onBlock(rawOptions, handler) {
|
|
|
81
80
|
withRegistration(function (registration) {
|
|
82
81
|
var match = registration.multichain;
|
|
83
82
|
if (match === "ordered") {
|
|
84
|
-
Js_exn.raiseError("Block Handlers are not supported for ordered multichain mode. Please reach out to the Envio team if you need this feature
|
|
85
|
-
}
|
|
86
|
-
if (registration.preloadHandlers) {
|
|
87
|
-
|
|
88
|
-
} else {
|
|
89
|
-
Js_exn.raiseError("Block Handlers require the Preload Optimization feature. Enable it by setting the `preload_handlers` option to `true` in your config.");
|
|
83
|
+
Js_exn.raiseError("Block Handlers are not supported for ordered multichain mode. Please reach out to the Envio team if you need this feature. Or enable unordered multichain mode by removing `multichain: ordered` from the config.yaml file.");
|
|
90
84
|
}
|
|
91
85
|
var options = S$RescriptSchema.parseOrThrow(rawOptions, onBlockOptionsSchema);
|
|
92
86
|
var chainId = options.chain;
|
package/src/EventRegister.resi
CHANGED
|
@@ -3,11 +3,7 @@ type registrations = {
|
|
|
3
3
|
mutable hasEvents: bool,
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
let startRegistration: (
|
|
7
|
-
~platform: Platform.t,
|
|
8
|
-
~multichain: Config.multichain,
|
|
9
|
-
~preloadHandlers: bool,
|
|
10
|
-
) => unit
|
|
6
|
+
let startRegistration: (~ecosystem: Ecosystem.t, ~multichain: Config.multichain) => unit
|
|
11
7
|
let isPendingRegistration: unit => bool
|
|
12
8
|
let finishRegistration: unit => registrations
|
|
13
9
|
|
|
@@ -15,9 +11,7 @@ type t
|
|
|
15
11
|
let make: (~contractName: string, ~eventName: string) => t
|
|
16
12
|
let setHandler: (
|
|
17
13
|
t,
|
|
18
|
-
Internal.genericHandler<
|
|
19
|
-
Internal.genericHandlerArgs<'event, Internal.handlerContext, 'loaderReturn>,
|
|
20
|
-
>,
|
|
14
|
+
Internal.genericHandler<Internal.genericHandlerArgs<'event, Internal.handlerContext>>,
|
|
21
15
|
~eventOptions: option<Internal.eventOptions<'eventFilters>>,
|
|
22
16
|
~logger: Pino.t=?,
|
|
23
17
|
) => unit
|
package/src/Internal.gen.ts
CHANGED
|
@@ -26,11 +26,7 @@ export type genericContractRegisterArgs<event,context> = { readonly event: event
|
|
|
26
26
|
|
|
27
27
|
export type genericContractRegister<args> = $$genericContractRegister<args>;
|
|
28
28
|
|
|
29
|
-
export type genericHandlerArgs<event,context
|
|
30
|
-
readonly event: event;
|
|
31
|
-
readonly context: context;
|
|
32
|
-
readonly loaderReturn: loaderReturn
|
|
33
|
-
};
|
|
29
|
+
export type genericHandlerArgs<event,context> = { readonly event: event; readonly context: context };
|
|
34
30
|
|
|
35
31
|
export type genericHandler<args> = (_1:args) => Promise<void>;
|
|
36
32
|
|
|
@@ -46,17 +42,10 @@ export type genericHandlerWithLoader<loader,handler,eventFilters> = {
|
|
|
46
42
|
readonly loader: loader;
|
|
47
43
|
readonly handler: handler;
|
|
48
44
|
readonly wildcard?: boolean;
|
|
49
|
-
readonly eventFilters?: eventFilters
|
|
50
|
-
/** @deprecated The option is removed starting from v2.19 since we made the default mode even faster than pre-registration. */
|
|
51
|
-
readonly preRegisterDynamicContracts?: boolean
|
|
45
|
+
readonly eventFilters?: eventFilters
|
|
52
46
|
};
|
|
53
47
|
|
|
54
|
-
export type eventOptions<eventFilters> = {
|
|
55
|
-
readonly wildcard?: boolean;
|
|
56
|
-
readonly eventFilters?: eventFilters;
|
|
57
|
-
/** @deprecated The option is removed starting from v2.19 since we made the default mode even faster than pre-registration. */
|
|
58
|
-
readonly preRegisterDynamicContracts?: boolean
|
|
59
|
-
};
|
|
48
|
+
export type eventOptions<eventFilters> = { readonly wildcard?: boolean; readonly eventFilters?: eventFilters };
|
|
60
49
|
|
|
61
50
|
export type fuelSupplyParams = { readonly subId: string; readonly amount: bigint };
|
|
62
51
|
|
package/src/Internal.res
CHANGED
|
@@ -37,10 +37,9 @@ type contractRegisterArgs = genericContractRegisterArgs<event, contractRegisterC
|
|
|
37
37
|
type contractRegister = genericContractRegister<contractRegisterArgs>
|
|
38
38
|
|
|
39
39
|
@genType
|
|
40
|
-
type genericHandlerArgs<'event, 'context
|
|
40
|
+
type genericHandlerArgs<'event, 'context> = {
|
|
41
41
|
event: 'event,
|
|
42
42
|
context: 'context,
|
|
43
|
-
loaderReturn: 'loaderReturn,
|
|
44
43
|
}
|
|
45
44
|
@genType
|
|
46
45
|
type genericHandler<'args> = 'args => promise<unit>
|
|
@@ -81,10 +80,6 @@ type genericHandlerWithLoader<'loader, 'handler, 'eventFilters> = {
|
|
|
81
80
|
handler: 'handler,
|
|
82
81
|
wildcard?: bool,
|
|
83
82
|
eventFilters?: 'eventFilters,
|
|
84
|
-
/**
|
|
85
|
-
@deprecated The option is removed starting from v2.19 since we made the default mode even faster than pre-registration.
|
|
86
|
-
*/
|
|
87
|
-
preRegisterDynamicContracts?: bool,
|
|
88
83
|
}
|
|
89
84
|
|
|
90
85
|
// This is private so it's not manually constructed internally
|
|
@@ -170,7 +165,7 @@ type eventItem = private {
|
|
|
170
165
|
event: event,
|
|
171
166
|
}
|
|
172
167
|
|
|
173
|
-
// Opaque type to support both EVM and
|
|
168
|
+
// Opaque type to support both EVM and other ecosystems
|
|
174
169
|
type blockEvent
|
|
175
170
|
|
|
176
171
|
type onBlockArgs = {
|
|
@@ -225,10 +220,6 @@ external setItemDcs: (item, dcs) => unit = "dcs"
|
|
|
225
220
|
type eventOptions<'eventFilters> = {
|
|
226
221
|
wildcard?: bool,
|
|
227
222
|
eventFilters?: 'eventFilters,
|
|
228
|
-
/**
|
|
229
|
-
@deprecated The option is removed starting from v2.19 since we made the default mode even faster than pre-registration.
|
|
230
|
-
*/
|
|
231
|
-
preRegisterDynamicContracts?: bool,
|
|
232
223
|
}
|
|
233
224
|
|
|
234
225
|
@genType
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type t
|
|
2
|
+
|
|
3
|
+
type options = {headers?: Js.Dict.t<string>}
|
|
4
|
+
|
|
5
|
+
@module("eventsource") @new
|
|
6
|
+
external create: (~url: string, ~options: options=?) => t = "EventSource"
|
|
7
|
+
|
|
8
|
+
@set external onopen: (t, unit => unit) => unit = "onopen"
|
|
9
|
+
@set external onerror: (t, Js.Exn.t => unit) => unit = "onerror"
|
|
10
|
+
|
|
11
|
+
type event = {data: string}
|
|
12
|
+
@send external addEventListener: (t, string, event => unit) => unit = "addEventListener"
|
|
13
|
+
@send external close: t => unit = "close"
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Pure js implementation of the HyperSync height stream.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
type t = {
|
|
6
|
+
heightRef: ref<int>,
|
|
7
|
+
errorRef: ref<option<string>>,
|
|
8
|
+
timeoutIdRef: ref<Js.Global.timeoutId>,
|
|
9
|
+
eventsourceRef: ref<option<EventSource.t>>,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let make = (~hyperSyncUrl, ~apiToken) => {
|
|
13
|
+
/**
|
|
14
|
+
On every successful ping or height event, clear the timeout and set a new one.
|
|
15
|
+
|
|
16
|
+
if the timeout lapses, close and reconnect the EventSource.
|
|
17
|
+
*/
|
|
18
|
+
let rec updateTimeoutId = (
|
|
19
|
+
~eventsourceRef: ref<option<EventSource.t>>,
|
|
20
|
+
~timeoutIdRef: ref<Js.Global.timeoutId>,
|
|
21
|
+
~hyperSyncUrl,
|
|
22
|
+
~apiToken,
|
|
23
|
+
~heightRef: ref<int>,
|
|
24
|
+
~errorRef: ref<option<string>>,
|
|
25
|
+
) => {
|
|
26
|
+
timeoutIdRef.contents->Js.Global.clearTimeout
|
|
27
|
+
|
|
28
|
+
// Should receive a ping at least every 5s, so 15s is a safe margin
|
|
29
|
+
// for staleness to restart the EventSource connection
|
|
30
|
+
let staleTimeMillis = 15_000
|
|
31
|
+
let newTimeoutId = Js.Global.setTimeout(() => {
|
|
32
|
+
Logging.trace({
|
|
33
|
+
"msg": "Timeout fired for height stream",
|
|
34
|
+
"url": hyperSyncUrl,
|
|
35
|
+
"staleTimeMillis": staleTimeMillis,
|
|
36
|
+
})
|
|
37
|
+
refreshEventSource(
|
|
38
|
+
~eventsourceRef,
|
|
39
|
+
~hyperSyncUrl,
|
|
40
|
+
~apiToken,
|
|
41
|
+
~heightRef,
|
|
42
|
+
~errorRef,
|
|
43
|
+
~timeoutIdRef,
|
|
44
|
+
)
|
|
45
|
+
}, staleTimeMillis)
|
|
46
|
+
|
|
47
|
+
timeoutIdRef := newTimeoutId
|
|
48
|
+
}
|
|
49
|
+
and /**
|
|
50
|
+
Instantiate a new EventSource and set it to the shared refs.
|
|
51
|
+
Add the necessary event listeners, handle errors
|
|
52
|
+
and update the timeout.
|
|
53
|
+
*/
|
|
54
|
+
refreshEventSource = (
|
|
55
|
+
~eventsourceRef: ref<option<EventSource.t>>,
|
|
56
|
+
~hyperSyncUrl,
|
|
57
|
+
~apiToken,
|
|
58
|
+
~heightRef: ref<int>,
|
|
59
|
+
~errorRef: ref<option<string>>,
|
|
60
|
+
~timeoutIdRef: ref<Js.Global.timeoutId>,
|
|
61
|
+
) => {
|
|
62
|
+
// Close the old EventSource if it exists (on a new connection after timeout)
|
|
63
|
+
switch eventsourceRef.contents {
|
|
64
|
+
| Some(es) => es->EventSource.close
|
|
65
|
+
| None => ()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let userAgent = `hyperindex/${Utils.EnvioPackage.value.version}`
|
|
69
|
+
let es = EventSource.create(
|
|
70
|
+
~url=`${hyperSyncUrl}/height/sse`,
|
|
71
|
+
~options={
|
|
72
|
+
headers: Js.Dict.fromArray([
|
|
73
|
+
("Authorization", `Bearer ${apiToken}`),
|
|
74
|
+
("User-Agent", userAgent),
|
|
75
|
+
]),
|
|
76
|
+
},
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
// Set the new EventSource to the shared ref
|
|
80
|
+
eventsourceRef := Some(es)
|
|
81
|
+
// Update the timeout in case connection goes stale
|
|
82
|
+
updateTimeoutId(~eventsourceRef, ~timeoutIdRef, ~hyperSyncUrl, ~apiToken, ~heightRef, ~errorRef)
|
|
83
|
+
|
|
84
|
+
es->EventSource.onopen(_ => {
|
|
85
|
+
Logging.trace({"msg": "SSE connection opened for height stream", "url": hyperSyncUrl})
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
es->EventSource.onerror(error => {
|
|
89
|
+
Logging.trace({
|
|
90
|
+
"msg": "EventSource error",
|
|
91
|
+
"error": error->Js.Exn.message,
|
|
92
|
+
})
|
|
93
|
+
// On errors, set the error ref
|
|
94
|
+
// so that getHeight can raise an error
|
|
95
|
+
errorRef :=
|
|
96
|
+
Some(error->Js.Exn.message->Belt.Option.getWithDefault("Unexpected no error.message"))
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
es->EventSource.addEventListener("ping", _event => {
|
|
100
|
+
// ping lets us know from the server that the connection is still alive
|
|
101
|
+
// and that the height hasn't updated for 5seconds
|
|
102
|
+
// update the timeout on each successful ping received
|
|
103
|
+
updateTimeoutId(
|
|
104
|
+
~eventsourceRef,
|
|
105
|
+
~timeoutIdRef,
|
|
106
|
+
~hyperSyncUrl,
|
|
107
|
+
~apiToken,
|
|
108
|
+
~heightRef,
|
|
109
|
+
~errorRef,
|
|
110
|
+
)
|
|
111
|
+
// reset the error ref, since we had a successful ping
|
|
112
|
+
errorRef := None
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
es->EventSource.addEventListener("height", event => {
|
|
116
|
+
switch event.data->Belt.Int.fromString {
|
|
117
|
+
| Some(height) =>
|
|
118
|
+
// On a successful height event, update the timeout
|
|
119
|
+
// and reset the error ref
|
|
120
|
+
updateTimeoutId(
|
|
121
|
+
~eventsourceRef,
|
|
122
|
+
~timeoutIdRef,
|
|
123
|
+
~hyperSyncUrl,
|
|
124
|
+
~apiToken,
|
|
125
|
+
~heightRef,
|
|
126
|
+
~errorRef,
|
|
127
|
+
)
|
|
128
|
+
errorRef := None
|
|
129
|
+
// Set the actual height ref
|
|
130
|
+
heightRef := height
|
|
131
|
+
| None =>
|
|
132
|
+
Logging.trace({"msg": "Height was not a number in event.data", "data": event.data})
|
|
133
|
+
errorRef := Some("Height was not a number in event.data")
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Refs used between the functions
|
|
139
|
+
|
|
140
|
+
let heightRef = ref(0)
|
|
141
|
+
let errorRef = ref(None)
|
|
142
|
+
let eventsourceRef = ref(None)
|
|
143
|
+
// Timeout doesn't do anything for initalization
|
|
144
|
+
let timeoutIdRef = ref(Js.Global.setTimeout(() => (), 0))
|
|
145
|
+
refreshEventSource(
|
|
146
|
+
~eventsourceRef,
|
|
147
|
+
~hyperSyncUrl,
|
|
148
|
+
~apiToken,
|
|
149
|
+
~heightRef,
|
|
150
|
+
~errorRef,
|
|
151
|
+
~timeoutIdRef,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
{
|
|
155
|
+
heightRef,
|
|
156
|
+
errorRef,
|
|
157
|
+
timeoutIdRef,
|
|
158
|
+
eventsourceRef,
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
let getHeight = async (t: t) => {
|
|
163
|
+
while t.heightRef.contents == 0 && t.errorRef.contents == None {
|
|
164
|
+
// Poll internally until height is over 0
|
|
165
|
+
await Utils.delay(200)
|
|
166
|
+
}
|
|
167
|
+
switch t.errorRef.contents {
|
|
168
|
+
| None => t.heightRef.contents
|
|
169
|
+
| Some(error) => Js.Exn.raiseError(error)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
let close = t => {
|
|
174
|
+
t.timeoutIdRef.contents->Js.Global.clearTimeout
|
|
175
|
+
switch t.eventsourceRef.contents {
|
|
176
|
+
| Some(es) => es->EventSource.close
|
|
177
|
+
| None => ()
|
|
178
|
+
}
|
|
179
|
+
}
|