envio 2.29.0-alpha.0 → 2.29.0-alpha.1

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/index.d.ts CHANGED
@@ -4,6 +4,9 @@ export type {
4
4
  effectContext as EffectContext,
5
5
  effectArgs as EffectArgs,
6
6
  effectOptions as EffectOptions,
7
+ blockEvent as BlockEvent,
8
+ onBlockArgs as OnBlockArgs,
9
+ onBlockOptions as OnBlockOptions,
7
10
  } from "./src/Envio.gen.ts";
8
11
  export type { EffectCaller } from "./src/Types.ts";
9
12
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "envio",
3
- "version": "v2.29.0-alpha.0",
3
+ "version": "v2.29.0-alpha.1",
4
4
  "description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
5
5
  "bin": "./bin.js",
6
6
  "main": "./index.js",
@@ -25,10 +25,10 @@
25
25
  },
26
26
  "homepage": "https://envio.dev",
27
27
  "optionalDependencies": {
28
- "envio-linux-x64": "v2.29.0-alpha.0",
29
- "envio-linux-arm64": "v2.29.0-alpha.0",
30
- "envio-darwin-x64": "v2.29.0-alpha.0",
31
- "envio-darwin-arm64": "v2.29.0-alpha.0"
28
+ "envio-linux-x64": "v2.29.0-alpha.1",
29
+ "envio-linux-arm64": "v2.29.0-alpha.1",
30
+ "envio-darwin-x64": "v2.29.0-alpha.1",
31
+ "envio-darwin-arm64": "v2.29.0-alpha.1"
32
32
  },
33
33
  "dependencies": {
34
34
  "@envio-dev/hypersync-client": "0.6.6",
package/src/Batch.res CHANGED
@@ -7,7 +7,7 @@ type progressedChain = {
7
7
  }
8
8
 
9
9
  type t = {
10
- items: array<Internal.eventItem>,
10
+ items: array<Internal.item>,
11
11
  progressedChains: array<progressedChain>,
12
12
  fetchStates: ChainMap.t<FetchState.t>,
13
13
  dcsToStoreByChainId: dict<array<FetchState.indexingContract>>,
@@ -18,19 +18,9 @@ type multiChainEventComparitor = {
18
18
  earliestEvent: FetchState.queueItem,
19
19
  }
20
20
 
21
- let getComparitorFromItem = (queueItem: Internal.eventItem) => {
22
- let {timestamp, chain, blockNumber, logIndex} = queueItem
23
- EventUtils.getEventComparator({
24
- timestamp,
25
- chainId: chain->ChainMap.Chain.toChainId,
26
- blockNumber,
27
- logIndex,
28
- })
29
- }
30
-
31
21
  let getQueueItemComparitor = (earliestQueueItem: FetchState.queueItem, ~chain) => {
32
22
  switch earliestQueueItem {
33
- | Item({item}) => item->getComparitorFromItem
23
+ | Item({item}) => item->EventUtils.getOrderedBatchItemComparator
34
24
  | NoItem({latestFetchedBlock: {blockTimestamp, blockNumber}}) => (
35
25
  blockTimestamp,
36
26
  chain->ChainMap.Chain.toChainId,
@@ -78,13 +68,13 @@ let popOrderedBatchItems = (
78
68
  let rec loop = () =>
79
69
  if items->Array.length < maxBatchSize {
80
70
  switch fetchStates->getOrderedNextItem {
81
- | Some({earliestEvent}) =>
71
+ | Some({earliestEvent, chain}) =>
82
72
  switch earliestEvent {
83
73
  | NoItem(_) => ()
84
74
  | Item({item, popItemOffQueue}) => {
85
75
  popItemOffQueue()
86
76
  items->Js.Array2.push(item)->ignore
87
- sizePerChain->Utils.Dict.incrementByInt(item.chain->ChainMap.Chain.toChainId)
77
+ sizePerChain->Utils.Dict.incrementByInt(chain->ChainMap.Chain.toChainId)
88
78
  loop()
89
79
  }
90
80
  }
package/src/Batch.res.js CHANGED
@@ -8,18 +8,9 @@ var Belt_Array = require("rescript/lib/js/belt_Array.js");
8
8
  var EventUtils = require("./EventUtils.res.js");
9
9
  var FetchState = require("./FetchState.res.js");
10
10
 
11
- function getComparitorFromItem(queueItem) {
12
- return EventUtils.getEventComparator({
13
- timestamp: queueItem.timestamp,
14
- chainId: queueItem.chain,
15
- blockNumber: queueItem.blockNumber,
16
- logIndex: queueItem.logIndex
17
- });
18
- }
19
-
20
11
  function getQueueItemComparitor(earliestQueueItem, chain) {
21
12
  if (earliestQueueItem.TAG === "Item") {
22
- return getComparitorFromItem(earliestQueueItem._0.item);
13
+ return EventUtils.getOrderedBatchItemComparator(earliestQueueItem._0.item);
23
14
  }
24
15
  var match = earliestQueueItem.latestFetchedBlock;
25
16
  return [
@@ -70,10 +61,9 @@ function popOrderedBatchItems(maxBatchSize, fetchStates, sizePerChain) {
70
61
  return ;
71
62
  }
72
63
  var match$1 = earliestEvent._0;
73
- var item = match$1.item;
74
64
  match$1.popItemOffQueue();
75
- items.push(item);
76
- Utils.Dict.incrementByInt(sizePerChain, item.chain);
65
+ items.push(match$1.item);
66
+ Utils.Dict.incrementByInt(sizePerChain, match.chain);
77
67
  continue ;
78
68
  };
79
69
  };
@@ -120,7 +110,6 @@ function popUnorderedBatchItems(maxBatchSize, fetchStates, sizePerChain) {
120
110
  return items;
121
111
  }
122
112
 
123
- exports.getComparitorFromItem = getComparitorFromItem;
124
113
  exports.getQueueItemComparitor = getQueueItemComparitor;
125
114
  exports.isQueueItemEarlier = isQueueItemEarlier;
126
115
  exports.getOrderedNextItem = getOrderedNextItem;
package/src/Envio.gen.ts CHANGED
@@ -11,6 +11,16 @@ import type {Logger as $$logger} from './Types.ts';
11
11
 
12
12
  import type {S_t as RescriptSchema_S_t} from 'rescript-schema/RescriptSchema.gen';
13
13
 
14
+ import type {blockEvent as Internal_blockEvent} from './Internal.gen';
15
+
16
+ export type blockEvent = Internal_blockEvent;
17
+
18
+ export type onBlockArgs<context> = { readonly block: blockEvent; readonly context: context };
19
+
20
+ export type chainReference = number;
21
+
22
+ export type onBlockOptions = { readonly name: string; readonly chain: chainReference };
23
+
14
24
  export type logger = $$logger;
15
25
 
16
26
  export type effect<input,output> = $$effect<input,output>;
package/src/Envio.res CHANGED
@@ -2,6 +2,27 @@
2
2
  // Should be an entry point after we get rid of the generated project.
3
3
  // Don't forget to keep index.d.ts in sync with this file.
4
4
 
5
+ @genType
6
+ type blockEvent = Internal.blockEvent
7
+
8
+ @genType
9
+ type onBlockArgs<'context> = {
10
+ block: blockEvent,
11
+ context: 'context,
12
+ }
13
+
14
+ @unboxed
15
+ type chainReference = Id(int) // | Name(string)
16
+
17
+ @genType
18
+ type onBlockOptions = {
19
+ name: string,
20
+ chain: chainReference,
21
+ // interval?: int,
22
+ // startBlock?: int,
23
+ // endBlock?: int,
24
+ }
25
+
5
26
  @genType.import(("./Types.ts", "Logger"))
6
27
  type logger = {
7
28
  debug: 'params. (string, ~params: {..} as 'params=?) => unit,
@@ -1,3 +1,118 @@
1
+ type registrations = {onBlockByChainId: dict<array<Internal.onBlockConfig>>}
2
+
3
+ type activeRegistration = {
4
+ ecosystem: InternalConfig.ecosystem,
5
+ multichain: InternalConfig.multichain,
6
+ preloadHandlers: bool,
7
+ registrations: registrations,
8
+ mutable finished: bool,
9
+ }
10
+
11
+ let activeRegistration = ref(None)
12
+
13
+ let withRegistration = (fn: activeRegistration => unit) => {
14
+ switch activeRegistration.contents {
15
+ | None => // The file with handlers might run by a non-envio process (eg mocha)
16
+ // So we just ignore handlers in this case
17
+ ()
18
+ | Some(r) =>
19
+ if r.finished {
20
+ Js.Exn.raiseError(
21
+ "The indexer finished initializing, so no more handlers can be registered. Make sure the handlers are registered on the top level of the file.",
22
+ )
23
+ } else {
24
+ fn(r)
25
+ }
26
+ }
27
+ }
28
+
29
+ let startRegistration = (~ecosystem, ~multichain, ~preloadHandlers) => {
30
+ activeRegistration.contents = Some({
31
+ ecosystem,
32
+ multichain,
33
+ preloadHandlers,
34
+ registrations: {
35
+ onBlockByChainId: Js.Dict.empty(),
36
+ },
37
+ finished: false,
38
+ })
39
+ }
40
+
41
+ let finishRegistration = () => {
42
+ switch activeRegistration.contents {
43
+ | Some(r) => {
44
+ r.finished = true
45
+ r.registrations
46
+ }
47
+ | None =>
48
+ Js.Exn.raiseError("The indexer has not started registering handlers, so can't finish it.")
49
+ }
50
+ }
51
+
52
+ let onBlockOptionsSchema = S.schema((s): Envio.onBlockOptions => {
53
+ name: s.matches(S.string),
54
+ chain: Id(s.matches(S.int)),
55
+ })
56
+
57
+ let onBlock = (options: Envio.onBlockOptions, handler: Internal.onBlockArgs => promise<unit>) => {
58
+ withRegistration(registration => {
59
+ // There's no big reason for this. It's just more work
60
+ switch registration.ecosystem {
61
+ | Evm => ()
62
+ | Fuel =>
63
+ Js.Exn.raiseError(
64
+ "Block Handlers are not supported for non-EVM ecosystems. Please reach out to the Envio team if you need this feature.",
65
+ )
66
+ }
67
+ // We need to get timestamp for ordered multichain mode
68
+ switch registration.multichain {
69
+ | Unordered => ()
70
+ | Ordered =>
71
+ Js.Exn.raiseError(
72
+ "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 with `unordered_multichain_mode: true` in your config.",
73
+ )
74
+ }
75
+ // So we encourage users to upgrade to preload optimization
76
+ // otherwise block handlers will be extremely slow
77
+ switch registration.preloadHandlers {
78
+ | true => ()
79
+ | false =>
80
+ Js.Exn.raiseError(
81
+ "Block Handlers require the Preload Optimization feature. Enable it by setting the `preload_handlers` option to `true` in your config.",
82
+ )
83
+ }
84
+
85
+ options->S.assertOrThrow(onBlockOptionsSchema)
86
+ let chainId = switch options.chain {
87
+ | Id(chainId) => chainId
88
+ // Dmitry: I want to add names for chains in the future
89
+ // and to be able to use them as a lookup.
90
+ // To do so, we'll need to pass a config during reigstration
91
+ // instead of isInitialized check.
92
+ }
93
+
94
+ let onBlockByChainId = registration.registrations.onBlockByChainId
95
+
96
+ switch onBlockByChainId->Utils.Dict.dangerouslyGetNonOption(chainId->Belt.Int.toString) {
97
+ | None =>
98
+ onBlockByChainId->Utils.Dict.setByInt(
99
+ chainId,
100
+ [
101
+ (
102
+ {
103
+ index: 0,
104
+ name: options.name,
105
+ chainId,
106
+ handler,
107
+ }: Internal.onBlockConfig
108
+ ),
109
+ ],
110
+ )
111
+ | Some(_) => Js.Exn.raiseError("Currently only one onBlock handler per chain is supported")
112
+ }
113
+ })
114
+ }
115
+
1
116
  type t = {
2
117
  contractName: string,
3
118
  eventName: string,
@@ -54,39 +169,43 @@ let setEventOptions = (t: t, ~eventOptions, ~logger=Logging.getLogger()) => {
54
169
  }
55
170
 
56
171
  let setHandler = (t: t, handler, ~eventOptions, ~logger=Logging.getLogger()) => {
57
- switch t.handler {
58
- | None =>
59
- t.handler =
60
- handler
61
- ->(Utils.magic: Internal.genericHandler<'args> => Internal.handler)
62
- ->Some
63
- | Some(_) =>
64
- let eventNamespace = {contractName: t.contractName, eventName: t.eventName}
65
- DuplicateEventRegistration(eventNamespace)->ErrorHandling.mkLogAndRaise(
66
- ~logger=Logging.createChildFrom(~logger, ~params=eventNamespace),
67
- ~msg="Duplicate registration of event handlers not allowed",
68
- )
69
- }
172
+ withRegistration(_ => {
173
+ switch t.handler {
174
+ | None =>
175
+ t.handler =
176
+ handler
177
+ ->(Utils.magic: Internal.genericHandler<'args> => Internal.handler)
178
+ ->Some
179
+ | Some(_) =>
180
+ let eventNamespace = {contractName: t.contractName, eventName: t.eventName}
181
+ DuplicateEventRegistration(eventNamespace)->ErrorHandling.mkLogAndRaise(
182
+ ~logger=Logging.createChildFrom(~logger, ~params=eventNamespace),
183
+ ~msg="Duplicate registration of event handlers not allowed",
184
+ )
185
+ }
70
186
 
71
- t->setEventOptions(~eventOptions, ~logger)
187
+ t->setEventOptions(~eventOptions, ~logger)
188
+ })
72
189
  }
73
190
 
74
191
  let setContractRegister = (t: t, contractRegister, ~eventOptions, ~logger=Logging.getLogger()) => {
75
- switch t.contractRegister {
76
- | None =>
77
- t.contractRegister = Some(
78
- contractRegister->(
79
- Utils.magic: Internal.genericContractRegister<
80
- Internal.genericContractRegisterArgs<'event, 'context>,
81
- > => Internal.contractRegister
82
- ),
83
- )
84
- | Some(_) =>
85
- let eventNamespace = {contractName: t.contractName, eventName: t.eventName}
86
- DuplicateEventRegistration(eventNamespace)->ErrorHandling.mkLogAndRaise(
87
- ~logger=Logging.createChildFrom(~logger, ~params=eventNamespace),
88
- ~msg="Duplicate contractRegister handlers not allowed",
89
- )
90
- }
91
- t->setEventOptions(~eventOptions, ~logger)
192
+ withRegistration(_ => {
193
+ switch t.contractRegister {
194
+ | None =>
195
+ t.contractRegister = Some(
196
+ contractRegister->(
197
+ Utils.magic: Internal.genericContractRegister<
198
+ Internal.genericContractRegisterArgs<'event, 'context>,
199
+ > => Internal.contractRegister
200
+ ),
201
+ )
202
+ | Some(_) =>
203
+ let eventNamespace = {contractName: t.contractName, eventName: t.eventName}
204
+ DuplicateEventRegistration(eventNamespace)->ErrorHandling.mkLogAndRaise(
205
+ ~logger=Logging.createChildFrom(~logger, ~params=eventNamespace),
206
+ ~msg="Duplicate contractRegister handlers not allowed",
207
+ )
208
+ }
209
+ t->setEventOptions(~eventOptions, ~logger)
210
+ })
92
211
  }
@@ -1,10 +1,90 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
  'use strict';
3
3
 
4
+ var Js_exn = require("rescript/lib/js/js_exn.js");
4
5
  var Logging = require("./Logging.res.js");
5
6
  var Belt_Option = require("rescript/lib/js/belt_Option.js");
6
7
  var ErrorHandling = require("./ErrorHandling.res.js");
7
8
  var Caml_exceptions = require("rescript/lib/js/caml_exceptions.js");
9
+ var S$RescriptSchema = require("rescript-schema/src/S.res.js");
10
+
11
+ var activeRegistration = {
12
+ contents: undefined
13
+ };
14
+
15
+ function withRegistration(fn) {
16
+ var r = activeRegistration.contents;
17
+ if (r !== undefined) {
18
+ if (r.finished) {
19
+ return Js_exn.raiseError("The indexer finished initializing, so no more handlers can be registered. Make sure the handlers are registered on the top level of the file.");
20
+ } else {
21
+ return fn(r);
22
+ }
23
+ }
24
+
25
+ }
26
+
27
+ function startRegistration(ecosystem, multichain, preloadHandlers) {
28
+ activeRegistration.contents = {
29
+ ecosystem: ecosystem,
30
+ multichain: multichain,
31
+ preloadHandlers: preloadHandlers,
32
+ registrations: {
33
+ onBlockByChainId: {}
34
+ },
35
+ finished: false
36
+ };
37
+ }
38
+
39
+ function finishRegistration() {
40
+ var r = activeRegistration.contents;
41
+ if (r !== undefined) {
42
+ r.finished = true;
43
+ return r.registrations;
44
+ } else {
45
+ return Js_exn.raiseError("The indexer has not started registering handlers, so can't finish it.");
46
+ }
47
+ }
48
+
49
+ var onBlockOptionsSchema = S$RescriptSchema.schema(function (s) {
50
+ return {
51
+ name: s.m(S$RescriptSchema.string),
52
+ chain: s.m(S$RescriptSchema.$$int)
53
+ };
54
+ });
55
+
56
+ function onBlock(options, handler) {
57
+ withRegistration(function (registration) {
58
+ var match = registration.ecosystem;
59
+ if (match !== "evm") {
60
+ Js_exn.raiseError("Block Handlers are not supported for non-EVM ecosystems. Please reach out to the Envio team if you need this feature.");
61
+ }
62
+ var match$1 = registration.multichain;
63
+ if (match$1 === "ordered") {
64
+ 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 with `unordered_multichain_mode: true` in your config.");
65
+ }
66
+ if (registration.preloadHandlers) {
67
+
68
+ } else {
69
+ Js_exn.raiseError("Block Handlers require the Preload Optimization feature. Enable it by setting the `preload_handlers` option to `true` in your config.");
70
+ }
71
+ S$RescriptSchema.assertOrThrow(options, onBlockOptionsSchema);
72
+ var chainId = options.chain;
73
+ var onBlockByChainId = registration.registrations.onBlockByChainId;
74
+ var match$2 = onBlockByChainId[String(chainId)];
75
+ if (match$2 !== undefined) {
76
+ return Js_exn.raiseError("Currently only one onBlock handler per chain is supported");
77
+ } else {
78
+ onBlockByChainId[chainId] = [{
79
+ index: 0,
80
+ name: options.name,
81
+ chainId: chainId,
82
+ handler: handler
83
+ }];
84
+ return ;
85
+ }
86
+ });
87
+ }
8
88
 
9
89
  function getHandler(t) {
10
90
  return t.handler;
@@ -75,44 +155,50 @@ function setEventOptions(t, eventOptions, loggerOpt) {
75
155
 
76
156
  function setHandler(t, handler, eventOptions, loggerOpt) {
77
157
  var logger = loggerOpt !== undefined ? loggerOpt : Logging.getLogger();
78
- var match = t.handler;
79
- if (match !== undefined) {
80
- var eventNamespace_contractName = t.contractName;
81
- var eventNamespace_eventName = t.eventName;
82
- var eventNamespace = {
83
- contractName: eventNamespace_contractName,
84
- eventName: eventNamespace_eventName
85
- };
86
- ErrorHandling.mkLogAndRaise(Logging.createChildFrom(logger, eventNamespace), "Duplicate registration of event handlers not allowed", {
87
- RE_EXN_ID: DuplicateEventRegistration,
88
- _1: eventNamespace
89
- });
90
- } else {
91
- t.handler = handler;
92
- }
93
- setEventOptions(t, eventOptions, logger);
158
+ withRegistration(function (param) {
159
+ var match = t.handler;
160
+ if (match !== undefined) {
161
+ var eventNamespace_contractName = t.contractName;
162
+ var eventNamespace_eventName = t.eventName;
163
+ var eventNamespace = {
164
+ contractName: eventNamespace_contractName,
165
+ eventName: eventNamespace_eventName
166
+ };
167
+ ErrorHandling.mkLogAndRaise(Logging.createChildFrom(logger, eventNamespace), "Duplicate registration of event handlers not allowed", {
168
+ RE_EXN_ID: DuplicateEventRegistration,
169
+ _1: eventNamespace
170
+ });
171
+ } else {
172
+ t.handler = handler;
173
+ }
174
+ setEventOptions(t, eventOptions, logger);
175
+ });
94
176
  }
95
177
 
96
178
  function setContractRegister(t, contractRegister, eventOptions, loggerOpt) {
97
179
  var logger = loggerOpt !== undefined ? loggerOpt : Logging.getLogger();
98
- var match = t.contractRegister;
99
- if (match !== undefined) {
100
- var eventNamespace_contractName = t.contractName;
101
- var eventNamespace_eventName = t.eventName;
102
- var eventNamespace = {
103
- contractName: eventNamespace_contractName,
104
- eventName: eventNamespace_eventName
105
- };
106
- ErrorHandling.mkLogAndRaise(Logging.createChildFrom(logger, eventNamespace), "Duplicate contractRegister handlers not allowed", {
107
- RE_EXN_ID: DuplicateEventRegistration,
108
- _1: eventNamespace
109
- });
110
- } else {
111
- t.contractRegister = contractRegister;
112
- }
113
- setEventOptions(t, eventOptions, logger);
180
+ withRegistration(function (param) {
181
+ var match = t.contractRegister;
182
+ if (match !== undefined) {
183
+ var eventNamespace_contractName = t.contractName;
184
+ var eventNamespace_eventName = t.eventName;
185
+ var eventNamespace = {
186
+ contractName: eventNamespace_contractName,
187
+ eventName: eventNamespace_eventName
188
+ };
189
+ ErrorHandling.mkLogAndRaise(Logging.createChildFrom(logger, eventNamespace), "Duplicate contractRegister handlers not allowed", {
190
+ RE_EXN_ID: DuplicateEventRegistration,
191
+ _1: eventNamespace
192
+ });
193
+ } else {
194
+ t.contractRegister = contractRegister;
195
+ }
196
+ setEventOptions(t, eventOptions, logger);
197
+ });
114
198
  }
115
199
 
200
+ exports.startRegistration = startRegistration;
201
+ exports.finishRegistration = finishRegistration;
116
202
  exports.make = make;
117
203
  exports.setHandler = setHandler;
118
204
  exports.setContractRegister = setContractRegister;
@@ -121,4 +207,5 @@ exports.getContractRegister = getContractRegister;
121
207
  exports.getEventFilters = getEventFilters;
122
208
  exports.isWildcard = isWildcard;
123
209
  exports.hasRegistration = hasRegistration;
124
- /* Logging Not a pure module */
210
+ exports.onBlock = onBlock;
211
+ /* onBlockOptionsSchema Not a pure module */
@@ -1,3 +1,12 @@
1
+ type registrations = {onBlockByChainId: dict<array<Internal.onBlockConfig>>}
2
+
3
+ let startRegistration: (
4
+ ~ecosystem: InternalConfig.ecosystem,
5
+ ~multichain: InternalConfig.multichain,
6
+ ~preloadHandlers: bool,
7
+ ) => unit
8
+ let finishRegistration: unit => registrations
9
+
1
10
  type t
2
11
  let make: (~contractName: string, ~eventName: string) => t
3
12
  let setHandler: (
@@ -19,3 +28,5 @@ let getContractRegister: t => option<Internal.contractRegister>
19
28
  let getEventFilters: t => option<Js.Json.t>
20
29
  let isWildcard: t => bool
21
30
  let hasRegistration: t => bool
31
+
32
+ let onBlock: (Envio.onBlockOptions, Internal.onBlockArgs => promise<unit>) => unit