envio 3.9.0 → 3.10.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 (143) hide show
  1. package/evm.schema.json +26 -0
  2. package/fuel.schema.json +26 -0
  3. package/index.d.ts +41 -8
  4. package/package.json +6 -7
  5. package/src/Batch.res +9 -0
  6. package/src/ChainState.res +35 -39
  7. package/src/ChainState.res.mjs +14 -11
  8. package/src/ChainState.resi +15 -7
  9. package/src/Config.res +61 -44
  10. package/src/Config.res.mjs +56 -19
  11. package/src/Core.res +19 -0
  12. package/src/Core.res.mjs +11 -0
  13. package/src/CrossChainState.res +15 -23
  14. package/src/CrossChainState.res.mjs +10 -18
  15. package/src/CrossChainState.resi +4 -1
  16. package/src/Ecosystem.res +7 -2
  17. package/src/Envio.res +6 -4
  18. package/src/EventConfigBuilder.res +169 -26
  19. package/src/EventConfigBuilder.res.mjs +124 -15
  20. package/src/EventProcessing.res +6 -6
  21. package/src/EventProcessing.res.mjs +8 -6
  22. package/src/HandlerLoader.res +20 -8
  23. package/src/HandlerLoader.res.mjs +11 -2
  24. package/src/HandlerRegister.res +21 -4
  25. package/src/HandlerRegister.res.mjs +24 -5
  26. package/src/InMemoryStore.res +9 -7
  27. package/src/InMemoryStore.res.mjs +3 -3
  28. package/src/IndexerState.res +43 -6
  29. package/src/IndexerState.res.mjs +36 -7
  30. package/src/IndexerState.resi +4 -4
  31. package/src/Internal.res +16 -17
  32. package/src/Metrics.res +72 -6
  33. package/src/Metrics.res.mjs +30 -2
  34. package/src/Persistence.res +36 -30
  35. package/src/Persistence.res.mjs +1 -20
  36. package/src/PgStorage.res +104 -56
  37. package/src/PgStorage.res.mjs +57 -35
  38. package/src/PruneStaleHistory.res +85 -52
  39. package/src/PruneStaleHistory.res.mjs +63 -37
  40. package/src/Rollback.res +68 -45
  41. package/src/Rollback.res.mjs +38 -19
  42. package/src/RollbackCommit.res +7 -9
  43. package/src/RollbackCommit.res.mjs +5 -6
  44. package/src/SafeCheckpointTracking.res +11 -11
  45. package/src/SafeCheckpointTracking.res.mjs +7 -6
  46. package/src/SimulateItems.res +33 -18
  47. package/src/SimulateItems.res.mjs +26 -22
  48. package/src/Sink.res +38 -26
  49. package/src/Sink.res.mjs +21 -16
  50. package/src/TestIndexer.res +5 -5
  51. package/src/TestIndexer.res.mjs +1 -1
  52. package/src/UserContext.res +358 -51
  53. package/src/UserContext.res.mjs +271 -35
  54. package/src/Utils.res +170 -0
  55. package/src/Utils.res.mjs +153 -0
  56. package/src/Writing.res +2 -2
  57. package/src/Writing.res.mjs +1 -1
  58. package/src/bindings/ClickHouse.res +366 -698
  59. package/src/bindings/ClickHouse.res.mjs +371 -421
  60. package/src/bindings/ClickHouseSink.res +337 -0
  61. package/src/bindings/ClickHouseSink.res.mjs +246 -0
  62. package/src/bindings/EventSource.res +8 -2
  63. package/src/bindings/NodeJs.res +6 -0
  64. package/src/bindings/Vitest.res +23 -0
  65. package/src/bindings/Vitest.res.mjs +3 -0
  66. package/src/bindings/WebSocket.res +9 -10
  67. package/src/db/CheckpointBounds.res +53 -0
  68. package/src/db/CheckpointBounds.res.mjs +44 -0
  69. package/src/db/EntityFilter.res +36 -17
  70. package/src/db/EntityFilter.res.mjs +25 -14
  71. package/src/db/EntityHistory.res +47 -22
  72. package/src/db/EntityHistory.res.mjs +19 -12
  73. package/src/db/InternalTable.res +84 -35
  74. package/src/db/InternalTable.res.mjs +56 -23
  75. package/src/db/RollbackFloors.res +55 -0
  76. package/src/db/RollbackFloors.res.mjs +92 -0
  77. package/src/db/Table.res +22 -4
  78. package/src/db/Table.res.mjs +30 -9
  79. package/src/sources/Evm.res +2 -0
  80. package/src/sources/Evm.res.mjs +2 -0
  81. package/src/sources/EvmHyperSyncSource.res +3 -3
  82. package/src/sources/EvmHyperSyncSource.res.mjs +3 -3
  83. package/src/sources/EvmRpcWs.res +124 -0
  84. package/src/sources/EvmRpcWs.res.mjs +117 -0
  85. package/src/sources/Fuel.res +2 -0
  86. package/src/sources/Fuel.res.mjs +2 -0
  87. package/src/sources/FuelHyperSyncSource.res +1 -1
  88. package/src/sources/FuelHyperSyncSource.res.mjs +2 -1
  89. package/src/sources/HeightFeed.res +568 -0
  90. package/src/sources/HeightFeed.res.mjs +452 -0
  91. package/src/sources/HeightStream.res +257 -0
  92. package/src/sources/HeightStream.res.mjs +194 -0
  93. package/src/sources/HyperSync.res +5 -0
  94. package/src/sources/HyperSync.res.mjs +3 -0
  95. package/src/sources/HyperSync.resi +4 -0
  96. package/src/sources/HyperSyncSSE.res +49 -0
  97. package/src/sources/HyperSyncSSE.res.mjs +79 -0
  98. package/src/sources/RpcSource.res +1 -1
  99. package/src/sources/RpcSource.res.mjs +2 -2
  100. package/src/sources/Source.res +54 -1
  101. package/src/sources/Source.res.mjs +25 -0
  102. package/src/sources/SourceManager.res +220 -227
  103. package/src/sources/SourceManager.res.mjs +139 -164
  104. package/src/sources/SourceManager.resi +8 -0
  105. package/src/sources/Svm.res +2 -0
  106. package/src/sources/Svm.res.mjs +2 -0
  107. package/src/sources/SvmHyperSyncClient.res +70 -127
  108. package/src/sources/SvmHyperSyncClient.res.mjs +51 -25
  109. package/src/sources/SvmHyperSyncSource.res +18 -15
  110. package/src/sources/SvmHyperSyncSource.res.mjs +5 -4
  111. package/src/subgraph/blocks.ts +176 -0
  112. package/src/subgraph/calls.ts +217 -0
  113. package/src/subgraph/conformance.ts +102 -0
  114. package/src/subgraph/division.ts +133 -0
  115. package/src/subgraph/errors.ts +90 -0
  116. package/src/subgraph/graph-ts-types/VERSION +2 -0
  117. package/src/subgraph/graph-ts-types/chain/arweave.d.ts +70 -0
  118. package/src/subgraph/graph-ts-types/chain/cosmos.d.ts +327 -0
  119. package/src/subgraph/graph-ts-types/chain/ethereum.d.ts +233 -0
  120. package/src/subgraph/graph-ts-types/chain/near.d.ts +253 -0
  121. package/src/subgraph/graph-ts-types/chain/starknet.d.ts +32 -0
  122. package/src/subgraph/graph-ts-types/common/collections.d.ts +136 -0
  123. package/src/subgraph/graph-ts-types/common/conversion.d.ts +11 -0
  124. package/src/subgraph/graph-ts-types/common/datasource.d.ts +30 -0
  125. package/src/subgraph/graph-ts-types/common/eager-offset.d.ts +0 -0
  126. package/src/subgraph/graph-ts-types/common/json.d.ts +17 -0
  127. package/src/subgraph/graph-ts-types/common/numbers.d.ts +120 -0
  128. package/src/subgraph/graph-ts-types/common/value.d.ts +120 -0
  129. package/src/subgraph/graph-ts-types/common/yaml.d.ts +90 -0
  130. package/src/subgraph/graph-ts-types/global/global.d.ts +194 -0
  131. package/src/subgraph/graph-ts-types/helper-functions.d.ts +22 -0
  132. package/src/subgraph/graph-ts-types/index.d.ts +102 -0
  133. package/src/subgraph/graph-ts.ts +1948 -0
  134. package/src/subgraph/hosts.ts +148 -0
  135. package/src/subgraph/runtime.ts +863 -0
  136. package/src/subgraph/scope.ts +66 -0
  137. package/svm.schema.json +6 -81
  138. package/src/MemoryStorage.res +0 -729
  139. package/src/MemoryStorage.res.mjs +0 -586
  140. package/src/sources/HyperSyncHeightStream.res +0 -129
  141. package/src/sources/HyperSyncHeightStream.res.mjs +0 -110
  142. package/src/sources/RpcWebSocketHeightStream.res +0 -175
  143. package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -180
@@ -14,6 +14,7 @@ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
14
14
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
15
15
  import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
16
16
  import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
17
+ import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
17
18
 
18
19
  let paramMetaSchema = S$RescriptSchema.recursive(self => S$RescriptSchema.object(s => ({
19
20
  name: s.f("name", S$RescriptSchema.string),
@@ -261,17 +262,13 @@ let svmSelectionKinds = [
261
262
  "log"
262
263
  ];
263
264
 
264
- function quotedJoin(names) {
265
- return names.map(name => `"` + name + `"`).join(", ");
266
- }
267
-
268
265
  function validateFieldsShapeOrThrow(fields, registration, validKeys, shapeNoun) {
269
266
  if (typeof fields !== "object" || fields === null || Array.isArray(fields)) {
270
267
  Stdlib_JsError.throwWithMessage(`The fields option of ` + registration + ` must be an object of ` + shapeNoun + ` field names.`);
271
268
  }
272
269
  Object.keys(fields).forEach(key => {
273
270
  if (!validKeys.includes(key)) {
274
- return Stdlib_JsError.throwWithMessage(`Invalid "` + key + `" key in the fields option of ` + registration + `. Valid keys: ` + quotedJoin(validKeys) + `.`);
271
+ return Stdlib_JsError.throwWithMessage(`Invalid "` + key + `" key in the fields option of ` + registration + `. Valid keys: ` + Utils.$$Array.quotedJoin(validKeys) + `.`);
275
272
  }
276
273
  });
277
274
  }
@@ -295,7 +292,7 @@ function parseFieldsOrThrow(fields, valid, kind, registration, rejectEmptyOpt) {
295
292
  ) : [];
296
293
  fields$1.forEach(name => {
297
294
  if (!valid.has(name)) {
298
- Stdlib_JsError.throwWithMessage(`Invalid "` + name + `" field in the fields.` + kind + ` option of ` + registration + `. Valid ` + kind + ` fields: ` + quotedJoin(Array.from(valid)) + `.`);
295
+ Stdlib_JsError.throwWithMessage(`Invalid "` + name + `" field in the fields.` + kind + ` option of ` + registration + `. Valid ` + kind + ` fields: ` + Utils.$$Array.quotedJoin(Array.from(valid)) + `.`);
299
296
  }
300
297
  if (seen.has(name)) {
301
298
  Stdlib_JsError.throwWithMessage(`Duplicate "` + name + `" field in the fields.` + kind + ` option of ` + registration + `.`);
@@ -420,7 +417,7 @@ let validSvmLogFields = new Set([
420
417
  ]);
421
418
 
422
419
  function resolveSvmInlineFieldSelection(fields, contractName, eventName) {
423
- let registration = `the "` + eventName + `" event registration on contract "` + contractName + `"`;
420
+ let registration = `the "` + eventName + `" instruction on program "` + contractName + `"`;
424
421
  validateFieldsShapeOrThrow(fields, registration, svmSelectionKinds, "instruction, transaction, accountActivity, block and log");
425
422
  let accountActivity = selectionList(fields, "accountActivity");
426
423
  let log = selectionList(fields, "log");
@@ -436,7 +433,7 @@ function resolveSvmInlineFieldSelection(fields, contractName, eventName) {
436
433
  return Internal.makeFieldSelection(blockFields, transactionFields, Primitive_option.some(instructionFields), Primitive_option.some(accountActivityFields), Primitive_option.some(logFields), Svm.eventBlockFieldMask, Svm.eventTransactionFieldMask);
437
434
  }
438
435
 
439
- function buildSvmInstructionEventConfig(contractName, instructionName, programId, discriminator, discriminatorByteLen, accountFilters, isInner, accountsOpt, argsOpt, definedTypesOpt) {
436
+ function buildSvmInstructionEventConfig(contractName, instructionName, programId, discriminator, accountsOpt, argsOpt, definedTypesOpt) {
440
437
  let accounts = accountsOpt !== undefined ? accountsOpt : [];
441
438
  let args = argsOpt !== undefined ? argsOpt : null;
442
439
  let definedTypes = definedTypesOpt !== undefined ? definedTypesOpt : null;
@@ -451,16 +448,121 @@ function buildSvmInstructionEventConfig(contractName, instructionName, programId
451
448
  fieldSelection: fieldSelection,
452
449
  programId: programId,
453
450
  discriminator: discriminator,
454
- discriminatorByteLen: discriminatorByteLen,
455
- accountFilters: accountFilters,
456
- isInner: isInner,
457
451
  accounts: accounts,
458
452
  args: args,
459
453
  definedTypes: definedTypes
460
454
  };
461
455
  }
462
456
 
463
- function buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, fieldSelection, startBlock) {
457
+ let validSvmWhereKeys = [
458
+ "accounts",
459
+ "isInner",
460
+ "block"
461
+ ];
462
+
463
+ let svmBlockFilterSchema = S$RescriptSchema.strict(S$RescriptSchema.object(s => ({
464
+ slot: s.f("slot", S$RescriptSchema.option(LogSelection.eventBlockRangeSchema))
465
+ })));
466
+
467
+ function resolveSvmWhereOrThrow(where, contractName, eventName, accountNames) {
468
+ let invalid = message => Stdlib_JsError.throwWithMessage(`Invalid where configuration for the "` + eventName + `" instruction on program "` + contractName + `". ` + message);
469
+ let obj;
470
+ obj = typeof where === "object" && where !== null && !Array.isArray(where) ? where : invalid("Expected an object.");
471
+ Utils.Dict.forEachWithKey(obj, (param, key) => {
472
+ if (!validSvmWhereKeys.includes(key)) {
473
+ return invalid(`Unknown field "` + key + `". Valid fields: ` + Utils.$$Array.quotedJoin(validSvmWhereKeys) + `.`);
474
+ }
475
+ });
476
+ let match = obj["isInner"];
477
+ let isInner = match !== undefined ? (
478
+ typeof match === "boolean" ? match : invalid(`The "isInner" filter must be a boolean.`)
479
+ ) : undefined;
480
+ let parseGroup = group => Object.entries(group).map(param => {
481
+ let name = param[0];
482
+ let position = accountNames.indexOf(name);
483
+ let position$1 = position !== -1 ? (
484
+ position >= 10 ? invalid(`Account "` + name + `" is at position ` + position.toString() + `, and only the first ` + (10).toString() + ` accounts of an instruction can be filtered.`) : position
485
+ ) : (
486
+ Utils.$$Array.isEmpty(accountNames) ? invalid("The instruction has no named accounts to filter on. Add `accounts` and `args` to it in config.yaml, or attach an IDL.") : invalid(`The instruction has no account named "` + name + `" to filter on. Named accounts: ` + Utils.$$Array.quotedJoin(accountNames) + `.`)
487
+ );
488
+ let values = normalizeOrThrow(param[1]);
489
+ if (Utils.$$Array.isEmpty(values)) {
490
+ invalid(`The "` + name + `" filter must list at least one pubkey.`);
491
+ }
492
+ return {
493
+ position: position$1,
494
+ values: values.map(value => {
495
+ if (typeof value === "string") {
496
+ if (Core.getAddon().isSvmPubkey(value)) {
497
+ return value;
498
+ } else {
499
+ return invalid(`The "` + name + `" filter value "` + value + `" is not a base58 SVM pubkey.`);
500
+ }
501
+ } else {
502
+ return invalid(`The "` + name + `" filter must list base58 pubkeys as strings.`);
503
+ }
504
+ })
505
+ };
506
+ });
507
+ let match$1 = obj["accounts"];
508
+ let groups;
509
+ if (match$1 !== undefined) {
510
+ if (Array.isArray(match$1)) {
511
+ groups = match$1.map(entry => {
512
+ if (typeof entry === "object" && entry !== null && !Array.isArray(entry)) {
513
+ return parseGroup(entry);
514
+ } else {
515
+ return invalid(`Each entry in "accounts" must be an object.`);
516
+ }
517
+ });
518
+ } else if (match$1 === null) {
519
+ groups = invalid(`Expected "accounts" to be an object or an array of objects.`);
520
+ } else {
521
+ switch (typeof match$1) {
522
+ case "object" :
523
+ groups = [parseGroup(match$1)];
524
+ break;
525
+ default:
526
+ groups = invalid(`Expected "accounts" to be an object or an array of objects.`);
527
+ }
528
+ }
529
+ } else {
530
+ groups = [];
531
+ }
532
+ let accountFilters = groups.some(Utils.$$Array.isEmpty) ? [] : groups;
533
+ let block = obj["block"];
534
+ let startBlock;
535
+ if (block !== undefined) {
536
+ let filter;
537
+ try {
538
+ filter = S$RescriptSchema.parseOrThrow(block, svmBlockFilterSchema);
539
+ } catch (raw_exn) {
540
+ let exn = Primitive_exceptions.internalToException(raw_exn);
541
+ if (exn.RE_EXN_ID === S$RescriptSchema.Raised) {
542
+ filter = invalid(`The "block" filter is invalid: ` + Utils.prettifyExn(exn._1) + `. Only \`_gte\` is supported on instruction filters — use \`indexer.onSlot\` for \`_lte\` or \`_every\`.`);
543
+ } else {
544
+ throw exn;
545
+ }
546
+ }
547
+ let match$2 = filter.slot;
548
+ startBlock = match$2 !== undefined ? match$2._gte : undefined;
549
+ } else {
550
+ startBlock = undefined;
551
+ }
552
+ return {
553
+ accountFilters: accountFilters,
554
+ isInner: isInner,
555
+ startBlock: startBlock
556
+ };
557
+ }
558
+
559
+ function buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, where, fieldSelection, startBlock) {
560
+ let resolvedWhere = where !== undefined ? resolveSvmWhereOrThrow(where, eventConfig.contractName, eventConfig.name, eventConfig.accounts) : ({
561
+ accountFilters: [],
562
+ isInner: undefined,
563
+ startBlock: undefined
564
+ });
565
+ let sb = resolvedWhere.startBlock;
464
566
  return {
465
567
  index: -1,
466
568
  eventConfig: eventConfig,
@@ -469,8 +571,10 @@ function buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractR
469
571
  isWildcard: isWildcard,
470
572
  filterByAddresses: false,
471
573
  dependsOnAddresses: Internal.dependsOnAddresses(isWildcard, false),
472
- startBlock: startBlock,
473
- fieldSelection: fieldSelection !== undefined ? fieldSelection : eventConfig.fieldSelection
574
+ startBlock: sb !== undefined ? sb : startBlock,
575
+ fieldSelection: fieldSelection !== undefined ? fieldSelection : eventConfig.fieldSelection,
576
+ accountFilters: resolvedWhere.accountFilters,
577
+ isInner: resolvedWhere.isInner
474
578
  };
475
579
  }
476
580
 
@@ -542,6 +646,8 @@ function buildFuelOnEventRegistration(eventConfig, isWildcard, handler, contract
542
646
  };
543
647
  }
544
648
 
649
+ let filterableAccountCount = 10;
650
+
545
651
  export {
546
652
  paramMetaSchema,
547
653
  normalizeOrThrow,
@@ -561,7 +667,6 @@ export {
561
667
  rawEventBlockFields,
562
668
  evmSelectionKinds,
563
669
  svmSelectionKinds,
564
- quotedJoin,
565
670
  validateFieldsShapeOrThrow,
566
671
  selectionList,
567
672
  validBlockFields,
@@ -578,6 +683,10 @@ export {
578
683
  validSvmLogFields,
579
684
  resolveSvmInlineFieldSelection,
580
685
  buildSvmInstructionEventConfig,
686
+ validSvmWhereKeys,
687
+ svmBlockFilterSchema,
688
+ filterableAccountCount,
689
+ resolveSvmWhereOrThrow,
581
690
  buildSvmOnEventRegistration,
582
691
  buildFuelEventConfig,
583
692
  buildFuelOnEventRegistration,
@@ -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
  )
@@ -38,6 +38,7 @@ let ProcessingError = /* @__PURE__ */Primitive_exceptions.create("EventProcessin
38
38
  async function runEventHandlerOrThrow(item, checkpointId, handler, indexerState, loadManager, persistence, chains, config) {
39
39
  let timeBeforeHandler = Performance.now();
40
40
  try {
41
+ let contextParams_sync = UserContext.makeSyncState();
41
42
  let contextParams = {
42
43
  item: item,
43
44
  checkpointId: checkpointId,
@@ -47,13 +48,13 @@ async function runEventHandlerOrThrow(item, checkpointId, handler, indexerState,
47
48
  isPreload: false,
48
49
  chains: chains,
49
50
  config: config,
50
- isResolved: false
51
+ sync: contextParams_sync
51
52
  };
52
53
  await handler({
53
54
  event: Ecosystem.getItemEvent(item, config.ecosystem),
54
55
  context: UserContext.getHandlerContext(contextParams)
55
56
  });
56
- contextParams.isResolved = true;
57
+ contextParams_sync.status = "Resolved";
57
58
  } catch (raw_exn) {
58
59
  let exn = Primitive_exceptions.internalToException(raw_exn);
59
60
  throw {
@@ -79,6 +80,7 @@ async function runHandlerOrThrow(item, checkpointId, indexerState, loadManager,
79
80
  }
80
81
  }
81
82
  try {
83
+ let contextParams_sync = UserContext.makeSyncState();
82
84
  let contextParams = {
83
85
  item: item,
84
86
  checkpointId: checkpointId,
@@ -88,10 +90,10 @@ async function runHandlerOrThrow(item, checkpointId, indexerState, loadManager,
88
90
  isPreload: false,
89
91
  chains: chains,
90
92
  config: config,
91
- isResolved: false
93
+ sync: contextParams_sync
92
94
  };
93
95
  await item.onBlockRegistration.handler(Ecosystem.makeOnBlockArgs(item.blockNumber, config.ecosystem, UserContext.getHandlerContext(contextParams)));
94
- contextParams.isResolved = true;
96
+ contextParams_sync.status = "Resolved";
95
97
  return;
96
98
  } catch (raw_exn) {
97
99
  let exn = Primitive_exceptions.internalToException(raw_exn);
@@ -133,7 +135,7 @@ async function preloadBatchOrThrow(batch, loadManager, persistence, config, inde
133
135
  isPreload: true,
134
136
  chains: chains,
135
137
  config: config,
136
- isResolved: false
138
+ sync: UserContext.makeSyncState()
137
139
  })
138
140
  }).then(() => IndexerState.endPreloadHandler(indexerState, timerRef, contractName, eventName))));
139
141
  } catch (exn) {
@@ -151,7 +153,7 @@ async function preloadBatchOrThrow(batch, loadManager, persistence, config, inde
151
153
  isPreload: true,
152
154
  chains: chains,
153
155
  config: config,
154
- isResolved: false
156
+ sync: UserContext.makeSyncState()
155
157
  })))));
156
158
  } catch (exn$1) {
157
159
 
@@ -77,18 +77,30 @@ let autoLoadFromSrcHandlers = async (~handlers: string) => {
77
77
  // `HandlerRegister.finishRegistration`. This loads the user handler files
78
78
  // (populating the global `HandlerRegister` registry as a side effect) and
79
79
  // returns the resulting per-chain registrations.
80
+ // The subgraph runtime lives in this package but is never exported: it's
81
+ // reached only from here, when the resolved config carries a translated
82
+ // manifest.
83
+ let registerSubgraph: (JSON.t, ~isDev: bool) => promise<unit> = %raw(`(subgraph, isDev) =>
84
+ import("./subgraph/runtime.ts").then((m) => m.registerSubgraph({ ...subgraph, isDev }))`)
85
+
80
86
  let registerAllHandlers = async (~config: Config.t): HandlerRegister.registrationsByChainId => {
81
87
  HandlerRegister.startRegistration(~config)
82
88
 
83
- // Auto-load all .js files from src/handlers directory
84
- await autoLoadFromSrcHandlers(~handlers=config.handlers)
89
+ switch config.subgraph {
90
+ // A subgraph project's `src/` holds AssemblyScript mappings, not envio
91
+ // handlers, so the usual auto-load would import them without a scope.
92
+ | Some(subgraph) => await registerSubgraph(subgraph, ~isDev=config.isDev)
93
+ | None =>
94
+ // Auto-load all .js files from src/handlers directory
95
+ await autoLoadFromSrcHandlers(~handlers=config.handlers)
85
96
 
86
- // Load contract-specific handlers
87
- let _ = await config.contractHandlers
88
- ->Array.map(({name, handler}) => {
89
- registerContractHandlers(~contractName=name, ~handler)
90
- })
91
- ->Promise.all
97
+ // Load contract-specific handlers
98
+ let _ = await config.contractHandlers
99
+ ->Array.map(({name, handler}) => {
100
+ registerContractHandlers(~contractName=name, ~handler)
101
+ })
102
+ ->Promise.all
103
+ }
92
104
 
93
105
  HandlerRegister.finishRegistration(~config)
94
106
  }
@@ -56,10 +56,18 @@ async function autoLoadFromSrcHandlers(handlers) {
56
56
  })));
57
57
  }
58
58
 
59
+ let registerSubgraph = ((subgraph, isDev) =>
60
+ import("./subgraph/runtime.ts").then((m) => m.registerSubgraph({ ...subgraph, isDev })));
61
+
59
62
  async function registerAllHandlers(config) {
60
63
  HandlerRegister.startRegistration(config);
61
- await autoLoadFromSrcHandlers(config.handlers);
62
- await Promise.all(config.contractHandlers.map(param => registerContractHandlers(param.name, param.handler)));
64
+ let subgraph = config.subgraph;
65
+ if (subgraph !== undefined) {
66
+ await registerSubgraph(subgraph, config.isDev);
67
+ } else {
68
+ await autoLoadFromSrcHandlers(config.handlers);
69
+ await Promise.all(config.contractHandlers.map(param => registerContractHandlers(param.name, param.handler)));
70
+ }
63
71
  return HandlerRegister.finishRegistration(config);
64
72
  }
65
73
 
@@ -67,6 +75,7 @@ export {
67
75
  toImportUrl,
68
76
  registerContractHandlers,
69
77
  autoLoadFromSrcHandlers,
78
+ registerSubgraph,
70
79
  registerAllHandlers,
71
80
  }
72
81
  /* Not a pure module */
@@ -154,6 +154,7 @@ let buildOnEventRegistrationWith = (
154
154
  ~isWildcard,
155
155
  ~handler,
156
156
  ~contractRegister,
157
+ ~where,
157
158
  ~fieldSelection?,
158
159
  ~startBlock?,
159
160
  ) :> Internal.onEventRegistration)
@@ -320,7 +321,7 @@ let addOnEventRegistration = (
320
321
  )
321
322
  | Fuel =>
322
323
  JsError.throwWithMessage(
323
- `The fields option of the "${eventName}" event registration on contract "${contractName}" is only supported on EVM. Select the fields in your config instead.`,
324
+ `The fields option of the "${eventName}" event registration on contract "${contractName}" is not supported on Fuel. Select the fields in your config instead.`,
324
325
  )
325
326
  }
326
327
  }
@@ -335,6 +336,21 @@ let addOnEventRegistration = (
335
336
  | None => ()
336
337
  | Some(eventConfig) =>
337
338
  matched := true
339
+ switch (registration.config.ecosystem.name, fieldSelection) {
340
+ | (Svm, Some(fieldSelection)) if fieldSelection.instructionFields->Utils.Set.has("args") =>
341
+ let svmEventConfig =
342
+ eventConfig->(Utils.magic: Internal.eventConfig => Internal.svmInstructionEventConfig)
343
+ let declaresArgs = switch svmEventConfig.args {
344
+ | JSON.Array(args) => args->Array.length > 0
345
+ | _ => false
346
+ }
347
+ if !declaresArgs {
348
+ JsError.throwWithMessage(
349
+ `Invalid "args" field in the fields.instruction option of the "${eventName}" instruction on program "${contractName}". The instruction declares no args in config.yaml, so there is nothing to decode. Remove "args" from the selection, or declare the instruction's args.`,
350
+ )
351
+ }
352
+ | _ => ()
353
+ }
338
354
  let reg = buildOnEventRegistrationWith(
339
355
  ~config=registration.config,
340
356
  ~chainId=chainConfig.id,
@@ -359,17 +375,18 @@ let addOnEventRegistration = (
359
375
  if !matched.contents {
360
376
  let (contractNames, eventNames) = registration->describeConfigured(~contractName)
361
377
  let listOr = (names, empty) =>
362
- names->Utils.Array.isEmpty ? empty : names->Array.joinUnsafe(", ")
378
+ names->Utils.Array.isEmpty ? empty : names->Utils.Array.quotedJoin
379
+ let {contractNoun, eventNoun} = registration.config.ecosystem
363
380
  if eventNames->Utils.Array.isEmpty {
364
381
  JsError.throwWithMessage(
365
- `Contract "${contractName}" is not configured on any chain, so its handler for "${eventName}" would never run. Add it to your config, or remove the registration. Configured contracts: ${listOr(
382
+ `${contractNoun->Utils.String.capitalize} "${contractName}" is not configured on any chain, so its handler for "${eventName}" would never run. Add it to your config, or remove the registration. Configured ${contractNoun}s: ${listOr(
366
383
  contractNames,
367
384
  "none",
368
385
  )}.`,
369
386
  )
370
387
  } else {
371
388
  JsError.throwWithMessage(
372
- `Event "${eventName}" is not configured on contract "${contractName}", so its handler would never run. Add it to your config, or remove the registration. Configured events on "${contractName}": ${listOr(
389
+ `${eventNoun->Utils.String.capitalize} "${eventName}" is not configured on ${contractNoun} "${contractName}", so its handler would never run. Add it to your config, or remove the registration. Configured ${eventNoun}s on "${contractName}": ${listOr(
373
390
  eventNames,
374
391
  "none",
375
392
  )}.`,
@@ -102,7 +102,7 @@ function buildOnEventRegistrationWith(config, chainId, eventConfig, isWildcard,
102
102
  case "fuel" :
103
103
  return EventConfigBuilder.buildFuelOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, startBlock);
104
104
  case "svm" :
105
- return EventConfigBuilder.buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, fieldSelection, startBlock);
105
+ return EventConfigBuilder.buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, where, fieldSelection, startBlock);
106
106
  }
107
107
  }
108
108
 
@@ -209,7 +209,7 @@ function addOnEventRegistration(registration, contractName, eventName, handler,
209
209
  fieldSelection = EventConfigBuilder.resolveInlineFieldSelection(fields$1, contractName, eventName, registration.config.enableRawEvents);
210
210
  break;
211
211
  case "fuel" :
212
- fieldSelection = Stdlib_JsError.throwWithMessage(`The fields option of the "` + eventName + `" event registration on contract "` + contractName + `" is only supported on EVM. Select the fields in your config instead.`);
212
+ fieldSelection = Stdlib_JsError.throwWithMessage(`The fields option of the "` + eventName + `" event registration on contract "` + contractName + `" is not supported on Fuel. Select the fields in your config instead.`);
213
213
  break;
214
214
  case "svm" :
215
215
  fieldSelection = EventConfigBuilder.resolveSvmInlineFieldSelection(fields$1, contractName, eventName);
@@ -231,6 +231,22 @@ function addOnEventRegistration(registration, contractName, eventName, handler,
231
231
  return;
232
232
  }
233
233
  matched.contents = true;
234
+ let match = registration.config.ecosystem.name;
235
+ switch (match) {
236
+ case "evm" :
237
+ case "fuel" :
238
+ break;
239
+ case "svm" :
240
+ if (fieldSelection !== undefined && fieldSelection.instructionFields.has("args")) {
241
+ let args = eventConfig.args;
242
+ let declaresArgs;
243
+ declaresArgs = Array.isArray(args) ? args.length !== 0 : false;
244
+ if (!declaresArgs) {
245
+ Stdlib_JsError.throwWithMessage(`Invalid "args" field in the fields.instruction option of the "` + eventName + `" instruction on program "` + contractName + `". The instruction declares no args in config.yaml, so there is nothing to decode. Remove "args" from the selection, or declare the instruction's args.`);
246
+ }
247
+ }
248
+ break;
249
+ }
234
250
  let reg = buildOnEventRegistrationWith(registration.config, chainConfig.id, eventConfig, isWildcard, handler, contractRegister, where, fieldSelection, contract.startBlock);
235
251
  getChainRegistrations(registration, chainConfig.id).onEventRegistrations.push(reg);
236
252
  });
@@ -243,13 +259,16 @@ function addOnEventRegistration(registration, contractName, eventName, handler,
243
259
  if (Utils.$$Array.isEmpty(names)) {
244
260
  return empty;
245
261
  } else {
246
- return names.join(", ");
262
+ return Utils.$$Array.quotedJoin(names);
247
263
  }
248
264
  };
265
+ let match$2 = registration.config.ecosystem;
266
+ let eventNoun = match$2.eventNoun;
267
+ let contractNoun = match$2.contractNoun;
249
268
  if (Utils.$$Array.isEmpty(eventNames)) {
250
- return Stdlib_JsError.throwWithMessage(`Contract "` + contractName + `" is not configured on any chain, so its handler for "` + eventName + `" would never run. Add it to your config, or remove the registration. Configured contracts: ` + listOr(match$1[0], "none") + `.`);
269
+ return Stdlib_JsError.throwWithMessage(Utils.$$String.capitalize(contractNoun) + ` "` + contractName + `" is not configured on any chain, so its handler for "` + eventName + `" would never run. Add it to your config, or remove the registration. Configured ` + contractNoun + `s: ` + listOr(match$1[0], "none") + `.`);
251
270
  } else {
252
- return Stdlib_JsError.throwWithMessage(`Event "` + eventName + `" is not configured on contract "` + contractName + `", so its handler would never run. Add it to your config, or remove the registration. Configured events on "` + contractName + `": ` + listOr(eventNames, "none") + `.`);
271
+ return Stdlib_JsError.throwWithMessage(Utils.$$String.capitalize(eventNoun) + ` "` + eventName + `" is not configured on ` + contractNoun + ` "` + contractName + `", so its handler would never run. Add it to your config, or remove the registration. Configured ` + eventNoun + `s on "` + contractName + `": ` + listOr(eventNames, "none") + `.`);
253
272
  }
254
273
  }
255
274
 
@@ -127,15 +127,15 @@ let dropCommittedEffects = (
127
127
 
128
128
  let prepareRollbackDiff = async (
129
129
  state: IndexerState.t,
130
- ~rollbackTargetCheckpointId,
130
+ ~floors: RollbackFloors.t,
131
131
  ~rollbackDiffCheckpointId,
132
- ~progressBlockNumberByChainId,
132
+ ~progressedChains,
133
133
  ~rolledBackAddresses,
134
134
  ) => {
135
135
  state->IndexerState.beginRollbackDiff(
136
- ~targetCheckpointId=rollbackTargetCheckpointId,
137
136
  ~diffCheckpointId=rollbackDiffCheckpointId,
138
- ~progressBlockNumberByChainId,
137
+ ~floors,
138
+ ~progressedChains,
139
139
  ~rolledBackAddresses,
140
140
  )
141
141
  let persistence = state->IndexerState.persistence
@@ -152,7 +152,7 @@ let prepareRollbackDiff = async (
152
152
  ->Array.map(async entityConfig => {
153
153
  let (removals, restoredEntities) = await persistence.storage.getRollbackData(
154
154
  ~entityConfig,
155
- ~rollbackTargetCheckpointId,
155
+ ~floors,
156
156
  )
157
157
 
158
158
  removals->Array.forEach(({entityId, scope}: Persistence.rollbackRemoval) => {
@@ -215,7 +215,8 @@ let setBatchDcs = (state: IndexerState.t, ~batch: Batch.t) => {
215
215
  }
216
216
  }
217
217
 
218
- batch.registeredAddresses->Array.pushMany(
218
+ batch.registeredAddresses
219
+ ->Array.pushMany(
219
220
  chainState
220
221
  ->ChainState.drainAddressesForWrite(
221
222
  ~toBlockInclusive=progressedChain.progressBlockNumber,
@@ -230,7 +231,8 @@ let setBatchDcs = (state: IndexerState.t, ~batch: Batch.t) => {
230
231
  },
231
232
  checkpointId: checkpointIds->Array.getUnsafe(dc.checkpointIdx),
232
233
  }),
233
- )->ignore
234
+ )
235
+ ->ignore
234
236
  }
235
237
  })
236
238
  }
@@ -106,14 +106,14 @@ function dropCommittedEffects(inMemTable, committedCheckpointId, keepLoadedFromD
106
106
  inMemTable.changesCount = inMemTable.changesCount - keysToDelete.length;
107
107
  }
108
108
 
109
- async function prepareRollbackDiff(state, rollbackTargetCheckpointId, rollbackDiffCheckpointId, progressBlockNumberByChainId, rolledBackAddresses) {
110
- IndexerState.beginRollbackDiff(state, rollbackTargetCheckpointId, rollbackDiffCheckpointId, progressBlockNumberByChainId, rolledBackAddresses);
109
+ async function prepareRollbackDiff(state, floors, rollbackDiffCheckpointId, progressedChains, rolledBackAddresses) {
110
+ IndexerState.beginRollbackDiff(state, rollbackDiffCheckpointId, floors, progressedChains, rolledBackAddresses);
111
111
  let persistence = IndexerState.persistence(state);
112
112
  let committedCheckpointId = IndexerState.committedCheckpointId(state);
113
113
  let deletedEntities = {};
114
114
  let setEntities = {};
115
115
  await Promise.all(persistence.allEntities.filter(entityConfig => entityConfig.storage.postgres).map(async entityConfig => {
116
- let match = await persistence.storage.getRollbackData(entityConfig, rollbackTargetCheckpointId);
116
+ let match = await persistence.storage.getRollbackData(entityConfig, floors);
117
117
  match[0].forEach(param => {
118
118
  let entityId = param.entityId;
119
119
  Utils.Dict.push(deletedEntities, entityConfig.name, entityId);