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.
- package/index.d.ts +23 -5
- package/package.json +6 -6
- package/src/Address.res +5 -2
- package/src/Address.res.mjs +3 -1
- package/src/Api.res +1 -1
- package/src/Api.res.mjs +1 -1
- package/src/ChainFetching.res +34 -34
- package/src/ChainFetching.res.mjs +29 -29
- package/src/ChainState.res +328 -165
- package/src/ChainState.res.mjs +205 -100
- package/src/ChainState.resi +16 -7
- package/src/Config.res +55 -27
- package/src/Config.res.mjs +46 -7
- package/src/ContractRegisterContext.res +2 -12
- package/src/ContractRegisterContext.res.mjs +3 -5
- package/src/Core.res +7 -0
- package/src/CrossChainState.res +54 -79
- package/src/CrossChainState.res.mjs +45 -60
- package/src/CrossChainState.resi +1 -1
- package/src/Ecosystem.res +3 -3
- package/src/Ecosystem.res.mjs +3 -3
- package/src/Envio.res +14 -9
- package/src/EventConfigBuilder.res +105 -56
- package/src/EventConfigBuilder.res.mjs +69 -33
- package/src/EventProcessing.res +19 -15
- package/src/EventProcessing.res.mjs +13 -12
- package/src/FetchState.res +383 -182
- package/src/FetchState.res.mjs +260 -264
- package/src/HandlerLoader.res +7 -112
- package/src/HandlerLoader.res.mjs +1 -87
- package/src/HandlerRegister.res +209 -6
- package/src/HandlerRegister.res.mjs +90 -5
- package/src/HandlerRegister.resi +13 -2
- package/src/IndexerState.res +6 -3
- package/src/IndexerState.res.mjs +3 -3
- package/src/IndexerState.resi +1 -1
- package/src/IndexingAddresses.res +10 -7
- package/src/IndexingAddresses.res.mjs +8 -7
- package/src/IndexingAddresses.resi +3 -1
- package/src/Internal.res +82 -36
- package/src/Internal.res.mjs +11 -1
- package/src/Main.res +22 -23
- package/src/Main.res.mjs +15 -17
- package/src/Metrics.res +43 -2
- package/src/Metrics.res.mjs +39 -3
- package/src/Prometheus.res +0 -35
- package/src/Prometheus.res.mjs +33 -68
- package/src/RawEvent.res +7 -2
- package/src/RawEvent.res.mjs +4 -4
- package/src/SimulateItems.res +26 -8
- package/src/SimulateItems.res.mjs +11 -14
- package/src/TestIndexer.res +1 -1
- package/src/TestIndexer.res.mjs +1 -1
- package/src/sources/BlockStore.res +46 -0
- package/src/sources/BlockStore.res.mjs +24 -0
- package/src/sources/EventRouter.res +19 -12
- package/src/sources/EventRouter.res.mjs +7 -5
- package/src/sources/Evm.res +54 -4
- package/src/sources/Evm.res.mjs +43 -4
- package/src/sources/EvmChain.res +14 -18
- package/src/sources/EvmChain.res.mjs +12 -13
- package/src/sources/FieldMask.res +39 -0
- package/src/sources/FieldMask.res.mjs +42 -0
- package/src/sources/Fuel.res +5 -2
- package/src/sources/Fuel.res.mjs +4 -3
- package/src/sources/HyperFuelSource.res +32 -40
- package/src/sources/HyperFuelSource.res.mjs +53 -45
- package/src/sources/HyperSync.res +35 -9
- package/src/sources/HyperSync.res.mjs +52 -35
- package/src/sources/HyperSync.resi +11 -3
- package/src/sources/HyperSyncClient.res +15 -4
- package/src/sources/HyperSyncHeightStream.res +1 -8
- package/src/sources/HyperSyncHeightStream.res.mjs +0 -2
- package/src/sources/HyperSyncSource.res +39 -58
- package/src/sources/HyperSyncSource.res.mjs +44 -44
- package/src/sources/RpcSource.res +114 -92
- package/src/sources/RpcSource.res.mjs +77 -46
- package/src/sources/RpcWebSocketHeightStream.res +0 -5
- package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -2
- package/src/sources/SimulateSource.res +6 -3
- package/src/sources/SimulateSource.res.mjs +13 -5
- package/src/sources/Source.res +25 -5
- package/src/sources/SourceManager.res +66 -3
- package/src/sources/SourceManager.res.mjs +55 -7
- package/src/sources/SourceManager.resi +10 -0
- package/src/sources/Svm.res +15 -10
- package/src/sources/Svm.res.mjs +24 -7
- package/src/sources/SvmHyperSyncClient.res +5 -6
- package/src/sources/SvmHyperSyncSource.res +84 -41
- package/src/sources/SvmHyperSyncSource.res.mjs +90 -43
- package/src/sources/TransactionStore.res +6 -107
- package/src/sources/TransactionStore.res.mjs +5 -86
- 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
|
-
//
|
|
25
|
-
// field
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
43
|
-
let codes = fieldCodes(fields);
|
|
44
|
-
return selectedTransactionFields => maskFromFields(selectedTransactionFields, codes);
|
|
45
|
-
}
|
|
20
|
+
let orMask = FieldMask.orMask;
|
|
46
21
|
|
|
47
|
-
let
|
|
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
|
-
|
|
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",
|