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.
Files changed (186) hide show
  1. package/README.md +40 -34
  2. package/evm.schema.json +3 -3
  3. package/fuel.schema.json +2 -2
  4. package/index.d.ts +3 -3
  5. package/licenses/README.md +1 -1
  6. package/package.json +9 -10
  7. package/src/Batch.res.mjs +5 -5
  8. package/src/BatchProcessing.res +1 -0
  9. package/src/BatchProcessing.res.mjs +1 -0
  10. package/src/Bin.res +0 -7
  11. package/src/Bin.res.mjs +0 -8
  12. package/src/ChainFetching.res +17 -456
  13. package/src/ChainFetching.res.mjs +33 -404
  14. package/src/ChainState.res +48 -83
  15. package/src/ChainState.res.mjs +83 -115
  16. package/src/ChainState.resi +0 -26
  17. package/src/Clock.res +57 -0
  18. package/src/Clock.res.mjs +72 -0
  19. package/src/Config.res +7 -16
  20. package/src/Config.res.mjs +4 -11
  21. package/src/ContractRegisterContext.res +6 -3
  22. package/src/ContractRegisterContext.res.mjs +2 -4
  23. package/src/Core.res +5 -136
  24. package/src/Core.res.mjs +1 -90
  25. package/src/CrossChainState.res +2 -8
  26. package/src/CrossChainState.res.mjs +3 -3
  27. package/src/Ecosystem.res +4 -7
  28. package/src/Ecosystem.res.mjs +8 -8
  29. package/src/EffectState.res +10 -2
  30. package/src/EffectState.res.mjs +8 -4
  31. package/src/EffectState.resi +3 -1
  32. package/src/EntityId.res +2 -7
  33. package/src/EntityId.res.mjs +1 -8
  34. package/src/EntityTables.res +4 -1
  35. package/src/EntityTables.res.mjs +1 -1
  36. package/src/Env.res +0 -16
  37. package/src/Env.res.mjs +0 -11
  38. package/src/EventProcessing.res +1 -38
  39. package/src/EventProcessing.res.mjs +1 -28
  40. package/src/FetchState.res +160 -319
  41. package/src/FetchState.res.mjs +182 -292
  42. package/src/FinalizeBackfill.res +2 -4
  43. package/src/FinalizeBackfill.res.mjs +3 -4
  44. package/src/HandlerLoader.res +15 -39
  45. package/src/HandlerLoader.res.mjs +8 -27
  46. package/src/HandlerRegister.res +0 -4
  47. package/src/HandlerRegister.res.mjs +2 -5
  48. package/src/HandlerRegister.resi +0 -2
  49. package/src/InMemoryTable.res +17 -16
  50. package/src/InMemoryTable.res.mjs +14 -15
  51. package/src/IndexerState.res +28 -4
  52. package/src/IndexerState.res.mjs +19 -6
  53. package/src/IndexerState.resi +4 -0
  54. package/src/Internal.res +0 -110
  55. package/src/Internal.res.mjs +1 -115
  56. package/src/LoadLayer.res +21 -47
  57. package/src/LoadLayer.res.mjs +47 -72
  58. package/src/LoadLayer.resi +0 -26
  59. package/src/Main.res +1 -14
  60. package/src/Main.res.mjs +3 -4
  61. package/src/Persistence.res +3 -23
  62. package/src/Persistence.res.mjs +3 -3
  63. package/src/Rollback.res +0 -1
  64. package/src/Rollback.res.mjs +1 -1
  65. package/src/RunScope.res +0 -3
  66. package/src/SafeCheckpointTracking.res +4 -4
  67. package/src/SafeCheckpointTracking.res.mjs +1 -1
  68. package/src/SimulateItems.res +26 -42
  69. package/src/SimulateItems.res.mjs +16 -40
  70. package/src/StagedRows.res +106 -0
  71. package/src/StagedRows.res.mjs +102 -0
  72. package/src/Staging.res +32 -14
  73. package/src/Staging.res.mjs +17 -20
  74. package/src/Storage.res +277 -998
  75. package/src/Storage.res.mjs +216 -731
  76. package/src/Supervisor.res +75 -56
  77. package/src/Supervisor.res.mjs +55 -26
  78. package/src/TestIndexer.res +22 -27
  79. package/src/TestIndexer.res.mjs +20 -17
  80. package/src/Throttler.res +15 -8
  81. package/src/Throttler.res.mjs +9 -6
  82. package/src/Throttler.resi +1 -1
  83. package/src/UserContext.res +46 -410
  84. package/src/UserContext.res.mjs +30 -318
  85. package/src/Utils.res +0 -23
  86. package/src/Utils.res.mjs +1 -17
  87. package/src/Writing.res +0 -1
  88. package/src/Writing.res.mjs +1 -1
  89. package/src/bindings/ClickHouse.res +0 -322
  90. package/src/bindings/ClickHouse.res.mjs +0 -338
  91. package/src/bindings/StorageClient.res +107 -175
  92. package/src/bindings/StorageClient.res.mjs +19 -8
  93. package/src/bindings/Vitest.res +0 -26
  94. package/src/bindings/Vitest.res.mjs +0 -3
  95. package/src/db/Table.res +24 -150
  96. package/src/db/Table.res.mjs +38 -272
  97. package/src/sources/AddressSet.res +0 -2
  98. package/src/sources/AddressStore.res +0 -3
  99. package/src/sources/ChainSources.res +2 -0
  100. package/src/sources/ChainSources.res.mjs +2 -2
  101. package/src/sources/EvmChain.res +4 -7
  102. package/src/sources/EvmChain.res.mjs +5 -4
  103. package/src/sources/EvmHyperSyncSource.res +2 -2
  104. package/src/sources/EvmHyperSyncSource.res.mjs +1 -1
  105. package/src/sources/EvmRpcClient.res +13 -3
  106. package/src/sources/EvmRpcClient.res.mjs +4 -3
  107. package/src/sources/EvmRpcWs.res +4 -3
  108. package/src/sources/EvmRpcWs.res.mjs +2 -2
  109. package/src/sources/HeightFeed.res +31 -10
  110. package/src/sources/HeightFeed.res.mjs +10 -6
  111. package/src/sources/HeightStream.res +32 -17
  112. package/src/sources/HeightStream.res.mjs +10 -10
  113. package/src/sources/HyperSync.res +1 -2
  114. package/src/sources/HyperSync.res.mjs +1 -2
  115. package/src/sources/HyperSyncSSE.res +4 -6
  116. package/src/sources/HyperSyncSSE.res.mjs +2 -2
  117. package/src/sources/RpcSource.res +10 -1
  118. package/src/sources/RpcSource.res.mjs +4 -3
  119. package/src/sources/Source.res +3 -0
  120. package/src/sources/SourceManager.res +85 -104
  121. package/src/sources/SourceManager.res.mjs +18 -37
  122. package/src/sources/SourceManager.resi +3 -5
  123. package/src/sources/StartBlockResolver.res +1 -0
  124. package/src/sources/StartBlockResolver.res.mjs +4 -3
  125. package/src/sources/SvmHyperSyncSource.res +2 -2
  126. package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
  127. package/svm.schema.json +3 -3
  128. package/src/EffectCacheLookup.res +0 -98
  129. package/src/EffectCacheLookup.res.mjs +0 -116
  130. package/src/PgWriting.res +0 -36
  131. package/src/PgWriting.res.mjs +0 -34
  132. package/src/PreloadLookahead.res +0 -184
  133. package/src/PreloadLookahead.res.mjs +0 -197
  134. package/src/SubgraphLog.res +0 -19
  135. package/src/SubgraphLog.res.mjs +0 -26
  136. package/src/SyncWrites.res +0 -101
  137. package/src/SyncWrites.res.mjs +0 -98
  138. package/src/db/IndexDefinition.res +0 -47
  139. package/src/db/IndexDefinition.res.mjs +0 -60
  140. package/src/sources/CallSource.res +0 -274
  141. package/src/sources/CallSource.res.mjs +0 -196
  142. package/src/subgraph/abi-types.ts +0 -84
  143. package/src/subgraph/aggregations.ts +0 -745
  144. package/src/subgraph/as-package.ts +0 -143
  145. package/src/subgraph/assemblyscript-regex.ts +0 -67
  146. package/src/subgraph/assemblyscript.ts +0 -731
  147. package/src/subgraph/blocks.ts +0 -398
  148. package/src/subgraph/calls-source.ts +0 -702
  149. package/src/subgraph/calls.ts +0 -258
  150. package/src/subgraph/conformance.ts +0 -106
  151. package/src/subgraph/errors.ts +0 -85
  152. package/src/subgraph/graft.ts +0 -73
  153. package/src/subgraph/graph-cli-worker.mjs +0 -35
  154. package/src/subgraph/graph-cli.ts +0 -900
  155. package/src/subgraph/graph-node-decimal.ts +0 -199
  156. package/src/subgraph/graph-ts-enums.ts +0 -28
  157. package/src/subgraph/graph-ts-types/VERSION +0 -2
  158. package/src/subgraph/graph-ts-types/chain/arweave.d.ts +0 -70
  159. package/src/subgraph/graph-ts-types/chain/cosmos.d.ts +0 -327
  160. package/src/subgraph/graph-ts-types/chain/ethereum.d.ts +0 -233
  161. package/src/subgraph/graph-ts-types/chain/near.d.ts +0 -253
  162. package/src/subgraph/graph-ts-types/chain/starknet.d.ts +0 -32
  163. package/src/subgraph/graph-ts-types/common/collections.d.ts +0 -136
  164. package/src/subgraph/graph-ts-types/common/conversion.d.ts +0 -11
  165. package/src/subgraph/graph-ts-types/common/datasource.d.ts +0 -30
  166. package/src/subgraph/graph-ts-types/common/eager-offset.d.ts +0 -0
  167. package/src/subgraph/graph-ts-types/common/json.d.ts +0 -17
  168. package/src/subgraph/graph-ts-types/common/numbers.d.ts +0 -120
  169. package/src/subgraph/graph-ts-types/common/value.d.ts +0 -120
  170. package/src/subgraph/graph-ts-types/common/yaml.d.ts +0 -90
  171. package/src/subgraph/graph-ts-types/global/global.d.ts +0 -194
  172. package/src/subgraph/graph-ts-types/helper-functions.d.ts +0 -22
  173. package/src/subgraph/graph-ts-types/index.d.ts +0 -102
  174. package/src/subgraph/graph-ts.ts +0 -4280
  175. package/src/subgraph/hosts.ts +0 -554
  176. package/src/subgraph/log.ts +0 -28
  177. package/src/subgraph/receipts.ts +0 -184
  178. package/src/subgraph/register-slots.ts +0 -93
  179. package/src/subgraph/rollup.ts +0 -109
  180. package/src/subgraph/rpc.ts +0 -337
  181. package/src/subgraph/runtime.ts +0 -2060
  182. package/src/subgraph/scope.ts +0 -177
  183. package/src/subgraph/stats.ts +0 -42
  184. package/src/subgraph/template-instances.ts +0 -66
  185. package/src/subgraph/toolchain.ts +0 -327
  186. package/src/subgraph/transient.ts +0 -176
@@ -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
  )
@@ -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, persistence.allEntities, persistence.allEnums, contractMapping, envioInfo);
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, persistence.allEntities, stored.contractMapping);
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(persistence.allEntities, chainConfigs.map(chain => chain.id), stored.contractMapping);
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
@@ -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, IndexerState.config(state).checkpointSequence);
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
- let safeBlockNumber = sourceBlockNumber - safeCheckpointTracking.maxReorgDepth
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;
@@ -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
- // A call is ordered by its position in its transaction's trace, so two
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
- let item = Internal.Event({
686
- onEventRegistration,
687
- chainId,
688
- blockNumber,
689
- logIndex,
690
- // Simulate keeps the transaction inline on the payload, so the store
691
- // key is unused; a subgraph's call triggers order by it among logs.
692
- transactionIndex: switch config.ecosystem.name {
693
- | Evm =>
694
- (
695
- transaction->(Utils.magic: Internal.eventTransaction => {"transactionIndex": int})
696
- )["transactionIndex"]
697
- | _ => 0
698
- },
699
- payload: (
700
- {
701
- contractName: eventConfig.contractName,
702
- eventName: eventConfig.name,
703
- params,
704
- chainId,
705
- srcAddress,
706
- logIndex,
707
- transaction,
708
- block,
709
- }: Evm.payload
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 match$12 = Internal.callRankOfEventName(eventConfig$1.name);
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$13 = ChainMap.values(config.chainMap).length;
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$13 !== 1 ? ` on chain ` + ChainId.toString(chainId) : ""
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
- let match = config.ecosystem.name;
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: tmp,
517
- payload: item_6
518
- };
519
- let rank = Internal.callRankOfEventName(eventConfig$1.name);
520
- if (rank !== undefined) {
521
- Internal.markItemCall(item, rank);
522
- }
523
- items.push(item);
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: (~table: int, ~rows: int) => begun,
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, ~table, ~rows, ~columns: array<column>) => {
83
- let {handle, buffers} = arena.beginStage(~table, ~rows)
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
- %%private(let isAbsent = (value: unknown) => value === %raw(`undefined`) || value === %raw(`null`))
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
+ }