envio 3.3.0-alpha.1 → 3.3.0-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/evm.schema.json +10 -0
- package/index.d.ts +45 -25
- package/licenses/CLA.md +35 -0
- package/licenses/EULA.md +67 -0
- package/licenses/LICENSE.md +45 -0
- package/licenses/README.md +35 -0
- package/package.json +10 -9
- package/src/Address.res +5 -2
- package/src/Address.res.mjs +3 -1
- package/src/Api.res +1 -1
- package/src/Api.res.mjs +1 -1
- package/src/Batch.res +0 -6
- package/src/Batch.res.mjs +1 -12
- package/src/BatchProcessing.res +7 -12
- package/src/BatchProcessing.res.mjs +8 -7
- package/src/Bin.res +3 -0
- package/src/Bin.res.mjs +4 -0
- package/src/ChainFetching.res +53 -16
- package/src/ChainFetching.res.mjs +37 -19
- package/src/ChainMetadata.res +1 -11
- package/src/ChainMetadata.res.mjs +1 -10
- package/src/ChainState.res +630 -161
- package/src/ChainState.res.mjs +438 -101
- package/src/ChainState.resi +77 -4
- package/src/Config.res +70 -38
- package/src/Config.res.mjs +52 -12
- package/src/ContractRegisterContext.res +2 -12
- package/src/ContractRegisterContext.res.mjs +3 -5
- package/src/Core.res +34 -3
- package/src/Core.res.mjs +12 -0
- package/src/CrossChainState.res +130 -89
- package/src/CrossChainState.res.mjs +66 -61
- package/src/CrossChainState.resi +1 -1
- package/src/Ecosystem.res +5 -6
- package/src/Ecosystem.res.mjs +3 -3
- package/src/Envio.res +17 -11
- package/src/EnvioGlobal.res +53 -0
- package/src/EnvioGlobal.res.mjs +31 -0
- package/src/EventConfigBuilder.res +191 -127
- package/src/EventConfigBuilder.res.mjs +116 -66
- package/src/EventProcessing.res +77 -28
- package/src/EventProcessing.res.mjs +56 -29
- package/src/ExitOnCaughtUp.res +10 -2
- package/src/ExitOnCaughtUp.res.mjs +10 -1
- package/src/FetchState.res +684 -415
- package/src/FetchState.res.mjs +505 -486
- package/src/HandlerLoader.res +8 -104
- package/src/HandlerLoader.res.mjs +2 -81
- package/src/HandlerRegister.res +520 -144
- package/src/HandlerRegister.res.mjs +286 -133
- package/src/HandlerRegister.resi +24 -8
- package/src/IndexerState.res +10 -3
- package/src/IndexerState.res.mjs +11 -4
- package/src/IndexerState.resi +2 -1
- package/src/IndexingAddresses.res +108 -0
- package/src/IndexingAddresses.res.mjs +101 -0
- package/src/IndexingAddresses.resi +34 -0
- package/src/Internal.res +166 -48
- package/src/Internal.res.mjs +30 -2
- package/src/LoadLayer.res +5 -5
- package/src/LoadLayer.res.mjs +6 -6
- package/src/LogSelection.res +92 -217
- package/src/LogSelection.res.mjs +95 -184
- package/src/Main.res +71 -236
- package/src/Main.res.mjs +60 -145
- package/src/Metrics.res +74 -0
- package/src/Metrics.res.mjs +75 -0
- package/src/PgStorage.res +4 -4
- package/src/PgStorage.res.mjs +5 -5
- package/src/Prometheus.res +10 -63
- package/src/Prometheus.res.mjs +124 -171
- package/src/PruneStaleHistory.res +2 -2
- package/src/PruneStaleHistory.res.mjs +3 -3
- package/src/RawEvent.res +7 -2
- package/src/RawEvent.res.mjs +4 -4
- package/src/Rollback.res +3 -3
- package/src/Rollback.res.mjs +4 -4
- package/src/RollbackCommit.res +4 -1
- package/src/RollbackCommit.res.mjs +3 -2
- package/src/SimulateDeadInputTracker.res +85 -0
- package/src/SimulateDeadInputTracker.res.mjs +73 -0
- package/src/SimulateDeadInputTracker.resi +12 -0
- package/src/SimulateItems.res +128 -28
- package/src/SimulateItems.res.mjs +82 -40
- package/src/TestIndexer.res +55 -41
- package/src/TestIndexer.res.mjs +39 -32
- package/src/TopicFilter.res +1 -25
- package/src/TopicFilter.res.mjs +0 -74
- package/src/bindings/Performance.res +7 -0
- package/src/bindings/Performance.res.mjs +21 -0
- package/src/bindings/Performance.resi +7 -0
- package/src/bindings/Viem.res +0 -46
- package/src/bindings/Viem.res.mjs +1 -43
- package/src/sources/BlockStore.res +46 -0
- package/src/sources/BlockStore.res.mjs +24 -0
- package/src/sources/EventRouter.res +31 -49
- package/src/sources/EventRouter.res.mjs +12 -25
- package/src/sources/Evm.res +83 -72
- package/src/sources/Evm.res.mjs +53 -69
- package/src/sources/EvmChain.res +7 -34
- package/src/sources/EvmChain.res.mjs +6 -27
- package/src/sources/EvmRpcClient.res +71 -5
- package/src/sources/EvmRpcClient.res.mjs +13 -4
- package/src/sources/FieldMask.res +39 -0
- package/src/sources/FieldMask.res.mjs +42 -0
- package/src/sources/Fuel.res +9 -6
- package/src/sources/Fuel.res.mjs +5 -10
- package/src/sources/HyperFuelSource.res +46 -50
- package/src/sources/HyperFuelSource.res.mjs +64 -54
- package/src/sources/HyperSync.res +45 -42
- package/src/sources/HyperSync.res.mjs +68 -60
- package/src/sources/HyperSync.resi +14 -4
- package/src/sources/HyperSyncClient.res +107 -119
- package/src/sources/HyperSyncClient.res.mjs +36 -31
- package/src/sources/HyperSyncHeightStream.res +1 -8
- package/src/sources/HyperSyncHeightStream.res.mjs +0 -2
- package/src/sources/HyperSyncSource.res +60 -254
- package/src/sources/HyperSyncSource.res.mjs +57 -180
- package/src/sources/Rpc.res +15 -79
- package/src/sources/Rpc.res.mjs +25 -101
- package/src/sources/RpcSource.res +221 -514
- package/src/sources/RpcSource.res.mjs +216 -411
- package/src/sources/RpcWebSocketHeightStream.res +0 -5
- package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -2
- package/src/sources/SimulateSource.res +44 -20
- package/src/sources/SimulateSource.res.mjs +41 -14
- package/src/sources/Source.res +34 -6
- package/src/sources/SourceManager.res +77 -19
- package/src/sources/SourceManager.res.mjs +63 -21
- package/src/sources/SourceManager.resi +10 -0
- package/src/sources/Svm.res +31 -16
- package/src/sources/Svm.res.mjs +36 -13
- package/src/sources/SvmHyperSyncClient.res +5 -32
- package/src/sources/SvmHyperSyncSource.res +159 -134
- package/src/sources/SvmHyperSyncSource.res.mjs +164 -129
- package/src/sources/TransactionStore.res +49 -0
- package/src/sources/TransactionStore.res.mjs +30 -0
- package/src/tui/Tui.res +13 -16
- package/src/tui/Tui.res.mjs +12 -14
- package/svm.schema.json +49 -37
- package/src/bindings/Hrtime.res +0 -58
- package/src/bindings/Hrtime.res.mjs +0 -90
- package/src/bindings/Hrtime.resi +0 -30
package/src/sources/Evm.res.mjs
CHANGED
|
@@ -1,8 +1,47 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Logging from "../Logging.res.mjs";
|
|
4
|
+
import * as Internal from "../Internal.res.mjs";
|
|
4
5
|
import * as RawEvent from "../RawEvent.res.mjs";
|
|
6
|
+
import * as BlockStore from "./BlockStore.res.mjs";
|
|
7
|
+
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
8
|
+
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
5
9
|
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
10
|
+
import * as TransactionStore from "./TransactionStore.res.mjs";
|
|
11
|
+
|
|
12
|
+
let eventTransactionFieldMask = TransactionStore.makeMaskFn(Internal.allEvmTransactionFields);
|
|
13
|
+
|
|
14
|
+
let blockFields = [
|
|
15
|
+
"number",
|
|
16
|
+
"timestamp",
|
|
17
|
+
"hash",
|
|
18
|
+
"parentHash",
|
|
19
|
+
"nonce",
|
|
20
|
+
"sha3Uncles",
|
|
21
|
+
"logsBloom",
|
|
22
|
+
"transactionsRoot",
|
|
23
|
+
"stateRoot",
|
|
24
|
+
"receiptsRoot",
|
|
25
|
+
"miner",
|
|
26
|
+
"difficulty",
|
|
27
|
+
"totalDifficulty",
|
|
28
|
+
"extraData",
|
|
29
|
+
"size",
|
|
30
|
+
"gasLimit",
|
|
31
|
+
"gasUsed",
|
|
32
|
+
"uncles",
|
|
33
|
+
"baseFeePerGas",
|
|
34
|
+
"blobGasUsed",
|
|
35
|
+
"excessBlobGas",
|
|
36
|
+
"parentBeaconBlockRoot",
|
|
37
|
+
"withdrawalsRoot",
|
|
38
|
+
"l1BlockNumber",
|
|
39
|
+
"sendCount",
|
|
40
|
+
"sendRoot",
|
|
41
|
+
"mixHash"
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
let eventBlockFieldMask = BlockStore.makeMaskFn(blockFields);
|
|
6
45
|
|
|
7
46
|
let cleanUpRawEventFieldsInPlace = (fields => {
|
|
8
47
|
delete fields.hash
|
|
@@ -13,82 +52,18 @@ let cleanUpRawEventFieldsInPlace = (fields => {
|
|
|
13
52
|
function make(logger) {
|
|
14
53
|
return {
|
|
15
54
|
name: "evm",
|
|
16
|
-
blockFields: [
|
|
17
|
-
"number",
|
|
18
|
-
"timestamp",
|
|
19
|
-
"hash",
|
|
20
|
-
"parentHash",
|
|
21
|
-
"nonce",
|
|
22
|
-
"sha3Uncles",
|
|
23
|
-
"logsBloom",
|
|
24
|
-
"transactionsRoot",
|
|
25
|
-
"stateRoot",
|
|
26
|
-
"receiptsRoot",
|
|
27
|
-
"miner",
|
|
28
|
-
"difficulty",
|
|
29
|
-
"totalDifficulty",
|
|
30
|
-
"extraData",
|
|
31
|
-
"size",
|
|
32
|
-
"gasLimit",
|
|
33
|
-
"gasUsed",
|
|
34
|
-
"uncles",
|
|
35
|
-
"baseFeePerGas",
|
|
36
|
-
"blobGasUsed",
|
|
37
|
-
"excessBlobGas",
|
|
38
|
-
"parentBeaconBlockRoot",
|
|
39
|
-
"withdrawalsRoot",
|
|
40
|
-
"l1BlockNumber",
|
|
41
|
-
"sendCount",
|
|
42
|
-
"sendRoot",
|
|
43
|
-
"mixHash"
|
|
44
|
-
],
|
|
45
|
-
transactionFields: [
|
|
46
|
-
"transactionIndex",
|
|
47
|
-
"hash",
|
|
48
|
-
"from",
|
|
49
|
-
"to",
|
|
50
|
-
"gas",
|
|
51
|
-
"gasPrice",
|
|
52
|
-
"maxPriorityFeePerGas",
|
|
53
|
-
"maxFeePerGas",
|
|
54
|
-
"cumulativeGasUsed",
|
|
55
|
-
"effectiveGasPrice",
|
|
56
|
-
"gasUsed",
|
|
57
|
-
"input",
|
|
58
|
-
"nonce",
|
|
59
|
-
"value",
|
|
60
|
-
"v",
|
|
61
|
-
"r",
|
|
62
|
-
"s",
|
|
63
|
-
"contractAddress",
|
|
64
|
-
"logsBloom",
|
|
65
|
-
"root",
|
|
66
|
-
"status",
|
|
67
|
-
"yParity",
|
|
68
|
-
"chainId",
|
|
69
|
-
"maxFeePerBlobGas",
|
|
70
|
-
"blobVersionedHashes",
|
|
71
|
-
"type",
|
|
72
|
-
"l1Fee",
|
|
73
|
-
"l1GasPrice",
|
|
74
|
-
"l1GasUsed",
|
|
75
|
-
"l1FeeScalar",
|
|
76
|
-
"gasUsedForL1",
|
|
77
|
-
"accessList",
|
|
78
|
-
"authorizationList"
|
|
79
|
-
],
|
|
80
55
|
blockNumberName: "number",
|
|
81
56
|
blockTimestampName: "timestamp",
|
|
82
57
|
blockHashName: "hash",
|
|
83
58
|
cleanUpRawEventFieldsInPlace: cleanUpRawEventFieldsInPlace,
|
|
84
59
|
onBlockMethodName: "onBlock",
|
|
85
60
|
onBlockFilterSchema: S$RescriptSchema.object(s => s.f("block", S$RescriptSchema.option(S$RescriptSchema.object(s2 => s2.f("number", S$RescriptSchema.unknown))))),
|
|
86
|
-
onEventBlockFilterSchema: S$RescriptSchema.object(s => s.f("block", S$RescriptSchema.option(S$RescriptSchema.object(s2 => s2.f("number", S$RescriptSchema.unknown))))),
|
|
61
|
+
onEventBlockFilterSchema: S$RescriptSchema.object(s => s.f("block", S$RescriptSchema.option(S$RescriptSchema.strict(S$RescriptSchema.object(s2 => s2.f("number", S$RescriptSchema.unknown)))))),
|
|
87
62
|
logger: logger,
|
|
88
63
|
toEvent: eventItem => eventItem.payload,
|
|
89
64
|
toEventLogger: eventItem => Logging.createChildFrom(logger, {
|
|
90
|
-
contract: eventItem.eventConfig.contractName,
|
|
91
|
-
event: eventItem.eventConfig.name,
|
|
65
|
+
contract: eventItem.onEventRegistration.eventConfig.contractName,
|
|
66
|
+
event: eventItem.onEventRegistration.eventConfig.name,
|
|
92
67
|
chainId: eventItem.chain,
|
|
93
68
|
block: eventItem.blockNumber,
|
|
94
69
|
logIndex: eventItem.logIndex,
|
|
@@ -96,13 +71,22 @@ function make(logger) {
|
|
|
96
71
|
}),
|
|
97
72
|
toRawEvent: eventItem => {
|
|
98
73
|
let payload = eventItem.payload;
|
|
99
|
-
|
|
74
|
+
let eventConfig = eventItem.onEventRegistration.eventConfig;
|
|
75
|
+
let block = payload.block;
|
|
76
|
+
let header = block !== undefined ? Primitive_option.valFromOption(block) : Stdlib_JsError.throwWithMessage("Unexpected case: The event block is missing for a raw event");
|
|
77
|
+
return RawEvent.make(eventItem, payload.block, payload.transaction, eventConfig.paramsMetadata.length === 0 ? undefined : payload.params, payload.srcAddress, header.hash, header.timestamp, cleanUpRawEventFieldsInPlace);
|
|
100
78
|
}
|
|
101
79
|
};
|
|
102
80
|
}
|
|
103
81
|
|
|
82
|
+
let transactionFields = Internal.allEvmTransactionFields;
|
|
83
|
+
|
|
104
84
|
export {
|
|
85
|
+
transactionFields,
|
|
86
|
+
eventTransactionFieldMask,
|
|
87
|
+
blockFields,
|
|
88
|
+
eventBlockFieldMask,
|
|
105
89
|
cleanUpRawEventFieldsInPlace,
|
|
106
90
|
make,
|
|
107
91
|
}
|
|
108
|
-
/*
|
|
92
|
+
/* eventTransactionFieldMask Not a pure module */
|
package/src/sources/EvmChain.res
CHANGED
|
@@ -3,6 +3,7 @@ type rpc = {
|
|
|
3
3
|
sourceFor: Source.sourceFor,
|
|
4
4
|
syncConfig?: Config.sourceSyncOptions,
|
|
5
5
|
ws?: string,
|
|
6
|
+
headers?: dict<string>,
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
let getSyncConfig = (
|
|
@@ -31,54 +32,26 @@ let getSyncConfig = (
|
|
|
31
32
|
intervalCeiling: Env.Configurable.SyncConfig.intervalCeiling->Option.getOr(
|
|
32
33
|
intervalCeiling->Option.getOr(10_000),
|
|
33
34
|
),
|
|
34
|
-
backoffMillis: backoffMillis->Option.getOr(
|
|
35
|
+
backoffMillis: backoffMillis->Option.getOr(2000),
|
|
35
36
|
queryTimeoutMillis,
|
|
36
37
|
fallbackStallTimeout: fallbackStallTimeout->Option.getOr(queryTimeoutMillis / 2),
|
|
37
38
|
pollingInterval: pollingInterval->Option.getOr(1000),
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
let collectEventParams = (contracts: array<Internal.evmContractConfig>): array<
|
|
42
|
-
HyperSyncClient.Decoder.eventParamsInput,
|
|
43
|
-
> => {
|
|
44
|
-
let result = []
|
|
45
|
-
contracts->Array.forEach(contract => {
|
|
46
|
-
contract.events->Array.forEach(event => {
|
|
47
|
-
result
|
|
48
|
-
->Array.push({
|
|
49
|
-
HyperSyncClient.Decoder.sighash: event.sighash,
|
|
50
|
-
topicCount: event.topicCount,
|
|
51
|
-
eventName: event.name,
|
|
52
|
-
contractName: contract.name,
|
|
53
|
-
params: event.paramsMetadata,
|
|
54
|
-
})
|
|
55
|
-
->ignore
|
|
56
|
-
})
|
|
57
|
-
})
|
|
58
|
-
result
|
|
59
|
-
}
|
|
60
|
-
|
|
61
42
|
let makeSources = (
|
|
62
43
|
~chain,
|
|
63
|
-
~
|
|
44
|
+
~onEventRegistrations: array<Internal.evmOnEventRegistration>,
|
|
64
45
|
~hyperSync,
|
|
65
46
|
~rpcs: array<rpc>,
|
|
66
47
|
~lowercaseAddresses,
|
|
67
48
|
) => {
|
|
68
|
-
let eventRouter =
|
|
69
|
-
contracts
|
|
70
|
-
->Array.flatMap(contract => contract.events)
|
|
71
|
-
->EventRouter.fromEvmEventModsOrThrow(~chain)
|
|
72
|
-
|
|
73
|
-
let allEventParams = collectEventParams(contracts)
|
|
74
|
-
|
|
75
49
|
let sources = switch hyperSync {
|
|
76
50
|
| Some(endpointUrl) => [
|
|
77
51
|
HyperSyncSource.make({
|
|
78
52
|
chain,
|
|
79
53
|
endpointUrl,
|
|
80
|
-
|
|
81
|
-
eventRouter,
|
|
54
|
+
onEventRegistrations,
|
|
82
55
|
apiToken: Env.envioApiToken,
|
|
83
56
|
clientTimeoutMillis: Env.hyperSyncClientTimeoutMillis,
|
|
84
57
|
lowercaseAddresses,
|
|
@@ -89,16 +62,16 @@ let makeSources = (
|
|
|
89
62
|
]
|
|
90
63
|
| _ => []
|
|
91
64
|
}
|
|
92
|
-
rpcs->Array.forEach(({?syncConfig, url, sourceFor, ?ws}) => {
|
|
65
|
+
rpcs->Array.forEach(({?syncConfig, url, sourceFor, ?ws, ?headers}) => {
|
|
93
66
|
let source = RpcSource.make({
|
|
94
67
|
chain,
|
|
95
68
|
sourceFor,
|
|
96
69
|
syncConfig: getSyncConfig(syncConfig->Option.getOr({})),
|
|
97
70
|
url,
|
|
98
|
-
|
|
99
|
-
allEventParams,
|
|
71
|
+
onEventRegistrations,
|
|
100
72
|
lowercaseAddresses,
|
|
101
73
|
?ws,
|
|
74
|
+
?headers,
|
|
102
75
|
})
|
|
103
76
|
let _ = sources->Array.push(source)
|
|
104
77
|
})
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import * as Env from "../Env.res.mjs";
|
|
4
4
|
import * as RpcSource from "./RpcSource.res.mjs";
|
|
5
|
-
import * as EventRouter from "./EventRouter.res.mjs";
|
|
6
5
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
7
6
|
import * as HyperSyncSource from "./HyperSyncSource.res.mjs";
|
|
8
7
|
|
|
@@ -13,37 +12,18 @@ function getSyncConfig(param) {
|
|
|
13
12
|
backoffMultiplicative: Stdlib_Option.getOr(Env.Configurable.SyncConfig.backoffMultiplicative, Stdlib_Option.getOr(param.backoffMultiplicative, 0.8)),
|
|
14
13
|
accelerationAdditive: Stdlib_Option.getOr(Env.Configurable.SyncConfig.accelerationAdditive, Stdlib_Option.getOr(param.accelerationAdditive, 500)),
|
|
15
14
|
intervalCeiling: Stdlib_Option.getOr(Env.Configurable.SyncConfig.intervalCeiling, Stdlib_Option.getOr(param.intervalCeiling, 10000)),
|
|
16
|
-
backoffMillis: Stdlib_Option.getOr(param.backoffMillis,
|
|
15
|
+
backoffMillis: Stdlib_Option.getOr(param.backoffMillis, 2000),
|
|
17
16
|
queryTimeoutMillis: queryTimeoutMillis,
|
|
18
17
|
fallbackStallTimeout: Stdlib_Option.getOr(param.fallbackStallTimeout, queryTimeoutMillis / 2 | 0),
|
|
19
18
|
pollingInterval: Stdlib_Option.getOr(param.pollingInterval, 1000)
|
|
20
19
|
};
|
|
21
20
|
}
|
|
22
21
|
|
|
23
|
-
function
|
|
24
|
-
let result = [];
|
|
25
|
-
contracts.forEach(contract => {
|
|
26
|
-
contract.events.forEach(event => {
|
|
27
|
-
result.push({
|
|
28
|
-
sighash: event.sighash,
|
|
29
|
-
topicCount: event.topicCount,
|
|
30
|
-
eventName: event.name,
|
|
31
|
-
contractName: contract.name,
|
|
32
|
-
params: event.paramsMetadata
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
return result;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function makeSources(chain, contracts, hyperSync, rpcs, lowercaseAddresses) {
|
|
40
|
-
let eventRouter = EventRouter.fromEvmEventModsOrThrow(contracts.flatMap(contract => contract.events), chain);
|
|
41
|
-
let allEventParams = collectEventParams(contracts);
|
|
22
|
+
function makeSources(chain, onEventRegistrations, hyperSync, rpcs, lowercaseAddresses) {
|
|
42
23
|
let sources = hyperSync !== undefined ? [HyperSyncSource.make({
|
|
43
24
|
chain: chain,
|
|
44
25
|
endpointUrl: hyperSync,
|
|
45
|
-
|
|
46
|
-
eventRouter: eventRouter,
|
|
26
|
+
onEventRegistrations: onEventRegistrations,
|
|
47
27
|
apiToken: Env.envioApiToken,
|
|
48
28
|
clientTimeoutMillis: Env.hyperSyncClientTimeoutMillis,
|
|
49
29
|
lowercaseAddresses: lowercaseAddresses,
|
|
@@ -57,10 +37,10 @@ function makeSources(chain, contracts, hyperSync, rpcs, lowercaseAddresses) {
|
|
|
57
37
|
syncConfig: getSyncConfig(Stdlib_Option.getOr(param.syncConfig, {})),
|
|
58
38
|
url: param.url,
|
|
59
39
|
chain: chain,
|
|
60
|
-
|
|
61
|
-
allEventParams: allEventParams,
|
|
40
|
+
onEventRegistrations: onEventRegistrations,
|
|
62
41
|
lowercaseAddresses: lowercaseAddresses,
|
|
63
|
-
ws: param.ws
|
|
42
|
+
ws: param.ws,
|
|
43
|
+
headers: param.headers
|
|
64
44
|
});
|
|
65
45
|
sources.push(source);
|
|
66
46
|
});
|
|
@@ -69,7 +49,6 @@ function makeSources(chain, contracts, hyperSync, rpcs, lowercaseAddresses) {
|
|
|
69
49
|
|
|
70
50
|
export {
|
|
71
51
|
getSyncConfig,
|
|
72
|
-
collectEventParams,
|
|
73
52
|
makeSources,
|
|
74
53
|
}
|
|
75
54
|
/* Env Not a pure module */
|
|
@@ -1,9 +1,53 @@
|
|
|
1
|
-
type cfg = {
|
|
1
|
+
type cfg = {
|
|
2
|
+
url: string,
|
|
3
|
+
httpReqTimeoutMillis?: int,
|
|
4
|
+
headers?: dict<string>,
|
|
5
|
+
initialBlockInterval: int,
|
|
6
|
+
backoffMultiplicative: float,
|
|
7
|
+
accelerationAdditive: int,
|
|
8
|
+
intervalCeiling: int,
|
|
9
|
+
backoffMillis: int,
|
|
10
|
+
queryTimeoutMillis: int,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Only logs that resolved to a registration cross the boundary, each carrying
|
|
14
|
+
// its registration's chain-scoped index.
|
|
15
|
+
type rpcEventItem = {
|
|
16
|
+
log: Rpc.GetLogs.log,
|
|
17
|
+
onEventRegistrationIndex: int,
|
|
18
|
+
params: Internal.eventParams,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type nextPageParams = {
|
|
22
|
+
fromBlock: int,
|
|
23
|
+
toBlockCeiling: int,
|
|
24
|
+
partitionId: string,
|
|
25
|
+
// The partition's registration selection, by chain-scoped index. Log
|
|
26
|
+
// selections and the routing index are derived on the Rust side from the
|
|
27
|
+
// registrations passed at construction.
|
|
28
|
+
registrationIndexes: array<int>,
|
|
29
|
+
addressesByContractName: dict<array<Address.t>>,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type nextPageResponse = {
|
|
33
|
+
items: array<rpcEventItem>,
|
|
34
|
+
toBlock: int,
|
|
35
|
+
requestStats: array<Source.requestStat>,
|
|
36
|
+
}
|
|
2
37
|
|
|
3
|
-
|
|
38
|
+
// The caller provides a range; Rust decides the actual `toBlock` and returns it.
|
|
39
|
+
type t = {
|
|
40
|
+
getHeight: unit => promise<int>,
|
|
41
|
+
getNextPage: nextPageParams => promise<nextPageResponse>,
|
|
42
|
+
}
|
|
4
43
|
|
|
5
44
|
@send
|
|
6
|
-
external classNew: (
|
|
45
|
+
external classNew: (
|
|
46
|
+
Core.evmRpcClientCtor,
|
|
47
|
+
cfg,
|
|
48
|
+
array<HyperSyncClient.Registration.input>,
|
|
49
|
+
~checksumAddresses: bool,
|
|
50
|
+
) => t = "new"
|
|
7
51
|
|
|
8
52
|
// Rust encodes JSON-RPC errors as a JSON payload in the napi error's
|
|
9
53
|
// message: `{"kind":"JsonRpcError","code":-32005,"message":"..."}`.
|
|
@@ -34,9 +78,31 @@ let coerceErrorOrThrow = exn =>
|
|
|
34
78
|
| None => exn->throw
|
|
35
79
|
}
|
|
36
80
|
|
|
37
|
-
let make = (
|
|
38
|
-
|
|
81
|
+
let make = (
|
|
82
|
+
~url,
|
|
83
|
+
~checksumAddresses,
|
|
84
|
+
~syncConfig: Config.sourceSync,
|
|
85
|
+
~httpReqTimeoutMillis=?,
|
|
86
|
+
~headers=?,
|
|
87
|
+
~eventRegistrations=[],
|
|
88
|
+
) => {
|
|
89
|
+
let client = Core.getAddon().evmRpcClient->classNew(
|
|
90
|
+
{
|
|
91
|
+
url,
|
|
92
|
+
?httpReqTimeoutMillis,
|
|
93
|
+
?headers,
|
|
94
|
+
initialBlockInterval: syncConfig.initialBlockInterval,
|
|
95
|
+
backoffMultiplicative: syncConfig.backoffMultiplicative,
|
|
96
|
+
accelerationAdditive: syncConfig.accelerationAdditive,
|
|
97
|
+
intervalCeiling: syncConfig.intervalCeiling,
|
|
98
|
+
backoffMillis: syncConfig.backoffMillis,
|
|
99
|
+
queryTimeoutMillis: syncConfig.queryTimeoutMillis,
|
|
100
|
+
},
|
|
101
|
+
eventRegistrations,
|
|
102
|
+
~checksumAddresses,
|
|
103
|
+
)
|
|
39
104
|
{
|
|
40
105
|
getHeight: () => client.getHeight()->Promise.catch(coerceErrorOrThrow),
|
|
106
|
+
getNextPage: params => client.getNextPage(params)->Promise.catch(coerceErrorOrThrow),
|
|
41
107
|
}
|
|
42
108
|
}
|
|
@@ -46,13 +46,22 @@ function coerceErrorOrThrow(exn) {
|
|
|
46
46
|
throw exn;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
function make(url, httpReqTimeoutMillis) {
|
|
49
|
+
function make(url, checksumAddresses, syncConfig, httpReqTimeoutMillis, headers, eventRegistrationsOpt) {
|
|
50
|
+
let eventRegistrations = eventRegistrationsOpt !== undefined ? eventRegistrationsOpt : [];
|
|
50
51
|
let client = Core.getAddon().EvmRpcClient.new({
|
|
51
52
|
url: url,
|
|
52
|
-
httpReqTimeoutMillis: httpReqTimeoutMillis
|
|
53
|
-
|
|
53
|
+
httpReqTimeoutMillis: httpReqTimeoutMillis,
|
|
54
|
+
headers: headers,
|
|
55
|
+
initialBlockInterval: syncConfig.initialBlockInterval,
|
|
56
|
+
backoffMultiplicative: syncConfig.backoffMultiplicative,
|
|
57
|
+
accelerationAdditive: syncConfig.accelerationAdditive,
|
|
58
|
+
intervalCeiling: syncConfig.intervalCeiling,
|
|
59
|
+
backoffMillis: syncConfig.backoffMillis,
|
|
60
|
+
queryTimeoutMillis: syncConfig.queryTimeoutMillis
|
|
61
|
+
}, eventRegistrations, checksumAddresses);
|
|
54
62
|
return {
|
|
55
|
-
getHeight: () => Stdlib_Promise.$$catch(client.getHeight(), coerceErrorOrThrow)
|
|
63
|
+
getHeight: () => Stdlib_Promise.$$catch(client.getHeight(), coerceErrorOrThrow),
|
|
64
|
+
getNextPage: params => Stdlib_Promise.$$catch(client.getNextPage(params), coerceErrorOrThrow)
|
|
56
65
|
};
|
|
57
66
|
}
|
|
58
67
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Selection-bitmask helpers shared by the per-chain field stores
|
|
2
|
+
// (`TransactionStore`, `BlockStore`). A field's bit index is its position in the
|
|
3
|
+
// ecosystem's ordered field-name array — the same code the Rust store uses.
|
|
4
|
+
|
|
5
|
+
// Field-name → bit-index map from an ordered field-name array.
|
|
6
|
+
let fieldCodes = (fields: array<string>): dict<int> => {
|
|
7
|
+
let codes = Dict.make()
|
|
8
|
+
fields->Array.forEachWithIndex((name, i) => codes->Dict.set(name, i))
|
|
9
|
+
codes
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let pow2: int => float = %raw(`c => Math.pow(2, c)`)
|
|
13
|
+
|
|
14
|
+
// One event's selected fields as a bitmask float (bit `code` set ⇔ selected).
|
|
15
|
+
// Each field appears once, so summing `pow2(code)` sets distinct bits with no
|
|
16
|
+
// overlap; the result stays exact in f64 (codes span 0..31, so a mask is at most
|
|
17
|
+
// 2^32-1).
|
|
18
|
+
let maskFromFields = (selectedFields: Utils.Set.t<string>, ~codes: dict<int>): float => {
|
|
19
|
+
let mask = ref(0.)
|
|
20
|
+
selectedFields->Utils.Set.forEach(name =>
|
|
21
|
+
switch codes->Utils.Dict.dangerouslyGetNonOption(name) {
|
|
22
|
+
| Some(code) => mask := mask.contents +. pow2(code)
|
|
23
|
+
| None => ()
|
|
24
|
+
}
|
|
25
|
+
)
|
|
26
|
+
mask.contents
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Build an ecosystem's per-event mask function from its ordered field-name
|
|
30
|
+
// array. The field codes are derived once and closed over.
|
|
31
|
+
let makeMaskFn = (fields: array<string>): (Utils.Set.t<string> => float) => {
|
|
32
|
+
let codes = fieldCodes(fields)
|
|
33
|
+
selectedFields => selectedFields->maskFromFields(~codes)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Bitwise OR of two per-event masks. Masks fit in 32 bits (≤32 fields), so
|
|
37
|
+
// `>>> 0` recovers the unsigned value that a plain `|` renders negative once bit
|
|
38
|
+
// 31 is set.
|
|
39
|
+
let orMask: (float, float) => float = %raw(`(a, b) => (a | b) >>> 0`)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
function fieldCodes(fields) {
|
|
5
|
+
let codes = {};
|
|
6
|
+
fields.forEach((name, i) => {
|
|
7
|
+
codes[name] = i;
|
|
8
|
+
});
|
|
9
|
+
return codes;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let pow2 = (c => Math.pow(2, c));
|
|
13
|
+
|
|
14
|
+
function maskFromFields(selectedFields, codes) {
|
|
15
|
+
let mask = {
|
|
16
|
+
contents: 0
|
|
17
|
+
};
|
|
18
|
+
selectedFields.forEach(name => {
|
|
19
|
+
let code = codes[name];
|
|
20
|
+
if (code !== undefined) {
|
|
21
|
+
mask.contents = mask.contents + pow2(code);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return mask.contents;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function makeMaskFn(fields) {
|
|
29
|
+
let codes = fieldCodes(fields);
|
|
30
|
+
return selectedFields => maskFromFields(selectedFields, codes);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let orMask = ((a, b) => (a | b) >>> 0);
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
fieldCodes,
|
|
37
|
+
pow2,
|
|
38
|
+
maskFromFields,
|
|
39
|
+
makeMaskFn,
|
|
40
|
+
orMask,
|
|
41
|
+
}
|
|
42
|
+
/* No side effect */
|
package/src/sources/Fuel.res
CHANGED
|
@@ -21,8 +21,6 @@ let cleanUpRawEventFieldsInPlace: JSON.t => unit = %raw(`fields => {
|
|
|
21
21
|
|
|
22
22
|
let make = (~logger: Pino.t): Ecosystem.t => {
|
|
23
23
|
name: Fuel,
|
|
24
|
-
blockFields: ["id", "height", "time"],
|
|
25
|
-
transactionFields: ["id"],
|
|
26
24
|
blockNumberName: "height",
|
|
27
25
|
blockTimestampName: "time",
|
|
28
26
|
blockHashName: "id",
|
|
@@ -37,17 +35,19 @@ let make = (~logger: Pino.t): Ecosystem.t => {
|
|
|
37
35
|
// Analogous to EVM, but keyed by `block.height` instead of
|
|
38
36
|
// `block.number`. See `Evm.res` for the rationale on the two-stage
|
|
39
37
|
// parse and the `_lte`/`_every` rejection.
|
|
38
|
+
// `S.strict` on the inner object rejects unknown `block` fields — including
|
|
39
|
+
// `block.number`, which is EVM-only; Fuel filters by `block.height`.
|
|
40
40
|
onEventBlockFilterSchema: S.object(s =>
|
|
41
|
-
s.field("block", S.option(S.object(s2 => s2.field("height", S.unknown))))
|
|
41
|
+
s.field("block", S.option(S.object(s2 => s2.field("height", S.unknown))->S.strict))
|
|
42
42
|
),
|
|
43
43
|
logger,
|
|
44
|
-
toEvent: eventItem => eventItem.payload->Internal.
|
|
44
|
+
toEvent: eventItem => eventItem.payload->(Utils.magic: Internal.eventPayload => Internal.event),
|
|
45
45
|
toEventLogger: eventItem =>
|
|
46
46
|
Logging.createChildFrom(
|
|
47
47
|
~logger,
|
|
48
48
|
~params={
|
|
49
|
-
"contract": eventItem.eventConfig.contractName,
|
|
50
|
-
"event": eventItem.eventConfig.name,
|
|
49
|
+
"contract": eventItem.onEventRegistration.eventConfig.contractName,
|
|
50
|
+
"event": eventItem.onEventRegistration.eventConfig.name,
|
|
51
51
|
"chainId": eventItem.chain->ChainMap.Chain.toChainId,
|
|
52
52
|
"block": eventItem.blockNumber,
|
|
53
53
|
"logIndex": eventItem.logIndex,
|
|
@@ -56,11 +56,14 @@ let make = (~logger: Pino.t): Ecosystem.t => {
|
|
|
56
56
|
),
|
|
57
57
|
toRawEvent: eventItem => {
|
|
58
58
|
let payload = eventItem.payload->toPayload
|
|
59
|
+
let header = payload.block->(Utils.magic: Internal.eventBlock => {"id": string, "time": int})
|
|
59
60
|
eventItem->RawEvent.make(
|
|
60
61
|
~block=payload.block,
|
|
61
62
|
~transaction=payload.transaction,
|
|
62
63
|
~params=payload.params,
|
|
63
64
|
~srcAddress=payload.srcAddress,
|
|
65
|
+
~blockHash=header["id"],
|
|
66
|
+
~blockTimestamp=header["time"],
|
|
64
67
|
~cleanUpRawEventFieldsInPlace,
|
|
65
68
|
)
|
|
66
69
|
},
|
package/src/sources/Fuel.res.mjs
CHANGED
|
@@ -13,24 +13,18 @@ let cleanUpRawEventFieldsInPlace = (fields => {
|
|
|
13
13
|
function make(logger) {
|
|
14
14
|
return {
|
|
15
15
|
name: "fuel",
|
|
16
|
-
blockFields: [
|
|
17
|
-
"id",
|
|
18
|
-
"height",
|
|
19
|
-
"time"
|
|
20
|
-
],
|
|
21
|
-
transactionFields: ["id"],
|
|
22
16
|
blockNumberName: "height",
|
|
23
17
|
blockTimestampName: "time",
|
|
24
18
|
blockHashName: "id",
|
|
25
19
|
cleanUpRawEventFieldsInPlace: cleanUpRawEventFieldsInPlace,
|
|
26
20
|
onBlockMethodName: "onBlock",
|
|
27
21
|
onBlockFilterSchema: S$RescriptSchema.object(s => s.f("block", S$RescriptSchema.option(S$RescriptSchema.object(s2 => s2.f("height", S$RescriptSchema.unknown))))),
|
|
28
|
-
onEventBlockFilterSchema: S$RescriptSchema.object(s => s.f("block", S$RescriptSchema.option(S$RescriptSchema.object(s2 => s2.f("height", S$RescriptSchema.unknown))))),
|
|
22
|
+
onEventBlockFilterSchema: S$RescriptSchema.object(s => s.f("block", S$RescriptSchema.option(S$RescriptSchema.strict(S$RescriptSchema.object(s2 => s2.f("height", S$RescriptSchema.unknown)))))),
|
|
29
23
|
logger: logger,
|
|
30
24
|
toEvent: eventItem => eventItem.payload,
|
|
31
25
|
toEventLogger: eventItem => Logging.createChildFrom(logger, {
|
|
32
|
-
contract: eventItem.eventConfig.contractName,
|
|
33
|
-
event: eventItem.eventConfig.name,
|
|
26
|
+
contract: eventItem.onEventRegistration.eventConfig.contractName,
|
|
27
|
+
event: eventItem.onEventRegistration.eventConfig.name,
|
|
34
28
|
chainId: eventItem.chain,
|
|
35
29
|
block: eventItem.blockNumber,
|
|
36
30
|
logIndex: eventItem.logIndex,
|
|
@@ -38,7 +32,8 @@ function make(logger) {
|
|
|
38
32
|
}),
|
|
39
33
|
toRawEvent: eventItem => {
|
|
40
34
|
let payload = eventItem.payload;
|
|
41
|
-
|
|
35
|
+
let header = payload.block;
|
|
36
|
+
return RawEvent.make(eventItem, payload.block, payload.transaction, payload.params, payload.srcAddress, header.id, header.time, cleanUpRawEventFieldsInPlace);
|
|
42
37
|
}
|
|
43
38
|
};
|
|
44
39
|
}
|