envio 3.9.0 → 3.10.0
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/evm.schema.json +26 -0
- package/fuel.schema.json +26 -0
- package/index.d.ts +35 -3
- package/package.json +6 -7
- package/src/Batch.res +9 -0
- package/src/ChainState.res +35 -39
- package/src/ChainState.res.mjs +14 -11
- package/src/ChainState.resi +15 -7
- package/src/Config.res +52 -44
- package/src/Config.res.mjs +51 -17
- package/src/Core.res +4 -0
- package/src/CrossChainState.res +15 -23
- package/src/CrossChainState.res.mjs +10 -18
- package/src/CrossChainState.resi +4 -1
- package/src/Ecosystem.res +7 -2
- package/src/Envio.res +6 -4
- package/src/EventConfigBuilder.res +169 -26
- package/src/EventConfigBuilder.res.mjs +124 -15
- package/src/HandlerRegister.res +21 -4
- package/src/HandlerRegister.res.mjs +24 -5
- package/src/InMemoryStore.res +9 -7
- package/src/InMemoryStore.res.mjs +3 -3
- package/src/IndexerState.res +43 -6
- package/src/IndexerState.res.mjs +36 -7
- package/src/IndexerState.resi +4 -4
- package/src/Internal.res +16 -17
- package/src/Metrics.res +72 -6
- package/src/Metrics.res.mjs +30 -2
- package/src/Persistence.res +36 -30
- package/src/Persistence.res.mjs +1 -20
- package/src/PgStorage.res +104 -56
- package/src/PgStorage.res.mjs +57 -35
- package/src/PruneStaleHistory.res +85 -52
- package/src/PruneStaleHistory.res.mjs +63 -37
- package/src/Rollback.res +68 -45
- package/src/Rollback.res.mjs +38 -19
- package/src/RollbackCommit.res +7 -9
- package/src/RollbackCommit.res.mjs +5 -6
- package/src/SafeCheckpointTracking.res +11 -11
- package/src/SafeCheckpointTracking.res.mjs +7 -6
- package/src/SimulateItems.res +33 -18
- package/src/SimulateItems.res.mjs +26 -22
- package/src/Sink.res +38 -26
- package/src/Sink.res.mjs +21 -16
- package/src/TestIndexer.res +5 -5
- package/src/TestIndexer.res.mjs +1 -1
- package/src/Utils.res +170 -0
- package/src/Utils.res.mjs +153 -0
- package/src/Writing.res +2 -2
- package/src/Writing.res.mjs +1 -1
- package/src/bindings/ClickHouse.res +366 -698
- package/src/bindings/ClickHouse.res.mjs +371 -421
- package/src/bindings/ClickHouseSink.res +337 -0
- package/src/bindings/ClickHouseSink.res.mjs +246 -0
- package/src/bindings/EventSource.res +8 -2
- package/src/bindings/NodeJs.res +6 -0
- package/src/bindings/Vitest.res +23 -0
- package/src/bindings/Vitest.res.mjs +3 -0
- package/src/bindings/WebSocket.res +9 -10
- package/src/db/CheckpointBounds.res +53 -0
- package/src/db/CheckpointBounds.res.mjs +44 -0
- package/src/db/EntityFilter.res +36 -17
- package/src/db/EntityFilter.res.mjs +25 -14
- package/src/db/EntityHistory.res +47 -22
- package/src/db/EntityHistory.res.mjs +19 -12
- package/src/db/InternalTable.res +84 -35
- package/src/db/InternalTable.res.mjs +56 -23
- package/src/db/RollbackFloors.res +55 -0
- package/src/db/RollbackFloors.res.mjs +92 -0
- package/src/db/Table.res +22 -4
- package/src/db/Table.res.mjs +30 -9
- package/src/sources/Evm.res +2 -0
- package/src/sources/Evm.res.mjs +2 -0
- package/src/sources/EvmHyperSyncSource.res +3 -3
- package/src/sources/EvmHyperSyncSource.res.mjs +3 -3
- package/src/sources/EvmRpcWs.res +124 -0
- package/src/sources/EvmRpcWs.res.mjs +117 -0
- package/src/sources/Fuel.res +2 -0
- package/src/sources/Fuel.res.mjs +2 -0
- package/src/sources/FuelHyperSyncSource.res +1 -1
- package/src/sources/FuelHyperSyncSource.res.mjs +2 -1
- package/src/sources/HeightFeed.res +568 -0
- package/src/sources/HeightFeed.res.mjs +452 -0
- package/src/sources/HeightStream.res +257 -0
- package/src/sources/HeightStream.res.mjs +194 -0
- package/src/sources/HyperSync.res +5 -0
- package/src/sources/HyperSync.res.mjs +3 -0
- package/src/sources/HyperSync.resi +4 -0
- package/src/sources/HyperSyncSSE.res +49 -0
- package/src/sources/HyperSyncSSE.res.mjs +79 -0
- package/src/sources/RpcSource.res +1 -1
- package/src/sources/RpcSource.res.mjs +2 -2
- package/src/sources/Source.res +54 -1
- package/src/sources/Source.res.mjs +25 -0
- package/src/sources/SourceManager.res +220 -227
- package/src/sources/SourceManager.res.mjs +139 -164
- package/src/sources/SourceManager.resi +8 -0
- package/src/sources/Svm.res +2 -0
- package/src/sources/Svm.res.mjs +2 -0
- package/src/sources/SvmHyperSyncClient.res +70 -127
- package/src/sources/SvmHyperSyncClient.res.mjs +51 -25
- package/src/sources/SvmHyperSyncSource.res +18 -15
- package/src/sources/SvmHyperSyncSource.res.mjs +5 -4
- package/svm.schema.json +1 -75
- package/src/MemoryStorage.res +0 -729
- package/src/MemoryStorage.res.mjs +0 -586
- package/src/sources/HyperSyncHeightStream.res +0 -129
- package/src/sources/HyperSyncHeightStream.res.mjs +0 -110
- package/src/sources/RpcWebSocketHeightStream.res +0 -175
- package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -180
|
@@ -14,19 +14,14 @@ module Registration = {
|
|
|
14
14
|
values: array<string>,
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
// from
|
|
17
|
+
// One `onInstruction`/`contractRegister` binding of an instruction on a
|
|
18
|
+
// chain: the handler-specific routing state and the fetch state queries are
|
|
19
|
+
// built from. Chain-scoped `index` is echoed back on routed items.
|
|
20
20
|
type input = {
|
|
21
|
-
// Chain-scoped sequential registration index, echoed back on routed items.
|
|
22
21
|
index: int,
|
|
23
|
-
instructionName: string,
|
|
24
|
-
contractName: string,
|
|
25
|
-
programId: string,
|
|
26
22
|
isWildcard: bool,
|
|
27
23
|
// Earliest slot this registration accepts; `None` is unrestricted.
|
|
28
24
|
startBlock: option<int>,
|
|
29
|
-
discriminator?: string,
|
|
30
25
|
isInner?: bool,
|
|
31
26
|
// DNF: outer array is OR of AND-groups.
|
|
32
27
|
accountFilters: array<array<accountFilter>>,
|
|
@@ -36,28 +31,73 @@ module Registration = {
|
|
|
36
31
|
accountActivityFields: array<string>,
|
|
37
32
|
logFields: array<string>,
|
|
38
33
|
instructionFields: array<string>,
|
|
39
|
-
|
|
40
|
-
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// One config instruction: its identity (data prefix of any length; absent
|
|
37
|
+
// matches every instruction of the program) and Borsh layout, shared by
|
|
38
|
+
// every registration bound to it.
|
|
39
|
+
type instruction = {
|
|
40
|
+
name: string,
|
|
41
|
+
discriminator?: string,
|
|
41
42
|
argsJson?: string,
|
|
43
|
+
registrations: array<input>,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
type program = {
|
|
47
|
+
// The config's program name.
|
|
48
|
+
name: string,
|
|
49
|
+
programId: string,
|
|
42
50
|
definedTypesJson?: string,
|
|
51
|
+
instructions: array<instruction>,
|
|
43
52
|
}
|
|
44
53
|
|
|
54
|
+
// Groups a chain's registrations under the config instruction each was
|
|
55
|
+
// built from, so the Rust client holds one layout per instruction rather
|
|
56
|
+
// than a copy per registration.
|
|
45
57
|
let fromOnEventRegistrations = (
|
|
46
58
|
onEventRegistrations: array<Internal.svmOnEventRegistration>,
|
|
47
|
-
): array<
|
|
48
|
-
|
|
59
|
+
): array<program> => {
|
|
60
|
+
let programs: array<program> = []
|
|
61
|
+
onEventRegistrations->Array.forEach(reg => {
|
|
49
62
|
let eventConfig =
|
|
50
63
|
reg.eventConfig->(Utils.magic: Internal.eventConfig => Internal.svmInstructionEventConfig)
|
|
51
|
-
{
|
|
64
|
+
let program = switch programs->Array.find(p => p.name === eventConfig.contractName) {
|
|
65
|
+
| Some(program) => program
|
|
66
|
+
| None =>
|
|
67
|
+
let program = {
|
|
68
|
+
name: eventConfig.contractName,
|
|
69
|
+
programId: eventConfig.programId->SvmTypes.Pubkey.toString,
|
|
70
|
+
definedTypesJson: ?switch eventConfig.definedTypes {
|
|
71
|
+
| JSON.Null => None
|
|
72
|
+
| definedTypes => Some(definedTypes->JSON.stringify)
|
|
73
|
+
},
|
|
74
|
+
instructions: [],
|
|
75
|
+
}
|
|
76
|
+
programs->Array.push(program)->ignore
|
|
77
|
+
program
|
|
78
|
+
}
|
|
79
|
+
let instruction = switch program.instructions->Array.find(i => i.name === eventConfig.name) {
|
|
80
|
+
| Some(instruction) => instruction
|
|
81
|
+
| None =>
|
|
82
|
+
let instruction = {
|
|
83
|
+
name: eventConfig.name,
|
|
84
|
+
discriminator: ?eventConfig.discriminator,
|
|
85
|
+
argsJson: ?switch eventConfig.args {
|
|
86
|
+
| JSON.Null => None
|
|
87
|
+
| args => Some(args->JSON.stringify)
|
|
88
|
+
},
|
|
89
|
+
registrations: [],
|
|
90
|
+
}
|
|
91
|
+
program.instructions->Array.push(instruction)->ignore
|
|
92
|
+
instruction
|
|
93
|
+
}
|
|
94
|
+
instruction.registrations
|
|
95
|
+
->Array.push({
|
|
52
96
|
index: reg.index,
|
|
53
|
-
instructionName: eventConfig.name,
|
|
54
|
-
contractName: eventConfig.contractName,
|
|
55
|
-
programId: eventConfig.programId->SvmTypes.Pubkey.toString,
|
|
56
97
|
isWildcard: reg.isWildcard,
|
|
57
98
|
startBlock: reg.startBlock,
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
accountFilters: eventConfig.accountFilters->Array.map(group =>
|
|
99
|
+
isInner: ?reg.isInner,
|
|
100
|
+
accountFilters: reg.accountFilters->Array.map(group =>
|
|
61
101
|
group->Array.map(
|
|
62
102
|
(filter): accountFilter => {
|
|
63
103
|
position: filter.position,
|
|
@@ -70,71 +110,10 @@ module Registration = {
|
|
|
70
110
|
accountActivityFields: reg.fieldSelection.accountActivityFields->Utils.Set.toArray,
|
|
71
111
|
logFields: reg.fieldSelection.logFields->Utils.Set.toArray,
|
|
72
112
|
instructionFields: reg.fieldSelection.instructionFields->Utils.Set.toArray,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
| JSON.Null => None
|
|
76
|
-
| args => Some(args->JSON.stringify)
|
|
77
|
-
},
|
|
78
|
-
definedTypesJson: ?switch eventConfig.definedTypes {
|
|
79
|
-
| JSON.Null => None
|
|
80
|
-
| definedTypes => Some(definedTypes->JSON.stringify)
|
|
81
|
-
},
|
|
82
|
-
}
|
|
113
|
+
})
|
|
114
|
+
->ignore
|
|
83
115
|
})
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
module QueryTypes = {
|
|
87
|
-
type blockField =
|
|
88
|
-
| @as("slot") Slot
|
|
89
|
-
| @as("blockhash") Blockhash
|
|
90
|
-
| @as("parent_slot") ParentSlot
|
|
91
|
-
| @as("parent_blockhash") ParentBlockhash
|
|
92
|
-
| @as("block_time") BlockTime
|
|
93
|
-
| @as("block_height") BlockHeight
|
|
94
|
-
|
|
95
|
-
type transactionField =
|
|
96
|
-
| @as("slot") Slot
|
|
97
|
-
| @as("transaction_index") TransactionIndex
|
|
98
|
-
| @as("signatures") Signatures
|
|
99
|
-
| @as("fee_payer") FeePayer
|
|
100
|
-
| @as("success") Success
|
|
101
|
-
| @as("err") Err
|
|
102
|
-
| @as("fee") Fee
|
|
103
|
-
| @as("compute_units_consumed") ComputeUnitsConsumed
|
|
104
|
-
| @as("account_keys") AccountKeys
|
|
105
|
-
| @as("recent_blockhash") RecentBlockhash
|
|
106
|
-
| @as("version") Version
|
|
107
|
-
| @as("loaded_addresses_writable") LoadedAddressesWritable
|
|
108
|
-
| @as("loaded_addresses_readonly") LoadedAddressesReadonly
|
|
109
|
-
|
|
110
|
-
type fieldSelection = {block?: array<blockField>, transaction?: array<transactionField>}
|
|
111
|
-
|
|
112
|
-
/** Filter for selecting instruction calls. All non-empty fields are AND-ed:
|
|
113
|
-
an instruction must match at least one value in every non-empty field.
|
|
114
|
-
|
|
115
|
-
Discriminator filters (d1..d8) take hex-encoded byte prefixes ("0x" optional).
|
|
116
|
-
Account filters (a0..a9) take base58 pubkey strings. */
|
|
117
|
-
type instructionSelection = {
|
|
118
|
-
executingAccount?: array<string>,
|
|
119
|
-
d1?: array<string>,
|
|
120
|
-
d2?: array<string>,
|
|
121
|
-
d4?: array<string>,
|
|
122
|
-
d8?: array<string>,
|
|
123
|
-
isInner?: bool,
|
|
124
|
-
/** Success of the parent transaction; absent matches both. */
|
|
125
|
-
txSuccess?: bool,
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// The `get` query surface, used only for block-data range queries; event
|
|
129
|
-
// fetching goes through `getEventItems`, which builds its query in Rust.
|
|
130
|
-
type query = {
|
|
131
|
-
fromSlot: int,
|
|
132
|
-
toSlot?: int,
|
|
133
|
-
instructionCalls?: array<instructionSelection>,
|
|
134
|
-
includeAllBlocks?: bool,
|
|
135
|
-
fields?: fieldSelection,
|
|
136
|
-
maxNumBlocks?: int,
|
|
137
|
-
maxNumInstructions?: int,
|
|
116
|
+
programs
|
|
138
117
|
}
|
|
139
118
|
}
|
|
140
119
|
|
|
@@ -146,37 +125,6 @@ module ResponseTypes = {
|
|
|
146
125
|
blockhash: string,
|
|
147
126
|
blockTime: Null.t<int>,
|
|
148
127
|
}
|
|
149
|
-
|
|
150
|
-
type instructionCall = {
|
|
151
|
-
slot: int,
|
|
152
|
-
transactionIndex: int,
|
|
153
|
-
instructionAddress: array<int>,
|
|
154
|
-
/** The invoked program's account. */
|
|
155
|
-
executingAccount: string,
|
|
156
|
-
accountArguments: array<string>,
|
|
157
|
-
data: string,
|
|
158
|
-
d1: Null.t<string>,
|
|
159
|
-
d2: Null.t<string>,
|
|
160
|
-
d4: Null.t<string>,
|
|
161
|
-
d8: Null.t<string>,
|
|
162
|
-
isInner: bool,
|
|
163
|
-
/** Success of the parent transaction, not of this invocation. */
|
|
164
|
-
txSuccess: bool,
|
|
165
|
-
/** Per-invocation failure reason (e.g. "custom program error: 0x1"). */
|
|
166
|
-
error: Null.t<string>,
|
|
167
|
-
computeUnitsConsumed: Null.t<bigint>,
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
type queryResponseData = {
|
|
171
|
-
blocks: array<block>,
|
|
172
|
-
instructionCalls: array<instructionCall>,
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
type queryResponse = {
|
|
176
|
-
nextSlot: int,
|
|
177
|
-
responseBytes: int,
|
|
178
|
-
data: queryResponseData,
|
|
179
|
-
}
|
|
180
128
|
}
|
|
181
129
|
|
|
182
130
|
module EventItems = {
|
|
@@ -213,12 +161,12 @@ module EventItems = {
|
|
|
213
161
|
path: array<int>,
|
|
214
162
|
programId: string,
|
|
215
163
|
accounts: array<string>,
|
|
216
|
-
data:
|
|
164
|
+
data: Uint8Array.t,
|
|
217
165
|
isInner: bool,
|
|
218
|
-
// Borsh-decoded args as a
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
|
|
166
|
+
// Borsh-decoded args as a JS value tree (wide integers as bigint).
|
|
167
|
+
// Non-null exactly when the routed registration selected `args`: an
|
|
168
|
+
// instruction its layout rejects is dropped in Rust.
|
|
169
|
+
args: Null.t<unknown>,
|
|
222
170
|
// Non-null only when the routed registration selected `fields.log`.
|
|
223
171
|
logs: Null.t<array<log>>,
|
|
224
172
|
}
|
|
@@ -234,16 +182,11 @@ module EventItems = {
|
|
|
234
182
|
}
|
|
235
183
|
}
|
|
236
184
|
|
|
237
|
-
type query = QueryTypes.query
|
|
238
|
-
type queryResponse = ResponseTypes.queryResponse
|
|
239
|
-
|
|
240
185
|
type t = {
|
|
241
186
|
getHeight: unit => promise<int>,
|
|
242
187
|
// Block-hash query construction, pagination, and cursor-backed skipped-slot
|
|
243
188
|
// coverage live in Rust.
|
|
244
189
|
getBlockHashes: (~blockNumbers: array<int>) => promise<(BlockStore.t, array<RequestStat.t>)>,
|
|
245
|
-
// Block-data range queries only; the store pages it returns are empty.
|
|
246
|
-
get: (~query: query) => promise<(queryResponse, TransactionStore.t, BlockStore.t)>,
|
|
247
190
|
// Returns the routed items plus pages of raw transactions and blocks (kept
|
|
248
191
|
// in Rust), keyed by (slot, transactionIndex) / slot, materialised at batch
|
|
249
192
|
// prep.
|
|
@@ -258,7 +201,7 @@ external classFromConfig: (
|
|
|
258
201
|
Core.svmHyperSyncClientCtor,
|
|
259
202
|
cfg,
|
|
260
203
|
string,
|
|
261
|
-
array<Registration.
|
|
204
|
+
array<Registration.program>,
|
|
262
205
|
AddressStore.t,
|
|
263
206
|
) => t = "fromConfig"
|
|
264
207
|
|
|
@@ -268,7 +211,7 @@ let make = (
|
|
|
268
211
|
~httpReqTimeoutMillis=?,
|
|
269
212
|
~retryBaseMs=?,
|
|
270
213
|
~retryCeilingMs=?,
|
|
271
|
-
~
|
|
214
|
+
~programs=[],
|
|
272
215
|
~addressStore,
|
|
273
216
|
) => {
|
|
274
217
|
let envioVersion = Utils.EnvioPackage.value.version
|
|
@@ -281,7 +224,7 @@ let make = (
|
|
|
281
224
|
?retryCeilingMs,
|
|
282
225
|
},
|
|
283
226
|
`hyperindex/${envioVersion}`,
|
|
284
|
-
|
|
227
|
+
programs,
|
|
285
228
|
addressStore,
|
|
286
229
|
)
|
|
287
230
|
}
|
|
@@ -4,24 +4,55 @@ import * as Core from "../Core.res.mjs";
|
|
|
4
4
|
import * as Utils from "../Utils.res.mjs";
|
|
5
5
|
|
|
6
6
|
function fromOnEventRegistrations(onEventRegistrations) {
|
|
7
|
-
|
|
7
|
+
let programs = [];
|
|
8
|
+
onEventRegistrations.forEach(reg => {
|
|
8
9
|
let eventConfig = reg.eventConfig;
|
|
9
|
-
let
|
|
10
|
-
let
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
let program = programs.find(p => p.name === eventConfig.contractName);
|
|
11
|
+
let program$1;
|
|
12
|
+
if (program !== undefined) {
|
|
13
|
+
program$1 = program;
|
|
14
|
+
} else {
|
|
15
|
+
let definedTypes = eventConfig.definedTypes;
|
|
16
|
+
let tmp;
|
|
17
|
+
tmp = definedTypes === null ? undefined : JSON.stringify(definedTypes);
|
|
18
|
+
let program_name = eventConfig.contractName;
|
|
19
|
+
let program_programId = eventConfig.programId;
|
|
20
|
+
let program_instructions = [];
|
|
21
|
+
let program$2 = {
|
|
22
|
+
name: program_name,
|
|
23
|
+
programId: program_programId,
|
|
24
|
+
definedTypesJson: tmp,
|
|
25
|
+
instructions: program_instructions
|
|
26
|
+
};
|
|
27
|
+
programs.push(program$2);
|
|
28
|
+
program$1 = program$2;
|
|
29
|
+
}
|
|
30
|
+
let instruction = program$1.instructions.find(i => i.name === eventConfig.name);
|
|
31
|
+
let instruction$1;
|
|
32
|
+
if (instruction !== undefined) {
|
|
33
|
+
instruction$1 = instruction;
|
|
34
|
+
} else {
|
|
35
|
+
let args = eventConfig.args;
|
|
36
|
+
let tmp$1;
|
|
37
|
+
tmp$1 = args === null ? undefined : JSON.stringify(args);
|
|
38
|
+
let instruction_name = eventConfig.name;
|
|
39
|
+
let instruction_discriminator = eventConfig.discriminator;
|
|
40
|
+
let instruction_registrations = [];
|
|
41
|
+
let instruction$2 = {
|
|
42
|
+
name: instruction_name,
|
|
43
|
+
discriminator: instruction_discriminator,
|
|
44
|
+
argsJson: tmp$1,
|
|
45
|
+
registrations: instruction_registrations
|
|
46
|
+
};
|
|
47
|
+
program$1.instructions.push(instruction$2);
|
|
48
|
+
instruction$1 = instruction$2;
|
|
49
|
+
}
|
|
50
|
+
instruction$1.registrations.push({
|
|
16
51
|
index: reg.index,
|
|
17
|
-
instructionName: eventConfig.name,
|
|
18
|
-
contractName: eventConfig.contractName,
|
|
19
|
-
programId: eventConfig.programId,
|
|
20
52
|
isWildcard: reg.isWildcard,
|
|
21
53
|
startBlock: reg.startBlock,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
accountFilters: eventConfig.accountFilters.map(group => group.map(filter => ({
|
|
54
|
+
isInner: reg.isInner,
|
|
55
|
+
accountFilters: reg.accountFilters.map(group => group.map(filter => ({
|
|
25
56
|
position: filter.position,
|
|
26
57
|
values: filter.values
|
|
27
58
|
}))),
|
|
@@ -29,26 +60,22 @@ function fromOnEventRegistrations(onEventRegistrations) {
|
|
|
29
60
|
blockFields: Array.from(reg.fieldSelection.blockFields),
|
|
30
61
|
accountActivityFields: Array.from(reg.fieldSelection.accountActivityFields),
|
|
31
62
|
logFields: Array.from(reg.fieldSelection.logFields),
|
|
32
|
-
instructionFields: Array.from(reg.fieldSelection.instructionFields)
|
|
33
|
-
|
|
34
|
-
argsJson: tmp,
|
|
35
|
-
definedTypesJson: tmp$1
|
|
36
|
-
};
|
|
63
|
+
instructionFields: Array.from(reg.fieldSelection.instructionFields)
|
|
64
|
+
});
|
|
37
65
|
});
|
|
66
|
+
return programs;
|
|
38
67
|
}
|
|
39
68
|
|
|
40
69
|
let Registration = {
|
|
41
70
|
fromOnEventRegistrations: fromOnEventRegistrations
|
|
42
71
|
};
|
|
43
72
|
|
|
44
|
-
let QueryTypes = {};
|
|
45
|
-
|
|
46
73
|
let ResponseTypes = {};
|
|
47
74
|
|
|
48
75
|
let EventItems = {};
|
|
49
76
|
|
|
50
|
-
function make(url, apiToken, httpReqTimeoutMillis, retryBaseMs, retryCeilingMs,
|
|
51
|
-
let
|
|
77
|
+
function make(url, apiToken, httpReqTimeoutMillis, retryBaseMs, retryCeilingMs, programsOpt, addressStore) {
|
|
78
|
+
let programs = programsOpt !== undefined ? programsOpt : [];
|
|
52
79
|
let envioVersion = Utils.EnvioPackage.value.version;
|
|
53
80
|
return Core.getAddon().SvmHyperSyncClient.fromConfig({
|
|
54
81
|
url: url,
|
|
@@ -56,12 +83,11 @@ function make(url, apiToken, httpReqTimeoutMillis, retryBaseMs, retryCeilingMs,
|
|
|
56
83
|
httpReqTimeoutMillis: httpReqTimeoutMillis,
|
|
57
84
|
retryBaseMs: retryBaseMs,
|
|
58
85
|
retryCeilingMs: retryCeilingMs
|
|
59
|
-
}, `hyperindex/` + envioVersion,
|
|
86
|
+
}, `hyperindex/` + envioVersion, programs, addressStore);
|
|
60
87
|
}
|
|
61
88
|
|
|
62
89
|
export {
|
|
63
90
|
Registration,
|
|
64
|
-
QueryTypes,
|
|
65
91
|
ResponseTypes,
|
|
66
92
|
EventItems,
|
|
67
93
|
make,
|
|
@@ -10,10 +10,9 @@ type options = {
|
|
|
10
10
|
addressStore: AddressStore.t,
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
let namedAccounts = (
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
): dict<Envio.svmInstructionAccount> => {
|
|
13
|
+
let namedAccounts = (~idlNames: array<string>, ~accountArguments: array<string>): dict<
|
|
14
|
+
Envio.svmInstructionAccount,
|
|
15
|
+
> => {
|
|
17
16
|
let out = Dict.make()
|
|
18
17
|
idlNames->Array.forEachWithIndex((name, i) =>
|
|
19
18
|
switch accountArguments->Array.get(i) {
|
|
@@ -32,7 +31,10 @@ let namedAccounts = (
|
|
|
32
31
|
out
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
let selectedLog = (
|
|
34
|
+
let selectedLog = (
|
|
35
|
+
log: SvmHyperSyncClient.EventItems.log,
|
|
36
|
+
~logFields: Utils.Set.t<string>,
|
|
37
|
+
): Envio.svmLog => {
|
|
36
38
|
let out = Dict.make()
|
|
37
39
|
if logFields->Utils.Set.has("kind") {
|
|
38
40
|
switch log.kind->Null.toOption {
|
|
@@ -63,9 +65,11 @@ let toSvmInstruction = (
|
|
|
63
65
|
~fieldSelection: Internal.fieldSelection,
|
|
64
66
|
): Envio.svmInstruction => {
|
|
65
67
|
let hasSelection = name => fieldSelection.instructionFields->Utils.Set.has(name)
|
|
68
|
+
// A program-wide registration has no configured discriminator, so the whole
|
|
69
|
+
// data stands in, hex-encoded like a configured one would be.
|
|
66
70
|
let discriminator = switch eventConfig.discriminator {
|
|
67
71
|
| Some(d) => d
|
|
68
|
-
| None => item.data
|
|
72
|
+
| None => "0x" ++ item.data->NodeJs.Buffer.fromUint8Array->NodeJs.Buffer.toHex
|
|
69
73
|
}
|
|
70
74
|
let out = Dict.make()
|
|
71
75
|
out->setField("programName", programName)
|
|
@@ -83,8 +87,9 @@ let toSvmInstruction = (
|
|
|
83
87
|
if hasSelection("isInner") {
|
|
84
88
|
out->setField("isInner", item.isInner)
|
|
85
89
|
}
|
|
86
|
-
|
|
87
|
-
|
|
90
|
+
switch item.args->Null.toOption {
|
|
91
|
+
| Some(args) => out->setField("args", args)
|
|
92
|
+
| None => ()
|
|
88
93
|
}
|
|
89
94
|
if hasSelection("accounts") {
|
|
90
95
|
out->setField(
|
|
@@ -125,9 +130,7 @@ let make = (
|
|
|
125
130
|
~url=endpointUrl,
|
|
126
131
|
~apiToken?,
|
|
127
132
|
~httpReqTimeoutMillis=clientTimeoutMillis,
|
|
128
|
-
~
|
|
129
|
-
onEventRegistrations,
|
|
130
|
-
),
|
|
133
|
+
~programs=SvmHyperSyncClient.Registration.fromOnEventRegistrations(onEventRegistrations),
|
|
131
134
|
~addressStore,
|
|
132
135
|
)
|
|
133
136
|
|
|
@@ -198,7 +201,7 @@ let make = (
|
|
|
198
201
|
~fieldSelection=onEventRegistration.fieldSelection,
|
|
199
202
|
)
|
|
200
203
|
Internal.Event({
|
|
201
|
-
onEventRegistration,
|
|
204
|
+
onEventRegistration: (onEventRegistration :> Internal.onEventRegistration),
|
|
202
205
|
chainId,
|
|
203
206
|
blockNumber: item.slot,
|
|
204
207
|
// A slot orders by `(transactionIndex, path)` — the
|
|
@@ -236,15 +239,15 @@ let make = (
|
|
|
236
239
|
|
|
237
240
|
// Called through the client rather than passed as a value: the client is a
|
|
238
241
|
// napi class, so a detached method reference loses the instance it belongs to.
|
|
239
|
-
let getBlockHashes = HyperSync.makeGetBlockHashes(
|
|
240
|
-
|
|
242
|
+
let getBlockHashes = HyperSync.makeGetBlockHashes(~query=(~blockNumbers) =>
|
|
243
|
+
client.getBlockHashes(~blockNumbers)
|
|
241
244
|
)
|
|
242
245
|
|
|
243
246
|
{
|
|
244
247
|
name,
|
|
245
248
|
sourceFor: Sync,
|
|
246
249
|
chainId,
|
|
247
|
-
pollingInterval:
|
|
250
|
+
pollingInterval: HyperSync.pollingInterval,
|
|
248
251
|
poweredByHyperSync: true,
|
|
249
252
|
getBlockHashes,
|
|
250
253
|
getHeightOrThrow: async () => {
|
|
@@ -48,7 +48,7 @@ function setField(out, name, value) {
|
|
|
48
48
|
|
|
49
49
|
function toSvmInstruction(item, programName, instructionName, eventConfig, fieldSelection) {
|
|
50
50
|
let d = eventConfig.discriminator;
|
|
51
|
-
let discriminator = d !== undefined ? d : item.data;
|
|
51
|
+
let discriminator = d !== undefined ? d : "0x" + Buffer.from(item.data).toString("hex");
|
|
52
52
|
let out = {};
|
|
53
53
|
setField(out, "programName", programName);
|
|
54
54
|
setField(out, "instructionName", instructionName);
|
|
@@ -65,8 +65,9 @@ function toSvmInstruction(item, programName, instructionName, eventConfig, field
|
|
|
65
65
|
if (fieldSelection.instructionFields.has("isInner")) {
|
|
66
66
|
setField(out, "isInner", item.isInner);
|
|
67
67
|
}
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
let args = item.args;
|
|
69
|
+
if (args !== null) {
|
|
70
|
+
setField(out, "args", args);
|
|
70
71
|
}
|
|
71
72
|
if (fieldSelection.instructionFields.has("accounts")) {
|
|
72
73
|
setField(out, "accounts", namedAccounts(eventConfig.accounts, item.accounts));
|
|
@@ -163,7 +164,7 @@ function make(param) {
|
|
|
163
164
|
sourceFor: "Sync",
|
|
164
165
|
chainId: chainId,
|
|
165
166
|
poweredByHyperSync: true,
|
|
166
|
-
pollingInterval:
|
|
167
|
+
pollingInterval: HyperSync.pollingInterval,
|
|
167
168
|
getBlockHashes: getBlockHashes,
|
|
168
169
|
getHeightOrThrow: async () => {
|
|
169
170
|
let timer = Performance.now();
|
package/svm.schema.json
CHANGED
|
@@ -381,30 +381,12 @@
|
|
|
381
381
|
"type": "string"
|
|
382
382
|
},
|
|
383
383
|
"discriminator": {
|
|
384
|
-
"description": "Hex-encoded instruction-data prefix used as the discriminator (\"0x\" optional)
|
|
384
|
+
"description": "Hex-encoded instruction-data prefix used as the discriminator (\"0x\" optional), of any whole number of bytes; an 8-byte value matches the standard Anchor discriminator. Omit it to match every instruction of the program. Every instruction whose prefix an on-chain call carries receives it, so a program-wide entry fires alongside a keyed one, and two entries may share a prefix (say, the layouts before and after a program upgrade): each decodes with its own `args`, and one whose layout rejects the data is skipped for that call.",
|
|
385
385
|
"type": [
|
|
386
386
|
"string",
|
|
387
387
|
"null"
|
|
388
388
|
]
|
|
389
389
|
},
|
|
390
|
-
"is_inner": {
|
|
391
|
-
"description": "Filter on inner-vs-outer instructions. None / absent matches both.",
|
|
392
|
-
"type": [
|
|
393
|
-
"boolean",
|
|
394
|
-
"null"
|
|
395
|
-
]
|
|
396
|
-
},
|
|
397
|
-
"account_filters": {
|
|
398
|
-
"description": "Optional positional account filters. Two shapes are accepted: a flat list of `{position, values}` entries (AND across positions, OR within `values`); or `{any_of: [[...]] }`, a list of AND-groups that are OR-ed together. Positions must be in 0..=5; positions 6..=9 are reserved for a future extension.",
|
|
399
|
-
"anyOf": [
|
|
400
|
-
{
|
|
401
|
-
"$ref": "#/$defs/AccountFilters"
|
|
402
|
-
},
|
|
403
|
-
{
|
|
404
|
-
"type": "null"
|
|
405
|
-
}
|
|
406
|
-
]
|
|
407
|
-
},
|
|
408
390
|
"accounts": {
|
|
409
391
|
"description": "Optional positional account names. The Nth entry names account slot N on the dispatched instruction; surfaces as `instruction.accounts.<name>` when `fields.instruction` includes `accounts`.",
|
|
410
392
|
"type": [
|
|
@@ -431,62 +413,6 @@
|
|
|
431
413
|
"name"
|
|
432
414
|
]
|
|
433
415
|
},
|
|
434
|
-
"AccountFilters": {
|
|
435
|
-
"anyOf": [
|
|
436
|
-
{
|
|
437
|
-
"type": "array",
|
|
438
|
-
"items": {
|
|
439
|
-
"$ref": "#/$defs/AccountFilter"
|
|
440
|
-
}
|
|
441
|
-
},
|
|
442
|
-
{
|
|
443
|
-
"$ref": "#/$defs/AnyOfAccountFilters"
|
|
444
|
-
}
|
|
445
|
-
]
|
|
446
|
-
},
|
|
447
|
-
"AccountFilter": {
|
|
448
|
-
"type": "object",
|
|
449
|
-
"properties": {
|
|
450
|
-
"position": {
|
|
451
|
-
"description": "Account position within the instruction (0..=5).",
|
|
452
|
-
"type": "integer",
|
|
453
|
-
"format": "uint8",
|
|
454
|
-
"minimum": 0,
|
|
455
|
-
"maximum": 255
|
|
456
|
-
},
|
|
457
|
-
"values": {
|
|
458
|
-
"description": "Allowed base58 pubkeys for this account position.",
|
|
459
|
-
"type": "array",
|
|
460
|
-
"items": {
|
|
461
|
-
"type": "string"
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
},
|
|
465
|
-
"additionalProperties": false,
|
|
466
|
-
"required": [
|
|
467
|
-
"position",
|
|
468
|
-
"values"
|
|
469
|
-
]
|
|
470
|
-
},
|
|
471
|
-
"AnyOfAccountFilters": {
|
|
472
|
-
"type": "object",
|
|
473
|
-
"properties": {
|
|
474
|
-
"any_of": {
|
|
475
|
-
"description": "A non-empty list of AND-groups. Each group is itself a non-empty list of `{position, values}` entries that must all match the same instruction. An instruction matches `any_of` when any one group matches.",
|
|
476
|
-
"type": "array",
|
|
477
|
-
"items": {
|
|
478
|
-
"type": "array",
|
|
479
|
-
"items": {
|
|
480
|
-
"$ref": "#/$defs/AccountFilter"
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
},
|
|
485
|
-
"additionalProperties": false,
|
|
486
|
-
"required": [
|
|
487
|
-
"any_of"
|
|
488
|
-
]
|
|
489
|
-
},
|
|
490
416
|
"ArgDef": {
|
|
491
417
|
"description": "One named argument of an instruction. Mirrors\n`hypersync_client_solana::decode::NamedField`.",
|
|
492
418
|
"type": "object",
|