envio 3.3.0-alpha.2 → 3.3.0-alpha.4

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 (71) hide show
  1. package/index.d.ts +23 -21
  2. package/package.json +6 -6
  3. package/src/Bin.res +3 -0
  4. package/src/Bin.res.mjs +4 -0
  5. package/src/ChainFetching.res +26 -3
  6. package/src/ChainFetching.res.mjs +22 -3
  7. package/src/ChainState.res +3 -12
  8. package/src/ChainState.res.mjs +6 -8
  9. package/src/ChainState.resi +0 -2
  10. package/src/CrossChainState.res +15 -0
  11. package/src/CrossChainState.res.mjs +12 -0
  12. package/src/Ecosystem.res +0 -6
  13. package/src/EventConfigBuilder.res +45 -18
  14. package/src/EventConfigBuilder.res.mjs +28 -10
  15. package/src/EventProcessing.res +53 -37
  16. package/src/EventProcessing.res.mjs +41 -36
  17. package/src/FetchState.res +35 -42
  18. package/src/FetchState.res.mjs +37 -63
  19. package/src/HandlerLoader.res +10 -1
  20. package/src/HandlerLoader.res.mjs +15 -8
  21. package/src/Internal.res +8 -3
  22. package/src/Internal.res.mjs +1 -1
  23. package/src/LoadLayer.res +5 -5
  24. package/src/LoadLayer.res.mjs +6 -6
  25. package/src/Main.res +17 -9
  26. package/src/Main.res.mjs +15 -6
  27. package/src/PgStorage.res +4 -4
  28. package/src/PgStorage.res.mjs +5 -5
  29. package/src/Prometheus.res +10 -10
  30. package/src/Prometheus.res.mjs +9 -9
  31. package/src/PruneStaleHistory.res +2 -2
  32. package/src/PruneStaleHistory.res.mjs +3 -3
  33. package/src/Rollback.res +2 -2
  34. package/src/Rollback.res.mjs +3 -3
  35. package/src/SimulateItems.res +81 -15
  36. package/src/SimulateItems.res.mjs +63 -20
  37. package/src/TestIndexer.res +77 -39
  38. package/src/TestIndexer.res.mjs +45 -31
  39. package/src/bindings/Performance.res +7 -0
  40. package/src/bindings/Performance.res.mjs +21 -0
  41. package/src/bindings/Performance.resi +7 -0
  42. package/src/sources/EventRouter.res +17 -21
  43. package/src/sources/EventRouter.res.mjs +6 -9
  44. package/src/sources/Evm.res +10 -37
  45. package/src/sources/Evm.res.mjs +5 -40
  46. package/src/sources/Fuel.res +0 -4
  47. package/src/sources/Fuel.res.mjs +0 -7
  48. package/src/sources/HyperFuelSource.res +10 -11
  49. package/src/sources/HyperFuelSource.res.mjs +11 -11
  50. package/src/sources/HyperSync.res +3 -0
  51. package/src/sources/HyperSync.res.mjs +1 -0
  52. package/src/sources/HyperSync.resi +1 -0
  53. package/src/sources/HyperSyncClient.res +5 -1
  54. package/src/sources/HyperSyncSource.res +42 -24
  55. package/src/sources/HyperSyncSource.res.mjs +30 -26
  56. package/src/sources/RpcSource.res +7 -8
  57. package/src/sources/RpcSource.res.mjs +8 -8
  58. package/src/sources/SimulateSource.res +1 -1
  59. package/src/sources/Source.res +1 -1
  60. package/src/sources/SourceManager.res +17 -16
  61. package/src/sources/SourceManager.res.mjs +10 -15
  62. package/src/sources/Svm.res +6 -11
  63. package/src/sources/Svm.res.mjs +6 -14
  64. package/src/sources/SvmHyperSyncSource.res +24 -18
  65. package/src/sources/SvmHyperSyncSource.res.mjs +22 -15
  66. package/src/sources/TransactionStore.res +62 -35
  67. package/src/sources/TransactionStore.res.mjs +44 -18
  68. package/svm.schema.json +30 -37
  69. package/src/bindings/Hrtime.res +0 -58
  70. package/src/bindings/Hrtime.res.mjs +0 -90
  71. package/src/bindings/Hrtime.resi +0 -30
@@ -14,6 +14,16 @@ function deriveEffectiveStartBlock(registrationBlock, contractStartBlock) {
14
14
  return Primitive_int.max(Primitive_int.max(registrationBlock, 0), Stdlib_Option.getOr(contractStartBlock, 0));
15
15
  }
16
16
 
17
+ let deriveContractNameByAddress = Utils.$$WeakMap.memoize(addressesByContractName => {
18
+ let result = {};
19
+ Utils.Dict.forEachWithKey(addressesByContractName, (addresses, contractName) => {
20
+ for (let i = 0, i_finish = addresses.length; i < i_finish; ++i) {
21
+ result[addresses[i]] = contractName;
22
+ }
23
+ });
24
+ return result;
25
+ });
26
+
17
27
  function calculateEstResponseSize(p, fromBlock, toBlock, maxQueryBlockNumber) {
18
28
  if (p.prevQueryRange <= 0) {
19
29
  return 10000;
@@ -965,8 +975,8 @@ function startFetchingQueries(param, queries) {
965
975
  }
966
976
  }
967
977
 
968
- function pushQueriesForRange(queries, partitionId, rangeFromBlock, rangeEndBlock, maxQueryBlockNumber, maybeChunkRange, partition, selection, addressesByContractName, indexingAddresses) {
969
- if (rangeFromBlock > maxQueryBlockNumber) {
978
+ function pushQueriesForRange(queries, partitionId, rangeFromBlock, rangeEndBlock, maxQueryBlockNumber, maybeChunkRange, maxChunks, partition, selection, addressesByContractName) {
979
+ if (!(rangeFromBlock <= maxQueryBlockNumber && maxChunks > 0)) {
970
980
  return;
971
981
  }
972
982
  if (rangeEndBlock !== undefined && rangeFromBlock > rangeEndBlock) {
@@ -975,19 +985,11 @@ function pushQueriesForRange(queries, partitionId, rangeFromBlock, rangeEndBlock
975
985
  if (maybeChunkRange !== undefined) {
976
986
  let maxBlock = rangeEndBlock !== undefined ? rangeEndBlock : maxQueryBlockNumber;
977
987
  let chunkSize = Js_math.ceil_int(maybeChunkRange * 1.8);
978
- let probeSize = Js_math.ceil_int(maybeChunkRange * 0.9);
979
- let getChunkSize = chunkIdx => {
980
- if (chunkIdx < 2) {
981
- return probeSize;
982
- } else {
983
- return chunkSize;
984
- }
985
- };
986
- if ((((rangeFromBlock + probeSize | 0) + probeSize | 0) - 1 | 0) <= maxBlock) {
988
+ if (((rangeFromBlock + (chunkSize << 1) | 0) - 1 | 0) <= maxBlock) {
987
989
  let chunkFromBlock = rangeFromBlock;
988
990
  let chunkIdx = 0;
989
- while (chunkIdx < 5 && ((chunkFromBlock + getChunkSize(chunkIdx) | 0) - 1 | 0) <= maxBlock) {
990
- let chunkToBlock = (chunkFromBlock + getChunkSize(chunkIdx) | 0) - 1 | 0;
991
+ while (chunkIdx < maxChunks && ((chunkFromBlock + chunkSize | 0) - 1 | 0) <= maxBlock) {
992
+ let chunkToBlock = (chunkFromBlock + chunkSize | 0) - 1 | 0;
991
993
  queries.push({
992
994
  partitionId: partitionId,
993
995
  fromBlock: chunkFromBlock,
@@ -997,8 +999,7 @@ function pushQueriesForRange(queries, partitionId, rangeFromBlock, rangeEndBlock
997
999
  chainId: 0,
998
1000
  progress: 0,
999
1001
  selection: selection,
1000
- addressesByContractName: addressesByContractName,
1001
- indexingAddresses: indexingAddresses
1002
+ addressesByContractName: addressesByContractName
1002
1003
  });
1003
1004
  chunkFromBlock = chunkToBlock + 1 | 0;
1004
1005
  chunkIdx = chunkIdx + 1 | 0;
@@ -1014,8 +1015,7 @@ function pushQueriesForRange(queries, partitionId, rangeFromBlock, rangeEndBlock
1014
1015
  chainId: 0,
1015
1016
  progress: 0,
1016
1017
  selection: selection,
1017
- addressesByContractName: addressesByContractName,
1018
- indexingAddresses: indexingAddresses
1018
+ addressesByContractName: addressesByContractName
1019
1019
  });
1020
1020
  return;
1021
1021
  }
@@ -1028,15 +1028,13 @@ function pushQueriesForRange(queries, partitionId, rangeFromBlock, rangeEndBlock
1028
1028
  chainId: 0,
1029
1029
  progress: 0,
1030
1030
  selection: selection,
1031
- addressesByContractName: addressesByContractName,
1032
- indexingAddresses: indexingAddresses
1031
+ addressesByContractName: addressesByContractName
1033
1032
  });
1034
1033
  }
1035
1034
 
1036
1035
  function getNextQuery(fetchState, budget, chainPendingBudget) {
1037
1036
  let knownHeight = fetchState.knownHeight;
1038
1037
  let blockLag = fetchState.blockLag;
1039
- let indexingAddresses = fetchState.indexingAddresses;
1040
1038
  let optimizedPartitions = fetchState.optimizedPartitions;
1041
1039
  let headBlockNumber = knownHeight - blockLag | 0;
1042
1040
  if (headBlockNumber <= 0) {
@@ -1083,9 +1081,10 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1083
1081
  if (pq.fromBlock > cursor) {
1084
1082
  let addressesByContractName = p.addressesByContractName;
1085
1083
  let selection = p.selection;
1084
+ let maxChunks = (10 - pendingCount | 0) - (queries.length - partitionQueriesStart | 0) | 0;
1086
1085
  let rangeEndBlock = Utils.$$Math.minOptInt(pq.fromBlock - 1 | 0, queryEndBlock$2);
1087
1086
  let rangeFromBlock = cursor;
1088
- if (rangeFromBlock <= maxQueryBlockNumber) {
1087
+ if (rangeFromBlock <= maxQueryBlockNumber && maxChunks > 0) {
1089
1088
  let exit = 0;
1090
1089
  if (!(rangeEndBlock !== undefined && rangeFromBlock > rangeEndBlock)) {
1091
1090
  exit = 1;
@@ -1094,19 +1093,11 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1094
1093
  if (maybeChunkRange !== undefined) {
1095
1094
  let maxBlock = rangeEndBlock !== undefined ? rangeEndBlock : maxQueryBlockNumber;
1096
1095
  let chunkSize = Js_math.ceil_int(maybeChunkRange * 1.8);
1097
- let probeSize = Js_math.ceil_int(maybeChunkRange * 0.9);
1098
- let getChunkSize = chunkIdx => {
1099
- if (chunkIdx < 2) {
1100
- return probeSize;
1101
- } else {
1102
- return chunkSize;
1103
- }
1104
- };
1105
- if ((((rangeFromBlock + getChunkSize(0) | 0) + getChunkSize(1) | 0) - 1 | 0) <= maxBlock) {
1096
+ if (((rangeFromBlock + (chunkSize << 1) | 0) - 1 | 0) <= maxBlock) {
1106
1097
  let chunkFromBlock = rangeFromBlock;
1107
1098
  let chunkIdx = 0;
1108
- while (chunkIdx < 5 && ((chunkFromBlock + getChunkSize(chunkIdx) | 0) - 1 | 0) <= maxBlock) {
1109
- let chunkToBlock = (chunkFromBlock + getChunkSize(chunkIdx) | 0) - 1 | 0;
1099
+ while (chunkIdx < maxChunks && ((chunkFromBlock + chunkSize | 0) - 1 | 0) <= maxBlock) {
1100
+ let chunkToBlock = (chunkFromBlock + chunkSize | 0) - 1 | 0;
1110
1101
  queries.push({
1111
1102
  partitionId: partitionId,
1112
1103
  fromBlock: chunkFromBlock,
@@ -1116,8 +1107,7 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1116
1107
  chainId: 0,
1117
1108
  progress: 0,
1118
1109
  selection: selection,
1119
- addressesByContractName: addressesByContractName,
1120
- indexingAddresses: indexingAddresses
1110
+ addressesByContractName: addressesByContractName
1121
1111
  });
1122
1112
  chunkFromBlock = chunkToBlock + 1 | 0;
1123
1113
  chunkIdx = chunkIdx + 1 | 0;
@@ -1132,8 +1122,7 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1132
1122
  chainId: 0,
1133
1123
  progress: 0,
1134
1124
  selection: selection,
1135
- addressesByContractName: addressesByContractName,
1136
- indexingAddresses: indexingAddresses
1125
+ addressesByContractName: addressesByContractName
1137
1126
  });
1138
1127
  }
1139
1128
  } else {
@@ -1146,8 +1135,7 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1146
1135
  chainId: 0,
1147
1136
  progress: 0,
1148
1137
  selection: selection,
1149
- addressesByContractName: addressesByContractName,
1150
- indexingAddresses: indexingAddresses
1138
+ addressesByContractName: addressesByContractName
1151
1139
  });
1152
1140
  }
1153
1141
  }
@@ -1170,8 +1158,9 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1170
1158
  if (canContinue) {
1171
1159
  let addressesByContractName$1 = p.addressesByContractName;
1172
1160
  let selection$1 = p.selection;
1161
+ let maxChunks$1 = (10 - pendingCount | 0) - (queries.length - partitionQueriesStart | 0) | 0;
1173
1162
  let rangeFromBlock$1 = cursor;
1174
- if (rangeFromBlock$1 <= maxQueryBlockNumber) {
1163
+ if (rangeFromBlock$1 <= maxQueryBlockNumber && maxChunks$1 > 0) {
1175
1164
  let exit$1 = 0;
1176
1165
  if (!(queryEndBlock$2 !== undefined && rangeFromBlock$1 > queryEndBlock$2)) {
1177
1166
  exit$1 = 1;
@@ -1180,19 +1169,11 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1180
1169
  if (maybeChunkRange !== undefined) {
1181
1170
  let maxBlock$1 = queryEndBlock$2 !== undefined ? queryEndBlock$2 : maxQueryBlockNumber;
1182
1171
  let chunkSize$1 = Js_math.ceil_int(maybeChunkRange * 1.8);
1183
- let probeSize$1 = Js_math.ceil_int(maybeChunkRange * 0.9);
1184
- let getChunkSize$1 = chunkIdx => {
1185
- if (chunkIdx < 2) {
1186
- return probeSize$1;
1187
- } else {
1188
- return chunkSize$1;
1189
- }
1190
- };
1191
- if ((((rangeFromBlock$1 + getChunkSize$1(0) | 0) + getChunkSize$1(1) | 0) - 1 | 0) <= maxBlock$1) {
1172
+ if (((rangeFromBlock$1 + (chunkSize$1 << 1) | 0) - 1 | 0) <= maxBlock$1) {
1192
1173
  let chunkFromBlock$1 = rangeFromBlock$1;
1193
1174
  let chunkIdx$1 = 0;
1194
- while (chunkIdx$1 < 5 && ((chunkFromBlock$1 + getChunkSize$1(chunkIdx$1) | 0) - 1 | 0) <= maxBlock$1) {
1195
- let chunkToBlock$1 = (chunkFromBlock$1 + getChunkSize$1(chunkIdx$1) | 0) - 1 | 0;
1175
+ while (chunkIdx$1 < maxChunks$1 && ((chunkFromBlock$1 + chunkSize$1 | 0) - 1 | 0) <= maxBlock$1) {
1176
+ let chunkToBlock$1 = (chunkFromBlock$1 + chunkSize$1 | 0) - 1 | 0;
1196
1177
  queries.push({
1197
1178
  partitionId: partitionId,
1198
1179
  fromBlock: chunkFromBlock$1,
@@ -1202,8 +1183,7 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1202
1183
  chainId: 0,
1203
1184
  progress: 0,
1204
1185
  selection: selection$1,
1205
- addressesByContractName: addressesByContractName$1,
1206
- indexingAddresses: indexingAddresses
1186
+ addressesByContractName: addressesByContractName$1
1207
1187
  });
1208
1188
  chunkFromBlock$1 = chunkToBlock$1 + 1 | 0;
1209
1189
  chunkIdx$1 = chunkIdx$1 + 1 | 0;
@@ -1218,8 +1198,7 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1218
1198
  chainId: 0,
1219
1199
  progress: 0,
1220
1200
  selection: selection$1,
1221
- addressesByContractName: addressesByContractName$1,
1222
- indexingAddresses: indexingAddresses
1201
+ addressesByContractName: addressesByContractName$1
1223
1202
  });
1224
1203
  }
1225
1204
  } else {
@@ -1232,18 +1211,12 @@ function getNextQuery(fetchState, budget, chainPendingBudget) {
1232
1211
  chainId: 0,
1233
1212
  progress: 0,
1234
1213
  selection: selection$1,
1235
- addressesByContractName: addressesByContractName$1,
1236
- indexingAddresses: indexingAddresses
1214
+ addressesByContractName: addressesByContractName$1
1237
1215
  });
1238
1216
  }
1239
1217
  }
1240
1218
  }
1241
1219
  }
1242
- let maxNewChunks = Primitive_int.max(0, 10 - pendingCount | 0);
1243
- let generatedCount = queries.length - partitionQueriesStart | 0;
1244
- if (generatedCount > maxNewChunks) {
1245
- queries.splice(partitionQueriesStart + maxNewChunks | 0, generatedCount - maxNewChunks | 0);
1246
- }
1247
1220
  idxRef = idxRef + 1 | 0;
1248
1221
  };
1249
1222
  if (Utils.$$Array.isEmpty(queries)) {
@@ -1748,6 +1721,7 @@ let maxPendingChunksPerPartition = 10;
1748
1721
 
1749
1722
  export {
1750
1723
  deriveEffectiveStartBlock,
1724
+ deriveContractNameByAddress,
1751
1725
  defaultEstResponseSize,
1752
1726
  calculateEstResponseSize,
1753
1727
  getMinHistoryRange,
@@ -1767,8 +1741,8 @@ export {
1767
1741
  registerDynamicContracts,
1768
1742
  handleQueryResult,
1769
1743
  startFetchingQueries,
1770
- pushQueriesForRange,
1771
1744
  maxPendingChunksPerPartition,
1745
+ pushQueriesForRange,
1772
1746
  getNextQuery,
1773
1747
  hasReadyItem,
1774
1748
  getReadyItemsCount,
@@ -1787,4 +1761,4 @@ export {
1787
1761
  getProgressBlockNumberAt,
1788
1762
  updateKnownHeight,
1789
1763
  }
1790
- /* Utils Not a pure module */
1764
+ /* deriveContractNameByAddress Not a pure module */
@@ -103,6 +103,7 @@ let applyRegistrations = (~config: Config.t): Config.t => {
103
103
  isWildcard,
104
104
  handler,
105
105
  contractRegister,
106
+ clientAddressFilter: ?EventConfigBuilder.buildAddressFilter([], ~isWildcard),
106
107
  dependsOnAddresses: Internal.dependsOnAddresses(
107
108
  ~isWildcard,
108
109
  ~filterByAddresses=false,
@@ -144,7 +145,10 @@ let applyRegistrations = (~config: Config.t): Config.t => {
144
145
  contractRegister,
145
146
  getEventFiltersOrThrow,
146
147
  filterByAddresses,
147
- clientAddressFilter: ?EventConfigBuilder.buildAddressFilter(addressFilterParamGroups),
148
+ clientAddressFilter: ?EventConfigBuilder.buildAddressFilter(
149
+ addressFilterParamGroups,
150
+ ~isWildcard,
151
+ ),
148
152
  dependsOnAddresses: Internal.dependsOnAddresses(~isWildcard, ~filterByAddresses),
149
153
  } :> Internal.eventConfig)
150
154
  | Svm =>
@@ -155,6 +159,11 @@ let applyRegistrations = (~config: Config.t): Config.t => {
155
159
  isWildcard,
156
160
  handler,
157
161
  contractRegister,
162
+ clientAddressFilter: ?EventConfigBuilder.buildAddressFilter(
163
+ [],
164
+ ~isWildcard,
165
+ ~srcAddressExpr="event.programId",
166
+ ),
158
167
  dependsOnAddresses: Internal.dependsOnAddresses(
159
168
  ~isWildcard,
160
169
  ~filterByAddresses=false,
@@ -79,21 +79,28 @@ function applyRegistrations(config) {
79
79
  newrecord.getEventFiltersOrThrow = match$1.getEventFiltersOrThrow;
80
80
  newrecord.contractRegister = contractRegister;
81
81
  newrecord.handler = handler;
82
- newrecord.clientAddressFilter = EventConfigBuilder.buildAddressFilter(match$1.addressFilterParamGroups);
82
+ newrecord.clientAddressFilter = EventConfigBuilder.buildAddressFilter(match$1.addressFilterParamGroups, isWildcard, undefined);
83
83
  newrecord.dependsOnAddresses = Internal.dependsOnAddresses(isWildcard, filterByAddresses);
84
84
  newrecord.filterByAddresses = filterByAddresses;
85
85
  newrecord.isWildcard = isWildcard;
86
86
  return newrecord;
87
87
  case "fuel" :
88
+ let newrecord$1 = {...ev};
89
+ newrecord$1.contractRegister = contractRegister;
90
+ newrecord$1.handler = handler;
91
+ newrecord$1.clientAddressFilter = EventConfigBuilder.buildAddressFilter([], isWildcard, undefined);
92
+ newrecord$1.dependsOnAddresses = Internal.dependsOnAddresses(isWildcard, false);
93
+ newrecord$1.isWildcard = isWildcard;
94
+ return newrecord$1;
88
95
  case "svm" :
89
- break;
96
+ let newrecord$2 = {...ev};
97
+ newrecord$2.contractRegister = contractRegister;
98
+ newrecord$2.handler = handler;
99
+ newrecord$2.clientAddressFilter = EventConfigBuilder.buildAddressFilter([], isWildcard, "event.programId");
100
+ newrecord$2.dependsOnAddresses = Internal.dependsOnAddresses(isWildcard, false);
101
+ newrecord$2.isWildcard = isWildcard;
102
+ return newrecord$2;
90
103
  }
91
- let newrecord$1 = {...ev};
92
- newrecord$1.contractRegister = contractRegister;
93
- newrecord$1.handler = handler;
94
- newrecord$1.dependsOnAddresses = Internal.dependsOnAddresses(isWildcard, false);
95
- newrecord$1.isWildcard = isWildcard;
96
- return newrecord$1;
97
104
  });
98
105
  return {
99
106
  name: contract.name,
package/src/Internal.res CHANGED
@@ -58,7 +58,6 @@ type evmTransactionField =
58
58
  | @as("root") Root
59
59
  | @as("status") Status
60
60
  | @as("yParity") YParity
61
- | @as("accessList") AccessList
62
61
  | @as("maxFeePerBlobGas") MaxFeePerBlobGas
63
62
  | @as("blobVersionedHashes") BlobVersionedHashes
64
63
  | @as("type") Type
@@ -67,6 +66,7 @@ type evmTransactionField =
67
66
  | @as("l1GasUsed") L1GasUsed
68
67
  | @as("l1FeeScalar") L1FeeScalar
69
68
  | @as("gasUsedForL1") GasUsedForL1
69
+ | @as("accessList") AccessList
70
70
  | @as("authorizationList") AuthorizationList
71
71
 
72
72
  let allEvmBlockFields: array<evmBlockField> = [
@@ -123,7 +123,6 @@ let allEvmTransactionFields: array<evmTransactionField> = [
123
123
  Root,
124
124
  Status,
125
125
  YParity,
126
- AccessList,
127
126
  MaxFeePerBlobGas,
128
127
  BlobVersionedHashes,
129
128
  Type,
@@ -132,6 +131,7 @@ let allEvmTransactionFields: array<evmTransactionField> = [
132
131
  L1GasUsed,
133
132
  L1FeeScalar,
134
133
  GasUsedForL1,
134
+ AccessList,
135
135
  AuthorizationList,
136
136
  ]
137
137
  let evmTransactionFieldSchema = S.enum(allEvmTransactionFields)
@@ -420,6 +420,11 @@ type eventConfig = private {
420
420
  // string set so the shared mask logic is ecosystem-agnostic; sources recover
421
421
  // the typed view where they need it.
422
422
  selectedTransactionFields: Utils.Set.t<string>,
423
+ // `selectedTransactionFields` precompiled to the transaction-store selection
424
+ // bitmask (bit per ecosystem field code). Materialisation reads this per item
425
+ // so each transaction decodes only the fields its event selected. `0.` when
426
+ // nothing is selected or the ecosystem carries the transaction inline (Fuel).
427
+ transactionFieldMask: float,
423
428
  }
424
429
 
425
430
  type fuelEventKind =
@@ -692,7 +697,7 @@ type effect = {
692
697
  input: S.t<effectInput>,
693
698
  // The number of functions that are currently running.
694
699
  mutable activeCallsCount: int,
695
- mutable prevCallStartTimerRef: Hrtime.timeRef,
700
+ mutable prevCallStartTimerRef: Performance.timeRef,
696
701
  rateLimit: option<rateLimitState>,
697
702
  }
698
703
  let cacheTablePrefix = "envio_effect_"
@@ -60,7 +60,6 @@ let allEvmTransactionFields = [
60
60
  "root",
61
61
  "status",
62
62
  "yParity",
63
- "accessList",
64
63
  "maxFeePerBlobGas",
65
64
  "blobVersionedHashes",
66
65
  "type",
@@ -69,6 +68,7 @@ let allEvmTransactionFields = [
69
68
  "l1GasUsed",
70
69
  "l1FeeScalar",
71
70
  "gasUsedForL1",
71
+ "accessList",
72
72
  "authorizationList"
73
73
  ];
74
74
 
package/src/LoadLayer.res CHANGED
@@ -85,7 +85,7 @@ let callEffect = (
85
85
  )
86
86
 
87
87
  if hadActiveCalls {
88
- let elapsed = Hrtime.secondsBetween(~from=effect.prevCallStartTimerRef, ~to=timerRef)
88
+ let elapsed = Performance.secondsBetween(~from=effect.prevCallStartTimerRef, ~to=timerRef)
89
89
  if elapsed > 0. {
90
90
  Prometheus.EffectCalls.timeCounter->Prometheus.SafeCounter.handleFloat(
91
91
  ~labels=effectName,
@@ -113,17 +113,17 @@ let callEffect = (
113
113
  ~labels=effectName,
114
114
  ~value=effect.activeCallsCount,
115
115
  )
116
- let newTimer = Hrtime.makeTimer()
116
+ let newTimer = Performance.now()
117
117
  Prometheus.EffectCalls.timeCounter->Prometheus.SafeCounter.handleFloat(
118
118
  ~labels=effectName,
119
- ~value=Hrtime.secondsBetween(~from=effect.prevCallStartTimerRef, ~to=newTimer),
119
+ ~value=Performance.secondsBetween(~from=effect.prevCallStartTimerRef, ~to=newTimer),
120
120
  )
121
121
  effect.prevCallStartTimerRef = newTimer
122
122
 
123
123
  Prometheus.EffectCalls.totalCallsCount->Prometheus.SafeCounter.increment(~labels=effectName)
124
124
  Prometheus.EffectCalls.sumTimeCounter->Prometheus.SafeCounter.handleFloat(
125
125
  ~labels=effectName,
126
- ~value=timerRef->Hrtime.timeSince->Hrtime.toSecondsFloat,
126
+ ~value=timerRef->Performance.secondsSince,
127
127
  )
128
128
  })
129
129
  }
@@ -137,7 +137,7 @@ let rec executeWithRateLimit = (
137
137
  ) => {
138
138
  let effectName = effect.name
139
139
 
140
- let timerRef = Hrtime.makeTimer()
140
+ let timerRef = Performance.now()
141
141
  let promises = []
142
142
 
143
143
  switch effect.rateLimit {
@@ -2,11 +2,11 @@
2
2
 
3
3
  import * as Table from "./db/Table.res.mjs";
4
4
  import * as Utils from "./Utils.res.mjs";
5
- import * as Hrtime from "./bindings/Hrtime.res.mjs";
6
5
  import * as Logging from "./Logging.res.mjs";
7
6
  import * as Ecosystem from "./Ecosystem.res.mjs";
8
7
  import * as Prometheus from "./Prometheus.res.mjs";
9
8
  import * as LoadManager from "./LoadManager.res.mjs";
9
+ import * as Performance from "./bindings/Performance.res.mjs";
10
10
  import * as Persistence from "./Persistence.res.mjs";
11
11
  import * as EntityFilter from "./db/EntityFilter.res.mjs";
12
12
  import * as IndexerState from "./IndexerState.res.mjs";
@@ -55,7 +55,7 @@ function callEffect(effect, arg, inMemTable, timerRef, onError) {
55
55
  effect.activeCallsCount = effect.activeCallsCount + 1 | 0;
56
56
  Prometheus.SafeGauge.handleInt(Prometheus.EffectCalls.activeCallsCount, effectName, effect.activeCallsCount);
57
57
  if (hadActiveCalls) {
58
- let elapsed = Hrtime.secondsBetween(effect.prevCallStartTimerRef, timerRef);
58
+ let elapsed = Performance.secondsBetween(effect.prevCallStartTimerRef, timerRef);
59
59
  if (elapsed > 0) {
60
60
  Prometheus.SafeCounter.handleFloat(Prometheus.EffectCalls.timeCounter, effectName, elapsed);
61
61
  }
@@ -64,17 +64,17 @@ function callEffect(effect, arg, inMemTable, timerRef, onError) {
64
64
  return effect.handler(arg).then(output => InMemoryStore.setEffectOutput(inMemTable, arg.checkpointId, arg.cacheKey, output, arg.context.cache)).catch(exn => onError(arg.cacheKey, exn)).finally(() => {
65
65
  effect.activeCallsCount = effect.activeCallsCount - 1 | 0;
66
66
  Prometheus.SafeGauge.handleInt(Prometheus.EffectCalls.activeCallsCount, effectName, effect.activeCallsCount);
67
- let newTimer = Hrtime.makeTimer();
68
- Prometheus.SafeCounter.handleFloat(Prometheus.EffectCalls.timeCounter, effectName, Hrtime.secondsBetween(effect.prevCallStartTimerRef, newTimer));
67
+ let newTimer = Performance.now();
68
+ Prometheus.SafeCounter.handleFloat(Prometheus.EffectCalls.timeCounter, effectName, Performance.secondsBetween(effect.prevCallStartTimerRef, newTimer));
69
69
  effect.prevCallStartTimerRef = newTimer;
70
70
  Prometheus.SafeCounter.increment(Prometheus.EffectCalls.totalCallsCount, effectName);
71
- Prometheus.SafeCounter.handleFloat(Prometheus.EffectCalls.sumTimeCounter, effectName, Hrtime.toSecondsFloat(Hrtime.timeSince(timerRef)));
71
+ Prometheus.SafeCounter.handleFloat(Prometheus.EffectCalls.sumTimeCounter, effectName, Performance.secondsSince(timerRef));
72
72
  });
73
73
  }
74
74
 
75
75
  function executeWithRateLimit(effect, effectArgs, inMemTable, onError, isFromQueue) {
76
76
  let effectName = effect.name;
77
- let timerRef = Hrtime.makeTimer();
77
+ let timerRef = Performance.now();
78
78
  let promises = [];
79
79
  let state = effect.rateLimit;
80
80
  if (state !== undefined) {
package/src/Main.res CHANGED
@@ -687,6 +687,10 @@ let dropSchema = async () => {
687
687
  await persistence.storage.close()
688
688
  }
689
689
 
690
+ // Rejection carried by `onError`: the failure is already logged with full
691
+ // context, so callers should act on it (exit / re-throw) without logging again.
692
+ exception FatalError(exn)
693
+
690
694
  let start = async (
691
695
  ~persistence: option<Persistence.t>=?,
692
696
  ~reset=false,
@@ -742,17 +746,20 @@ let start = async (
742
746
  | None => config
743
747
  }
744
748
  // The single fatal-error handler, invoked once via IndexerState.errorExit.
749
+ // It logs the failure once (with chain context) and rejects the run wrapped in
750
+ // `FatalError` so callers know it's already logged — `Bin.res` just exits, the
751
+ // test worker unwraps and re-throws it to the parent thread. `runUntilFatalError`
752
+ // only ever rejects: on a clean run it stays pending and the process exits via
753
+ // ExitOnCaughtUp / when the indexer loop drains.
754
+ let onErrorReject = ref(None)
755
+ let runUntilFatalError: promise<unit> = Promise.make((_resolve, reject) =>
756
+ onErrorReject := Some(reject)
757
+ )
758
+ // `onErrorReject` is filled synchronously by `Promise.make` above, before the
759
+ // indexer can run and call `onError`, so it's always present here.
745
760
  let onError = (errHandler: ErrorHandling.t) => {
746
761
  errHandler->ErrorHandling.log
747
- if isTest {
748
- // The TestIndexer runs the indexer in a worker thread and reads the
749
- // failure off the worker 'error' event. Re-throw the original error
750
- // outside the promise chain on the next tick so the test sees its real
751
- // message instead of a generic non-zero exit code.
752
- NodeJs.setImmediate(() => errHandler->ErrorHandling.raiseExn)
753
- } else {
754
- NodeJs.process->NodeJs.exitWithCode(Failure)
755
- }
762
+ (onErrorReject.contents->Option.getUnsafe)(FatalError(errHandler.exn->Utils.prettifyExn))
756
763
  }
757
764
  let envioVersion = Utils.EnvioPackage.value.version
758
765
  Prometheus.Info.set(~version=envioVersion)
@@ -793,4 +800,5 @@ let start = async (
793
800
  }
794
801
  indexerStateRef := Some(state)
795
802
  state->IndexerLoop.start
803
+ await runUntilFatalError
796
804
  }
package/src/Main.res.mjs CHANGED
@@ -522,6 +522,8 @@ async function dropSchema() {
522
522
  return await persistence.storage.close();
523
523
  }
524
524
 
525
+ let FatalError = /* @__PURE__ */Primitive_exceptions.create("Main.FatalError");
526
+
525
527
  async function start(persistence, resetOpt, isTestOpt, exitAfterFirstEventBlockOpt, patchConfig) {
526
528
  let reset = resetOpt !== undefined ? resetOpt : false;
527
529
  let isTest = isTestOpt !== undefined ? isTestOpt : false;
@@ -562,13 +564,18 @@ async function start(persistence, resetOpt, isTestOpt, exitAfterFirstEventBlockO
562
564
  allEnums: config.allEnums
563
565
  }) : config;
564
566
  let config$2 = patchConfig !== undefined ? patchConfig(config$1, registrations) : config$1;
567
+ let onErrorReject = {
568
+ contents: undefined
569
+ };
570
+ let runUntilFatalError = new Promise((_resolve, reject) => {
571
+ onErrorReject.contents = reject;
572
+ });
565
573
  let onError = errHandler => {
566
574
  ErrorHandling.log(errHandler);
567
- if (isTest) {
568
- setImmediate(() => ErrorHandling.raiseExn(errHandler));
569
- } else {
570
- Process.exit(1);
571
- }
575
+ onErrorReject.contents({
576
+ RE_EXN_ID: FatalError,
577
+ _1: Utils.prettifyExn(errHandler.exn)
578
+ });
572
579
  };
573
580
  let envioVersion = Utils.EnvioPackage.value.version;
574
581
  Prometheus.Info.set(envioVersion);
@@ -599,7 +606,8 @@ async function start(persistence, resetOpt, isTestOpt, exitAfterFirstEventBlockO
599
606
  Tui.start(() => state);
600
607
  }
601
608
  indexerStateRef.contents = Primitive_option.some(state);
602
- return IndexerLoop.start(state);
609
+ IndexerLoop.start(state);
610
+ return await runUntilFatalError;
603
611
  }
604
612
 
605
613
  export {
@@ -616,6 +624,7 @@ export {
616
624
  getEnvioInfo,
617
625
  migrate,
618
626
  dropSchema,
627
+ FatalError,
619
628
  start,
620
629
  }
621
630
  /* chainDataSchema Not a pure module */
package/src/PgStorage.res CHANGED
@@ -1707,13 +1707,13 @@ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::
1707
1707
  // Initialize sink if configured
1708
1708
  let sinkPromise = switch sink {
1709
1709
  | Some(sink) => {
1710
- let timerRef = Hrtime.makeTimer()
1710
+ let timerRef = Performance.now()
1711
1711
  Some(
1712
1712
  sink.writeBatch(~batch, ~updatedEntities=chUpdates)
1713
1713
  ->Promise.thenResolve(_ => {
1714
1714
  Prometheus.StorageWrite.increment(
1715
1715
  ~storage=sink.name,
1716
- ~timeSeconds=timerRef->Hrtime.timeSince->Hrtime.toSecondsFloat,
1716
+ ~timeSeconds=timerRef->Performance.secondsSince,
1717
1717
  )
1718
1718
  None
1719
1719
  })
@@ -1724,7 +1724,7 @@ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::
1724
1724
  | None => None
1725
1725
  }
1726
1726
 
1727
- let primaryTimerRef = Hrtime.makeTimer()
1727
+ let primaryTimerRef = Performance.now()
1728
1728
  await writeBatch(
1729
1729
  sql,
1730
1730
  ~batch,
@@ -1741,7 +1741,7 @@ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::
1741
1741
  )
1742
1742
  Prometheus.StorageWrite.increment(
1743
1743
  ~storage="postgres",
1744
- ~timeSeconds=primaryTimerRef->Hrtime.timeSince->Hrtime.toSecondsFloat,
1744
+ ~timeSeconds=primaryTimerRef->Performance.secondsSince,
1745
1745
  )
1746
1746
  }
1747
1747
 
@@ -8,13 +8,13 @@ import * as Table from "./db/Table.res.mjs";
8
8
  import * as Utils from "./Utils.res.mjs";
9
9
  import * as Config from "./Config.res.mjs";
10
10
  import * as Hasura from "./Hasura.res.mjs";
11
- import * as Hrtime from "./bindings/Hrtime.res.mjs";
12
11
  import * as Schema from "./db/Schema.res.mjs";
13
12
  import * as Logging from "./Logging.res.mjs";
14
13
  import * as Internal from "./Internal.res.mjs";
15
14
  import Postgres from "postgres";
16
15
  import * as ChainState from "./ChainState.res.mjs";
17
16
  import * as Prometheus from "./Prometheus.res.mjs";
17
+ import * as Performance from "./bindings/Performance.res.mjs";
18
18
  import * as Persistence from "./Persistence.res.mjs";
19
19
  import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
20
20
  import * as EntityHistory from "./db/EntityHistory.res.mjs";
@@ -1116,16 +1116,16 @@ SELECT id, chain_id, -1, -1, contract_name FROM unnest($1::text[],$2::int[],$3::
1116
1116
  }
1117
1117
  let sinkPromise;
1118
1118
  if (sink !== undefined) {
1119
- let timerRef = Hrtime.makeTimer();
1119
+ let timerRef = Performance.now();
1120
1120
  sinkPromise = sink.writeBatch(batch, chUpdates).then(() => {
1121
- Prometheus.StorageWrite.increment(sink.name, Hrtime.toSecondsFloat(Hrtime.timeSince(timerRef)));
1121
+ Prometheus.StorageWrite.increment(sink.name, Performance.secondsSince(timerRef));
1122
1122
  }).catch(exn => exn);
1123
1123
  } else {
1124
1124
  sinkPromise = undefined;
1125
1125
  }
1126
- let primaryTimerRef = Hrtime.makeTimer();
1126
+ let primaryTimerRef = Performance.now();
1127
1127
  await writeBatch(sql, batch, pgSchema, rollback, isInReorgThreshold, config, allEntities, setEffectCacheOrThrow, updatedEffectsCache, pgUpdates, sinkPromise, chainMetaData, undefined);
1128
- return Prometheus.StorageWrite.increment("postgres", Hrtime.toSecondsFloat(Hrtime.timeSince(primaryTimerRef)));
1128
+ return Prometheus.StorageWrite.increment("postgres", Performance.secondsSince(primaryTimerRef));
1129
1129
  };
1130
1130
  let close = () => sql.end();
1131
1131
  return {