envio 2.14.3 → 2.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,17 +14,17 @@ HyperIndex is a fast, developer-friendly multichain indexer, optimized for both
14
14
  - **[Indexer auto-generation](https://docs.envio.dev/docs/HyperIndex/contract-import)** – Generate Indexers directly from smart contract addresses
15
15
  - **High performance** – Historical backfills at over 5,000+ events per second ([fastest in market](https://docs.envio.dev/blog/indexer-benchmarking-results))
16
16
  - **Local development** – Full-featured local environment with Docker
17
- - **Multichain indexing** – Index any EVM-compatible blockchain and Fuel (simultaneously)
17
+ - **[Multichain indexing](https://docs.envio.dev/docs/HyperIndex/multichain-indexing)** – Index any EVM-compatible blockchain and Fuel (simultaneously)
18
18
  - **Real-time indexing** – Instantly track blockchain events
19
- - **Reorg support** – Graceful handling of blockchain reorganizations
19
+ - **[Reorg support](https://docs.envio.dev/docs/HyperIndex/reorgs-support)** – Graceful handling of blockchain reorganizations
20
20
  - **GraphQL API** – Easy-to-query indexed data
21
21
  - **Flexible language support** – JavaScript, TypeScript, and ReScript
22
22
  - **Factory contract support** – Index data from 100,000+ factory contracts seamlessly
23
23
  - **On-chain & off-chain data integration** – Easily combine multiple data sources
24
- - **Self-hosted & managed options** – Run your own setup or use HyperIndex hosted services
24
+ - **[Self-hosted & managed options](https://docs.envio.dev/docs/HyperIndex/hosted-service)** – Run your own setup or use HyperIndex hosted services
25
25
  - **Detailed logging & error reporting** – Debug and optimize with clarity
26
26
  - **External API actions** – Trigger external services based on blockchain events
27
- - **Wildcard topic indexing** – Flexible indexing based on event topics
27
+ - **[Wildcard topic indexing](https://docs.envio.dev/docs/HyperIndex/wildcard-indexing)** – Flexible indexing based on event topics
28
28
  - **Fallback RPC data sources** – Enhanced reliability with RPC connections
29
29
 
30
30
  ## Getting Started
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "envio",
3
- "version": "v2.14.3",
3
+ "version": "v2.15.0",
4
4
  "description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
5
5
  "bin": "./bin.js",
6
6
  "repository": {
@@ -23,10 +23,10 @@
23
23
  },
24
24
  "homepage": "https://envio.dev",
25
25
  "optionalDependencies": {
26
- "envio-linux-x64": "v2.14.3",
27
- "envio-linux-arm64": "v2.14.3",
28
- "envio-darwin-x64": "v2.14.3",
29
- "envio-darwin-arm64": "v2.14.3"
26
+ "envio-linux-x64": "v2.15.0",
27
+ "envio-linux-arm64": "v2.15.0",
28
+ "envio-darwin-x64": "v2.15.0",
29
+ "envio-darwin-arm64": "v2.15.0"
30
30
  },
31
31
  "dependencies": {
32
32
  "@envio-dev/hypersync-client": "0.6.3",
@@ -3,6 +3,8 @@
3
3
  /* eslint-disable */
4
4
  /* tslint:disable */
5
5
 
6
+ import type {invalid as $$noEventFilters} from './bindings/OpaqueTypes.ts';
7
+
6
8
  import type {t as Address_t} from './Address.gen';
7
9
 
8
10
  export type genericEvent<params,block,transaction> = {
@@ -45,3 +47,5 @@ export type fuelTransferParams = {
45
47
  readonly assetId: string;
46
48
  readonly amount: bigint
47
49
  };
50
+
51
+ export type noEventFilters = $$noEventFilters;
package/src/Internal.res CHANGED
@@ -64,22 +64,16 @@ type genericHandlerWithLoader<'loader, 'handler, 'eventFilters> = {
64
64
  preRegisterDynamicContracts?: bool,
65
65
  }
66
66
 
67
- type eventItem = {
68
- eventName: string,
67
+ type baseEventConfig = {
68
+ id: string,
69
+ name: string,
69
70
  contractName: string,
71
+ isWildcard: bool,
72
+ preRegisterDynamicContracts: bool,
70
73
  loader: option<loader>,
71
74
  handler: option<handler>,
72
75
  contractRegister: option<contractRegister>,
73
- timestamp: int,
74
- chain: ChainMap.Chain.t,
75
- blockNumber: int,
76
- logIndex: int,
77
- event: event,
78
76
  paramsRawEventSchema: S.schema<eventParams>,
79
- //Default to false, if an event needs to
80
- //be reprocessed after it has loaded dynamic contracts
81
- //This gets set to true and does not try and reload events
82
- hasRegisteredDynamicContracts?: bool,
83
77
  }
84
78
 
85
79
  type fuelEventKind =
@@ -89,20 +83,47 @@ type fuelEventKind =
89
83
  | Transfer
90
84
  | Call
91
85
  type fuelEventConfig = {
92
- name: string,
93
- contractName: string,
86
+ ...baseEventConfig,
94
87
  kind: fuelEventKind,
95
- isWildcard: bool,
96
- loader: option<loader>,
97
- handler: option<handler>,
98
- contractRegister: option<contractRegister>,
99
- paramsRawEventSchema: S.schema<eventParams>,
100
88
  }
101
89
  type fuelContractConfig = {
102
90
  name: string,
103
91
  events: array<fuelEventConfig>,
104
92
  }
105
93
 
94
+ type topicSelection = {
95
+ topic0: array<EvmTypes.Hex.t>,
96
+ topic1: array<EvmTypes.Hex.t>,
97
+ topic2: array<EvmTypes.Hex.t>,
98
+ topic3: array<EvmTypes.Hex.t>,
99
+ }
100
+
101
+ type evmEventConfig = {
102
+ ...baseEventConfig,
103
+ getTopicSelectionsOrThrow: (~chain: ChainMap.Chain.t) => array<topicSelection>,
104
+ blockSchema: S.schema<eventBlock>,
105
+ transactionSchema: S.schema<eventTransaction>,
106
+ convertHyperSyncEventArgs: HyperSyncClient.Decoder.decodedEvent => eventParams,
107
+ }
108
+ type evmContractConfig = {
109
+ name: string,
110
+ abi: Ethers.abi,
111
+ events: array<evmEventConfig>,
112
+ }
113
+
114
+ type eventItem = {
115
+ eventConfig: baseEventConfig,
116
+ timestamp: int,
117
+ chain: ChainMap.Chain.t,
118
+ blockNumber: int,
119
+ logIndex: int,
120
+ event: event,
121
+ //Default to false, if an event needs to
122
+ //be reprocessed after it has loaded dynamic contracts
123
+ //This gets set to true and does not try and reload events
124
+ hasRegisteredDynamicContracts?: bool,
125
+ }
126
+
106
127
  @genType
107
128
  type fuelSupplyParams = {
108
129
  subId: string,
@@ -125,3 +146,8 @@ let fuelTransferParamsSchema = S.schema(s => {
125
146
  })
126
147
 
127
148
  type entity = private {id: string}
149
+
150
+ @genType.import(("./bindings/OpaqueTypes.ts", "invalid"))
151
+ type noEventFilters
152
+ type eventFilters
153
+ type eventFiltersArgs = {chainId: int}
@@ -1,24 +1,17 @@
1
- type topicSelection = {
2
- topic0: array<EvmTypes.Hex.t>,
3
- topic1: array<EvmTypes.Hex.t>,
4
- topic2: array<EvmTypes.Hex.t>,
5
- topic3: array<EvmTypes.Hex.t>,
6
- }
7
-
8
1
  exception MissingRequiredTopic0
9
2
  let makeTopicSelection = (~topic0, ~topic1=[], ~topic2=[], ~topic3=[]) =>
10
3
  if topic0->Utils.Array.isEmpty {
11
4
  Error(MissingRequiredTopic0)
12
5
  } else {
13
6
  {
14
- topic0,
7
+ Internal.topic0,
15
8
  topic1,
16
9
  topic2,
17
10
  topic3,
18
11
  }->Ok
19
12
  }
20
13
 
21
- let hasFilters = ({topic1, topic2, topic3}: topicSelection) => {
14
+ let hasFilters = ({topic1, topic2, topic3}: Internal.topicSelection) => {
22
15
  [topic1, topic2, topic3]->Js.Array2.find(topic => !Utils.Array.isEmpty(topic))->Belt.Option.isSome
23
16
  }
24
17
 
@@ -26,7 +19,7 @@ let hasFilters = ({topic1, topic2, topic3}: topicSelection) => {
26
19
  For a group of topic selections, if multiple only use topic0, then they can be compressed into one
27
20
  selection combining the topic0s
28
21
  */
29
- let compressTopicSelections = (topicSelections: array<topicSelection>) => {
22
+ let compressTopicSelections = (topicSelections: array<Internal.topicSelection>) => {
30
23
  let topic0sOfSelectionsWithoutFilters = []
31
24
 
32
25
  let selectionsWithFilters = []
@@ -45,7 +38,7 @@ let compressTopicSelections = (topicSelections: array<topicSelection>) => {
45
38
  | [] => selectionsWithFilters
46
39
  | topic0 =>
47
40
  let selectionWithoutFilters = {
48
- topic0,
41
+ Internal.topic0,
49
42
  topic1: [],
50
43
  topic2: [],
51
44
  topic3: [],
@@ -56,10 +49,61 @@ let compressTopicSelections = (topicSelections: array<topicSelection>) => {
56
49
 
57
50
  type t = {
58
51
  addresses: array<Address.t>,
59
- topicSelections: array<topicSelection>,
52
+ topicSelections: array<Internal.topicSelection>,
60
53
  }
61
54
 
62
55
  let make = (~addresses, ~topicSelections) => {
63
56
  let topicSelections = compressTopicSelections(topicSelections)
64
57
  {addresses, topicSelections}
65
58
  }
59
+
60
+ let fromEventFiltersOrThrow = {
61
+ let emptyTopics = []
62
+ let noopGetter = _ => emptyTopics
63
+
64
+ (
65
+ ~chain,
66
+ ~eventFilters: option<Js.Json.t>,
67
+ ~sighash,
68
+ ~topic1=noopGetter,
69
+ ~topic2=noopGetter,
70
+ ~topic3=noopGetter,
71
+ ) => {
72
+ let topic0 = [sighash->EvmTypes.Hex.fromStringUnsafe]
73
+ switch eventFilters {
74
+ | None => [
75
+ {
76
+ Internal.topic0,
77
+ topic1: emptyTopics,
78
+ topic2: emptyTopics,
79
+ topic3: emptyTopics,
80
+ },
81
+ ]
82
+ | Some(eventFilters) => {
83
+ let eventFilters = if Js.typeof(eventFilters) === "function" {
84
+ (eventFilters->(Utils.magic: Js.Json.t => Internal.eventFiltersArgs => Js.Json.t))({
85
+ chainId: chain->ChainMap.Chain.toChainId,
86
+ })
87
+ } else {
88
+ eventFilters
89
+ }
90
+
91
+ switch eventFilters {
92
+ | Array([]) => [%raw(`{}`)]
93
+ | Array(a) => a
94
+ | _ => [eventFilters]
95
+ }->Js.Array2.map(eventFilter => {
96
+ switch eventFilter {
97
+ | Object(eventFilter) => {
98
+ Internal.topic0,
99
+ topic1: topic1(eventFilter),
100
+ topic2: topic2(eventFilter),
101
+ topic3: topic3(eventFilter),
102
+ }
103
+ | _ => Js.Exn.raiseError("Invalid event filters configuration. Expected an object")
104
+ }
105
+ })
106
+ }
107
+ }
108
+ }
109
+ }
package/src/Utils.res CHANGED
@@ -267,8 +267,6 @@ let unwrapResultExn = res =>
267
267
  external queueMicrotask: (unit => unit) => unit = "queueMicrotask"
268
268
 
269
269
  module Schema = {
270
- let enum = S.enum
271
-
272
270
  let getNonOptionalFieldNames = schema => {
273
271
  let acc = []
274
272
  switch schema->S.classify {
@@ -1 +1,2 @@
1
1
  export type Address = string;
2
+ export type invalid = never;
@@ -422,13 +422,11 @@ type t = {
422
422
 
423
423
  @module("@envio-dev/hypersync-client") @scope("HypersyncClient") external new: cfg => t = "new"
424
424
 
425
- let defaultToken = "3dc856dd-b0ea-494f-b27e-017b8b6b7e07"
426
-
427
- let make = (~url, ~bearerToken: option<string>, ~httpReqTimeoutMillis, ~maxNumRetries) =>
425
+ let make = (~url, ~apiToken, ~httpReqTimeoutMillis, ~maxNumRetries) =>
428
426
  new({
429
427
  url,
430
428
  enableChecksumAddresses: true,
431
- bearerToken: bearerToken->Belt.Option.getWithDefault(defaultToken),
429
+ bearerToken: apiToken,
432
430
  httpReqTimeoutMillis,
433
431
  maxNumRetries,
434
432
  })
@@ -360,13 +360,17 @@ module ResponseTypes = {
360
360
  let queryRoute = Rest.route(() => {
361
361
  path: "/query",
362
362
  method: Post,
363
- input: s => s.body(QueryTypes.postQueryBodySchema),
363
+ input: s =>
364
+ {
365
+ "query": s.body(QueryTypes.postQueryBodySchema),
366
+ "token": s.auth(Bearer),
367
+ },
364
368
  responses: [s => s.data(ResponseTypes.queryResponseSchema)],
365
369
  })
366
370
 
367
371
  let heightRoute = Rest.route(() => {
368
372
  path: "/height",
369
373
  method: Get,
370
- input: _ => (),
374
+ input: s => s.auth(Bearer),
371
375
  responses: [s => s.field("height", S.int)],
372
376
  })
@@ -71,7 +71,7 @@ module GetLogs = {
71
71
  topics->Belt.Array.map(toTopicFilter)
72
72
  }
73
73
 
74
- let mapTopicQuery = ({topic0, topic1, topic2, topic3}: LogSelection.topicSelection): topicQuery =>
74
+ let mapTopicQuery = ({topic0, topic1, topic2, topic3}: Internal.topicSelection): topicQuery =>
75
75
  makeTopicQuery(~topic0, ~topic1, ~topic2, ~topic3)
76
76
 
77
77
  type param = {