envio 3.13.0-rc.0 → 3.14.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 (119) hide show
  1. package/bin.mjs +10 -1
  2. package/index.d.ts +11 -0
  3. package/package.json +8 -20
  4. package/rescript.json +1 -4
  5. package/src/BatchProcessing.res +0 -2
  6. package/src/ChainState.res +39 -25
  7. package/src/ChainState.res.mjs +26 -23
  8. package/src/ChainState.resi +1 -2
  9. package/src/Config.res +78 -100
  10. package/src/Config.res.mjs +55 -64
  11. package/src/Core.res +67 -6
  12. package/src/Core.res.mjs +58 -4
  13. package/src/CrossChainState.res +13 -6
  14. package/src/CrossChainState.res.mjs +17 -4
  15. package/src/EventConfigBuilder.res +4 -10
  16. package/src/EventConfigBuilder.res.mjs +1 -3
  17. package/src/EventProcessing.res +6 -6
  18. package/src/EventProcessing.res.mjs +8 -6
  19. package/src/ExitOnCaughtUp.res +5 -1
  20. package/src/ExitOnCaughtUp.res.mjs +8 -3
  21. package/src/FinalizeBackfill.res +16 -10
  22. package/src/FinalizeBackfill.res.mjs +16 -5
  23. package/src/HandlerLoader.res +98 -36
  24. package/src/HandlerLoader.res.mjs +89 -24
  25. package/src/HandlerTypeCheck.mjs +14 -0
  26. package/src/HandlerTypeCheckWorker.mjs +68 -0
  27. package/src/Internal.res +1 -1
  28. package/src/LoadLayer.res +39 -7
  29. package/src/LoadLayer.res.mjs +65 -38
  30. package/src/LoadLayer.resi +28 -0
  31. package/src/Main.res +17 -12
  32. package/src/Main.res.mjs +9 -3
  33. package/src/NodeVersion.mjs +13 -0
  34. package/src/Persistence.res +79 -38
  35. package/src/Persistence.res.mjs +41 -10
  36. package/src/PgStorage.res +86 -39
  37. package/src/PgStorage.res.mjs +83 -32
  38. package/src/ResumePlan.res +172 -0
  39. package/src/ResumePlan.res.mjs +122 -0
  40. package/src/Supervisor.res +8 -8
  41. package/src/Supervisor.res.mjs +6 -1
  42. package/src/SyncWrites.res +86 -0
  43. package/src/SyncWrites.res.mjs +85 -0
  44. package/src/TestIndexer.res +19 -6
  45. package/src/TestIndexer.res.mjs +5 -4
  46. package/src/TsModuleHooks.mjs +121 -0
  47. package/src/UserContext.res +377 -62
  48. package/src/UserContext.res.mjs +297 -39
  49. package/src/Utils.res +0 -8
  50. package/src/Worker.res +8 -0
  51. package/src/Worker.res.mjs +11 -0
  52. package/src/bindings/NodeJs.res +8 -7
  53. package/src/bindings/NodeJs.res.mjs +0 -3
  54. package/src/bindings/Pino.res +2 -2
  55. package/src/db/InternalTable.res +52 -2
  56. package/src/db/InternalTable.res.mjs +32 -3
  57. package/src/db/Table.res +10 -0
  58. package/src/db/Table.res.mjs +22 -11
  59. package/src/sources/FuelHyperSync.res +2 -0
  60. package/src/sources/FuelHyperSync.res.mjs +1 -0
  61. package/src/sources/FuelHyperSync.resi +1 -0
  62. package/src/sources/FuelHyperSyncClient.res +25 -8
  63. package/src/sources/FuelHyperSyncClient.res.mjs +8 -2
  64. package/src/sources/FuelHyperSyncSource.res +24 -22
  65. package/src/sources/FuelHyperSyncSource.res.mjs +18 -13
  66. package/src/subgraph/abi-types.ts +63 -0
  67. package/src/subgraph/assemblyscript.ts +85 -0
  68. package/src/subgraph/blocks.ts +183 -0
  69. package/src/subgraph/calls.ts +149 -0
  70. package/src/subgraph/conformance.ts +83 -0
  71. package/src/subgraph/errors.ts +96 -0
  72. package/src/subgraph/graph-cli-worker.mjs +26 -0
  73. package/src/subgraph/graph-cli.ts +190 -0
  74. package/src/subgraph/graph-ts-enums.ts +28 -0
  75. package/src/subgraph/graph-ts-types/VERSION +2 -0
  76. package/src/subgraph/graph-ts-types/chain/arweave.d.ts +70 -0
  77. package/src/subgraph/graph-ts-types/chain/cosmos.d.ts +327 -0
  78. package/src/subgraph/graph-ts-types/chain/ethereum.d.ts +233 -0
  79. package/src/subgraph/graph-ts-types/chain/near.d.ts +253 -0
  80. package/src/subgraph/graph-ts-types/chain/starknet.d.ts +32 -0
  81. package/src/subgraph/graph-ts-types/common/collections.d.ts +136 -0
  82. package/src/subgraph/graph-ts-types/common/conversion.d.ts +11 -0
  83. package/src/subgraph/graph-ts-types/common/datasource.d.ts +30 -0
  84. package/src/subgraph/graph-ts-types/common/eager-offset.d.ts +0 -0
  85. package/src/subgraph/graph-ts-types/common/json.d.ts +17 -0
  86. package/src/subgraph/graph-ts-types/common/numbers.d.ts +120 -0
  87. package/src/subgraph/graph-ts-types/common/value.d.ts +120 -0
  88. package/src/subgraph/graph-ts-types/common/yaml.d.ts +90 -0
  89. package/src/subgraph/graph-ts-types/global/global.d.ts +194 -0
  90. package/src/subgraph/graph-ts-types/helper-functions.d.ts +22 -0
  91. package/src/subgraph/graph-ts-types/index.d.ts +102 -0
  92. package/src/subgraph/graph-ts.ts +2285 -0
  93. package/src/subgraph/hosts.ts +158 -0
  94. package/src/subgraph/rpc.ts +65 -0
  95. package/src/subgraph/runtime.ts +595 -0
  96. package/src/subgraph/scope.ts +68 -0
  97. package/src/tui/InitApi.res +85 -0
  98. package/src/tui/{components/CustomHooks.res.mjs → InitApi.res.mjs} +11 -64
  99. package/src/tui/Tui.res +142 -249
  100. package/src/tui/Tui.res.mjs +123 -332
  101. package/src/Js.shim.ts +0 -11
  102. package/src/bindings/DateFns.res +0 -74
  103. package/src/bindings/DateFns.res.mjs +0 -22
  104. package/src/sources/FuelSDK.res +0 -38
  105. package/src/sources/FuelSDK.res.mjs +0 -27
  106. package/src/sources/vendored-fuel-abi-coder.js +0 -1792
  107. package/src/tui/bindings/Ink.res +0 -369
  108. package/src/tui/bindings/Ink.res.mjs +0 -66
  109. package/src/tui/bindings/Style.res +0 -123
  110. package/src/tui/bindings/Style.res.mjs +0 -2
  111. package/src/tui/components/BufferedProgressBar.res +0 -40
  112. package/src/tui/components/BufferedProgressBar.res.mjs +0 -57
  113. package/src/tui/components/CustomHooks.res +0 -122
  114. package/src/tui/components/Messages.res +0 -40
  115. package/src/tui/components/Messages.res.mjs +0 -71
  116. package/src/tui/components/SyncETA.res +0 -179
  117. package/src/tui/components/SyncETA.res.mjs +0 -249
  118. package/src/tui/components/TuiData.res +0 -98
  119. package/src/tui/components/TuiData.res.mjs +0 -73
@@ -18,7 +18,6 @@ import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
18
18
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
19
19
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
20
20
  import * as ContractMapping from "./ContractMapping.res.mjs";
21
- import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
22
21
  import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
23
22
  import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
24
23
  import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
@@ -439,6 +438,7 @@ let publicConfigSchema = S$RescriptSchema.schema(s => ({
439
438
  handlers: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
440
439
  isDev: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
441
440
  isolatedChains: s.m(S$RescriptSchema.option(S$RescriptSchema.array(ChainId.schema))),
441
+ projectFlags: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
442
442
  fullBatchSize: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
443
443
  rollbackOnReorg: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
444
444
  saveFullHistory: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
@@ -450,7 +450,8 @@ let publicConfigSchema = S$RescriptSchema.schema(s => ({
450
450
  fuel: s.m(S$RescriptSchema.option(publicConfigEcosystemSchema)),
451
451
  svm: s.m(S$RescriptSchema.option(publicConfigEcosystemSchema)),
452
452
  enums: s.m(S$RescriptSchema.option(S$RescriptSchema.dict(S$RescriptSchema.array(S$RescriptSchema.string)))),
453
- entities: s.m(S$RescriptSchema.option(S$RescriptSchema.array(entityJsonSchema)))
453
+ entities: s.m(S$RescriptSchema.option(S$RescriptSchema.array(entityJsonSchema))),
454
+ subgraph: s.m(S$RescriptSchema.option(S$RescriptSchema.json(false)))
454
455
  }));
455
456
 
456
457
  function contractMappingOf(chainConfigs) {
@@ -495,6 +496,42 @@ function isolate(config, chainIds) {
495
496
  return newrecord;
496
497
  }
497
498
 
499
+ let commandFields = [
500
+ "isDev",
501
+ "isolatedChains",
502
+ "projectFlags"
503
+ ];
504
+
505
+ function withProjectFlags(command, config) {
506
+ let flags = config.projectFlags;
507
+ if (flags === "") {
508
+ return command;
509
+ } else {
510
+ return command + ` ` + flags;
511
+ }
512
+ }
513
+
514
+ let ecosystemFields = [
515
+ "evm",
516
+ "fuel",
517
+ "svm"
518
+ ];
519
+
520
+ function toEnvioInfo(publicConfigJson) {
521
+ let envioInfo = JSON.parse(JSON.stringify(publicConfigJson));
522
+ if (typeof envioInfo === "object" && envioInfo !== null && !Array.isArray(envioInfo)) {
523
+ commandFields.forEach(field => Utils.Dict.deleteInPlace(envioInfo, field));
524
+ Utils.Dict.deleteInPlace(envioInfo, "subgraph");
525
+ ecosystemFields.forEach(ecosystem => {
526
+ let match = envioInfo[ecosystem];
527
+ if (typeof match === "object" && match !== null && !Array.isArray(match)) {
528
+ return Utils.Dict.deleteInPlace(match, "chains");
529
+ }
530
+ });
531
+ }
532
+ return envioInfo;
533
+ }
534
+
498
535
  function fromPublic(publicConfigJson) {
499
536
  let publicConfig;
500
537
  try {
@@ -801,7 +838,10 @@ function fromPublic(publicConfigJson) {
801
838
  let config_enableRawEvents = Stdlib_Option.getOr(publicConfig.rawEvents, false);
802
839
  let config_batchSize = Stdlib_Option.getOr(publicConfig.fullBatchSize, 5000);
803
840
  let config_isDev = Stdlib_Option.getOr(publicConfig.isDev, false);
841
+ let config_projectFlags = Stdlib_Option.getOr(publicConfig.projectFlags, "");
804
842
  let config_checkpointSequence = CheckpointSequence.fromEntities(userEntities);
843
+ let config_envioInfo = toEnvioInfo(publicConfigJson);
844
+ let config_subgraph = publicConfig.subgraph;
805
845
  let config = {
806
846
  name: config_name,
807
847
  description: config_description,
@@ -823,11 +863,14 @@ function fromPublic(publicConfigJson) {
823
863
  reorgThresholdReadyTolerance: 100,
824
864
  lowercaseAddresses: lowercaseAddresses,
825
865
  isDev: config_isDev,
866
+ projectFlags: config_projectFlags,
826
867
  isolated: false,
827
868
  userEntitiesByName: userEntitiesByName,
828
869
  userEntities: userEntities,
829
870
  allEnums: allEnums,
830
- checkpointSequence: config_checkpointSequence
871
+ checkpointSequence: config_checkpointSequence,
872
+ envioInfo: config_envioInfo,
873
+ subgraph: config_subgraph
831
874
  };
832
875
  let chainIds = publicConfig.isolatedChains;
833
876
  if (chainIds !== undefined) {
@@ -933,44 +976,6 @@ function getPublicConfigJson() {
933
976
  }
934
977
  }
935
978
 
936
- function stripSensitiveData(json) {
937
- let cloned = JSON.parse(JSON.stringify(json));
938
- let stripChains = ecosystem => {
939
- if (ecosystem === undefined) {
940
- return;
941
- }
942
- if (typeof ecosystem !== "object" || ecosystem === null || Array.isArray(ecosystem)) {
943
- return;
944
- }
945
- let match = ecosystem["chains"];
946
- if (match === undefined) {
947
- return;
948
- }
949
- if (typeof match !== "object" || match === null || Array.isArray(match)) {
950
- return;
951
- }
952
- Object.values(match).forEach(chainJson => {
953
- if (typeof chainJson !== "object" || chainJson === null || Array.isArray(chainJson)) {
954
- return;
955
- }
956
- Utils.Dict.deleteInPlace(chainJson, "rpcs");
957
- Utils.Dict.deleteInPlace(chainJson, "hypersync");
958
- });
959
- };
960
- if (typeof cloned === "object" && cloned !== null && !Array.isArray(cloned)) {
961
- Utils.Dict.deleteInPlace(cloned, "isDev");
962
- Utils.Dict.deleteInPlace(cloned, "isolatedChains");
963
- stripChains(cloned["evm"]);
964
- stripChains(cloned["fuel"]);
965
- stripChains(cloned["svm"]);
966
- }
967
- return cloned;
968
- }
969
-
970
- function envioInfo() {
971
- return stripSensitiveData(getPublicConfigJson());
972
- }
973
-
974
979
  function canonicalJson(json) {
975
980
  if (Array.isArray(json)) {
976
981
  return json.map(canonicalJson);
@@ -1088,7 +1093,8 @@ function diffPaths(stored, current) {
1088
1093
  [
1089
1094
  "evm",
1090
1095
  "fuel",
1091
- "svm"
1096
+ "svm",
1097
+ "chains"
1092
1098
  ],
1093
1099
  ["entities"]
1094
1100
  ];
@@ -1113,10 +1119,7 @@ function diffPaths(stored, current) {
1113
1119
  return acc;
1114
1120
  }
1115
1121
 
1116
- function throwIfIncompatible(changedPaths, resetCommand, runCommand, hasClickhouse) {
1117
- if (changedPaths.length === 0) {
1118
- return;
1119
- }
1122
+ function incompatibleMessage(changedPaths, resetCommand, runCommand, hasClickhouse) {
1120
1123
  let bullets = changedPaths.map(p => ` - ` + p).join("\n");
1121
1124
  let option1 = "Revert the changes above";
1122
1125
  let padTo = (s, col) => s + " ".repeat(Math.max(col - s.length | 0, 1));
@@ -1128,20 +1131,7 @@ function throwIfIncompatible(changedPaths, resetCommand, runCommand, hasClickhou
1128
1131
  } else {
1129
1132
  option3 = "";
1130
1133
  }
1131
- Stdlib_JsError.throwWithMessage(`The following config changes are incompatible with the existing indexer data:\n\n` + bullets + `\n\nPick one:\n 1. ` + padTo(option1, col) + `# resume indexing where it left off\n 2. ` + padTo(resetCommand, col) + `# delete all indexed data and start over` + option3);
1132
- }
1133
-
1134
- function throwIfResumeIncompatible(storedEnvioInfo, storedContractMapping, envioInfo, contractMapping, resetCommand, runCommand) {
1135
- let changedPaths = storedEnvioInfo !== undefined ? diffPaths(storedEnvioInfo, envioInfo) : ["storage was initialized by an older envio version"];
1136
- let changedPaths$1 = ContractMapping.isEqual(storedContractMapping, contractMapping) ? changedPaths : changedPaths.concat(["contracts"]);
1137
- let hasClickhouse;
1138
- if (typeof envioInfo === "object" && envioInfo !== null && !Array.isArray(envioInfo)) {
1139
- let match = envioInfo["storage"];
1140
- hasClickhouse = typeof match === "object" && match !== null && !Array.isArray(match) ? Primitive_object.equal(match["clickhouse"], true) : false;
1141
- } else {
1142
- hasClickhouse = false;
1143
- }
1144
- throwIfIncompatible(changedPaths$1, resetCommand, runCommand, hasClickhouse);
1134
+ return `The following config changes are incompatible with the existing indexer data:\n\n` + bullets + `\n\nPick one:\n 1. ` + padTo(option1, col) + `# resume indexing where it left off\n 2. ` + padTo(resetCommand, col) + `# delete all indexed data and start over` + option3;
1145
1135
  }
1146
1136
 
1147
1137
  function load() {
@@ -1195,6 +1185,10 @@ export {
1195
1185
  getChain,
1196
1186
  isPerChain,
1197
1187
  isolate,
1188
+ commandFields,
1189
+ withProjectFlags,
1190
+ ecosystemFields,
1191
+ toEnvioInfo,
1198
1192
  fromPublic,
1199
1193
  normalizeUserAddress,
1200
1194
  normalizeSimulateAddress,
@@ -1202,12 +1196,9 @@ export {
1202
1196
  prime,
1203
1197
  withCommandFields,
1204
1198
  getPublicConfigJson,
1205
- stripSensitiveData,
1206
- envioInfo,
1207
1199
  canonicalJson,
1208
1200
  diffPaths,
1209
- throwIfIncompatible,
1210
- throwIfResumeIncompatible,
1201
+ incompatibleMessage,
1211
1202
  load,
1212
1203
  getPgUserEntities,
1213
1204
  }
package/src/Core.res CHANGED
@@ -12,6 +12,7 @@ type transactionStoreCtor
12
12
  type blockStoreCtor
13
13
  type clickHouseSinkCtor
14
14
  type addressStoreCtor
15
+ type tuiCtor
15
16
  // Test-only: a local HyperSync server, bound by MockHyperSyncServer in envio-tests.
16
17
  type mockHyperSyncServerCtor
17
18
  type fromUserApiOptions = {
@@ -27,12 +28,25 @@ type fromUserApiResult = {
27
28
  indexerCode: Null.t<string>,
28
29
  }
29
30
 
31
+ type fromSubgraphOptions = {
32
+ name?: string,
33
+ env?: dict<string>,
34
+ files?: dict<string>,
35
+ root?: string,
36
+ }
37
+
30
38
  type addon = {
31
39
  getConfigJson: (~configPath: Null.t<string>, ~directory: Null.t<string>) => string,
40
+ fromSubgraph: (string, string, fromSubgraphOptions) => fromUserApiResult,
41
+ subgraphFileToJavascript: (string, string) => string,
32
42
  encodeIndexedTopic: (~abiType: string, ~value: unknown) => EvmTypes.Hex.t,
33
43
  isSvmPubkey: (~value: string) => bool,
34
44
  fromUserApi: (string, fromUserApiOptions) => fromUserApiResult,
35
45
  runCli: (~args: array<string>, ~envioPackageDir: Null.t<string>) => promise<Null.t<string>>,
46
+ loadTs: string => string,
47
+ tsCheckHandlerFormat: string => unit,
48
+ tsResolveCandidates: (string, Null.t<string>) => array<string>,
49
+ tsNotFoundCandidates: (string, Null.t<string>, string) => array<string>,
36
50
  @as("EvmHyperSyncClient")
37
51
  evmHyperSyncClient: evmHyperSyncClientCtor,
38
52
  @as("EvmRpcClient")
@@ -49,6 +63,8 @@ type addon = {
49
63
  addressStore: addressStoreCtor,
50
64
  @as("ClickHouseSink")
51
65
  clickHouseSink: clickHouseSinkCtor,
66
+ @as("Tui")
67
+ tui: tuiCtor,
52
68
  @as("MockHyperSyncServer")
53
69
  mockHyperSyncServer: mockHyperSyncServerCtor,
54
70
  encodeAddresses: (~ecosystem: string, ~addresses: array<Address.t>) => array<NodeJs.Buffer.t>,
@@ -99,7 +115,7 @@ let callRequire: ({..}, string) => addon = %raw(`(req, id) => req(id)`)
99
115
  let envioPackageDir = pathDirname(pathDirname(fileURLToPath(importMetaUrl)))
100
116
 
101
117
  // Runs `cargo build` on every invocation (like `cargo run`).
102
- let loadDevAddon: ({..}, string) => addon = %raw(`function(req, envioDir) {
118
+ let loadDevAddon: ({..}, string) => Null.t<addon> = %raw(`function(req, envioDir) {
103
119
  var cp = Nodechild_process;
104
120
  var path = Nodepath;
105
121
  var fs = Nodefs;
@@ -177,6 +193,22 @@ let loadDevAddon: ({..}, string) => addon = %raw(`function(req, envioDir) {
177
193
  // `code`, and any other fields a diagnostic might rely on.
178
194
  let rethrow: JsExn.t => 'a = %raw(`function(e) { throw e }`)
179
195
 
196
+ type packageJson = {version: string}
197
+ let requirePackageJson: ({..}, string) => packageJson = %raw(`(req, p) => req(p)`)
198
+ let devVersion = "0.0.1-dev"
199
+
200
+ let isGlibc: unit => bool = %raw(`() => Boolean(process.report?.getReport().header.glibcVersionRuntime)`)
201
+
202
+ @val external npmUserAgent: option<string> = "process.env.npm_config_user_agent"
203
+
204
+ let addCommand = () =>
205
+ switch npmUserAgent {
206
+ | Some(ua) if ua->String.startsWith("pnpm/") => "pnpm add"
207
+ | Some(ua) if ua->String.startsWith("yarn/") => "yarn add"
208
+ | Some(ua) if ua->String.startsWith("bun/") => "bun add"
209
+ | _ => "npm install"
210
+ }
211
+
180
212
  let loadAddon = () => {
181
213
  let req = createRequire(importMetaUrl)
182
214
 
@@ -212,15 +244,32 @@ let loadAddon = () => {
212
244
  switch tryRequire(0) {
213
245
  | Some(addon) => addon
214
246
  | None =>
215
- // Dev build fallback (cargo build on every run)
216
- switch loadDevAddon(req, envioPackageDir)->(Utils.magic: addon => option<addon>) {
247
+ let version = requirePackageJson(req, "../package.json").version
248
+ // Publishing stamps the real version, so only a monorepo checkout (or a
249
+ // `file:` link to one) can have a dev build to fall back to. Skipping it
250
+ // spares published installs a `pnpm list` spawn before the error below.
251
+ let devAddon = if version === devVersion {
252
+ loadDevAddon(req, envioPackageDir)->Null.toOption
253
+ } else {
254
+ None
255
+ }
256
+ switch devAddon {
217
257
  | Some(addon) => addon
218
258
  | None =>
219
259
  let host = `${processPlatform}-${processArch}`
220
- let msg = if candidates->Array.length === 0 {
260
+ let msg = switch candidates {
261
+ | []
262
+ if processPlatform === "win32" => `envio doesn't run natively on Windows. Use WSL 2 instead: https://learn.microsoft.com/windows/wsl/install`
263
+ | [] =>
221
264
  `envio doesn't support ${host}. Supported: linux-x64 (glibc/musl), linux-arm64, darwin-x64, darwin-arm64.`
222
- } else {
223
- `Couldn't load the envio native addon for ${host}. Reinstall envio (ensure optional dependencies aren't skipped).`
265
+ | _ =>
266
+ let pkg = if processPlatform === "linux" && processArch === "x64" && !isGlibc() {
267
+ `envio-linux-x64-musl`
268
+ } else {
269
+ candidates->Array.getUnsafe(0)
270
+ }
271
+ `envio's native binary for ${host} isn't installed (package "${pkg}"). This happens when optional dependencies are skipped (--omit=optional, --no-optional) or the lockfile was generated on another platform.
272
+ Reinstall dependencies, or add the package explicitly: ${addCommand()} ${pkg}@${version}`
224
273
  }
225
274
  JsError.throwWithMessage(msg)
226
275
  }
@@ -265,6 +314,18 @@ let fromUserApi = (~schema=?, ~env=?, ~files=?, ~withIndexerTypes=false, yaml) =
265
314
  )
266
315
  }
267
316
 
317
+ /// Parses a subgraph project without touching the filesystem: subgraph.yaml and
318
+ /// its schema inline, ABI bodies through `files`.
319
+ let fromSubgraph = (~name=?, ~env=?, ~files=?, ~root=?, ~manifest, ~schema) => {
320
+ let addon = getAddon()
321
+ addon.fromSubgraph(manifest, schema, {?name, ?env, ?files, ?root})
322
+ }
323
+
324
+ let subgraphFileToJavascript = (~source, ~path) => {
325
+ let addon = getAddon()
326
+ addon.subgraphFileToJavascript(source, path)
327
+ }
328
+
268
329
  let runCli = args => {
269
330
  let addon = getAddon()
270
331
  addon.runCli(~args, ~envioPackageDir=Null.make(envioPackageDir))
package/src/Core.res.mjs CHANGED
@@ -6,6 +6,7 @@ import * as Nodepath from "node:path";
6
6
  import * as Stdlib_Null from "@rescript/runtime/lib/es6/Stdlib_Null.js";
7
7
  import * as Nodemodule from "node:module";
8
8
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
9
+ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
9
10
  import * as Nodechild_process from "node:child_process";
10
11
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
11
12
 
@@ -97,6 +98,29 @@ let loadDevAddon = (function(req, envioDir) {
97
98
 
98
99
  let rethrow = (function(e) { throw e });
99
100
 
101
+ let requirePackageJson = ((req, p) => req(p));
102
+
103
+ let devVersion = "0.0.1-dev";
104
+
105
+ let isGlibc = (() => Boolean(process.report?.getReport().header.glibcVersionRuntime));
106
+
107
+ function addCommand() {
108
+ let ua = process.env.npm_config_user_agent;
109
+ if (ua !== undefined) {
110
+ if (ua.startsWith("pnpm/")) {
111
+ return "pnpm add";
112
+ } else if (ua.startsWith("yarn/")) {
113
+ return "yarn add";
114
+ } else if (ua.startsWith("bun/")) {
115
+ return "bun add";
116
+ } else {
117
+ return "npm install";
118
+ }
119
+ } else {
120
+ return "npm install";
121
+ }
122
+ }
123
+
100
124
  function loadAddon() {
101
125
  let req = Nodemodule.createRequire(import.meta.url);
102
126
  let match = process.platform;
@@ -161,12 +185,21 @@ function loadAddon() {
161
185
  if (addon !== undefined) {
162
186
  return addon;
163
187
  }
164
- let addon$1 = loadDevAddon(req, envioPackageDir);
165
- if (addon$1 !== undefined) {
166
- return addon$1;
188
+ let version = requirePackageJson(req, "../package.json").version;
189
+ let devAddon = version === devVersion ? Primitive_option.fromNull(loadDevAddon(req, envioPackageDir)) : undefined;
190
+ if (devAddon !== undefined) {
191
+ return devAddon;
167
192
  }
168
193
  let host = process.platform + `-` + process.arch;
169
- return Stdlib_JsError.throwWithMessage(candidates.length === 0 ? `envio doesn't support ` + host + `. Supported: linux-x64 (glibc/musl), linux-arm64, darwin-x64, darwin-arm64.` : `Couldn't load the envio native addon for ` + host + `. Reinstall envio (ensure optional dependencies aren't skipped).`);
194
+ let tmp;
195
+ if (candidates.length !== 0) {
196
+ let pkg = process.platform === "linux" && process.arch === "x64" && !isGlibc() ? `envio-linux-x64-musl` : candidates[0];
197
+ tmp = `envio's native binary for ` + host + ` isn't installed (package "` + pkg + `"). This happens when optional dependencies are skipped (--omit=optional, --no-optional) or the lockfile was generated on another platform.
198
+ Reinstall dependencies, or add the package explicitly: ` + addCommand() + ` ` + pkg + `@` + version;
199
+ } else {
200
+ tmp = process.platform === "win32" ? `envio doesn't run natively on Windows. Use WSL 2 instead: https://learn.microsoft.com/windows/wsl/install` : `envio doesn't support ` + host + `. Supported: linux-x64 (glibc/musl), linux-arm64, darwin-x64, darwin-arm64.`;
201
+ }
202
+ return Stdlib_JsError.throwWithMessage(tmp);
170
203
  }
171
204
 
172
205
  let addonRef = {
@@ -199,6 +232,21 @@ function fromUserApi(schema, env, files, withIndexerTypesOpt, yaml) {
199
232
  });
200
233
  }
201
234
 
235
+ function fromSubgraph(name, env, files, root, manifest, schema) {
236
+ let addon = getAddon();
237
+ return addon.fromSubgraph(manifest, schema, {
238
+ name: name,
239
+ env: env,
240
+ files: files,
241
+ root: root
242
+ });
243
+ }
244
+
245
+ function subgraphFileToJavascript(source, path) {
246
+ let addon = getAddon();
247
+ return addon.subgraphFileToJavascript(source, path);
248
+ }
249
+
202
250
  function runCli(args) {
203
251
  let addon = getAddon();
204
252
  return addon.runCli(args, envioPackageDir);
@@ -211,11 +259,17 @@ export {
211
259
  envioPackageDir,
212
260
  loadDevAddon,
213
261
  rethrow,
262
+ requirePackageJson,
263
+ devVersion,
264
+ isGlibc,
265
+ addCommand,
214
266
  loadAddon,
215
267
  addonRef,
216
268
  getAddon,
217
269
  getConfigJson,
218
270
  fromUserApi,
271
+ fromSubgraph,
272
+ subgraphFileToJavascript,
219
273
  runCli,
220
274
  }
221
275
  /* envioPackageDir Not a pure module */
@@ -199,7 +199,7 @@ let applyBatchProgress = (crossChainState: t, ~batch: Batch.t, ~blockTimestampNa
199
199
  for i in 0 to chainIds->Array.length - 1 {
200
200
  let cs = crossChainState->getChainState(chainIds->Array.getUnsafe(i))
201
201
  cs->ChainState.applyBatchProgress(~batch, ~blockTimestampName)
202
- if !(cs->ChainState.hasProcessedToEndblock || cs->ChainState.isProgressAtHead) {
202
+ if !(cs->ChainState.hasCaughtUp) {
203
203
  everyChainCaughtUp := false
204
204
  }
205
205
  }
@@ -254,7 +254,7 @@ let markCaughtUpOnResume = (crossChainState: t) => {
254
254
  let everyChainCaughtUp = ref(crossChainState.chainIds->Array.length > 0)
255
255
  for i in 0 to crossChainState.chainIds->Array.length - 1 {
256
256
  let cs = crossChainState->getChainState(crossChainState.chainIds->Array.getUnsafe(i))
257
- if !(cs->ChainState.isDurablyCaughtUp) {
257
+ if !(cs->ChainState.hasCaughtUp) {
258
258
  everyChainCaughtUp := false
259
259
  }
260
260
  }
@@ -284,11 +284,19 @@ let markReady = (crossChainState: t, ~readyAt) => {
284
284
  crossChainState.isRealtime = true
285
285
  }
286
286
 
287
+ // What a caught-up chain is waiting on before its process can finalize: the run
288
+ // holding the process back, or another chain it drives still behind. Read when
289
+ // the chain speaks, so "waiting" is said only while it is true.
290
+ let isWaitingOnOthers = (crossChainState: t, cs: ChainState.t) =>
291
+ crossChainState.holdRealtime ||
292
+ crossChainState.chainStates
293
+ ->Dict.valuesToArray
294
+ ->Array.some(other => other !== cs && !(other->ChainState.hasCaughtUp))
295
+
287
296
  // Each chain that has just finished indexing, said once, by the chain it is
288
297
  // about — so a chain that finishes early says so then, rather than when the
289
298
  // last chain in its process catches up.
290
- let reportFinished = (crossChainState: t) => {
291
- let waitingOnOthers = crossChainState.holdRealtime || crossChainState.chainIds->Array.length > 1
299
+ let reportFinished = (crossChainState: t) =>
292
300
  crossChainState.chainStates
293
301
  ->Dict.valuesToArray
294
302
  ->Array.forEach(cs =>
@@ -301,7 +309,7 @@ let reportFinished = (crossChainState: t) => {
301
309
  cs
302
310
  ->ChainState.logger
303
311
  ->Logging.childInfo({
304
- "msg": waitingOnOthers
312
+ "msg": crossChainState->isWaitingOnOthers(cs)
305
313
  ? "Finished backfill. Waiting for the other chains."
306
314
  : "Finished backfill.",
307
315
  "block": block,
@@ -309,7 +317,6 @@ let reportFinished = (crossChainState: t) => {
309
317
  | None => ()
310
318
  }
311
319
  )
312
- }
313
320
 
314
321
  // --- Fetch control. ---
315
322
 
@@ -141,7 +141,7 @@ function applyBatchProgress(crossChainState, batch, blockTimestampName) {
141
141
  for (let i = 0, i_finish = chainIds.length; i < i_finish; ++i) {
142
142
  let cs = crossChainState.chainStates[chainIds[i]];
143
143
  ChainState.applyBatchProgress(cs, batch, blockTimestampName);
144
- if (!(ChainState.hasProcessedToEndblock(cs) || ChainState.isProgressAtHead(cs))) {
144
+ if (!ChainState.hasCaughtUp(cs)) {
145
145
  everyChainCaughtUp = false;
146
146
  }
147
147
  }
@@ -169,7 +169,7 @@ function markCaughtUpOnResume(crossChainState) {
169
169
  let everyChainCaughtUp = crossChainState.chainIds.length !== 0;
170
170
  for (let i = 0, i_finish = crossChainState.chainIds.length; i < i_finish; ++i) {
171
171
  let cs = crossChainState.chainStates[crossChainState.chainIds[i]];
172
- if (!ChainState.isDurablyCaughtUp(cs)) {
172
+ if (!ChainState.hasCaughtUp(cs)) {
173
173
  everyChainCaughtUp = false;
174
174
  }
175
175
  }
@@ -191,8 +191,21 @@ function markReady(crossChainState, readyAt) {
191
191
  crossChainState.isRealtime = true;
192
192
  }
193
193
 
194
+ function isWaitingOnOthers(crossChainState, cs) {
195
+ if (crossChainState.holdRealtime) {
196
+ return true;
197
+ } else {
198
+ return Object.values(crossChainState.chainStates).some(other => {
199
+ if (other !== cs) {
200
+ return !ChainState.hasCaughtUp(other);
201
+ } else {
202
+ return false;
203
+ }
204
+ });
205
+ }
206
+ }
207
+
194
208
  function reportFinished(crossChainState) {
195
- let waitingOnOthers = crossChainState.holdRealtime || crossChainState.chainIds.length > 1;
196
209
  Object.values(crossChainState.chainStates).forEach(cs => {
197
210
  let match = ChainState.takeFinished(cs);
198
211
  if (match !== undefined) {
@@ -203,7 +216,7 @@ function reportFinished(crossChainState) {
203
216
  });
204
217
  } else {
205
218
  return Logging.childInfo(ChainState.logger(cs), {
206
- msg: waitingOnOthers ? "Finished backfill. Waiting for the other chains." : "Finished backfill.",
219
+ msg: isWaitingOnOthers(crossChainState, cs) ? "Finished backfill. Waiting for the other chains." : "Finished backfill.",
207
220
  block: match._0
208
221
  });
209
222
  }
@@ -343,7 +343,7 @@ let validateFieldsShapeOrThrow = (
343
343
  }
344
344
 
345
345
  let selectionList = (fields: unknown, key: string): option<array<string>> =>
346
- switch (fields->(Utils.magic: unknown => dict<unknown>))->Dict.get(key) {
346
+ switch fields->(Utils.magic: unknown => dict<unknown>)->Dict.get(key) {
347
347
  | None => None
348
348
  | Some(value) => Some(value->(Utils.magic: unknown => array<string>))
349
349
  }
@@ -371,8 +371,8 @@ let parseFieldsOrThrow = (
371
371
  if !(valid->Utils.Set.has(name)) {
372
372
  JsError.throwWithMessage(
373
373
  `Invalid "${name}" field in the fields.${kind} option of ${registration}. Valid ${kind} fields: ${Utils.Array.quotedJoin(
374
- valid->Utils.Set.toArray,
375
- )}.`,
374
+ valid->Utils.Set.toArray,
375
+ )}.`,
376
376
  )
377
377
  }
378
378
  if seen->Utils.Set.has(name) {
@@ -858,13 +858,7 @@ let buildFuelEventConfig = (
858
858
  ~rawAbi: JSON.t,
859
859
  ): Internal.fuelEventConfig => {
860
860
  let fuelKind = switch kind {
861
- | "logData" =>
862
- // Transpile raw Fuel ABI to the format expected by the vendored ABI coder
863
- let abi = FuelSDK.transpileAbi(rawAbi)
864
- Internal.LogData({
865
- logId: sighash,
866
- decode: FuelSDK.Receipt.getLogDataDecoder(~abi, ~logId=sighash),
867
- })
861
+ | "logData" => Internal.LogData({logId: sighash, abi: rawAbi})
868
862
  | "mint" => Mint
869
863
  | "burn" => Burn
870
864
  | "transfer" => Transfer
@@ -6,7 +6,6 @@ import * as Core from "./Core.res.mjs";
6
6
  import * as Fuel from "./sources/Fuel.res.mjs";
7
7
  import * as Utils from "./Utils.res.mjs";
8
8
  import * as Address from "./Address.res.mjs";
9
- import * as FuelSDK from "./sources/FuelSDK.res.mjs";
10
9
  import * as Internal from "./Internal.res.mjs";
11
10
  import * as LogSelection from "./LogSelection.res.mjs";
12
11
  import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
@@ -590,11 +589,10 @@ function buildFuelEventConfig(contractName, eventName, kind, sighash, rawAbi) {
590
589
  fuelKind = "Call";
591
590
  break;
592
591
  case "logData" :
593
- let abi = FuelSDK.transpileAbi(rawAbi);
594
592
  fuelKind = {
595
593
  TAG: "LogData",
596
594
  logId: sighash,
597
- decode: FuelSDK.Receipt.getLogDataDecoder(abi, sighash)
595
+ abi: rawAbi
598
596
  };
599
597
  break;
600
598
  case "mint" :
@@ -51,7 +51,7 @@ let runEventHandlerOrThrow = async (
51
51
  isPreload: false,
52
52
  chains,
53
53
  config,
54
- isResolved: false,
54
+ sync: UserContext.makeSyncState(),
55
55
  }
56
56
  await handler(
57
57
  (
@@ -61,7 +61,7 @@ let runEventHandlerOrThrow = async (
61
61
  }: Internal.handlerArgs
62
62
  ),
63
63
  )
64
- contextParams.isResolved = true
64
+ contextParams.sync.status = Resolved
65
65
  } catch {
66
66
  | exn =>
67
67
  throw(
@@ -102,7 +102,7 @@ let runHandlerOrThrow = async (
102
102
  isPreload: false,
103
103
  chains,
104
104
  config,
105
- isResolved: false,
105
+ sync: UserContext.makeSyncState(),
106
106
  }
107
107
  await handler(
108
108
  Ecosystem.makeOnBlockArgs(
@@ -111,7 +111,7 @@ let runHandlerOrThrow = async (
111
111
  ~context=UserContext.getHandlerContext(contextParams),
112
112
  ),
113
113
  )
114
- contextParams.isResolved = true
114
+ contextParams.sync.status = Resolved
115
115
  } catch {
116
116
  | exn =>
117
117
  throw(
@@ -186,7 +186,7 @@ let preloadBatchOrThrow = async (
186
186
  checkpointId,
187
187
  isPreload: true,
188
188
  chains,
189
- isResolved: false,
189
+ sync: UserContext.makeSyncState(),
190
190
  config,
191
191
  }),
192
192
  })
@@ -221,7 +221,7 @@ let preloadBatchOrThrow = async (
221
221
  checkpointId,
222
222
  isPreload: true,
223
223
  chains,
224
- isResolved: false,
224
+ sync: UserContext.makeSyncState(),
225
225
  config,
226
226
  }),
227
227
  )