envio 3.7.0-svm-alpha.1 → 3.8.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 (45) hide show
  1. package/index.d.ts +331 -142
  2. package/package.json +6 -6
  3. package/src/ChainState.res +9 -1
  4. package/src/ChainState.res.mjs +6 -1
  5. package/src/Config.res +19 -10
  6. package/src/Config.res.mjs +17 -7
  7. package/src/Core.res +4 -0
  8. package/src/Envio.res +54 -76
  9. package/src/EventConfigBuilder.res +159 -30
  10. package/src/EventConfigBuilder.res.mjs +120 -24
  11. package/src/HandlerRegister.res +20 -11
  12. package/src/HandlerRegister.res.mjs +22 -5
  13. package/src/Hasura.res +30 -22
  14. package/src/Hasura.res.mjs +11 -5
  15. package/src/InMemoryStore.res +1 -6
  16. package/src/InMemoryStore.res.mjs +1 -3
  17. package/src/Internal.res +33 -13
  18. package/src/Internal.res.mjs +12 -16
  19. package/src/Main.res +2 -5
  20. package/src/MemoryStorage.res +40 -8
  21. package/src/MemoryStorage.res.mjs +38 -16
  22. package/src/Persistence.res +4 -2
  23. package/src/PgStorage.res +6 -1
  24. package/src/PgStorage.res.mjs +1 -1
  25. package/src/SimulateItems.res +261 -9
  26. package/src/SimulateItems.res.mjs +218 -47
  27. package/src/TestIndexer.res +26 -10
  28. package/src/TestIndexer.res.mjs +34 -12
  29. package/src/bindings/ClickHouse.res +49 -17
  30. package/src/bindings/ClickHouse.res.mjs +35 -14
  31. package/src/db/InternalTable.res +11 -0
  32. package/src/db/InternalTable.res.mjs +7 -0
  33. package/src/sources/EvmHyperSyncSource.res +8 -3
  34. package/src/sources/EvmHyperSyncSource.res.mjs +1 -1
  35. package/src/sources/SimulateSource.res +8 -4
  36. package/src/sources/SimulateSource.res.mjs +7 -3
  37. package/src/sources/Svm.res +34 -7
  38. package/src/sources/Svm.res.mjs +32 -4
  39. package/src/sources/SvmHyperSyncClient.res +10 -12
  40. package/src/sources/SvmHyperSyncClient.res.mjs +3 -2
  41. package/src/sources/SvmHyperSyncSource.res +96 -35
  42. package/src/sources/SvmHyperSyncSource.res.mjs +78 -38
  43. package/src/sources/TransactionStore.res +38 -0
  44. package/src/sources/TransactionStore.res.mjs +5 -0
  45. package/svm.schema.json +27 -78
package/index.d.ts CHANGED
@@ -1160,146 +1160,296 @@ export type SvmOnSlotOptions<Config extends IndexerConfigTypes = GlobalConfig> =
1160
1160
 
1161
1161
  // ============== SVM onInstruction types ==============
1162
1162
 
1163
- /** Borsh-decoded params view of an instruction. Present whenever a
1164
- * `ProgramSchema` was attached to the program (bundled, Anchor IDL, or
1165
- * hand-written `accounts`/`args` in YAML). Absent when no schema applies or
1166
- * the discriminator didn't match any registered instruction. */
1167
- export type SvmInstructionParams = {
1168
- /** Schema-declared instruction name. */
1169
- readonly name: string;
1170
- /** Borsh-decoded args object. POC types this as `unknown`; narrow with a
1171
- * locally-declared type until the typed-args codegen lands. */
1172
- readonly args: unknown;
1173
- /** Named accounts in schema order. Keys are exactly the schema-declared
1174
- * names; values are base58 pubkeys. */
1175
- readonly accounts: Readonly<Record<string, string>>;
1176
- /** Accounts beyond the schema's named list (Anchor `remaining_accounts`,
1177
- * IDL drift). Empty when counts match the schema. */
1178
- readonly extraAccounts: readonly string[];
1179
- };
1180
-
1181
- /** Permissive fallback shape for an instruction's `block`. The generated
1182
- * per-instruction type narrows this to `slot`/`hash` (always present) and
1183
- * `time` (always present but possibly `undefined`), plus the selected
1184
- * `field_selection.block_fields`. */
1185
- export type SvmInstructionBlock = {
1186
- /** Slot this instruction's block was matched in. */
1163
+ export type SvmLogKind =
1164
+ | "invoke"
1165
+ | "success"
1166
+ | "failed"
1167
+ | "consumed"
1168
+ | "log"
1169
+ | "data"
1170
+ | (string & {});
1171
+
1172
+ export type SvmLog = {
1173
+ readonly kind: SvmLogKind;
1174
+ readonly message: string;
1175
+ };
1176
+
1177
+ export type SvmAccountActivity = {
1178
+ readonly address: string;
1179
+ readonly transactionAccountIndex: number;
1180
+ readonly isSigner: boolean;
1181
+ readonly isWritable: boolean;
1182
+ readonly lamports: { readonly pre: bigint; readonly post: bigint } | undefined;
1183
+ readonly token: {
1184
+ readonly mint: string;
1185
+ readonly owner: string;
1186
+ readonly decimals: number;
1187
+ readonly preAmount: bigint | undefined;
1188
+ readonly postAmount: bigint | undefined;
1189
+ } | undefined;
1190
+ };
1191
+
1192
+ export type SvmInstructionAccount<
1193
+ Activity = SvmAccountActivity,
1194
+ Name extends string = string,
1195
+ > = {
1196
+ readonly address: string;
1197
+ readonly accountName: Name;
1198
+ readonly instructionAccountIndex: number;
1199
+ readonly activity: Activity | undefined;
1200
+ };
1201
+
1202
+ export type SvmBlock = {
1187
1203
  readonly slot: number;
1188
- /** Unix block time (seconds). Absent when HyperSync/Solana doesn't report a
1189
- * block time for this slot. */
1190
- readonly time?: number;
1191
- /** Block hash. */
1204
+ readonly time: number;
1192
1205
  readonly hash: string;
1193
- /** Block height. Select via `field_selection.block_fields`. */
1194
- readonly height?: number;
1195
- /** Parent slot. Select via `field_selection.block_fields`. */
1196
- readonly parentSlot?: number;
1197
- /** Parent block hash. Select via `field_selection.block_fields`. */
1198
- readonly parentHash?: string;
1199
- };
1200
-
1201
- export type SvmTokenBalance = {
1202
- readonly account?: string;
1203
- readonly mint?: string;
1204
- /** Owner at the end of the transaction, falling back to the owner on entry
1205
- * when the account was closed during it. Pre and post owners differ only
1206
- * when a `SetAuthority(AccountOwner)` runs mid-transaction. */
1207
- readonly owner?: string;
1208
- /** Mint decimals, for scaling the raw amounts below. */
1209
- readonly decimals?: number;
1210
- /** Raw amount in base units before the transaction. Absent when the token
1211
- * account was created during it. */
1212
- readonly preAmount?: bigint;
1213
- /** Raw amount in base units after the transaction. Absent when the token
1214
- * account was closed during it. */
1215
- readonly postAmount?: bigint;
1206
+ readonly height: number;
1207
+ readonly parentSlot: number;
1208
+ readonly parentHash: string;
1216
1209
  };
1217
1210
 
1218
- export type SvmLog = {
1219
- readonly kind: string;
1220
- readonly message: string;
1211
+ /** All SVM parent-transaction fields when selected. Handler
1212
+ * `fields.transaction` narrows this; `accountActivities` is implied by
1213
+ * `fields.accountActivity`. */
1214
+ export type SvmTransaction = {
1215
+ readonly transactionIndex: number;
1216
+ readonly signature: string;
1217
+ readonly feePayer: string;
1218
+ readonly success: boolean;
1219
+ readonly err: string | undefined;
1220
+ readonly fee: bigint;
1221
+ readonly computeUnitsConsumed: bigint | undefined;
1222
+ readonly accountKeys: readonly string[];
1223
+ readonly recentBlockhash: string;
1224
+ readonly version: string | undefined;
1225
+ readonly allSignatures: readonly string[];
1226
+ };
1227
+
1228
+ export type SvmInstructionFieldName =
1229
+ | "args"
1230
+ | "accounts"
1231
+ | "accountArguments"
1232
+ | "programId"
1233
+ | "data"
1234
+ | "path"
1235
+ | "isInner";
1236
+ export type SvmTransactionFieldName =
1237
+ | "transactionIndex"
1238
+ | "signature"
1239
+ | "feePayer"
1240
+ | "success"
1241
+ | "err"
1242
+ | "fee"
1243
+ | "computeUnitsConsumed"
1244
+ | "accountKeys"
1245
+ | "recentBlockhash"
1246
+ | "version"
1247
+ | "allSignatures";
1248
+ export type SvmAccountActivityFieldName =
1249
+ | "address"
1250
+ | "transactionAccountIndex"
1251
+ | "isSigner"
1252
+ | "isWritable"
1253
+ | "lamports"
1254
+ | "lamports.pre"
1255
+ | "lamports.post"
1256
+ | "token"
1257
+ | "token.mint"
1258
+ | "token.owner"
1259
+ | "token.decimals"
1260
+ | "token.preAmount"
1261
+ | "token.postAmount";
1262
+ export type SvmBlockFieldName =
1263
+ | "slot"
1264
+ | "time"
1265
+ | "hash"
1266
+ | "height"
1267
+ | "parentSlot"
1268
+ | "parentHash";
1269
+ export type SvmLogFieldName = "kind" | "message";
1270
+
1271
+ export type SvmFieldsSelection = {
1272
+ readonly instruction?: readonly SvmInstructionFieldName[];
1273
+ readonly transaction?: readonly SvmTransactionFieldName[];
1274
+ readonly accountActivity?: readonly SvmAccountActivityFieldName[];
1275
+ readonly block?: readonly SvmBlockFieldName[];
1276
+ readonly log?: readonly SvmLogFieldName[];
1277
+ };
1278
+
1279
+ type SvmListedArray<Fields, Knob extends keyof SvmFieldsSelection> = Fields[Knob &
1280
+ keyof Fields];
1281
+ type SvmListedFields<Fields, Knob extends keyof SvmFieldsSelection> = NonNullable<
1282
+ SvmListedArray<Fields, Knob>
1283
+ >[number] &
1284
+ string;
1285
+
1286
+ type SvmFieldsLiteralCheck<Fields> = [Fields] extends [undefined]
1287
+ ? unknown
1288
+ : IsWidenedArray<SvmListedArray<Fields, "instruction">> extends true
1289
+ ? EvmFieldsMustBeLiteral<"instruction">
1290
+ : IsWidenedArray<SvmListedArray<Fields, "transaction">> extends true
1291
+ ? EvmFieldsMustBeLiteral<"transaction">
1292
+ : IsWidenedArray<SvmListedArray<Fields, "accountActivity">> extends true
1293
+ ? EvmFieldsMustBeLiteral<"accountActivity">
1294
+ : IsWidenedArray<SvmListedArray<Fields, "block">> extends true
1295
+ ? EvmFieldsMustBeLiteral<"block">
1296
+ : IsWidenedArray<SvmListedArray<Fields, "log">> extends true
1297
+ ? EvmFieldsMustBeLiteral<"log">
1298
+ : unknown;
1299
+
1300
+ type SvmActivityListed<Fields> = SvmListedFields<Fields, "accountActivity">;
1301
+ type SvmActivityHas<Fields, Name extends string> = [SvmActivityListed<Fields>] extends [never]
1302
+ ? false
1303
+ : Name extends SvmActivityListed<Fields>
1304
+ ? true
1305
+ : Name extends `lamports.${string}`
1306
+ ? "lamports" extends SvmActivityListed<Fields>
1307
+ ? true
1308
+ : false
1309
+ : Name extends `token.${string}`
1310
+ ? "token" extends SvmActivityListed<Fields>
1311
+ ? true
1312
+ : false
1313
+ : false;
1314
+
1315
+ type SvmActivityField<Fields, Name extends string, T> = SvmActivityHas<
1316
+ Fields,
1317
+ Name
1318
+ > extends true
1319
+ ? T
1320
+ : FieldNotSelected<`Field '${Name}' is not selected for this handler. Add it to fields.accountActivity in the registration options.`>;
1321
+
1322
+ type SvmSelectedLamports<Fields> =
1323
+ SvmActivityHas<Fields, "lamports.pre"> extends true
1324
+ ? SvmActivityHas<Fields, "lamports.post"> extends true
1325
+ ? { readonly pre: bigint; readonly post: bigint } | undefined
1326
+ : { readonly pre: bigint } | undefined
1327
+ : SvmActivityHas<Fields, "lamports.post"> extends true
1328
+ ? { readonly post: bigint } | undefined
1329
+ : FieldNotSelected<`Field 'lamports' is not selected for this handler. Add it to fields.accountActivity in the registration options.`>;
1330
+
1331
+ export type SvmAccountTokenActivity = {
1332
+ readonly mint: string;
1333
+ readonly owner: string;
1334
+ readonly decimals: number;
1335
+ readonly preAmount: bigint | undefined;
1336
+ readonly postAmount: bigint | undefined;
1337
+ };
1338
+
1339
+ type SvmSelectedToken<Fields> = [SvmActivityListed<Fields> & (`token` | `token.${string}`)] extends [never]
1340
+ ? FieldNotSelected<`Field 'token' is not selected for this handler. Add it to fields.accountActivity in the registration options.`>
1341
+ : {
1342
+ readonly [K in keyof SvmAccountTokenActivity as SvmActivityHas<Fields, `token.${K & string}`> extends true
1343
+ ? K
1344
+ : never]: SvmAccountTokenActivity[K];
1345
+ } | undefined;
1346
+
1347
+ type SvmSelectedAccountActivity<Fields> = {
1348
+ readonly address: string;
1349
+ readonly transactionAccountIndex: SvmActivityField<Fields, "transactionAccountIndex", number>;
1350
+ readonly isSigner: SvmActivityField<Fields, "isSigner", boolean>;
1351
+ readonly isWritable: SvmActivityField<Fields, "isWritable", boolean>;
1352
+ readonly lamports: SvmSelectedLamports<Fields>;
1353
+ readonly token: SvmSelectedToken<Fields>;
1354
+ };
1355
+
1356
+ type SvmInstrListed<Fields> = SvmListedFields<Fields, "instruction">;
1357
+ type SvmInstrField<Fields, Name extends SvmInstructionFieldName, T> = Name extends SvmInstrListed<Fields>
1358
+ ? T
1359
+ : FieldNotSelected<`Field '${Name}' is not selected for this handler. Add it to fields.instruction in the registration options.`>;
1360
+
1361
+ type SvmNamedAccounts<
1362
+ Acc extends Readonly<Record<string, unknown>>,
1363
+ Fields,
1364
+ > = {
1365
+ readonly [K in keyof Acc & string]: SvmInstructionAccount<
1366
+ [SvmActivityListed<Fields>] extends [never]
1367
+ ? FieldNotSelected<`Field 'activity' is not selected for this handler. Add fields.accountActivity in the registration options.`>
1368
+ : SvmSelectedAccountActivity<Fields> | undefined,
1369
+ K
1370
+ >;
1371
+ };
1372
+
1373
+ type SvmSelectedTransaction<Fields> = {
1374
+ readonly [K in keyof SvmTransaction]: K extends SvmListedFields<Fields, "transaction">
1375
+ ? SvmTransaction[K]
1376
+ : FieldNotSelected<`Field '${K & string}' is not selected for this handler. Add it to fields.transaction in the registration options.`>;
1377
+ } & {
1378
+ readonly accountActivities: [SvmActivityListed<Fields>] extends [never]
1379
+ ? FieldNotSelected<`Field 'accountActivities' is not selected for this handler. Add fields.accountActivity in the registration options.`>
1380
+ : readonly SvmSelectedAccountActivity<Fields>[];
1381
+ };
1382
+
1383
+ type SvmSelectedBlock<Fields> = {
1384
+ readonly [K in keyof SvmBlock]: K extends "slot"
1385
+ ? SvmBlock[K]
1386
+ : K extends SvmListedFields<Fields, "block">
1387
+ ? SvmBlock[K]
1388
+ : FieldNotSelected<`Field '${K & string}' is not selected for this handler. Add it to fields.block in the registration options.`>;
1389
+ };
1390
+
1391
+ type SvmSelectedLog<Fields> = {
1392
+ readonly kind: "kind" extends SvmListedFields<Fields, "log">
1393
+ ? SvmLogKind
1394
+ : FieldNotSelected<`Field 'kind' is not selected for this handler. Add it to fields.log in the registration options.`>;
1395
+ readonly message: "message" extends SvmListedFields<Fields, "log">
1396
+ ? string
1397
+ : FieldNotSelected<`Field 'message' is not selected for this handler. Add it to fields.log in the registration options.`>;
1221
1398
  };
1222
1399
 
1223
- /** A single Solana instruction delivered to an `onInstruction` handler.
1224
- *
1225
- * Carries the matched instruction's own fields (`programId`, `data`,
1226
- * `accounts`, discriminator prefixes, `params`) plus the program/instruction
1227
- * names, parent transaction, scoped logs, and block context. Parameterised
1228
- * over `Params` so the per-(program, instruction) overload of
1229
- * `onInstruction` can narrow `instruction.params` to the codegen-generated
1230
- * `{ args, accounts }` shape.
1231
- *
1232
- * `data` and discriminator prefixes are `0x`-prefixed hex strings; accounts
1233
- * are base58 strings. */
1234
1400
  export type SvmInstruction<
1235
- Params extends SvmInstructionParams = SvmInstructionParams,
1236
- Tx = SvmTransaction,
1237
- Block = SvmInstructionBlock,
1401
+ ProgInstr = { readonly args: unknown; readonly accounts: Readonly<Record<string, string>> },
1402
+ Fields = {},
1238
1403
  > = {
1239
- /** Program name as declared under `programs[].name` in `config.yaml`. */
1240
1404
  readonly programName: string;
1241
- /** Instruction name as declared under `instructions[].name` in
1242
- * `config.yaml`. */
1243
1405
  readonly instructionName: string;
1244
- readonly programId: string;
1245
- readonly data: string;
1246
- readonly accounts: readonly string[];
1247
- readonly instructionAddress: readonly number[];
1248
- readonly isInner: boolean;
1249
- readonly d1?: string;
1250
- readonly d2?: string;
1251
- readonly d4?: string;
1252
- readonly d8?: string;
1253
- /** Borsh-decoded params. Present when a schema is configured and matched. */
1254
- readonly params?: Params;
1255
- /** Parent transaction. Carries only the fields selected via this
1256
- * instruction's `field_selection`; unselected fields are typed as
1257
- * `FieldNotSelected<...>` so reading them is a compile error. Always present
1258
- * (`{}` when no fields are selected). */
1259
- readonly transaction: Tx;
1260
- /** Present when the instruction's `include_logs` is `true`; only logs
1261
- * scoped to this exact instruction (matching `instruction_address`). */
1262
- readonly logs?: readonly SvmLog[];
1263
- /** The block this instruction's slot belongs to. Carries `slot`/`hash`
1264
- * (always present) and `time` (always present but possibly `undefined`),
1265
- * plus the fields selected via this instruction's
1266
- * `field_selection.block_fields`; unselected fields are typed as
1267
- * `FieldNotSelected<...>`. */
1268
- readonly block: Block;
1406
+ readonly discriminator: string;
1407
+ readonly programId: SvmInstrField<Fields, "programId", string>;
1408
+ readonly data: SvmInstrField<Fields, "data", string>;
1409
+ readonly path: SvmInstrField<Fields, "path", readonly number[]>;
1410
+ readonly isInner: SvmInstrField<Fields, "isInner", boolean>;
1411
+ readonly args: SvmInstrField<
1412
+ Fields,
1413
+ "args",
1414
+ ProgInstr extends { readonly args: infer A } ? A | undefined : unknown | undefined
1415
+ >;
1416
+ readonly accounts: SvmInstrField<
1417
+ Fields,
1418
+ "accounts",
1419
+ ProgInstr extends { readonly accounts: infer Acc extends Readonly<Record<string, unknown>> }
1420
+ ? SvmNamedAccounts<Acc, Fields>
1421
+ : SvmNamedAccounts<Readonly<Record<string, string>>, Fields>
1422
+ >;
1423
+ readonly accountArguments: SvmInstrField<Fields, "accountArguments", readonly string[]>;
1424
+ readonly logs: [SvmListedFields<Fields, "log">] extends [never]
1425
+ ? FieldNotSelected<`Field 'logs' is not selected for this handler. Add fields.log in the registration options.`>
1426
+ : readonly SvmSelectedLog<Fields>[];
1427
+ readonly transaction: SvmSelectedTransaction<Fields>;
1428
+ readonly block: SvmSelectedBlock<Fields>;
1269
1429
  };
1270
1430
 
1271
1431
  /** Arguments passed to handlers registered via `indexer.onInstruction`. */
1272
1432
  export type SvmOnInstructionHandlerArgs<
1273
1433
  Config extends IndexerConfigTypes = GlobalConfig,
1274
- Instr extends SvmInstruction = SvmInstruction,
1434
+ Instr = SvmInstruction,
1275
1435
  > = {
1276
1436
  readonly instruction: Instr;
1277
1437
  readonly context: SvmOnSlotContext<Config>;
1278
1438
  };
1279
1439
 
1280
- /** Shape extracted from `Global.config.svm.programs[P][I]`. The codegen
1281
- * emits `{ args: ...; accounts: ... }` per (program, instruction); this
1282
- * helper turns that into a `SvmInstructionParams`-compatible record. */
1283
- type SvmParamsFromProgramTable<TInstr> = TInstr extends {
1284
- args: infer A;
1285
- accounts: infer Acc extends Readonly<Record<string, string>>;
1286
- }
1287
- ? {
1288
- readonly name: string;
1289
- readonly args: A;
1290
- readonly accounts: Acc;
1291
- readonly extraAccounts: readonly string[];
1292
- }
1293
- : SvmInstructionParams;
1294
-
1295
1440
  /** Options for an SVM `indexer.onInstruction` registration. */
1296
- export type SvmOnInstructionOptions<P extends string = string, I extends string = string> = {
1441
+ export type SvmOnInstructionOptions<
1442
+ P extends string = string,
1443
+ I extends string = string,
1444
+ Fields extends SvmFieldsSelection | undefined = undefined,
1445
+ > = {
1297
1446
  /** Program name as declared under `chains[].programs[].name` in
1298
1447
  * `config.yaml`. */
1299
1448
  readonly program: P;
1300
1449
  /** Instruction name as declared under
1301
1450
  * `chains[].programs[].instructions[].name` in `config.yaml`. */
1302
1451
  readonly instruction: I;
1452
+ readonly fields?: Fields & SvmFieldsLiteralCheck<Fields>;
1303
1453
  };
1304
1454
 
1305
1455
  /** Handler function for an SVM `indexer.onInstruction` registration. */
@@ -1530,25 +1680,20 @@ type SvmEcosystem<Config extends IndexerConfigTypes = GlobalConfig> =
1530
1680
  /**
1531
1681
  * Register an instruction handler. Dispatch matches on
1532
1682
  * `(programId, discriminator)` from the YAML config.
1533
- * `instruction.params.args` and
1534
- * `instruction.params.accounts` are typed from the
1535
- * program's Borsh schema (Anchor IDL, bundled, or
1536
- * hand-written `accounts`/`args` in YAML). `params` stays
1537
- * optional at runtime because schema-matching can fail on
1538
- * IDL drift or unknown discriminators.
1683
+ * Handler `fields` is the only source of payload selection.
1539
1684
  */
1540
1685
  readonly onInstruction: <
1541
1686
  P extends keyof Programs & string,
1542
1687
  I extends keyof Programs[P] & string,
1688
+ const F extends SvmFieldsSelection | undefined,
1543
1689
  >(
1544
- options: SvmOnInstructionOptions<P, I>,
1690
+ options: SvmOnInstructionOptions<P, I, F>,
1545
1691
  handler: (
1546
1692
  args: SvmOnInstructionHandlerArgs<
1547
1693
  Config,
1548
1694
  SvmInstruction<
1549
- SvmParamsFromProgramTable<Programs[P][I]>,
1550
- Programs[P][I]["transaction"],
1551
- Programs[P][I]["block"]
1695
+ Programs[P][I],
1696
+ [F] extends [undefined] ? {} : F
1552
1697
  >
1553
1698
  >,
1554
1699
  ) => Promise<void>,
@@ -1691,14 +1836,71 @@ type FuelTestIndexerChainConfig<Config extends IndexerConfigTypes = GlobalConfig
1691
1836
  simulate?: FuelSimulateItem<Config>[];
1692
1837
  };
1693
1838
 
1694
- /** Configuration for a single SVM chain in the test indexer. SVM has no
1695
- * `onEvent` handlers yet, so simulate items aren't supported — only slot
1696
- * range overrides for driving `indexer.onSlot` block handlers under test. */
1697
- type SvmTestIndexerChainConfig = {
1839
+ /** Simulate item type for SVM ecosystem. */
1840
+ type SvmSimulateItem<Config extends IndexerConfigTypes = GlobalConfig> =
1841
+ Config["svm"] extends { programs: infer Programs extends Record<string, Record<string, any>> }
1842
+ ? {
1843
+ [P in keyof Programs]: {
1844
+ [I in keyof Programs[P]]: {
1845
+ /** Program name as declared under `chains[].programs[].name`. */
1846
+ program: P;
1847
+ /** Instruction name as declared under the program. */
1848
+ instruction: I;
1849
+ /** Override the slot. Auto-increments by default. */
1850
+ slot?: number;
1851
+ /** Instruction path in the CPI tree. Defaults to `[0]`. */
1852
+ path?: readonly number[];
1853
+ /** Override the program id. Defaults to the configured `program_id`. */
1854
+ programId?: string;
1855
+ /** Raw instruction data, `0x`-prefixed hex. */
1856
+ data?: string;
1857
+ /** Whether this is a CPI-invoked inner instruction. */
1858
+ isInner?: boolean;
1859
+ /** Decoded args. Keys match the instruction's arg names. */
1860
+ args?: Programs[P][I] extends { args: infer A } ? A : unknown;
1861
+ /** Named accounts. Keys match the instruction's account names. */
1862
+ accounts?: Programs[P][I] extends { accounts: infer Acc extends Record<string, unknown> }
1863
+ ? { readonly [K in keyof Acc]?: { readonly address: string } }
1864
+ : Record<string, { readonly address: string }>;
1865
+ /** Positional account addresses, zipped onto IDL names when `accounts` is omitted. */
1866
+ accountArguments?: readonly string[];
1867
+ /** Logs scoped to this instruction. */
1868
+ logs?: readonly { readonly kind?: string; readonly message?: string }[];
1869
+ /** Override block fields. */
1870
+ block?: Partial<SvmBlock>;
1871
+ /** Override transaction fields. `accountActivities` are joined onto named accounts at process time. */
1872
+ transaction?: Partial<SvmTransaction> & {
1873
+ readonly accountActivities?: readonly {
1874
+ readonly address: string;
1875
+ readonly transactionAccountIndex?: number;
1876
+ readonly isSigner?: boolean;
1877
+ readonly isWritable?: boolean;
1878
+ readonly lamports?: {
1879
+ readonly pre?: bigint;
1880
+ readonly post?: bigint;
1881
+ };
1882
+ readonly token?: {
1883
+ readonly mint?: string;
1884
+ readonly owner?: string;
1885
+ readonly decimals?: number;
1886
+ readonly preAmount?: bigint;
1887
+ readonly postAmount?: bigint;
1888
+ };
1889
+ }[];
1890
+ };
1891
+ };
1892
+ }[keyof Programs[P]];
1893
+ }[keyof Programs]
1894
+ : never;
1895
+
1896
+ /** Configuration for a single SVM chain in the test indexer. */
1897
+ type SvmTestIndexerChainConfig<Config extends IndexerConfigTypes = GlobalConfig> = {
1698
1898
  /** The slot number to start processing from. Defaults to config startBlock or progressBlock+1. */
1699
1899
  startBlock?: number;
1700
- /** The slot number to stop processing at. */
1900
+ /** The slot number to stop processing at. Defaults to max simulate slot when simulate is provided. */
1701
1901
  endBlock?: number;
1902
+ /** Simulate items to process instead of fetching from real sources. */
1903
+ simulate?: SvmSimulateItem<Config>[];
1702
1904
  };
1703
1905
 
1704
1906
  /** Entity change value containing sets and/or deleted IDs. */
@@ -1806,7 +2008,7 @@ type FuelTestChains<Config extends IndexerConfigTypes = GlobalConfig> =
1806
2008
 
1807
2009
  type SvmTestChains<Config extends IndexerConfigTypes = GlobalConfig> =
1808
2010
  HasSvm<Config> extends true
1809
- ? { [K in SvmChainIds<Config>]?: SvmTestIndexerChainConfig }
2011
+ ? { [K in SvmChainIds<Config>]?: SvmTestIndexerChainConfig<Config> }
1810
2012
  : {};
1811
2013
 
1812
2014
  /** Process configuration for the test indexer, with chains keyed by chain ID. */
@@ -1936,7 +2138,6 @@ type EvmContractsT = GlobalConfig extends { evm: { contracts: infer X extends
1936
2138
  type FuelChainsT = GlobalConfig extends { fuel: { chains: infer X extends Record<string, { id: number }> } } ? X : {};
1937
2139
  type FuelContractsT = GlobalConfig extends { fuel: { contracts: infer X extends Record<string, Record<string, any>> } } ? X : {};
1938
2140
  type SvmChainsT = GlobalConfig extends { svm: { chains: infer X extends Record<string, { id: number }> } } ? X : {};
1939
- type SvmProgramsT = GlobalConfig extends { svm: { programs: infer X extends Record<string, Record<string, any>> } } ? X : {};
1940
2141
  type EntitiesT = GlobalConfig extends { entities: infer X extends Record<string, object> } ? X : {};
1941
2142
  type EnumsT = GlobalConfig extends { enums: infer X extends Record<string, any> } ? X : {};
1942
2143
 
@@ -1958,18 +2159,6 @@ export type FuelChainId = IsEmptyObject<FuelChainsT> extends true ? NotConfigure
1958
2159
  /** Union of all configured SVM chain IDs. */
1959
2160
  export type SvmChainId = IsEmptyObject<SvmChainsT> extends true ? NotConfigured<"SvmChainId", "Configure SVM chains"> : SvmChainsT [keyof SvmChainsT ]["id"];
1960
2161
 
1961
- /** The SVM parent-transaction type generated from this project's
1962
- * `field_selection`: the union of every instruction's `transaction` shape,
1963
- * with unselected fields typed as `FieldNotSelected<...>`. Resolves to a
1964
- * `NotConfigured` hint until `envio codegen` augments {@link Global}. */
1965
- export type SvmTransaction = IsEmptyObject<SvmProgramsT> extends true
1966
- ? NotConfigured<"SvmTransaction", "Configure SVM programs">
1967
- : {
1968
- [P in keyof SvmProgramsT]: {
1969
- [I in keyof SvmProgramsT[P]]: SvmProgramsT[P][I]["transaction"];
1970
- }[keyof SvmProgramsT[P]];
1971
- }[keyof SvmProgramsT];
1972
-
1973
2162
  /** Lookup an EVM event type by contract and event name. Without generics,
1974
2163
  * resolves to the discriminated union of every EVM event in the project. */
1975
2164
  export type EvmEvent<
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "envio",
3
- "version": "3.7.0-svm-alpha.1",
3
+ "version": "3.8.0",
4
4
  "type": "module",
5
5
  "description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
6
6
  "bin": "./bin.mjs",
@@ -69,10 +69,10 @@
69
69
  "tsx": "4.21.0"
70
70
  },
71
71
  "optionalDependencies": {
72
- "envio-linux-x64": "3.7.0-svm-alpha.1",
73
- "envio-linux-x64-musl": "3.7.0-svm-alpha.1",
74
- "envio-linux-arm64": "3.7.0-svm-alpha.1",
75
- "envio-darwin-x64": "3.7.0-svm-alpha.1",
76
- "envio-darwin-arm64": "3.7.0-svm-alpha.1"
72
+ "envio-linux-x64": "3.8.0",
73
+ "envio-linux-x64-musl": "3.8.0",
74
+ "envio-linux-arm64": "3.8.0",
75
+ "envio-darwin-x64": "3.8.0",
76
+ "envio-darwin-arm64": "3.8.0"
77
77
  }
78
78
  }
@@ -301,13 +301,15 @@ let makeInternal = (
301
301
  }),
302
302
  ]
303
303
  }
304
- | Config.SimulateSourceConfig({items, endBlock}) => [
304
+ | Config.SimulateSourceConfig({items, endBlock, ?transactionStore, ?blockStore}) => [
305
305
  SimulateSource.make(
306
306
  ~items,
307
307
  ~endBlock,
308
308
  ~chainId,
309
309
  ~addressStore,
310
310
  ~ecosystem=config.ecosystem.name,
311
+ ~transactionStore,
312
+ ~blockStore,
311
313
  ),
312
314
  ]
313
315
  // For tests: use ready-to-use sources directly
@@ -852,6 +854,12 @@ let applyTransactionGroups = async (store: TransactionStore.t, g: transactionGro
852
854
  g.payloadGroups->Array.forEachWithIndex((payloads, i) => {
853
855
  let tx = txs->Array.getUnsafe(i)
854
856
  payloads->Array.forEach(payload => payload->Internal.setPayloadTransaction(tx))
857
+ switch (
858
+ tx->(Utils.magic: Internal.eventTransaction => dict<unknown>)
859
+ )->Dict.get("accountActivities") {
860
+ | Some(_) => payloads->Array.forEach(payload => Svm.attachAccountActivities(payload, tx))
861
+ | None => ()
862
+ }
855
863
  })
856
864
  } else {
857
865
  g.payloadGroups->Array.forEach(payloads =>
@@ -181,7 +181,7 @@ function makeInternal(chainConfig, indexingAddresses, startBlock, endBlock, firs
181
181
  );
182
182
  break;
183
183
  case "SimulateSourceConfig" :
184
- sources$1 = [SimulateSource.make(sources.items, sources.endBlock, chainId, addressStore, config.ecosystem.name)];
184
+ sources$1 = [SimulateSource.make(sources.items, sources.endBlock, chainId, addressStore, config.ecosystem.name, Primitive_option.some(sources.transactionStore), Primitive_option.some(sources.blockStore))];
185
185
  break;
186
186
  case "CustomSources" :
187
187
  sources$1 = sources._0;
@@ -567,6 +567,11 @@ async function applyTransactionGroups(store, g) {
567
567
  payloads.forEach(payload => {
568
568
  payload.transaction = tx;
569
569
  });
570
+ let match = tx["accountActivities"];
571
+ if (match !== undefined) {
572
+ payloads.forEach(payload => Svm.attachAccountActivities(payload, tx));
573
+ return;
574
+ }
570
575
  });
571
576
  return;
572
577
  }