envio 3.3.0-alpha.10 → 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/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 +9 -8
- package/src/Batch.res.mjs +1 -1
- package/src/ChainFetching.res +13 -10
- package/src/ChainFetching.res.mjs +3 -4
- package/src/ChainState.res +45 -30
- package/src/ChainState.res.mjs +22 -8
- package/src/ChainState.resi +5 -0
- package/src/Config.res +9 -5
- package/src/Config.res.mjs +2 -2
- package/src/Core.res +20 -0
- package/src/Core.res.mjs +12 -0
- package/src/CrossChainState.res +18 -1
- package/src/CrossChainState.res.mjs +2 -1
- package/src/EventConfigBuilder.res +21 -46
- package/src/EventConfigBuilder.res.mjs +18 -25
- package/src/EventProcessing.res +8 -5
- package/src/EventProcessing.res.mjs +2 -1
- package/src/FetchState.res +344 -263
- package/src/FetchState.res.mjs +209 -131
- package/src/HandlerRegister.res +3 -1
- package/src/HandlerRegister.res.mjs +3 -2
- package/src/Internal.res +11 -2
- package/src/LogSelection.res +0 -62
- package/src/LogSelection.res.mjs +0 -74
- package/src/RawEvent.res +2 -2
- package/src/SimulateDeadInputTracker.res +1 -1
- package/src/SimulateItems.res +38 -6
- package/src/SimulateItems.res.mjs +28 -9
- package/src/TestIndexer.res +2 -2
- package/src/TestIndexer.res.mjs +2 -2
- package/src/TopicFilter.res +1 -25
- package/src/TopicFilter.res.mjs +0 -74
- package/src/bindings/Viem.res +0 -5
- package/src/sources/EventRouter.res +0 -21
- package/src/sources/EventRouter.res.mjs +0 -12
- package/src/sources/EvmChain.res +2 -27
- package/src/sources/EvmChain.res.mjs +2 -23
- package/src/sources/EvmRpcClient.res +12 -15
- package/src/sources/EvmRpcClient.res.mjs +3 -3
- package/src/sources/HyperSync.res +9 -38
- package/src/sources/HyperSync.res.mjs +16 -28
- package/src/sources/HyperSync.resi +2 -2
- package/src/sources/HyperSyncClient.res +88 -11
- package/src/sources/HyperSyncClient.res.mjs +39 -6
- package/src/sources/HyperSyncSource.res +18 -199
- package/src/sources/HyperSyncSource.res.mjs +9 -128
- package/src/sources/Rpc.res +0 -32
- package/src/sources/Rpc.res.mjs +1 -46
- package/src/sources/RpcSource.res +29 -175
- package/src/sources/RpcSource.res.mjs +32 -110
- package/src/sources/SimulateSource.res +37 -19
- package/src/sources/SimulateSource.res.mjs +27 -10
- package/src/sources/SvmHyperSyncSource.res +3 -3
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
-
import * as Utils from "../Utils.res.mjs";
|
|
4
3
|
import * as Source from "./Source.res.mjs";
|
|
5
4
|
import * as Logging from "../Logging.res.mjs";
|
|
6
5
|
import * as HyperSync from "./HyperSync.res.mjs";
|
|
7
|
-
import * as EventRouter from "./EventRouter.res.mjs";
|
|
8
6
|
import * as Performance from "../bindings/Performance.res.mjs";
|
|
9
|
-
import * as LogSelection from "../LogSelection.res.mjs";
|
|
10
7
|
import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
|
|
11
8
|
import * as ErrorHandling from "../ErrorHandling.res.mjs";
|
|
12
9
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
@@ -16,109 +13,27 @@ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js
|
|
|
16
13
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
17
14
|
import * as HyperSyncHeightStream from "./HyperSyncHeightStream.res.mjs";
|
|
18
15
|
|
|
19
|
-
function getSelectionConfig(selection) {
|
|
20
|
-
let capitalizedBlockFields = new Set();
|
|
21
|
-
let capitalizedTransactionFields = new Set();
|
|
22
|
-
let topicSelectionsByContract = {};
|
|
23
|
-
let wildcardTopicSelectionsByContract = {};
|
|
24
|
-
let noAddressesTopicSelections = [];
|
|
25
|
-
let contractNames = new Set();
|
|
26
|
-
selection.onEventRegistrations.forEach(reg => {
|
|
27
|
-
let eventConfig = reg.eventConfig;
|
|
28
|
-
let contractName = eventConfig.contractName;
|
|
29
|
-
let resolvedWhere = reg.resolvedWhere;
|
|
30
|
-
Array.from(eventConfig.selectedBlockFields).forEach(name => {
|
|
31
|
-
capitalizedBlockFields.add(Utils.$$String.capitalize(name));
|
|
32
|
-
});
|
|
33
|
-
Array.from(eventConfig.selectedTransactionFields).forEach(name => {
|
|
34
|
-
if (name !== "transactionIndex") {
|
|
35
|
-
capitalizedTransactionFields.add(Utils.$$String.capitalize(name));
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
if (reg.dependsOnAddresses) {
|
|
40
|
-
contractNames.add(contractName);
|
|
41
|
-
return Utils.Dict.pushMany(reg.isWildcard ? wildcardTopicSelectionsByContract : topicSelectionsByContract, contractName, resolvedWhere.topicSelections);
|
|
42
|
-
} else {
|
|
43
|
-
noAddressesTopicSelections.push(...LogSelection.materializeTopicSelections(resolvedWhere.topicSelections, []));
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
let fieldSelection_block = Array.from(capitalizedBlockFields);
|
|
48
|
-
let fieldSelection_transaction = Array.from(capitalizedTransactionFields);
|
|
49
|
-
let fieldSelection_log = [
|
|
50
|
-
"Address",
|
|
51
|
-
"Data",
|
|
52
|
-
"LogIndex",
|
|
53
|
-
"Topic0",
|
|
54
|
-
"Topic1",
|
|
55
|
-
"Topic2",
|
|
56
|
-
"Topic3"
|
|
57
|
-
];
|
|
58
|
-
let fieldSelection = {
|
|
59
|
-
block: fieldSelection_block,
|
|
60
|
-
transaction: fieldSelection_transaction,
|
|
61
|
-
log: fieldSelection_log
|
|
62
|
-
};
|
|
63
|
-
let noAddressesLogSelection = LogSelection.make([], noAddressesTopicSelections);
|
|
64
|
-
let getLogSelectionOrThrow = addressesByContractName => {
|
|
65
|
-
let logSelections = [];
|
|
66
|
-
if (!Utils.$$Array.isEmpty(noAddressesLogSelection.topicSelections)) {
|
|
67
|
-
logSelections.push(noAddressesLogSelection);
|
|
68
|
-
}
|
|
69
|
-
contractNames.forEach(contractName => {
|
|
70
|
-
let addresses = addressesByContractName[contractName];
|
|
71
|
-
if (addresses === undefined) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
if (addresses.length === 0) {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
let topicSelections = topicSelectionsByContract[contractName];
|
|
78
|
-
if (topicSelections !== undefined) {
|
|
79
|
-
logSelections.push(LogSelection.make(addresses, LogSelection.materializeTopicSelections(topicSelections, addresses)));
|
|
80
|
-
}
|
|
81
|
-
let topicSelections$1 = wildcardTopicSelectionsByContract[contractName];
|
|
82
|
-
if (topicSelections$1 !== undefined) {
|
|
83
|
-
logSelections.push(LogSelection.make([], LogSelection.materializeTopicSelections(topicSelections$1, addresses)));
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
return logSelections;
|
|
88
|
-
};
|
|
89
|
-
return {
|
|
90
|
-
getLogSelectionOrThrow: getLogSelectionOrThrow,
|
|
91
|
-
fieldSelection: fieldSelection
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function memoGetSelectionConfig() {
|
|
96
|
-
return Utils.$$WeakMap.memoize(getSelectionConfig);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
16
|
function isUnauthorizedError(message) {
|
|
100
17
|
return message.includes("401 Unauthorized");
|
|
101
18
|
}
|
|
102
19
|
|
|
103
20
|
function make(param) {
|
|
104
21
|
let apiToken = param.apiToken;
|
|
105
|
-
let
|
|
22
|
+
let onEventRegistrations = param.onEventRegistrations;
|
|
106
23
|
let endpointUrl = param.endpointUrl;
|
|
107
24
|
let chain = param.chain;
|
|
108
25
|
let name = "HyperSync";
|
|
109
|
-
let getSelectionConfig$1 = Utils.$$WeakMap.memoize(getSelectionConfig);
|
|
110
26
|
let apiToken$1 = apiToken !== undefined ? apiToken : Stdlib_JsError.throwWithMessage(`An Envio API token is required for using HyperSync as a data-source.
|
|
111
27
|
Set the ENVIO_API_TOKEN environment variable in your .env file.
|
|
112
28
|
Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
113
29
|
let client;
|
|
114
30
|
try {
|
|
115
|
-
client = HyperSyncClient.make(endpointUrl, apiToken$1, param.clientTimeoutMillis,
|
|
31
|
+
client = HyperSyncClient.make(endpointUrl, apiToken$1, param.clientTimeoutMillis, HyperSyncClient.Registration.fromOnEventRegistrations(onEventRegistrations), !param.lowercaseAddresses, param.serializationFormat, param.enableQueryCaching, undefined, undefined, undefined, param.logLevel);
|
|
116
32
|
} catch (raw_exn) {
|
|
117
33
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
118
34
|
client = ErrorHandling.mkLogAndRaise(undefined, "Failed to instantiate the hypersync client, please double check your ABI", exn);
|
|
119
35
|
}
|
|
120
|
-
let
|
|
121
|
-
let makeEventBatchQueueItem = (item, params, onEventRegistration) => {
|
|
36
|
+
let makeEventBatchQueueItem = (item, onEventRegistration) => {
|
|
122
37
|
let logIndex = item.logIndex;
|
|
123
38
|
return {
|
|
124
39
|
kind: 0,
|
|
@@ -130,27 +45,19 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
130
45
|
payload: {
|
|
131
46
|
contractName: onEventRegistration.eventConfig.contractName,
|
|
132
47
|
eventName: onEventRegistration.eventConfig.name,
|
|
133
|
-
params: params,
|
|
48
|
+
params: item.params,
|
|
134
49
|
chainId: chain,
|
|
135
50
|
srcAddress: item.srcAddress,
|
|
136
51
|
logIndex: logIndex
|
|
137
52
|
}
|
|
138
53
|
};
|
|
139
54
|
};
|
|
140
|
-
let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName,
|
|
55
|
+
let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName, param, knownHeight, param$1, selection, itemsTarget, retry, param$2) => {
|
|
141
56
|
let totalTimeRef = Performance.now();
|
|
142
|
-
let selectionConfig = getSelectionConfig$1(selection);
|
|
143
|
-
let logSelections;
|
|
144
|
-
try {
|
|
145
|
-
logSelections = selectionConfig.getLogSelectionOrThrow(addressesByContractName);
|
|
146
|
-
} catch (raw_exn) {
|
|
147
|
-
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
148
|
-
logSelections = ErrorHandling.mkLogAndRaise(logger, "Failed getting log selection for the query", exn);
|
|
149
|
-
}
|
|
150
57
|
let startFetchingBatchTimeRef = Performance.now();
|
|
151
58
|
let pageUnsafe;
|
|
152
59
|
try {
|
|
153
|
-
pageUnsafe = await HyperSync.GetLogs.query(client, fromBlock, toBlock,
|
|
60
|
+
pageUnsafe = await HyperSync.GetLogs.query(client, fromBlock, toBlock, itemsTarget, selection.onEventRegistrations.map(reg => reg.index), addressesByContractName);
|
|
154
61
|
} catch (raw_error) {
|
|
155
62
|
let error = Primitive_exceptions.internalToException(raw_error);
|
|
156
63
|
if (error.RE_EXN_ID === HyperSync.GetLogs.$$Error) {
|
|
@@ -212,32 +119,8 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
212
119
|
blocksByNumber.set(block.number, block);
|
|
213
120
|
});
|
|
214
121
|
pageUnsafe.items.forEach(item => {
|
|
215
|
-
let
|
|
216
|
-
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
let params = Stdlib_Option.flatMap(Primitive_option.fromNullable(item.params), __x => __x[maybeEventConfig.eventConfig.contractName]);
|
|
220
|
-
if (params !== undefined) {
|
|
221
|
-
parsedQueueItems.push(makeEventBatchQueueItem(item, Primitive_option.valFromOption(params), maybeEventConfig));
|
|
222
|
-
return;
|
|
223
|
-
} else {
|
|
224
|
-
let logIndex = item.logIndex;
|
|
225
|
-
let blockNumber = item.blockNumber;
|
|
226
|
-
let exn = {
|
|
227
|
-
RE_EXN_ID: UndefinedValue
|
|
228
|
-
};
|
|
229
|
-
if (maybeEventConfig.isWildcard) {
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
let msg = `Event ` + maybeEventConfig.eventConfig.name + ` was unexpectedly parsed as undefined`;
|
|
233
|
-
let logger$1 = Logging.createChildFrom(logger, {
|
|
234
|
-
chainId: chain,
|
|
235
|
-
blockNumber: blockNumber,
|
|
236
|
-
logIndex: logIndex,
|
|
237
|
-
decoder: "hypersync-client"
|
|
238
|
-
});
|
|
239
|
-
return ErrorHandling.mkLogAndRaise(logger$1, msg, exn);
|
|
240
|
-
}
|
|
122
|
+
let onEventRegistration = onEventRegistrations[item.onEventRegistrationIndex];
|
|
123
|
+
parsedQueueItems.push(makeEventBatchQueueItem(item, onEventRegistration));
|
|
241
124
|
});
|
|
242
125
|
let parsingTimeElapsed = Performance.secondsSince(parsingTimeRef);
|
|
243
126
|
let blockHashes = [];
|
|
@@ -346,9 +229,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
346
229
|
}
|
|
347
230
|
|
|
348
231
|
export {
|
|
349
|
-
getSelectionConfig,
|
|
350
|
-
memoGetSelectionConfig,
|
|
351
232
|
isUnauthorizedError,
|
|
352
233
|
make,
|
|
353
234
|
}
|
|
354
|
-
/*
|
|
235
|
+
/* Logging Not a pure module */
|
package/src/sources/Rpc.res
CHANGED
|
@@ -82,38 +82,6 @@ let decimalFloatSchema: S.schema<float> = S.string->S.transform(s => {
|
|
|
82
82
|
})
|
|
83
83
|
|
|
84
84
|
module GetLogs = {
|
|
85
|
-
@unboxed
|
|
86
|
-
type topicFilter = Single(hex) | Multiple(array<hex>) | @as(null) Null
|
|
87
|
-
type topicQuery = array<topicFilter>
|
|
88
|
-
|
|
89
|
-
let makeTopicQuery = (~topic0=[], ~topic1=[], ~topic2=[], ~topic3=[]) => {
|
|
90
|
-
let topics = [topic0, topic1, topic2, topic3]
|
|
91
|
-
|
|
92
|
-
let isLastTopicEmpty = () =>
|
|
93
|
-
switch topics->Utils.Array.last {
|
|
94
|
-
| Some([]) => true
|
|
95
|
-
| _ => false
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
//Remove all empty topics from the end of the array
|
|
99
|
-
while isLastTopicEmpty() {
|
|
100
|
-
topics->Array.pop->ignore
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
let toTopicFilter = topic => {
|
|
104
|
-
switch topic {
|
|
105
|
-
| [] => Null
|
|
106
|
-
| [single] => Single(single->EvmTypes.Hex.toString)
|
|
107
|
-
| multiple => Multiple(multiple->EvmTypes.Hex.toStrings)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
topics->Array.map(toTopicFilter)
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
let mapTopicQuery = ({topic0, topic1, topic2, topic3}: Internal.topicSelection): topicQuery =>
|
|
115
|
-
makeTopicQuery(~topic0, ~topic1, ~topic2, ~topic3)
|
|
116
|
-
|
|
117
85
|
type log = {
|
|
118
86
|
address: Address.t,
|
|
119
87
|
topics: array<hex>,
|
package/src/sources/Rpc.res.mjs
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import * as Rest from "../vendored/Rest.res.mjs";
|
|
4
4
|
import * as Viem from "viem";
|
|
5
|
-
import * as Utils from "../Utils.res.mjs";
|
|
6
5
|
import * as Address from "../Address.res.mjs";
|
|
7
6
|
import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
|
|
8
7
|
import * as Stdlib_BigInt from "@rescript/runtime/lib/es6/Stdlib_BigInt.js";
|
|
@@ -95,51 +94,7 @@ let decimalFloatSchema = S$RescriptSchema.transform(S$RescriptSchema.string, s =
|
|
|
95
94
|
}
|
|
96
95
|
}));
|
|
97
96
|
|
|
98
|
-
|
|
99
|
-
let topic0 = topic0Opt !== undefined ? topic0Opt : [];
|
|
100
|
-
let topic1 = topic1Opt !== undefined ? topic1Opt : [];
|
|
101
|
-
let topic2 = topic2Opt !== undefined ? topic2Opt : [];
|
|
102
|
-
let topic3 = topic3Opt !== undefined ? topic3Opt : [];
|
|
103
|
-
let topics = [
|
|
104
|
-
topic0,
|
|
105
|
-
topic1,
|
|
106
|
-
topic2,
|
|
107
|
-
topic3
|
|
108
|
-
];
|
|
109
|
-
let isLastTopicEmpty = () => {
|
|
110
|
-
let match = Utils.$$Array.last(topics);
|
|
111
|
-
if (match !== undefined) {
|
|
112
|
-
return match.length === 0;
|
|
113
|
-
} else {
|
|
114
|
-
return false;
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
while (isLastTopicEmpty()) {
|
|
118
|
-
topics.pop();
|
|
119
|
-
};
|
|
120
|
-
let toTopicFilter = topic => {
|
|
121
|
-
let len = topic.length;
|
|
122
|
-
if (len !== 1) {
|
|
123
|
-
if (len !== 0) {
|
|
124
|
-
return topic;
|
|
125
|
-
} else {
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
let single = topic[0];
|
|
130
|
-
return single;
|
|
131
|
-
};
|
|
132
|
-
return topics.map(toTopicFilter);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function mapTopicQuery(param) {
|
|
136
|
-
return makeTopicQuery(param.topic0, param.topic1, param.topic2, param.topic3);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
let GetLogs = {
|
|
140
|
-
makeTopicQuery: makeTopicQuery,
|
|
141
|
-
mapTopicQuery: mapTopicQuery
|
|
142
|
-
};
|
|
97
|
+
let GetLogs = {};
|
|
143
98
|
|
|
144
99
|
let blockSchema = S$RescriptSchema.object(s => ({
|
|
145
100
|
difficulty: s.f("difficulty", S$RescriptSchema.$$null(hexBigintSchema)),
|
|
@@ -97,10 +97,6 @@ let getErrorMessage = (exn: exn): option<string> =>
|
|
|
97
97
|
| _ => None
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
type logSelection = {
|
|
101
|
-
addresses: option<array<Address.t>>,
|
|
102
|
-
topicQuery: Rpc.GetLogs.topicQuery,
|
|
103
|
-
}
|
|
104
100
|
|
|
105
101
|
// `EvmRpcClient.getNextPage` throws a napi error whose message is a JSON
|
|
106
102
|
// payload describing the retry decision:
|
|
@@ -161,122 +157,6 @@ let parseGetNextPageRetryError = (exn: exn): option<(
|
|
|
161
157
|
| _ => None
|
|
162
158
|
}
|
|
163
159
|
|
|
164
|
-
type selectionConfig = {
|
|
165
|
-
getLogSelectionsOrThrow: (
|
|
166
|
-
~addressesByContractName: dict<array<Address.t>>,
|
|
167
|
-
) => array<logSelection>,
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
let getSelectionConfig = (selection: FetchState.selection) => {
|
|
171
|
-
let evmOnEventRegistrations =
|
|
172
|
-
selection.onEventRegistrations->(
|
|
173
|
-
Utils.magic: array<Internal.onEventRegistration> => array<Internal.evmOnEventRegistration>
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
if evmOnEventRegistrations->Utils.Array.isEmpty {
|
|
177
|
-
throw(
|
|
178
|
-
Source.GetItemsError(
|
|
179
|
-
UnsupportedSelection({
|
|
180
|
-
message: "Invalid events configuration for the partition. Nothing to fetch. Please, report to the Envio team.",
|
|
181
|
-
}),
|
|
182
|
-
),
|
|
183
|
-
)
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// eth_getLogs takes one address list and one topic selection per request, so
|
|
187
|
-
// fan out to one request per selection. Each address-bound event is grouped by
|
|
188
|
-
// its contract and later scoped to that contract's own addresses — pooling all
|
|
189
|
-
// contracts' addresses would let one contract's query fetch a sibling's logs,
|
|
190
|
-
// which route back by address and bypass the sibling's filter (routing never
|
|
191
|
-
// re-applies it). Pure-wildcard events carry no address constraint, so they're
|
|
192
|
-
// pooled and resolved once.
|
|
193
|
-
let noAddressTopicSelections = []
|
|
194
|
-
let byContract = Dict.make()
|
|
195
|
-
let wildcardByContract = Dict.make()
|
|
196
|
-
let contractNames = Utils.Set.make()
|
|
197
|
-
|
|
198
|
-
evmOnEventRegistrations->Array.forEach(reg => {
|
|
199
|
-
let contractName = reg.eventConfig.contractName
|
|
200
|
-
let {isWildcard, dependsOnAddresses, resolvedWhere} = reg
|
|
201
|
-
if dependsOnAddresses {
|
|
202
|
-
contractNames->Utils.Set.add(contractName)->ignore
|
|
203
|
-
(isWildcard ? wildcardByContract : byContract)->Utils.Dict.pushMany(
|
|
204
|
-
contractName,
|
|
205
|
-
resolvedWhere.topicSelections,
|
|
206
|
-
)
|
|
207
|
-
} else {
|
|
208
|
-
noAddressTopicSelections
|
|
209
|
-
->Array.pushMany(
|
|
210
|
-
resolvedWhere.topicSelections->LogSelection.materializeTopicSelections(~addresses=[]),
|
|
211
|
-
)
|
|
212
|
-
->ignore
|
|
213
|
-
}
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
// `compressTopicSelections` folds the filter-less events into a single topic0
|
|
217
|
-
// OR-set, keeping the common case at one request.
|
|
218
|
-
let toLogSelections = (~addresses, topicSelections): array<logSelection> =>
|
|
219
|
-
topicSelections
|
|
220
|
-
->LogSelection.compressTopicSelections
|
|
221
|
-
->Array.map(topicSelection => {
|
|
222
|
-
addresses,
|
|
223
|
-
topicQuery: topicSelection->Rpc.GetLogs.mapTopicQuery,
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
// Address-independent, so resolve once (the wildcard partition reuses this).
|
|
227
|
-
let noAddressLogSelections = toLogSelections(~addresses=None, noAddressTopicSelections)
|
|
228
|
-
|
|
229
|
-
let getLogSelectionsOrThrow = if contractNames->Utils.Set.size === 0 {
|
|
230
|
-
(~addressesByContractName as _) => noAddressLogSelections
|
|
231
|
-
} else {
|
|
232
|
-
(~addressesByContractName): array<logSelection> => {
|
|
233
|
-
let logSelections = noAddressLogSelections->Array.copy
|
|
234
|
-
contractNames->Utils.Set.forEach(contractName => {
|
|
235
|
-
switch addressesByContractName->Utils.Dict.dangerouslyGetNonOption(contractName) {
|
|
236
|
-
| None
|
|
237
|
-
| Some([]) => ()
|
|
238
|
-
| Some(addresses) =>
|
|
239
|
-
// Non-wildcard filters, scoped to this contract's addresses.
|
|
240
|
-
switch byContract->Utils.Dict.dangerouslyGetNonOption(contractName) {
|
|
241
|
-
| Some(topicSelections) =>
|
|
242
|
-
logSelections
|
|
243
|
-
->Array.pushMany(
|
|
244
|
-
toLogSelections(
|
|
245
|
-
~addresses=Some(addresses),
|
|
246
|
-
topicSelections->LogSelection.materializeTopicSelections(~addresses),
|
|
247
|
-
),
|
|
248
|
-
)
|
|
249
|
-
->ignore
|
|
250
|
-
| None => ()
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Wildcard-by-address filters fold the address into the topics,
|
|
254
|
-
// so they still match any address.
|
|
255
|
-
switch wildcardByContract->Utils.Dict.dangerouslyGetNonOption(contractName) {
|
|
256
|
-
| Some(topicSelections) =>
|
|
257
|
-
logSelections
|
|
258
|
-
->Array.pushMany(
|
|
259
|
-
toLogSelections(
|
|
260
|
-
~addresses=None,
|
|
261
|
-
topicSelections->LogSelection.materializeTopicSelections(~addresses),
|
|
262
|
-
),
|
|
263
|
-
)
|
|
264
|
-
->ignore
|
|
265
|
-
| None => ()
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
})
|
|
269
|
-
logSelections
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
{
|
|
274
|
-
getLogSelectionsOrThrow: getLogSelectionsOrThrow,
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
let memoGetSelectionConfig = () => Utils.WeakMap.memoize(getSelectionConfig)
|
|
279
|
-
|
|
280
160
|
// Type-erase a schema for storage in the field registry
|
|
281
161
|
external toFieldSchema: S.t<'a> => S.t<JSON.t> = "%identity"
|
|
282
162
|
|
|
@@ -735,8 +615,8 @@ type options = {
|
|
|
735
615
|
syncConfig: Config.sourceSync,
|
|
736
616
|
url: string,
|
|
737
617
|
chain: ChainMap.Chain.t,
|
|
738
|
-
|
|
739
|
-
|
|
618
|
+
// The chain's registrations, indexed by their sequential `index`.
|
|
619
|
+
onEventRegistrations: array<Internal.evmOnEventRegistration>,
|
|
740
620
|
lowercaseAddresses: bool,
|
|
741
621
|
ws?: string,
|
|
742
622
|
headers?: dict<string>,
|
|
@@ -748,8 +628,7 @@ let make = (
|
|
|
748
628
|
syncConfig,
|
|
749
629
|
url,
|
|
750
630
|
chain,
|
|
751
|
-
|
|
752
|
-
allEventParams,
|
|
631
|
+
onEventRegistrations,
|
|
753
632
|
lowercaseAddresses,
|
|
754
633
|
?ws,
|
|
755
634
|
?headers,
|
|
@@ -765,12 +644,12 @@ let make = (
|
|
|
765
644
|
}
|
|
766
645
|
let name = `RPC (${urlHost})`
|
|
767
646
|
|
|
768
|
-
let getSelectionConfig = memoGetSelectionConfig()
|
|
769
|
-
|
|
770
647
|
let client = Rpc.makeClient(url, ~headers?)
|
|
771
648
|
let rpcClient = EvmRpcClient.make(
|
|
772
649
|
~url,
|
|
773
|
-
~
|
|
650
|
+
~eventRegistrations=HyperSyncClient.Registration.fromOnEventRegistrations(
|
|
651
|
+
onEventRegistrations,
|
|
652
|
+
),
|
|
774
653
|
~checksumAddresses=!lowercaseAddresses,
|
|
775
654
|
~syncConfig,
|
|
776
655
|
~headers?,
|
|
@@ -921,7 +800,7 @@ let make = (
|
|
|
921
800
|
~fromBlock,
|
|
922
801
|
~toBlock,
|
|
923
802
|
~addressesByContractName,
|
|
924
|
-
~contractNameByAddress,
|
|
803
|
+
~contractNameByAddress as _,
|
|
925
804
|
~knownHeight,
|
|
926
805
|
~partitionId,
|
|
927
806
|
~selection: FetchState.selection,
|
|
@@ -944,26 +823,22 @@ let make = (
|
|
|
944
823
|
->Promise.thenResolve(json => Some(parseBlockInfo(json)))
|
|
945
824
|
: Promise.resolve(None)
|
|
946
825
|
|
|
947
|
-
|
|
948
|
-
|
|
826
|
+
if selection.onEventRegistrations->Utils.Array.isEmpty {
|
|
827
|
+
throw(
|
|
828
|
+
Source.GetItemsError(
|
|
829
|
+
UnsupportedSelection({
|
|
830
|
+
message: "Invalid events configuration for the partition. Nothing to fetch. Please, report to the Envio team.",
|
|
831
|
+
}),
|
|
832
|
+
),
|
|
833
|
+
)
|
|
834
|
+
}
|
|
949
835
|
|
|
950
836
|
let {items, toBlock: queriedToBlock, requestStats} = try await rpcClient.getNextPage({
|
|
951
837
|
fromBlock,
|
|
952
838
|
toBlockCeiling: toBlock,
|
|
953
|
-
logSelections: logSelections->Array.map(({
|
|
954
|
-
addresses,
|
|
955
|
-
topicQuery,
|
|
956
|
-
}): EvmRpcClient.logSelectionInput => {
|
|
957
|
-
?addresses,
|
|
958
|
-
topics: topicQuery->Array.map(filter =>
|
|
959
|
-
switch filter {
|
|
960
|
-
| Rpc.GetLogs.Null => Nullable.null
|
|
961
|
-
| Single(topic) => Nullable.make([topic])
|
|
962
|
-
| Multiple(topics) => Nullable.make(topics)
|
|
963
|
-
}
|
|
964
|
-
),
|
|
965
|
-
}),
|
|
966
839
|
partitionId,
|
|
840
|
+
registrationIndexes: selection.onEventRegistrations->Array.map(reg => reg.index),
|
|
841
|
+
addressesByContractName,
|
|
967
842
|
}) catch {
|
|
968
843
|
| exn =>
|
|
969
844
|
switch exn->parseGetNextPageRetryError {
|
|
@@ -997,32 +872,15 @@ let make = (
|
|
|
997
872
|
->Promise.thenResolve(parseBlockInfo)
|
|
998
873
|
|
|
999
874
|
let parsedQueueItems = await items
|
|
1000
|
-
->Array.
|
|
1001
|
-
|
|
1002
|
-
let
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
~tag=EventRouter.getEvmEventId(~sighash=topic0, ~topicCount=log.topics->Array.length),
|
|
1010
|
-
~contractNameByAddress,
|
|
1011
|
-
~contractAddress=routedAddress,
|
|
1012
|
-
) {
|
|
1013
|
-
| None => None
|
|
1014
|
-
| Some(onEventRegistration) =>
|
|
1015
|
-
let eventConfig =
|
|
1016
|
-
onEventRegistration.eventConfig->(
|
|
1017
|
-
Utils.magic: Internal.eventConfig => Internal.evmEventConfig
|
|
1018
|
-
)
|
|
1019
|
-
switch maybeDecodedEvent
|
|
1020
|
-
->Nullable.toOption
|
|
1021
|
-
->Option.flatMap(Dict.get(_, eventConfig.contractName)) {
|
|
1022
|
-
| Some(decoded) =>
|
|
1023
|
-
Some(
|
|
1024
|
-
(
|
|
1025
|
-
async () => {
|
|
875
|
+
->Array.map(({log, onEventRegistrationIndex, params: decoded}: EvmRpcClient.rpcEventItem) => {
|
|
876
|
+
// `log.address` comes back already normalized to the client's casing.
|
|
877
|
+
let onEventRegistration = onEventRegistrations->Array.getUnsafe(onEventRegistrationIndex)
|
|
878
|
+
let eventConfig =
|
|
879
|
+
onEventRegistration.eventConfig->(
|
|
880
|
+
Utils.magic: Internal.eventConfig => Internal.evmEventConfig
|
|
881
|
+
)
|
|
882
|
+
(
|
|
883
|
+
async () => {
|
|
1026
884
|
let (block, transaction) = try await Promise.all2((
|
|
1027
885
|
log->getEventBlockOrThrow(~selectedBlockFields=eventConfig.selectedBlockFields),
|
|
1028
886
|
log->getEventTransactionOrThrow(
|
|
@@ -1074,16 +932,12 @@ let make = (
|
|
|
1074
932
|
params: decoded,
|
|
1075
933
|
block,
|
|
1076
934
|
transaction,
|
|
1077
|
-
srcAddress:
|
|
935
|
+
srcAddress: log.address,
|
|
1078
936
|
logIndex: log.logIndex,
|
|
1079
937
|
}->Evm.fromPayload,
|
|
1080
938
|
})
|
|
1081
|
-
}
|
|
1082
|
-
)(),
|
|
1083
|
-
)
|
|
1084
|
-
| None => None
|
|
1085
939
|
}
|
|
1086
|
-
|
|
940
|
+
)()
|
|
1087
941
|
})
|
|
1088
942
|
->Promise.all
|
|
1089
943
|
|