envio 3.3.2 → 3.4.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/package.json +6 -6
- package/src/Api.res +1 -8
- package/src/Api.res.mjs +1 -5
- package/src/ChainState.res +6 -1
- package/src/ChainState.res.mjs +4 -3
- package/src/Config.res +33 -4
- package/src/Config.res.mjs +34 -5
- package/src/Core.res +30 -19
- package/src/Core.res.mjs +5 -5
- package/src/EnvioGlobal.res +0 -2
- package/src/EnvioGlobal.res.mjs +0 -1
- package/src/ExitOnCaughtUp.res +6 -2
- package/src/ExitOnCaughtUp.res.mjs +4 -0
- package/src/FetchState.res +3 -3
- package/src/HandlerRegister.res +357 -434
- package/src/HandlerRegister.res.mjs +202 -242
- package/src/HandlerRegister.resi +7 -15
- package/src/IndexerState.res +10 -0
- package/src/IndexerState.res.mjs +9 -3
- package/src/IndexerState.resi +3 -0
- package/src/Internal.res +10 -1
- package/src/Main.res.mjs +4 -4
- package/src/PgStorage.res +16 -1
- package/src/PgStorage.res.mjs +9 -1
- package/src/SimulateItems.res +61 -40
- package/src/SimulateItems.res.mjs +37 -21
- package/src/TestIndexer.res +446 -453
- package/src/TestIndexer.res.mjs +320 -343
- package/src/bindings/ClickHouse.res +68 -2
- package/src/bindings/ClickHouse.res.mjs +47 -2
- package/src/sources/EvmChain.res +1 -1
- package/src/sources/EvmChain.res.mjs +2 -2
- package/src/sources/FuelHyperSync.res +74 -0
- package/src/sources/FuelHyperSync.res.mjs +80 -0
- package/src/sources/FuelHyperSync.resi +22 -0
- package/src/sources/FuelHyperSyncClient.res +120 -0
- package/src/sources/FuelHyperSyncClient.res.mjs +71 -0
- package/src/sources/FuelHyperSyncSource.res +257 -0
- package/src/sources/FuelHyperSyncSource.res.mjs +252 -0
- package/src/sources/HyperSyncClient.res +2 -2
- package/src/sources/HyperSyncClient.res.mjs +1 -1
- package/src/sources/SvmHyperSyncClient.res +139 -102
- package/src/sources/SvmHyperSyncClient.res.mjs +45 -5
- package/src/sources/SvmHyperSyncSource.res +60 -440
- package/src/sources/SvmHyperSyncSource.res.mjs +42 -363
- package/src/TestIndexerProxyStorage.res +0 -196
- package/src/TestIndexerProxyStorage.res.mjs +0 -121
- package/src/TestIndexerWorker.res +0 -4
- package/src/TestIndexerWorker.res.mjs +0 -7
- package/src/sources/EventRouter.res +0 -165
- package/src/sources/EventRouter.res.mjs +0 -153
- package/src/sources/HyperFuel.res +0 -179
- package/src/sources/HyperFuel.res.mjs +0 -146
- package/src/sources/HyperFuel.resi +0 -36
- package/src/sources/HyperFuelClient.res +0 -127
- package/src/sources/HyperFuelClient.res.mjs +0 -20
- package/src/sources/HyperFuelSource.res +0 -502
- package/src/sources/HyperFuelSource.res.mjs +0 -481
- /package/src/sources/{HyperSyncSource.res → EvmHyperSyncSource.res} +0 -0
- /package/src/sources/{HyperSyncSource.res.mjs → EvmHyperSyncSource.res.mjs} +0 -0
|
@@ -7,10 +7,78 @@ type cfg = {
|
|
|
7
7
|
maxNumRetries?: int,
|
|
8
8
|
retryBaseMs?: int,
|
|
9
9
|
retryCeilingMs?: int,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module Registration = {
|
|
13
|
+
type accountFilter = {
|
|
14
|
+
position: int,
|
|
15
|
+
values: array<string>,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// The full per-(instruction, chain) registration passed to the Rust client
|
|
19
|
+
// at construction: routing identity, the fetch state queries are built
|
|
20
|
+
// from, and the Borsh schema pieces the client builds decoders from.
|
|
21
|
+
type input = {
|
|
22
|
+
// Chain-scoped sequential registration index, echoed back on routed items.
|
|
23
|
+
index: int,
|
|
24
|
+
instructionName: string,
|
|
25
|
+
contractName: string,
|
|
26
|
+
programId: string,
|
|
27
|
+
isWildcard: bool,
|
|
28
|
+
discriminator?: string,
|
|
29
|
+
discriminatorByteLen: int,
|
|
30
|
+
isInner?: bool,
|
|
31
|
+
includeLogs: bool,
|
|
32
|
+
// DNF: outer array is OR of AND-groups.
|
|
33
|
+
accountFilters: array<array<accountFilter>>,
|
|
34
|
+
// camelCase Internal.svmTransactionField / svmBlockField names.
|
|
35
|
+
transactionFields: array<string>,
|
|
36
|
+
blockFields: array<string>,
|
|
37
|
+
// Borsh schema pieces; empty accounts + absent argsJson = no schema.
|
|
38
|
+
accounts: array<string>,
|
|
39
|
+
argsJson?: string,
|
|
40
|
+
definedTypesJson?: string,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let fromOnEventRegistrations = (
|
|
44
|
+
onEventRegistrations: array<Internal.svmOnEventRegistration>,
|
|
45
|
+
): array<input> =>
|
|
46
|
+
onEventRegistrations->Array.map(reg => {
|
|
47
|
+
let eventConfig =
|
|
48
|
+
reg.eventConfig->(Utils.magic: Internal.eventConfig => Internal.svmInstructionEventConfig)
|
|
49
|
+
{
|
|
50
|
+
index: reg.index,
|
|
51
|
+
instructionName: eventConfig.name,
|
|
52
|
+
contractName: eventConfig.contractName,
|
|
53
|
+
programId: eventConfig.programId->SvmTypes.Pubkey.toString,
|
|
54
|
+
isWildcard: reg.isWildcard,
|
|
55
|
+
discriminator: ?eventConfig.discriminator,
|
|
56
|
+
discriminatorByteLen: eventConfig.discriminatorByteLen,
|
|
57
|
+
isInner: ?eventConfig.isInner,
|
|
58
|
+
includeLogs: eventConfig.includeLogs,
|
|
59
|
+
accountFilters: eventConfig.accountFilters->Array.map(group =>
|
|
60
|
+
group->Array.map(
|
|
61
|
+
(filter): accountFilter => {
|
|
62
|
+
position: filter.position,
|
|
63
|
+
values: filter.values->SvmTypes.Pubkey.toStrings,
|
|
64
|
+
},
|
|
65
|
+
)
|
|
66
|
+
),
|
|
67
|
+
transactionFields: eventConfig.selectedTransactionFields->Utils.Set.toArray,
|
|
68
|
+
blockFields: eventConfig.selectedBlockFields
|
|
69
|
+
->(Utils.magic: Utils.Set.t<Internal.svmBlockField> => Utils.Set.t<string>)
|
|
70
|
+
->Utils.Set.toArray,
|
|
71
|
+
accounts: eventConfig.accounts,
|
|
72
|
+
argsJson: ?switch eventConfig.args {
|
|
73
|
+
| JSON.Null => None
|
|
74
|
+
| args => Some(args->JSON.stringify)
|
|
75
|
+
},
|
|
76
|
+
definedTypesJson: ?switch eventConfig.definedTypes {
|
|
77
|
+
| JSON.Null => None
|
|
78
|
+
| definedTypes => Some(definedTypes->JSON.stringify)
|
|
79
|
+
},
|
|
80
|
+
}
|
|
81
|
+
})
|
|
14
82
|
}
|
|
15
83
|
|
|
16
84
|
module QueryTypes = {
|
|
@@ -37,54 +105,7 @@ module QueryTypes = {
|
|
|
37
105
|
| @as("loaded_addresses_writable") LoadedAddressesWritable
|
|
38
106
|
| @as("loaded_addresses_readonly") LoadedAddressesReadonly
|
|
39
107
|
|
|
40
|
-
type
|
|
41
|
-
| @as("slot") Slot
|
|
42
|
-
| @as("transaction_index") TransactionIndex
|
|
43
|
-
| @as("instruction_address") InstructionAddress
|
|
44
|
-
| @as("program_id") ProgramId
|
|
45
|
-
| @as("accounts") Accounts
|
|
46
|
-
| @as("data") Data
|
|
47
|
-
| @as("d1") D1
|
|
48
|
-
| @as("d2") D2
|
|
49
|
-
| @as("d4") D4
|
|
50
|
-
| @as("d8") D8
|
|
51
|
-
| @as("a0") A0
|
|
52
|
-
| @as("a1") A1
|
|
53
|
-
| @as("a2") A2
|
|
54
|
-
| @as("a3") A3
|
|
55
|
-
| @as("a4") A4
|
|
56
|
-
| @as("a5") A5
|
|
57
|
-
| @as("a6") A6
|
|
58
|
-
| @as("a7") A7
|
|
59
|
-
| @as("a8") A8
|
|
60
|
-
| @as("a9") A9
|
|
61
|
-
| @as("is_inner") IsInner
|
|
62
|
-
| @as("is_committed") IsCommitted
|
|
63
|
-
|
|
64
|
-
type logField =
|
|
65
|
-
| @as("slot") Slot
|
|
66
|
-
| @as("transaction_index") TransactionIndex
|
|
67
|
-
| @as("instruction_address") InstructionAddress
|
|
68
|
-
| @as("program_id") ProgramId
|
|
69
|
-
| @as("kind") Kind
|
|
70
|
-
| @as("message") Message
|
|
71
|
-
|
|
72
|
-
type tokenBalanceField =
|
|
73
|
-
| @as("slot") Slot
|
|
74
|
-
| @as("transaction_index") TransactionIndex
|
|
75
|
-
| @as("account") Account
|
|
76
|
-
| @as("mint") Mint
|
|
77
|
-
| @as("owner") Owner
|
|
78
|
-
| @as("pre_amount") PreAmount
|
|
79
|
-
| @as("post_amount") PostAmount
|
|
80
|
-
|
|
81
|
-
type fieldSelection = {
|
|
82
|
-
block?: array<blockField>,
|
|
83
|
-
transaction?: array<transactionField>,
|
|
84
|
-
instruction?: array<instructionField>,
|
|
85
|
-
log?: array<logField>,
|
|
86
|
-
tokenBalance?: array<tokenBalanceField>,
|
|
87
|
-
}
|
|
108
|
+
type fieldSelection = {block?: array<blockField>, transaction?: array<transactionField>}
|
|
88
109
|
|
|
89
110
|
/** Filter for selecting instructions. All non-empty fields are AND-ed: an
|
|
90
111
|
instruction must match at least one value in every non-empty field.
|
|
@@ -97,43 +118,19 @@ module QueryTypes = {
|
|
|
97
118
|
d2?: array<string>,
|
|
98
119
|
d4?: array<string>,
|
|
99
120
|
d8?: array<string>,
|
|
100
|
-
a0?: array<string>,
|
|
101
|
-
a1?: array<string>,
|
|
102
|
-
a2?: array<string>,
|
|
103
|
-
a3?: array<string>,
|
|
104
|
-
a4?: array<string>,
|
|
105
|
-
a5?: array<string>,
|
|
106
|
-
a6?: array<string>,
|
|
107
|
-
a7?: array<string>,
|
|
108
|
-
a8?: array<string>,
|
|
109
|
-
a9?: array<string>,
|
|
110
121
|
isInner?: bool,
|
|
111
122
|
}
|
|
112
123
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
success?: bool,
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
type logSelection = {
|
|
119
|
-
programId?: array<string>,
|
|
120
|
-
kind?: array<string>,
|
|
121
|
-
}
|
|
122
|
-
|
|
124
|
+
// The `get` query surface, used only for block-data range queries; event
|
|
125
|
+
// fetching goes through `getEventItems`, which builds its query in Rust.
|
|
123
126
|
type query = {
|
|
124
127
|
fromSlot: int,
|
|
125
128
|
toSlot?: int,
|
|
126
129
|
instructions?: array<instructionSelection>,
|
|
127
|
-
transactions?: array<transactionSelection>,
|
|
128
|
-
logs?: array<logSelection>,
|
|
129
130
|
includeAllBlocks?: bool,
|
|
130
|
-
includeTokenBalances?: bool,
|
|
131
131
|
fields?: fieldSelection,
|
|
132
132
|
maxNumBlocks?: int,
|
|
133
|
-
maxNumTransactions?: int,
|
|
134
133
|
maxNumInstructions?: int,
|
|
135
|
-
maxNumLogs?: int,
|
|
136
|
-
maxNumTokenBalances?: int,
|
|
137
134
|
}
|
|
138
135
|
}
|
|
139
136
|
|
|
@@ -148,13 +145,6 @@ module ResponseTypes = {
|
|
|
148
145
|
|
|
149
146
|
/// Borsh-decoded view attached by the Rust client. `argsJson`/`accountsJson`
|
|
150
147
|
/// are stringified to side-step napi-rs's lack of native JSON passthrough.
|
|
151
|
-
/** Solana instruction record.
|
|
152
|
-
|
|
153
|
-
`data` is the raw instruction byte buffer, hex-encoded with a `0x` prefix.
|
|
154
|
-
`d1`..`d8` are the same byte prefix as `data` but truncated to N bytes
|
|
155
|
-
(only `Some` when the instruction is at least that long), exposed for
|
|
156
|
-
handler-dispatch convenience.
|
|
157
|
-
`accounts` is the full positional account list in base58. */
|
|
158
148
|
type decodedInstruction = {
|
|
159
149
|
name: string,
|
|
160
150
|
argsJson: string,
|
|
@@ -175,22 +165,11 @@ module ResponseTypes = {
|
|
|
175
165
|
d8?: string,
|
|
176
166
|
isInner: bool,
|
|
177
167
|
isCommitted: bool,
|
|
178
|
-
decoded?: decodedInstruction,
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
type log = {
|
|
182
|
-
slot: int,
|
|
183
|
-
transactionIndex?: int,
|
|
184
|
-
instructionAddress?: array<int>,
|
|
185
|
-
programId?: string,
|
|
186
|
-
kind?: string,
|
|
187
|
-
message?: string,
|
|
188
168
|
}
|
|
189
169
|
|
|
190
170
|
type queryResponseData = {
|
|
191
171
|
blocks: array<block>,
|
|
192
172
|
instructions: array<instruction>,
|
|
193
|
-
logs: array<log>,
|
|
194
173
|
}
|
|
195
174
|
|
|
196
175
|
type queryResponse = {
|
|
@@ -200,18 +179,76 @@ module ResponseTypes = {
|
|
|
200
179
|
}
|
|
201
180
|
}
|
|
202
181
|
|
|
182
|
+
module EventItems = {
|
|
183
|
+
// The whole per-query input: slot range, the partition's registration
|
|
184
|
+
// selection (by index), and its current addresses (program ids per program
|
|
185
|
+
// name). Instruction selections, field selection, and routing are derived
|
|
186
|
+
// on the Rust side.
|
|
187
|
+
type query = {
|
|
188
|
+
fromSlot: int,
|
|
189
|
+
// Inclusive; None queries to the end of available data.
|
|
190
|
+
toSlot: option<int>,
|
|
191
|
+
maxNumInstructions: int,
|
|
192
|
+
registrationIndexes: array<int>,
|
|
193
|
+
addressesByContractName: dict<array<Address.t>>,
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
type log = {
|
|
197
|
+
kind: string,
|
|
198
|
+
message: string,
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// One routed instruction; `block` and `transaction` are materialised from
|
|
202
|
+
// the per-chain stores at batch prep.
|
|
203
|
+
type item = {
|
|
204
|
+
onEventRegistrationIndex: int,
|
|
205
|
+
slot: int,
|
|
206
|
+
transactionIndex: int,
|
|
207
|
+
instructionAddress: array<int>,
|
|
208
|
+
programId: string,
|
|
209
|
+
accounts: array<string>,
|
|
210
|
+
data: string,
|
|
211
|
+
d1?: string,
|
|
212
|
+
d2?: string,
|
|
213
|
+
d4?: string,
|
|
214
|
+
d8?: string,
|
|
215
|
+
isInner: bool,
|
|
216
|
+
decoded?: ResponseTypes.decodedInstruction,
|
|
217
|
+
// Present only when the routed registration opted in via `includeLogs`.
|
|
218
|
+
logs?: array<log>,
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
type response = {
|
|
222
|
+
nextSlot: int,
|
|
223
|
+
// One lean header per slot referenced by `items`; the full blocks live in
|
|
224
|
+
// the block store returned alongside.
|
|
225
|
+
blocks: array<ResponseTypes.block>,
|
|
226
|
+
items: array<item>,
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
203
230
|
type query = QueryTypes.query
|
|
204
231
|
type queryResponse = ResponseTypes.queryResponse
|
|
205
232
|
|
|
206
233
|
type t = {
|
|
207
234
|
getHeight: unit => promise<int>,
|
|
208
|
-
//
|
|
209
|
-
// Rust), keyed by (slot, transactionIndex) / slot, materialised at batch prep.
|
|
235
|
+
// Block-data range queries only; the store pages it returns are empty.
|
|
210
236
|
get: (~query: query) => promise<(queryResponse, TransactionStore.t, BlockStore.t)>,
|
|
237
|
+
// Returns the routed items plus pages of raw transactions and blocks (kept
|
|
238
|
+
// in Rust), keyed by (slot, transactionIndex) / slot, materialised at batch
|
|
239
|
+
// prep.
|
|
240
|
+
getEventItems: (
|
|
241
|
+
~query: EventItems.query,
|
|
242
|
+
) => promise<(EventItems.response, TransactionStore.t, BlockStore.t)>,
|
|
211
243
|
}
|
|
212
244
|
|
|
213
245
|
@send
|
|
214
|
-
external classFromConfig: (
|
|
246
|
+
external classFromConfig: (
|
|
247
|
+
Core.svmHyperSyncClientCtor,
|
|
248
|
+
cfg,
|
|
249
|
+
string,
|
|
250
|
+
array<Registration.input>,
|
|
251
|
+
) => t = "fromConfig"
|
|
215
252
|
|
|
216
253
|
let make = (
|
|
217
254
|
~url,
|
|
@@ -220,10 +257,10 @@ let make = (
|
|
|
220
257
|
~maxNumRetries=?,
|
|
221
258
|
~retryBaseMs=?,
|
|
222
259
|
~retryCeilingMs=?,
|
|
223
|
-
~
|
|
260
|
+
~eventRegistrations=[],
|
|
224
261
|
) => {
|
|
225
262
|
let envioVersion = Utils.EnvioPackage.value.version
|
|
226
|
-
Core.getAddon().
|
|
263
|
+
Core.getAddon().svmHyperSyncClient->classFromConfig(
|
|
227
264
|
{
|
|
228
265
|
url,
|
|
229
266
|
?apiToken,
|
|
@@ -231,8 +268,8 @@ let make = (
|
|
|
231
268
|
?maxNumRetries,
|
|
232
269
|
?retryBaseMs,
|
|
233
270
|
?retryCeilingMs,
|
|
234
|
-
?programSchemas,
|
|
235
271
|
},
|
|
236
272
|
`hyperindex/${envioVersion}`,
|
|
273
|
+
eventRegistrations,
|
|
237
274
|
)
|
|
238
275
|
}
|
|
@@ -3,26 +3,66 @@
|
|
|
3
3
|
import * as Core from "../Core.res.mjs";
|
|
4
4
|
import * as Utils from "../Utils.res.mjs";
|
|
5
5
|
|
|
6
|
+
function fromOnEventRegistrations(onEventRegistrations) {
|
|
7
|
+
return onEventRegistrations.map(reg => {
|
|
8
|
+
let eventConfig = reg.eventConfig;
|
|
9
|
+
let args = eventConfig.args;
|
|
10
|
+
let tmp;
|
|
11
|
+
tmp = args === null ? undefined : JSON.stringify(args);
|
|
12
|
+
let definedTypes = eventConfig.definedTypes;
|
|
13
|
+
let tmp$1;
|
|
14
|
+
tmp$1 = definedTypes === null ? undefined : JSON.stringify(definedTypes);
|
|
15
|
+
return {
|
|
16
|
+
index: reg.index,
|
|
17
|
+
instructionName: eventConfig.name,
|
|
18
|
+
contractName: eventConfig.contractName,
|
|
19
|
+
programId: eventConfig.programId,
|
|
20
|
+
isWildcard: reg.isWildcard,
|
|
21
|
+
discriminator: eventConfig.discriminator,
|
|
22
|
+
discriminatorByteLen: eventConfig.discriminatorByteLen,
|
|
23
|
+
isInner: eventConfig.isInner,
|
|
24
|
+
includeLogs: eventConfig.includeLogs,
|
|
25
|
+
accountFilters: eventConfig.accountFilters.map(group => group.map(filter => ({
|
|
26
|
+
position: filter.position,
|
|
27
|
+
values: filter.values
|
|
28
|
+
}))),
|
|
29
|
+
transactionFields: Array.from(eventConfig.selectedTransactionFields),
|
|
30
|
+
blockFields: Array.from(eventConfig.selectedBlockFields),
|
|
31
|
+
accounts: eventConfig.accounts,
|
|
32
|
+
argsJson: tmp,
|
|
33
|
+
definedTypesJson: tmp$1
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let Registration = {
|
|
39
|
+
fromOnEventRegistrations: fromOnEventRegistrations
|
|
40
|
+
};
|
|
41
|
+
|
|
6
42
|
let QueryTypes = {};
|
|
7
43
|
|
|
8
44
|
let ResponseTypes = {};
|
|
9
45
|
|
|
10
|
-
|
|
46
|
+
let EventItems = {};
|
|
47
|
+
|
|
48
|
+
function make(url, apiToken, httpReqTimeoutMillis, maxNumRetries, retryBaseMs, retryCeilingMs, eventRegistrationsOpt) {
|
|
49
|
+
let eventRegistrations = eventRegistrationsOpt !== undefined ? eventRegistrationsOpt : [];
|
|
11
50
|
let envioVersion = Utils.EnvioPackage.value.version;
|
|
12
|
-
return Core.getAddon().
|
|
51
|
+
return Core.getAddon().SvmHyperSyncClient.fromConfig({
|
|
13
52
|
url: url,
|
|
14
53
|
apiToken: apiToken,
|
|
15
54
|
httpReqTimeoutMillis: httpReqTimeoutMillis,
|
|
16
55
|
maxNumRetries: maxNumRetries,
|
|
17
56
|
retryBaseMs: retryBaseMs,
|
|
18
|
-
retryCeilingMs: retryCeilingMs
|
|
19
|
-
|
|
20
|
-
}, `hyperindex/` + envioVersion);
|
|
57
|
+
retryCeilingMs: retryCeilingMs
|
|
58
|
+
}, `hyperindex/` + envioVersion, eventRegistrations);
|
|
21
59
|
}
|
|
22
60
|
|
|
23
61
|
export {
|
|
62
|
+
Registration,
|
|
24
63
|
QueryTypes,
|
|
25
64
|
ResponseTypes,
|
|
65
|
+
EventItems,
|
|
26
66
|
make,
|
|
27
67
|
}
|
|
28
68
|
/* Core Not a pure module */
|