envio 3.0.1 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "envio",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "type": "module",
5
5
  "description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
6
6
  "bin": "./bin.mjs",
@@ -71,10 +71,10 @@
71
71
  "tsx": "4.21.0"
72
72
  },
73
73
  "optionalDependencies": {
74
- "envio-linux-x64": "3.0.1",
75
- "envio-linux-x64-musl": "3.0.1",
76
- "envio-linux-arm64": "3.0.1",
77
- "envio-darwin-x64": "3.0.1",
78
- "envio-darwin-arm64": "3.0.1"
74
+ "envio-linux-x64": "3.0.2",
75
+ "envio-linux-x64-musl": "3.0.2",
76
+ "envio-linux-arm64": "3.0.2",
77
+ "envio-darwin-x64": "3.0.2",
78
+ "envio-darwin-arm64": "3.0.2"
79
79
  }
80
80
  }
@@ -142,25 +142,28 @@ let rec abiTypeToDefaultValue = (abiType: string): unknown => {
142
142
 
143
143
  // ============== Named-tuple (struct) schema helpers ==============
144
144
 
145
- // Build a simulate schema that honours component names: whenever an event param
146
- // (or nested field) has components, we decode it as an object with named fields
147
- // rather than a positional tuple. Walks through array wrappers so `struct[]`
148
- // still produces `array<{...}>`.
149
- let rec componentsToSimulateSchema = (abiType: string, components: array<eventParamComponent>): S.t<
150
- unknown,
151
- > => {
145
+ // Build an object schema that honours component names: whenever an event param
146
+ // (or nested field) has components, decode/serialize it as an object with
147
+ // named fields rather than a positional tuple. Walks through array wrappers so
148
+ // `struct[]` still produces `array<{...}>`. `~leafSchema` picks the per-ABI
149
+ // schema for non-tuple leaves (raw-event vs simulate variants differ in how
150
+ // they accept primitives — string-encoded numbers vs native bigints).
151
+ let rec componentsToObjectSchema = (
152
+ ~leafSchema: string => S.t<unknown>,
153
+ abiType: string,
154
+ components: array<eventParamComponent>,
155
+ ): S.t<unknown> => {
152
156
  if abiType->String.endsWith("]") {
153
157
  let bracketIdx = abiType->String.lastIndexOf("[")
154
158
  let baseType = abiType->String.slice(~start=0, ~end=bracketIdx)
155
- S.array(componentsToSimulateSchema(baseType, components))->S.toUnknown
159
+ S.array(componentsToObjectSchema(~leafSchema, baseType, components))->S.toUnknown
156
160
  } else {
157
- // Must be a tuple at this level: build a record keyed by component names.
158
161
  S.object(s => {
159
162
  let dict = Dict.make()
160
163
  components->Array.forEach(c => {
161
164
  let childSchema = switch c.components {
162
- | Some(sub) => componentsToSimulateSchema(c.abiType, sub)
163
- | None => abiTypeToSimulateSchema(c.abiType)
165
+ | Some(sub) => componentsToObjectSchema(~leafSchema, c.abiType, sub)
166
+ | None => leafSchema(c.abiType)
164
167
  }
165
168
  dict->Dict.set(c.name, s.field(c.name, childSchema))
166
169
  })
@@ -233,7 +236,16 @@ let buildParamsSchema = (params: array<eventParam>): S.t<Internal.eventParams> =
233
236
  S.object(s => {
234
237
  let dict = Dict.make()
235
238
  params->Array.forEach(p => {
236
- dict->Dict.set(p.name, s.field(p.name, abiTypeToSchema(p.abiType)))
239
+ // Indexed structs arrive as keccak256 topic hashes (single hex
240
+ // strings), so they keep the positional/leaf path; only non-indexed
241
+ // tuple params get the named-object shape that the HyperSync decoder
242
+ // (componentsToRemapper) produces.
243
+ let paramSchema = switch p.components {
244
+ | Some(components) if !p.indexed =>
245
+ componentsToObjectSchema(~leafSchema=abiTypeToSchema, p.abiType, components)
246
+ | _ => abiTypeToSchema(p.abiType)
247
+ }
248
+ dict->Dict.set(p.name, s.field(p.name, paramSchema))
237
249
  })
238
250
  dict
239
251
  })->(Utils.magic: S.t<dict<unknown>> => S.t<Internal.eventParams>)
@@ -255,7 +267,7 @@ let buildSimulateParamsSchema = (params: array<eventParam>): S.t<Internal.eventP
255
267
  params->Array.forEach(p => {
256
268
  let (paramSchema, paramDefault) = switch p.components {
257
269
  | Some(components) => (
258
- componentsToSimulateSchema(p.abiType, components),
270
+ componentsToObjectSchema(~leafSchema=abiTypeToSimulateSchema, p.abiType, components),
259
271
  componentsToDefaultValue(p.abiType, components),
260
272
  )
261
273
  | None => (abiTypeToSimulateSchema(p.abiType), abiTypeToDefaultValue(p.abiType))
@@ -144,13 +144,13 @@ function abiTypeToDefaultValue(abiType) {
144
144
  }
145
145
  }
146
146
 
147
- function componentsToSimulateSchema(abiType, components) {
147
+ function componentsToObjectSchema(leafSchema, abiType, components) {
148
148
  if (!abiType.endsWith("]")) {
149
149
  return S$RescriptSchema.object(s => {
150
150
  let dict = {};
151
151
  components.forEach(c => {
152
152
  let sub = c.components;
153
- let childSchema = sub !== undefined ? componentsToSimulateSchema(c.abiType, sub) : abiTypeToSimulateSchema(c.abiType);
153
+ let childSchema = sub !== undefined ? componentsToObjectSchema(leafSchema, c.abiType, sub) : leafSchema(c.abiType);
154
154
  dict[c.name] = s.f(c.name, childSchema);
155
155
  });
156
156
  return dict;
@@ -158,7 +158,7 @@ function componentsToSimulateSchema(abiType, components) {
158
158
  }
159
159
  let bracketIdx = abiType.lastIndexOf("[");
160
160
  let baseType = abiType.slice(0, bracketIdx);
161
- return S$RescriptSchema.array(componentsToSimulateSchema(baseType, components));
161
+ return S$RescriptSchema.array(componentsToObjectSchema(leafSchema, baseType, components));
162
162
  }
163
163
 
164
164
  function componentsToDefaultValue(abiType, components) {
@@ -197,7 +197,9 @@ function buildParamsSchema(params) {
197
197
  return S$RescriptSchema.object(s => {
198
198
  let dict = {};
199
199
  params.forEach(p => {
200
- dict[p.name] = s.f(p.name, abiTypeToSchema(p.abiType));
200
+ let components = p.components;
201
+ let paramSchema = components !== undefined && !p.indexed ? componentsToObjectSchema(abiTypeToSchema, p.abiType, components) : abiTypeToSchema(p.abiType);
202
+ dict[p.name] = s.f(p.name, paramSchema);
201
203
  });
202
204
  return dict;
203
205
  });
@@ -213,7 +215,7 @@ function buildSimulateParamsSchema(params) {
213
215
  params.forEach(p => {
214
216
  let components = p.components;
215
217
  let match = components !== undefined ? [
216
- componentsToSimulateSchema(p.abiType, components),
218
+ componentsToObjectSchema(abiTypeToSimulateSchema, p.abiType, components),
217
219
  componentsToDefaultValue(p.abiType, components)
218
220
  ] : [
219
221
  abiTypeToSimulateSchema(p.abiType),
@@ -417,7 +419,7 @@ export {
417
419
  abiTypeToSchema,
418
420
  abiTypeToSimulateSchema,
419
421
  abiTypeToDefaultValue,
420
- componentsToSimulateSchema,
422
+ componentsToObjectSchema,
421
423
  componentsToDefaultValue,
422
424
  componentsToRemapper,
423
425
  buildParamsSchema,
@@ -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