envio 3.3.0-alpha.6 → 3.3.0-alpha.8

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 (93) hide show
  1. package/index.d.ts +23 -5
  2. package/package.json +6 -6
  3. package/src/Address.res +5 -2
  4. package/src/Address.res.mjs +3 -1
  5. package/src/Api.res +1 -1
  6. package/src/Api.res.mjs +1 -1
  7. package/src/ChainFetching.res +34 -34
  8. package/src/ChainFetching.res.mjs +29 -29
  9. package/src/ChainState.res +328 -165
  10. package/src/ChainState.res.mjs +205 -100
  11. package/src/ChainState.resi +16 -7
  12. package/src/Config.res +55 -27
  13. package/src/Config.res.mjs +46 -7
  14. package/src/ContractRegisterContext.res +2 -12
  15. package/src/ContractRegisterContext.res.mjs +3 -5
  16. package/src/Core.res +7 -0
  17. package/src/CrossChainState.res +54 -79
  18. package/src/CrossChainState.res.mjs +45 -60
  19. package/src/CrossChainState.resi +1 -1
  20. package/src/Ecosystem.res +3 -3
  21. package/src/Ecosystem.res.mjs +3 -3
  22. package/src/Envio.res +14 -9
  23. package/src/EventConfigBuilder.res +105 -56
  24. package/src/EventConfigBuilder.res.mjs +69 -33
  25. package/src/EventProcessing.res +19 -15
  26. package/src/EventProcessing.res.mjs +13 -12
  27. package/src/FetchState.res +383 -182
  28. package/src/FetchState.res.mjs +260 -264
  29. package/src/HandlerLoader.res +7 -112
  30. package/src/HandlerLoader.res.mjs +1 -87
  31. package/src/HandlerRegister.res +209 -6
  32. package/src/HandlerRegister.res.mjs +90 -5
  33. package/src/HandlerRegister.resi +13 -2
  34. package/src/IndexerState.res +6 -3
  35. package/src/IndexerState.res.mjs +3 -3
  36. package/src/IndexerState.resi +1 -1
  37. package/src/IndexingAddresses.res +10 -7
  38. package/src/IndexingAddresses.res.mjs +8 -7
  39. package/src/IndexingAddresses.resi +3 -1
  40. package/src/Internal.res +82 -36
  41. package/src/Internal.res.mjs +11 -1
  42. package/src/Main.res +22 -23
  43. package/src/Main.res.mjs +15 -17
  44. package/src/Metrics.res +43 -2
  45. package/src/Metrics.res.mjs +39 -3
  46. package/src/Prometheus.res +0 -35
  47. package/src/Prometheus.res.mjs +33 -68
  48. package/src/RawEvent.res +7 -2
  49. package/src/RawEvent.res.mjs +4 -4
  50. package/src/SimulateItems.res +26 -8
  51. package/src/SimulateItems.res.mjs +11 -14
  52. package/src/TestIndexer.res +1 -1
  53. package/src/TestIndexer.res.mjs +1 -1
  54. package/src/sources/BlockStore.res +46 -0
  55. package/src/sources/BlockStore.res.mjs +24 -0
  56. package/src/sources/EventRouter.res +19 -12
  57. package/src/sources/EventRouter.res.mjs +7 -5
  58. package/src/sources/Evm.res +54 -4
  59. package/src/sources/Evm.res.mjs +43 -4
  60. package/src/sources/EvmChain.res +14 -18
  61. package/src/sources/EvmChain.res.mjs +12 -13
  62. package/src/sources/FieldMask.res +39 -0
  63. package/src/sources/FieldMask.res.mjs +42 -0
  64. package/src/sources/Fuel.res +5 -2
  65. package/src/sources/Fuel.res.mjs +4 -3
  66. package/src/sources/HyperFuelSource.res +32 -40
  67. package/src/sources/HyperFuelSource.res.mjs +53 -45
  68. package/src/sources/HyperSync.res +35 -9
  69. package/src/sources/HyperSync.res.mjs +52 -35
  70. package/src/sources/HyperSync.resi +11 -3
  71. package/src/sources/HyperSyncClient.res +15 -4
  72. package/src/sources/HyperSyncHeightStream.res +1 -8
  73. package/src/sources/HyperSyncHeightStream.res.mjs +0 -2
  74. package/src/sources/HyperSyncSource.res +39 -58
  75. package/src/sources/HyperSyncSource.res.mjs +44 -44
  76. package/src/sources/RpcSource.res +114 -92
  77. package/src/sources/RpcSource.res.mjs +77 -46
  78. package/src/sources/RpcWebSocketHeightStream.res +0 -5
  79. package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -2
  80. package/src/sources/SimulateSource.res +6 -3
  81. package/src/sources/SimulateSource.res.mjs +13 -5
  82. package/src/sources/Source.res +25 -5
  83. package/src/sources/SourceManager.res +66 -3
  84. package/src/sources/SourceManager.res.mjs +55 -7
  85. package/src/sources/SourceManager.resi +10 -0
  86. package/src/sources/Svm.res +15 -10
  87. package/src/sources/Svm.res.mjs +24 -7
  88. package/src/sources/SvmHyperSyncClient.res +5 -6
  89. package/src/sources/SvmHyperSyncSource.res +84 -41
  90. package/src/sources/SvmHyperSyncSource.res.mjs +90 -43
  91. package/src/sources/TransactionStore.res +6 -107
  92. package/src/sources/TransactionStore.res.mjs +5 -86
  93. package/svm.schema.json +19 -0
@@ -21,42 +21,12 @@ let make = (~ecosystem: Ecosystem.name, ~shouldChecksum: bool): t => {
21
21
  }
22
22
  }
23
23
 
24
- // Field-name bit-index map from an ordered field-name array. The index is the
25
- // field code shared with the Rust store (`EvmTxField`/`SvmTxField`).
26
- let fieldCodes = (fields: array<string>): dict<int> => {
27
- let codes = Dict.make()
28
- fields->Array.forEachWithIndex((name, i) => codes->Dict.set(name, i))
29
- codes
30
- }
31
-
32
- let pow2: int => float = %raw(`c => Math.pow(2, c)`)
33
-
34
- // One event's selected transaction fields as a bitmask float (bit `code` set ⇔
35
- // selected). Each field appears once, so summing `pow2(code)` sets distinct bits
36
- // with no overlap; the result stays exact in f64 (codes span 0..31, so a mask is
37
- // at most 2^32-1).
38
- let maskFromFields = (selectedTransactionFields: Utils.Set.t<string>, ~codes: dict<int>): float => {
39
- let mask = ref(0.)
40
- selectedTransactionFields->Utils.Set.forEach(name =>
41
- switch codes->Utils.Dict.dangerouslyGetNonOption(name) {
42
- | Some(code) => mask := mask.contents +. pow2(code)
43
- | None => ()
44
- }
45
- )
46
- mask.contents
47
- }
48
-
49
- // Build an ecosystem's per-event mask function from its ordered field-name
50
- // array. The field codes are derived once and closed over.
51
- let makeMaskFn = (fields: array<string>): (Utils.Set.t<string> => float) => {
52
- let codes = fieldCodes(fields)
53
- selectedTransactionFields => selectedTransactionFields->maskFromFields(~codes)
54
- }
55
-
56
- // Bitwise OR of two per-event masks. Masks fit in 32 bits (≤32 transaction
57
- // fields), so `>>> 0` recovers the unsigned value that a plain `|` renders
58
- // negative once bit 31 is set.
59
- let orMask: (float, float) => float = %raw(`(a, b) => (a | b) >>> 0`)
24
+ // One event's selected transaction fields store selection bitmask, built from
25
+ // the ecosystem's ordered field-name array (the bit index is the field code
26
+ // shared with the Rust store, `EvmTxField`/`SvmTxField`).
27
+ let makeMaskFn = FieldMask.makeMaskFn
28
+ let orMask = FieldMask.orMask
29
+ let fieldCodes = FieldMask.fieldCodes
60
30
 
61
31
  // Drain another store (a fetch-response page) into this one.
62
32
  @send external merge: (t, t) => unit = "merge"
@@ -77,74 +47,3 @@ external materialize: (
77
47
 
78
48
  // Drop transactions for blocks above the given block (rolled back).
79
49
  @send external rollback: (t, int) => unit = "rollback"
80
-
81
- // Materialise each store-backed item's selected transaction fields and write the
82
- // resulting transaction onto its payload. Every event's mask comes from its own
83
- // `eventConfig.transactionFieldMask`, so a transaction decodes only the fields
84
- // the events on it selected — a large field (e.g. `input`) never materialises
85
- // for events that didn't ask for it. Items that already carry an inline
86
- // transaction (RPC/simulate/Fuel) are skipped. Store-backed items always get a
87
- // transaction object — the selected fields, or `{}` when nothing was selected —
88
- // so `event.transaction` is never `undefined` (matching the inline sources).
89
- // Deduped per (blockNumber, transactionIndex); each row's mask is the OR of the
90
- // masks of the events sharing that transaction.
91
- let materializeItems = async (store: t, ~items: array<Internal.item>) => {
92
- // Store-backed items arrive in (block, logIndex) order, and a transaction's
93
- // logs are contiguous within a block, so events sharing a (blockNumber,
94
- // transactionIndex) are adjacent regardless of event. Group them by extending
95
- // the current run rather than hashing a string key per item. A key recurring
96
- // non-adjacently just splits into two groups (one redundant decode) — never
97
- // incorrect.
98
- let blockNumbers = []
99
- let transactionIndices = []
100
- let masks = []
101
- let payloadGroups = []
102
- let anySelected = ref(false)
103
-
104
- items->Array.forEach(item =>
105
- switch item {
106
- | Internal.Event(_) =>
107
- let eventItem = item->Internal.castUnsafeEventItem
108
- switch eventItem.payload->Internal.getPayloadTransaction->Nullable.toOption {
109
- | Some(_) => () // RPC/simulate/Fuel carry the transaction inline.
110
- | None =>
111
- let {blockNumber, transactionIndex} = eventItem
112
- let mask = eventItem.eventConfig.transactionFieldMask
113
- if mask != 0. {
114
- anySelected := true
115
- }
116
- let last = payloadGroups->Array.length - 1
117
- if (
118
- last >= 0 &&
119
- blockNumbers->Array.getUnsafe(last) == blockNumber &&
120
- transactionIndices->Array.getUnsafe(last) == transactionIndex
121
- ) {
122
- payloadGroups->Array.getUnsafe(last)->Array.push(eventItem.payload)
123
- masks->Array.setUnsafe(last, orMask(masks->Array.getUnsafe(last), mask))
124
- } else {
125
- blockNumbers->Array.push(blockNumber)
126
- transactionIndices->Array.push(transactionIndex)
127
- masks->Array.push(mask)
128
- payloadGroups->Array.push([eventItem.payload])
129
- }
130
- }
131
- | Internal.Block(_) => ()
132
- }
133
- )
134
-
135
- if payloadGroups->Utils.Array.notEmpty {
136
- if anySelected.contents {
137
- let txs = await store->materialize(~blockNumbers, ~transactionIndices, ~masks)
138
- payloadGroups->Array.forEachWithIndex((payloads, i) => {
139
- let tx = txs->Array.getUnsafe(i)
140
- payloads->Array.forEach(payload => payload->Internal.setPayloadTransaction(tx))
141
- })
142
- } else {
143
- // No event selected any field: stamp an empty transaction object so
144
- // `event.transaction` is never undefined, without a materialize call.
145
- payloadGroups->Array.forEach(payloads =>
146
- payloads->Array.forEach(payload => payload->Internal.setPayloadTransaction(%raw(`{}`)))
147
- )
148
- }
149
- }
150
- }
@@ -1,7 +1,7 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as Core from "../Core.res.mjs";
4
- import * as Utils from "../Utils.res.mjs";
4
+ import * as FieldMask from "./FieldMask.res.mjs";
5
5
 
6
6
  function make(ecosystem, shouldChecksum) {
7
7
  let ctor = Core.getAddon().TransactionStore;
@@ -15,97 +15,16 @@ function make(ecosystem, shouldChecksum) {
15
15
  }
16
16
  }
17
17
 
18
- function fieldCodes(fields) {
19
- let codes = {};
20
- fields.forEach((name, i) => {
21
- codes[name] = i;
22
- });
23
- return codes;
24
- }
25
-
26
- let pow2 = (c => Math.pow(2, c));
27
-
28
- function maskFromFields(selectedTransactionFields, codes) {
29
- let mask = {
30
- contents: 0
31
- };
32
- selectedTransactionFields.forEach(name => {
33
- let code = codes[name];
34
- if (code !== undefined) {
35
- mask.contents = mask.contents + pow2(code);
36
- return;
37
- }
38
- });
39
- return mask.contents;
40
- }
18
+ let makeMaskFn = FieldMask.makeMaskFn;
41
19
 
42
- function makeMaskFn(fields) {
43
- let codes = fieldCodes(fields);
44
- return selectedTransactionFields => maskFromFields(selectedTransactionFields, codes);
45
- }
20
+ let orMask = FieldMask.orMask;
46
21
 
47
- let orMask = ((a, b) => (a | b) >>> 0);
48
-
49
- async function materializeItems(store, items) {
50
- let blockNumbers = [];
51
- let transactionIndices = [];
52
- let masks = [];
53
- let payloadGroups = [];
54
- let anySelected = {
55
- contents: false
56
- };
57
- items.forEach(item => {
58
- if (item.kind !== 0) {
59
- return;
60
- }
61
- let match = item.payload.transaction;
62
- if (!(match == null)) {
63
- return;
64
- }
65
- let transactionIndex = item.transactionIndex;
66
- let blockNumber = item.blockNumber;
67
- let mask = item.eventConfig.transactionFieldMask;
68
- if (mask !== 0) {
69
- anySelected.contents = true;
70
- }
71
- let last = payloadGroups.length - 1 | 0;
72
- if (last >= 0 && blockNumbers[last] === blockNumber && transactionIndices[last] === transactionIndex) {
73
- payloadGroups[last].push(item.payload);
74
- masks[last] = orMask(masks[last], mask);
75
- } else {
76
- blockNumbers.push(blockNumber);
77
- transactionIndices.push(transactionIndex);
78
- masks.push(mask);
79
- payloadGroups.push([item.payload]);
80
- }
81
- });
82
- if (!Utils.$$Array.notEmpty(payloadGroups)) {
83
- return;
84
- }
85
- if (anySelected.contents) {
86
- let txs = await store.materialize(blockNumbers, transactionIndices, masks);
87
- payloadGroups.forEach((payloads, i) => {
88
- let tx = txs[i];
89
- payloads.forEach(payload => {
90
- payload.transaction = tx;
91
- });
92
- });
93
- return;
94
- }
95
- payloadGroups.forEach(payloads => {
96
- payloads.forEach(payload => {
97
- payload.transaction = {};
98
- });
99
- });
100
- }
22
+ let fieldCodes = FieldMask.fieldCodes;
101
23
 
102
24
  export {
103
25
  make,
104
- fieldCodes,
105
- pow2,
106
- maskFromFields,
107
26
  makeMaskFn,
108
27
  orMask,
109
- materializeItems,
28
+ fieldCodes,
110
29
  }
111
30
  /* Core Not a pure module */
package/svm.schema.json CHANGED
@@ -472,6 +472,16 @@
472
472
  "$ref": "#/$defs/SvmTransactionField"
473
473
  }
474
474
  },
475
+ "block_fields": {
476
+ "description": "Block fields to include on each matched instruction's `block`, as a list of field names. `slot`/`time`/`hash` are always included; this adds `height`/`parentSlot`/`parentHash`.",
477
+ "type": [
478
+ "array",
479
+ "null"
480
+ ],
481
+ "items": {
482
+ "$ref": "#/$defs/SvmBlockField"
483
+ }
484
+ },
475
485
  "log_fields": {
476
486
  "description": "Set to `true` to include program logs scoped to each matched instruction.",
477
487
  "type": [
@@ -505,6 +515,15 @@
505
515
  "version"
506
516
  ]
507
517
  },
518
+ "SvmBlockField": {
519
+ "description": "Selectable block field names (camelCase), matching the public\n`instruction.block` shape. `slot`/`time`/`hash` are always included,\nso everything here is opt-in on top of that trio.",
520
+ "type": "string",
521
+ "enum": [
522
+ "height",
523
+ "parentSlot",
524
+ "parentHash"
525
+ ]
526
+ },
508
527
  "ArgDef": {
509
528
  "description": "One named argument of an instruction. Mirrors\n`hypersync_client_solana::decode::NamedField`.",
510
529
  "type": "object",