envio 3.5.0 → 3.5.1-svm-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/evm.schema.json +7 -0
- package/fuel.schema.json +7 -0
- package/index.d.ts +33 -10
- package/package.json +6 -6
- package/src/ChainFetching.res +11 -21
- package/src/ChainFetching.res.mjs +12 -20
- package/src/ChainState.res +41 -4
- package/src/ChainState.res.mjs +39 -5
- package/src/ChainState.resi +10 -1
- package/src/Config.res +62 -3
- package/src/Config.res.mjs +49 -13
- package/src/EffectState.res +2 -2
- package/src/EffectState.res.mjs +2 -2
- package/src/EntityTables.res +32 -0
- package/src/EntityTables.res.mjs +44 -0
- package/src/Envio.res +7 -7
- package/src/Envio.res.mjs +5 -6
- package/src/FetchState.res +38 -75
- package/src/FetchState.res.mjs +20 -62
- package/src/Hasura.res +37 -3
- package/src/Hasura.res.mjs +23 -5
- package/src/InMemoryStore.res +95 -43
- package/src/InMemoryStore.res.mjs +69 -38
- package/src/IndexerState.res +30 -24
- package/src/IndexerState.res.mjs +20 -35
- package/src/IndexerState.resi +8 -6
- package/src/Internal.res +29 -18
- package/src/Internal.res.mjs +27 -10
- package/src/LoadLayer.res +39 -8
- package/src/LoadLayer.res.mjs +36 -9
- package/src/LoadLayer.resi +2 -0
- package/src/Persistence.res +12 -1
- package/src/PgStorage.res +183 -37
- package/src/PgStorage.res.mjs +149 -34
- package/src/PruneStaleHistory.res +1 -0
- package/src/PruneStaleHistory.res.mjs +2 -1
- package/src/Sink.res +3 -3
- package/src/Sink.res.mjs +2 -2
- package/src/TestIndexer.res +128 -17
- package/src/TestIndexer.res.mjs +75 -9
- package/src/UserContext.res +19 -4
- package/src/UserContext.res.mjs +15 -9
- package/src/Writing.res +8 -16
- package/src/Writing.res.mjs +10 -10
- package/src/bindings/ClickHouse.res +40 -4
- package/src/bindings/ClickHouse.res.mjs +37 -5
- package/src/bindings/Vitest.res +0 -3
- package/src/bindings/Vitest.res.mjs +2 -12
- package/src/db/EntityHistory.res +64 -21
- package/src/db/EntityHistory.res.mjs +43 -22
- package/src/db/InternalTable.res.mjs +31 -31
- package/src/db/Table.res +24 -1
- package/src/db/Table.res.mjs +26 -4
- package/src/sources/AddressStore.res +77 -26
- package/src/sources/AddressStore.res.mjs +21 -10
- package/src/sources/SvmHyperSyncClient.res +8 -7
- package/src/sources/SvmHyperSyncSource.res +38 -1
- package/src/sources/SvmHyperSyncSource.res.mjs +24 -0
- package/svm.schema.json +17 -4
package/src/Config.res
CHANGED
|
@@ -59,11 +59,26 @@ type sourceSync = {
|
|
|
59
59
|
pollingInterval: int,
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
// How a backend spells column names, mirroring `column_name_format` in
|
|
63
|
+
// config.yaml. Only the internal columns the runtime appends need it — user
|
|
64
|
+
// field names arrive pre-resolved from the CLI.
|
|
65
|
+
type columnNameFormat = | @as("original") Original | @as("snake_case") SnakeCase
|
|
66
|
+
|
|
62
67
|
type storage = {
|
|
63
68
|
postgres: bool,
|
|
64
69
|
clickhouse: bool,
|
|
70
|
+
postgresColumnNameFormat: columnNameFormat,
|
|
71
|
+
clickhouseColumnNameFormat: columnNameFormat,
|
|
65
72
|
}
|
|
66
73
|
|
|
74
|
+
let chainIdFieldName = "chainId"
|
|
75
|
+
|
|
76
|
+
let chainIdColumnName = format =>
|
|
77
|
+
switch format {
|
|
78
|
+
| Original => chainIdFieldName
|
|
79
|
+
| SnakeCase => "chain_id"
|
|
80
|
+
}
|
|
81
|
+
|
|
67
82
|
type contractHandler = {
|
|
68
83
|
name: string,
|
|
69
84
|
handler: option<string>,
|
|
@@ -76,6 +91,10 @@ type t = {
|
|
|
76
91
|
contractHandlers: array<contractHandler>,
|
|
77
92
|
shouldRollbackOnReorg: bool,
|
|
78
93
|
shouldSaveFullHistory: bool,
|
|
94
|
+
// False when `disable_default_cross_chain: true` in config.yaml. Entities
|
|
95
|
+
// carry their own resolved `crossChain`; this only decides the default for
|
|
96
|
+
// effects that don't state one.
|
|
97
|
+
defaultCrossChain: bool,
|
|
79
98
|
storage: storage,
|
|
80
99
|
// Widest scalar the internal chain-id columns need, resolved by the CLI from
|
|
81
100
|
// the maximum active chain id. Older configs predate the field, and every id
|
|
@@ -114,7 +133,8 @@ module EnvioAddresses = {
|
|
|
114
133
|
id: string,
|
|
115
134
|
@as("chain_id") chainId: ChainId.t,
|
|
116
135
|
@as("registration_block") registrationBlock: int,
|
|
117
|
-
//
|
|
136
|
+
// Vestigial: always written as -1 and never read back. The column stays so
|
|
137
|
+
// an existing schema doesn't need a migration.
|
|
118
138
|
@as("registration_log_index") registrationLogIndex: int,
|
|
119
139
|
@as("contract_name") contractName: string,
|
|
120
140
|
}
|
|
@@ -160,6 +180,9 @@ module EnvioAddresses = {
|
|
|
160
180
|
// always required to have Postgres enabled (Storage::resolve forbids
|
|
161
181
|
// a Postgres-disabled global), so this is safe regardless of mode.
|
|
162
182
|
storage: {postgres: true, clickhouse: false},
|
|
183
|
+
// The table already keys rows by chain through the composite `id`, so the
|
|
184
|
+
// per-chain mode must not append a second chain-id column to it.
|
|
185
|
+
crossChain: true,
|
|
163
186
|
}->Internal.fromGenericEntityConfig
|
|
164
187
|
}
|
|
165
188
|
|
|
@@ -352,6 +375,7 @@ let entityStorageSchema = S.schema(s =>
|
|
|
352
375
|
let entityJsonSchema = S.schema(s =>
|
|
353
376
|
{
|
|
354
377
|
"name": s.matches(S.string),
|
|
378
|
+
"crossChain": s.matches(S.option(S.bool)),
|
|
355
379
|
"storage": s.matches(S.option(entityStorageSchema)),
|
|
356
380
|
"properties": s.matches(S.array(propertySchema)),
|
|
357
381
|
"derivedFields": s.matches(S.option(S.array(derivedFieldSchema))),
|
|
@@ -423,13 +447,30 @@ let parseEnumsFromJson = (enumsJson: dict<array<string>>): array<Table.enumConfi
|
|
|
423
447
|
)
|
|
424
448
|
}
|
|
425
449
|
|
|
450
|
+
// The chain-id column appended to a per-chain entity's table. It completes the
|
|
451
|
+
// primary key so the same id can exist independently on every chain, and it's
|
|
452
|
+
// spelled per backend because the two can be configured with different
|
|
453
|
+
// `column_name_format`s.
|
|
454
|
+
let makeChainIdField = (~globalStorage: storage) =>
|
|
455
|
+
Table.mkField(
|
|
456
|
+
chainIdFieldName,
|
|
457
|
+
ChainId,
|
|
458
|
+
~fieldSchema=ChainId.schema,
|
|
459
|
+
~isPrimaryKey=true,
|
|
460
|
+
~isChainId=true,
|
|
461
|
+
~postgresDbName=globalStorage.postgresColumnNameFormat->chainIdColumnName,
|
|
462
|
+
~clickhouseDbName=globalStorage.clickhouseColumnNameFormat->chainIdColumnName,
|
|
463
|
+
)
|
|
464
|
+
|
|
426
465
|
let parseEntitiesFromJson = (
|
|
427
466
|
entitiesJson: array<'entityJson>,
|
|
428
467
|
~enumConfigsByName: dict<Table.enumConfig<Table.enum>>,
|
|
429
468
|
~globalStorage: storage,
|
|
469
|
+
~defaultCrossChain: bool,
|
|
430
470
|
): array<Internal.entityConfig> => {
|
|
431
471
|
entitiesJson->Array.mapWithIndex((entityJson, index) => {
|
|
432
472
|
let entityName = entityJson["name"]
|
|
473
|
+
let crossChain = entityJson["crossChain"]->Option.getOr(defaultCrossChain)
|
|
433
474
|
|
|
434
475
|
let fields: array<Table.fieldOrDerived> = entityJson["properties"]->Array.map(prop => {
|
|
435
476
|
let (fieldType, fieldSchema, isNullable, isArray, isIndex) = getFieldTypeAndSchema(
|
|
@@ -477,7 +518,10 @@ let parseEntitiesFromJson = (
|
|
|
477
518
|
|
|
478
519
|
let table = Table.mkTable(
|
|
479
520
|
entityName,
|
|
480
|
-
~fields=Array.
|
|
521
|
+
~fields=Array.concatMany(
|
|
522
|
+
fields,
|
|
523
|
+
[crossChain ? [] : [makeChainIdField(~globalStorage)], derivedFields],
|
|
524
|
+
),
|
|
481
525
|
~compositeIndexes,
|
|
482
526
|
~description=?entityJson["description"],
|
|
483
527
|
)
|
|
@@ -535,14 +579,19 @@ let parseEntitiesFromJson = (
|
|
|
535
579
|
schema: schema->(Utils.magic: S.t<dict<unknown>> => S.t<Internal.entity>),
|
|
536
580
|
table,
|
|
537
581
|
storage,
|
|
582
|
+
crossChain,
|
|
538
583
|
}->Internal.fromGenericEntityConfig
|
|
539
584
|
})
|
|
540
585
|
}
|
|
541
586
|
|
|
587
|
+
let columnNameFormatSchema = S.enum([Original, SnakeCase])
|
|
588
|
+
|
|
542
589
|
let publicConfigStorageSchema = S.schema(s =>
|
|
543
590
|
{
|
|
544
591
|
"postgres": s.matches(S.bool),
|
|
545
592
|
"clickhouse": s.matches(S.option(S.bool)),
|
|
593
|
+
"postgresColumnNameFormat": s.matches(S.option(columnNameFormatSchema)),
|
|
594
|
+
"clickhouseColumnNameFormat": s.matches(S.option(columnNameFormatSchema)),
|
|
546
595
|
}
|
|
547
596
|
)
|
|
548
597
|
|
|
@@ -557,6 +606,7 @@ let publicConfigSchema = S.schema(s =>
|
|
|
557
606
|
"saveFullHistory": s.matches(S.option(S.bool)),
|
|
558
607
|
"rawEvents": s.matches(S.option(S.bool)),
|
|
559
608
|
"chainIdMode": s.matches(S.option(ChainId.modeSchema)),
|
|
609
|
+
"defaultCrossChain": s.matches(S.option(S.bool)),
|
|
560
610
|
"storage": s.matches(publicConfigStorageSchema),
|
|
561
611
|
"evm": s.matches(S.option(publicConfigEvmSchema)),
|
|
562
612
|
"fuel": s.matches(S.option(publicConfigEcosystemSchema)),
|
|
@@ -994,12 +1044,20 @@ let fromPublic = (publicConfigJson: JSON.t) => {
|
|
|
994
1044
|
let globalStorage: storage = {
|
|
995
1045
|
postgres: publicConfig["storage"]["postgres"],
|
|
996
1046
|
clickhouse: publicConfig["storage"]["clickhouse"]->Option.getOr(false),
|
|
1047
|
+
postgresColumnNameFormat: publicConfig["storage"]["postgresColumnNameFormat"]->Option.getOr(
|
|
1048
|
+
Original,
|
|
1049
|
+
),
|
|
1050
|
+
clickhouseColumnNameFormat: publicConfig["storage"]["clickhouseColumnNameFormat"]->Option.getOr(
|
|
1051
|
+
Original,
|
|
1052
|
+
),
|
|
997
1053
|
}
|
|
998
1054
|
|
|
1055
|
+
let defaultCrossChain = publicConfig["defaultCrossChain"]->Option.getOr(true)
|
|
1056
|
+
|
|
999
1057
|
let userEntities =
|
|
1000
1058
|
publicConfig["entities"]
|
|
1001
1059
|
->Option.getOr([])
|
|
1002
|
-
->parseEntitiesFromJson(~enumConfigsByName, ~globalStorage)
|
|
1060
|
+
->parseEntitiesFromJson(~enumConfigsByName, ~globalStorage, ~defaultCrossChain)
|
|
1003
1061
|
|
|
1004
1062
|
let allEntities = userEntities->Array.concat([EnvioAddresses.entityConfig])
|
|
1005
1063
|
|
|
@@ -1035,6 +1093,7 @@ let fromPublic = (publicConfigJson: JSON.t) => {
|
|
|
1035
1093
|
contractHandlers,
|
|
1036
1094
|
shouldRollbackOnReorg: publicConfig["rollbackOnReorg"]->Option.getOr(true),
|
|
1037
1095
|
shouldSaveFullHistory: publicConfig["saveFullHistory"]->Option.getOr(false),
|
|
1096
|
+
defaultCrossChain,
|
|
1038
1097
|
storage: globalStorage,
|
|
1039
1098
|
chainIdMode: publicConfig["chainIdMode"]->Option.getOr(Int32),
|
|
1040
1099
|
chainMap,
|
package/src/Config.res.mjs
CHANGED
|
@@ -22,6 +22,16 @@ import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
|
22
22
|
import * as EventConfigBuilder from "./EventConfigBuilder.res.mjs";
|
|
23
23
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
24
24
|
|
|
25
|
+
let chainIdFieldName = "chainId";
|
|
26
|
+
|
|
27
|
+
function chainIdColumnName(format) {
|
|
28
|
+
if (format === "original") {
|
|
29
|
+
return chainIdFieldName;
|
|
30
|
+
} else {
|
|
31
|
+
return "chain_id";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
25
35
|
let name = "envio_addresses";
|
|
26
36
|
|
|
27
37
|
function makeId(chainId, address) {
|
|
@@ -42,11 +52,11 @@ let schema = S$RescriptSchema.schema(s => ({
|
|
|
42
52
|
}));
|
|
43
53
|
|
|
44
54
|
let table = Table.mkTable(name, undefined, [
|
|
45
|
-
Table.mkField("id", "String", S$RescriptSchema.string, undefined, undefined, undefined, true, undefined, undefined, undefined, undefined, undefined),
|
|
46
|
-
Table.mkField("chain_id", "ChainId", ChainId.schema, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
47
|
-
Table.mkField("registration_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
48
|
-
Table.mkField("registration_log_index", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
49
|
-
Table.mkField("contract_name", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined)
|
|
55
|
+
Table.mkField("id", "String", S$RescriptSchema.string, undefined, undefined, undefined, true, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
56
|
+
Table.mkField("chain_id", "ChainId", ChainId.schema, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
57
|
+
Table.mkField("registration_block", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
58
|
+
Table.mkField("registration_log_index", "Int32", S$RescriptSchema.int, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined),
|
|
59
|
+
Table.mkField("contract_name", "String", S$RescriptSchema.string, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined)
|
|
50
60
|
], undefined);
|
|
51
61
|
|
|
52
62
|
let entityConfig_storage = {
|
|
@@ -59,7 +69,8 @@ let entityConfig = {
|
|
|
59
69
|
index: -1,
|
|
60
70
|
schema: schema,
|
|
61
71
|
table: table,
|
|
62
|
-
storage: entityConfig_storage
|
|
72
|
+
storage: entityConfig_storage,
|
|
73
|
+
crossChain: true
|
|
63
74
|
};
|
|
64
75
|
|
|
65
76
|
let EnvioAddresses = {
|
|
@@ -217,6 +228,7 @@ let entityStorageSchema = S$RescriptSchema.schema(s => ({
|
|
|
217
228
|
|
|
218
229
|
let entityJsonSchema = S$RescriptSchema.schema(s => ({
|
|
219
230
|
name: s.m(S$RescriptSchema.string),
|
|
231
|
+
crossChain: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
|
|
220
232
|
storage: s.m(S$RescriptSchema.option(entityStorageSchema)),
|
|
221
233
|
properties: s.m(S$RescriptSchema.array(propertySchema)),
|
|
222
234
|
derivedFields: s.m(S$RescriptSchema.option(S$RescriptSchema.array(derivedFieldSchema))),
|
|
@@ -324,19 +336,24 @@ function parseEnumsFromJson(enumsJson) {
|
|
|
324
336
|
return Object.entries(enumsJson).map(param => Table.makeEnumConfig(param[0], param[1]));
|
|
325
337
|
}
|
|
326
338
|
|
|
327
|
-
function
|
|
339
|
+
function makeChainIdField(globalStorage) {
|
|
340
|
+
return Table.mkField(chainIdFieldName, "ChainId", ChainId.schema, undefined, undefined, undefined, true, undefined, true, undefined, undefined, chainIdColumnName(globalStorage.postgresColumnNameFormat), chainIdColumnName(globalStorage.clickhouseColumnNameFormat));
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function parseEntitiesFromJson(entitiesJson, enumConfigsByName, globalStorage, defaultCrossChain) {
|
|
328
344
|
return entitiesJson.map((entityJson, index) => {
|
|
329
345
|
let entityName = entityJson.name;
|
|
346
|
+
let crossChain = Stdlib_Option.getOr(entityJson.crossChain, defaultCrossChain);
|
|
330
347
|
let fields = entityJson.properties.map(prop => {
|
|
331
348
|
let match = getFieldTypeAndSchema(prop, enumConfigsByName);
|
|
332
|
-
return Table.mkField(prop.name, match[0], match[1], undefined, match[3], match[2], prop.name === "id", match[4], prop.linkedEntity, prop.description, prop.postgresDbName, prop.clickhouseDbName);
|
|
349
|
+
return Table.mkField(prop.name, match[0], match[1], undefined, match[3], match[2], prop.name === "id", match[4], undefined, prop.linkedEntity, prop.description, prop.postgresDbName, prop.clickhouseDbName);
|
|
333
350
|
});
|
|
334
351
|
let derivedFields = Stdlib_Option.getOr(entityJson.derivedFields, []).map(df => Table.mkDerivedFromField(df.fieldName, df.derivedFromEntity, df.derivedFromField, df.description));
|
|
335
352
|
let compositeIndexes = Stdlib_Option.getOr(entityJson.compositeIndices, []).map(ci => ci.map(f => ({
|
|
336
353
|
fieldName: f.fieldName,
|
|
337
354
|
direction: f.direction === "Asc" ? "Asc" : "Desc"
|
|
338
355
|
})));
|
|
339
|
-
let table = Table.mkTable(entityName, compositeIndexes, fields.concat(derivedFields), entityJson.description);
|
|
356
|
+
let table = Table.mkTable(entityName, compositeIndexes, fields.concat(crossChain ? [] : [makeChainIdField(globalStorage)], derivedFields), entityJson.description);
|
|
340
357
|
let getApiFieldName = prop => {
|
|
341
358
|
let match = prop.linkedEntity;
|
|
342
359
|
if (match !== undefined) {
|
|
@@ -382,14 +399,22 @@ function parseEntitiesFromJson(entitiesJson, enumConfigsByName, globalStorage) {
|
|
|
382
399
|
index: index,
|
|
383
400
|
schema: schema,
|
|
384
401
|
table: table,
|
|
385
|
-
storage: storage
|
|
402
|
+
storage: storage,
|
|
403
|
+
crossChain: crossChain
|
|
386
404
|
};
|
|
387
405
|
});
|
|
388
406
|
}
|
|
389
407
|
|
|
408
|
+
let columnNameFormatSchema = S$RescriptSchema.$$enum([
|
|
409
|
+
"original",
|
|
410
|
+
"snake_case"
|
|
411
|
+
]);
|
|
412
|
+
|
|
390
413
|
let publicConfigStorageSchema = S$RescriptSchema.schema(s => ({
|
|
391
414
|
postgres: s.m(S$RescriptSchema.bool),
|
|
392
|
-
clickhouse: s.m(S$RescriptSchema.option(S$RescriptSchema.bool))
|
|
415
|
+
clickhouse: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
|
|
416
|
+
postgresColumnNameFormat: s.m(S$RescriptSchema.option(columnNameFormatSchema)),
|
|
417
|
+
clickhouseColumnNameFormat: s.m(S$RescriptSchema.option(columnNameFormatSchema))
|
|
393
418
|
}));
|
|
394
419
|
|
|
395
420
|
let publicConfigSchema = S$RescriptSchema.schema(s => ({
|
|
@@ -402,6 +427,7 @@ let publicConfigSchema = S$RescriptSchema.schema(s => ({
|
|
|
402
427
|
saveFullHistory: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
|
|
403
428
|
rawEvents: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
|
|
404
429
|
chainIdMode: s.m(S$RescriptSchema.option(ChainId.modeSchema)),
|
|
430
|
+
defaultCrossChain: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
|
|
405
431
|
storage: s.m(publicConfigStorageSchema),
|
|
406
432
|
evm: s.m(S$RescriptSchema.option(publicConfigEvmSchema)),
|
|
407
433
|
fuel: s.m(S$RescriptSchema.option(publicConfigEcosystemSchema)),
|
|
@@ -689,11 +715,16 @@ function fromPublic(publicConfigJson) {
|
|
|
689
715
|
]));
|
|
690
716
|
let globalStorage_postgres = publicConfig.storage.postgres;
|
|
691
717
|
let globalStorage_clickhouse = Stdlib_Option.getOr(publicConfig.storage.clickhouse, false);
|
|
718
|
+
let globalStorage_postgresColumnNameFormat = Stdlib_Option.getOr(publicConfig.storage.postgresColumnNameFormat, "original");
|
|
719
|
+
let globalStorage_clickhouseColumnNameFormat = Stdlib_Option.getOr(publicConfig.storage.clickhouseColumnNameFormat, "original");
|
|
692
720
|
let globalStorage = {
|
|
693
721
|
postgres: globalStorage_postgres,
|
|
694
|
-
clickhouse: globalStorage_clickhouse
|
|
722
|
+
clickhouse: globalStorage_clickhouse,
|
|
723
|
+
postgresColumnNameFormat: globalStorage_postgresColumnNameFormat,
|
|
724
|
+
clickhouseColumnNameFormat: globalStorage_clickhouseColumnNameFormat
|
|
695
725
|
};
|
|
696
|
-
let
|
|
726
|
+
let defaultCrossChain = Stdlib_Option.getOr(publicConfig.defaultCrossChain, true);
|
|
727
|
+
let userEntities = parseEntitiesFromJson(Stdlib_Option.getOr(publicConfig.entities, []), enumConfigsByName, globalStorage, defaultCrossChain);
|
|
697
728
|
let allEntities = userEntities.concat([entityConfig]);
|
|
698
729
|
let userEntitiesByName = Object.fromEntries(userEntities.map(entityConfig => [
|
|
699
730
|
Utils.$$String.capitalize(entityConfig.name),
|
|
@@ -710,6 +741,7 @@ function fromPublic(publicConfigJson) {
|
|
|
710
741
|
contractHandlers: contractHandlers,
|
|
711
742
|
shouldRollbackOnReorg: Stdlib_Option.getOr(publicConfig.rollbackOnReorg, true),
|
|
712
743
|
shouldSaveFullHistory: Stdlib_Option.getOr(publicConfig.saveFullHistory, false),
|
|
744
|
+
defaultCrossChain: defaultCrossChain,
|
|
713
745
|
storage: globalStorage,
|
|
714
746
|
chainIdMode: Stdlib_Option.getOr(publicConfig.chainIdMode, "int32"),
|
|
715
747
|
chainMap: chainMap,
|
|
@@ -1049,6 +1081,8 @@ function getPgUserEntities(config) {
|
|
|
1049
1081
|
}
|
|
1050
1082
|
|
|
1051
1083
|
export {
|
|
1084
|
+
chainIdFieldName,
|
|
1085
|
+
chainIdColumnName,
|
|
1052
1086
|
EnvioAddresses,
|
|
1053
1087
|
rpcSourceForSchema,
|
|
1054
1088
|
rpcConfigSchema,
|
|
@@ -1069,7 +1103,9 @@ export {
|
|
|
1069
1103
|
entityJsonSchema,
|
|
1070
1104
|
getFieldTypeAndSchema,
|
|
1071
1105
|
parseEnumsFromJson,
|
|
1106
|
+
makeChainIdField,
|
|
1072
1107
|
parseEntitiesFromJson,
|
|
1108
|
+
columnNameFormatSchema,
|
|
1073
1109
|
publicConfigStorageSchema,
|
|
1074
1110
|
publicConfigSchema,
|
|
1075
1111
|
fromPublic,
|
package/src/EffectState.res
CHANGED
|
@@ -131,7 +131,7 @@ let commitCacheCount = (inMemTable: effectCacheInMemTable, ~count) => {
|
|
|
131
131
|
|
|
132
132
|
let statsToMetrics = (stats: effectStats): Metrics.effectMetrics => {
|
|
133
133
|
Metrics.effect: stats.effectName,
|
|
134
|
-
scope: stats.scope->Internal.
|
|
134
|
+
scope: stats.scope->Internal.chainScopeToString,
|
|
135
135
|
callSeconds: stats.callSeconds,
|
|
136
136
|
callSecondsTotal: stats.callSecondsTotal,
|
|
137
137
|
callCount: stats.callCount,
|
|
@@ -152,7 +152,7 @@ let toMetrics = (self: t): array<Metrics.effectMetrics> => {
|
|
|
152
152
|
metrics
|
|
153
153
|
->Array.push({
|
|
154
154
|
Metrics.effect: effectName,
|
|
155
|
-
scope: scope->Internal.
|
|
155
|
+
scope: scope->Internal.chainScopeToString,
|
|
156
156
|
callSeconds: 0.,
|
|
157
157
|
callSecondsTotal: 0.,
|
|
158
158
|
callCount: 0.,
|
package/src/EffectState.res.mjs
CHANGED
|
@@ -68,7 +68,7 @@ function toMetrics(self) {
|
|
|
68
68
|
let stats = t.stats;
|
|
69
69
|
return {
|
|
70
70
|
effect: stats.effectName,
|
|
71
|
-
scope: Internal.
|
|
71
|
+
scope: Internal.chainScopeToString(stats.scope),
|
|
72
72
|
callSeconds: stats.callSeconds,
|
|
73
73
|
callSecondsTotal: stats.callSecondsTotal,
|
|
74
74
|
callCount: stats.callCount,
|
|
@@ -82,7 +82,7 @@ function toMetrics(self) {
|
|
|
82
82
|
Utils.Dict.forEach(self.unregisteredCacheCounts, param => {
|
|
83
83
|
metrics.push({
|
|
84
84
|
effect: param.effectName,
|
|
85
|
-
scope: Internal.
|
|
85
|
+
scope: Internal.chainScopeToString(param.scope),
|
|
86
86
|
callSeconds: 0,
|
|
87
87
|
callSecondsTotal: 0,
|
|
88
88
|
callCount: 0,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// One in-memory table per entity, for a single chain scope. The indexer holds
|
|
2
|
+
// the cross-chain partition; each ChainState holds the per-chain one.
|
|
3
|
+
|
|
4
|
+
type t = dict<InMemoryTable.Entity.t>
|
|
5
|
+
|
|
6
|
+
exception UndefinedEntity({entityName: string})
|
|
7
|
+
|
|
8
|
+
let make = (entities: array<Internal.entityConfig>): t => {
|
|
9
|
+
let init = Dict.make()
|
|
10
|
+
entities->Array.forEach(entityConfig => {
|
|
11
|
+
init->Dict.set((entityConfig.name :> string), InMemoryTable.Entity.make())
|
|
12
|
+
})
|
|
13
|
+
init
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let get = (self: t, ~entityName: string) => {
|
|
17
|
+
switch self->Utils.Dict.dangerouslyGetNonOption(entityName) {
|
|
18
|
+
| Some(table) => table
|
|
19
|
+
| None =>
|
|
20
|
+
UndefinedEntity({entityName: entityName})->ErrorHandling.mkLogAndRaise(
|
|
21
|
+
~msg="Unexpected, entity InMemoryTable is undefined",
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Entities whose rows are shared by every chain, so their tables live on the
|
|
27
|
+
// indexer rather than on a ChainState.
|
|
28
|
+
let crossChain = (entities: array<Internal.entityConfig>) =>
|
|
29
|
+
entities->Array.filter((entityConfig: Internal.entityConfig) => entityConfig.crossChain)
|
|
30
|
+
|
|
31
|
+
let perChain = (entities: array<Internal.entityConfig>) =>
|
|
32
|
+
entities->Array.filter((entityConfig: Internal.entityConfig) => !entityConfig.crossChain)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as ErrorHandling from "./ErrorHandling.res.mjs";
|
|
4
|
+
import * as InMemoryTable from "./InMemoryTable.res.mjs";
|
|
5
|
+
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
6
|
+
|
|
7
|
+
let UndefinedEntity = /* @__PURE__ */Primitive_exceptions.create("EntityTables.UndefinedEntity");
|
|
8
|
+
|
|
9
|
+
function make(entities) {
|
|
10
|
+
let init = {};
|
|
11
|
+
entities.forEach(entityConfig => {
|
|
12
|
+
init[entityConfig.name] = InMemoryTable.Entity.make();
|
|
13
|
+
});
|
|
14
|
+
return init;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function get(self, entityName) {
|
|
18
|
+
let table = self[entityName];
|
|
19
|
+
if (table !== undefined) {
|
|
20
|
+
return table;
|
|
21
|
+
} else {
|
|
22
|
+
return ErrorHandling.mkLogAndRaise(undefined, "Unexpected, entity InMemoryTable is undefined", {
|
|
23
|
+
RE_EXN_ID: UndefinedEntity,
|
|
24
|
+
entityName: entityName
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function crossChain(entities) {
|
|
30
|
+
return entities.filter(entityConfig => entityConfig.crossChain);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function perChain(entities) {
|
|
34
|
+
return entities.filter(entityConfig => !entityConfig.crossChain);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
UndefinedEntity,
|
|
39
|
+
make,
|
|
40
|
+
get,
|
|
41
|
+
crossChain,
|
|
42
|
+
perChain,
|
|
43
|
+
}
|
|
44
|
+
/* ErrorHandling Not a pure module */
|
package/src/Envio.res
CHANGED
|
@@ -186,7 +186,8 @@ and effectOptions<'input, 'output> = {
|
|
|
186
186
|
rateLimit: rateLimit,
|
|
187
187
|
/** Whether the effect should be cached. */
|
|
188
188
|
cache?: bool,
|
|
189
|
-
/** Whether the effect's cache is shared across all chains. Defaults to `true
|
|
189
|
+
/** Whether the effect's cache is shared across all chains. Defaults to `true`,
|
|
190
|
+
or to `false` when config.yaml sets `disable_default_cross_chain: true`.
|
|
190
191
|
Set to `false` to isolate the cache (and rate limiting) per chain and enable
|
|
191
192
|
`context.chain.id` inside the handler. */
|
|
192
193
|
crossChain?: bool,
|
|
@@ -196,8 +197,8 @@ and effectContext = {
|
|
|
196
197
|
log: logger,
|
|
197
198
|
effect: 'input 'output. (effect<'input, 'output>, 'input) => promise<'output>,
|
|
198
199
|
mutable cache: bool,
|
|
199
|
-
/** The chain the effect was called on. Only available on
|
|
200
|
-
|
|
200
|
+
/** The chain the effect was called on. Only available on chain-scoped
|
|
201
|
+
effects; accessing it on a cross-chain effect throws. */
|
|
201
202
|
chain: effectChain,
|
|
202
203
|
}
|
|
203
204
|
and effectArgs<'input> = {
|
|
@@ -259,10 +260,9 @@ let createEffect = (
|
|
|
259
260
|
| Some(true) => true
|
|
260
261
|
| _ => false
|
|
261
262
|
},
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
},
|
|
263
|
+
// Left unresolved: the config's `defaultCrossChain` fills it in when the
|
|
264
|
+
// effect didn't state one, and the config isn't available here.
|
|
265
|
+
crossChain: options.crossChain,
|
|
266
266
|
rateLimit: switch options.rateLimit {
|
|
267
267
|
| Disable => None
|
|
268
268
|
| Enable({calls, per}) =>
|
package/src/Envio.res.mjs
CHANGED
|
@@ -30,12 +30,11 @@ function createEffect(options, handler) {
|
|
|
30
30
|
output: s.m(outputSchema)
|
|
31
31
|
}));
|
|
32
32
|
let match = options.cache;
|
|
33
|
-
let match$1 = options.
|
|
34
|
-
let match$2 = options.rateLimit;
|
|
33
|
+
let match$1 = options.rateLimit;
|
|
35
34
|
let tmp;
|
|
36
|
-
tmp = match$
|
|
37
|
-
callsPerDuration: match$
|
|
38
|
-
durationMs: durationToMs(match$
|
|
35
|
+
tmp = match$1 === false ? undefined : ({
|
|
36
|
+
callsPerDuration: match$1.calls,
|
|
37
|
+
durationMs: durationToMs(match$1.per)
|
|
39
38
|
});
|
|
40
39
|
return {
|
|
41
40
|
name: options.name,
|
|
@@ -45,7 +44,7 @@ function createEffect(options, handler) {
|
|
|
45
44
|
outputSchema: outputSchema
|
|
46
45
|
},
|
|
47
46
|
defaultShouldCache: match !== undefined ? match : false,
|
|
48
|
-
crossChain:
|
|
47
|
+
crossChain: options.crossChain,
|
|
49
48
|
output: outputSchema,
|
|
50
49
|
input: S$RescriptSchema.schema(param => options.input),
|
|
51
50
|
rateLimit: tmp
|