envio 3.3.0-alpha.0 → 3.3.0-alpha.10

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 (140) hide show
  1. package/evm.schema.json +10 -0
  2. package/index.d.ts +45 -25
  3. package/package.json +7 -7
  4. package/src/Address.res +5 -2
  5. package/src/Address.res.mjs +3 -1
  6. package/src/Api.res +1 -1
  7. package/src/Api.res.mjs +1 -1
  8. package/src/Batch.res +0 -6
  9. package/src/Batch.res.mjs +1 -12
  10. package/src/BatchProcessing.res +7 -12
  11. package/src/BatchProcessing.res.mjs +8 -7
  12. package/src/Bin.res +3 -0
  13. package/src/Bin.res.mjs +4 -0
  14. package/src/ChainFetching.res +48 -16
  15. package/src/ChainFetching.res.mjs +36 -17
  16. package/src/ChainMetadata.res +1 -11
  17. package/src/ChainMetadata.res.mjs +1 -10
  18. package/src/ChainState.res +628 -149
  19. package/src/ChainState.res.mjs +440 -102
  20. package/src/ChainState.resi +74 -4
  21. package/src/Config.res +61 -33
  22. package/src/Config.res.mjs +50 -10
  23. package/src/ContractRegisterContext.res +2 -12
  24. package/src/ContractRegisterContext.res.mjs +3 -5
  25. package/src/Core.res +14 -3
  26. package/src/CrossChainState.res +142 -93
  27. package/src/CrossChainState.res.mjs +88 -60
  28. package/src/CrossChainState.resi +2 -10
  29. package/src/Ecosystem.res +5 -6
  30. package/src/Ecosystem.res.mjs +3 -3
  31. package/src/Env.res +0 -7
  32. package/src/Env.res.mjs +0 -6
  33. package/src/Envio.res +17 -11
  34. package/src/EnvioGlobal.res +53 -0
  35. package/src/EnvioGlobal.res.mjs +31 -0
  36. package/src/EventConfigBuilder.res +177 -88
  37. package/src/EventConfigBuilder.res.mjs +99 -42
  38. package/src/EventProcessing.res +74 -28
  39. package/src/EventProcessing.res.mjs +55 -29
  40. package/src/ExitOnCaughtUp.res +10 -2
  41. package/src/ExitOnCaughtUp.res.mjs +10 -1
  42. package/src/FetchState.res +558 -300
  43. package/src/FetchState.res.mjs +437 -423
  44. package/src/HandlerLoader.res +8 -104
  45. package/src/HandlerLoader.res.mjs +2 -81
  46. package/src/HandlerRegister.res +518 -144
  47. package/src/HandlerRegister.res.mjs +285 -133
  48. package/src/HandlerRegister.resi +24 -8
  49. package/src/IndexerLoop.res +2 -3
  50. package/src/IndexerLoop.res.mjs +1 -1
  51. package/src/IndexerState.res +10 -11
  52. package/src/IndexerState.res.mjs +14 -11
  53. package/src/IndexerState.resi +2 -5
  54. package/src/IndexingAddresses.res +108 -0
  55. package/src/IndexingAddresses.res.mjs +101 -0
  56. package/src/IndexingAddresses.resi +34 -0
  57. package/src/Internal.res +155 -46
  58. package/src/Internal.res.mjs +30 -2
  59. package/src/LoadLayer.res +5 -5
  60. package/src/LoadLayer.res.mjs +6 -6
  61. package/src/LogSelection.res +102 -165
  62. package/src/LogSelection.res.mjs +101 -116
  63. package/src/Main.res +71 -236
  64. package/src/Main.res.mjs +60 -145
  65. package/src/Metrics.res +74 -0
  66. package/src/Metrics.res.mjs +75 -0
  67. package/src/PgStorage.res +4 -4
  68. package/src/PgStorage.res.mjs +5 -5
  69. package/src/Prometheus.res +10 -74
  70. package/src/Prometheus.res.mjs +124 -186
  71. package/src/PruneStaleHistory.res +2 -2
  72. package/src/PruneStaleHistory.res.mjs +3 -3
  73. package/src/RawEvent.res +7 -2
  74. package/src/RawEvent.res.mjs +4 -4
  75. package/src/Rollback.res +3 -3
  76. package/src/Rollback.res.mjs +4 -4
  77. package/src/RollbackCommit.res +4 -1
  78. package/src/RollbackCommit.res.mjs +3 -2
  79. package/src/SimulateDeadInputTracker.res +85 -0
  80. package/src/SimulateDeadInputTracker.res.mjs +73 -0
  81. package/src/SimulateDeadInputTracker.resi +12 -0
  82. package/src/SimulateItems.res +91 -23
  83. package/src/SimulateItems.res.mjs +55 -32
  84. package/src/TestIndexer.res +54 -40
  85. package/src/TestIndexer.res.mjs +37 -30
  86. package/src/bindings/Performance.res +7 -0
  87. package/src/bindings/Performance.res.mjs +21 -0
  88. package/src/bindings/Performance.resi +7 -0
  89. package/src/bindings/Viem.res +0 -41
  90. package/src/bindings/Viem.res.mjs +1 -43
  91. package/src/sources/BlockStore.res +46 -0
  92. package/src/sources/BlockStore.res.mjs +24 -0
  93. package/src/sources/EventRouter.res +36 -33
  94. package/src/sources/EventRouter.res.mjs +13 -14
  95. package/src/sources/Evm.res +83 -72
  96. package/src/sources/Evm.res.mjs +53 -69
  97. package/src/sources/EvmChain.res +18 -20
  98. package/src/sources/EvmChain.res.mjs +15 -15
  99. package/src/sources/EvmRpcClient.res +74 -5
  100. package/src/sources/EvmRpcClient.res.mjs +13 -4
  101. package/src/sources/FieldMask.res +39 -0
  102. package/src/sources/FieldMask.res.mjs +42 -0
  103. package/src/sources/Fuel.res +9 -6
  104. package/src/sources/Fuel.res.mjs +5 -10
  105. package/src/sources/HyperFuelSource.res +46 -50
  106. package/src/sources/HyperFuelSource.res.mjs +64 -54
  107. package/src/sources/HyperSync.res +39 -7
  108. package/src/sources/HyperSync.res.mjs +57 -37
  109. package/src/sources/HyperSync.resi +12 -2
  110. package/src/sources/HyperSyncClient.res +22 -111
  111. package/src/sources/HyperSyncClient.res.mjs +2 -30
  112. package/src/sources/HyperSyncHeightStream.res +1 -8
  113. package/src/sources/HyperSyncHeightStream.res.mjs +0 -2
  114. package/src/sources/HyperSyncSource.res +94 -107
  115. package/src/sources/HyperSyncSource.res.mjs +82 -86
  116. package/src/sources/Rpc.res +15 -47
  117. package/src/sources/Rpc.res.mjs +25 -56
  118. package/src/sources/RpcSource.res +320 -467
  119. package/src/sources/RpcSource.res.mjs +268 -385
  120. package/src/sources/RpcWebSocketHeightStream.res +0 -5
  121. package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -2
  122. package/src/sources/SimulateSource.res +10 -4
  123. package/src/sources/SimulateSource.res.mjs +16 -6
  124. package/src/sources/Source.res +34 -6
  125. package/src/sources/SourceManager.res +86 -27
  126. package/src/sources/SourceManager.res.mjs +84 -47
  127. package/src/sources/SourceManager.resi +12 -3
  128. package/src/sources/Svm.res +31 -16
  129. package/src/sources/Svm.res.mjs +36 -13
  130. package/src/sources/SvmHyperSyncClient.res +5 -32
  131. package/src/sources/SvmHyperSyncSource.res +159 -134
  132. package/src/sources/SvmHyperSyncSource.res.mjs +164 -129
  133. package/src/sources/TransactionStore.res +49 -0
  134. package/src/sources/TransactionStore.res.mjs +30 -0
  135. package/src/tui/Tui.res +13 -16
  136. package/src/tui/Tui.res.mjs +12 -14
  137. package/svm.schema.json +49 -37
  138. package/src/bindings/Hrtime.res +0 -58
  139. package/src/bindings/Hrtime.res.mjs +0 -90
  140. package/src/bindings/Hrtime.resi +0 -30
@@ -21,18 +21,27 @@ let make: (
21
21
 
22
22
  let getActiveSource: t => Source.t
23
23
 
24
+ type requestStatSample = {
25
+ sourceName: string,
26
+ chainId: int,
27
+ method: string,
28
+ count: int,
29
+ seconds: float,
30
+ }
31
+
32
+ let getRequestStatSamples: t => array<requestStatSample>
33
+
24
34
  let inFlightCount: t => int
25
35
 
26
36
  let onReorg: (t, ~rollbackTargetBlock: int) => unit
27
37
 
28
- let fetchNext: (
38
+ let dispatch: (
29
39
  t,
30
40
  ~fetchState: FetchState.t,
31
41
  ~executeQuery: FetchState.query => promise<unit>,
32
42
  ~waitForNewBlock: (~knownHeight: int) => promise<int>,
33
43
  ~onNewBlock: (~knownHeight: int) => unit,
34
- ~concurrencyLimit: int,
35
- ~bufferLimit: int,
44
+ ~action: FetchState.nextQuery,
36
45
  ~stateId: int,
37
46
  ) => promise<unit>
38
47
 
@@ -4,10 +4,31 @@ let cleanUpRawEventFieldsInPlace: JSON.t => unit = %raw(`fields => {
4
4
  delete fields.time
5
5
  }`)
6
6
 
7
+ // Ordered transaction field names, the field codes shared with the Rust store
8
+ // (`SvmTxField`). Derived from the typed field list so the two can't drift;
9
+ // `Internal.allSvmTransactionFields` is pinned to the Rust ordinal order by a test.
10
+ let transactionFields =
11
+ Internal.allSvmTransactionFields->(
12
+ Utils.magic: array<Internal.svmTransactionField> => array<string>
13
+ )
14
+
15
+ // One instruction's selected transaction fields → store selection bitmask.
16
+ // Computed per event at config build and cached on the event config.
17
+ let eventTransactionFieldMask = TransactionStore.makeMaskFn(transactionFields)
18
+
19
+ // Ordered block field names. The index of each is the field code shared with the
20
+ // Rust store (`SvmBlockField`) — keep this order in sync.
21
+ let blockFields = ["slot", "time", "hash", "height", "parentSlot", "parentHash"]
22
+
23
+ // `slot`/`time`/`hash` are always included; every other block field is opt-in
24
+ // via `field_selection.block_fields`. All are materialised from the store.
25
+ //
26
+ // One instruction's selected block fields → store selection bitmask. Computed per
27
+ // event at config build and cached on the event config.
28
+ let eventBlockFieldMask = BlockStore.makeMaskFn(blockFields)
29
+
7
30
  let make = (~logger: Pino.t): Ecosystem.t => {
8
31
  name: Svm,
9
- blockFields: ["slot"],
10
- transactionFields: [],
11
32
  blockNumberName: "height",
12
33
  blockTimestampName: "time",
13
34
  blockHashName: "hash",
@@ -20,15 +41,15 @@ let make = (~logger: Pino.t): Ecosystem.t => {
20
41
  // parse. The schema is a no-op object that always surfaces `None`.
21
42
  onEventBlockFilterSchema: S.object(_ => None),
22
43
  logger,
23
- toEvent: eventItem => eventItem.payload->Internal.payloadToEvent,
44
+ toEvent: eventItem => eventItem.payload->(Utils.magic: Internal.eventPayload => Internal.event),
24
45
  toEventLogger: eventItem => {
25
46
  let instruction =
26
47
  eventItem.payload->(Utils.magic: Internal.eventPayload => Envio.svmInstruction)
27
48
  Logging.createChildFrom(
28
49
  ~logger,
29
50
  ~params={
30
- "program": eventItem.eventConfig.contractName,
31
- "instruction": eventItem.eventConfig.name,
51
+ "program": eventItem.onEventRegistration.eventConfig.contractName,
52
+ "instruction": eventItem.onEventRegistration.eventConfig.name,
32
53
  "chainId": eventItem.chain->ChainMap.Chain.toChainId,
33
54
  "slot": eventItem.blockNumber,
34
55
  "programId": instruction.programId,
@@ -71,26 +92,20 @@ let makeRPCSource = (~chain, ~rpc: string, ~sourceFor: Source.sourceFor=Sync): S
71
92
  getBlockHashes: (~blockNumbers as _, ~logger as _) =>
72
93
  JsError.throwWithMessage("Svm does not support getting block hashes"),
73
94
  getHeightOrThrow: async () => {
74
- let timerRef = Hrtime.makeTimer()
95
+ let timerRef = Performance.now()
75
96
  let height = await GetFinalizedSlot.route->Rest.fetch((), ~client)
76
- let seconds = timerRef->Hrtime.timeSince->Hrtime.toSecondsFloat
77
- Prometheus.SourceRequestCount.increment(~sourceName=name, ~chainId, ~method="getSlot")
78
- Prometheus.SourceRequestCount.addSeconds(
79
- ~sourceName=name,
80
- ~chainId,
81
- ~method="getSlot",
82
- ~seconds,
83
- )
84
- height
97
+ let seconds = timerRef->Performance.secondsSince
98
+ {Source.height, requestStats: [{Source.method: "getSlot", seconds}]}
85
99
  },
86
100
  getItemsOrThrow: (
87
101
  ~fromBlock as _,
88
102
  ~toBlock as _,
89
103
  ~addressesByContractName as _,
90
- ~indexingAddresses as _,
104
+ ~contractNameByAddress as _,
91
105
  ~knownHeight as _,
92
106
  ~partitionId as _,
93
107
  ~selection as _,
108
+ ~itemsTarget as _,
94
109
  ~retry as _,
95
110
  ~logger as _,
96
111
  ) => JsError.throwWithMessage("Svm does not support getting items"),
@@ -3,11 +3,13 @@
3
3
  import * as Rpc from "./Rpc.res.mjs";
4
4
  import * as Rest from "../vendored/Rest.res.mjs";
5
5
  import * as Utils from "../Utils.res.mjs";
6
- import * as Hrtime from "../bindings/Hrtime.res.mjs";
7
6
  import * as Logging from "../Logging.res.mjs";
8
- import * as Prometheus from "../Prometheus.res.mjs";
7
+ import * as Internal from "../Internal.res.mjs";
8
+ import * as BlockStore from "./BlockStore.res.mjs";
9
+ import * as Performance from "../bindings/Performance.res.mjs";
9
10
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
10
11
  import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
12
+ import * as TransactionStore from "./TransactionStore.res.mjs";
11
13
 
12
14
  let cleanUpRawEventFieldsInPlace = (fields => {
13
15
  delete fields.hash
@@ -15,11 +17,22 @@ let cleanUpRawEventFieldsInPlace = (fields => {
15
17
  delete fields.time
16
18
  });
17
19
 
20
+ let eventTransactionFieldMask = TransactionStore.makeMaskFn(Internal.allSvmTransactionFields);
21
+
22
+ let blockFields = [
23
+ "slot",
24
+ "time",
25
+ "hash",
26
+ "height",
27
+ "parentSlot",
28
+ "parentHash"
29
+ ];
30
+
31
+ let eventBlockFieldMask = BlockStore.makeMaskFn(blockFields);
32
+
18
33
  function make(logger) {
19
34
  return {
20
35
  name: "svm",
21
- blockFields: ["slot"],
22
- transactionFields: [],
23
36
  blockNumberName: "height",
24
37
  blockTimestampName: "time",
25
38
  blockHashName: "hash",
@@ -32,8 +45,8 @@ function make(logger) {
32
45
  toEventLogger: eventItem => {
33
46
  let instruction = eventItem.payload;
34
47
  return Logging.createChildFrom(logger, {
35
- program: eventItem.eventConfig.contractName,
36
- instruction: eventItem.eventConfig.name,
48
+ program: eventItem.onEventRegistration.eventConfig.contractName,
49
+ instruction: eventItem.onEventRegistration.eventConfig.name,
37
50
  chainId: eventItem.chain,
38
51
  slot: eventItem.blockNumber,
39
52
  programId: instruction.programId
@@ -67,21 +80,31 @@ function makeRPCSource(chain, rpc, sourceForOpt) {
67
80
  pollingInterval: 10000,
68
81
  getBlockHashes: (param, param$1) => Stdlib_JsError.throwWithMessage("Svm does not support getting block hashes"),
69
82
  getHeightOrThrow: async () => {
70
- let timerRef = Hrtime.makeTimer();
83
+ let timerRef = Performance.now();
71
84
  let height = await Rest.fetch(route, undefined, client);
72
- let seconds = Hrtime.toSecondsFloat(Hrtime.timeSince(timerRef));
73
- Prometheus.SourceRequestCount.increment(name, chain, "getSlot");
74
- Prometheus.SourceRequestCount.addSeconds(name, chain, "getSlot", seconds);
75
- return height;
85
+ let seconds = Performance.secondsSince(timerRef);
86
+ return {
87
+ height: height,
88
+ requestStats: [{
89
+ method: "getSlot",
90
+ seconds: seconds
91
+ }]
92
+ };
76
93
  },
77
- getItemsOrThrow: (param, param$1, param$2, param$3, param$4, param$5, param$6, param$7, param$8) => Stdlib_JsError.throwWithMessage("Svm does not support getting items")
94
+ getItemsOrThrow: (param, param$1, param$2, param$3, param$4, param$5, param$6, param$7, param$8, param$9) => Stdlib_JsError.throwWithMessage("Svm does not support getting items")
78
95
  };
79
96
  }
80
97
 
98
+ let transactionFields = Internal.allSvmTransactionFields;
99
+
81
100
  export {
82
101
  cleanUpRawEventFieldsInPlace,
102
+ transactionFields,
103
+ eventTransactionFieldMask,
104
+ blockFields,
105
+ eventBlockFieldMask,
83
106
  make,
84
107
  GetFinalizedSlot,
85
108
  makeRPCSource,
86
109
  }
87
- /* route Not a pure module */
110
+ /* eventTransactionFieldMask Not a pure module */
@@ -138,29 +138,12 @@ module QueryTypes = {
138
138
  }
139
139
 
140
140
  module ResponseTypes = {
141
+ // Lean per-slot header for reorg detection and each item's slot/time; the
142
+ // selectable fields live in the block store and are materialised on demand.
141
143
  type block = {
142
144
  slot: int,
143
145
  blockhash: string,
144
- parentSlot?: int,
145
- parentBlockhash?: string,
146
146
  blockTime?: int,
147
- blockHeight?: int,
148
- }
149
-
150
- type transaction = {
151
- slot: int,
152
- transactionIndex: int,
153
- signatures: array<string>,
154
- feePayer?: string,
155
- success?: bool,
156
- err?: string,
157
- fee?: int,
158
- computeUnitsConsumed?: int,
159
- accountKeys: array<string>,
160
- recentBlockhash?: string,
161
- version?: string,
162
- loadedAddressesWritable: array<string>,
163
- loadedAddressesReadonly: array<string>,
164
147
  }
165
148
 
166
149
  /// Borsh-decoded view attached by the Rust client. `argsJson`/`accountsJson`
@@ -204,22 +187,10 @@ module ResponseTypes = {
204
187
  message?: string,
205
188
  }
206
189
 
207
- type tokenBalance = {
208
- slot: int,
209
- transactionIndex?: int,
210
- account?: string,
211
- mint?: string,
212
- owner?: string,
213
- preAmount?: string,
214
- postAmount?: string,
215
- }
216
-
217
190
  type queryResponseData = {
218
191
  blocks: array<block>,
219
- transactions: array<transaction>,
220
192
  instructions: array<instruction>,
221
193
  logs: array<log>,
222
- tokenBalances: array<tokenBalance>,
223
194
  }
224
195
 
225
196
  type queryResponse = {
@@ -234,7 +205,9 @@ type queryResponse = ResponseTypes.queryResponse
234
205
 
235
206
  type t = {
236
207
  getHeight: unit => promise<int>,
237
- get: (~query: query) => promise<queryResponse>,
208
+ // Returns the response plus pages of raw transactions and blocks (kept in
209
+ // Rust), keyed by (slot, transactionIndex) / slot, materialised at batch prep.
210
+ get: (~query: query) => promise<(queryResponse, TransactionStore.t, BlockStore.t)>,
238
211
  }
239
212
 
240
213
  @send