envio 3.15.0 → 3.16.0-subgraph

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 +11 -2
  3. package/fuel.schema.json +10 -1
  4. package/index.d.ts +6 -0
  5. package/licenses/README.md +1 -1
  6. package/package.json +10 -9
  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 +7 -0
  11. package/src/Bin.res.mjs +8 -0
  12. package/src/ChainFetching.res +450 -16
  13. package/src/ChainFetching.res.mjs +403 -32
  14. package/src/ChainState.res +124 -7
  15. package/src/ChainState.res.mjs +128 -67
  16. package/src/ChainState.resi +26 -0
  17. package/src/Clock.res +57 -0
  18. package/src/Clock.res.mjs +72 -0
  19. package/src/Config.res +31 -3
  20. package/src/Config.res.mjs +15 -4
  21. package/src/ContractRegisterContext.res +3 -6
  22. package/src/ContractRegisterContext.res.mjs +4 -2
  23. package/src/Core.res +95 -36
  24. package/src/Core.res.mjs +90 -1
  25. package/src/CrossChainState.res +12 -2
  26. package/src/CrossChainState.res.mjs +3 -3
  27. package/src/Ecosystem.res +7 -4
  28. package/src/Ecosystem.res.mjs +8 -8
  29. package/src/EffectCacheLookup.res +98 -0
  30. package/src/EffectCacheLookup.res.mjs +116 -0
  31. package/src/EffectState.res +10 -2
  32. package/src/EffectState.res.mjs +8 -4
  33. package/src/EffectState.resi +3 -1
  34. package/src/EntityId.res +2 -7
  35. package/src/EntityId.res.mjs +1 -8
  36. package/src/EntityTables.res +4 -1
  37. package/src/EntityTables.res.mjs +1 -1
  38. package/src/Env.res +20 -0
  39. package/src/Env.res.mjs +16 -0
  40. package/src/EventProcessing.res +38 -1
  41. package/src/EventProcessing.res.mjs +28 -1
  42. package/src/FetchState.res +408 -73
  43. package/src/FetchState.res.mjs +361 -91
  44. package/src/FinalizeBackfill.res +2 -4
  45. package/src/FinalizeBackfill.res.mjs +3 -4
  46. package/src/HandlerLoader.res +39 -15
  47. package/src/HandlerLoader.res.mjs +27 -8
  48. package/src/HandlerRegister.res +4 -0
  49. package/src/HandlerRegister.res.mjs +5 -2
  50. package/src/HandlerRegister.resi +2 -0
  51. package/src/InMemoryTable.res +17 -16
  52. package/src/InMemoryTable.res.mjs +14 -15
  53. package/src/IndexerState.res +28 -4
  54. package/src/IndexerState.res.mjs +19 -6
  55. package/src/IndexerState.resi +4 -0
  56. package/src/Internal.res +61 -49
  57. package/src/Internal.res.mjs +36 -80
  58. package/src/LoadLayer.res +54 -15
  59. package/src/LoadLayer.res.mjs +75 -45
  60. package/src/LoadLayer.resi +26 -0
  61. package/src/Main.res +14 -1
  62. package/src/Main.res.mjs +4 -3
  63. package/src/Persistence.res +3 -23
  64. package/src/Persistence.res.mjs +3 -3
  65. package/src/PreloadLookahead.res +202 -0
  66. package/src/PreloadLookahead.res.mjs +218 -0
  67. package/src/Rollback.res +0 -1
  68. package/src/Rollback.res.mjs +1 -1
  69. package/src/RunScope.res +3 -0
  70. package/src/SafeCheckpointTracking.res +4 -4
  71. package/src/SafeCheckpointTracking.res.mjs +1 -1
  72. package/src/SimulateItems.res +42 -26
  73. package/src/SimulateItems.res.mjs +40 -16
  74. package/src/StagedRows.res +106 -0
  75. package/src/StagedRows.res.mjs +102 -0
  76. package/src/Staging.res +32 -14
  77. package/src/Staging.res.mjs +17 -20
  78. package/src/Storage.res +303 -948
  79. package/src/Storage.res.mjs +229 -708
  80. package/src/SubgraphLog.res +19 -0
  81. package/src/SubgraphLog.res.mjs +26 -0
  82. package/src/Supervisor.res +75 -56
  83. package/src/Supervisor.res.mjs +55 -26
  84. package/src/SyncWrites.res +107 -0
  85. package/src/SyncWrites.res.mjs +98 -0
  86. package/src/TestIndexer.res +22 -27
  87. package/src/TestIndexer.res.mjs +20 -17
  88. package/src/Throttler.res +15 -8
  89. package/src/Throttler.res.mjs +9 -6
  90. package/src/Throttler.resi +1 -1
  91. package/src/UserContext.res +419 -46
  92. package/src/UserContext.res.mjs +318 -30
  93. package/src/Utils.res +17 -6
  94. package/src/Utils.res.mjs +12 -6
  95. package/src/Writing.res +0 -1
  96. package/src/Writing.res.mjs +1 -1
  97. package/src/bindings/ClickHouse.res +0 -322
  98. package/src/bindings/ClickHouse.res.mjs +0 -338
  99. package/src/bindings/StorageClient.res +108 -174
  100. package/src/bindings/StorageClient.res.mjs +19 -8
  101. package/src/bindings/Vitest.res +0 -26
  102. package/src/bindings/Vitest.res.mjs +0 -3
  103. package/src/db/Table.res +24 -150
  104. package/src/db/Table.res.mjs +38 -272
  105. package/src/sources/AddressSet.res +2 -0
  106. package/src/sources/AddressStore.res +3 -0
  107. package/src/sources/CallSource.res +274 -0
  108. package/src/sources/CallSource.res.mjs +196 -0
  109. package/src/sources/ChainSources.res +2 -0
  110. package/src/sources/ChainSources.res.mjs +2 -2
  111. package/src/sources/EvmChain.res +10 -1
  112. package/src/sources/EvmChain.res.mjs +6 -3
  113. package/src/sources/EvmHyperSyncSource.res +2 -2
  114. package/src/sources/EvmHyperSyncSource.res.mjs +1 -1
  115. package/src/sources/EvmRpcClient.res +13 -3
  116. package/src/sources/EvmRpcClient.res.mjs +4 -3
  117. package/src/sources/EvmRpcWs.res +4 -3
  118. package/src/sources/EvmRpcWs.res.mjs +2 -2
  119. package/src/sources/HeightFeed.res +31 -10
  120. package/src/sources/HeightFeed.res.mjs +10 -6
  121. package/src/sources/HeightStream.res +32 -17
  122. package/src/sources/HeightStream.res.mjs +10 -10
  123. package/src/sources/HyperSync.res +2 -1
  124. package/src/sources/HyperSync.res.mjs +2 -1
  125. package/src/sources/HyperSyncSSE.res +4 -6
  126. package/src/sources/HyperSyncSSE.res.mjs +2 -2
  127. package/src/sources/RpcSource.res +10 -1
  128. package/src/sources/RpcSource.res.mjs +4 -3
  129. package/src/sources/Source.res +3 -0
  130. package/src/sources/SourceManager.res +84 -77
  131. package/src/sources/SourceManager.res.mjs +17 -20
  132. package/src/sources/SourceManager.resi +3 -4
  133. package/src/sources/StartBlockResolver.res +1 -0
  134. package/src/sources/StartBlockResolver.res.mjs +3 -2
  135. package/src/sources/SvmHyperSyncSource.res +2 -2
  136. package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
  137. package/src/subgraph/abi-types.ts +84 -0
  138. package/src/subgraph/aggregations.ts +745 -0
  139. package/src/subgraph/as-package.ts +143 -0
  140. package/src/subgraph/assemblyscript-regex.ts +67 -0
  141. package/src/subgraph/assemblyscript.ts +731 -0
  142. package/src/subgraph/blocks.ts +398 -0
  143. package/src/subgraph/calls-source.ts +702 -0
  144. package/src/subgraph/calls.ts +258 -0
  145. package/src/subgraph/conformance.ts +106 -0
  146. package/src/subgraph/errors.ts +85 -0
  147. package/src/subgraph/graft.ts +73 -0
  148. package/src/subgraph/graph-cli-worker.mjs +35 -0
  149. package/src/subgraph/graph-cli.ts +900 -0
  150. package/src/subgraph/graph-node-decimal.ts +199 -0
  151. package/src/subgraph/graph-ts-enums.ts +28 -0
  152. package/src/subgraph/graph-ts-types/VERSION +2 -0
  153. package/src/subgraph/graph-ts-types/chain/arweave.d.ts +70 -0
  154. package/src/subgraph/graph-ts-types/chain/cosmos.d.ts +327 -0
  155. package/src/subgraph/graph-ts-types/chain/ethereum.d.ts +233 -0
  156. package/src/subgraph/graph-ts-types/chain/near.d.ts +253 -0
  157. package/src/subgraph/graph-ts-types/chain/starknet.d.ts +32 -0
  158. package/src/subgraph/graph-ts-types/common/collections.d.ts +136 -0
  159. package/src/subgraph/graph-ts-types/common/conversion.d.ts +11 -0
  160. package/src/subgraph/graph-ts-types/common/datasource.d.ts +30 -0
  161. package/src/subgraph/graph-ts-types/common/eager-offset.d.ts +0 -0
  162. package/src/subgraph/graph-ts-types/common/json.d.ts +17 -0
  163. package/src/subgraph/graph-ts-types/common/numbers.d.ts +120 -0
  164. package/src/subgraph/graph-ts-types/common/value.d.ts +120 -0
  165. package/src/subgraph/graph-ts-types/common/yaml.d.ts +90 -0
  166. package/src/subgraph/graph-ts-types/global/global.d.ts +194 -0
  167. package/src/subgraph/graph-ts-types/helper-functions.d.ts +22 -0
  168. package/src/subgraph/graph-ts-types/index.d.ts +102 -0
  169. package/src/subgraph/graph-ts.ts +4339 -0
  170. package/src/subgraph/hosts.ts +554 -0
  171. package/src/subgraph/log.ts +28 -0
  172. package/src/subgraph/receipts.ts +184 -0
  173. package/src/subgraph/register-slots.ts +93 -0
  174. package/src/subgraph/rollup.ts +109 -0
  175. package/src/subgraph/rpc.ts +337 -0
  176. package/src/subgraph/runtime.ts +2059 -0
  177. package/src/subgraph/scope.ts +176 -0
  178. package/src/subgraph/stats.ts +42 -0
  179. package/src/subgraph/template-instances.ts +66 -0
  180. package/src/subgraph/toolchain.ts +327 -0
  181. package/src/subgraph/transient.ts +176 -0
  182. package/svm.schema.json +11 -2
  183. package/src/PgWriting.res +0 -36
  184. package/src/PgWriting.res.mjs +0 -34
  185. package/src/db/IndexDefinition.res +0 -47
  186. package/src/db/IndexDefinition.res.mjs +0 -67
package/src/Config.res CHANGED
@@ -65,6 +65,7 @@ type chain = {
65
65
  endBlock?: int,
66
66
  maxReorgDepth: int,
67
67
  blockLag: int,
68
+ blockThrottle: int,
68
69
  contracts: array<contract>,
69
70
  sourceConfig: sourceConfig,
70
71
  }
@@ -154,6 +155,9 @@ type t = {
154
155
  // reach, so its checkpoints have to be comparable across chains.
155
156
  checkpointSequence: CheckpointSequence.t,
156
157
  envioInfo: JSON.t,
158
+ // Set only in subgraph mode: the translated manifest, which is what makes
159
+ // the subgraph runtime take over handler registration.
160
+ subgraph: option<JSON.t>,
157
161
  }
158
162
 
159
163
  type rpcSourceFor = | @as("sync") Sync | @as("fallback") Fallback | @as("realtime") Realtime
@@ -217,6 +221,7 @@ let publicConfigChainSchema = S.schema(s =>
217
221
  "endBlock": s.matches(S.option(S.int)),
218
222
  "maxReorgDepth": s.matches(S.option(S.int)),
219
223
  "blockLag": s.matches(S.option(S.int)),
224
+ "blockThrottle": s.matches(S.option(S.int)),
220
225
  // EVM/Fuel source config (hypersync for EVM, hyperfuel for Fuel)
221
226
  "hypersync": s.matches(S.option(S.string)),
222
227
  "rpcs": s.matches(S.option(S.array(rpcConfigSchema))),
@@ -616,6 +621,7 @@ let publicConfigSchema = S.schema(s =>
616
621
  "svm": s.matches(S.option(publicConfigEcosystemSchema)),
617
622
  "enums": s.matches(S.option(S.dict(S.array(S.string)))),
618
623
  "entities": s.matches(S.option(S.array(entityJsonSchema))),
624
+ "subgraph": s.matches(S.option(S.json(~validate=false))),
619
625
  }
620
626
  )
621
627
 
@@ -698,6 +704,10 @@ let toEnvioInfo = (publicConfigJson: JSON.t): JSON.t => {
698
704
  switch envioInfo {
699
705
  | Object(obj) => {
700
706
  commandFields->Array.forEach(field => obj->Utils.Dict.deleteInPlace(field))
707
+ // The subgraph blob is how the runtime finds mappings. None of it
708
+ // describes stored data — that's already in `evm` / `entities` — so a
709
+ // specVersion bump or a mapping-path edit must not force a reset.
710
+ obj->Utils.Dict.deleteInPlace("subgraph")
701
711
  ecosystemFields->Array.forEach(ecosystem =>
702
712
  switch obj->Dict.get(ecosystem) {
703
713
  | Some(Object(ecosystemDict)) => ecosystemDict->Utils.Dict.deleteInPlace("chains")
@@ -1069,18 +1079,23 @@ let fromPublic = (publicConfigJson: JSON.t) => {
1069
1079
  startBlock: publicChainConfig["startBlock"],
1070
1080
  endBlock: ?publicChainConfig["endBlock"],
1071
1081
  maxReorgDepth: switch ecosystemName {
1072
- | Ecosystem.Evm => publicChainConfig["maxReorgDepth"]->Option.getOr(200)
1082
+ // One less than the 200 blocks behind the head a source checks for a
1083
+ // lagging node, so the backfill, which stops one block below the window,
1084
+ // ends exactly where those checks begin.
1085
+ | Ecosystem.Evm => publicChainConfig["maxReorgDepth"]->Option.getOr(199)
1073
1086
  // Tower BFT roots a block once 32 votes lock it in (MAX_LOCKOUT_HISTORY
1074
1087
  // is 31, plus the slot itself), which is what `finalized` waits for — so
1075
1088
  // 32 is the protocol's own bound on how far a fork can be replaced. That
1076
1089
  // bound counts *blocks* while the threshold here is measured in slot
1077
1090
  // numbers, and skipped slots make the slot distance the larger of the
1078
1091
  // two, so the default keeps a wide margin over it. Slots are ~0.4s, so
1079
- // even this spans well under two minutes of chain.
1080
- | Ecosystem.Svm => publicChainConfig["maxReorgDepth"]->Option.getOr(200)
1092
+ // even this spans well under two minutes of chain. One less than 200
1093
+ // for the same reason as EVM: the backfill stops one slot below it.
1094
+ | Ecosystem.Svm => publicChainConfig["maxReorgDepth"]->Option.getOr(199)
1081
1095
  | Ecosystem.Fuel => 0
1082
1096
  },
1083
1097
  blockLag: publicChainConfig["blockLag"]->Option.getOr(0),
1098
+ blockThrottle: publicChainConfig["blockThrottle"]->Option.getOr(0),
1084
1099
  contracts,
1085
1100
  sourceConfig,
1086
1101
  }
@@ -1145,6 +1160,18 @@ let fromPublic = (publicConfigJson: JSON.t) => {
1145
1160
  | None => []
1146
1161
  }
1147
1162
 
1163
+ switch publicConfig["subgraph"] {
1164
+ | Some(subgraph) =>
1165
+ Env.subgraphMode := true
1166
+ Env.subgraphHasTemplates :=
1167
+ subgraph
1168
+ ->JSON.Decode.object
1169
+ ->Option.flatMap(manifest => manifest->Dict.get("templates"))
1170
+ ->Option.flatMap(JSON.Decode.array)
1171
+ ->Option.mapOr(false, templates => templates->Array.length > 0)
1172
+ | None => ()
1173
+ }
1174
+
1148
1175
  let config = {
1149
1176
  name: publicConfig["name"],
1150
1177
  description: publicConfig["description"],
@@ -1173,6 +1200,7 @@ let fromPublic = (publicConfigJson: JSON.t) => {
1173
1200
  allEnums,
1174
1201
  checkpointSequence: CheckpointSequence.fromEntities(userEntities),
1175
1202
  envioInfo: publicConfigJson->toEnvioInfo,
1203
+ subgraph: publicConfig["subgraph"],
1176
1204
  }
1177
1205
 
1178
1206
  switch publicConfig["isolatedChains"] {
@@ -88,6 +88,7 @@ let publicConfigChainSchema = S$RescriptSchema.schema(s => ({
88
88
  endBlock: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
89
89
  maxReorgDepth: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
90
90
  blockLag: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
91
+ blockThrottle: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
91
92
  hypersync: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
92
93
  rpcs: s.m(S$RescriptSchema.option(S$RescriptSchema.array(rpcConfigSchema))),
93
94
  contracts: s.m(S$RescriptSchema.option(S$RescriptSchema.dict(chainContractSchema)))
@@ -448,7 +449,8 @@ let publicConfigSchema = S$RescriptSchema.schema(s => ({
448
449
  fuel: s.m(S$RescriptSchema.option(publicConfigEcosystemSchema)),
449
450
  svm: s.m(S$RescriptSchema.option(publicConfigEcosystemSchema)),
450
451
  enums: s.m(S$RescriptSchema.option(S$RescriptSchema.dict(S$RescriptSchema.array(S$RescriptSchema.string)))),
451
- entities: s.m(S$RescriptSchema.option(S$RescriptSchema.array(entityJsonSchema)))
452
+ entities: s.m(S$RescriptSchema.option(S$RescriptSchema.array(entityJsonSchema))),
453
+ subgraph: s.m(S$RescriptSchema.option(S$RescriptSchema.json(false)))
452
454
  }));
453
455
 
454
456
  function contractMappingOf(chainConfigs) {
@@ -518,6 +520,7 @@ function toEnvioInfo(publicConfigJson) {
518
520
  let envioInfo = JSON.parse(JSON.stringify(publicConfigJson));
519
521
  if (typeof envioInfo === "object" && envioInfo !== null && !Array.isArray(envioInfo)) {
520
522
  commandFields.forEach(field => Utils.Dict.deleteInPlace(envioInfo, field));
523
+ Utils.Dict.deleteInPlace(envioInfo, "subgraph");
521
524
  ecosystemFields.forEach(ecosystem => {
522
525
  let match = envioInfo[ecosystem];
523
526
  if (typeof match === "object" && match !== null && !Array.isArray(match)) {
@@ -762,7 +765,7 @@ function fromPublic(publicConfigJson) {
762
765
  break;
763
766
  case "evm" :
764
767
  case "svm" :
765
- tmp = Stdlib_Option.getOr(publicChainConfig.maxReorgDepth, 200);
768
+ tmp = Stdlib_Option.getOr(publicChainConfig.maxReorgDepth, 199);
766
769
  break;
767
770
  }
768
771
  return {
@@ -773,6 +776,7 @@ function fromPublic(publicConfigJson) {
773
776
  endBlock: publicChainConfig.endBlock,
774
777
  maxReorgDepth: tmp,
775
778
  blockLag: Stdlib_Option.getOr(publicChainConfig.blockLag, 0),
779
+ blockThrottle: Stdlib_Option.getOr(publicChainConfig.blockThrottle, 0),
776
780
  contracts: contracts,
777
781
  sourceConfig: sourceConfig
778
782
  };
@@ -806,6 +810,11 @@ function fromPublic(publicConfigJson) {
806
810
  name: Utils.$$String.capitalize(param[0]),
807
811
  handler: param[1].handler
808
812
  })) : [];
813
+ let subgraph = publicConfig.subgraph;
814
+ if (subgraph !== undefined) {
815
+ Env.subgraphMode.contents = true;
816
+ Env.subgraphHasTemplates.contents = Stdlib_Option.mapOr(Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_JSON.Decode.object(subgraph), manifest => manifest["templates"]), Stdlib_JSON.Decode.array), false, templates => templates.length !== 0);
817
+ }
809
818
  let config_name = publicConfig.name;
810
819
  let config_description = publicConfig.description;
811
820
  let config_handlers = Stdlib_Option.getOr(publicConfig.handlers, "src/handlers");
@@ -820,6 +829,7 @@ function fromPublic(publicConfigJson) {
820
829
  let config_projectFlags = Stdlib_Option.getOr(publicConfig.projectFlags, "");
821
830
  let config_checkpointSequence = CheckpointSequence.fromEntities(userEntities);
822
831
  let config_envioInfo = toEnvioInfo(publicConfigJson);
832
+ let config_subgraph = publicConfig.subgraph;
823
833
  let config = {
824
834
  name: config_name,
825
835
  description: config_description,
@@ -847,7 +857,8 @@ function fromPublic(publicConfigJson) {
847
857
  userEntities: userEntities,
848
858
  allEnums: allEnums,
849
859
  checkpointSequence: config_checkpointSequence,
850
- envioInfo: config_envioInfo
860
+ envioInfo: config_envioInfo,
861
+ subgraph: config_subgraph
851
862
  };
852
863
  let chainIds = publicConfig.isolatedChains;
853
864
  if (chainIds !== undefined) {
@@ -972,7 +983,7 @@ function diffPaths(stored, current) {
972
983
  }
973
984
  return;
974
985
  }
975
- } else {
986
+ } else if (s !== null) {
976
987
  switch (typeof s) {
977
988
  case "object" :
978
989
  if (typeof c === "object" && c !== null && !Array.isArray(c)) {
@@ -20,11 +20,7 @@ let make = (~config: Config.t): Internal.contractRegisterContext => {
20
20
  {
21
21
  enumerable: true,
22
22
  get: () =>
23
- (
24
- RunScope.currentContractRegisterRunOrThrow(
25
- ~prop="chain",
26
- ).item->Internal.castUnsafeEventItem
27
- ).chainId,
23
+ RunScope.currentContractRegisterRunOrThrow(~prop="chain").item->Internal.getItemChainId,
28
24
  },
29
25
  )
30
26
  ->ignore
@@ -49,7 +45,8 @@ let make = (~config: Config.t): Internal.contractRegisterContext => {
49
45
  // The value is passed from user-land, so validate and checksum/lowercase it.
50
46
  address: config->Config.normalizeUserAddress(contractAddress),
51
47
  contractName,
52
- registrationBlock: (run.item->Internal.castUnsafeEventItem).blockNumber,
48
+ registrationBlock: run.item->Internal.getItemBlockNumber,
49
+ creationRound: ?run.creationRound,
53
50
  })
54
51
  ->ignore
55
52
  },
@@ -4,6 +4,7 @@ import * as Utils from "./Utils.res.mjs";
4
4
  import * as Config from "./Config.res.mjs";
5
5
  import * as Logger from "./Logger.res.mjs";
6
6
  import * as ChainMap from "./ChainMap.res.mjs";
7
+ import * as Internal from "./Internal.res.mjs";
7
8
  import * as RunScope from "./RunScope.res.mjs";
8
9
  import * as EntityFilter from "./db/EntityFilter.res.mjs";
9
10
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
@@ -12,7 +13,7 @@ function make(config) {
12
13
  let chain = Object.create(Utils.StrictObject.makePrototype(prop => Stdlib_JsError.throwWithMessage(`Invalid contract name '` + prop + `' on context.chain. ` + EntityFilter.codegenHelpMessage)));
13
14
  Object.defineProperty(chain, "id", {
14
15
  enumerable: true,
15
- get: () => RunScope.currentContractRegisterRunOrThrow("chain").item.chainId
16
+ get: () => Internal.getItemChainId(RunScope.currentContractRegisterRunOrThrow("chain").item)
16
17
  });
17
18
  let contractNames = new Set();
18
19
  ChainMap.values(config.chainMap).forEach(chainConfig => {
@@ -29,7 +30,8 @@ function make(config) {
29
30
  run.registrations.push({
30
31
  address: Config.normalizeUserAddress(config, contractAddress),
31
32
  contractName: contractName,
32
- registrationBlock: run.item.blockNumber
33
+ registrationBlock: run.item.blockNumber,
34
+ creationRound: run.creationRound
33
35
  });
34
36
  }
35
37
  }
package/src/Core.res CHANGED
@@ -18,6 +18,8 @@ type loggerCtor
18
18
  type mockHyperSyncServerCtor
19
19
  // Test-only: the ledger behind envio-tests' MockSource.
20
20
  type mockSourceCtor
21
+ // Test-only: the virtual clock a scenario's source layer runs on.
22
+ type virtualClockCtor
21
23
  type fromUserApiOptions = {
22
24
  schema?: string,
23
25
  env?: dict<string>,
@@ -31,48 +33,43 @@ type fromUserApiResult = {
31
33
  indexerCode: Null.t<string>,
32
34
  }
33
35
 
34
- // One column of a Postgres table, flattened for the boundary: napi carries no
35
- // tagged union, so the field type arrives as its name plus whichever of the
36
- // modifiers it takes.
37
- type pgColumnInput = {
38
- // The database column name, renames already resolved.
39
- name: string,
40
- fieldType: string,
41
- isArray: bool,
42
- isNullable: bool,
43
- isPrimaryKey: bool,
44
- defaultValue?: string,
45
- precision?: int,
46
- scale?: int,
47
- enumName?: string,
36
+ type fromSubgraphOptions = {
37
+ name?: string,
38
+ env?: dict<string>,
39
+ files?: dict<string>,
40
+ root?: string,
48
41
  }
49
42
 
50
- type pgTableInput = {
51
- // In the order the table declares them.
52
- columns: array<pgColumnInput>,
53
- // The columns a batch's rows carry, in the order they are laid out.
54
- writeColumns: array<string>,
55
- partitionByColumn?: string,
56
- appendOnly: bool,
57
- // An entity's history table, and the column its chain is in when it is
58
- // per-chain.
59
- historyTable?: string,
60
- chainIdColumn?: string,
61
- }
43
+ type bundledCodegenResult = {outputDir: string, files: array<string>}
62
44
 
63
- type pgIndexColumnInput = {
64
- name: string,
65
- direction: string,
66
- }
67
-
68
- type pgIndexInput = {
69
- tableName: string,
70
- columns: array<pgIndexColumnInput>,
71
- method: string,
45
+ type filledGeneratedFile = {
46
+ file: string,
47
+ source: string,
48
+ abiName?: string,
49
+ renamedFrom?: string,
50
+ undeclared: bool,
72
51
  }
73
52
 
74
53
  type addon = {
75
- getConfigJson: (~configPath: Null.t<string>, ~directory: Null.t<string>) => string,
54
+ getConfigJson: (
55
+ ~configPath: Null.t<string>,
56
+ ~directory: Null.t<string>,
57
+ ~portsServedHere: array<int>,
58
+ ) => string,
59
+ fromSubgraph: (string, string, fromSubgraphOptions) => fromUserApiResult,
60
+ subgraphFileToJavascript: (string, string, bool) => string,
61
+ subgraphRegisterHandlers: (array<string>, array<array<string>>) => array<array<string>>,
62
+ subgraphSureCreates: (string, array<string>, array<string>) => array<array<string>>,
63
+ subgraphKeccak256: Uint8Array.t => Uint8Array.t,
64
+ subgraphAbiDecode: (string, Uint8Array.t, bool) => unknown,
65
+ subgraphAbiEncodeCall: (string, string, JSON.t) => string,
66
+ subgraphBundledCodegen: (string, Null.t<string>) => bundledCodegenResult,
67
+ subgraphBundledCodegenCurrent: (string, string) => bool,
68
+ subgraphMissingGraphCliMessage: string => string,
69
+ subgraphFillGenerated: (string, string, string, array<string>) => array<filledGeneratedFile>,
70
+ subgraphWorkspacePackages: string => dict<string>,
71
+ subgraphWorkspaceRoot: string => Null.t<string>,
72
+ subgraphScriptsWriting: (string, string) => array<array<string>>,
76
73
  encodeIndexedTopic: (~abiType: string, ~value: unknown) => EvmTypes.Hex.t,
77
74
  isSvmPubkey: (~value: string) => bool,
78
75
  fromUserApi: (string, fromUserApiOptions) => fromUserApiResult,
@@ -107,6 +104,8 @@ type addon = {
107
104
  mockHyperSyncServer: mockHyperSyncServerCtor,
108
105
  @as("MockSource")
109
106
  mockSource: mockSourceCtor,
107
+ @as("VirtualClock")
108
+ virtualClock: virtualClockCtor,
110
109
  encodeAddresses: (~ecosystem: string, ~addresses: array<Address.t>) => array<NodeJs.Buffer.t>,
111
110
  normalizeEvmAddress: (~address: string, ~shouldChecksum: bool) => Null.t<Address.t>,
112
111
  renderAddresses: (
@@ -330,11 +329,24 @@ let getAddon = () =>
330
329
  }
331
330
  }
332
331
 
332
+ // The ports servers in this process listen on. Node has no public list of
333
+ // them; `_getActiveHandles` has held them since its first releases, and
334
+ // without it nothing is reported.
335
+ let portsServedHere: unit => array<int> = %raw(`() =>
336
+ typeof process._getActiveHandles !== "function"
337
+ ? []
338
+ : process
339
+ ._getActiveHandles()
340
+ .map((handle) => (handle?.listening === true && typeof handle.address === "function" ? handle.address() : null))
341
+ .filter((address) => typeof address?.port === "number")
342
+ .map((address) => address.port)`)
343
+
333
344
  let getConfigJson = (~configPath=?, ~directory=?) => {
334
345
  let addon = getAddon()
335
346
  addon.getConfigJson(
336
347
  ~configPath=configPath->Null.fromOption,
337
348
  ~directory=directory->Null.fromOption,
349
+ ~portsServedHere=portsServedHere(),
338
350
  )
339
351
  }
340
352
 
@@ -356,6 +368,53 @@ let fromUserApi = (~schema=?, ~env=?, ~files=?, ~withIndexerTypes=false, yaml) =
356
368
  )
357
369
  }
358
370
 
371
+ /// Parses a subgraph project without touching the filesystem: subgraph.yaml and
372
+ /// its schema inline, ABI bodies through `files`.
373
+ let fromSubgraph = (~name=?, ~env=?, ~files=?, ~root=?, ~manifest, ~schema) => {
374
+ let addon = getAddon()
375
+ addon.fromSubgraph(manifest, schema, {?name, ?env, ?files, ?root})
376
+ }
377
+
378
+ let subgraphFileToJavascript = (~source, ~path, ~legacyNulls) => {
379
+ let addon = getAddon()
380
+ addon.subgraphFileToJavascript(source, path, legacyNulls)
381
+ }
382
+
383
+ let subgraphRegisterHandlers = (~mappingFiles, ~handlers) => {
384
+ let addon = getAddon()
385
+ addon.subgraphRegisterHandlers(mappingFiles, handlers)
386
+ }
387
+
388
+ let subgraphSureCreates = (~mappingFile, ~handlers, ~templates) =>
389
+ getAddon().subgraphSureCreates(mappingFile, handlers, templates)
390
+
391
+ let subgraphKeccak256 = bytes => getAddon().subgraphKeccak256(bytes)
392
+
393
+ let subgraphAbiDecode = (ty, data, params) => getAddon().subgraphAbiDecode(ty, data, params)
394
+
395
+ let subgraphAbiEncodeCall = (name, inputs, args) =>
396
+ getAddon().subgraphAbiEncodeCall(name, inputs, args)
397
+
398
+ let subgraphBundledCodegen = (~manifestFile, ~outputDir: option<string>) => {
399
+ let addon = getAddon()
400
+ addon.subgraphBundledCodegen(manifestFile, outputDir->Null.fromOption)
401
+ }
402
+
403
+ let subgraphBundledCodegenCurrent = (~manifestFile, ~outputDir) =>
404
+ getAddon().subgraphBundledCodegenCurrent(manifestFile, outputDir)
405
+
406
+ let subgraphMissingGraphCliMessage = generated =>
407
+ getAddon().subgraphMissingGraphCliMessage(generated)
408
+
409
+ let subgraphFillGenerated = (~root, ~manifestFile, ~outputDir, ~wanted) =>
410
+ getAddon().subgraphFillGenerated(root, manifestFile, outputDir, wanted)
411
+
412
+ let subgraphWorkspacePackages = root => getAddon().subgraphWorkspacePackages(root)
413
+
414
+ let subgraphWorkspaceRoot = root => getAddon().subgraphWorkspaceRoot(root)
415
+
416
+ let subgraphScriptsWriting = (~dir, ~needle) => getAddon().subgraphScriptsWriting(dir, needle)
417
+
359
418
  let runCli = args => {
360
419
  let addon = getAddon()
361
420
  addon.runCli(~args, ~envioPackageDir=Null.make(envioPackageDir))
package/src/Core.res.mjs CHANGED
@@ -216,9 +216,18 @@ function getAddon() {
216
216
  return a$1;
217
217
  }
218
218
 
219
+ let portsServedHere = (() =>
220
+ typeof process._getActiveHandles !== "function"
221
+ ? []
222
+ : process
223
+ ._getActiveHandles()
224
+ .map((handle) => (handle?.listening === true && typeof handle.address === "function" ? handle.address() : null))
225
+ .filter((address) => typeof address?.port === "number")
226
+ .map((address) => address.port));
227
+
219
228
  function getConfigJson(configPath, directory) {
220
229
  let addon = getAddon();
221
- return addon.getConfigJson(Stdlib_Null.fromOption(configPath), Stdlib_Null.fromOption(directory));
230
+ return addon.getConfigJson(Stdlib_Null.fromOption(configPath), Stdlib_Null.fromOption(directory), portsServedHere());
222
231
  }
223
232
 
224
233
  function fromUserApi(schema, env, files, withIndexerTypesOpt, yaml) {
@@ -232,6 +241,71 @@ function fromUserApi(schema, env, files, withIndexerTypesOpt, yaml) {
232
241
  });
233
242
  }
234
243
 
244
+ function fromSubgraph(name, env, files, root, manifest, schema) {
245
+ let addon = getAddon();
246
+ return addon.fromSubgraph(manifest, schema, {
247
+ name: name,
248
+ env: env,
249
+ files: files,
250
+ root: root
251
+ });
252
+ }
253
+
254
+ function subgraphFileToJavascript(source, path, legacyNulls) {
255
+ let addon = getAddon();
256
+ return addon.subgraphFileToJavascript(source, path, legacyNulls);
257
+ }
258
+
259
+ function subgraphRegisterHandlers(mappingFiles, handlers) {
260
+ let addon = getAddon();
261
+ return addon.subgraphRegisterHandlers(mappingFiles, handlers);
262
+ }
263
+
264
+ function subgraphSureCreates(mappingFile, handlers, templates) {
265
+ return getAddon().subgraphSureCreates(mappingFile, handlers, templates);
266
+ }
267
+
268
+ function subgraphKeccak256(bytes) {
269
+ return getAddon().subgraphKeccak256(bytes);
270
+ }
271
+
272
+ function subgraphAbiDecode(ty, data, params) {
273
+ return getAddon().subgraphAbiDecode(ty, data, params);
274
+ }
275
+
276
+ function subgraphAbiEncodeCall(name, inputs, args) {
277
+ return getAddon().subgraphAbiEncodeCall(name, inputs, args);
278
+ }
279
+
280
+ function subgraphBundledCodegen(manifestFile, outputDir) {
281
+ let addon = getAddon();
282
+ return addon.subgraphBundledCodegen(manifestFile, Stdlib_Null.fromOption(outputDir));
283
+ }
284
+
285
+ function subgraphBundledCodegenCurrent(manifestFile, outputDir) {
286
+ return getAddon().subgraphBundledCodegenCurrent(manifestFile, outputDir);
287
+ }
288
+
289
+ function subgraphMissingGraphCliMessage(generated) {
290
+ return getAddon().subgraphMissingGraphCliMessage(generated);
291
+ }
292
+
293
+ function subgraphFillGenerated(root, manifestFile, outputDir, wanted) {
294
+ return getAddon().subgraphFillGenerated(root, manifestFile, outputDir, wanted);
295
+ }
296
+
297
+ function subgraphWorkspacePackages(root) {
298
+ return getAddon().subgraphWorkspacePackages(root);
299
+ }
300
+
301
+ function subgraphWorkspaceRoot(root) {
302
+ return getAddon().subgraphWorkspaceRoot(root);
303
+ }
304
+
305
+ function subgraphScriptsWriting(dir, needle) {
306
+ return getAddon().subgraphScriptsWriting(dir, needle);
307
+ }
308
+
235
309
  function runCli(args) {
236
310
  let addon = getAddon();
237
311
  return addon.runCli(args, envioPackageDir);
@@ -251,8 +325,23 @@ export {
251
325
  loadAddon,
252
326
  addonRef,
253
327
  getAddon,
328
+ portsServedHere,
254
329
  getConfigJson,
255
330
  fromUserApi,
331
+ fromSubgraph,
332
+ subgraphFileToJavascript,
333
+ subgraphRegisterHandlers,
334
+ subgraphSureCreates,
335
+ subgraphKeccak256,
336
+ subgraphAbiDecode,
337
+ subgraphAbiEncodeCall,
338
+ subgraphBundledCodegen,
339
+ subgraphBundledCodegenCurrent,
340
+ subgraphMissingGraphCliMessage,
341
+ subgraphFillGenerated,
342
+ subgraphWorkspacePackages,
343
+ subgraphWorkspaceRoot,
344
+ subgraphScriptsWriting,
256
345
  runCli,
257
346
  }
258
347
  /* envioPackageDir Not a pure module */
@@ -24,11 +24,21 @@ type t = {
24
24
  mutable holdRealtime: bool,
25
25
  }
26
26
 
27
- // The whole-indexer fetch buffer pool, independent of chain count.
27
+ // The whole-indexer fetch buffer pool, independent of chain count. A subgraph
28
+ // with templates keeps far more per fetched event than a handler run does: a
29
+ // register pass with its pending contract calls, and (for a chain kept open by
30
+ // a template) responses well past the block the handlers are at. Venus on BSC
31
+ // held 100k of them and its heap passed 4 GB, so the default there is a tenth
32
+ // of that. Without templates there is neither, and a pool that small leaves
33
+ // one query in flight at a time: fetching stops overlapping processing.
34
+ let defaultSubgraphTargetBufferSize = 10_000
28
35
  let calculateTargetBufferSize = () =>
29
36
  switch Env.targetBufferSize {
30
37
  | Some(size) => size
31
- | None => 100_000
38
+ | None =>
39
+ Env.subgraphMode.contents && Env.subgraphHasTemplates.contents
40
+ ? defaultSubgraphTargetBufferSize
41
+ : 100_000
32
42
  }
33
43
 
34
44
  let make = (
@@ -15,15 +15,15 @@ import * as SafeCheckpointTracking from "./SafeCheckpointTracking.res.mjs";
15
15
  function calculateTargetBufferSize() {
16
16
  if (Env.targetBufferSize !== undefined) {
17
17
  return Env.targetBufferSize;
18
+ } else if (Env.subgraphMode.contents && Env.subgraphHasTemplates.contents) {
19
+ return 10000;
18
20
  } else {
19
21
  return 100000;
20
22
  }
21
23
  }
22
24
 
23
25
  function make(chainStates, isRealtime, targetBufferSizeOpt, holdRealtimeOpt) {
24
- let targetBufferSize = targetBufferSizeOpt !== undefined ? targetBufferSizeOpt : (
25
- Env.targetBufferSize !== undefined ? Env.targetBufferSize : 100000
26
- );
26
+ let targetBufferSize = targetBufferSizeOpt !== undefined ? targetBufferSizeOpt : calculateTargetBufferSize();
27
27
  let holdRealtime = holdRealtimeOpt !== undefined ? holdRealtimeOpt : false;
28
28
  return {
29
29
  chainStates: chainStates,
package/src/Ecosystem.res CHANGED
@@ -85,6 +85,12 @@ let loggerForItem = (item: Internal.item, ~ecosystem: t, ~logger: Logger.t): Log
85
85
  )
86
86
  }
87
87
 
88
+ let makeKeyOnlyBlock = (~blockNumber: int, ~ecosystem: t): Internal.eventBlock => {
89
+ let keyOnly = Dict.make()
90
+ keyOnly->Dict.set(ecosystem.blockNumberName, blockNumber->(Utils.magic: int => unknown))
91
+ keyOnly->(Utils.magic: dict<unknown> => Internal.eventBlock)
92
+ }
93
+
88
94
  // `block` is the item's materialised selection, which already carries the key;
89
95
  // without one the handler selected nothing but the key.
90
96
  let makeOnBlockArgs = (
@@ -98,10 +104,7 @@ let makeOnBlockArgs = (
98
104
  | Evm | Fuel =>
99
105
  let block = switch block {
100
106
  | Some(block) => block
101
- | None =>
102
- let keyOnly = Dict.make()
103
- keyOnly->Dict.set(ecosystem.blockNumberName, blockNumber->(Utils.magic: int => unknown))
104
- keyOnly->(Utils.magic: dict<unknown> => Internal.eventBlock)
107
+ | None => makeKeyOnlyBlock(~blockNumber, ~ecosystem)
105
108
  }
106
109
  {block, context}
107
110
  }
@@ -23,6 +23,12 @@ function loggerForItem(item, ecosystem, logger) {
23
23
  }
24
24
  }
25
25
 
26
+ function makeKeyOnlyBlock(blockNumber, ecosystem) {
27
+ let keyOnly = {};
28
+ keyOnly[ecosystem.blockNumberName] = blockNumber;
29
+ return keyOnly;
30
+ }
31
+
26
32
  function makeOnBlockArgs(blockNumber, block, ecosystem, context) {
27
33
  let match = ecosystem.name;
28
34
  switch (match) {
@@ -36,14 +42,7 @@ function makeOnBlockArgs(blockNumber, block, ecosystem, context) {
36
42
  context: context
37
43
  };
38
44
  }
39
- let block$1;
40
- if (block !== undefined) {
41
- block$1 = Primitive_option.valFromOption(block);
42
- } else {
43
- let keyOnly = {};
44
- keyOnly[ecosystem.blockNumberName] = blockNumber;
45
- block$1 = keyOnly;
46
- }
45
+ let block$1 = block !== undefined ? Primitive_option.valFromOption(block) : makeKeyOnlyBlock(blockNumber, ecosystem);
47
46
  return {
48
47
  block: Primitive_option.some(block$1),
49
48
  context: context
@@ -53,6 +52,7 @@ function makeOnBlockArgs(blockNumber, block, ecosystem, context) {
53
52
  export {
54
53
  getItemEvent,
55
54
  loggerForItem,
55
+ makeKeyOnlyBlock,
56
56
  makeOnBlockArgs,
57
57
  }
58
58
  /* Logger Not a pure module */