envio 3.8.0 → 3.9.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 +2 -2
- package/index.d.ts +158 -104
- package/package.json +6 -6
- package/src/AddressRows.res +121 -0
- package/src/AddressRows.res.mjs +143 -0
- package/src/Batch.res +2 -0
- package/src/Batch.res.mjs +2 -1
- package/src/ChainState.res +76 -70
- package/src/ChainState.res.mjs +76 -65
- package/src/ChainState.resi +14 -9
- package/src/Config.res +23 -82
- package/src/Config.res.mjs +19 -63
- package/src/ContractMapping.res +66 -0
- package/src/ContractMapping.res.mjs +73 -0
- package/src/Core.res +20 -0
- package/src/Core.res.mjs +4 -0
- package/src/EventConfigBuilder.res +0 -2
- package/src/EventConfigBuilder.res.mjs +0 -2
- package/src/FetchState.res +59 -67
- package/src/FetchState.res.mjs +34 -44
- package/src/InMemoryStore.res +17 -30
- package/src/InMemoryStore.res.mjs +11 -23
- package/src/IndexerState.res +21 -1
- package/src/IndexerState.res.mjs +9 -3
- package/src/IndexerState.resi +1 -0
- package/src/Main.res +25 -15
- package/src/Main.res.mjs +19 -14
- package/src/MemoryStorage.res +39 -66
- package/src/MemoryStorage.res.mjs +28 -65
- package/src/Metrics.res +15 -1
- package/src/Metrics.res.mjs +5 -1
- package/src/Persistence.res +30 -16
- package/src/Persistence.res.mjs +8 -5
- package/src/PgStorage.res +183 -65
- package/src/PgStorage.res.mjs +92 -58
- package/src/Rollback.res +14 -10
- package/src/Rollback.res.mjs +4 -2
- package/src/SimulateItems.res +5 -12
- package/src/SimulateItems.res.mjs +6 -10
- package/src/TestIndexer.res +93 -111
- package/src/TestIndexer.res.mjs +61 -88
- package/src/Utils.res +7 -0
- package/src/Utils.res.mjs +9 -2
- package/src/Writing.res +2 -0
- package/src/Writing.res.mjs +2 -1
- package/src/bindings/ClickHouse.res +6 -0
- package/src/bindings/ClickHouse.res.mjs +4 -0
- package/src/bindings/NodeJs.res +9 -0
- package/src/bindings/NodeJs.res.mjs +8 -1
- package/src/bindings/Postgres.res +9 -0
- package/src/bindings/Postgres.res.mjs +3 -0
- package/src/db/EntityHistory.res +12 -18
- package/src/db/EntityHistory.res.mjs +3 -14
- package/src/db/InternalTable.res +171 -65
- package/src/db/InternalTable.res.mjs +176 -73
- package/src/db/Table.res +24 -0
- package/src/db/Table.res.mjs +20 -1
- package/src/sources/AddressSet.res +0 -22
- package/src/sources/AddressStore.res +48 -88
- package/src/sources/AddressStore.res.mjs +11 -22
- package/src/sources/SvmHyperSyncClient.res +17 -21
- package/src/sources/SvmHyperSyncSource.res +4 -9
- package/src/sources/SvmHyperSyncSource.res.mjs +5 -13
- package/svm.schema.json +10 -4
package/src/TestIndexer.res
CHANGED
|
@@ -37,44 +37,19 @@ type testIndexerState = {
|
|
|
37
37
|
// Store decoded entities (not JSON) for proper comparison operations
|
|
38
38
|
entities: dict<dict<Internal.entity>>,
|
|
39
39
|
entityConfigs: dict<Internal.entityConfig>,
|
|
40
|
+
addresses: AddressRows.Table.t,
|
|
41
|
+
contractMapping: ContractMapping.t,
|
|
40
42
|
mutable processChanges: array<unknown>,
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
let addressRowsByChain = (state: testIndexerState) =>
|
|
46
|
+
state.addresses->AddressRows.Table.groupByChain
|
|
45
47
|
|
|
46
|
-
let
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// All indexing addresses (config-seeded + dynamically registered) grouped by
|
|
53
|
-
// chain id string, derived from the envio_addresses entities.
|
|
54
|
-
let getIndexingAddressesByChain = (state: testIndexerState): dict<
|
|
55
|
-
array<Internal.indexingAddress>,
|
|
56
|
-
> => {
|
|
57
|
-
let byChain = Dict.make()
|
|
58
|
-
switch state.entities->Dict.get(InternalTable.EnvioAddresses.name) {
|
|
59
|
-
| Some(dcDict) =>
|
|
60
|
-
dcDict
|
|
61
|
-
->Dict.valuesToArray
|
|
62
|
-
->Array.forEach(entity => {
|
|
63
|
-
let dc = entity->castToEnvioAddresses
|
|
64
|
-
let chainIdStr = dc.chainId->ChainId.toString
|
|
65
|
-
let contracts = switch byChain->Dict.get(chainIdStr) {
|
|
66
|
-
| Some(arr) => arr
|
|
67
|
-
| None =>
|
|
68
|
-
let arr = []
|
|
69
|
-
byChain->Dict.set(chainIdStr, arr)
|
|
70
|
-
arr
|
|
71
|
-
}
|
|
72
|
-
contracts->Array.push(dc->toIndexingAddress)->ignore
|
|
73
|
-
})
|
|
74
|
-
| None => ()
|
|
75
|
-
}
|
|
76
|
-
byChain
|
|
77
|
-
}
|
|
48
|
+
let renderRows = (rows: array<AddressRows.row>, ~config: Config.t) =>
|
|
49
|
+
rows->AddressRows.render(
|
|
50
|
+
~ecosystem=(config.ecosystem.name :> string),
|
|
51
|
+
~shouldChecksum=!config.lowercaseAddresses,
|
|
52
|
+
)
|
|
78
53
|
|
|
79
54
|
// Rows of a per-chain entity are keyed per (chain, id): the same id exists
|
|
80
55
|
// independently on every chain.
|
|
@@ -125,7 +100,9 @@ let handleLoad = (state: testIndexerState, ~tableName: string, ~filter: EntityFi
|
|
|
125
100
|
|
|
126
101
|
let handleWriteBatch = (
|
|
127
102
|
state: testIndexerState,
|
|
103
|
+
~config: Config.t,
|
|
128
104
|
~updatedEntities: array<Persistence.updatedEntity>,
|
|
105
|
+
~registeredAddresses: array<AddressRows.staged>,
|
|
129
106
|
~checkpointIds: array<bigint>,
|
|
130
107
|
~checkpointChainIds: array<ChainId.t>,
|
|
131
108
|
~checkpointBlockNumbers: array<int>,
|
|
@@ -135,6 +112,22 @@ let handleWriteBatch = (
|
|
|
135
112
|
// checkpointId -> entityName -> entityChange
|
|
136
113
|
let changesByCheckpoint: dict<dict<entityChange>> = Dict.make()
|
|
137
114
|
|
|
115
|
+
// checkpointId -> the addresses that checkpoint registered, rendered for the
|
|
116
|
+
// change log. Rendering is the Rust codec's job, so the rows keep their keys
|
|
117
|
+
// right up to here.
|
|
118
|
+
let addressesByCheckpoint: dict<array<{"address": Address.t, "contract": string}>> = Dict.make()
|
|
119
|
+
let rendered = registeredAddresses->Array.map(({row}) => row)->renderRows(~config)
|
|
120
|
+
registeredAddresses->Array.forEachWithIndex(({row, checkpointId}, idx) => {
|
|
121
|
+
state.addresses->AddressRows.Table.insert(row)
|
|
122
|
+
addressesByCheckpoint->Utils.Dict.push(
|
|
123
|
+
checkpointId->BigInt.toString,
|
|
124
|
+
{
|
|
125
|
+
"address": rendered->Array.getUnsafe(idx),
|
|
126
|
+
"contract": state.contractMapping->ContractMapping.nameOfOrThrow(row.contractId),
|
|
127
|
+
},
|
|
128
|
+
)
|
|
129
|
+
})
|
|
130
|
+
|
|
138
131
|
updatedEntities->Array.forEach(({entityConfig, scope, changes}: Persistence.updatedEntity) => {
|
|
139
132
|
let entityName = entityConfig.name
|
|
140
133
|
// The scope is what makes a per-chain row identifiable, so it's stamped
|
|
@@ -210,43 +203,33 @@ let handleWriteBatch = (
|
|
|
210
203
|
|
|
211
204
|
// Add entity changes for this checkpoint
|
|
212
205
|
let checkpointKey = checkpointId->BigInt.toString
|
|
206
|
+
switch addressesByCheckpoint->Utils.Dict.dangerouslyGetNonOption(checkpointKey) {
|
|
207
|
+
| Some(rendered) =>
|
|
208
|
+
let addressesObj: dict<unknown> = Dict.make()
|
|
209
|
+
addressesObj->Dict.set(
|
|
210
|
+
"sets",
|
|
211
|
+
rendered->(Utils.magic: array<{"address": Address.t, "contract": string}> => unknown),
|
|
212
|
+
)
|
|
213
|
+
change->Dict.set("addresses", addressesObj->(Utils.magic: dict<unknown> => unknown))
|
|
214
|
+
| None => ()
|
|
215
|
+
}
|
|
213
216
|
switch changesByCheckpoint->Dict.get(checkpointKey) {
|
|
214
217
|
| Some(entityChanges) =>
|
|
215
218
|
entityChanges
|
|
216
219
|
->Dict.toArray
|
|
217
220
|
->Array.forEach(((entityName, {sets, deleted})) => {
|
|
218
|
-
|
|
219
|
-
if
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
let dc = entity->Utils.magic->castToEnvioAddresses
|
|
225
|
-
{"address": dc->Config.EnvioAddresses.getAddress, "contract": dc.contractName}
|
|
226
|
-
})
|
|
227
|
-
entityObj->Dict.set(
|
|
228
|
-
"sets",
|
|
229
|
-
simplifiedSets->(
|
|
230
|
-
Utils.magic: array<{"address": Address.t, "contract": string}> => unknown
|
|
231
|
-
),
|
|
232
|
-
)
|
|
233
|
-
}
|
|
234
|
-
// Note: deleted is not relevant for addresses since we use address string directly
|
|
235
|
-
change->Dict.set("addresses", entityObj->(Utils.magic: dict<unknown> => unknown))
|
|
236
|
-
} else {
|
|
237
|
-
let entityObj: dict<unknown> = Dict.make()
|
|
238
|
-
if sets->Array.length > 0 {
|
|
239
|
-
entityObj->Dict.set("sets", sets->(Utils.magic: array<unknown> => unknown))
|
|
240
|
-
}
|
|
241
|
-
if deleted->Array.length > 0 {
|
|
242
|
-
entityObj->Dict.set("deleted", deleted->(Utils.magic: array<EntityId.t> => unknown))
|
|
243
|
-
}
|
|
244
|
-
// Match the capitalized entity accessor the generated change types expose.
|
|
245
|
-
change->Dict.set(
|
|
246
|
-
entityName->Utils.String.capitalize,
|
|
247
|
-
entityObj->(Utils.magic: dict<unknown> => unknown),
|
|
248
|
-
)
|
|
221
|
+
let entityObj: dict<unknown> = Dict.make()
|
|
222
|
+
if sets->Array.length > 0 {
|
|
223
|
+
entityObj->Dict.set("sets", sets->(Utils.magic: array<unknown> => unknown))
|
|
224
|
+
}
|
|
225
|
+
if deleted->Array.length > 0 {
|
|
226
|
+
entityObj->Dict.set("deleted", deleted->(Utils.magic: array<EntityId.t> => unknown))
|
|
249
227
|
}
|
|
228
|
+
// Match the capitalized entity accessor the generated change types expose.
|
|
229
|
+
change->Dict.set(
|
|
230
|
+
entityName->Utils.String.capitalize,
|
|
231
|
+
entityObj->(Utils.magic: dict<unknown> => unknown),
|
|
232
|
+
)
|
|
250
233
|
})
|
|
251
234
|
| None => ()
|
|
252
235
|
}
|
|
@@ -260,7 +243,8 @@ let handleWriteBatch = (
|
|
|
260
243
|
let makeInitialState = (
|
|
261
244
|
~config: Config.t,
|
|
262
245
|
~processConfigChains: dict<chainConfig>,
|
|
263
|
-
~
|
|
246
|
+
~addressRowsByChain: dict<AddressRows.seedRows>,
|
|
247
|
+
~contractMapping: ContractMapping.t,
|
|
264
248
|
): Persistence.initialState => {
|
|
265
249
|
let chainKeys = processConfigChains->Dict.keysToArray
|
|
266
250
|
let chains = chainKeys->Array.map(chainIdStr => {
|
|
@@ -271,7 +255,10 @@ let makeInitialState = (
|
|
|
271
255
|
}
|
|
272
256
|
|
|
273
257
|
let processChainConfig = processConfigChains->Dict.getUnsafe(chainIdStr)
|
|
274
|
-
let
|
|
258
|
+
let addressRows =
|
|
259
|
+
addressRowsByChain
|
|
260
|
+
->Utils.Dict.dangerouslyGetNonOption(chainIdStr)
|
|
261
|
+
->Option.getOr(AddressRows.emptySeedRows())
|
|
275
262
|
{
|
|
276
263
|
Persistence.id: chain,
|
|
277
264
|
startBlock: processChainConfig.startBlock,
|
|
@@ -282,17 +269,18 @@ let makeInitialState = (
|
|
|
282
269
|
numEventsProcessed: 0.,
|
|
283
270
|
firstEventBlockNumber: None,
|
|
284
271
|
timestampCaughtUpToHeadOrEndblock: None,
|
|
285
|
-
|
|
272
|
+
addressRows,
|
|
286
273
|
}
|
|
287
274
|
})
|
|
288
275
|
|
|
289
276
|
{
|
|
290
277
|
cleanRun: true,
|
|
278
|
+
contractMapping,
|
|
279
|
+
envioInfo: Some(JSON.Encode.object(Dict.make())),
|
|
291
280
|
cache: Dict.make(),
|
|
292
281
|
chains,
|
|
293
282
|
checkpointId: InternalTable.Checkpoints.initialCheckpointId,
|
|
294
283
|
reorgCheckpoints: [],
|
|
295
|
-
envioInfo: Some(Config.getPublicConfigJson()->Config.stripSensitiveData),
|
|
296
284
|
}
|
|
297
285
|
}
|
|
298
286
|
|
|
@@ -591,7 +579,13 @@ let makeInMemoryStorage = (~state: testIndexerState): Persistence.storage => {
|
|
|
591
579
|
// The runner injects the config-derived initial state by setting
|
|
592
580
|
// `persistence.storageStatus = Ready(...)` directly, bypassing `Persistence.init`,
|
|
593
581
|
// so neither of these is reached.
|
|
594
|
-
initialize: async (
|
|
582
|
+
initialize: async (
|
|
583
|
+
~chainConfigs as _=?,
|
|
584
|
+
~entities as _=?,
|
|
585
|
+
~enums as _=?,
|
|
586
|
+
~contractMapping as _,
|
|
587
|
+
~envioInfo as _,
|
|
588
|
+
) =>
|
|
595
589
|
JsError.throwWithMessage(
|
|
596
590
|
"TestIndexer: initialize should not be called; the initial state is derived from config.",
|
|
597
591
|
),
|
|
@@ -611,15 +605,18 @@ let makeInMemoryStorage = (~state: testIndexerState): Persistence.storage => {
|
|
|
611
605
|
~batch,
|
|
612
606
|
~rollback as _,
|
|
613
607
|
~isInReorgThreshold as _,
|
|
614
|
-
~config
|
|
608
|
+
~config,
|
|
615
609
|
~allEntities as _,
|
|
616
610
|
~updatedEffectsCache as _,
|
|
617
611
|
~updatedEntities,
|
|
612
|
+
~registeredAddresses,
|
|
618
613
|
~chainMetaData as _,
|
|
619
614
|
~onWrite as _,
|
|
620
615
|
) =>
|
|
621
616
|
state->handleWriteBatch(
|
|
617
|
+
~config,
|
|
622
618
|
~updatedEntities,
|
|
619
|
+
~registeredAddresses,
|
|
623
620
|
~checkpointIds=batch.checkpointIds,
|
|
624
621
|
~checkpointChainIds=batch.checkpointChainIds,
|
|
625
622
|
~checkpointBlockNumbers=batch.checkpointBlockNumbers,
|
|
@@ -688,7 +685,7 @@ let getRegistrations = (~config) =>
|
|
|
688
685
|
|
|
689
686
|
let createTestIndexer = (): t<'processConfig> => {
|
|
690
687
|
let config = Config.load()
|
|
691
|
-
let allEntities = config.
|
|
688
|
+
let allEntities = config.userEntities
|
|
692
689
|
let entities = Dict.make()
|
|
693
690
|
let entityConfigs = Dict.make()
|
|
694
691
|
allEntities->Array.forEach(entityConfig => {
|
|
@@ -696,32 +693,19 @@ let createTestIndexer = (): t<'processConfig> => {
|
|
|
696
693
|
entityConfigs->Dict.set(entityConfig.name, entityConfig)
|
|
697
694
|
})
|
|
698
695
|
|
|
699
|
-
|
|
700
|
-
let
|
|
701
|
-
config.
|
|
702
|
-
|
|
703
|
-
->
|
|
704
|
-
chainConfig.contracts->Array.forEach(contract => {
|
|
705
|
-
contract.addresses->Array.forEach(
|
|
706
|
-
address => {
|
|
707
|
-
let entity: InternalTable.EnvioAddresses.t = {
|
|
708
|
-
id: Config.EnvioAddresses.makeId(~chainId=chainConfig.id, ~address),
|
|
709
|
-
chainId: chainConfig.id,
|
|
710
|
-
contractName: contract.name,
|
|
711
|
-
registrationBlock: -1,
|
|
712
|
-
registrationLogIndex: -1,
|
|
713
|
-
}
|
|
714
|
-
envioAddressesDict->Dict.set(entity.id, entity->Config.EnvioAddresses.castToInternal)
|
|
715
|
-
},
|
|
716
|
-
)
|
|
717
|
-
})
|
|
718
|
-
})
|
|
696
|
+
let chainConfigs = config.chainMap->ChainMap.values
|
|
697
|
+
let contractMapping = config.contractMapping
|
|
698
|
+
let ecosystem = config.ecosystem.name
|
|
699
|
+
let addresses = AddressRows.Table.make()
|
|
700
|
+
addresses->ChainState.seedConfigAddresses(~chainConfigs, ~ecosystem, ~contractMapping)
|
|
719
701
|
|
|
720
702
|
let state = {
|
|
721
703
|
processInProgress: false,
|
|
722
704
|
progressBlockByChain: Dict.make(),
|
|
723
705
|
entities,
|
|
724
706
|
entityConfigs,
|
|
707
|
+
addresses,
|
|
708
|
+
contractMapping,
|
|
725
709
|
processChanges: [],
|
|
726
710
|
}
|
|
727
711
|
|
|
@@ -744,19 +728,16 @@ let createTestIndexer = (): t<'processConfig> => {
|
|
|
744
728
|
// Build entity operations for each user entity
|
|
745
729
|
let entityOpsDict: dict<entityOperations> = Dict.make()
|
|
746
730
|
allEntities->Array.forEach(entityConfig => {
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
entityConfig
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
},
|
|
758
|
-
)
|
|
759
|
-
}
|
|
731
|
+
entityOpsDict->Dict.set(
|
|
732
|
+
entityConfig.name,
|
|
733
|
+
{
|
|
734
|
+
get: makeEntityGet(~state, ~entityConfig),
|
|
735
|
+
getAll: makeEntityGetAll(~state, ~entityConfig),
|
|
736
|
+
getWhere: makeEntityGetWhere(~state, ~entityConfig),
|
|
737
|
+
getOrThrow: makeEntityGetOrThrow(~state, ~entityConfig),
|
|
738
|
+
set: makeEntitySet(~state, ~entityConfig),
|
|
739
|
+
},
|
|
740
|
+
)
|
|
760
741
|
})
|
|
761
742
|
|
|
762
743
|
// Build chain info from config (similar to Main.getGlobalIndexer but static)
|
|
@@ -799,10 +780,11 @@ let createTestIndexer = (): t<'processConfig> => {
|
|
|
799
780
|
`Cannot access ${contract.name}.addresses while indexer.process() is running. ` ++ "Wait for process() to complete before reading contract addresses.",
|
|
800
781
|
)
|
|
801
782
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
->
|
|
805
|
-
->Array.
|
|
783
|
+
let contractId = state.contractMapping->ContractMapping.idOfOrThrow(contract.name)
|
|
784
|
+
state.addresses
|
|
785
|
+
->AddressRows.Table.rows
|
|
786
|
+
->Array.filter(row => row.chainId === chainConfig.id && row.contractId === contractId)
|
|
787
|
+
->renderRows(~config)
|
|
806
788
|
},
|
|
807
789
|
},
|
|
808
790
|
)
|
|
@@ -899,11 +881,11 @@ let createTestIndexer = (): t<'processConfig> => {
|
|
|
899
881
|
// by earlier ones.
|
|
900
882
|
let chains: dict<chainConfig> = Dict.make()
|
|
901
883
|
chains->Dict.set(chainIdStr, processChainConfig)
|
|
902
|
-
let indexingAddressesByChain = getIndexingAddressesByChain(state)
|
|
903
884
|
let initialState = makeInitialState(
|
|
904
885
|
~config,
|
|
905
886
|
~processConfigChains=chains,
|
|
906
|
-
~
|
|
887
|
+
~addressRowsByChain=addressRowsByChain(state),
|
|
888
|
+
~contractMapping=state.contractMapping,
|
|
907
889
|
)
|
|
908
890
|
|
|
909
891
|
// No endBlock means auto-exit mode: process one block checkpoint at a
|
package/src/TestIndexer.res.mjs
CHANGED
|
@@ -9,13 +9,14 @@ import * as Logging from "./Logging.res.mjs";
|
|
|
9
9
|
import * as ChainMap from "./ChainMap.res.mjs";
|
|
10
10
|
import * as EntityId from "./EntityId.res.mjs";
|
|
11
11
|
import * as Internal from "./Internal.res.mjs";
|
|
12
|
+
import * as ChainState from "./ChainState.res.mjs";
|
|
12
13
|
import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
|
|
14
|
+
import * as AddressRows from "./AddressRows.res.mjs";
|
|
13
15
|
import * as IndexerLoop from "./IndexerLoop.res.mjs";
|
|
14
16
|
import * as Persistence from "./Persistence.res.mjs";
|
|
15
17
|
import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
|
|
16
18
|
import * as EntityFilter from "./db/EntityFilter.res.mjs";
|
|
17
19
|
import * as IndexerState from "./IndexerState.res.mjs";
|
|
18
|
-
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
19
20
|
import * as ErrorHandling from "./ErrorHandling.res.mjs";
|
|
20
21
|
import * as HandlerLoader from "./HandlerLoader.res.mjs";
|
|
21
22
|
import * as InternalTable from "./db/InternalTable.res.mjs";
|
|
@@ -24,37 +25,17 @@ import * as SimulateItems from "./SimulateItems.res.mjs";
|
|
|
24
25
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
25
26
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
26
27
|
import * as Stdlib_Promise from "@rescript/runtime/lib/es6/Stdlib_Promise.js";
|
|
28
|
+
import * as ContractMapping from "./ContractMapping.res.mjs";
|
|
27
29
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
28
30
|
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
29
31
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
30
32
|
|
|
31
|
-
function
|
|
32
|
-
return
|
|
33
|
-
address: Config.EnvioAddresses.getAddress(dc),
|
|
34
|
-
contractName: dc.contract_name,
|
|
35
|
-
registrationBlock: dc.registration_block
|
|
36
|
-
};
|
|
33
|
+
function addressRowsByChain(state) {
|
|
34
|
+
return AddressRows.Table.groupByChain(state.addresses);
|
|
37
35
|
}
|
|
38
36
|
|
|
39
|
-
function
|
|
40
|
-
|
|
41
|
-
let dcDict = state.entities[Config.EnvioAddresses.name];
|
|
42
|
-
if (dcDict !== undefined) {
|
|
43
|
-
Object.values(dcDict).forEach(entity => {
|
|
44
|
-
let chainIdStr = ChainId.toString(entity.chain_id);
|
|
45
|
-
let arr = byChain[chainIdStr];
|
|
46
|
-
let contracts;
|
|
47
|
-
if (arr !== undefined) {
|
|
48
|
-
contracts = arr;
|
|
49
|
-
} else {
|
|
50
|
-
let arr$1 = [];
|
|
51
|
-
byChain[chainIdStr] = arr$1;
|
|
52
|
-
contracts = arr$1;
|
|
53
|
-
}
|
|
54
|
-
contracts.push(toIndexingAddress(entity));
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
return byChain;
|
|
37
|
+
function renderRows(rows, config) {
|
|
38
|
+
return AddressRows.render(rows, config.ecosystem.name, !config.lowercaseAddresses);
|
|
58
39
|
}
|
|
59
40
|
|
|
60
41
|
function rowKey(scope, entityId) {
|
|
@@ -88,8 +69,18 @@ function handleLoad(state, tableName, filter) {
|
|
|
88
69
|
}
|
|
89
70
|
}
|
|
90
71
|
|
|
91
|
-
function handleWriteBatch(state, updatedEntities, checkpointIds, checkpointChainIds, checkpointBlockNumbers, checkpointEventsProcessed) {
|
|
72
|
+
function handleWriteBatch(state, config, updatedEntities, registeredAddresses, checkpointIds, checkpointChainIds, checkpointBlockNumbers, checkpointEventsProcessed) {
|
|
92
73
|
let changesByCheckpoint = {};
|
|
74
|
+
let addressesByCheckpoint = {};
|
|
75
|
+
let rendered = renderRows(registeredAddresses.map(param => param.row), config);
|
|
76
|
+
registeredAddresses.forEach((param, idx) => {
|
|
77
|
+
let row = param.row;
|
|
78
|
+
AddressRows.Table.insert(state.addresses, row);
|
|
79
|
+
Utils.Dict.push(addressesByCheckpoint, param.checkpointId.toString(), {
|
|
80
|
+
address: rendered[idx],
|
|
81
|
+
contract: ContractMapping.nameOfOrThrow(state.contractMapping, row.contractId)
|
|
82
|
+
});
|
|
83
|
+
});
|
|
93
84
|
updatedEntities.forEach(param => {
|
|
94
85
|
let scope = param.scope;
|
|
95
86
|
let entityConfig = param.entityConfig;
|
|
@@ -151,40 +142,33 @@ function handleWriteBatch(state, updatedEntities, checkpointIds, checkpointChain
|
|
|
151
142
|
change["chainId"] = checkpointChainIds[i];
|
|
152
143
|
change["eventsProcessed"] = checkpointEventsProcessed[i];
|
|
153
144
|
let checkpointKey = checkpointId.toString();
|
|
145
|
+
let rendered$1 = addressesByCheckpoint[checkpointKey];
|
|
146
|
+
if (rendered$1 !== undefined) {
|
|
147
|
+
let addressesObj = {};
|
|
148
|
+
addressesObj["sets"] = rendered$1;
|
|
149
|
+
change["addresses"] = addressesObj;
|
|
150
|
+
}
|
|
154
151
|
let entityChanges = changesByCheckpoint[checkpointKey];
|
|
155
152
|
if (entityChanges !== undefined) {
|
|
156
153
|
Object.entries(entityChanges).forEach(param => {
|
|
157
154
|
let match = param[1];
|
|
158
155
|
let deleted = match.deleted;
|
|
159
156
|
let sets = match.sets;
|
|
160
|
-
let
|
|
161
|
-
if (entityName === Config.EnvioAddresses.name) {
|
|
162
|
-
let entityObj = {};
|
|
163
|
-
if (sets.length !== 0) {
|
|
164
|
-
let simplifiedSets = sets.map(entity => ({
|
|
165
|
-
address: Config.EnvioAddresses.getAddress(entity),
|
|
166
|
-
contract: entity.contract_name
|
|
167
|
-
}));
|
|
168
|
-
entityObj["sets"] = simplifiedSets;
|
|
169
|
-
}
|
|
170
|
-
change["addresses"] = entityObj;
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
let entityObj$1 = {};
|
|
157
|
+
let entityObj = {};
|
|
174
158
|
if (sets.length !== 0) {
|
|
175
|
-
entityObj
|
|
159
|
+
entityObj["sets"] = sets;
|
|
176
160
|
}
|
|
177
161
|
if (deleted.length !== 0) {
|
|
178
|
-
entityObj
|
|
162
|
+
entityObj["deleted"] = deleted;
|
|
179
163
|
}
|
|
180
|
-
change[Utils.$$String.capitalize(
|
|
164
|
+
change[Utils.$$String.capitalize(param[0])] = entityObj;
|
|
181
165
|
});
|
|
182
166
|
}
|
|
183
167
|
state.processChanges.push(change);
|
|
184
168
|
}
|
|
185
169
|
}
|
|
186
170
|
|
|
187
|
-
function makeInitialState(config, processConfigChains,
|
|
171
|
+
function makeInitialState(config, processConfigChains, addressRowsByChain, contractMapping) {
|
|
188
172
|
let chainKeys = Object.keys(processConfigChains);
|
|
189
173
|
let chains = chainKeys.map(chainIdStr => {
|
|
190
174
|
let chain = ChainId.normalizeOrThrow(chainIdStr);
|
|
@@ -192,7 +176,7 @@ function makeInitialState(config, processConfigChains, indexingAddressesByChain)
|
|
|
192
176
|
Stdlib_JsError.throwWithMessage(`Chain ` + chainIdStr + ` is not configured in config.yaml`);
|
|
193
177
|
}
|
|
194
178
|
let processChainConfig = processConfigChains[chainIdStr];
|
|
195
|
-
let
|
|
179
|
+
let addressRows = Stdlib_Option.getOr(addressRowsByChain[chainIdStr], AddressRows.emptySeedRows());
|
|
196
180
|
return {
|
|
197
181
|
id: chain,
|
|
198
182
|
startBlock: processChainConfig.startBlock,
|
|
@@ -202,17 +186,18 @@ function makeInitialState(config, processConfigChains, indexingAddressesByChain)
|
|
|
202
186
|
numEventsProcessed: 0,
|
|
203
187
|
firstEventBlockNumber: undefined,
|
|
204
188
|
timestampCaughtUpToHeadOrEndblock: undefined,
|
|
205
|
-
|
|
189
|
+
addressRows: addressRows,
|
|
206
190
|
sourceBlockNumber: Stdlib_Option.getOr(processChainConfig.endBlock, 0)
|
|
207
191
|
};
|
|
208
192
|
});
|
|
209
193
|
return {
|
|
210
194
|
cleanRun: true,
|
|
195
|
+
contractMapping: contractMapping,
|
|
196
|
+
envioInfo: {},
|
|
211
197
|
cache: {},
|
|
212
198
|
chains: chains,
|
|
213
199
|
checkpointId: InternalTable.Checkpoints.initialCheckpointId,
|
|
214
|
-
reorgCheckpoints: []
|
|
215
|
-
envioInfo: Config.stripSensitiveData(Config.getPublicConfigJson())
|
|
200
|
+
reorgCheckpoints: []
|
|
216
201
|
};
|
|
217
202
|
}
|
|
218
203
|
|
|
@@ -399,7 +384,7 @@ function makeInMemoryStorage(state) {
|
|
|
399
384
|
return {
|
|
400
385
|
name: "test-inmemory",
|
|
401
386
|
isInitialized: async () => true,
|
|
402
|
-
initialize: async (param, param$1, param$2, param$3) => Stdlib_JsError.throwWithMessage("TestIndexer: initialize should not be called; the initial state is derived from config."),
|
|
387
|
+
initialize: async (param, param$1, param$2, param$3, param$4) => Stdlib_JsError.throwWithMessage("TestIndexer: initialize should not be called; the initial state is derived from config."),
|
|
403
388
|
resumeInitialState: async () => Stdlib_JsError.throwWithMessage("TestIndexer: resumeInitialState should not be called; the initial state is derived from config."),
|
|
404
389
|
loadOrThrow: async (filter, table) => handleLoad(state, table.tableName, filter),
|
|
405
390
|
ensureQueryIndexes: async (param, param$1) => {},
|
|
@@ -413,7 +398,7 @@ function makeInMemoryStorage(state) {
|
|
|
413
398
|
getRollbackTargetCheckpoint: async (param, param$1) => Stdlib_JsError.throwWithMessage("TestIndexer: Rollback is not supported. The runner forces rollbackOnReorg off, so this should be unreachable."),
|
|
414
399
|
getRollbackProgressDiff: async param => Stdlib_JsError.throwWithMessage("TestIndexer: Rollback is not supported. The runner forces rollbackOnReorg off, so this should be unreachable."),
|
|
415
400
|
getRollbackData: async (param, param$1) => Stdlib_JsError.throwWithMessage("TestIndexer: Rollback is not supported. The runner forces rollbackOnReorg off, so this should be unreachable."),
|
|
416
|
-
writeBatch: async (batch, param, param$1, param$2, param$3,
|
|
401
|
+
writeBatch: async (batch, param, param$1, config, param$2, param$3, updatedEntities, registeredAddresses, param$4, param$5) => handleWriteBatch(state, config, updatedEntities, registeredAddresses, batch.checkpointIds, batch.checkpointChainIds, batch.checkpointBlockNumbers, batch.checkpointEventsProcessed),
|
|
417
402
|
close: async () => {}
|
|
418
403
|
};
|
|
419
404
|
}
|
|
@@ -446,36 +431,25 @@ function getRegistrations(config) {
|
|
|
446
431
|
|
|
447
432
|
function createTestIndexer() {
|
|
448
433
|
let config = Config.load();
|
|
449
|
-
let allEntities = config.
|
|
434
|
+
let allEntities = config.userEntities;
|
|
450
435
|
let entities = {};
|
|
451
436
|
let entityConfigs = {};
|
|
452
437
|
allEntities.forEach(entityConfig => {
|
|
453
438
|
entities[entityConfig.name] = {};
|
|
454
439
|
entityConfigs[entityConfig.name] = entityConfig;
|
|
455
440
|
});
|
|
456
|
-
let
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
let entity_chain_id = chainConfig.id;
|
|
462
|
-
let entity_contract_name = contract.name;
|
|
463
|
-
let entity = {
|
|
464
|
-
id: entity_id,
|
|
465
|
-
chain_id: entity_chain_id,
|
|
466
|
-
registration_block: -1,
|
|
467
|
-
registration_log_index: -1,
|
|
468
|
-
contract_name: entity_contract_name
|
|
469
|
-
};
|
|
470
|
-
envioAddressesDict[entity_id] = entity;
|
|
471
|
-
});
|
|
472
|
-
});
|
|
473
|
-
});
|
|
441
|
+
let chainConfigs = ChainMap.values(config.chainMap);
|
|
442
|
+
let contractMapping = config.contractMapping;
|
|
443
|
+
let ecosystem = config.ecosystem.name;
|
|
444
|
+
let addresses = AddressRows.Table.make();
|
|
445
|
+
ChainState.seedConfigAddresses(addresses, chainConfigs, ecosystem, contractMapping);
|
|
474
446
|
let state = {
|
|
475
447
|
processInProgress: false,
|
|
476
448
|
progressBlockByChain: {},
|
|
477
449
|
entities: entities,
|
|
478
450
|
entityConfigs: entityConfigs,
|
|
451
|
+
addresses: addresses,
|
|
452
|
+
contractMapping: contractMapping,
|
|
479
453
|
processChanges: []
|
|
480
454
|
};
|
|
481
455
|
let storage = makeInMemoryStorage(state);
|
|
@@ -487,16 +461,13 @@ function createTestIndexer() {
|
|
|
487
461
|
}
|
|
488
462
|
let entityOpsDict = {};
|
|
489
463
|
allEntities.forEach(entityConfig => {
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
};
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
464
|
+
entityOpsDict[entityConfig.name] = {
|
|
465
|
+
get: makeEntityGet(state, entityConfig),
|
|
466
|
+
getAll: makeEntityGetAll(state, entityConfig),
|
|
467
|
+
getWhere: makeEntityGetWhere(state, entityConfig),
|
|
468
|
+
getOrThrow: makeEntityGetOrThrow(state, entityConfig),
|
|
469
|
+
set: makeEntitySet(state, entityConfig)
|
|
470
|
+
};
|
|
500
471
|
});
|
|
501
472
|
let chainIds = [];
|
|
502
473
|
let chains = Object.create(null);
|
|
@@ -534,11 +505,14 @@ function createTestIndexer() {
|
|
|
534
505
|
if (state.processInProgress) {
|
|
535
506
|
Stdlib_JsError.throwWithMessage(`Cannot access ` + contract.name + `.addresses while indexer.process() is running. ` + "Wait for process() to complete before reading contract addresses.");
|
|
536
507
|
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
508
|
+
let contractId = ContractMapping.idOfOrThrow(state.contractMapping, contract.name, undefined);
|
|
509
|
+
return renderRows(AddressRows.Table.rows(state.addresses).filter(row => {
|
|
510
|
+
if (row.chainId === chainConfig.id) {
|
|
511
|
+
return row.contractId === contractId;
|
|
512
|
+
} else {
|
|
513
|
+
return false;
|
|
540
514
|
}
|
|
541
|
-
});
|
|
515
|
+
}), config);
|
|
542
516
|
}
|
|
543
517
|
});
|
|
544
518
|
Object.defineProperty(chainObj, contract.name, {
|
|
@@ -608,8 +582,7 @@ function createTestIndexer() {
|
|
|
608
582
|
let chainIdStr = param[0];
|
|
609
583
|
let chains = {};
|
|
610
584
|
chains[chainIdStr] = processChainConfig;
|
|
611
|
-
let
|
|
612
|
-
let initialState = makeInitialState(config, chains, indexingAddressesByChain);
|
|
585
|
+
let initialState = makeInitialState(config, chains, AddressRows.Table.groupByChain(state.addresses), state.contractMapping);
|
|
613
586
|
let exitAfterFirstEventBlock = Stdlib_Option.isNone(processChainConfig.endBlock);
|
|
614
587
|
let resolvedChainDict = {};
|
|
615
588
|
resolvedChainDict["startBlock"] = processChainConfig.startBlock;
|
|
@@ -696,8 +669,8 @@ function createTestIndexer() {
|
|
|
696
669
|
}
|
|
697
670
|
|
|
698
671
|
export {
|
|
699
|
-
|
|
700
|
-
|
|
672
|
+
addressRowsByChain,
|
|
673
|
+
renderRows,
|
|
701
674
|
rowKey,
|
|
702
675
|
readChainId,
|
|
703
676
|
handleLoad,
|
package/src/Utils.res
CHANGED
|
@@ -199,6 +199,13 @@ module Dict = {
|
|
|
199
199
|
}
|
|
200
200
|
`)
|
|
201
201
|
|
|
202
|
+
let clearInPlace: dict<'a> => unit = %raw(`(dict) => {
|
|
203
|
+
for (const key in dict) {
|
|
204
|
+
delete dict[key];
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
`)
|
|
208
|
+
|
|
202
209
|
let unsafeDeleteUndefinedFieldsInPlace: 'a => unit = %raw(`(dict) => {
|
|
203
210
|
for (var key in dict) {
|
|
204
211
|
if (dict[key] === undefined) {
|
package/src/Utils.res.mjs
CHANGED
|
@@ -149,6 +149,12 @@ let deleteInPlace = ((dict, key) => {
|
|
|
149
149
|
delete dict[key];
|
|
150
150
|
});
|
|
151
151
|
|
|
152
|
+
let clearInPlace = ((dict) => {
|
|
153
|
+
for (const key in dict) {
|
|
154
|
+
delete dict[key];
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
152
158
|
let unsafeDeleteUndefinedFieldsInPlace = ((dict) => {
|
|
153
159
|
for (var key in dict) {
|
|
154
160
|
if (dict[key] === undefined) {
|
|
@@ -175,6 +181,7 @@ let Dict = {
|
|
|
175
181
|
size: size,
|
|
176
182
|
isEmpty: isEmpty,
|
|
177
183
|
deleteInPlace: deleteInPlace,
|
|
184
|
+
clearInPlace: clearInPlace,
|
|
178
185
|
unsafeDeleteUndefinedFieldsInPlace: unsafeDeleteUndefinedFieldsInPlace,
|
|
179
186
|
updateImmutable: updateImmutable,
|
|
180
187
|
shallowCopy: shallowCopy
|
|
@@ -249,7 +256,7 @@ function mergeSorted(f, xs, ys) {
|
|
|
249
256
|
return result;
|
|
250
257
|
}
|
|
251
258
|
|
|
252
|
-
let clearInPlace = ((arr) => {
|
|
259
|
+
let clearInPlace$1 = ((arr) => {
|
|
253
260
|
arr.length = 0
|
|
254
261
|
});
|
|
255
262
|
|
|
@@ -387,7 +394,7 @@ let $$Array$1 = {
|
|
|
387
394
|
unzip: Stdlib_Array.unzip,
|
|
388
395
|
immutableEmpty: immutableEmpty,
|
|
389
396
|
mergeSorted: mergeSorted,
|
|
390
|
-
clearInPlace: clearInPlace,
|
|
397
|
+
clearInPlace: clearInPlace$1,
|
|
391
398
|
setIndexImmutable: setIndexImmutable,
|
|
392
399
|
transposeResults: transposeResults,
|
|
393
400
|
includes: includes,
|