envio 2.32.2 → 3.0.0-alpha-main-clickhouse-sink

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
@@ -7,6 +7,7 @@ export type {
7
7
  rateLimitDuration as RateLimitDuration,
8
8
  rateLimit as RateLimit,
9
9
  blockEvent as BlockEvent,
10
+ fuelBlockEvent as FuelBlockEvent,
10
11
  onBlockArgs as OnBlockArgs,
11
12
  onBlockOptions as OnBlockOptions,
12
13
  } from "./src/Envio.gen.ts";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "envio",
3
- "version": "v2.32.2",
3
+ "version": "v3.0.0-alpha-main-clickhouse-sink",
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,12 +25,13 @@
25
25
  },
26
26
  "homepage": "https://envio.dev",
27
27
  "optionalDependencies": {
28
- "envio-linux-x64": "v2.32.2",
29
- "envio-linux-arm64": "v2.32.2",
30
- "envio-darwin-x64": "v2.32.2",
31
- "envio-darwin-arm64": "v2.32.2"
28
+ "envio-linux-x64": "v3.0.0-alpha-main-clickhouse-sink",
29
+ "envio-linux-arm64": "v3.0.0-alpha-main-clickhouse-sink",
30
+ "envio-darwin-x64": "v3.0.0-alpha-main-clickhouse-sink",
31
+ "envio-darwin-arm64": "v3.0.0-alpha-main-clickhouse-sink"
32
32
  },
33
33
  "dependencies": {
34
+ "@clickhouse/client": "1.12.1",
34
35
  "@envio-dev/hypersync-client": "0.6.6",
35
36
  "@envio-dev/hyperfuel-client": "1.2.2",
36
37
  "rescript": "11.1.3",
package/src/Batch.res CHANGED
@@ -24,7 +24,7 @@ type t = {
24
24
  items: array<Internal.item>,
25
25
  progressedChainsById: dict<chainAfterBatch>,
26
26
  // Unnest-like checkpoint fields:
27
- checkpointIds: array<int>,
27
+ checkpointIds: array<float>,
28
28
  checkpointChainIds: array<int>,
29
29
  checkpointBlockNumbers: array<int>,
30
30
  checkpointBlockHashes: array<Js.Null.t<string>>,
@@ -196,7 +196,7 @@ let addReorgCheckpoints = (
196
196
  for blockNumber in fromBlockExclusive + 1 to toBlockExclusive - 1 {
197
197
  switch reorgDetection->ReorgDetection.getHashByBlockNumber(~blockNumber) {
198
198
  | Js.Null.Value(hash) =>
199
- let checkpointId = prevCheckpointId.contents + 1
199
+ let checkpointId = prevCheckpointId.contents +. 1.
200
200
  prevCheckpointId := checkpointId
201
201
 
202
202
  mutCheckpointIds->Js.Array2.push(checkpointId)->ignore
@@ -277,7 +277,7 @@ let prepareOrderedBatch = (
277
277
  ~mutCheckpointEventsProcessed=checkpointEventsProcessed,
278
278
  )
279
279
 
280
- let checkpointId = prevCheckpointId.contents + 1
280
+ let checkpointId = prevCheckpointId.contents +. 1.
281
281
 
282
282
  items
283
283
  ->Js.Array2.push(item0)
@@ -421,7 +421,7 @@ let prepareUnorderedBatch = (
421
421
  ~mutCheckpointEventsProcessed=checkpointEventsProcessed,
422
422
  )
423
423
 
424
- let checkpointId = prevCheckpointId.contents + 1
424
+ let checkpointId = prevCheckpointId.contents +. 1.
425
425
 
426
426
  checkpointIds->Js.Array2.push(checkpointId)->ignore
427
427
  checkpointChainIds->Js.Array2.push(fetchState.chainId)->ignore
package/src/Change.res ADDED
@@ -0,0 +1,9 @@
1
+ @tag("type")
2
+ type t<'entity> =
3
+ | @as("SET") Set({entityId: string, entity: 'entity, checkpointId: float})
4
+ | @as("DELETE") Delete({entityId: string, checkpointId: float})
5
+
6
+ @get
7
+ external getEntityId: t<'entity> => string = "entityId"
8
+ @get
9
+ external getCheckpointId: t<'entity> => float = "checkpointId"
@@ -0,0 +1,2 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
package/src/Config.res CHANGED
@@ -1,7 +1,5 @@
1
1
  open Belt
2
2
 
3
- type ecosystem = | @as("evm") Evm | @as("fuel") Fuel
4
-
5
3
  type sourceSyncOptions = {
6
4
  initialBlockInterval?: int,
7
5
  backoffMultiplicative?: float,
@@ -47,7 +45,7 @@ type t = {
47
45
  multichain: multichain,
48
46
  chainMap: ChainMap.t<chain>,
49
47
  defaultChain: option<chain>,
50
- ecosystem: ecosystem,
48
+ platform: Platform.t,
51
49
  enableRawEvents: bool,
52
50
  preloadHandlers: bool,
53
51
  maxAddrInPartition: int,
@@ -62,7 +60,7 @@ let make = (
62
60
  ~chains: array<chain>=[],
63
61
  ~enableRawEvents=false,
64
62
  ~preloadHandlers=false,
65
- ~ecosystem=Evm,
63
+ ~ecosystem: Platform.name=Platform.Evm,
66
64
  ~batchSize=5000,
67
65
  ~lowercaseAddresses=false,
68
66
  ~multichain=Unordered,
@@ -92,6 +90,8 @@ let make = (
92
90
  })
93
91
  })
94
92
 
93
+ let platform = Platform.fromName(ecosystem)
94
+
95
95
  {
96
96
  shouldRollbackOnReorg,
97
97
  shouldSaveFullHistory,
@@ -99,7 +99,7 @@ let make = (
99
99
  chainMap,
100
100
  defaultChain: chains->Array.get(0),
101
101
  enableRawEvents,
102
- ecosystem,
102
+ platform,
103
103
  maxAddrInPartition,
104
104
  preloadHandlers,
105
105
  batchSize,
package/src/Config.res.js CHANGED
@@ -4,6 +4,7 @@
4
4
  var Utils = require("./Utils.res.js");
5
5
  var Js_exn = require("rescript/lib/js/js_exn.js");
6
6
  var ChainMap = require("./ChainMap.res.js");
7
+ var Platform = require("./Platform.res.js");
7
8
  var Belt_Array = require("rescript/lib/js/belt_Array.js");
8
9
 
9
10
  function make(shouldRollbackOnReorgOpt, shouldSaveFullHistoryOpt, chainsOpt, enableRawEventsOpt, preloadHandlersOpt, ecosystemOpt, batchSizeOpt, lowercaseAddressesOpt, multichainOpt, shouldUseHypersyncClientDecoderOpt, maxAddrInPartitionOpt) {
@@ -34,13 +35,14 @@ function make(shouldRollbackOnReorgOpt, shouldSaveFullHistoryOpt, chainsOpt, ena
34
35
  addContractNameToContractNameMapping[addKey] = contract.name;
35
36
  }));
36
37
  }));
38
+ var platform = Platform.fromName(ecosystem);
37
39
  return {
38
40
  shouldRollbackOnReorg: shouldRollbackOnReorg,
39
41
  shouldSaveFullHistory: shouldSaveFullHistory,
40
42
  multichain: multichain,
41
43
  chainMap: chainMap,
42
44
  defaultChain: Belt_Array.get(chains, 0),
43
- ecosystem: ecosystem,
45
+ platform: platform,
44
46
  enableRawEvents: enableRawEvents,
45
47
  preloadHandlers: preloadHandlers,
46
48
  maxAddrInPartition: maxAddrInPartition,
package/src/Envio.gen.ts CHANGED
@@ -11,11 +11,11 @@ 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';
14
+ export type blockEvent = { readonly number: number; readonly chainId: number };
15
15
 
16
- export type blockEvent = Internal_blockEvent;
16
+ export type fuelBlockEvent = { readonly height: number; readonly chainId: number };
17
17
 
18
- export type onBlockArgs<context> = { readonly block: blockEvent; readonly context: context };
18
+ export type onBlockArgs<block,context> = { readonly block: block; readonly context: context };
19
19
 
20
20
  export type onBlockOptions<chain> = {
21
21
  readonly name: string;
package/src/Envio.res CHANGED
@@ -2,12 +2,23 @@
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
+ // EVM block event with 'number' field for backward compatibility
5
6
  @genType
6
- type blockEvent = Internal.blockEvent
7
+ type blockEvent = {
8
+ number: int,
9
+ chainId: int,
10
+ }
11
+
12
+ // Fuel block event with 'height' field
13
+ @genType
14
+ type fuelBlockEvent = {
15
+ height: int,
16
+ chainId: int,
17
+ }
7
18
 
8
19
  @genType
9
- type onBlockArgs<'context> = {
10
- block: blockEvent,
20
+ type onBlockArgs<'block, 'context> = {
21
+ block: 'block,
11
22
  context: 'context,
12
23
  }
13
24
 
@@ -4,7 +4,7 @@ type registrations = {
4
4
  }
5
5
 
6
6
  type activeRegistration = {
7
- ecosystem: Config.ecosystem,
7
+ platform: Platform.t,
8
8
  multichain: Config.multichain,
9
9
  preloadHandlers: bool,
10
10
  registrations: registrations,
@@ -36,9 +36,9 @@ let withRegistration = (fn: activeRegistration => unit) => {
36
36
  }
37
37
  }
38
38
 
39
- let startRegistration = (~ecosystem, ~multichain, ~preloadHandlers) => {
39
+ let startRegistration = (~platform, ~multichain, ~preloadHandlers) => {
40
40
  let r = {
41
- ecosystem,
41
+ platform,
42
42
  multichain,
43
43
  preloadHandlers,
44
44
  registrations: {
@@ -80,14 +80,6 @@ let onBlockOptionsSchema = S.schema(s =>
80
80
 
81
81
  let onBlock = (rawOptions: unknown, handler: Internal.onBlockArgs => promise<unit>) => {
82
82
  withRegistration(registration => {
83
- // There's no big reason for this. It's just more work
84
- switch registration.ecosystem {
85
- | Evm => ()
86
- | Fuel =>
87
- Js.Exn.raiseError(
88
- "Block Handlers are not supported for non-EVM ecosystems. Please reach out to the Envio team if you need this feature.",
89
- )
90
- }
91
83
  // We need to get timestamp for ordered multichain mode
92
84
  switch registration.multichain {
93
85
  | Unordered => ()
@@ -28,9 +28,9 @@ function withRegistration(fn) {
28
28
  }
29
29
  }
30
30
 
31
- function startRegistration(ecosystem, multichain, preloadHandlers) {
31
+ function startRegistration(platform, multichain, preloadHandlers) {
32
32
  var r = {
33
- ecosystem: ecosystem,
33
+ platform: platform,
34
34
  multichain: multichain,
35
35
  preloadHandlers: preloadHandlers,
36
36
  registrations: {
@@ -71,12 +71,8 @@ var onBlockOptionsSchema = S$RescriptSchema.schema(function (s) {
71
71
 
72
72
  function onBlock(rawOptions, handler) {
73
73
  withRegistration(function (registration) {
74
- var match = registration.ecosystem;
75
- if (match !== "evm") {
76
- Js_exn.raiseError("Block Handlers are not supported for non-EVM ecosystems. Please reach out to the Envio team if you need this feature.");
77
- }
78
- var match$1 = registration.multichain;
79
- if (match$1 === "ordered") {
74
+ var match = registration.multichain;
75
+ if (match === "ordered") {
80
76
  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.");
81
77
  }
82
78
  if (registration.preloadHandlers) {
@@ -4,7 +4,7 @@ type registrations = {
4
4
  }
5
5
 
6
6
  let startRegistration: (
7
- ~ecosystem: Config.ecosystem,
7
+ ~platform: Platform.t,
8
8
  ~multichain: Config.multichain,
9
9
  ~preloadHandlers: bool,
10
10
  ) => unit
@@ -22,9 +22,7 @@ module EntityTables = {
22
22
  switch self->Utils.Dict.dangerouslyGetNonOption(entityName) {
23
23
  | Some(table) =>
24
24
  table->(
25
- Utils.magic: InMemoryTable.Entity.t<Internal.entity> => InMemoryTable.Entity.t<
26
- entity,
27
- >
25
+ Utils.magic: InMemoryTable.Entity.t<Internal.entity> => InMemoryTable.Entity.t<entity>
28
26
  )
29
27
 
30
28
  | None =>
@@ -53,13 +51,10 @@ type t = {
53
51
  rawEvents: InMemoryTable.t<rawEventsKey, InternalTable.RawEvents.t>,
54
52
  entities: dict<InMemoryTable.Entity.t<Internal.entity>>,
55
53
  effects: dict<effectCacheInMemTable>,
56
- rollbackTargetCheckpointId: option<int>,
54
+ rollbackTargetCheckpointId: option<Internal.checkpointId>,
57
55
  }
58
56
 
59
- let make = (
60
- ~entities: array<Internal.entityConfig>,
61
- ~rollbackTargetCheckpointId=?,
62
- ): t => {
57
+ let make = (~entities: array<Internal.entityConfig>, ~rollbackTargetCheckpointId=?): t => {
63
58
  rawEvents: InMemoryTable.make(~hash=hashRawEventsKey),
64
59
  entities: EntityTables.make(entities),
65
60
  effects: Js.Dict.empty(),
@@ -105,9 +100,7 @@ let isRollingBack = (inMemoryStore: t) => inMemoryStore.rollbackTargetCheckpoint
105
100
 
106
101
  let setBatchDcs = (inMemoryStore: t, ~batch: Batch.t, ~shouldSaveHistory) => {
107
102
  let inMemTable =
108
- inMemoryStore->getInMemTable(
109
- ~entityConfig=InternalTable.DynamicContractRegistry.config,
110
- )
103
+ inMemoryStore->getInMemTable(~entityConfig=InternalTable.DynamicContractRegistry.config)
111
104
 
112
105
  let itemIdx = ref(0)
113
106
 
@@ -140,11 +133,11 @@ let setBatchDcs = (inMemoryStore: t, ~batch: Batch.t, ~shouldSaveHistory) => {
140
133
  }
141
134
 
142
135
  inMemTable->InMemoryTable.Entity.set(
143
- {
136
+ Set({
144
137
  entityId: entity.id,
145
138
  checkpointId,
146
- entityUpdateAction: Set(entity->InternalTable.DynamicContractRegistry.castToInternal),
147
- },
139
+ entity: entity->InternalTable.DynamicContractRegistry.castToInternal,
140
+ }),
148
141
  ~shouldSaveHistory,
149
142
  )
150
143
  }
@@ -154,4 +147,3 @@ let setBatchDcs = (inMemoryStore: t, ~batch: Batch.t, ~shouldSaveHistory) => {
154
147
  itemIdx := itemIdx.contents + checkpointEventsProcessed
155
148
  }
156
149
  }
157
-
@@ -137,11 +137,9 @@ function setBatchDcs(inMemoryStore, batch, shouldSaveHistory) {
137
137
  contract_name: entity_contract_name
138
138
  };
139
139
  InMemoryTable.Entity.set(inMemTable, {
140
+ type: "SET",
140
141
  entityId: entity_id,
141
- entityUpdateAction: {
142
- TAG: "Set",
143
- _0: entity
144
- },
142
+ entity: entity,
145
143
  checkpointId: checkpointId
146
144
  }, shouldSaveHistory, undefined);
147
145
  }
@@ -39,7 +39,8 @@ module Entity = {
39
39
  type indexFieldNameToIndices = t<TableIndices.Index.t, indicesSerializedToValue>
40
40
 
41
41
  type entityWithIndices<'entity> = {
42
- entityRow: Internal.inMemoryStoreRowEntity<'entity>,
42
+ latest: option<'entity>,
43
+ status: Internal.inMemoryStoreEntityStatus<'entity>,
43
44
  entityIndices: Utils.Set.t<TableIndices.Index.t>,
44
45
  }
45
46
  type t<'entity> = {
@@ -147,18 +148,20 @@ module Entity = {
147
148
  //or if allowOverWriteEntity is true (used for mockDb in test helpers)
148
149
  if shouldWriteEntity {
149
150
  let entityIndices = Utils.Set.make()
150
- let initialStoreRow: Internal.inMemoryStoreRowEntity<'entity> = switch entity {
151
+ switch entity {
151
152
  | Some(entity) =>
152
153
  //update table indices in the case where there
153
154
  //is an already set entity
154
155
  inMemTable->updateIndices(~entity, ~entityIndices)
155
- InitialReadFromDb(AlreadySet(entity))
156
-
157
- | None => InitialReadFromDb(NotSet)
156
+ | None => ()
158
157
  }
159
158
  inMemTable.table.dict->Js.Dict.set(
160
159
  key->inMemTable.table.hash,
161
- {entityRow: initialStoreRow, entityIndices},
160
+ {
161
+ latest: entity,
162
+ status: Loaded,
163
+ entityIndices,
164
+ },
162
165
  )
163
166
  }
164
167
  }
@@ -166,56 +169,64 @@ module Entity = {
166
169
  let setRow = set
167
170
  let set = (
168
171
  inMemTable: t<'entity>,
169
- entityUpdate: EntityHistory.entityUpdate<'entity>,
172
+ change: Change.t<'entity>,
170
173
  ~shouldSaveHistory,
171
174
  ~containsRollbackDiffChange=false,
172
175
  ) => {
173
176
  //New entity row with only the latest update
174
177
  @inline
175
- let newEntityRow = () => Internal.Updated({
176
- latest: entityUpdate,
177
- history: shouldSaveHistory ? [entityUpdate] : [],
178
+ let newStatus = () => Internal.Updated({
179
+ latestChange: change,
180
+ history: shouldSaveHistory
181
+ ? [change]
182
+ : Utils.Array.immutableEmpty->(Utils.magic: array<unknown> => array<Change.t<'entity>>),
178
183
  containsRollbackDiffChange,
179
184
  })
185
+ let latest = switch change {
186
+ | Set({entity}) => Some(entity)
187
+ | Delete(_) => None
188
+ }
180
189
 
181
- let {entityRow, entityIndices} = switch inMemTable.table->get(entityUpdate.entityId) {
182
- | None => {entityRow: newEntityRow(), entityIndices: Utils.Set.make()}
183
- | Some({entityRow: InitialReadFromDb(_), entityIndices}) => {
184
- entityRow: newEntityRow(),
190
+ let updatedEntityRecord = switch inMemTable.table->get(change->Change.getEntityId) {
191
+ | None => {latest, status: newStatus(), entityIndices: Utils.Set.make()}
192
+ | Some({status: Loaded, entityIndices}) => {
193
+ latest,
194
+ status: newStatus(),
185
195
  entityIndices,
186
196
  }
187
- | Some({entityRow: Updated(previous_values), entityIndices}) =>
188
- let entityRow = Internal.Updated({
189
- latest: entityUpdate,
197
+ | Some({status: Updated(previous_values), entityIndices}) =>
198
+ let newStatus = Internal.Updated({
199
+ latestChange: change,
190
200
  history: switch shouldSaveHistory {
191
201
  // This prevents two db actions in the same event on the same entity from being recorded to the history table.
192
- | true if previous_values.latest.checkpointId === entityUpdate.checkpointId =>
202
+ | true
203
+ if previous_values.latestChange->Change.getCheckpointId ===
204
+ change->Change.getCheckpointId =>
193
205
  previous_values.history->Utils.Array.setIndexImmutable(
194
206
  previous_values.history->Array.length - 1,
195
- entityUpdate,
207
+ change,
196
208
  )
197
- | true => [...previous_values.history, entityUpdate]
209
+ | true => [...previous_values.history, change]
198
210
  | false => previous_values.history
199
211
  },
200
212
  containsRollbackDiffChange: previous_values.containsRollbackDiffChange,
201
213
  })
202
- {entityRow, entityIndices}
214
+ {latest, status: newStatus, entityIndices}
203
215
  }
204
216
 
205
- switch entityUpdate.entityUpdateAction {
206
- | Set(entity) => inMemTable->updateIndices(~entity, ~entityIndices)
207
- | Delete => inMemTable->deleteEntityFromIndices(~entityId=entityUpdate.entityId, ~entityIndices)
217
+ switch change {
218
+ | Set({entity}) =>
219
+ inMemTable->updateIndices(~entity, ~entityIndices=updatedEntityRecord.entityIndices)
220
+ | Delete({entityId}) =>
221
+ inMemTable->deleteEntityFromIndices(
222
+ ~entityId,
223
+ ~entityIndices=updatedEntityRecord.entityIndices,
224
+ )
208
225
  }
209
- inMemTable.table->setRow(entityUpdate.entityId, {entityRow, entityIndices})
226
+ inMemTable.table->setRow(change->Change.getEntityId, updatedEntityRecord)
210
227
  }
211
228
 
212
- let rowToEntity = row =>
213
- switch row.entityRow {
214
- | Internal.Updated({latest: {entityUpdateAction: Set(entity)}}) => Some(entity)
215
- | Updated({latest: {entityUpdateAction: Delete}}) => None
216
- | InitialReadFromDb(AlreadySet(entity)) => Some(entity)
217
- | InitialReadFromDb(NotSet) => None
218
- }
229
+ let rowToEntity = row => row.latest
219
230
 
220
231
  let getRow = get
221
232
 
@@ -330,10 +341,15 @@ module Entity = {
330
341
  }
331
342
  }
332
343
 
333
- let rows = (inMemTable: t<'entity>) => {
344
+ let updates = (inMemTable: t<'entity>) => {
334
345
  inMemTable.table
335
346
  ->values
336
- ->Array.map(v => v.entityRow)
347
+ ->Array.keepMapU(v =>
348
+ switch v.status {
349
+ | Updated(update) => Some(update)
350
+ | Loaded => None
351
+ }
352
+ )
337
353
  }
338
354
 
339
355
  let values = (inMemTable: t<'entity>) => {
@@ -353,4 +369,3 @@ module Entity = {
353
369
  },
354
370
  }
355
371
  }
356
-