envio 3.8.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.
- package/README.md +2 -2
- package/index.d.ts +158 -104
- package/package.json +6 -6
- package/src/AddressRows.res +121 -0
- package/src/AddressRows.res.mjs +143 -0
- package/src/Batch.res +2 -0
- package/src/Batch.res.mjs +2 -1
- package/src/ChainState.res +76 -70
- package/src/ChainState.res.mjs +76 -65
- package/src/ChainState.resi +14 -9
- package/src/Config.res +23 -82
- package/src/Config.res.mjs +19 -63
- package/src/ContractMapping.res +66 -0
- package/src/ContractMapping.res.mjs +73 -0
- package/src/Core.res +20 -0
- package/src/Core.res.mjs +4 -0
- package/src/EventConfigBuilder.res +0 -2
- package/src/EventConfigBuilder.res.mjs +0 -2
- package/src/FetchState.res +59 -67
- package/src/FetchState.res.mjs +34 -44
- package/src/InMemoryStore.res +17 -30
- package/src/InMemoryStore.res.mjs +11 -23
- package/src/IndexerState.res +21 -1
- package/src/IndexerState.res.mjs +9 -3
- package/src/IndexerState.resi +1 -0
- package/src/Main.res +25 -15
- package/src/Main.res.mjs +19 -14
- package/src/MemoryStorage.res +39 -66
- package/src/MemoryStorage.res.mjs +28 -65
- package/src/Metrics.res +15 -1
- package/src/Metrics.res.mjs +5 -1
- package/src/Persistence.res +30 -16
- package/src/Persistence.res.mjs +8 -5
- package/src/PgStorage.res +183 -65
- package/src/PgStorage.res.mjs +92 -58
- package/src/Rollback.res +14 -10
- package/src/Rollback.res.mjs +4 -2
- package/src/SimulateItems.res +5 -12
- package/src/SimulateItems.res.mjs +6 -10
- package/src/TestIndexer.res +93 -111
- package/src/TestIndexer.res.mjs +61 -88
- package/src/Utils.res +7 -0
- package/src/Utils.res.mjs +9 -2
- package/src/Writing.res +2 -0
- package/src/Writing.res.mjs +2 -1
- package/src/bindings/ClickHouse.res +6 -0
- package/src/bindings/ClickHouse.res.mjs +4 -0
- package/src/bindings/NodeJs.res +9 -0
- package/src/bindings/NodeJs.res.mjs +8 -1
- package/src/bindings/Postgres.res +9 -0
- package/src/bindings/Postgres.res.mjs +3 -0
- package/src/db/EntityHistory.res +12 -18
- package/src/db/EntityHistory.res.mjs +3 -14
- package/src/db/InternalTable.res +171 -65
- package/src/db/InternalTable.res.mjs +176 -73
- package/src/db/Table.res +24 -0
- package/src/db/Table.res.mjs +20 -1
- package/src/sources/AddressSet.res +0 -22
- package/src/sources/AddressStore.res +48 -88
- package/src/sources/AddressStore.res.mjs +11 -22
- package/src/sources/SvmHyperSyncClient.res +17 -21
- package/src/sources/SvmHyperSyncSource.res +4 -9
- package/src/sources/SvmHyperSyncSource.res.mjs +5 -13
- package/svm.schema.json +10 -4
package/README.md
CHANGED
|
@@ -69,7 +69,7 @@ A few things already running in production:
|
|
|
69
69
|
|
|
70
70
|
**Multichain indexing**
|
|
71
71
|
- Index EVM, SVM, and Fuel blockchains from a single indexer
|
|
72
|
-
-
|
|
72
|
+
- 79+ EVM chains with first-class HyperSync support, plus any EVM chain via RPC
|
|
73
73
|
- Real-time indexing with reorg handling built in
|
|
74
74
|
|
|
75
75
|
**Developer experience**
|
|
@@ -129,7 +129,7 @@ HyperSync can also be used directly for custom data pipelines in Python, Rust, N
|
|
|
129
129
|
|
|
130
130
|
## Supported networks
|
|
131
131
|
|
|
132
|
-
HyperIndex supports any EVM-compatible L1, L2, or L3, plus Fuel and Solana (
|
|
132
|
+
HyperIndex supports any EVM-compatible L1, L2, or L3, plus Fuel and Solana (beta). 79+ chains have first-class HyperSync support for maximum speed. For any EVM chain not on the HyperSync list, RPC-based indexing works out of the box. Solana indexing runs on HyperSync for Solana, with instruction-level handlers and IDL-aware decoding.
|
|
133
133
|
|
|
134
134
|
[Full network list →](https://docs.envio.dev/docs/HyperIndex/supported-networks)
|
|
135
135
|
|
package/index.d.ts
CHANGED
|
@@ -1169,37 +1169,34 @@ export type SvmLogKind =
|
|
|
1169
1169
|
| "data"
|
|
1170
1170
|
| (string & {});
|
|
1171
1171
|
|
|
1172
|
-
export type
|
|
1172
|
+
export type SvmAllLogFields = {
|
|
1173
1173
|
readonly kind: SvmLogKind;
|
|
1174
1174
|
readonly message: string;
|
|
1175
1175
|
};
|
|
1176
1176
|
|
|
1177
|
-
export type
|
|
1177
|
+
export type SvmAllAccountLamportsFields = {
|
|
1178
|
+
readonly pre: bigint;
|
|
1179
|
+
readonly post: bigint;
|
|
1180
|
+
};
|
|
1181
|
+
|
|
1182
|
+
export type SvmAllAccountTokenActivityFields = {
|
|
1183
|
+
readonly mint: string;
|
|
1184
|
+
readonly owner: string;
|
|
1185
|
+
readonly decimals: number;
|
|
1186
|
+
readonly preAmount: bigint | undefined;
|
|
1187
|
+
readonly postAmount: bigint | undefined;
|
|
1188
|
+
};
|
|
1189
|
+
|
|
1190
|
+
export type SvmAllAccountActivityFields = {
|
|
1178
1191
|
readonly address: string;
|
|
1179
1192
|
readonly transactionAccountIndex: number;
|
|
1180
1193
|
readonly isSigner: boolean;
|
|
1181
1194
|
readonly isWritable: boolean;
|
|
1182
|
-
readonly lamports:
|
|
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;
|
|
1195
|
+
readonly lamports: SvmAllAccountLamportsFields | undefined;
|
|
1196
|
+
readonly token: SvmAllAccountTokenActivityFields | undefined;
|
|
1190
1197
|
};
|
|
1191
1198
|
|
|
1192
|
-
export type
|
|
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 = {
|
|
1199
|
+
export type SvmAllBlockFields = {
|
|
1203
1200
|
readonly slot: number;
|
|
1204
1201
|
readonly time: number;
|
|
1205
1202
|
readonly hash: string;
|
|
@@ -1208,10 +1205,10 @@ export type SvmBlock = {
|
|
|
1208
1205
|
readonly parentHash: string;
|
|
1209
1206
|
};
|
|
1210
1207
|
|
|
1211
|
-
/** All SVM parent-transaction fields
|
|
1212
|
-
*
|
|
1208
|
+
/** All SVM parent-transaction fields. Handler `fields.transaction` narrows
|
|
1209
|
+
* this via {@link SvmTransaction}; `accountActivities` is implied by
|
|
1213
1210
|
* `fields.accountActivity`. */
|
|
1214
|
-
export type
|
|
1211
|
+
export type SvmAllTransactionFields = {
|
|
1215
1212
|
readonly transactionIndex: number;
|
|
1216
1213
|
readonly signature: string;
|
|
1217
1214
|
readonly feePayer: string;
|
|
@@ -1250,10 +1247,8 @@ export type SvmAccountActivityFieldName =
|
|
|
1250
1247
|
| "transactionAccountIndex"
|
|
1251
1248
|
| "isSigner"
|
|
1252
1249
|
| "isWritable"
|
|
1253
|
-
| "lamports"
|
|
1254
1250
|
| "lamports.pre"
|
|
1255
1251
|
| "lamports.post"
|
|
1256
|
-
| "token"
|
|
1257
1252
|
| "token.mint"
|
|
1258
1253
|
| "token.owner"
|
|
1259
1254
|
| "token.decimals"
|
|
@@ -1276,6 +1271,19 @@ export type SvmFieldsSelection = {
|
|
|
1276
1271
|
readonly log?: readonly SvmLogFieldName[];
|
|
1277
1272
|
};
|
|
1278
1273
|
|
|
1274
|
+
/** A {@link SvmFieldsSelection} with every field selected.
|
|
1275
|
+
*
|
|
1276
|
+
* Type-level only — its knobs are field-name arrays rather than literals, so it
|
|
1277
|
+
* describes a payload (`SvmInstruction<SvmAllFieldsSelection>`) but can't be
|
|
1278
|
+
* passed as a registration's `fields` value. */
|
|
1279
|
+
export type SvmAllFieldsSelection = {
|
|
1280
|
+
readonly instruction: readonly SvmInstructionFieldName[];
|
|
1281
|
+
readonly transaction: readonly SvmTransactionFieldName[];
|
|
1282
|
+
readonly accountActivity: readonly SvmAccountActivityFieldName[];
|
|
1283
|
+
readonly block: readonly SvmBlockFieldName[];
|
|
1284
|
+
readonly log: readonly SvmLogFieldName[];
|
|
1285
|
+
};
|
|
1286
|
+
|
|
1279
1287
|
type SvmListedArray<Fields, Knob extends keyof SvmFieldsSelection> = Fields[Knob &
|
|
1280
1288
|
keyof Fields];
|
|
1281
1289
|
type SvmListedFields<Fields, Knob extends keyof SvmFieldsSelection> = NonNullable<
|
|
@@ -1302,15 +1310,7 @@ type SvmActivityHas<Fields, Name extends string> = [SvmActivityListed<Fields>] e
|
|
|
1302
1310
|
? false
|
|
1303
1311
|
: Name extends SvmActivityListed<Fields>
|
|
1304
1312
|
? true
|
|
1305
|
-
:
|
|
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;
|
|
1313
|
+
: false;
|
|
1314
1314
|
|
|
1315
1315
|
type SvmActivityField<Fields, Name extends string, T> = SvmActivityHas<
|
|
1316
1316
|
Fields,
|
|
@@ -1319,38 +1319,37 @@ type SvmActivityField<Fields, Name extends string, T> = SvmActivityHas<
|
|
|
1319
1319
|
? T
|
|
1320
1320
|
: FieldNotSelected<`Field '${Name}' is not selected for this handler. Add it to fields.accountActivity in the registration options.`>;
|
|
1321
1321
|
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
readonly owner: string;
|
|
1334
|
-
readonly decimals: number;
|
|
1335
|
-
readonly preAmount: bigint | undefined;
|
|
1336
|
-
readonly postAmount: bigint | undefined;
|
|
1337
|
-
};
|
|
1322
|
+
/** The pre/post lamport balances of a {@link SvmAccountActivity}, narrowed to
|
|
1323
|
+
* the registration's fields selection. */
|
|
1324
|
+
export type SvmAccountLamports<Fields extends SvmFieldsSelection> = [
|
|
1325
|
+
SvmActivityListed<Fields> & `lamports.${string}`,
|
|
1326
|
+
] extends [never]
|
|
1327
|
+
? FieldNotSelected<`Field 'lamports' is not selected for this handler. Add it to fields.accountActivity in the registration options.`>
|
|
1328
|
+
: {
|
|
1329
|
+
readonly [K in keyof SvmAllAccountLamportsFields]: SvmActivityHas<Fields, `lamports.${K & string}`> extends true
|
|
1330
|
+
? SvmAllAccountLamportsFields[K]
|
|
1331
|
+
: FieldNotSelected<`Field 'lamports.${K & string}' is not selected for this handler. Add it to fields.accountActivity in the registration options.`>;
|
|
1332
|
+
} | undefined;
|
|
1338
1333
|
|
|
1339
|
-
|
|
1334
|
+
/** The token activity of a {@link SvmAccountActivity}, narrowed to the
|
|
1335
|
+
* registration's fields selection. */
|
|
1336
|
+
export type SvmAccountTokenActivity<Fields extends SvmFieldsSelection> = [SvmActivityListed<Fields> & `token.${string}`] extends [never]
|
|
1340
1337
|
? FieldNotSelected<`Field 'token' is not selected for this handler. Add it to fields.accountActivity in the registration options.`>
|
|
1341
1338
|
: {
|
|
1342
|
-
readonly [K in keyof
|
|
1343
|
-
? K
|
|
1344
|
-
:
|
|
1339
|
+
readonly [K in keyof SvmAllAccountTokenActivityFields]: SvmActivityHas<Fields, `token.${K & string}`> extends true
|
|
1340
|
+
? SvmAllAccountTokenActivityFields[K]
|
|
1341
|
+
: FieldNotSelected<`Field 'token.${K & string}' is not selected for this handler. Add it to fields.accountActivity in the registration options.`>;
|
|
1345
1342
|
} | undefined;
|
|
1346
1343
|
|
|
1347
|
-
|
|
1344
|
+
/** An account activity of a {@link SvmTransaction}, narrowed to the
|
|
1345
|
+
* registration's fields selection. */
|
|
1346
|
+
export type SvmAccountActivity<Fields extends SvmFieldsSelection> = {
|
|
1348
1347
|
readonly address: string;
|
|
1349
1348
|
readonly transactionAccountIndex: SvmActivityField<Fields, "transactionAccountIndex", number>;
|
|
1350
1349
|
readonly isSigner: SvmActivityField<Fields, "isSigner", boolean>;
|
|
1351
1350
|
readonly isWritable: SvmActivityField<Fields, "isWritable", boolean>;
|
|
1352
|
-
readonly lamports:
|
|
1353
|
-
readonly token:
|
|
1351
|
+
readonly lamports: SvmAccountLamports<Fields>;
|
|
1352
|
+
readonly token: SvmAccountTokenActivity<Fields>;
|
|
1354
1353
|
};
|
|
1355
1354
|
|
|
1356
1355
|
type SvmInstrListed<Fields> = SvmListedFields<Fields, "instruction">;
|
|
@@ -1358,37 +1357,54 @@ type SvmInstrField<Fields, Name extends SvmInstructionFieldName, T> = Name exten
|
|
|
1358
1357
|
? T
|
|
1359
1358
|
: FieldNotSelected<`Field '${Name}' is not selected for this handler. Add it to fields.instruction in the registration options.`>;
|
|
1360
1359
|
|
|
1360
|
+
/** A named account of a {@link SvmInstruction}. Its `activity` narrows to the
|
|
1361
|
+
* registration's fields selection. */
|
|
1362
|
+
export type SvmInstructionAccount<
|
|
1363
|
+
Fields extends SvmFieldsSelection,
|
|
1364
|
+
Name extends string = string,
|
|
1365
|
+
> = {
|
|
1366
|
+
readonly address: string;
|
|
1367
|
+
readonly accountName: Name;
|
|
1368
|
+
readonly instructionAccountIndex: number;
|
|
1369
|
+
readonly activity:
|
|
1370
|
+
| ([SvmActivityListed<Fields>] extends [never]
|
|
1371
|
+
? FieldNotSelected<`Field 'activity' is not selected for this handler. Add fields.accountActivity in the registration options.`>
|
|
1372
|
+
: SvmAccountActivity<Fields>)
|
|
1373
|
+
| undefined;
|
|
1374
|
+
};
|
|
1375
|
+
|
|
1361
1376
|
type SvmNamedAccounts<
|
|
1362
1377
|
Acc extends Readonly<Record<string, unknown>>,
|
|
1363
|
-
Fields,
|
|
1378
|
+
Fields extends SvmFieldsSelection,
|
|
1364
1379
|
> = {
|
|
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
|
-
>;
|
|
1380
|
+
readonly [K in keyof Acc & string]: SvmInstructionAccount<Fields, K>;
|
|
1371
1381
|
};
|
|
1372
1382
|
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1383
|
+
/** The parent transaction of a {@link SvmInstruction}, narrowed to the
|
|
1384
|
+
* registration's fields selection. */
|
|
1385
|
+
export type SvmTransaction<Fields extends SvmFieldsSelection> = {
|
|
1386
|
+
readonly [K in keyof SvmAllTransactionFields]: K extends SvmListedFields<Fields, "transaction">
|
|
1387
|
+
? SvmAllTransactionFields[K]
|
|
1376
1388
|
: FieldNotSelected<`Field '${K & string}' is not selected for this handler. Add it to fields.transaction in the registration options.`>;
|
|
1377
1389
|
} & {
|
|
1378
1390
|
readonly accountActivities: [SvmActivityListed<Fields>] extends [never]
|
|
1379
1391
|
? FieldNotSelected<`Field 'accountActivities' is not selected for this handler. Add fields.accountActivity in the registration options.`>
|
|
1380
|
-
: readonly
|
|
1392
|
+
: readonly SvmAccountActivity<Fields>[];
|
|
1381
1393
|
};
|
|
1382
1394
|
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1395
|
+
/** The block of a {@link SvmInstruction}, narrowed to the registration's
|
|
1396
|
+
* fields selection. `slot` is always selected. */
|
|
1397
|
+
export type SvmBlock<Fields extends SvmFieldsSelection> = {
|
|
1398
|
+
readonly [K in keyof SvmAllBlockFields]: K extends "slot"
|
|
1399
|
+
? SvmAllBlockFields[K]
|
|
1386
1400
|
: K extends SvmListedFields<Fields, "block">
|
|
1387
|
-
?
|
|
1401
|
+
? SvmAllBlockFields[K]
|
|
1388
1402
|
: FieldNotSelected<`Field '${K & string}' is not selected for this handler. Add it to fields.block in the registration options.`>;
|
|
1389
1403
|
};
|
|
1390
1404
|
|
|
1391
|
-
|
|
1405
|
+
/** A log of a {@link SvmInstruction}, narrowed to the registration's fields
|
|
1406
|
+
* selection. */
|
|
1407
|
+
export type SvmLog<Fields extends SvmFieldsSelection> = {
|
|
1392
1408
|
readonly kind: "kind" extends SvmListedFields<Fields, "log">
|
|
1393
1409
|
? SvmLogKind
|
|
1394
1410
|
: FieldNotSelected<`Field 'kind' is not selected for this handler. Add it to fields.log in the registration options.`>;
|
|
@@ -1397,10 +1413,12 @@ type SvmSelectedLog<Fields> = {
|
|
|
1397
1413
|
: FieldNotSelected<`Field 'message' is not selected for this handler. Add it to fields.log in the registration options.`>;
|
|
1398
1414
|
};
|
|
1399
1415
|
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1416
|
+
type SvmAnyProgramInstruction = {
|
|
1417
|
+
readonly args: unknown;
|
|
1418
|
+
readonly accounts: Readonly<Record<string, string>>;
|
|
1419
|
+
};
|
|
1420
|
+
|
|
1421
|
+
type SvmSelectedInstruction<Fields extends SvmFieldsSelection, ProgInstr> = {
|
|
1404
1422
|
readonly programName: string;
|
|
1405
1423
|
readonly instructionName: string;
|
|
1406
1424
|
readonly discriminator: string;
|
|
@@ -1411,7 +1429,7 @@ export type SvmInstruction<
|
|
|
1411
1429
|
readonly args: SvmInstrField<
|
|
1412
1430
|
Fields,
|
|
1413
1431
|
"args",
|
|
1414
|
-
ProgInstr extends { readonly args: infer A } ? A
|
|
1432
|
+
ProgInstr extends { readonly args: infer A } ? A : unknown
|
|
1415
1433
|
>;
|
|
1416
1434
|
readonly accounts: SvmInstrField<
|
|
1417
1435
|
Fields,
|
|
@@ -1423,25 +1441,54 @@ export type SvmInstruction<
|
|
|
1423
1441
|
readonly accountArguments: SvmInstrField<Fields, "accountArguments", readonly string[]>;
|
|
1424
1442
|
readonly logs: [SvmListedFields<Fields, "log">] extends [never]
|
|
1425
1443
|
? FieldNotSelected<`Field 'logs' is not selected for this handler. Add fields.log in the registration options.`>
|
|
1426
|
-
: readonly
|
|
1427
|
-
readonly transaction:
|
|
1428
|
-
readonly block:
|
|
1429
|
-
};
|
|
1444
|
+
: readonly SvmLog<Fields>[];
|
|
1445
|
+
readonly transaction: SvmTransaction<Fields>;
|
|
1446
|
+
readonly block: SvmBlock<Fields>;
|
|
1447
|
+
};
|
|
1448
|
+
|
|
1449
|
+
type SvmConfiguredInstruction<Program extends string, Instruction extends string> = [
|
|
1450
|
+
Program,
|
|
1451
|
+
] extends [never]
|
|
1452
|
+
? SvmAnyProgramInstruction
|
|
1453
|
+
: Program extends keyof SvmProgramsT
|
|
1454
|
+
? Instruction extends keyof SvmProgramsT[Program]
|
|
1455
|
+
? SvmProgramsT[Program][Instruction]
|
|
1456
|
+
: SvmAnyProgramInstruction
|
|
1457
|
+
: SvmAnyProgramInstruction;
|
|
1458
|
+
|
|
1459
|
+
/** The `instruction` payload of an `indexer.onInstruction` handler. `Fields`
|
|
1460
|
+
* must be the registration's fields selection (use `typeof fields` on a
|
|
1461
|
+
* `const fields = {...} as const satisfies SvmFieldsSelection`, or
|
|
1462
|
+
* {@link SvmAllFieldsSelection}). Pass the config-declared program and
|
|
1463
|
+
* instruction names to type `args` and `accounts`. */
|
|
1464
|
+
export type SvmInstruction<
|
|
1465
|
+
Fields extends SvmFieldsSelection,
|
|
1466
|
+
Program extends keyof SvmProgramsT & string = never,
|
|
1467
|
+
Instruction extends keyof SvmProgramsT[Program] & string = never,
|
|
1468
|
+
> = SvmSelectedInstruction<Fields, SvmConfiguredInstruction<Program, Instruction>>;
|
|
1430
1469
|
|
|
1431
|
-
|
|
1432
|
-
export type SvmOnInstructionHandlerArgs<
|
|
1433
|
-
Config extends IndexerConfigTypes = GlobalConfig,
|
|
1434
|
-
Instr = SvmInstruction,
|
|
1435
|
-
> = {
|
|
1470
|
+
type SvmOnInstructionArgsFor<Instr, Config extends IndexerConfigTypes> = {
|
|
1436
1471
|
readonly instruction: Instr;
|
|
1437
1472
|
readonly context: SvmOnSlotContext<Config>;
|
|
1438
1473
|
};
|
|
1439
1474
|
|
|
1475
|
+
type SvmOnInstructionHandlerFor<Instr, Config extends IndexerConfigTypes> = (
|
|
1476
|
+
args: SvmOnInstructionArgsFor<Instr, Config>,
|
|
1477
|
+
) => Promise<void>;
|
|
1478
|
+
|
|
1479
|
+
/** Arguments passed to handlers registered via `indexer.onInstruction`.
|
|
1480
|
+
* Takes the same type arguments as {@link SvmInstruction}. */
|
|
1481
|
+
export type SvmOnInstructionHandlerArgs<
|
|
1482
|
+
Fields extends SvmFieldsSelection,
|
|
1483
|
+
Program extends keyof SvmProgramsT & string = never,
|
|
1484
|
+
Instruction extends keyof SvmProgramsT[Program] & string = never,
|
|
1485
|
+
> = SvmOnInstructionArgsFor<SvmInstruction<Fields, Program, Instruction>, GlobalConfig>;
|
|
1486
|
+
|
|
1440
1487
|
/** Options for an SVM `indexer.onInstruction` registration. */
|
|
1441
1488
|
export type SvmOnInstructionOptions<
|
|
1442
1489
|
P extends string = string,
|
|
1443
1490
|
I extends string = string,
|
|
1444
|
-
Fields extends SvmFieldsSelection
|
|
1491
|
+
Fields extends SvmFieldsSelection = {},
|
|
1445
1492
|
> = {
|
|
1446
1493
|
/** Program name as declared under `chains[].programs[].name` in
|
|
1447
1494
|
* `config.yaml`. */
|
|
@@ -1452,10 +1499,21 @@ export type SvmOnInstructionOptions<
|
|
|
1452
1499
|
readonly fields?: Fields & SvmFieldsLiteralCheck<Fields>;
|
|
1453
1500
|
};
|
|
1454
1501
|
|
|
1455
|
-
/** Handler function for an SVM `indexer.onInstruction` registration.
|
|
1502
|
+
/** Handler function for an SVM `indexer.onInstruction` registration. Takes
|
|
1503
|
+
* the same type arguments as {@link SvmInstruction}, so a standalone handler
|
|
1504
|
+
* needs a single annotation:
|
|
1505
|
+
*
|
|
1506
|
+
* const handleSwap: SvmOnInstructionHandler<typeof fields, "Swapper", "swap"> =
|
|
1507
|
+
* async ({ instruction, context }) => { ... };
|
|
1508
|
+
*/
|
|
1456
1509
|
export type SvmOnInstructionHandler<
|
|
1457
|
-
|
|
1458
|
-
|
|
1510
|
+
Fields extends SvmFieldsSelection,
|
|
1511
|
+
Program extends keyof SvmProgramsT & string = never,
|
|
1512
|
+
Instruction extends keyof SvmProgramsT[Program] & string = never,
|
|
1513
|
+
> = SvmOnInstructionHandlerFor<
|
|
1514
|
+
SvmInstruction<Fields, Program, Instruction>,
|
|
1515
|
+
GlobalConfig
|
|
1516
|
+
>;
|
|
1459
1517
|
|
|
1460
1518
|
// ============== Indexer Types ==============
|
|
1461
1519
|
|
|
@@ -1685,18 +1743,13 @@ type SvmEcosystem<Config extends IndexerConfigTypes = GlobalConfig> =
|
|
|
1685
1743
|
readonly onInstruction: <
|
|
1686
1744
|
P extends keyof Programs & string,
|
|
1687
1745
|
I extends keyof Programs[P] & string,
|
|
1688
|
-
const F extends SvmFieldsSelection
|
|
1746
|
+
const F extends SvmFieldsSelection = {},
|
|
1689
1747
|
>(
|
|
1690
1748
|
options: SvmOnInstructionOptions<P, I, F>,
|
|
1691
|
-
handler:
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
Programs[P][I],
|
|
1696
|
-
[F] extends [undefined] ? {} : F
|
|
1697
|
-
>
|
|
1698
|
-
>,
|
|
1699
|
-
) => Promise<void>,
|
|
1749
|
+
handler: SvmOnInstructionHandlerFor<
|
|
1750
|
+
SvmSelectedInstruction<F, Programs[P][I]>,
|
|
1751
|
+
Config
|
|
1752
|
+
>,
|
|
1700
1753
|
) => void;
|
|
1701
1754
|
}
|
|
1702
1755
|
: {
|
|
@@ -1867,9 +1920,9 @@ type SvmSimulateItem<Config extends IndexerConfigTypes = GlobalConfig> =
|
|
|
1867
1920
|
/** Logs scoped to this instruction. */
|
|
1868
1921
|
logs?: readonly { readonly kind?: string; readonly message?: string }[];
|
|
1869
1922
|
/** Override block fields. */
|
|
1870
|
-
block?: Partial<
|
|
1923
|
+
block?: Partial<SvmAllBlockFields>;
|
|
1871
1924
|
/** Override transaction fields. `accountActivities` are joined onto named accounts at process time. */
|
|
1872
|
-
transaction?: Partial<
|
|
1925
|
+
transaction?: Partial<SvmAllTransactionFields> & {
|
|
1873
1926
|
readonly accountActivities?: readonly {
|
|
1874
1927
|
readonly address: string;
|
|
1875
1928
|
readonly transactionAccountIndex?: number;
|
|
@@ -2138,6 +2191,7 @@ type EvmContractsT = GlobalConfig extends { evm: { contracts: infer X extends
|
|
|
2138
2191
|
type FuelChainsT = GlobalConfig extends { fuel: { chains: infer X extends Record<string, { id: number }> } } ? X : {};
|
|
2139
2192
|
type FuelContractsT = GlobalConfig extends { fuel: { contracts: infer X extends Record<string, Record<string, any>> } } ? X : {};
|
|
2140
2193
|
type SvmChainsT = GlobalConfig extends { svm: { chains: infer X extends Record<string, { id: number }> } } ? X : {};
|
|
2194
|
+
type SvmProgramsT = GlobalConfig extends { svm: { programs: infer X extends Record<string, Record<string, any>> } } ? X : {};
|
|
2141
2195
|
type EntitiesT = GlobalConfig extends { entities: infer X extends Record<string, object> } ? X : {};
|
|
2142
2196
|
type EnumsT = GlobalConfig extends { enums: infer X extends Record<string, any> } ? X : {};
|
|
2143
2197
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "envio",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.9.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.
|
|
73
|
-
"envio-linux-x64-musl": "3.
|
|
74
|
-
"envio-linux-arm64": "3.
|
|
75
|
-
"envio-darwin-x64": "3.
|
|
76
|
-
"envio-darwin-arm64": "3.
|
|
72
|
+
"envio-linux-x64": "3.9.0",
|
|
73
|
+
"envio-linux-x64-musl": "3.9.0",
|
|
74
|
+
"envio-linux-arm64": "3.9.0",
|
|
75
|
+
"envio-darwin-x64": "3.9.0",
|
|
76
|
+
"envio-darwin-arm64": "3.9.0"
|
|
77
77
|
}
|
|
78
78
|
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
type key = {
|
|
2
|
+
chainId: ChainId.t,
|
|
3
|
+
address: NodeJs.Buffer.t,
|
|
4
|
+
contractId: int,
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
type row = {
|
|
8
|
+
chainId: ChainId.t,
|
|
9
|
+
address: NodeJs.Buffer.t,
|
|
10
|
+
contractId: int,
|
|
11
|
+
registrationBlock: int,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type staged = {
|
|
15
|
+
row: row,
|
|
16
|
+
checkpointId: Internal.checkpointId,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type seedRows = {
|
|
20
|
+
addresses: array<NodeJs.Buffer.t>,
|
|
21
|
+
contractIds: array<int>,
|
|
22
|
+
registrationBlocks: array<int>,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let emptySeedRows = (): seedRows => {
|
|
26
|
+
addresses: [],
|
|
27
|
+
contractIds: [],
|
|
28
|
+
registrationBlocks: [],
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Config addresses are registered by no event. Rollback never reaches them.
|
|
32
|
+
let configRegistrationBlock = -1
|
|
33
|
+
|
|
34
|
+
let keyOf = (row: row): key => {
|
|
35
|
+
chainId: row.chainId,
|
|
36
|
+
address: row.address,
|
|
37
|
+
contractId: row.contractId,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let packBuffers = (addresses: array<NodeJs.Buffer.t>) => (
|
|
41
|
+
NodeJs.Buffer.concat(addresses),
|
|
42
|
+
addresses->Array.map(address => address->NodeJs.Buffer.length),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
let packKeys = (rows: array<row>) => packBuffers(rows->Array.map(row => row.address))
|
|
46
|
+
|
|
47
|
+
let seedRowsOf = (rows: array<row>): seedRows => {
|
|
48
|
+
let addresses = []
|
|
49
|
+
let contractIds = []
|
|
50
|
+
let registrationBlocks = []
|
|
51
|
+
rows->Array.forEach(row => {
|
|
52
|
+
addresses->Array.push(row.address)->ignore
|
|
53
|
+
contractIds->Array.push(row.contractId)->ignore
|
|
54
|
+
registrationBlocks->Array.push(row.registrationBlock)->ignore
|
|
55
|
+
})
|
|
56
|
+
{addresses, contractIds, registrationBlocks}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Rows arrive clustered per chain. Normalizing a chain id is a schema parse.
|
|
60
|
+
let group = (rows: array<row>): dict<seedRows> => {
|
|
61
|
+
let rowsByChain: dict<array<row>> = Dict.make()
|
|
62
|
+
let runChainId = ref(None)
|
|
63
|
+
let runKey = ref("")
|
|
64
|
+
rows->Array.forEach(row => {
|
|
65
|
+
if runChainId.contents !== Some(row.chainId) {
|
|
66
|
+
runChainId := Some(row.chainId)
|
|
67
|
+
runKey := row.chainId->ChainId.normalizeOrThrow->ChainId.toString
|
|
68
|
+
}
|
|
69
|
+
rowsByChain->Utils.Dict.push(runKey.contents, row)
|
|
70
|
+
})
|
|
71
|
+
rowsByChain->Utils.Dict.mapValues(seedRowsOf)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
module Table = {
|
|
75
|
+
type t = dict<row>
|
|
76
|
+
|
|
77
|
+
let dictKey = (key: key) =>
|
|
78
|
+
`${key.chainId->ChainId.toString}|${key.contractId->Int.toString}|${key.address->NodeJs.Buffer.toBase64}`
|
|
79
|
+
|
|
80
|
+
let make = (): t => Dict.make()
|
|
81
|
+
|
|
82
|
+
let clear = (table: t) => table->Utils.Dict.clearInPlace
|
|
83
|
+
|
|
84
|
+
let insert = (table: t, row: row) => {
|
|
85
|
+
let key = row->keyOf->dictKey
|
|
86
|
+
switch table->Utils.Dict.dangerouslyGetNonOption(key) {
|
|
87
|
+
| Some(_) => ()
|
|
88
|
+
| None => table->Dict.set(key, row)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
let insertMany = (table: t, rows: array<row>) => rows->Array.forEach(row => table->insert(row))
|
|
93
|
+
|
|
94
|
+
let delete = (table: t, key: key) => table->Utils.Dict.deleteInPlace(key->dictKey)
|
|
95
|
+
|
|
96
|
+
let rows = (table: t): array<row> => table->Dict.valuesToArray
|
|
97
|
+
|
|
98
|
+
let groupByChain = (table: t) => table->rows->group
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let render = (rows: array<row>, ~ecosystem: string, ~shouldChecksum: bool) => {
|
|
102
|
+
let (bytes, lengths) = rows->packKeys
|
|
103
|
+
Core.getAddon().renderAddresses(~ecosystem, ~shouldChecksum, ~bytes, ~lengths)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
let renderOfContract = (
|
|
107
|
+
rows: seedRows,
|
|
108
|
+
~ecosystem: string,
|
|
109
|
+
~shouldChecksum: bool,
|
|
110
|
+
~contractId: int,
|
|
111
|
+
) => {
|
|
112
|
+
let (bytes, lengths) = packBuffers(rows.addresses)
|
|
113
|
+
Core.getAddon().renderContractAddresses(
|
|
114
|
+
~ecosystem,
|
|
115
|
+
~shouldChecksum,
|
|
116
|
+
~bytes,
|
|
117
|
+
~lengths,
|
|
118
|
+
~contractIds=rows.contractIds,
|
|
119
|
+
~contractId,
|
|
120
|
+
)
|
|
121
|
+
}
|