envio 3.15.0-subgraph → 3.16.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 +40 -34
- package/evm.schema.json +3 -3
- package/fuel.schema.json +2 -2
- package/index.d.ts +3 -3
- package/licenses/README.md +1 -1
- package/package.json +9 -10
- package/src/Batch.res.mjs +5 -5
- package/src/BatchProcessing.res +1 -0
- package/src/BatchProcessing.res.mjs +1 -0
- package/src/Bin.res +0 -7
- package/src/Bin.res.mjs +0 -8
- package/src/ChainFetching.res +17 -456
- package/src/ChainFetching.res.mjs +33 -404
- package/src/ChainState.res +48 -83
- package/src/ChainState.res.mjs +83 -115
- package/src/ChainState.resi +0 -26
- package/src/Clock.res +57 -0
- package/src/Clock.res.mjs +72 -0
- package/src/Config.res +7 -16
- package/src/Config.res.mjs +4 -11
- package/src/ContractRegisterContext.res +6 -3
- package/src/ContractRegisterContext.res.mjs +2 -4
- package/src/Core.res +5 -136
- package/src/Core.res.mjs +1 -90
- package/src/CrossChainState.res +2 -8
- package/src/CrossChainState.res.mjs +3 -3
- package/src/Ecosystem.res +4 -7
- package/src/Ecosystem.res.mjs +8 -8
- package/src/EffectState.res +10 -2
- package/src/EffectState.res.mjs +8 -4
- package/src/EffectState.resi +3 -1
- package/src/EntityId.res +2 -7
- package/src/EntityId.res.mjs +1 -8
- package/src/EntityTables.res +4 -1
- package/src/EntityTables.res.mjs +1 -1
- package/src/Env.res +0 -16
- package/src/Env.res.mjs +0 -11
- package/src/EventProcessing.res +1 -38
- package/src/EventProcessing.res.mjs +1 -28
- package/src/FetchState.res +160 -319
- package/src/FetchState.res.mjs +182 -292
- package/src/FinalizeBackfill.res +2 -4
- package/src/FinalizeBackfill.res.mjs +3 -4
- package/src/HandlerLoader.res +15 -39
- package/src/HandlerLoader.res.mjs +8 -27
- package/src/HandlerRegister.res +0 -4
- package/src/HandlerRegister.res.mjs +2 -5
- package/src/HandlerRegister.resi +0 -2
- package/src/InMemoryTable.res +17 -16
- package/src/InMemoryTable.res.mjs +14 -15
- package/src/IndexerState.res +28 -4
- package/src/IndexerState.res.mjs +19 -6
- package/src/IndexerState.resi +4 -0
- package/src/Internal.res +0 -110
- package/src/Internal.res.mjs +1 -115
- package/src/LoadLayer.res +21 -47
- package/src/LoadLayer.res.mjs +47 -72
- package/src/LoadLayer.resi +0 -26
- package/src/Main.res +1 -14
- package/src/Main.res.mjs +3 -4
- package/src/Persistence.res +3 -23
- package/src/Persistence.res.mjs +3 -3
- package/src/Rollback.res +0 -1
- package/src/Rollback.res.mjs +1 -1
- package/src/RunScope.res +0 -3
- package/src/SafeCheckpointTracking.res +4 -4
- package/src/SafeCheckpointTracking.res.mjs +1 -1
- package/src/SimulateItems.res +26 -42
- package/src/SimulateItems.res.mjs +16 -40
- package/src/StagedRows.res +106 -0
- package/src/StagedRows.res.mjs +102 -0
- package/src/Staging.res +32 -14
- package/src/Staging.res.mjs +17 -20
- package/src/Storage.res +277 -998
- package/src/Storage.res.mjs +216 -731
- package/src/Supervisor.res +75 -56
- package/src/Supervisor.res.mjs +55 -26
- package/src/TestIndexer.res +22 -27
- package/src/TestIndexer.res.mjs +20 -17
- package/src/Throttler.res +15 -8
- package/src/Throttler.res.mjs +9 -6
- package/src/Throttler.resi +1 -1
- package/src/UserContext.res +46 -410
- package/src/UserContext.res.mjs +30 -318
- package/src/Utils.res +0 -23
- package/src/Utils.res.mjs +1 -17
- package/src/Writing.res +0 -1
- package/src/Writing.res.mjs +1 -1
- package/src/bindings/ClickHouse.res +0 -322
- package/src/bindings/ClickHouse.res.mjs +0 -338
- package/src/bindings/StorageClient.res +107 -175
- package/src/bindings/StorageClient.res.mjs +19 -8
- package/src/bindings/Vitest.res +0 -26
- package/src/bindings/Vitest.res.mjs +0 -3
- package/src/db/Table.res +24 -150
- package/src/db/Table.res.mjs +38 -272
- package/src/sources/AddressSet.res +0 -2
- package/src/sources/AddressStore.res +0 -3
- package/src/sources/ChainSources.res +2 -0
- package/src/sources/ChainSources.res.mjs +2 -2
- package/src/sources/EvmChain.res +4 -7
- package/src/sources/EvmChain.res.mjs +5 -4
- package/src/sources/EvmHyperSyncSource.res +2 -2
- package/src/sources/EvmHyperSyncSource.res.mjs +1 -1
- package/src/sources/EvmRpcClient.res +13 -3
- package/src/sources/EvmRpcClient.res.mjs +4 -3
- package/src/sources/EvmRpcWs.res +4 -3
- package/src/sources/EvmRpcWs.res.mjs +2 -2
- package/src/sources/HeightFeed.res +31 -10
- package/src/sources/HeightFeed.res.mjs +10 -6
- package/src/sources/HeightStream.res +32 -17
- package/src/sources/HeightStream.res.mjs +10 -10
- package/src/sources/HyperSync.res +1 -2
- package/src/sources/HyperSync.res.mjs +1 -2
- package/src/sources/HyperSyncSSE.res +4 -6
- package/src/sources/HyperSyncSSE.res.mjs +2 -2
- package/src/sources/RpcSource.res +10 -1
- package/src/sources/RpcSource.res.mjs +4 -3
- package/src/sources/Source.res +3 -0
- package/src/sources/SourceManager.res +85 -104
- package/src/sources/SourceManager.res.mjs +18 -37
- package/src/sources/SourceManager.resi +3 -5
- package/src/sources/StartBlockResolver.res +1 -0
- package/src/sources/StartBlockResolver.res.mjs +4 -3
- package/src/sources/SvmHyperSyncSource.res +2 -2
- package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
- package/svm.schema.json +3 -3
- package/src/EffectCacheLookup.res +0 -98
- package/src/EffectCacheLookup.res.mjs +0 -116
- package/src/PgWriting.res +0 -36
- package/src/PgWriting.res.mjs +0 -34
- package/src/PreloadLookahead.res +0 -184
- package/src/PreloadLookahead.res.mjs +0 -197
- package/src/SubgraphLog.res +0 -19
- package/src/SubgraphLog.res.mjs +0 -26
- package/src/SyncWrites.res +0 -101
- package/src/SyncWrites.res.mjs +0 -98
- package/src/db/IndexDefinition.res +0 -47
- package/src/db/IndexDefinition.res.mjs +0 -60
- package/src/sources/CallSource.res +0 -274
- package/src/sources/CallSource.res.mjs +0 -196
- package/src/subgraph/abi-types.ts +0 -84
- package/src/subgraph/aggregations.ts +0 -745
- package/src/subgraph/as-package.ts +0 -143
- package/src/subgraph/assemblyscript-regex.ts +0 -67
- package/src/subgraph/assemblyscript.ts +0 -731
- package/src/subgraph/blocks.ts +0 -398
- package/src/subgraph/calls-source.ts +0 -702
- package/src/subgraph/calls.ts +0 -258
- package/src/subgraph/conformance.ts +0 -106
- package/src/subgraph/errors.ts +0 -85
- package/src/subgraph/graft.ts +0 -73
- package/src/subgraph/graph-cli-worker.mjs +0 -35
- package/src/subgraph/graph-cli.ts +0 -900
- package/src/subgraph/graph-node-decimal.ts +0 -199
- package/src/subgraph/graph-ts-enums.ts +0 -28
- package/src/subgraph/graph-ts-types/VERSION +0 -2
- package/src/subgraph/graph-ts-types/chain/arweave.d.ts +0 -70
- package/src/subgraph/graph-ts-types/chain/cosmos.d.ts +0 -327
- package/src/subgraph/graph-ts-types/chain/ethereum.d.ts +0 -233
- package/src/subgraph/graph-ts-types/chain/near.d.ts +0 -253
- package/src/subgraph/graph-ts-types/chain/starknet.d.ts +0 -32
- package/src/subgraph/graph-ts-types/common/collections.d.ts +0 -136
- package/src/subgraph/graph-ts-types/common/conversion.d.ts +0 -11
- package/src/subgraph/graph-ts-types/common/datasource.d.ts +0 -30
- package/src/subgraph/graph-ts-types/common/eager-offset.d.ts +0 -0
- package/src/subgraph/graph-ts-types/common/json.d.ts +0 -17
- package/src/subgraph/graph-ts-types/common/numbers.d.ts +0 -120
- package/src/subgraph/graph-ts-types/common/value.d.ts +0 -120
- package/src/subgraph/graph-ts-types/common/yaml.d.ts +0 -90
- package/src/subgraph/graph-ts-types/global/global.d.ts +0 -194
- package/src/subgraph/graph-ts-types/helper-functions.d.ts +0 -22
- package/src/subgraph/graph-ts-types/index.d.ts +0 -102
- package/src/subgraph/graph-ts.ts +0 -4280
- package/src/subgraph/hosts.ts +0 -554
- package/src/subgraph/log.ts +0 -28
- package/src/subgraph/receipts.ts +0 -184
- package/src/subgraph/register-slots.ts +0 -93
- package/src/subgraph/rollup.ts +0 -109
- package/src/subgraph/rpc.ts +0 -337
- package/src/subgraph/runtime.ts +0 -2060
- package/src/subgraph/scope.ts +0 -177
- package/src/subgraph/stats.ts +0 -42
- package/src/subgraph/template-instances.ts +0 -66
- package/src/subgraph/toolchain.ts +0 -327
- package/src/subgraph/transient.ts +0 -176
package/src/Persistence.res
CHANGED
|
@@ -117,8 +117,6 @@ type storage = {
|
|
|
117
117
|
// carries a matching row — storage doesn't interpret it.
|
|
118
118
|
initialize: (
|
|
119
119
|
~chainConfigs: array<Config.chain>=?,
|
|
120
|
-
~entities: array<Internal.entityConfig>=?,
|
|
121
|
-
~enums: array<Table.enumConfig<Table.enum>>=?,
|
|
122
120
|
~contractMapping: ContractMapping.t,
|
|
123
121
|
~envioInfo: JSON.t,
|
|
124
122
|
) => promise<initialState>,
|
|
@@ -129,16 +127,11 @@ type storage = {
|
|
|
129
127
|
// Brings an initialized storage a chain it doesn't have yet: its row, its
|
|
130
128
|
// partitions and its config addresses, as `initialize` would have created
|
|
131
129
|
// them. The chains already there are left untouched.
|
|
132
|
-
addChain: (
|
|
133
|
-
~chainConfig: Config.chain,
|
|
134
|
-
~entities: array<Internal.entityConfig>,
|
|
135
|
-
~contractMapping: ContractMapping.t,
|
|
136
|
-
) => promise<unit>,
|
|
130
|
+
addChain: (~chainConfig: Config.chain, ~contractMapping: ContractMapping.t) => promise<unit>,
|
|
137
131
|
// `chainIds` is what this run drives. An isolated run resumes a subset of
|
|
138
132
|
// the stored chains, and ClickHouse's resume trims past each resumed chain's
|
|
139
133
|
// checkpoint, so chains a sibling process is still writing must stay out.
|
|
140
134
|
resumeInitialState: (
|
|
141
|
-
~entities: array<Internal.entityConfig>,
|
|
142
135
|
~chainIds: array<ChainId.t>,
|
|
143
136
|
~contractMapping: ContractMapping.t,
|
|
144
137
|
) => promise<initialState>,
|
|
@@ -159,19 +152,12 @@ type storage = {
|
|
|
159
152
|
// never runs `finalizeBackfill`: an index dropped or invalidated while it was
|
|
160
153
|
// down would otherwise never be rebuilt. Best-effort, and safe to run with
|
|
161
154
|
// indexing live.
|
|
162
|
-
ensureSchemaIndexes: (
|
|
163
|
-
~entities: array<Internal.entityConfig>,
|
|
164
|
-
~chainIds: array<ChainId.t>,
|
|
165
|
-
) => promise<unit>,
|
|
155
|
+
ensureSchemaIndexes: (~chainIds: array<ChainId.t>) => promise<unit>,
|
|
166
156
|
// Creates every index the schema promises for the given chains, then stamps
|
|
167
157
|
// `ready_at` on them. Called once those chains finish backfill. The indexes
|
|
168
158
|
// are committed one at a time so a failure part way through doesn't undo the
|
|
169
159
|
// ones already built; `ready_at` is only written once they all verify.
|
|
170
|
-
finalizeBackfill: (
|
|
171
|
-
~entities: array<Internal.entityConfig>,
|
|
172
|
-
~chainIds: array<ChainId.t>,
|
|
173
|
-
~readyAt: Date.t,
|
|
174
|
-
) => promise<unit>,
|
|
160
|
+
finalizeBackfill: (~chainIds: array<ChainId.t>, ~readyAt: Date.t) => promise<unit>,
|
|
175
161
|
// This is to download cache from the database to .envio/cache
|
|
176
162
|
dumpEffectCache: unit => promise<unit>,
|
|
177
163
|
reset: unit => promise<unit>,
|
|
@@ -190,7 +176,6 @@ type storage = {
|
|
|
190
176
|
getRollbackTargetCheckpoint: (
|
|
191
177
|
~reorgChainId: ChainId.t,
|
|
192
178
|
~lastKnownValidBlockNumber: int,
|
|
193
|
-
~sequence: CheckpointSequence.t,
|
|
194
179
|
) => promise<option<Internal.checkpointId>>,
|
|
195
180
|
// Get rollback progress diff
|
|
196
181
|
getRollbackProgressDiff: (
|
|
@@ -214,7 +199,6 @@ type storage = {
|
|
|
214
199
|
~batch: Batch.t,
|
|
215
200
|
~rollback: option<rollback>,
|
|
216
201
|
~config: Config.t,
|
|
217
|
-
~allEntities: array<Internal.entityConfig>,
|
|
218
202
|
~updatedEffectsCache: array<updatedEffectCache>,
|
|
219
203
|
~updatedEntities: array<updatedEntity>,
|
|
220
204
|
// Addresses this batch registered, with the checkpoint that covers them.
|
|
@@ -339,8 +323,6 @@ let init = {
|
|
|
339
323
|
throw(Refused(Config.setUpMeanwhileMessage))
|
|
340
324
|
}
|
|
341
325
|
let initialState = await persistence.storage.initialize(
|
|
342
|
-
~entities=persistence.allEntities,
|
|
343
|
-
~enums=persistence.allEnums,
|
|
344
326
|
~chainConfigs,
|
|
345
327
|
~contractMapping,
|
|
346
328
|
~envioInfo,
|
|
@@ -397,13 +379,11 @@ let init = {
|
|
|
397
379
|
)->Array.getUnsafe(0)
|
|
398
380
|
await persistence.storage.addChain(
|
|
399
381
|
~chainConfig,
|
|
400
|
-
~entities=persistence.allEntities,
|
|
401
382
|
~contractMapping=stored.contractMapping,
|
|
402
383
|
)
|
|
403
384
|
}
|
|
404
385
|
if resume {
|
|
405
386
|
let initialState = await persistence.storage.resumeInitialState(
|
|
406
|
-
~entities=persistence.allEntities,
|
|
407
387
|
~chainIds=chainConfigs->Array.map(chain => chain.id),
|
|
408
388
|
~contractMapping=stored.contractMapping,
|
|
409
389
|
)
|
package/src/Persistence.res.mjs
CHANGED
|
@@ -94,7 +94,7 @@ async function init(persistence, logger, chainConfigs, contractMapping, envioInf
|
|
|
94
94
|
Error: new Error()
|
|
95
95
|
};
|
|
96
96
|
}
|
|
97
|
-
let initialState = await persistence.storage.initialize(chainConfigs$1,
|
|
97
|
+
let initialState = await persistence.storage.initialize(chainConfigs$1, contractMapping, envioInfo);
|
|
98
98
|
Logger.info(logger, `The indexer storage is ready. Starting indexing!`, undefined);
|
|
99
99
|
persistence.storageStatus = {
|
|
100
100
|
TAG: "Ready",
|
|
@@ -136,11 +136,11 @@ async function init(persistence, logger, chainConfigs, contractMapping, envioInf
|
|
|
136
136
|
chainId: chainConfig.id
|
|
137
137
|
});
|
|
138
138
|
let chainConfig$1 = (await StartBlockResolver.resolveAllOrThrow([chainConfig], logger, lowercaseAddresses, startBlockRetry, sourceTiming))[0];
|
|
139
|
-
await persistence.storage.addChain(chainConfig$1,
|
|
139
|
+
await persistence.storage.addChain(chainConfig$1, stored.contractMapping);
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
if (resume) {
|
|
143
|
-
let initialState$1 = await persistence.storage.resumeInitialState(
|
|
143
|
+
let initialState$1 = await persistence.storage.resumeInitialState(chainConfigs.map(chain => chain.id), stored.contractMapping);
|
|
144
144
|
persistence.storageStatus = {
|
|
145
145
|
TAG: "Ready",
|
|
146
146
|
_0: initialState$1
|
package/src/Rollback.res
CHANGED
|
@@ -130,7 +130,6 @@ and executeRollback = async (
|
|
|
130
130
|
switch await (state->IndexerState.persistence).storage.getRollbackTargetCheckpoint(
|
|
131
131
|
~reorgChainId=reorgChain,
|
|
132
132
|
~lastKnownValidBlockNumber=rollbackTargetBlockNumber,
|
|
133
|
-
~sequence=(state->IndexerState.config).checkpointSequence,
|
|
134
133
|
) {
|
|
135
134
|
| Some(checkpointId) => checkpointId
|
|
136
135
|
| None => 0n
|
package/src/Rollback.res.mjs
CHANGED
|
@@ -42,7 +42,7 @@ async function executeRollback(state, reorgChain, rollbackTargetBlockNumber, sch
|
|
|
42
42
|
Logger.info(logger, "Started rollback on reorg", undefined);
|
|
43
43
|
ChainState.setRollbackTargetBlock(IndexerState.getChainState(state, reorgChain), rollbackTargetBlockNumber);
|
|
44
44
|
await Writing.flush(state);
|
|
45
|
-
let checkpointId = await IndexerState.persistence(state).storage.getRollbackTargetCheckpoint(reorgChain, rollbackTargetBlockNumber
|
|
45
|
+
let checkpointId = await IndexerState.persistence(state).storage.getRollbackTargetCheckpoint(reorgChain, rollbackTargetBlockNumber);
|
|
46
46
|
let rollbackTargetCheckpointId = checkpointId !== undefined ? checkpointId : 0n;
|
|
47
47
|
let config = IndexerState.config(state);
|
|
48
48
|
let next = RollbackFloors.make(config.checkpointSequence, ChainMap.keys(config.chainMap), reorgChain, rollbackTargetCheckpointId, rollbackTargetBlockNumber);
|
package/src/RunScope.res
CHANGED
|
@@ -22,9 +22,6 @@ type contractRegisterRun = {
|
|
|
22
22
|
chainLogger: Logger.t,
|
|
23
23
|
ecosystem: Ecosystem.t,
|
|
24
24
|
registrations: array<AddressStore.registration>,
|
|
25
|
-
// Subgraph mode: the creation round the addresses it adds belong to (see
|
|
26
|
-
// `AddressStore.registration.creationRound`).
|
|
27
|
-
creationRound?: int,
|
|
28
25
|
}
|
|
29
26
|
|
|
30
27
|
// An effect call is shared by the runs that asked for it, so it is told by the
|
|
@@ -16,9 +16,7 @@ let make = (
|
|
|
16
16
|
) => {
|
|
17
17
|
if maxReorgDepth > 0 && shouldRollbackOnReorg {
|
|
18
18
|
let checkpointIds = Utils.Array.jsArrayCreate(chainReorgCheckpoints->Array.length)
|
|
19
|
-
let checkpointBlockNumbers = Utils.Array.jsArrayCreate(
|
|
20
|
-
chainReorgCheckpoints->Array.length,
|
|
21
|
-
)
|
|
19
|
+
let checkpointBlockNumbers = Utils.Array.jsArrayCreate(chainReorgCheckpoints->Array.length)
|
|
22
20
|
chainReorgCheckpoints->Array.forEachWithIndex((checkpoint, idx) => {
|
|
23
21
|
checkpointIds->Array.setUnsafe(idx, checkpoint.checkpointId)
|
|
24
22
|
checkpointBlockNumbers->Array.setUnsafe(idx, checkpoint.blockNumber)
|
|
@@ -36,7 +34,9 @@ let make = (
|
|
|
36
34
|
let getSafeCheckpointId = (safeCheckpointTracking: t, ~sourceBlockNumber: int): option<
|
|
37
35
|
Internal.checkpointId,
|
|
38
36
|
> => {
|
|
39
|
-
|
|
37
|
+
// The first block reorg detection compares is itself reorgable, so the safe
|
|
38
|
+
// block is the one below it.
|
|
39
|
+
let safeBlockNumber = sourceBlockNumber - safeCheckpointTracking.maxReorgDepth - 1
|
|
40
40
|
|
|
41
41
|
switch safeCheckpointTracking.checkpointIds {
|
|
42
42
|
| [] => None
|
|
@@ -20,7 +20,7 @@ function make(maxReorgDepth, shouldRollbackOnReorg, chainReorgCheckpoints) {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function getSafeCheckpointId(safeCheckpointTracking, sourceBlockNumber) {
|
|
23
|
-
let safeBlockNumber = sourceBlockNumber - safeCheckpointTracking.maxReorgDepth | 0;
|
|
23
|
+
let safeBlockNumber = (sourceBlockNumber - safeCheckpointTracking.maxReorgDepth | 0) - 1 | 0;
|
|
24
24
|
let match = safeCheckpointTracking.checkpointIds;
|
|
25
25
|
if (match.length === 0) {
|
|
26
26
|
return;
|
package/src/SimulateItems.res
CHANGED
|
@@ -638,16 +638,7 @@ let parse = (
|
|
|
638
638
|
// A simulate item must land on a distinct (block, logIndex): event ordering
|
|
639
639
|
// and the dead-input tracker both key on it. Catch explicit duplicates and
|
|
640
640
|
// explicit-vs-auto-increment collisions here, naming both offending indices.
|
|
641
|
-
|
|
642
|
-
// transactions' calls share an index.
|
|
643
|
-
let coordinate = switch Internal.callRankOfEventName(eventConfig.name) {
|
|
644
|
-
| Some(_) =>
|
|
645
|
-
let transactionIndex = (
|
|
646
|
-
transaction->(Utils.magic: Internal.eventTransaction => {"transactionIndex": int})
|
|
647
|
-
)["transactionIndex"]
|
|
648
|
-
`${blockNumber->Int.toString}:tx${transactionIndex->Int.toString}:${logIndex->Int.toString}`
|
|
649
|
-
| None => `${blockNumber->Int.toString}:${logIndex->Int.toString}`
|
|
650
|
-
}
|
|
641
|
+
let coordinate = `${blockNumber->Int.toString}:${logIndex->Int.toString}`
|
|
651
642
|
switch seenCoordinates->Dict.get(coordinate) {
|
|
652
643
|
| Some(firstIndex) =>
|
|
653
644
|
JsError.throwWithMessage(
|
|
@@ -682,38 +673,31 @@ let parse = (
|
|
|
682
673
|
let onEventRegistration = {...reg, index: onEventRegistrationIndex}
|
|
683
674
|
onEventRegistrations->Array.push(onEventRegistration)->ignore
|
|
684
675
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
)->Evm.fromPayload,
|
|
711
|
-
})
|
|
712
|
-
switch Internal.callRankOfEventName(eventConfig.name) {
|
|
713
|
-
| Some(rank) => item->Internal.markItemCall(~rank)
|
|
714
|
-
| None => ()
|
|
715
|
-
}
|
|
716
|
-
items->Array.push(item)->ignore
|
|
676
|
+
items
|
|
677
|
+
->Array.push(
|
|
678
|
+
Internal.Event({
|
|
679
|
+
onEventRegistration,
|
|
680
|
+
chainId,
|
|
681
|
+
blockNumber,
|
|
682
|
+
logIndex,
|
|
683
|
+
// Simulate keeps the transaction inline on the payload, so the store
|
|
684
|
+
// key is unused.
|
|
685
|
+
transactionIndex: 0,
|
|
686
|
+
payload: (
|
|
687
|
+
{
|
|
688
|
+
contractName: eventConfig.contractName,
|
|
689
|
+
eventName: eventConfig.name,
|
|
690
|
+
params,
|
|
691
|
+
chainId,
|
|
692
|
+
srcAddress,
|
|
693
|
+
logIndex,
|
|
694
|
+
transaction,
|
|
695
|
+
block,
|
|
696
|
+
}: Evm.payload
|
|
697
|
+
)->Evm.fromPayload,
|
|
698
|
+
}),
|
|
699
|
+
)
|
|
700
|
+
->ignore
|
|
717
701
|
})
|
|
718
702
|
}
|
|
719
703
|
})
|
|
@@ -460,14 +460,7 @@ function parse(simulateItems, config, chainConfig, onEventRegistrations) {
|
|
|
460
460
|
break;
|
|
461
461
|
}
|
|
462
462
|
currentBlock.contents = blockNumber$1;
|
|
463
|
-
let
|
|
464
|
-
let coordinate;
|
|
465
|
-
if (match$12 !== undefined) {
|
|
466
|
-
let transactionIndex$1 = transaction$1.transactionIndex;
|
|
467
|
-
coordinate = blockNumber$1.toString() + `:tx` + transactionIndex$1.toString() + `:` + logIndex.toString();
|
|
468
|
-
} else {
|
|
469
|
-
coordinate = blockNumber$1.toString() + `:` + logIndex.toString();
|
|
470
|
-
}
|
|
463
|
+
let coordinate = blockNumber$1.toString() + `:` + logIndex.toString();
|
|
471
464
|
let firstIndex = seenCoordinates[coordinate];
|
|
472
465
|
if (firstIndex !== undefined) {
|
|
473
466
|
Stdlib_JsError.throwWithMessage(`simulate: items at index ` + firstIndex.toString() + ` and ` + itemIndex.toString() + ` on chain ` + ChainId.toString(chainId) + ` both resolve to block ` + blockNumber$1.toString() + `, logIndex ` + logIndex.toString() + `. Give each item a distinct logIndex (or omit logIndex so they auto-increment).`);
|
|
@@ -476,9 +469,9 @@ function parse(simulateItems, config, chainConfig, onEventRegistrations) {
|
|
|
476
469
|
}
|
|
477
470
|
let liveRegistrations$1 = liveRegistrationsFor(config, chainId, eventConfig$1);
|
|
478
471
|
if (Utils.$$Array.isEmpty(liveRegistrations$1)) {
|
|
479
|
-
let match$
|
|
472
|
+
let match$12 = ChainMap.values(config.chainMap).length;
|
|
480
473
|
Stdlib_JsError.throwWithMessage(`simulate: no handler runs for event "` + eventName + `" on contract "` + contractName + `"` + (
|
|
481
|
-
match$
|
|
474
|
+
match$12 !== 1 ? ` on chain ` + ChainId.toString(chainId) : ""
|
|
482
475
|
) + `. Register a handler with indexer.onEvent (and check any \`where\` filter isn't excluding this chain) before simulating it.`);
|
|
483
476
|
}
|
|
484
477
|
liveRegistrations$1.forEach(reg => {
|
|
@@ -486,41 +479,24 @@ function parse(simulateItems, config, chainConfig, onEventRegistrations) {
|
|
|
486
479
|
let newrecord = {...reg};
|
|
487
480
|
newrecord.index = onEventRegistrationIndex;
|
|
488
481
|
onEventRegistrations.push(newrecord);
|
|
489
|
-
|
|
490
|
-
let tmp;
|
|
491
|
-
switch (match) {
|
|
492
|
-
case "evm" :
|
|
493
|
-
tmp = transaction$1.transactionIndex;
|
|
494
|
-
break;
|
|
495
|
-
case "fuel" :
|
|
496
|
-
case "svm" :
|
|
497
|
-
tmp = 0;
|
|
498
|
-
break;
|
|
499
|
-
}
|
|
500
|
-
let item_6 = {
|
|
501
|
-
contractName: eventConfig$1.contractName,
|
|
502
|
-
eventName: eventConfig$1.name,
|
|
503
|
-
params: params,
|
|
504
|
-
chainId: chainId,
|
|
505
|
-
srcAddress: srcAddress,
|
|
506
|
-
logIndex: logIndex,
|
|
507
|
-
transaction: Primitive_option.some(transaction$1),
|
|
508
|
-
block: Primitive_option.some(block$2)
|
|
509
|
-
};
|
|
510
|
-
let item = {
|
|
482
|
+
items.push({
|
|
511
483
|
kind: 0,
|
|
512
484
|
onEventRegistration: newrecord,
|
|
513
485
|
chainId: chainId,
|
|
514
486
|
blockNumber: blockNumber$1,
|
|
515
487
|
logIndex: logIndex,
|
|
516
|
-
transactionIndex:
|
|
517
|
-
payload:
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
488
|
+
transactionIndex: 0,
|
|
489
|
+
payload: {
|
|
490
|
+
contractName: eventConfig$1.contractName,
|
|
491
|
+
eventName: eventConfig$1.name,
|
|
492
|
+
params: params,
|
|
493
|
+
chainId: chainId,
|
|
494
|
+
srcAddress: srcAddress,
|
|
495
|
+
logIndex: logIndex,
|
|
496
|
+
transaction: Primitive_option.some(transaction$1),
|
|
497
|
+
block: Primitive_option.some(block$2)
|
|
498
|
+
}
|
|
499
|
+
});
|
|
524
500
|
});
|
|
525
501
|
return;
|
|
526
502
|
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// Values as the addon declares each staged field has to arrive, compiled once
|
|
2
|
+
// per layout and written into a stage.
|
|
3
|
+
|
|
4
|
+
@send external getTime: unknown => float = "getTime"
|
|
5
|
+
@send external toFixed: unknown => string = "toFixed"
|
|
6
|
+
@val @scope("Array") external isArray: unknown => bool = "isArray"
|
|
7
|
+
|
|
8
|
+
// A list element as its JSON: the encoding a scalar of its type would take,
|
|
9
|
+
// except that a boolean stays one and bytes become their values.
|
|
10
|
+
%%private(
|
|
11
|
+
let elementOf = (encoding: Staging.encoding, ~column): (unknown => unknown) =>
|
|
12
|
+
switch encoding {
|
|
13
|
+
| Number =>
|
|
14
|
+
value =>
|
|
15
|
+
value->Staging.toNumber->Staging.finiteOrThrow(~column)->(Utils.magic: float => unknown)
|
|
16
|
+
| Date => value => value->getTime->(Utils.magic: float => unknown)
|
|
17
|
+
| Digits => value => value->Staging.stringOf->(Utils.magic: string => unknown)
|
|
18
|
+
| Decimal => value => value->toFixed->(Utils.magic: string => unknown)
|
|
19
|
+
| Document => value => value->Sql.canonicalDocument->(Utils.magic: string => unknown)
|
|
20
|
+
| Bytes =>
|
|
21
|
+
value =>
|
|
22
|
+
value
|
|
23
|
+
->(Utils.magic: unknown => Array.arrayLike<int>)
|
|
24
|
+
->Array.fromArrayLike
|
|
25
|
+
->(Utils.magic: array<int> => unknown)
|
|
26
|
+
| Bool | Text | List => value => value
|
|
27
|
+
}
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
%%private(
|
|
31
|
+
let rec mapList = (value: unknown, element: unknown => unknown): unknown =>
|
|
32
|
+
if value->isArray {
|
|
33
|
+
value
|
|
34
|
+
->(Utils.magic: unknown => array<unknown>)
|
|
35
|
+
->Array.map(item => item->mapList(element))
|
|
36
|
+
->(Utils.magic: array<unknown> => unknown)
|
|
37
|
+
} else if value === %raw(`undefined`) || value === %raw(`null`) {
|
|
38
|
+
%raw(`null`)
|
|
39
|
+
} else {
|
|
40
|
+
element(value)
|
|
41
|
+
}
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
// What a present value becomes before it is written to its slot.
|
|
45
|
+
%%private(
|
|
46
|
+
let encoderOf = ({name, encoding, element}: Staging.stagedField): (unknown => unknown) =>
|
|
47
|
+
switch encoding {
|
|
48
|
+
| Bool =>
|
|
49
|
+
value => (value->(Utils.magic: unknown => bool) ? 1. : 0.)->(Utils.magic: float => unknown)
|
|
50
|
+
| Date => value => value->getTime->(Utils.magic: float => unknown)
|
|
51
|
+
| Decimal => value => value->toFixed->(Utils.magic: string => unknown)
|
|
52
|
+
| Document => value => value->Sql.canonicalDocument->(Utils.magic: string => unknown)
|
|
53
|
+
| List =>
|
|
54
|
+
let encode = elementOf(element, ~column=name)
|
|
55
|
+
// A document can be a list itself, so a list of them is one level deep.
|
|
56
|
+
let mapList = switch element {
|
|
57
|
+
| Document =>
|
|
58
|
+
(value, encode) =>
|
|
59
|
+
value
|
|
60
|
+
->(Utils.magic: unknown => array<unknown>)
|
|
61
|
+
->Array.map(item => item->Staging.isAbsent ? %raw(`null`) : encode(item))
|
|
62
|
+
->(Utils.magic: array<unknown> => unknown)
|
|
63
|
+
| _ => mapList
|
|
64
|
+
}
|
|
65
|
+
value =>
|
|
66
|
+
value
|
|
67
|
+
->mapList(encode)
|
|
68
|
+
->(Utils.magic: unknown => JSON.t)
|
|
69
|
+
->JSON.stringify
|
|
70
|
+
->Utils.replaceLoneSurrogateEscapes
|
|
71
|
+
->(Utils.magic: string => unknown)
|
|
72
|
+
| Number | Text | Digits | Bytes => value => value
|
|
73
|
+
}
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
// A layout's fields compiled once: the slot each takes and how a value of it
|
|
77
|
+
// is written there.
|
|
78
|
+
type writer = {field: Staging.stagedField, encode: unknown => unknown}
|
|
79
|
+
|
|
80
|
+
let writersOf = (fields: array<Staging.stagedField>) =>
|
|
81
|
+
fields->Array.map(field => {field, encode: encoderOf(field)})
|
|
82
|
+
|
|
83
|
+
let columnsOf = (writers: array<writer>): array<Staging.column> =>
|
|
84
|
+
writers->Array.map(({field}) => {
|
|
85
|
+
Staging.name: field.name,
|
|
86
|
+
kind: field.encoding->Staging.kindOf,
|
|
87
|
+
isNullable: field.isNullable,
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
// JSON `null` is a document of its own, which a column that can't be NULL
|
|
91
|
+
// stores as one. Left out, the value is no document and is refused like any
|
|
92
|
+
// other.
|
|
93
|
+
let writeField = (stage, ~writers: array<writer>, ~column, ~row, value: unknown) => {
|
|
94
|
+
let {field, encode} = writers->Array.getUnsafe(column)
|
|
95
|
+
if value->Staging.isAbsent {
|
|
96
|
+
stage->Staging.writeValue(
|
|
97
|
+
~column,
|
|
98
|
+
~row,
|
|
99
|
+
field.encoding === Staging.Document && !field.isNullable && value === %raw(`null`)
|
|
100
|
+
? "null"->(Utils.magic: string => unknown)
|
|
101
|
+
: value,
|
|
102
|
+
)
|
|
103
|
+
} else {
|
|
104
|
+
stage->Staging.writeValue(~column, ~row, encode(value))
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Sql from "./db/Sql.res.mjs";
|
|
4
|
+
import * as Utils from "./Utils.res.mjs";
|
|
5
|
+
import * as Staging from "./Staging.res.mjs";
|
|
6
|
+
|
|
7
|
+
function elementOf(encoding, column) {
|
|
8
|
+
switch (encoding) {
|
|
9
|
+
case "Number" :
|
|
10
|
+
return value => Staging.finiteOrThrow(Number(value), column);
|
|
11
|
+
case "Date" :
|
|
12
|
+
return value => value.getTime();
|
|
13
|
+
case "Digits" :
|
|
14
|
+
return value => String(value);
|
|
15
|
+
case "Decimal" :
|
|
16
|
+
return value => value.toFixed();
|
|
17
|
+
case "Document" :
|
|
18
|
+
return Sql.canonicalDocument;
|
|
19
|
+
case "Bytes" :
|
|
20
|
+
return value => Array.from(value);
|
|
21
|
+
default:
|
|
22
|
+
return value => value;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function mapList(value, element) {
|
|
27
|
+
if (Array.isArray(value)) {
|
|
28
|
+
return value.map(item => mapList(item, element));
|
|
29
|
+
} else if (value === undefined || value === null) {
|
|
30
|
+
return null;
|
|
31
|
+
} else {
|
|
32
|
+
return element(value);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function encoderOf(param) {
|
|
37
|
+
let element = param.element;
|
|
38
|
+
switch (param.encoding) {
|
|
39
|
+
case "Bool" :
|
|
40
|
+
return value => {
|
|
41
|
+
if (value) {
|
|
42
|
+
return 1;
|
|
43
|
+
} else {
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
case "Date" :
|
|
48
|
+
return value => value.getTime();
|
|
49
|
+
case "Decimal" :
|
|
50
|
+
return value => value.toFixed();
|
|
51
|
+
case "Document" :
|
|
52
|
+
return Sql.canonicalDocument;
|
|
53
|
+
case "List" :
|
|
54
|
+
let encode = elementOf(element, param.name);
|
|
55
|
+
let mapList$1;
|
|
56
|
+
mapList$1 = element === "Document" ? (value, encode) => value.map(item => {
|
|
57
|
+
if (Staging.isAbsent(item)) {
|
|
58
|
+
return null;
|
|
59
|
+
} else {
|
|
60
|
+
return encode(item);
|
|
61
|
+
}
|
|
62
|
+
}) : mapList;
|
|
63
|
+
return value => Utils.replaceLoneSurrogateEscapes(JSON.stringify(mapList$1(value, encode)));
|
|
64
|
+
default:
|
|
65
|
+
return value => value;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function writersOf(fields) {
|
|
70
|
+
return fields.map(field => ({
|
|
71
|
+
field: field,
|
|
72
|
+
encode: encoderOf(field)
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function columnsOf(writers) {
|
|
77
|
+
return writers.map(param => {
|
|
78
|
+
let field = param.field;
|
|
79
|
+
return {
|
|
80
|
+
name: field.name,
|
|
81
|
+
kind: Staging.kindOf(field.encoding),
|
|
82
|
+
isNullable: field.isNullable
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function writeField(stage, writers, column, row, value) {
|
|
88
|
+
let match = writers[column];
|
|
89
|
+
let field = match.field;
|
|
90
|
+
if (Staging.isAbsent(value)) {
|
|
91
|
+
return Staging.writeValue(stage, column, row, field.encoding === "Document" && !field.isNullable && value === null ? "null" : value);
|
|
92
|
+
} else {
|
|
93
|
+
return Staging.writeValue(stage, column, row, match.encode(value));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export {
|
|
98
|
+
writersOf,
|
|
99
|
+
columnsOf,
|
|
100
|
+
writeField,
|
|
101
|
+
}
|
|
102
|
+
/* Sql Not a pure module */
|
package/src/Staging.res
CHANGED
|
@@ -10,16 +10,6 @@ type kind =
|
|
|
10
10
|
| @as(3) Text
|
|
11
11
|
| @as(4) Bytes
|
|
12
12
|
|
|
13
|
-
let kindOfOrdinal = ordinal =>
|
|
14
|
-
switch ordinal {
|
|
15
|
-
| 0 => F64
|
|
16
|
-
| 1 => U64
|
|
17
|
-
| 2 => I64
|
|
18
|
-
| 3 => Text
|
|
19
|
-
| 4 => Bytes
|
|
20
|
-
| unknown => JsError.throwWithMessage(`Unknown staged column kind ${unknown->Int.toString}`)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
13
|
// The replacer closes over nothing but the column's name, so it is built once
|
|
24
14
|
// with the column rather than once per column per batch.
|
|
25
15
|
type column = {name: string, kind: kind, isNullable: bool, replacer?: JSON.replacer}
|
|
@@ -28,7 +18,7 @@ type begun = {handle: int, buffers: array<ArrayBuffer.t>}
|
|
|
28
18
|
|
|
29
19
|
// What the addon exposes, so this module stays free of the storage's own API.
|
|
30
20
|
type arena = {
|
|
31
|
-
beginStage: (~
|
|
21
|
+
beginStage: (~rows: int) => begun,
|
|
32
22
|
growStage: (~handle: int, ~column: int, ~needed: int, ~stale: ArrayBuffer.t) => ArrayBuffer.t,
|
|
33
23
|
commitStage: (~handle: int, ~buffers: array<ArrayBuffer.t>) => unit,
|
|
34
24
|
abortStage: (~handle: int, ~buffers: array<ArrayBuffer.t>) => unit,
|
|
@@ -79,8 +69,8 @@ type t = {
|
|
|
79
69
|
builders: array<builder>,
|
|
80
70
|
}
|
|
81
71
|
|
|
82
|
-
let begin = (arena, ~
|
|
83
|
-
let {handle, buffers} = arena.beginStage(~
|
|
72
|
+
let begin = (arena, ~rows, ~columns: array<column>) => {
|
|
73
|
+
let {handle, buffers} = arena.beginStage(~rows)
|
|
84
74
|
let slot = ref(0)
|
|
85
75
|
let take = () => {
|
|
86
76
|
let buffer = buffers->Array.getUnsafe(slot.contents)
|
|
@@ -275,7 +265,7 @@ let toText = (value: unknown, ~replacer=?) =>
|
|
|
275
265
|
}
|
|
276
266
|
)
|
|
277
267
|
|
|
278
|
-
|
|
268
|
+
let isAbsent = (value: unknown) => value === %raw(`undefined`) || value === %raw(`null`)
|
|
279
269
|
|
|
280
270
|
// Writes one value of a row the handler set. `undefined`/`null` marks the row's
|
|
281
271
|
// null bit, which a column that accepts NULL stores as such — and which one that
|
|
@@ -317,3 +307,31 @@ let commit = stage => {
|
|
|
317
307
|
}
|
|
318
308
|
|
|
319
309
|
let abort = stage => stage.arena.abortStage(~handle=stage.handle, ~buffers=stage.buffers)
|
|
310
|
+
|
|
311
|
+
// How a staged value has to arrive, as the addon declares it for every field:
|
|
312
|
+
// `storage::schema::Encoding`.
|
|
313
|
+
type encoding =
|
|
314
|
+
| Number
|
|
315
|
+
| Bool
|
|
316
|
+
| Date
|
|
317
|
+
| Text
|
|
318
|
+
| Digits
|
|
319
|
+
| Decimal
|
|
320
|
+
| Document
|
|
321
|
+
| Bytes
|
|
322
|
+
| List
|
|
323
|
+
|
|
324
|
+
type stagedField = {
|
|
325
|
+
name: string,
|
|
326
|
+
encoding: encoding,
|
|
327
|
+
// What a list's elements are encoded as; the field's own for a scalar.
|
|
328
|
+
element: encoding,
|
|
329
|
+
isNullable: bool,
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
let kindOf = (encoding: encoding) =>
|
|
333
|
+
switch encoding {
|
|
334
|
+
| Number | Bool | Date => F64
|
|
335
|
+
| Text | Digits | Decimal | Document | List => Text
|
|
336
|
+
| Bytes => Bytes
|
|
337
|
+
}
|