envio 2.29.0-alpha.1 → 2.29.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "envio",
3
- "version": "v2.29.0-alpha.1",
3
+ "version": "v2.29.0-alpha.2",
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.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"
28
+ "envio-linux-x64": "v2.29.0-alpha.2",
29
+ "envio-linux-arm64": "v2.29.0-alpha.2",
30
+ "envio-darwin-x64": "v2.29.0-alpha.2",
31
+ "envio-darwin-arm64": "v2.29.0-alpha.2"
32
32
  },
33
33
  "dependencies": {
34
34
  "@envio-dev/hypersync-client": "0.6.6",
package/src/Envio.gen.ts CHANGED
@@ -17,9 +17,13 @@ export type blockEvent = Internal_blockEvent;
17
17
 
18
18
  export type onBlockArgs<context> = { readonly block: blockEvent; readonly context: context };
19
19
 
20
- export type chainReference = number;
21
-
22
- export type onBlockOptions = { readonly name: string; readonly chain: chainReference };
20
+ export type onBlockOptions<chain> = {
21
+ readonly name: string;
22
+ readonly chain: chain;
23
+ readonly interval?: number;
24
+ readonly startBlock?: number;
25
+ readonly endBlock?: number
26
+ };
23
27
 
24
28
  export type logger = $$logger;
25
29
 
package/src/Envio.res CHANGED
@@ -11,16 +11,13 @@ type onBlockArgs<'context> = {
11
11
  context: 'context,
12
12
  }
13
13
 
14
- @unboxed
15
- type chainReference = Id(int) // | Name(string)
16
-
17
14
  @genType
18
- type onBlockOptions = {
15
+ type onBlockOptions<'chain> = {
19
16
  name: string,
20
- chain: chainReference,
21
- // interval?: int,
22
- // startBlock?: int,
23
- // endBlock?: int,
17
+ chain: 'chain,
18
+ interval?: int,
19
+ startBlock?: int,
20
+ endBlock?: int,
24
21
  }
25
22
 
26
23
  @genType.import(("./Types.ts", "Logger"))
@@ -10,11 +10,18 @@ type activeRegistration = {
10
10
 
11
11
  let activeRegistration = ref(None)
12
12
 
13
+ // Might happen for tests when the handler file
14
+ // is imported by a non-envio process (eg mocha)
15
+ // and initialized before we started registration.
16
+ // So we track them here to register when the startRegistration is called.
17
+ // Theoretically we could keep preRegistration without an explicit start
18
+ // but I want it to be this way, so for the actual indexer run
19
+ // an error is thrown with the exact stack trace where the handler was registered.
20
+ let preRegistered = []
21
+
13
22
  let withRegistration = (fn: activeRegistration => unit) => {
14
23
  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
- ()
24
+ | None => preRegistered->Belt.Array.push(fn)
18
25
  | Some(r) =>
19
26
  if r.finished {
20
27
  Js.Exn.raiseError(
@@ -27,7 +34,7 @@ let withRegistration = (fn: activeRegistration => unit) => {
27
34
  }
28
35
 
29
36
  let startRegistration = (~ecosystem, ~multichain, ~preloadHandlers) => {
30
- activeRegistration.contents = Some({
37
+ let r = {
31
38
  ecosystem,
32
39
  multichain,
33
40
  preloadHandlers,
@@ -35,7 +42,15 @@ let startRegistration = (~ecosystem, ~multichain, ~preloadHandlers) => {
35
42
  onBlockByChainId: Js.Dict.empty(),
36
43
  },
37
44
  finished: false,
38
- })
45
+ }
46
+ activeRegistration.contents = Some(r)
47
+ while preRegistered->Js.Array2.length > 0 {
48
+ // Loop + cleanup in one go
49
+ switch preRegistered->Js.Array2.pop {
50
+ | Some(fn) => fn(r)
51
+ | None => ()
52
+ }
53
+ }
39
54
  }
40
55
 
41
56
  let finishRegistration = () => {
@@ -49,12 +64,17 @@ let finishRegistration = () => {
49
64
  }
50
65
  }
51
66
 
52
- let onBlockOptionsSchema = S.schema((s): Envio.onBlockOptions => {
53
- name: s.matches(S.string),
54
- chain: Id(s.matches(S.int)),
55
- })
67
+ let onBlockOptionsSchema = S.schema(s =>
68
+ {
69
+ "name": s.matches(S.string),
70
+ "chain": s.matches(S.int),
71
+ "interval": s.matches(S.option(S.int->S.intMin(1))->S.Option.getOr(1)),
72
+ "startBlock": s.matches(S.option(S.int)),
73
+ "endBlock": s.matches(S.option(S.int)),
74
+ }
75
+ )
56
76
 
57
- let onBlock = (options: Envio.onBlockOptions, handler: Internal.onBlockArgs => promise<unit>) => {
77
+ let onBlock = (rawOptions: unknown, handler: Internal.onBlockArgs => promise<unit>) => {
58
78
  withRegistration(registration => {
59
79
  // There's no big reason for this. It's just more work
60
80
  switch registration.ecosystem {
@@ -82,9 +102,9 @@ let onBlock = (options: Envio.onBlockOptions, handler: Internal.onBlockArgs => p
82
102
  )
83
103
  }
84
104
 
85
- options->S.assertOrThrow(onBlockOptionsSchema)
86
- let chainId = switch options.chain {
87
- | Id(chainId) => chainId
105
+ let options = rawOptions->S.parseOrThrow(onBlockOptionsSchema)
106
+ let chainId = switch options["chain"] {
107
+ | chainId => chainId
88
108
  // Dmitry: I want to add names for chains in the future
89
109
  // and to be able to use them as a lookup.
90
110
  // To do so, we'll need to pass a config during reigstration
@@ -101,7 +121,10 @@ let onBlock = (options: Envio.onBlockOptions, handler: Internal.onBlockArgs => p
101
121
  (
102
122
  {
103
123
  index: 0,
104
- name: options.name,
124
+ name: options["name"],
125
+ startBlock: options["startBlock"],
126
+ endBlock: options["endBlock"],
127
+ interval: options["interval"],
105
128
  chainId,
106
129
  handler,
107
130
  }: Internal.onBlockConfig
@@ -12,6 +12,8 @@ var activeRegistration = {
12
12
  contents: undefined
13
13
  };
14
14
 
15
+ var preRegistered = [];
16
+
15
17
  function withRegistration(fn) {
16
18
  var r = activeRegistration.contents;
17
19
  if (r !== undefined) {
@@ -20,12 +22,14 @@ function withRegistration(fn) {
20
22
  } else {
21
23
  return fn(r);
22
24
  }
25
+ } else {
26
+ preRegistered.push(fn);
27
+ return ;
23
28
  }
24
-
25
29
  }
26
30
 
27
31
  function startRegistration(ecosystem, multichain, preloadHandlers) {
28
- activeRegistration.contents = {
32
+ var r = {
29
33
  ecosystem: ecosystem,
30
34
  multichain: multichain,
31
35
  preloadHandlers: preloadHandlers,
@@ -34,6 +38,14 @@ function startRegistration(ecosystem, multichain, preloadHandlers) {
34
38
  },
35
39
  finished: false
36
40
  };
41
+ activeRegistration.contents = r;
42
+ while(preRegistered.length > 0) {
43
+ var fn = preRegistered.pop();
44
+ if (fn !== undefined) {
45
+ fn(r);
46
+ }
47
+
48
+ };
37
49
  }
38
50
 
39
51
  function finishRegistration() {
@@ -49,11 +61,14 @@ function finishRegistration() {
49
61
  var onBlockOptionsSchema = S$RescriptSchema.schema(function (s) {
50
62
  return {
51
63
  name: s.m(S$RescriptSchema.string),
52
- chain: s.m(S$RescriptSchema.$$int)
64
+ chain: s.m(S$RescriptSchema.$$int),
65
+ interval: s.m(S$RescriptSchema.$$Option.getOr(S$RescriptSchema.option(S$RescriptSchema.intMin(S$RescriptSchema.$$int, 1, undefined)), 1)),
66
+ startBlock: s.m(S$RescriptSchema.option(S$RescriptSchema.$$int)),
67
+ endBlock: s.m(S$RescriptSchema.option(S$RescriptSchema.$$int))
53
68
  };
54
69
  });
55
70
 
56
- function onBlock(options, handler) {
71
+ function onBlock(rawOptions, handler) {
57
72
  withRegistration(function (registration) {
58
73
  var match = registration.ecosystem;
59
74
  if (match !== "evm") {
@@ -68,7 +83,7 @@ function onBlock(options, handler) {
68
83
  } else {
69
84
  Js_exn.raiseError("Block Handlers require the Preload Optimization feature. Enable it by setting the `preload_handlers` option to `true` in your config.");
70
85
  }
71
- S$RescriptSchema.assertOrThrow(options, onBlockOptionsSchema);
86
+ var options = S$RescriptSchema.parseOrThrow(rawOptions, onBlockOptionsSchema);
72
87
  var chainId = options.chain;
73
88
  var onBlockByChainId = registration.registrations.onBlockByChainId;
74
89
  var match$2 = onBlockByChainId[String(chainId)];
@@ -79,6 +94,9 @@ function onBlock(options, handler) {
79
94
  index: 0,
80
95
  name: options.name,
81
96
  chainId: chainId,
97
+ startBlock: options.startBlock,
98
+ endBlock: options.endBlock,
99
+ interval: options.interval,
82
100
  handler: handler
83
101
  }];
84
102
  return ;
@@ -29,4 +29,4 @@ let getEventFilters: t => option<Js.Json.t>
29
29
  let isWildcard: t => bool
30
30
  let hasRegistration: t => bool
31
31
 
32
- let onBlock: (Envio.onBlockOptions, Internal.onBlockArgs => promise<unit>) => unit
32
+ let onBlock: (unknown, Internal.onBlockArgs => promise<unit>) => unit
@@ -52,6 +52,7 @@ type t = {
52
52
  // since partitions might be deleted on merge or cleaned up
53
53
  nextPartitionIndex: int,
54
54
  isFetchingAtHead: bool,
55
+ startBlock: int,
55
56
  endBlock: option<int>,
56
57
  maxAddrInPartition: int,
57
58
  normalSelection: selection,
@@ -78,6 +79,7 @@ let copy = (fetchState: t) => {
78
79
  {
79
80
  maxAddrInPartition: fetchState.maxAddrInPartition,
80
81
  partitions: fetchState.partitions,
82
+ startBlock: fetchState.startBlock,
81
83
  endBlock: fetchState.endBlock,
82
84
  nextPartitionIndex: fetchState.nextPartitionIndex,
83
85
  isFetchingAtHead: fetchState.isFetchingAtHead,
@@ -252,6 +254,7 @@ let updateInternal = (
252
254
 
253
255
  {
254
256
  maxAddrInPartition: fetchState.maxAddrInPartition,
257
+ startBlock: fetchState.startBlock,
255
258
  endBlock: fetchState.endBlock,
256
259
  contractConfigs: fetchState.contractConfigs,
257
260
  normalSelection: fetchState.normalSelection,
@@ -640,10 +643,26 @@ let handleQueryResult = (
640
643
  }
641
644
 
642
645
  if nextLatestFullyFetchedBlockNumber > prevLatestFetchedBlockNumber {
643
- for blockNumber in prevLatestFetchedBlockNumber + 1 to nextLatestFullyFetchedBlockNumber {
644
- for configIdx in 0 to onBlockConfigs->Array.length - 1 {
645
- let onBlockConfig = onBlockConfigs->Js.Array2.unsafe_get(configIdx)
646
- newQueue->Array.push(Block({onBlockConfig, blockNumber, logIndex: blockItemLogIndex}))
646
+ for configIdx in 0 to onBlockConfigs->Array.length - 1 {
647
+ let onBlockConfig = onBlockConfigs->Js.Array2.unsafe_get(configIdx)
648
+
649
+ let handlerStartBlock = switch onBlockConfig.startBlock {
650
+ | Some(startBlock) => startBlock
651
+ | None => fetchState.startBlock
652
+ }
653
+ let rangeStart = Pervasives.max(handlerStartBlock, prevLatestFetchedBlockNumber + 1)
654
+ let rangeEnd = switch onBlockConfig.endBlock {
655
+ | Some(endBlock) => Pervasives.min(endBlock, nextLatestFullyFetchedBlockNumber)
656
+ | None => nextLatestFullyFetchedBlockNumber
657
+ }
658
+ if rangeStart <= rangeEnd {
659
+ for blockNumber in rangeStart to rangeEnd {
660
+ if (blockNumber - handlerStartBlock)->Pervasives.mod(onBlockConfig.interval) === 0 {
661
+ newQueue->Array.push(
662
+ Block({onBlockConfig, blockNumber, logIndex: blockItemLogIndex}),
663
+ )
664
+ }
665
+ }
647
666
  }
648
667
  }
649
668
  }
@@ -959,12 +978,13 @@ let make = (
959
978
  ~contracts: array<indexingContract>,
960
979
  ~maxAddrInPartition,
961
980
  ~chainId,
981
+ ~progressBlockNumber=startBlock - 1,
962
982
  ~onBlockConfigs=?,
963
983
  ~blockLag=0,
964
984
  ): t => {
965
985
  let latestFetchedBlock = {
966
986
  blockTimestamp: 0,
967
- blockNumber: startBlock - 1,
987
+ blockNumber: progressBlockNumber,
968
988
  }
969
989
 
970
990
  let notDependingOnAddresses = []
@@ -1078,6 +1098,7 @@ let make = (
1078
1098
  isFetchingAtHead: false,
1079
1099
  maxAddrInPartition,
1080
1100
  chainId,
1101
+ startBlock,
1081
1102
  endBlock,
1082
1103
  latestFullyFetchedBlock: latestFetchedBlock,
1083
1104
  normalSelection,
@@ -10,6 +10,7 @@ var Logging = require("./Logging.res.js");
10
10
  var Belt_Int = require("rescript/lib/js/belt_Int.js");
11
11
  var Caml_obj = require("rescript/lib/js/caml_obj.js");
12
12
  var Belt_Array = require("rescript/lib/js/belt_Array.js");
13
+ var Caml_int32 = require("rescript/lib/js/caml_int32.js");
13
14
  var Prometheus = require("./Prometheus.res.js");
14
15
  var Belt_Option = require("rescript/lib/js/belt_Option.js");
15
16
  var Belt_Result = require("rescript/lib/js/belt_Result.js");
@@ -21,6 +22,7 @@ function copy(fetchState) {
21
22
  partitions: fetchState.partitions,
22
23
  nextPartitionIndex: fetchState.nextPartitionIndex,
23
24
  isFetchingAtHead: fetchState.isFetchingAtHead,
25
+ startBlock: fetchState.startBlock,
24
26
  endBlock: fetchState.endBlock,
25
27
  maxAddrInPartition: fetchState.maxAddrInPartition,
26
28
  normalSelection: fetchState.normalSelection,
@@ -142,6 +144,7 @@ function updateInternal(fetchState, partitionsOpt, nextPartitionIndexOpt, indexi
142
144
  partitions: partitions,
143
145
  nextPartitionIndex: nextPartitionIndex,
144
146
  isFetchingAtHead: isFetchingAtHead,
147
+ startBlock: fetchState.startBlock,
145
148
  endBlock: fetchState.endBlock,
146
149
  maxAddrInPartition: fetchState.maxAddrInPartition,
147
150
  normalSelection: fetchState.normalSelection,
@@ -423,16 +426,27 @@ function handleQueryResult(fetchState, query, latestFetchedBlock, newItems, curr
423
426
  }
424
427
  var nextLatestFullyFetchedBlockNumber$1 = nextLatestFullyFetchedBlockNumber;
425
428
  if (nextLatestFullyFetchedBlockNumber$1 > prevLatestFetchedBlockNumber) {
426
- for(var blockNumber = prevLatestFetchedBlockNumber + 1 | 0; blockNumber <= nextLatestFullyFetchedBlockNumber$1; ++blockNumber){
427
- for(var configIdx = 0 ,configIdx_finish = onBlockConfigs.length; configIdx < configIdx_finish; ++configIdx){
428
- var onBlockConfig = onBlockConfigs[configIdx];
429
- newQueue.push({
430
- kind: 1,
431
- onBlockConfig: onBlockConfig,
432
- blockNumber: blockNumber,
433
- logIndex: 16777216
434
- });
429
+ for(var configIdx = 0 ,configIdx_finish = onBlockConfigs.length; configIdx < configIdx_finish; ++configIdx){
430
+ var onBlockConfig = onBlockConfigs[configIdx];
431
+ var startBlock = onBlockConfig.startBlock;
432
+ var handlerStartBlock = startBlock !== undefined ? startBlock : fetchState.startBlock;
433
+ var rangeStart = Caml.int_max(handlerStartBlock, prevLatestFetchedBlockNumber + 1 | 0);
434
+ var endBlock = onBlockConfig.endBlock;
435
+ var rangeEnd = endBlock !== undefined && endBlock < nextLatestFullyFetchedBlockNumber$1 ? endBlock : nextLatestFullyFetchedBlockNumber$1;
436
+ if (rangeStart <= rangeEnd) {
437
+ for(var blockNumber = rangeStart; blockNumber <= rangeEnd; ++blockNumber){
438
+ if (Caml_int32.mod_(blockNumber - handlerStartBlock | 0, onBlockConfig.interval) === 0) {
439
+ newQueue.push({
440
+ kind: 1,
441
+ onBlockConfig: onBlockConfig,
442
+ blockNumber: blockNumber,
443
+ logIndex: 16777216
444
+ });
445
+ }
446
+
447
+ }
435
448
  }
449
+
436
450
  }
437
451
  }
438
452
 
@@ -689,11 +703,11 @@ function getEarliestEvent(param) {
689
703
  }
690
704
  }
691
705
 
692
- function make(startBlock, endBlock, eventConfigs, contracts, maxAddrInPartition, chainId, onBlockConfigs, blockLagOpt) {
706
+ function make(startBlock, endBlock, eventConfigs, contracts, maxAddrInPartition, chainId, progressBlockNumberOpt, onBlockConfigs, blockLagOpt) {
707
+ var progressBlockNumber = progressBlockNumberOpt !== undefined ? progressBlockNumberOpt : startBlock - 1 | 0;
693
708
  var blockLag = blockLagOpt !== undefined ? blockLagOpt : 0;
694
- var latestFetchedBlock_blockNumber = startBlock - 1 | 0;
695
709
  var latestFetchedBlock = {
696
- blockNumber: latestFetchedBlock_blockNumber,
710
+ blockNumber: progressBlockNumber,
697
711
  blockTimestamp: 0
698
712
  };
699
713
  var notDependingOnAddresses = [];
@@ -780,7 +794,7 @@ function make(startBlock, endBlock, eventConfigs, contracts, maxAddrInPartition,
780
794
  Prometheus.IndexingAddresses.set(numAddresses, chainId);
781
795
  Prometheus.IndexingPartitions.set(partitions.length, chainId);
782
796
  Prometheus.IndexingBufferSize.set(0, chainId);
783
- Prometheus.IndexingBufferBlockNumber.set(latestFetchedBlock_blockNumber, chainId);
797
+ Prometheus.IndexingBufferBlockNumber.set(progressBlockNumber, chainId);
784
798
  if (endBlock !== undefined) {
785
799
  Prometheus.IndexingEndBlock.set(endBlock, chainId);
786
800
  }
@@ -788,6 +802,7 @@ function make(startBlock, endBlock, eventConfigs, contracts, maxAddrInPartition,
788
802
  partitions: partitions,
789
803
  nextPartitionIndex: partitions.length,
790
804
  isFetchingAtHead: false,
805
+ startBlock: startBlock,
791
806
  endBlock: endBlock,
792
807
  maxAddrInPartition: maxAddrInPartition,
793
808
  normalSelection: normalSelection,
package/src/Internal.res CHANGED
@@ -162,6 +162,9 @@ type onBlockConfig = {
162
162
  index: int,
163
163
  name: string,
164
164
  chainId: int,
165
+ startBlock: option<int>,
166
+ endBlock: option<int>,
167
+ interval: int,
165
168
  handler: onBlockArgs => promise<unit>,
166
169
  }
167
170