envio 3.7.0 → 3.9.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.
Files changed (79) hide show
  1. package/README.md +2 -2
  2. package/index.d.ts +399 -156
  3. package/package.json +6 -6
  4. package/src/AddressRows.res +121 -0
  5. package/src/AddressRows.res.mjs +143 -0
  6. package/src/Batch.res +2 -0
  7. package/src/Batch.res.mjs +2 -1
  8. package/src/ChainState.res +82 -68
  9. package/src/ChainState.res.mjs +81 -65
  10. package/src/ChainState.resi +14 -9
  11. package/src/Config.res +41 -91
  12. package/src/Config.res.mjs +34 -68
  13. package/src/ContractMapping.res +66 -0
  14. package/src/ContractMapping.res.mjs +73 -0
  15. package/src/Core.res +20 -0
  16. package/src/Core.res.mjs +4 -0
  17. package/src/Envio.res +54 -76
  18. package/src/EventConfigBuilder.res +157 -30
  19. package/src/EventConfigBuilder.res.mjs +118 -24
  20. package/src/FetchState.res +59 -67
  21. package/src/FetchState.res.mjs +34 -44
  22. package/src/HandlerRegister.res +20 -11
  23. package/src/HandlerRegister.res.mjs +22 -5
  24. package/src/Hasura.res +30 -22
  25. package/src/Hasura.res.mjs +11 -5
  26. package/src/InMemoryStore.res +18 -36
  27. package/src/InMemoryStore.res.mjs +12 -26
  28. package/src/IndexerState.res +21 -1
  29. package/src/IndexerState.res.mjs +9 -3
  30. package/src/IndexerState.resi +1 -0
  31. package/src/Internal.res +33 -13
  32. package/src/Internal.res.mjs +12 -16
  33. package/src/Main.res +27 -20
  34. package/src/Main.res.mjs +19 -14
  35. package/src/MemoryStorage.res +78 -73
  36. package/src/MemoryStorage.res.mjs +66 -81
  37. package/src/Metrics.res +15 -1
  38. package/src/Metrics.res.mjs +5 -1
  39. package/src/Persistence.res +34 -18
  40. package/src/Persistence.res.mjs +8 -5
  41. package/src/PgStorage.res +189 -66
  42. package/src/PgStorage.res.mjs +93 -59
  43. package/src/Rollback.res +14 -10
  44. package/src/Rollback.res.mjs +4 -2
  45. package/src/SimulateItems.res +254 -9
  46. package/src/SimulateItems.res.mjs +214 -47
  47. package/src/TestIndexer.res +119 -121
  48. package/src/TestIndexer.res.mjs +95 -100
  49. package/src/Utils.res +7 -0
  50. package/src/Utils.res.mjs +9 -2
  51. package/src/Writing.res +2 -0
  52. package/src/Writing.res.mjs +2 -1
  53. package/src/bindings/ClickHouse.res +39 -6
  54. package/src/bindings/ClickHouse.res.mjs +29 -4
  55. package/src/bindings/NodeJs.res +9 -0
  56. package/src/bindings/NodeJs.res.mjs +8 -1
  57. package/src/bindings/Postgres.res +9 -0
  58. package/src/bindings/Postgres.res.mjs +3 -0
  59. package/src/db/EntityHistory.res +12 -18
  60. package/src/db/EntityHistory.res.mjs +3 -14
  61. package/src/db/InternalTable.res +182 -65
  62. package/src/db/InternalTable.res.mjs +183 -73
  63. package/src/db/Table.res +24 -0
  64. package/src/db/Table.res.mjs +20 -1
  65. package/src/sources/AddressSet.res +0 -22
  66. package/src/sources/AddressStore.res +48 -88
  67. package/src/sources/AddressStore.res.mjs +11 -22
  68. package/src/sources/EvmHyperSyncSource.res +3 -2
  69. package/src/sources/SimulateSource.res +8 -4
  70. package/src/sources/SimulateSource.res.mjs +7 -3
  71. package/src/sources/Svm.res +34 -7
  72. package/src/sources/Svm.res.mjs +32 -4
  73. package/src/sources/SvmHyperSyncClient.res +24 -30
  74. package/src/sources/SvmHyperSyncClient.res.mjs +3 -2
  75. package/src/sources/SvmHyperSyncSource.res +88 -36
  76. package/src/sources/SvmHyperSyncSource.res.mjs +71 -39
  77. package/src/sources/TransactionStore.res +38 -0
  78. package/src/sources/TransactionStore.res.mjs +5 -0
  79. package/svm.schema.json +37 -82
@@ -10,50 +10,100 @@ type options = {
10
10
  addressStore: AddressStore.t,
11
11
  }
12
12
 
13
- // Parse the Rust-decoded instruction (args/accounts arrive as JSON strings to
14
- // side-step napi-rs's lack of native JSON passthrough) into the public shape.
15
- let parseDecoded = (
16
- d: SvmHyperSyncClient.ResponseTypes.decodedInstruction,
17
- ): Envio.svmInstructionParams => {
18
- let args = try JSON.parseOrThrow(d.argsJson) catch {
19
- | _ => JSON.Object(Dict.make())
20
- }
21
- let accounts = try {
22
- JSON.parseOrThrow(d.accountsJson)->(Utils.magic: JSON.t => dict<string>)
23
- } catch {
24
- | _ => Dict.make()
13
+ let namedAccounts = (
14
+ ~idlNames: array<string>,
15
+ ~accountArguments: array<string>,
16
+ ): dict<Envio.svmInstructionAccount> => {
17
+ let out = Dict.make()
18
+ idlNames->Array.forEachWithIndex((name, i) =>
19
+ switch accountArguments->Array.get(i) {
20
+ | Some(address) =>
21
+ out->Dict.set(
22
+ name,
23
+ {
24
+ Envio.address: address->SvmTypes.Pubkey.fromStringUnsafe,
25
+ accountName: name,
26
+ instructionAccountIndex: i,
27
+ },
28
+ )
29
+ | None => ()
30
+ }
31
+ )
32
+ out
33
+ }
34
+
35
+ let selectedLog = (log: SvmHyperSyncClient.EventItems.log, ~logFields: Utils.Set.t<string>): Envio.svmLog => {
36
+ let out = Dict.make()
37
+ if logFields->Utils.Set.has("kind") {
38
+ switch log.kind->Null.toOption {
39
+ | Some(kind) => out->Dict.set("kind", kind)
40
+ | None => ()
41
+ }
25
42
  }
26
- {
27
- name: d.name,
28
- args,
29
- accounts,
30
- extraAccounts: d.extraAccounts,
43
+ if logFields->Utils.Set.has("message") {
44
+ switch log.message->Null.toOption {
45
+ | Some(message) => out->Dict.set("message", message)
46
+ | None => ()
47
+ }
31
48
  }
49
+ out->(Utils.magic: dict<string> => Envio.svmLog)
32
50
  }
33
51
 
34
- // `block` is omitted; it's materialised from the block store at batch prep.
52
+ let setField = (out: dict<unknown>, name: string, value: 'a) =>
53
+ out->Dict.set(name, value->(Utils.magic: 'a => unknown))
54
+
55
+ // `block` and `transaction` are omitted; they're materialised from the stores
56
+ // at batch prep. Named-account `.activity` is attached then too.
57
+ // Unselected instruction keys must be omitted, not assigned `undefined`.
35
58
  let toSvmInstruction = (
36
59
  item: SvmHyperSyncClient.EventItems.item,
37
60
  ~programName,
38
61
  ~instructionName,
62
+ ~eventConfig: Internal.svmInstructionEventConfig,
63
+ ~fieldSelection: Internal.fieldSelection,
39
64
  ): Envio.svmInstruction => {
40
- programName,
41
- instructionName,
42
- programId: item.programId->SvmTypes.Pubkey.fromStringUnsafe,
43
- data: item.data,
44
- accounts: item.accounts->SvmTypes.Pubkey.fromStringsUnsafe,
45
- instructionAddress: item.instructionAddress,
46
- isInner: item.isInner,
47
- d1: ?item.d1,
48
- d2: ?item.d2,
49
- d4: ?item.d4,
50
- d8: ?item.d8,
51
- params: ?(item.decoded->Option.map(parseDecoded)),
52
- logs: ?(
53
- item.logs->Option.map(logs =>
54
- logs->Array.map((log): Envio.svmLog => {kind: log.kind, message: log.message})
65
+ let hasSelection = name => fieldSelection.instructionFields->Utils.Set.has(name)
66
+ let discriminator = switch eventConfig.discriminator {
67
+ | Some(d) => d
68
+ | None => item.data
69
+ }
70
+ let out = Dict.make()
71
+ out->setField("programName", programName)
72
+ out->setField("instructionName", instructionName)
73
+ out->setField("discriminator", discriminator)
74
+ if hasSelection("programId") {
75
+ out->setField("programId", item.programId->SvmTypes.Pubkey.fromStringUnsafe)
76
+ }
77
+ if hasSelection("data") {
78
+ out->setField("data", item.data)
79
+ }
80
+ if hasSelection("path") {
81
+ out->setField("path", item.path)
82
+ }
83
+ if hasSelection("isInner") {
84
+ out->setField("isInner", item.isInner)
85
+ }
86
+ if hasSelection("args") {
87
+ out->setField("args", item.argsJson->JSON.parseOrThrow)
88
+ }
89
+ if hasSelection("accounts") {
90
+ out->setField(
91
+ "accounts",
92
+ namedAccounts(~idlNames=eventConfig.accounts, ~accountArguments=item.accounts),
55
93
  )
56
- ),
94
+ }
95
+ if hasSelection("accountArguments") {
96
+ out->setField("accountArguments", item.accounts->SvmTypes.Pubkey.fromStringsUnsafe)
97
+ }
98
+ if fieldSelection.logFields->Utils.Set.size > 0 {
99
+ out->setField(
100
+ "logs",
101
+ item.logs
102
+ ->Null.getOr([])
103
+ ->Array.map(log => selectedLog(log, ~logFields=fieldSelection.logFields)),
104
+ )
105
+ }
106
+ out->(Utils.magic: dict<unknown> => Envio.svmInstruction)
57
107
  }
58
108
 
59
109
  let make = (
@@ -144,18 +194,20 @@ let make = (
144
194
  item,
145
195
  ~programName=eventConfig.contractName,
146
196
  ~instructionName=eventConfig.name,
197
+ ~eventConfig,
198
+ ~fieldSelection=onEventRegistration.fieldSelection,
147
199
  )
148
200
  Internal.Event({
149
201
  onEventRegistration,
150
202
  chainId,
151
203
  blockNumber: item.slot,
152
- // A slot orders by `(transactionIndex, instructionAddress)` — the
204
+ // A slot orders by `(transactionIndex, path)` — the
153
205
  // transaction, then the instruction's position in its CPI tree. Both
154
206
  // ride the item so the buffer comparator can order on the pair
155
207
  // directly; no single integer can hold it (Solana allows a CPI depth
156
208
  // of 5, which needs more bits than a JS integer is exact to).
157
209
  logIndex: item.transactionIndex,
158
- orderPath: item.instructionAddress,
210
+ orderPath: item.path,
159
211
  // The parent transaction is materialised from the store at batch prep.
160
212
  transactionIndex: item.transactionIndex,
161
213
  payload: payload->(Utils.magic: Envio.svmInstruction => Internal.eventPayload),
@@ -3,51 +3,81 @@
3
3
  import * as Source from "./Source.res.mjs";
4
4
  import * as HyperSync from "./HyperSync.res.mjs";
5
5
  import * as Performance from "../bindings/Performance.res.mjs";
6
+ import * as Stdlib_Null from "@rescript/runtime/lib/es6/Stdlib_Null.js";
6
7
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
7
8
  import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
8
9
  import * as SvmHyperSyncClient from "./SvmHyperSyncClient.res.mjs";
9
10
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
10
11
 
11
- function parseDecoded(d) {
12
- let args;
13
- try {
14
- args = JSON.parse(d.argsJson);
15
- } catch (exn) {
16
- args = {};
12
+ function namedAccounts(idlNames, accountArguments) {
13
+ let out = {};
14
+ idlNames.forEach((name, i) => {
15
+ let address = accountArguments[i];
16
+ if (address !== undefined) {
17
+ out[name] = {
18
+ address: address,
19
+ accountName: name,
20
+ instructionAccountIndex: i
21
+ };
22
+ return;
23
+ }
24
+ });
25
+ return out;
26
+ }
27
+
28
+ function selectedLog(log, logFields) {
29
+ let out = {};
30
+ if (logFields.has("kind")) {
31
+ let kind = log.kind;
32
+ if (kind !== null) {
33
+ out["kind"] = kind;
34
+ }
17
35
  }
18
- let accounts;
19
- try {
20
- accounts = JSON.parse(d.accountsJson);
21
- } catch (exn$1) {
22
- accounts = {};
36
+ if (logFields.has("message")) {
37
+ let message = log.message;
38
+ if (message !== null) {
39
+ out["message"] = message;
40
+ }
23
41
  }
24
- return {
25
- name: d.name,
26
- args: args,
27
- accounts: accounts,
28
- extraAccounts: d.extraAccounts
29
- };
42
+ return out;
30
43
  }
31
44
 
32
- function toSvmInstruction(item, programName, instructionName) {
33
- return {
34
- programName: programName,
35
- instructionName: instructionName,
36
- programId: item.programId,
37
- data: item.data,
38
- accounts: item.accounts,
39
- instructionAddress: item.instructionAddress,
40
- isInner: item.isInner,
41
- d1: item.d1,
42
- d2: item.d2,
43
- d4: item.d4,
44
- d8: item.d8,
45
- params: Stdlib_Option.map(item.decoded, parseDecoded),
46
- logs: Stdlib_Option.map(item.logs, logs => logs.map(log => ({
47
- kind: log.kind,
48
- message: log.message
49
- })))
50
- };
45
+ function setField(out, name, value) {
46
+ out[name] = value;
47
+ }
48
+
49
+ function toSvmInstruction(item, programName, instructionName, eventConfig, fieldSelection) {
50
+ let d = eventConfig.discriminator;
51
+ let discriminator = d !== undefined ? d : item.data;
52
+ let out = {};
53
+ setField(out, "programName", programName);
54
+ setField(out, "instructionName", instructionName);
55
+ setField(out, "discriminator", discriminator);
56
+ if (fieldSelection.instructionFields.has("programId")) {
57
+ setField(out, "programId", item.programId);
58
+ }
59
+ if (fieldSelection.instructionFields.has("data")) {
60
+ setField(out, "data", item.data);
61
+ }
62
+ if (fieldSelection.instructionFields.has("path")) {
63
+ setField(out, "path", item.path);
64
+ }
65
+ if (fieldSelection.instructionFields.has("isInner")) {
66
+ setField(out, "isInner", item.isInner);
67
+ }
68
+ if (fieldSelection.instructionFields.has("args")) {
69
+ setField(out, "args", JSON.parse(item.argsJson));
70
+ }
71
+ if (fieldSelection.instructionFields.has("accounts")) {
72
+ setField(out, "accounts", namedAccounts(eventConfig.accounts, item.accounts));
73
+ }
74
+ if (fieldSelection.instructionFields.has("accountArguments")) {
75
+ setField(out, "accountArguments", item.accounts);
76
+ }
77
+ if (fieldSelection.logFields.size > 0) {
78
+ setField(out, "logs", Stdlib_Null.getOr(item.logs, []).map(log => selectedLog(log, fieldSelection.logFields)));
79
+ }
80
+ return out;
51
81
  }
52
82
 
53
83
  function make(param) {
@@ -97,14 +127,14 @@ function make(param) {
97
127
  let parsedQueueItems = resp.items.map(item => {
98
128
  let onEventRegistration = onEventRegistrations[item.onEventRegistrationIndex];
99
129
  let eventConfig = onEventRegistration.eventConfig;
100
- let payload = toSvmInstruction(item, eventConfig.contractName, eventConfig.name);
130
+ let payload = toSvmInstruction(item, eventConfig.contractName, eventConfig.name, eventConfig, onEventRegistration.fieldSelection);
101
131
  return {
102
132
  kind: 0,
103
133
  onEventRegistration: onEventRegistration,
104
134
  chainId: chainId,
105
135
  blockNumber: item.slot,
106
136
  logIndex: item.transactionIndex,
107
- orderPath: item.instructionAddress,
137
+ orderPath: item.path,
108
138
  transactionIndex: item.transactionIndex,
109
139
  payload: payload
110
140
  };
@@ -152,7 +182,9 @@ function make(param) {
152
182
  }
153
183
 
154
184
  export {
155
- parseDecoded,
185
+ namedAccounts,
186
+ selectedLog,
187
+ setField,
156
188
  toSvmInstruction,
157
189
  make,
158
190
  }
@@ -31,6 +31,44 @@ let fieldCodes = FieldMask.fieldCodes
31
31
  // Drain another store (a fetch-response page) into this one.
32
32
  @send external merge: (t, t) => unit = "merge"
33
33
 
34
+ type svmTxInput = {
35
+ slot: int,
36
+ transactionIndex: int,
37
+ signature?: string,
38
+ allSignatures?: array<string>,
39
+ feePayer?: string,
40
+ success?: bool,
41
+ err?: string,
42
+ fee?: bigint,
43
+ computeUnitsConsumed?: bigint,
44
+ accountKeys?: array<string>,
45
+ recentBlockhash?: string,
46
+ version?: string,
47
+ }
48
+
49
+ type svmActivityInput = {
50
+ slot: int,
51
+ transactionIndex: int,
52
+ account: string,
53
+ accountIndex?: int,
54
+ isSigner?: bool,
55
+ isWritable?: bool,
56
+ preBalance?: bigint,
57
+ postBalance?: bigint,
58
+ mint?: string,
59
+ owner?: string,
60
+ decimals?: int,
61
+ preAmount?: bigint,
62
+ postAmount?: bigint,
63
+ }
64
+
65
+ @send
66
+ external fromJsSvm: (Core.transactionStoreCtor, array<svmTxInput>, array<svmActivityInput>) => t =
67
+ "fromJsSvm"
68
+
69
+ let fromSvmJs = (transactions: array<svmTxInput>, activities: array<svmActivityInput>): t =>
70
+ Core.getAddon().transactionStore->fromJsSvm(transactions, activities)
71
+
34
72
  // Bulk-materialise transactions off the JS thread, one row per
35
73
  // (blockNumbers[i], transactionIndices[i]) key, decoding only the fields set in
36
74
  // that row's own masks[i]. Result is aligned with the input.
@@ -15,6 +15,10 @@ function make(ecosystem, shouldChecksum) {
15
15
  }
16
16
  }
17
17
 
18
+ function fromSvmJs(transactions, activities) {
19
+ return Core.getAddon().TransactionStore.fromJsSvm(transactions, activities);
20
+ }
21
+
18
22
  let makeMaskFn = FieldMask.makeMaskFn;
19
23
 
20
24
  let orMask = FieldMask.orMask;
@@ -26,5 +30,6 @@ export {
26
30
  makeMaskFn,
27
31
  orMask,
28
32
  fieldCodes,
33
+ fromSvmJs,
29
34
  }
30
35
  /* Core Not a pure module */
package/svm.schema.json CHANGED
@@ -212,6 +212,10 @@
212
212
  "Chain": {
213
213
  "type": "object",
214
214
  "properties": {
215
+ "id": {
216
+ "description": "Identifies the Svm cluster: the label \"solana\" (7565164) or \"solana-devnet\" (7565165), or an explicit number of your choosing for other clusters (up to Number.MAX_SAFE_INTEGER). Svm has no native numeric chain id, so the label ids are assigned by Envio and match the ids used for HyperSync usage attribution.",
217
+ "$ref": "#/$defs/ChainId"
218
+ },
215
219
  "skip": {
216
220
  "description": "Excludes the chain from indexing and migrations. Code generation is unaffected. For testing, prefer using a test framework instead.",
217
221
  "type": [
@@ -264,15 +268,44 @@
264
268
  },
265
269
  "additionalProperties": false,
266
270
  "required": [
271
+ "id",
267
272
  "start_block"
268
273
  ]
269
274
  },
275
+ "ChainId": {
276
+ "description": "The chain id of an Svm chain: either a known cluster label or an\nexplicit number (for private chains, rollups, or custom clusters).",
277
+ "anyOf": [
278
+ {
279
+ "$ref": "#/$defs/ChainLabel"
280
+ },
281
+ {
282
+ "type": "integer",
283
+ "format": "uint64",
284
+ "minimum": 0,
285
+ "maximum": 9007199254740991
286
+ }
287
+ ]
288
+ },
289
+ "ChainLabel": {
290
+ "type": "string",
291
+ "enum": [
292
+ "solana",
293
+ "solana-devnet"
294
+ ]
295
+ },
270
296
  "Experimental": {
271
297
  "type": "object",
272
298
  "properties": {
273
299
  "hypersync_config": {
274
- "description": "HyperSync Config for fetching historical instructions on this chain.",
275
- "$ref": "#/$defs/HypersyncConfig"
300
+ "description": "HyperSync Config for fetching historical instructions on this chain. Optional for the `solana` and `solana-devnet` chain ids, which default to their public HyperSync endpoints; required for any other chain id.",
301
+ "anyOf": [
302
+ {
303
+ "$ref": "#/$defs/HypersyncConfig"
304
+ },
305
+ {
306
+ "type": "null"
307
+ }
308
+ ]
276
309
  },
277
310
  "programs": {
278
311
  "description": "Solana programs to index on this chain.",
@@ -284,7 +317,6 @@
284
317
  },
285
318
  "additionalProperties": false,
286
319
  "required": [
287
- "hypersync_config",
288
320
  "programs"
289
321
  ]
290
322
  },
@@ -292,7 +324,7 @@
292
324
  "type": "object",
293
325
  "properties": {
294
326
  "url": {
295
- "description": "URL of the HyperSync endpoint (default: the public Solana HyperSync endpoint at https://solana.hypersync.xyz)",
327
+ "description": "URL of the HyperSync endpoint (defaults to the public endpoint of the chain id: https://solana.hypersync.xyz for `solana`, https://solana-devnet.hypersync.xyz for `solana-devnet`)",
296
328
  "type": "string"
297
329
  }
298
330
  },
@@ -373,19 +405,8 @@
373
405
  }
374
406
  ]
375
407
  },
376
- "field_selection": {
377
- "description": "Select which additional data to fetch for each matched instruction. Each key accepts `true` (include all fields) or a list of field names (per-field selection, not yet supported). When absent, only the instruction itself is included.",
378
- "anyOf": [
379
- {
380
- "$ref": "#/$defs/SvmFieldSelection"
381
- },
382
- {
383
- "type": "null"
384
- }
385
- ]
386
- },
387
408
  "accounts": {
388
- "description": "Optional positional account names. The Nth entry names account slot N on the dispatched instruction; surfaces as `event.instruction.decoded.accounts.<name>`. Accounts beyond the named list become `extra_accounts`.",
409
+ "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`.",
389
410
  "type": [
390
411
  "array",
391
412
  "null"
@@ -466,72 +487,6 @@
466
487
  "any_of"
467
488
  ]
468
489
  },
469
- "SvmFieldSelection": {
470
- "type": "object",
471
- "properties": {
472
- "transaction_fields": {
473
- "description": "Parent-transaction fields to include on each matched instruction, as a list of field names. Omit (or pass an empty list) to include no transaction.",
474
- "type": [
475
- "array",
476
- "null"
477
- ],
478
- "items": {
479
- "$ref": "#/$defs/SvmTransactionField"
480
- }
481
- },
482
- "block_fields": {
483
- "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`.",
484
- "type": [
485
- "array",
486
- "null"
487
- ],
488
- "items": {
489
- "$ref": "#/$defs/SvmBlockField"
490
- }
491
- },
492
- "log_fields": {
493
- "description": "Set to `true` to include program logs scoped to each matched instruction.",
494
- "type": [
495
- "boolean",
496
- "null"
497
- ]
498
- },
499
- "token_balance_fields": {
500
- "description": "Set to `true` to include SPL Token / Token-2022 balance snapshots for the parent transaction, exposed as `transaction.tokenBalances`. Independent of `transaction_fields`.",
501
- "type": [
502
- "boolean",
503
- "null"
504
- ]
505
- }
506
- },
507
- "additionalProperties": false
508
- },
509
- "SvmTransactionField": {
510
- "description": "Selectable parent-transaction field names (camelCase), matching the\npublic `svmTransaction` shape. `tokenBalances` is selected via the\nseparate `token_balance_fields` toggle, so it isn't listed here.",
511
- "type": "string",
512
- "enum": [
513
- "transactionIndex",
514
- "signature",
515
- "feePayer",
516
- "success",
517
- "err",
518
- "fee",
519
- "computeUnitsConsumed",
520
- "accountKeys",
521
- "recentBlockhash",
522
- "version",
523
- "allSignatures"
524
- ]
525
- },
526
- "SvmBlockField": {
527
- "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.",
528
- "type": "string",
529
- "enum": [
530
- "height",
531
- "parentSlot",
532
- "parentHash"
533
- ]
534
- },
535
490
  "ArgDef": {
536
491
  "description": "One named argument of an instruction. Mirrors\n`hypersync_client_solana::decode::NamedField`.",
537
492
  "type": "object",