envio 3.0.2-svm-alpha.0 → 3.0.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.
Files changed (43) hide show
  1. package/evm.schema.json +8 -8
  2. package/fuel.schema.json +12 -12
  3. package/index.d.ts +1 -155
  4. package/package.json +7 -6
  5. package/src/ChainFetcher.res +1 -25
  6. package/src/ChainFetcher.res.mjs +1 -19
  7. package/src/Config.res +94 -156
  8. package/src/Config.res.mjs +97 -60
  9. package/src/Core.res +0 -32
  10. package/src/Env.res.mjs +2 -1
  11. package/src/Envio.res +0 -94
  12. package/src/EventConfigBuilder.res +25 -63
  13. package/src/EventConfigBuilder.res.mjs +8 -37
  14. package/src/HandlerLoader.res +1 -12
  15. package/src/HandlerLoader.res.mjs +1 -6
  16. package/src/Internal.res +0 -38
  17. package/src/Main.res +3 -53
  18. package/src/Main.res.mjs +2 -34
  19. package/src/Persistence.res +17 -2
  20. package/src/Persistence.res.mjs +14 -2
  21. package/src/SimulateItems.res +10 -23
  22. package/src/SimulateItems.res.mjs +6 -21
  23. package/src/bindings/ClickHouse.res +6 -2
  24. package/src/bindings/ClickHouse.res.mjs +3 -2
  25. package/src/sources/EventRouter.res +0 -65
  26. package/src/sources/EventRouter.res.mjs +0 -43
  27. package/src/sources/HyperSyncClient.res +157 -30
  28. package/src/sources/HyperSyncClient.res.mjs +6 -20
  29. package/src/sources/HyperSyncSource.res +8 -5
  30. package/src/sources/HyperSyncSource.res.mjs +8 -1
  31. package/src/sources/RpcSource.res.mjs +1 -1
  32. package/src/sources/Svm.res +2 -2
  33. package/src/sources/Svm.res.mjs +2 -3
  34. package/src/tui/Tui.res +2 -9
  35. package/src/tui/Tui.res.mjs +4 -19
  36. package/src/tui/components/TuiData.res +0 -3
  37. package/svm.schema.json +4 -345
  38. package/src/SvmTypes.res +0 -9
  39. package/src/SvmTypes.res.mjs +0 -14
  40. package/src/sources/HyperSyncSolanaClient.res +0 -227
  41. package/src/sources/HyperSyncSolanaClient.res.mjs +0 -25
  42. package/src/sources/HyperSyncSolanaSource.res +0 -515
  43. package/src/sources/HyperSyncSolanaSource.res.mjs +0 -441
@@ -27,7 +27,7 @@ function make(userEntities, allEnums, storage) {
27
27
  };
28
28
  }
29
29
 
30
- async function init(persistence, chainConfigs, envioInfo, resetCommand, resetOpt) {
30
+ async function init(persistence, chainConfigs, envioInfo, resetCommand, runCommand, resetOpt) {
31
31
  let reset = resetOpt !== undefined ? resetOpt : false;
32
32
  try {
33
33
  let promise = persistence.storageStatus;
@@ -70,7 +70,19 @@ async function init(persistence, chainConfigs, envioInfo, resetCommand, resetOpt
70
70
  let initialState$1 = await persistence.storage.resumeInitialState();
71
71
  let stored = initialState$1.envioInfo;
72
72
  let changedPaths = stored !== undefined ? Config.diffPaths(stored, envioInfo) : ["envio info is missing — storage initialized by an older envio"];
73
- Config.throwIfIncompatible(changedPaths, resetCommand);
73
+ let hasClickhouse;
74
+ if (typeof envioInfo === "object" && envioInfo !== null && !Array.isArray(envioInfo)) {
75
+ let match$1 = envioInfo["storage"];
76
+ if (typeof match$1 === "object" && match$1 !== null && !Array.isArray(match$1)) {
77
+ let match$2 = match$1["clickhouse"];
78
+ hasClickhouse = match$2 === true;
79
+ } else {
80
+ hasClickhouse = false;
81
+ }
82
+ } else {
83
+ hasClickhouse = false;
84
+ }
85
+ Config.throwIfIncompatible(changedPaths, resetCommand, runCommand, hasClickhouse);
74
86
  persistence.storageStatus = {
75
87
  TAG: "Ready",
76
88
  _0: initialState$1
@@ -320,34 +320,21 @@ let patchConfig = (~config: Config.t, ~processConfig: JSON.t): Config.t => {
320
320
  let chainIdStr = chain->ChainMap.Chain.toChainId->Int.toString
321
321
  switch chainsDict->Dict.get(chainIdStr) {
322
322
  | Some(processChainJson) =>
323
- let raw = processChainJson->(Utils.magic: JSON.t => {..})
324
- let simulateRaw: option<array<JSON.t>> = raw["simulate"]->Nullable.toOption
323
+ let simulateRaw: option<array<JSON.t>> =
324
+ (processChainJson->(Utils.magic: JSON.t => {..}))["simulate"]->Nullable.toOption
325
325
  switch simulateRaw {
326
326
  | Some(simulateItems) =>
327
327
  let items = parse(~simulateItems, ~config, ~chainConfig)
328
- let startBlock: int = raw["startBlock"]->(Utils.magic: 'a => int)
329
- let endBlock: int = raw["endBlock"]->(Utils.magic: 'a => int)
328
+ // Use endBlock from processConfig (the user-specified range)
329
+ let startBlock: int =
330
+ (processChainJson->(Utils.magic: JSON.t => {..}))["startBlock"]->(
331
+ Utils.magic: 'a => int
332
+ )
333
+ let endBlock: int =
334
+ (processChainJson->(Utils.magic: JSON.t => {..}))["endBlock"]->(Utils.magic: 'a => int)
330
335
  let source = SimulateSource.make(~items, ~endBlock, ~chain)
331
336
  {...chainConfig, startBlock, endBlock, sourceConfig: Config.CustomSources([source])}
332
- | None =>
333
- // No simulate items: still honor `startBlock` / `endBlock` overrides
334
- // so non-EVM/Fuel ecosystems (notably SVM `indexer.onInstruction`,
335
- // which doesn't support simulate items) can bound the run window
336
- // via `testIndexer.process({chains: { id: {startBlock, endBlock} }})`.
337
- let startBlockOpt: option<int> =
338
- raw["startBlock"]
339
- ->(Utils.magic: 'a => Nullable.t<int>)
340
- ->Nullable.toOption
341
- let endBlockOpt: option<int> =
342
- raw["endBlock"]->(Utils.magic: 'a => Nullable.t<int>)->Nullable.toOption
343
- let withStart = switch startBlockOpt {
344
- | Some(sb) => {...chainConfig, startBlock: sb}
345
- | None => chainConfig
346
- }
347
- switch endBlockOpt {
348
- | Some(eb) => {...withStart, endBlock: eb}
349
- | None => withStart
350
- }
337
+ | None => chainConfig
351
338
  }
352
339
  | None => chainConfig
353
340
  }
@@ -266,35 +266,20 @@ function patchConfig(config, processConfig) {
266
266
  }
267
267
  let simulateRaw = processChainJson.simulate;
268
268
  if (simulateRaw == null) {
269
- let startBlockOpt = processChainJson.startBlock;
270
- let endBlockOpt = processChainJson.endBlock;
271
- let withStart;
272
- if (startBlockOpt == null) {
273
- withStart = chainConfig;
274
- } else {
275
- let newrecord = {...chainConfig};
276
- newrecord.startBlock = startBlockOpt;
277
- withStart = newrecord;
278
- }
279
- if (endBlockOpt == null) {
280
- return withStart;
281
- }
282
- let newrecord$1 = {...withStart};
283
- newrecord$1.endBlock = endBlockOpt;
284
- return newrecord$1;
269
+ return chainConfig;
285
270
  }
286
271
  let items = parse(simulateRaw, config, chainConfig);
287
272
  let startBlock = processChainJson.startBlock;
288
273
  let endBlock = processChainJson.endBlock;
289
274
  let source = SimulateSource.make(items, endBlock, chain);
290
- let newrecord$2 = {...chainConfig};
291
- newrecord$2.sourceConfig = {
275
+ let newrecord = {...chainConfig};
276
+ newrecord.sourceConfig = {
292
277
  TAG: "CustomSources",
293
278
  _0: [source]
294
279
  };
295
- newrecord$2.endBlock = endBlock;
296
- newrecord$2.startBlock = startBlock;
297
- return newrecord$2;
280
+ newrecord.endBlock = endBlock;
281
+ newrecord.startBlock = startBlock;
282
+ return newrecord;
298
283
  });
299
284
  let newrecord = {...config};
300
285
  newrecord.chainMap = newChainMap;
@@ -426,6 +426,10 @@ let initialize = async (
426
426
  | Some(engine) => ` ENGINE = ${engine}`
427
427
  | None => ""
428
428
  }
429
+ // Replicated database engine requires CREATE DATABASE to run on every
430
+ // replica; ON CLUSTER fans the DDL out via Keeper. The '{cluster}' macro
431
+ // resolves to each node's configured cluster name.
432
+ let onClusterClause = replicated ? ` ON CLUSTER '{cluster}'` : ""
429
433
 
430
434
  switch databaseEngine {
431
435
  | Some(engineSpec) => {
@@ -445,9 +449,9 @@ let initialize = async (
445
449
  | None => ()
446
450
  }
447
451
 
448
- await client->exec({query: `TRUNCATE DATABASE IF EXISTS ${database}`})
452
+ await client->exec({query: `TRUNCATE DATABASE IF EXISTS ${database}${onClusterClause}`})
449
453
  await client->exec({
450
- query: `CREATE DATABASE IF NOT EXISTS ${database}${databaseEngineClause}`,
454
+ query: `CREATE DATABASE IF NOT EXISTS ${database}${onClusterClause}${databaseEngineClause}`,
451
455
  })
452
456
  await client->exec({query: `USE ${database}`})
453
457
 
@@ -301,6 +301,7 @@ async function initialize(client, database, entities, param) {
301
301
  let replicated = Env.ClickHouse.replicated();
302
302
  let databaseEngine = Env.ClickHouse.databaseEngine();
303
303
  let databaseEngineClause = databaseEngine !== undefined ? ` ENGINE = ` + databaseEngine : "";
304
+ let onClusterClause = replicated ? ` ON CLUSTER '{cluster}'` : "";
304
305
  if (databaseEngine !== undefined) {
305
306
  let expectedEngineName = databaseEngine.split("(")[0].trim();
306
307
  let existingResult = await client.query({
@@ -316,10 +317,10 @@ async function initialize(client, database, entities, param) {
316
317
  }
317
318
  }
318
319
  await client.exec({
319
- query: `TRUNCATE DATABASE IF EXISTS ` + database
320
+ query: `TRUNCATE DATABASE IF EXISTS ` + database + onClusterClause
320
321
  });
321
322
  await client.exec({
322
- query: `CREATE DATABASE IF NOT EXISTS ` + database + databaseEngineClause
323
+ query: `CREATE DATABASE IF NOT EXISTS ` + database + onClusterClause + databaseEngineClause
323
324
  });
324
325
  await client.exec({
325
326
  query: `USE ` + database
@@ -116,68 +116,3 @@ let fromEvmEventModsOrThrow = (events: array<Internal.evmEventConfig>, ~chain):
116
116
  })
117
117
  router
118
118
  }
119
-
120
- /** Dispatch key for SVM instructions. `None` matches any instruction in the
121
- program (lowest priority). */
122
- let getSvmEventId = (~programId: SvmTypes.Pubkey.t, ~discriminator: option<string>) =>
123
- switch discriminator {
124
- | None => (programId->SvmTypes.Pubkey.toString) ++ "_none"
125
- | Some(d) => (programId->SvmTypes.Pubkey.toString) ++ "_" ++ d
126
- }
127
-
128
- /** Discriminator byte-lengths declared by a program, sorted descending. The
129
- source uses this to probe `(programId, dN)` keys longest-first when routing
130
- a returned instruction to a handler — matching the locked Q1 answer. */
131
- type svmProgramOrdering = {
132
- programId: SvmTypes.Pubkey.t,
133
- /** Byte lengths in descending order, deduplicated. Includes `0` only when
134
- a handler is registered with no discriminator (program-wide match). */
135
- byteLengthsDesc: array<int>,
136
- }
137
-
138
- let fromSvmEventConfigsOrThrow = (
139
- events: array<Internal.svmInstructionEventConfig>,
140
- ~chain,
141
- ): (t<Internal.svmInstructionEventConfig>, array<svmProgramOrdering>) => {
142
- let router = empty()
143
- events->Belt.Array.forEach(config => {
144
- // The router tag must include the programId so two programs declaring the
145
- // same discriminator coexist. The source-side lookup uses the same shape
146
- // via `getSvmEventId(~programId, ~discriminator)`.
147
- let routerTag = getSvmEventId(~programId=config.programId, ~discriminator=config.discriminator)
148
- router->addOrThrow(
149
- routerTag,
150
- config,
151
- ~contractName=config.contractName,
152
- ~eventName=config.name,
153
- ~chain,
154
- ~isWildcard=config.isWildcard,
155
- )
156
- })
157
-
158
- // Per-program list of declared discriminator byte lengths, sorted desc.
159
- let byProgram: dict<Utils.Set.t<int>> = Dict.make()
160
- events->Belt.Array.forEach(config => {
161
- let key = config.programId->SvmTypes.Pubkey.toString
162
- let set = switch byProgram->Utils.Dict.dangerouslyGetNonOption(key) {
163
- | Some(s) => s
164
- | None =>
165
- let s = Utils.Set.make()
166
- byProgram->Dict.set(key, s)
167
- s
168
- }
169
- let _ = set->Utils.Set.add(config.discriminatorByteLen)
170
- })
171
- let ordering =
172
- byProgram
173
- ->Dict.toArray
174
- ->Array.map(((programIdString, lens)) => {
175
- let sorted = lens->Utils.Set.toArray->Array.toSorted((a, b) => (b - a)->Int.toFloat)
176
- {
177
- programId: programIdString->SvmTypes.Pubkey.fromStringUnsafe,
178
- byteLengthsDesc: sorted,
179
- }
180
- })
181
-
182
- (router, ordering)
183
- }
@@ -111,47 +111,6 @@ function fromEvmEventModsOrThrow(events, chain) {
111
111
  return router;
112
112
  }
113
113
 
114
- function getSvmEventId(programId, discriminator) {
115
- if (discriminator !== undefined) {
116
- return programId + "_" + discriminator;
117
- } else {
118
- return programId + "_none";
119
- }
120
- }
121
-
122
- function fromSvmEventConfigsOrThrow(events, chain) {
123
- let router = {};
124
- Belt_Array.forEach(events, config => {
125
- let routerTag = getSvmEventId(config.programId, config.discriminator);
126
- addOrThrow$1(router, routerTag, config, config.contractName, config.isWildcard, config.name, chain);
127
- });
128
- let byProgram = {};
129
- Belt_Array.forEach(events, config => {
130
- let key = config.programId;
131
- let s = byProgram[key];
132
- let set;
133
- if (s !== undefined) {
134
- set = Primitive_option.valFromOption(s);
135
- } else {
136
- let s$1 = new Set();
137
- byProgram[key] = s$1;
138
- set = s$1;
139
- }
140
- set.add(config.discriminatorByteLen);
141
- });
142
- let ordering = Object.entries(byProgram).map(param => {
143
- let sorted = Array.from(param[1]).toSorted((a, b) => b - a | 0);
144
- return {
145
- programId: param[0],
146
- byteLengthsDesc: sorted
147
- };
148
- });
149
- return [
150
- router,
151
- ordering
152
- ];
153
- }
154
-
155
114
  export {
156
115
  EventDuplicate,
157
116
  WildcardCollision,
@@ -161,7 +120,5 @@ export {
161
120
  get$1 as get,
162
121
  getEvmEventId,
163
122
  fromEvmEventModsOrThrow,
164
- getSvmEventId,
165
- fromSvmEventConfigsOrThrow,
166
123
  }
167
124
  /* ChainMap Not a pure module */
@@ -155,18 +155,41 @@ module QueryTypes = {
155
155
  )
156
156
 
157
157
  type logFilter = {
158
+ /**
159
+ * Address of the contract, any logs that has any of these addresses will be returned.
160
+ * Empty means match all.
161
+ */
158
162
  address?: array<Address.t>,
163
+ /**
164
+ * Topics to match, each member of the top level array is another array, if the nth topic matches any
165
+ * topic specified in topics[n] the log will be returned. Empty means match all.
166
+ */
159
167
  topics: topicSelection,
160
168
  }
161
169
 
162
170
  let makeLogSelection = (~address, ~topics) => {address, topics}
163
171
 
164
172
  type transactionFilter = {
173
+ /**
174
+ * Address the transaction should originate from. If transaction.from matches any of these, the transaction
175
+ * will be returned. Keep in mind that this has an and relationship with to filter, so each transaction should
176
+ * match both of them. Empty means match all.
177
+ */
165
178
  from?: array<Address.t>,
166
- @as("to") to_?: array<Address.t>,
179
+ /**
180
+ * Address the transaction should go to. If transaction.to matches any of these, the transaction will
181
+ * be returned. Keep in mind that this has an and relationship with from filter, so each transaction should
182
+ * match both of them. Empty means match all.
183
+ */
184
+ @as("to")
185
+ to_?: array<Address.t>,
186
+ /** If first 4 bytes of transaction input matches any of these, transaction will be returned. Empty means match all. */
167
187
  sighash?: array<string>,
188
+ /** If tx.status matches this it will be returned. */
168
189
  status?: int,
169
- @as("type") type_?: array<int>,
190
+ /** If transaction.type matches any of these values, the transaction will be returned */
191
+ @as("type")
192
+ type_?: array<int>,
170
193
  contractAddress?: array<Address.t>,
171
194
  }
172
195
 
@@ -176,30 +199,94 @@ module QueryTypes = {
176
199
  address?: array<Address.t>,
177
200
  callType?: array<string>,
178
201
  rewardType?: array<string>,
179
- @as("type") type_?: array<string>,
202
+ @as("type")
203
+ type_?: array<string>,
180
204
  sighash?: array<string>,
181
205
  }
182
206
 
183
207
  type blockSelection = {
208
+ /**
209
+ * Hash of a block, any blocks that have one of these hashes will be returned.
210
+ * Empty means match all.
211
+ */
184
212
  hash?: array<string>,
213
+ /**
214
+ * Miner address of a block, any blocks that have one of these miners will be returned.
215
+ * Empty means match all.
216
+ */
185
217
  miner?: array<Address.t>,
186
218
  }
187
219
 
188
220
  type joinMode = | @as(0) Default | @as(1) JoinAll | @as(2) JoinNothing
189
221
 
190
222
  type query = {
223
+ /** The block to start the query from */
191
224
  fromBlock: int,
192
- @as("toBlock") toBlockExclusive?: int,
225
+ /**
226
+ * The block to end the query at. If not specified, the query will go until the
227
+ * end of data. Exclusive, the returned range will be [from_block..to_block).
228
+ *
229
+ * The query will return before it reaches this target block if it hits the time limit
230
+ * configured on the server. The user should continue their query by putting the
231
+ * next_block field in the response into from_block field of their next query. This implements
232
+ * pagination.
233
+ */
234
+ @as("toBlock")
235
+ toBlockExclusive?: int,
236
+ /**
237
+ * List of log selections, these have an or relationship between them, so the query will return logs
238
+ * that match any of these selections.
239
+ */
193
240
  logs?: array<logFilter>,
241
+ /**
242
+ * List of transaction selections, the query will return transactions that match any of these selections and
243
+ * it will return transactions that are related to the returned logs.
244
+ */
194
245
  transactions?: array<transactionFilter>,
246
+ /**
247
+ * List of trace selections, the query will return traces that match any of these selections and
248
+ * it will re turn traces that are related to the returned logs.
249
+ */
195
250
  traces?: array<traceSelection>,
251
+ /** List of block selections, the query will return blocks that match any of these selections */
196
252
  blocks?: array<blockSelection>,
253
+ /**
254
+ * Field selection. The user can select which fields they are interested in, requesting less fields will improve
255
+ * query execution time and reduce the payload size so the user should always use a minimal number of fields.
256
+ */
197
257
  fieldSelection: fieldSelection,
258
+ /**
259
+ * Maximum number of blocks that should be returned, the server might return more blocks than this number but
260
+ * it won't overshoot by too much.
261
+ */
198
262
  maxNumBlocks?: int,
263
+ /**
264
+ * Maximum number of transactions that should be returned, the server might return more transactions than this number but
265
+ * it won't overshoot by too much.
266
+ */
199
267
  maxNumTransactions?: int,
268
+ /**
269
+ * Maximum number of logs that should be returned, the server might return more logs than this number but
270
+ * it won't overshoot by too much.
271
+ */
200
272
  maxNumLogs?: int,
273
+ /**
274
+ * Maximum number of traces that should be returned, the server might return more traces than this number but
275
+ * it won't overshoot by too much.
276
+ */
201
277
  maxNumTraces?: int,
278
+ /**
279
+ * Selects join mode for the query,
280
+ * Default: join in this order logs -> transactions -> traces -> blocks
281
+ * JoinAll: join everything to everything. For example if logSelection matches log0, we get the
282
+ * associated transaction of log0 and then we get associated logs of that transaction as well. Applites similarly
283
+ * to blocks, traces.
284
+ * JoinNothing: join nothing.
285
+ */
202
286
  joinMode?: joinMode,
287
+ /**
288
+ * If set to true, the server will return data for all blocks in the requested range [from_block, to_block).
289
+ */
203
290
  includeAllBlocks?: bool,
204
291
  }
205
292
  }
@@ -298,7 +385,8 @@ module ResponseTypes = {
298
385
  gasUsed?: bigint,
299
386
  contractAddress?: string,
300
387
  logsBloom?: string,
301
- @as("type") type_?: int,
388
+ @as("type")
389
+ type_?: int,
302
390
  root?: string,
303
391
  status?: int,
304
392
  l1Fee?: bigint,
@@ -328,18 +416,40 @@ module ResponseTypes = {
328
416
  }
329
417
 
330
418
  type rollbackGuard = {
419
+ /** Block number of the last scanned block */
331
420
  blockNumber: int,
421
+ /** Block timestamp of the last scanned block */
332
422
  timestamp: int,
423
+ /** Block hash of the last scanned block */
333
424
  hash: string,
425
+ /**
426
+ * Block number of the first scanned block in memory.
427
+ *
428
+ * This might not be the first scanned block. It only includes blocks that are in memory (possible to be rolled back).
429
+ */
334
430
  firstBlockNumber: int,
431
+ /**
432
+ * Parent hash of the first scanned block in memory.
433
+ *
434
+ * This might not be the first scanned block. It only includes blocks that are in memory (possible to be rolled back).
435
+ */
335
436
  firstParentHash: string,
336
437
  }
337
438
 
338
439
  type eventResponse = {
440
+ /** Current height of the source hypersync instance */
339
441
  archiveHeight: option<int>,
442
+ /**
443
+ * Next block to query for, the responses are paginated so,
444
+ * the caller should continue the query from this block if they
445
+ * didn't get responses up to the to_block they specified in the Query.
446
+ */
340
447
  nextBlock: int,
448
+ /** Total time it took the hypersync instance to execute the query. */
341
449
  totalExecutionTime: int,
450
+ /** Response data */
342
451
  data: array<event>,
452
+ /** Rollback guard, supposed to be used to detect rollbacks */
343
453
  rollbackGuard: option<rollbackGuard>,
344
454
  }
345
455
  }
@@ -361,16 +471,40 @@ type queryResponse = {
361
471
  rollbackGuard: option<ResponseTypes.rollbackGuard>,
362
472
  }
363
473
 
474
+ //Todo, add bindings for these types
475
+ type streamConfig
476
+ type queryResponseStream
477
+ type eventStream
478
+
479
+ @tag("type")
480
+ type heightStreamEvent =
481
+ | Height({height: int})
482
+ | Connected
483
+ | Reconnecting({delayMillis: int, errorMsg: string})
484
+
485
+ module HeightStream = {
486
+ type t = {
487
+ /** Close the height stream */
488
+ close: unit => promise<unit>,
489
+ /** Receive the next height stream event from the stream */
490
+ recv: unit => promise<heightStreamEvent>,
491
+ }
492
+ }
493
+
364
494
  type t = {
495
+ getHeight: unit => promise<int>,
496
+ collect: (~query: query, ~config: streamConfig) => promise<queryResponse>,
497
+ collectEvents: (~query: query, ~config: streamConfig) => promise<eventResponse>,
498
+ collectParquet: (~path: string, ~query: query, ~config: streamConfig) => promise<unit>,
365
499
  get: (~query: query) => promise<queryResponse>,
366
500
  getEvents: (~query: query) => promise<eventResponse>,
501
+ stream: (~query: query, ~config: streamConfig) => promise<queryResponseStream>,
502
+ streamEvents: (~query: query, ~config: streamConfig) => promise<eventStream>,
503
+ streamHeight: unit => promise<HeightStream.t>,
367
504
  }
368
505
 
369
- @send
370
- external classNewWithAgent: (Core.hypersyncClientCtor, cfg, string) => t = "newWithAgent"
371
-
372
- let makeWithAgent = (cfg, ~userAgent) =>
373
- Core.getAddon().hypersyncClient->classNewWithAgent(cfg, userAgent)
506
+ @module("@envio-dev/hypersync-client") @scope("HypersyncClient")
507
+ external makeWithAgent: (cfg, ~userAgent: string) => t = "newWithAgent"
374
508
 
375
509
  let make = (
376
510
  ~url,
@@ -406,19 +540,11 @@ type logLevel = [#trace | #debug | #info | #warn | #error]
406
540
  let logLevelSchema: S.t<logLevel> = S.enum([#trace, #debug, #info, #warn, #error])
407
541
 
408
542
  /**
409
- * Set the log level for the underlying Rust logger.
543
+ * Set the log level for the underlying Rust logger in hypersync-client.
410
544
  * Must be called before creating any HypersyncClient.
411
545
  */
412
- let setLogLevel = (level: logLevel) => {
413
- let s = switch level {
414
- | #trace => "trace"
415
- | #debug => "debug"
416
- | #info => "info"
417
- | #warn => "warn"
418
- | #error => "error"
419
- }
420
- Core.getAddon().setLogLevel(s)
421
- }
546
+ @module("@envio-dev/hypersync-client")
547
+ external setLogLevel: logLevel => unit = "setLogLevel"
422
548
 
423
549
  module Decoder = {
424
550
  type rec decodedSolType<'a> = {val: 'a}
@@ -453,17 +579,18 @@ module Decoder = {
453
579
  body: array<decodedRaw>,
454
580
  }
455
581
 
582
+ type log
456
583
  type t = {
584
+ enableChecksummedAddresses: unit => unit,
585
+ disableChecksummedAddresses: unit => unit,
586
+ decodeLogs: array<log> => promise<array<Nullable.t<decodedEvent>>>,
587
+ decodeLogsSync: array<log> => array<Nullable.t<decodedEvent>>,
457
588
  decodeEvents: array<ResponseTypes.event> => promise<array<Nullable.t<decodedEvent>>>,
589
+ decodeEventsSync: array<ResponseTypes.event> => array<Nullable.t<decodedEvent>>,
458
590
  }
459
591
 
460
- @send
461
- external classFromSignatures: (
462
- Core.decoderCtor,
463
- array<string>,
464
- ~checksumAddresses: bool=?,
465
- ) => t = "fromSignatures"
466
-
467
- let fromSignatures = (signatures, ~checksumAddresses=?) =>
468
- Core.getAddon().decoder->classFromSignatures(signatures, ~checksumAddresses?)
592
+ @module("@envio-dev/hypersync-client") @scope("Decoder")
593
+ external fromSignatures: array<string> => t = "fromSignatures"
594
+ // Keep the @envio-dev/hypersync-client import inside of the package
595
+ let fromSignatures = fromSignatures
469
596
  }
@@ -1,11 +1,10 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
- import * as Core from "../Core.res.mjs";
4
3
  import * as Utils from "../Utils.res.mjs";
5
4
  import * as Address from "../Address.res.mjs";
6
5
  import * as Belt_Array from "@rescript/runtime/lib/es6/Belt_Array.js";
7
- import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
8
6
  import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
7
+ import * as HypersyncClient from "@envio-dev/hypersync-client";
9
8
 
10
9
  let serializationFormatSchema = S$RescriptSchema.$$enum([
11
10
  "Json",
@@ -59,14 +58,12 @@ let ResponseTypes = {
59
58
  authorizationListSchema: authorizationListSchema
60
59
  };
61
60
 
62
- function makeWithAgent(cfg, userAgent) {
63
- return Core.getAddon().HypersyncClient.newWithAgent(cfg, userAgent);
64
- }
61
+ let HeightStream = {};
65
62
 
66
63
  function make(url, apiToken, httpReqTimeoutMillis, maxNumRetries, enableChecksumAddressesOpt, serializationFormat, enableQueryCaching, retryBaseMs, retryBackoffMs, retryCeilingMs) {
67
64
  let enableChecksumAddresses = enableChecksumAddressesOpt !== undefined ? enableChecksumAddressesOpt : true;
68
65
  let envioVersion = Utils.EnvioPackage.value.version;
69
- return makeWithAgent({
66
+ return HypersyncClient.HypersyncClient.newWithAgent({
70
67
  url: url,
71
68
  apiToken: apiToken,
72
69
  httpReqTimeoutMillis: httpReqTimeoutMillis,
@@ -88,16 +85,6 @@ let logLevelSchema = S$RescriptSchema.$$enum([
88
85
  "error"
89
86
  ]);
90
87
 
91
- function setLogLevel(level) {
92
- Core.getAddon().setLogLevel(level === "warn" ? "warn" : (
93
- level === "debug" ? "debug" : (
94
- level === "error" ? "error" : (
95
- level === "trace" ? "trace" : "info"
96
- )
97
- )
98
- ));
99
- }
100
-
101
88
  function toUnderlying(_d) {
102
89
  while (true) {
103
90
  let d = _d;
@@ -118,8 +105,8 @@ function toUnderlying(_d) {
118
105
  };
119
106
  }
120
107
 
121
- function fromSignatures(signatures, checksumAddresses) {
122
- return Core.getAddon().Decoder.fromSignatures(signatures, checksumAddresses !== undefined ? Primitive_option.valFromOption(checksumAddresses) : undefined);
108
+ function fromSignatures(prim) {
109
+ return HypersyncClient.Decoder.fromSignatures(prim);
123
110
  }
124
111
 
125
112
  let Decoder = {
@@ -131,10 +118,9 @@ export {
131
118
  serializationFormatSchema,
132
119
  QueryTypes,
133
120
  ResponseTypes,
134
- makeWithAgent,
121
+ HeightStream,
135
122
  make,
136
123
  logLevelSchema,
137
- setLogLevel,
138
124
  Decoder,
139
125
  }
140
126
  /* serializationFormatSchema Not a pure module */
@@ -192,15 +192,18 @@ Learn more or get a free API token at: https://envio.dev/app/api-tokens`)
192
192
  switch hscDecoder.contents {
193
193
  | Some(decoder) => decoder
194
194
  | None =>
195
- switch HyperSyncClient.Decoder.fromSignatures(
196
- allEventSignatures,
197
- ~checksumAddresses=!lowercaseAddresses,
198
- ) {
195
+ switch HyperSyncClient.Decoder.fromSignatures(allEventSignatures) {
199
196
  | exception exn =>
200
197
  exn->ErrorHandling.mkLogAndRaise(
201
198
  ~msg="Failed to instantiate a decoder from hypersync client, please double check your ABI",
202
199
  )
203
- | decoder => decoder
200
+ | decoder =>
201
+ if lowercaseAddresses {
202
+ decoder.disableChecksummedAddresses()
203
+ } else {
204
+ decoder.enableChecksummedAddresses()
205
+ }
206
+ decoder
204
207
  }
205
208
  }
206
209
  }