envio 3.5.0-alpha.1 → 3.5.0-alpha.2
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/index.d.ts +10 -6
- package/package.json +6 -6
- package/src/BatchProcessing.res +13 -0
- package/src/BatchProcessing.res.mjs +4 -0
- package/src/ChainFetching.res +5 -5
- package/src/ChainFetching.res.mjs +3 -4
- package/src/ChainState.res +38 -21
- package/src/ChainState.res.mjs +17 -24
- package/src/ChainState.resi +1 -5
- package/src/Change.res +3 -3
- package/src/Config.res +0 -4
- package/src/Config.res.mjs +0 -10
- package/src/Core.res +3 -0
- package/src/EntityId.res +15 -0
- package/src/EntityId.res.mjs +9 -0
- package/src/EventConfigBuilder.res +1 -58
- package/src/EventConfigBuilder.res.mjs +1 -33
- package/src/FetchState.res +345 -459
- package/src/FetchState.res.mjs +269 -430
- package/src/HandlerRegister.res +45 -0
- package/src/HandlerRegister.res.mjs +43 -0
- package/src/InMemoryStore.res +11 -4
- package/src/InMemoryTable.res +12 -10
- package/src/InMemoryTable.res.mjs +6 -5
- package/src/IndexerState.res +59 -2
- package/src/IndexerState.res.mjs +48 -3
- package/src/IndexerState.resi +2 -0
- package/src/Internal.res +17 -8
- package/src/LogSelection.res +2 -1
- package/src/Metrics.res +37 -6
- package/src/Metrics.res.mjs +5 -1
- package/src/Persistence.res +1 -1
- package/src/PgStorage.res +55 -22
- package/src/PgStorage.res.mjs +25 -17
- package/src/SimulateItems.res +2 -2
- package/src/TestIndexer.res +6 -5
- package/src/TestIndexer.res.mjs +3 -2
- package/src/UserContext.res +3 -3
- package/src/Writing.res +12 -2
- package/src/Writing.res.mjs +13 -2
- package/src/bindings/ClickHouse.res +5 -3
- package/src/bindings/ClickHouse.res.mjs +2 -5
- package/src/bindings/Vitest.res +22 -1
- package/src/bindings/Vitest.res.mjs +15 -0
- package/src/db/EntityHistory.res +16 -7
- package/src/db/EntityHistory.res.mjs +7 -6
- package/src/db/Table.res +40 -9
- package/src/db/Table.res.mjs +44 -6
- package/src/sources/AddressSet.res +48 -0
- package/src/sources/AddressSet.res.mjs +11 -0
- package/src/sources/AddressStore.res +152 -0
- package/src/sources/AddressStore.res.mjs +97 -0
- package/src/sources/EvmChain.res +3 -0
- package/src/sources/EvmChain.res.mjs +4 -2
- package/src/sources/EvmHyperSyncSource.res +6 -3
- package/src/sources/EvmHyperSyncSource.res.mjs +3 -3
- package/src/sources/EvmRpcClient.res +6 -3
- package/src/sources/EvmRpcClient.res.mjs +3 -3
- package/src/sources/FuelHyperSync.res +4 -3
- package/src/sources/FuelHyperSync.res.mjs +3 -3
- package/src/sources/FuelHyperSync.resi +2 -1
- package/src/sources/FuelHyperSyncClient.res +12 -6
- package/src/sources/FuelHyperSyncClient.res.mjs +2 -2
- package/src/sources/FuelHyperSyncSource.res +7 -4
- package/src/sources/FuelHyperSyncSource.res.mjs +3 -3
- package/src/sources/HyperSync.res +6 -4
- package/src/sources/HyperSync.res.mjs +2 -3
- package/src/sources/HyperSync.resi +1 -1
- package/src/sources/HyperSyncClient.res +18 -9
- package/src/sources/HyperSyncClient.res.mjs +4 -4
- package/src/sources/RpcSource.res +15 -10
- package/src/sources/RpcSource.res.mjs +3 -4
- package/src/sources/SimulateSource.res +26 -11
- package/src/sources/SimulateSource.res.mjs +13 -5
- package/src/sources/Source.res +4 -2
- package/src/sources/SourceManager.res +2 -3
- package/src/sources/SourceManager.res.mjs +2 -3
- package/src/sources/Svm.res +1 -2
- package/src/sources/Svm.res.mjs +1 -1
- package/src/sources/SvmHyperSyncClient.res +12 -3
- package/src/sources/SvmHyperSyncClient.res.mjs +2 -2
- package/src/sources/SvmHyperSyncSource.res +10 -5
- package/src/sources/SvmHyperSyncSource.res.mjs +5 -4
- package/src/IndexingAddresses.res +0 -151
- package/src/IndexingAddresses.res.mjs +0 -130
- package/src/IndexingAddresses.resi +0 -39
|
@@ -16,6 +16,8 @@ type options = {
|
|
|
16
16
|
serializationFormat: HyperSyncClient.serializationFormat,
|
|
17
17
|
enableQueryCaching: bool,
|
|
18
18
|
logLevel: HyperSyncClient.logLevel,
|
|
19
|
+
// The chain's address index; the client reads it while routing.
|
|
20
|
+
addressStore: AddressStore.t,
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
let make = (
|
|
@@ -29,6 +31,7 @@ let make = (
|
|
|
29
31
|
serializationFormat,
|
|
30
32
|
enableQueryCaching,
|
|
31
33
|
logLevel,
|
|
34
|
+
addressStore,
|
|
32
35
|
}: options,
|
|
33
36
|
): t => {
|
|
34
37
|
let name = "HyperSync"
|
|
@@ -50,6 +53,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
50
53
|
~serializationFormat,
|
|
51
54
|
~enableQueryCaching,
|
|
52
55
|
~logLevel,
|
|
56
|
+
~addressStore,
|
|
53
57
|
) {
|
|
54
58
|
| client => client
|
|
55
59
|
| exception exn =>
|
|
@@ -86,8 +90,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
86
90
|
let getItemsOrThrow = async (
|
|
87
91
|
~fromBlock,
|
|
88
92
|
~toBlock,
|
|
89
|
-
~
|
|
90
|
-
~contractNameByAddress as _,
|
|
93
|
+
~addressSet,
|
|
91
94
|
~knownHeight,
|
|
92
95
|
~partitionId as _,
|
|
93
96
|
~selection: FetchState.selection,
|
|
@@ -106,7 +109,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
106
109
|
~toBlock,
|
|
107
110
|
~maxNumLogs=itemsTarget,
|
|
108
111
|
~registrationIndexes=selection.onEventRegistrations->Array.map(reg => reg.index),
|
|
109
|
-
~
|
|
112
|
+
~addressSet,
|
|
110
113
|
~clientFilteredContracts=selection.clientFilteredContracts,
|
|
111
114
|
) catch {
|
|
112
115
|
| HyperSync.GetLogs.Error(error) =>
|
|
@@ -28,7 +28,7 @@ Set the ENVIO_API_TOKEN environment variable in your .env file.
|
|
|
28
28
|
Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
29
29
|
let client;
|
|
30
30
|
try {
|
|
31
|
-
client = HyperSyncClient.make(endpointUrl, apiToken$1, param.clientTimeoutMillis, HyperSyncClient.Registration.fromOnEventRegistrations(onEventRegistrations), !param.lowercaseAddresses, param.serializationFormat, param.enableQueryCaching, undefined, undefined, undefined, param.logLevel);
|
|
31
|
+
client = HyperSyncClient.make(endpointUrl, apiToken$1, param.clientTimeoutMillis, HyperSyncClient.Registration.fromOnEventRegistrations(onEventRegistrations), !param.lowercaseAddresses, param.serializationFormat, param.enableQueryCaching, undefined, undefined, undefined, param.logLevel, param.addressStore);
|
|
32
32
|
} catch (raw_exn) {
|
|
33
33
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
34
34
|
client = ErrorHandling.mkLogAndRaise(undefined, "Failed to instantiate the hypersync client, please double check your ABI", exn);
|
|
@@ -52,12 +52,12 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
52
52
|
}
|
|
53
53
|
};
|
|
54
54
|
};
|
|
55
|
-
let getItemsOrThrow = async (fromBlock, toBlock,
|
|
55
|
+
let getItemsOrThrow = async (fromBlock, toBlock, addressSet, knownHeight, param, selection, itemsTarget, retry, param$1) => {
|
|
56
56
|
let totalTimeRef = Performance.now();
|
|
57
57
|
let startFetchingBatchTimeRef = Performance.now();
|
|
58
58
|
let pageUnsafe;
|
|
59
59
|
try {
|
|
60
|
-
pageUnsafe = await HyperSync.GetLogs.query(client, fromBlock, toBlock, itemsTarget, selection.onEventRegistrations.map(reg => reg.index),
|
|
60
|
+
pageUnsafe = await HyperSync.GetLogs.query(client, fromBlock, toBlock, itemsTarget, selection.onEventRegistrations.map(reg => reg.index), addressSet, selection.clientFilteredContracts);
|
|
61
61
|
} catch (raw_error) {
|
|
62
62
|
let error = Primitive_exceptions.internalToException(raw_error);
|
|
63
63
|
if (error.RE_EXN_ID === HyperSync.GetLogs.$$Error) {
|
|
@@ -26,7 +26,6 @@ type nextPageParams = {
|
|
|
26
26
|
// selections and the routing index are derived on the Rust side from the
|
|
27
27
|
// registrations passed at construction.
|
|
28
28
|
registrationIndexes: array<int>,
|
|
29
|
-
addressesByContractName: dict<array<Address.t>>,
|
|
30
29
|
// Contract names to fetch address-free even though their registrations
|
|
31
30
|
// depend on addresses (client-side filtering). None/empty means
|
|
32
31
|
// every address-dependent contract is filtered server-side.
|
|
@@ -42,7 +41,7 @@ type nextPageResponse = {
|
|
|
42
41
|
// The caller provides a range; Rust decides the actual `toBlock` and returns it.
|
|
43
42
|
type t = {
|
|
44
43
|
getHeight: unit => promise<int>,
|
|
45
|
-
getNextPage: nextPageParams => promise<nextPageResponse>,
|
|
44
|
+
getNextPage: (nextPageParams, AddressSet.t) => promise<nextPageResponse>,
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
@send
|
|
@@ -51,6 +50,7 @@ external classNew: (
|
|
|
51
50
|
cfg,
|
|
52
51
|
array<HyperSyncClient.Registration.input>,
|
|
53
52
|
~checksumAddresses: bool,
|
|
53
|
+
~addressStore: AddressStore.t,
|
|
54
54
|
) => t = "new"
|
|
55
55
|
|
|
56
56
|
// Rust encodes JSON-RPC errors as a JSON payload in the napi error's
|
|
@@ -89,6 +89,7 @@ let make = (
|
|
|
89
89
|
~httpReqTimeoutMillis=?,
|
|
90
90
|
~headers=?,
|
|
91
91
|
~eventRegistrations=[],
|
|
92
|
+
~addressStore,
|
|
92
93
|
) => {
|
|
93
94
|
let client = Core.getAddon().evmRpcClient->classNew(
|
|
94
95
|
{
|
|
@@ -104,9 +105,11 @@ let make = (
|
|
|
104
105
|
},
|
|
105
106
|
eventRegistrations,
|
|
106
107
|
~checksumAddresses,
|
|
108
|
+
~addressStore,
|
|
107
109
|
)
|
|
108
110
|
{
|
|
109
111
|
getHeight: () => client.getHeight()->Promise.catch(coerceErrorOrThrow),
|
|
110
|
-
getNextPage: params =>
|
|
112
|
+
getNextPage: (params, addressSet) =>
|
|
113
|
+
client.getNextPage(params, addressSet)->Promise.catch(coerceErrorOrThrow),
|
|
111
114
|
}
|
|
112
115
|
}
|
|
@@ -46,7 +46,7 @@ function coerceErrorOrThrow(exn) {
|
|
|
46
46
|
throw exn;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
function make(url, checksumAddresses, syncConfig, httpReqTimeoutMillis, headers, eventRegistrationsOpt) {
|
|
49
|
+
function make(url, checksumAddresses, syncConfig, httpReqTimeoutMillis, headers, eventRegistrationsOpt, addressStore) {
|
|
50
50
|
let eventRegistrations = eventRegistrationsOpt !== undefined ? eventRegistrationsOpt : [];
|
|
51
51
|
let client = Core.getAddon().EvmRpcClient.new({
|
|
52
52
|
url: url,
|
|
@@ -58,10 +58,10 @@ function make(url, checksumAddresses, syncConfig, httpReqTimeoutMillis, headers,
|
|
|
58
58
|
intervalCeiling: syncConfig.intervalCeiling,
|
|
59
59
|
backoffMillis: syncConfig.backoffMillis,
|
|
60
60
|
queryTimeoutMillis: syncConfig.queryTimeoutMillis
|
|
61
|
-
}, eventRegistrations, checksumAddresses);
|
|
61
|
+
}, eventRegistrations, checksumAddresses, addressStore);
|
|
62
62
|
return {
|
|
63
63
|
getHeight: () => Stdlib_Promise.$$catch(client.getHeight(), coerceErrorOrThrow),
|
|
64
|
-
getNextPage: params => Stdlib_Promise.$$catch(client.getNextPage(params), coerceErrorOrThrow)
|
|
64
|
+
getNextPage: (params, addressSet) => Stdlib_Promise.$$catch(client.getNextPage(params, addressSet), coerceErrorOrThrow)
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -43,16 +43,17 @@ module GetLogs = {
|
|
|
43
43
|
~fromBlock,
|
|
44
44
|
~toBlock,
|
|
45
45
|
~registrationIndexes,
|
|
46
|
-
~
|
|
46
|
+
~addressSet,
|
|
47
|
+
~clientFilteredContracts,
|
|
47
48
|
): logsQueryPage => {
|
|
48
49
|
let query: FuelHyperSyncClient.EventItems.query = {
|
|
49
50
|
fromBlock,
|
|
50
51
|
toBlock,
|
|
51
52
|
registrationIndexes,
|
|
52
|
-
|
|
53
|
+
clientFilteredContracts,
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
let res = switch await client->FuelHyperSyncClient.getEventItems(query) {
|
|
56
|
+
let res = switch await client->FuelHyperSyncClient.getEventItems(query, addressSet) {
|
|
56
57
|
| res => res
|
|
57
58
|
| exception exn =>
|
|
58
59
|
switch exn->extractMissingParams {
|
|
@@ -29,16 +29,16 @@ function extractMissingParams(exn) {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
async function query(client, fromBlock, toBlock, registrationIndexes,
|
|
32
|
+
async function query(client, fromBlock, toBlock, registrationIndexes, addressSet, clientFilteredContracts) {
|
|
33
33
|
let query$1 = {
|
|
34
34
|
fromBlock: fromBlock,
|
|
35
35
|
toBlock: toBlock,
|
|
36
36
|
registrationIndexes: registrationIndexes,
|
|
37
|
-
|
|
37
|
+
clientFilteredContracts: clientFilteredContracts
|
|
38
38
|
};
|
|
39
39
|
let res;
|
|
40
40
|
try {
|
|
41
|
-
res = await client.getEventItems(query$1);
|
|
41
|
+
res = await client.getEventItems(query$1, addressSet);
|
|
42
42
|
} catch (raw_exn) {
|
|
43
43
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
44
44
|
let missingParams = extractMissingParams(exn);
|
|
@@ -17,6 +17,7 @@ module GetLogs: {
|
|
|
17
17
|
~fromBlock: int,
|
|
18
18
|
~toBlock: option<int>,
|
|
19
19
|
~registrationIndexes: array<int>,
|
|
20
|
-
~
|
|
20
|
+
~addressSet: AddressSet.t,
|
|
21
|
+
~clientFilteredContracts: option<array<string>>,
|
|
21
22
|
) => promise<logsQueryPage>
|
|
22
23
|
}
|
|
@@ -52,15 +52,18 @@ module Registration = {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
module EventItems = {
|
|
55
|
-
// The whole per-query input
|
|
56
|
-
// selection (by index)
|
|
57
|
-
//
|
|
55
|
+
// The whole per-query input beside the partition's address set: block range
|
|
56
|
+
// and the registration selection (by index). Receipt selections, field
|
|
57
|
+
// selection, and routing are derived on the Rust side.
|
|
58
58
|
type query = {
|
|
59
59
|
fromBlock: int,
|
|
60
60
|
// Inclusive; None queries to the end of available data.
|
|
61
61
|
toBlock: option<int>,
|
|
62
62
|
registrationIndexes: array<int>,
|
|
63
|
-
|
|
63
|
+
// Contract names to fetch address-free even though their registrations
|
|
64
|
+
// depend on addresses (client-side filtering). None/empty means every
|
|
65
|
+
// address-dependent contract is filtered server-side.
|
|
66
|
+
clientFilteredContracts: option<array<string>>,
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
// One routed receipt with its kind-specific columns flattened: LogData
|
|
@@ -102,19 +105,22 @@ external classNew: (
|
|
|
102
105
|
cfg,
|
|
103
106
|
~userAgent: string,
|
|
104
107
|
array<Registration.input>,
|
|
108
|
+
AddressStore.t,
|
|
105
109
|
) => t = "new"
|
|
106
110
|
|
|
107
|
-
let make = (cfg: cfg, ~eventRegistrations) => {
|
|
111
|
+
let make = (cfg: cfg, ~eventRegistrations, ~addressStore) => {
|
|
108
112
|
let envioVersion = Utils.EnvioPackage.value.version
|
|
109
113
|
Core.getAddon().fuelHyperSyncClient->classNew(
|
|
110
114
|
cfg,
|
|
111
115
|
~userAgent=`hyperindex/${envioVersion}`,
|
|
112
116
|
eventRegistrations,
|
|
117
|
+
addressStore,
|
|
113
118
|
)
|
|
114
119
|
}
|
|
115
120
|
|
|
116
121
|
@send
|
|
117
|
-
external getEventItems: (t, EventItems.query) => promise<EventItems.response> =
|
|
122
|
+
external getEventItems: (t, EventItems.query, AddressSet.t) => promise<EventItems.response> =
|
|
123
|
+
"getEventItems"
|
|
118
124
|
|
|
119
125
|
@send
|
|
120
126
|
external getHeight: t => promise<int> = "getHeight"
|
|
@@ -58,9 +58,9 @@ let Registration = {
|
|
|
58
58
|
|
|
59
59
|
let EventItems = {};
|
|
60
60
|
|
|
61
|
-
function make(cfg, eventRegistrations) {
|
|
61
|
+
function make(cfg, eventRegistrations, addressStore) {
|
|
62
62
|
let envioVersion = Utils.EnvioPackage.value.version;
|
|
63
|
-
return Core.getAddon().FuelHyperSyncClient.new(cfg, `hyperindex/` + envioVersion, eventRegistrations);
|
|
63
|
+
return Core.getAddon().FuelHyperSyncClient.new(cfg, `hyperindex/` + envioVersion, eventRegistrations, addressStore);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
export {
|
|
@@ -8,9 +8,11 @@ type options = {
|
|
|
8
8
|
apiToken: option<string>,
|
|
9
9
|
// The chain's registrations, indexed by their sequential `index`.
|
|
10
10
|
onEventRegistrations: array<Internal.fuelOnEventRegistration>,
|
|
11
|
+
// The chain's address index; the client reads it while routing.
|
|
12
|
+
addressStore: AddressStore.t,
|
|
11
13
|
}
|
|
12
14
|
|
|
13
|
-
let make = ({chain, endpointUrl, apiToken, onEventRegistrations}: options): t => {
|
|
15
|
+
let make = ({chain, endpointUrl, apiToken, onEventRegistrations, addressStore}: options): t => {
|
|
14
16
|
let name = "HyperFuel"
|
|
15
17
|
|
|
16
18
|
let apiToken = switch apiToken {
|
|
@@ -24,6 +26,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
24
26
|
let client = switch FuelHyperSyncClient.make(
|
|
25
27
|
{url: endpointUrl, apiToken},
|
|
26
28
|
~eventRegistrations=FuelHyperSyncClient.Registration.fromOnEventRegistrations(onEventRegistrations),
|
|
29
|
+
~addressStore,
|
|
27
30
|
) {
|
|
28
31
|
| client => client
|
|
29
32
|
| exception exn =>
|
|
@@ -33,8 +36,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
33
36
|
let getItemsOrThrow = async (
|
|
34
37
|
~fromBlock,
|
|
35
38
|
~toBlock,
|
|
36
|
-
~
|
|
37
|
-
~contractNameByAddress as _,
|
|
39
|
+
~addressSet,
|
|
38
40
|
~knownHeight,
|
|
39
41
|
~partitionId as _,
|
|
40
42
|
~selection: FetchState.selection,
|
|
@@ -52,7 +54,8 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
52
54
|
~fromBlock,
|
|
53
55
|
~toBlock,
|
|
54
56
|
~registrationIndexes=selection.onEventRegistrations->Array.map(reg => reg.index),
|
|
55
|
-
~
|
|
57
|
+
~addressSet,
|
|
58
|
+
~clientFilteredContracts=selection.clientFilteredContracts,
|
|
56
59
|
) catch {
|
|
57
60
|
| FuelHyperSync.GetLogs.Error(error) =>
|
|
58
61
|
throw(
|
|
@@ -27,17 +27,17 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
27
27
|
client = FuelHyperSyncClient.make({
|
|
28
28
|
url: param.endpointUrl,
|
|
29
29
|
apiToken: apiToken$1
|
|
30
|
-
}, FuelHyperSyncClient.Registration.fromOnEventRegistrations(onEventRegistrations));
|
|
30
|
+
}, FuelHyperSyncClient.Registration.fromOnEventRegistrations(onEventRegistrations), param.addressStore);
|
|
31
31
|
} catch (raw_exn) {
|
|
32
32
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
33
33
|
client = ErrorHandling.mkLogAndRaise(undefined, "Failed to instantiate the HyperFuel client", exn);
|
|
34
34
|
}
|
|
35
|
-
let getItemsOrThrow = async (fromBlock, toBlock,
|
|
35
|
+
let getItemsOrThrow = async (fromBlock, toBlock, addressSet, knownHeight, param, selection, param$1, retry, logger) => {
|
|
36
36
|
let totalTimeRef = Performance.now();
|
|
37
37
|
let startFetchingBatchTimeRef = Performance.now();
|
|
38
38
|
let pageUnsafe;
|
|
39
39
|
try {
|
|
40
|
-
pageUnsafe = await FuelHyperSync.GetLogs.query(client, fromBlock, toBlock, selection.onEventRegistrations.map(reg => reg.index),
|
|
40
|
+
pageUnsafe = await FuelHyperSync.GetLogs.query(client, fromBlock, toBlock, selection.onEventRegistrations.map(reg => reg.index), addressSet, selection.clientFilteredContracts);
|
|
41
41
|
} catch (raw_error) {
|
|
42
42
|
let error = Primitive_exceptions.internalToException(raw_error);
|
|
43
43
|
if (error.RE_EXN_ID === FuelHyperSync.GetLogs.$$Error) {
|
|
@@ -16,7 +16,7 @@ let reraisIfRateLimited = exn =>
|
|
|
16
16
|
|
|
17
17
|
type logsQueryPage = {
|
|
18
18
|
items: array<HyperSyncClient.EventItems.item>,
|
|
19
|
-
//
|
|
19
|
+
// Headers for every returned block, deduplicated by block number.
|
|
20
20
|
blocks: array<HyperSyncClient.EventItems.blockHeader>,
|
|
21
21
|
nextBlock: int,
|
|
22
22
|
archiveHeight: int,
|
|
@@ -92,7 +92,7 @@ module GetLogs = {
|
|
|
92
92
|
~toBlock,
|
|
93
93
|
~maxNumLogs,
|
|
94
94
|
~registrationIndexes,
|
|
95
|
-
~
|
|
95
|
+
~addressSet,
|
|
96
96
|
~clientFilteredContracts,
|
|
97
97
|
): logsQueryPage => {
|
|
98
98
|
let query: HyperSyncClient.EventItems.query = {
|
|
@@ -100,11 +100,13 @@ module GetLogs = {
|
|
|
100
100
|
toBlock,
|
|
101
101
|
?maxNumLogs,
|
|
102
102
|
registrationIndexes,
|
|
103
|
-
addressesByContractName,
|
|
104
103
|
clientFilteredContracts,
|
|
105
104
|
}
|
|
106
105
|
|
|
107
|
-
let (res, transactionStore, blockStore) = switch await client.getEventItems(
|
|
106
|
+
let (res, transactionStore, blockStore) = switch await client.getEventItems(
|
|
107
|
+
~query,
|
|
108
|
+
~addressSet,
|
|
109
|
+
) {
|
|
108
110
|
| res => res
|
|
109
111
|
| exception exn =>
|
|
110
112
|
reraisIfRateLimited(exn)
|
|
@@ -82,18 +82,17 @@ function extractMissingParams(exn) {
|
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
async function query(client, fromBlock, toBlock, maxNumLogs, registrationIndexes,
|
|
85
|
+
async function query(client, fromBlock, toBlock, maxNumLogs, registrationIndexes, addressSet, clientFilteredContracts) {
|
|
86
86
|
let query$1 = {
|
|
87
87
|
fromBlock: fromBlock,
|
|
88
88
|
toBlock: toBlock,
|
|
89
89
|
maxNumLogs: maxNumLogs,
|
|
90
90
|
registrationIndexes: registrationIndexes,
|
|
91
|
-
addressesByContractName: addressesByContractName,
|
|
92
91
|
clientFilteredContracts: clientFilteredContracts
|
|
93
92
|
};
|
|
94
93
|
let match;
|
|
95
94
|
try {
|
|
96
|
-
match = await client.getEventItems(query$1);
|
|
95
|
+
match = await client.getEventItems(query$1, addressSet);
|
|
97
96
|
} catch (raw_exn) {
|
|
98
97
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
99
98
|
reraisIfRateLimited(exn);
|
|
@@ -34,7 +34,7 @@ module GetLogs: {
|
|
|
34
34
|
~toBlock: option<int>,
|
|
35
35
|
~maxNumLogs: option<int>,
|
|
36
36
|
~registrationIndexes: array<int>,
|
|
37
|
-
~
|
|
37
|
+
~addressSet: AddressSet.t,
|
|
38
38
|
~clientFilteredContracts: option<array<string>>,
|
|
39
39
|
) => promise<logsQueryPage>
|
|
40
40
|
}
|
|
@@ -302,9 +302,9 @@ module Registration = {
|
|
|
302
302
|
}
|
|
303
303
|
|
|
304
304
|
module EventItems = {
|
|
305
|
-
// The whole per-query input
|
|
306
|
-
// selection (by id)
|
|
307
|
-
//
|
|
305
|
+
// The whole per-query input beside the partition's address set: block range
|
|
306
|
+
// and the registration selection (by id). Log selections, field selection,
|
|
307
|
+
// and the routing index are derived on the Rust side.
|
|
308
308
|
type query = {
|
|
309
309
|
fromBlock: int,
|
|
310
310
|
// Inclusive; None queries to the end of available data.
|
|
@@ -312,7 +312,6 @@ module EventItems = {
|
|
|
312
312
|
// Absent means no server-side cap on the number of logs returned.
|
|
313
313
|
maxNumLogs?: int,
|
|
314
314
|
registrationIndexes: array<int>,
|
|
315
|
-
addressesByContractName: dict<array<Address.t>>,
|
|
316
315
|
// Contract names to fetch address-free even though their registrations
|
|
317
316
|
// depend on addresses (client-side filtering). None/empty means
|
|
318
317
|
// every address-dependent contract is filtered server-side.
|
|
@@ -345,7 +344,9 @@ module EventItems = {
|
|
|
345
344
|
type response = {
|
|
346
345
|
archiveHeight: option<int>,
|
|
347
346
|
nextBlock: int,
|
|
348
|
-
// One header per block number
|
|
347
|
+
// One header per returned block number, including blocks no item
|
|
348
|
+
// references — reorg detection reads them all. The block store keeps only
|
|
349
|
+
// the ones items reference.
|
|
349
350
|
blocks: array<blockHeader>,
|
|
350
351
|
items: array<item>,
|
|
351
352
|
rollbackGuard: option<ResponseTypes.rollbackGuard>,
|
|
@@ -358,16 +359,22 @@ type t = {
|
|
|
358
359
|
// and blocks.
|
|
359
360
|
getEventItems: (
|
|
360
361
|
~query: EventItems.query,
|
|
362
|
+
~addressSet: AddressSet.t,
|
|
361
363
|
) => promise<(EventItems.response, TransactionStore.t, BlockStore.t)>,
|
|
362
364
|
getHeight: unit => promise<int>,
|
|
363
365
|
}
|
|
364
366
|
|
|
365
367
|
@send
|
|
366
|
-
external classNew: (
|
|
367
|
-
|
|
368
|
+
external classNew: (
|
|
369
|
+
Core.evmHyperSyncClientCtor,
|
|
370
|
+
cfg,
|
|
371
|
+
string,
|
|
372
|
+
array<Registration.input>,
|
|
373
|
+
AddressStore.t,
|
|
374
|
+
) => t = "new"
|
|
368
375
|
|
|
369
|
-
let makeWithAgent = (cfg, ~userAgent, ~eventRegistrations) =>
|
|
370
|
-
Core.getAddon().evmHyperSyncClient->classNew(cfg, userAgent, eventRegistrations)
|
|
376
|
+
let makeWithAgent = (cfg, ~userAgent, ~eventRegistrations, ~addressStore) =>
|
|
377
|
+
Core.getAddon().evmHyperSyncClient->classNew(cfg, userAgent, eventRegistrations, addressStore)
|
|
371
378
|
|
|
372
379
|
type logLevel = [#trace | #debug | #info | #warn | #error]
|
|
373
380
|
let logLevelSchema: S.t<logLevel> = S.enum([#trace, #debug, #info, #warn, #error])
|
|
@@ -393,6 +400,7 @@ let make = (
|
|
|
393
400
|
~retryBackoffMs=?,
|
|
394
401
|
~retryCeilingMs=?,
|
|
395
402
|
~logLevel=#info,
|
|
403
|
+
~addressStore,
|
|
396
404
|
) => {
|
|
397
405
|
let envioVersion = Utils.EnvioPackage.value.version
|
|
398
406
|
makeWithAgent(
|
|
@@ -412,5 +420,6 @@ let make = (
|
|
|
412
420
|
},
|
|
413
421
|
~userAgent=`hyperindex/${envioVersion}`,
|
|
414
422
|
~eventRegistrations,
|
|
423
|
+
~addressStore,
|
|
415
424
|
)
|
|
416
425
|
}
|
|
@@ -73,8 +73,8 @@ let Registration = {
|
|
|
73
73
|
|
|
74
74
|
let EventItems = {};
|
|
75
75
|
|
|
76
|
-
function makeWithAgent(cfg, userAgent, eventRegistrations) {
|
|
77
|
-
return Core.getAddon().EvmHyperSyncClient.new(cfg, userAgent, eventRegistrations);
|
|
76
|
+
function makeWithAgent(cfg, userAgent, eventRegistrations, addressStore) {
|
|
77
|
+
return Core.getAddon().EvmHyperSyncClient.new(cfg, userAgent, eventRegistrations, addressStore);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
let logLevelSchema = S$RescriptSchema.$$enum([
|
|
@@ -99,7 +99,7 @@ function logLevelToString(level) {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
function make(url, apiToken, httpReqTimeoutMillis, eventRegistrations, enableChecksumAddressesOpt, serializationFormat, enableQueryCaching, retryBaseMs, retryBackoffMs, retryCeilingMs, logLevelOpt) {
|
|
102
|
+
function make(url, apiToken, httpReqTimeoutMillis, eventRegistrations, enableChecksumAddressesOpt, serializationFormat, enableQueryCaching, retryBaseMs, retryBackoffMs, retryCeilingMs, logLevelOpt, addressStore) {
|
|
103
103
|
let enableChecksumAddresses = enableChecksumAddressesOpt !== undefined ? enableChecksumAddressesOpt : true;
|
|
104
104
|
let logLevel = logLevelOpt !== undefined ? logLevelOpt : "info";
|
|
105
105
|
let envioVersion = Utils.EnvioPackage.value.version;
|
|
@@ -115,7 +115,7 @@ function make(url, apiToken, httpReqTimeoutMillis, eventRegistrations, enableChe
|
|
|
115
115
|
serializationFormat: serializationFormat,
|
|
116
116
|
enableQueryCaching: enableQueryCaching,
|
|
117
117
|
logLevel: logLevelToString(logLevel)
|
|
118
|
-
}, `hyperindex/` + envioVersion, eventRegistrations);
|
|
118
|
+
}, `hyperindex/` + envioVersion, eventRegistrations, addressStore);
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
export {
|
|
@@ -617,6 +617,8 @@ type options = {
|
|
|
617
617
|
// The chain's registrations, indexed by their sequential `index`.
|
|
618
618
|
onEventRegistrations: array<Internal.evmOnEventRegistration>,
|
|
619
619
|
lowercaseAddresses: bool,
|
|
620
|
+
// The chain's address index; the client reads it while routing.
|
|
621
|
+
addressStore: AddressStore.t,
|
|
620
622
|
ws?: string,
|
|
621
623
|
headers?: dict<string>,
|
|
622
624
|
}
|
|
@@ -629,6 +631,7 @@ let make = (
|
|
|
629
631
|
chain,
|
|
630
632
|
onEventRegistrations,
|
|
631
633
|
lowercaseAddresses,
|
|
634
|
+
addressStore,
|
|
632
635
|
?ws,
|
|
633
636
|
?headers,
|
|
634
637
|
}: options,
|
|
@@ -650,6 +653,7 @@ let make = (
|
|
|
650
653
|
~checksumAddresses=!lowercaseAddresses,
|
|
651
654
|
~syncConfig,
|
|
652
655
|
~headers?,
|
|
656
|
+
~addressStore,
|
|
653
657
|
)
|
|
654
658
|
|
|
655
659
|
// Requests are made from shared, memoized loaders, so they can't be
|
|
@@ -796,8 +800,7 @@ let make = (
|
|
|
796
800
|
let getItemsOrThrow = async (
|
|
797
801
|
~fromBlock,
|
|
798
802
|
~toBlock,
|
|
799
|
-
~
|
|
800
|
-
~contractNameByAddress as _,
|
|
803
|
+
~addressSet,
|
|
801
804
|
~knownHeight,
|
|
802
805
|
~partitionId,
|
|
803
806
|
~selection: FetchState.selection,
|
|
@@ -830,14 +833,16 @@ let make = (
|
|
|
830
833
|
)
|
|
831
834
|
}
|
|
832
835
|
|
|
833
|
-
let {items, toBlock: queriedToBlock, requestStats} = try await rpcClient.getNextPage(
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
836
|
+
let {items, toBlock: queriedToBlock, requestStats} = try await rpcClient.getNextPage(
|
|
837
|
+
{
|
|
838
|
+
fromBlock,
|
|
839
|
+
toBlockCeiling: toBlock,
|
|
840
|
+
partitionId,
|
|
841
|
+
registrationIndexes: selection.onEventRegistrations->Array.map(reg => reg.index),
|
|
842
|
+
clientFilteredContracts: selection.clientFilteredContracts,
|
|
843
|
+
},
|
|
844
|
+
addressSet,
|
|
845
|
+
) catch {
|
|
841
846
|
| exn =>
|
|
842
847
|
switch exn->parseGetNextPageRetryError {
|
|
843
848
|
| Some((attemptedToBlock, retry, requestStats)) =>
|
|
@@ -734,7 +734,7 @@ function make(param) {
|
|
|
734
734
|
let urlHost = host !== undefined ? host : Stdlib_JsError.throwWithMessage(`The RPC url for chain ` + chain.toString() + ` is in incorrect format. The RPC url needs to start with either http:// or https://`);
|
|
735
735
|
let name = `RPC (` + urlHost + `)`;
|
|
736
736
|
let client = Rpc.makeClient(url, headers);
|
|
737
|
-
let rpcClient = EvmRpcClient.make(url, !lowercaseAddresses, syncConfig, undefined, headers, HyperSyncClient.Registration.fromOnEventRegistrations(onEventRegistrations));
|
|
737
|
+
let rpcClient = EvmRpcClient.make(url, !lowercaseAddresses, syncConfig, undefined, headers, HyperSyncClient.Registration.fromOnEventRegistrations(onEventRegistrations), param.addressStore);
|
|
738
738
|
let pendingRequestStats = [];
|
|
739
739
|
let recordRequest = (method, seconds) => {
|
|
740
740
|
pendingRequestStats.push({
|
|
@@ -820,7 +820,7 @@ function make(param) {
|
|
|
820
820
|
Error: new Error()
|
|
821
821
|
};
|
|
822
822
|
}, lowercaseAddresses);
|
|
823
|
-
let getItemsOrThrow = async (fromBlock, toBlock,
|
|
823
|
+
let getItemsOrThrow = async (fromBlock, toBlock, addressSet, knownHeight, partitionId, selection, param, retry, param$1) => {
|
|
824
824
|
let startFetchingBatchTimeRef = Performance.now();
|
|
825
825
|
let toBlock$1 = toBlock !== undefined ? Primitive_int.min(toBlock, knownHeight) : knownHeight;
|
|
826
826
|
let firstBlockParentPromise = fromBlock > 0 ? LazyLoader.get(blockLoader.contents, fromBlock - 1 | 0).then(json => parseBlockInfo(json)) : Promise.resolve(undefined);
|
|
@@ -841,9 +841,8 @@ function make(param) {
|
|
|
841
841
|
toBlockCeiling: toBlock$1,
|
|
842
842
|
partitionId: partitionId,
|
|
843
843
|
registrationIndexes: selection.onEventRegistrations.map(reg => reg.index),
|
|
844
|
-
addressesByContractName: addressesByContractName,
|
|
845
844
|
clientFilteredContracts: selection.clientFilteredContracts
|
|
846
|
-
});
|
|
845
|
+
}, addressSet);
|
|
847
846
|
} catch (raw_exn) {
|
|
848
847
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
849
848
|
let match$1 = parseGetNextPageRetryError(exn);
|
|
@@ -18,8 +18,7 @@ let make = (~items: array<Internal.item>, ~endBlock: int, ~chain: ChainMap.Chain
|
|
|
18
18
|
getItemsOrThrow: (
|
|
19
19
|
~fromBlock,
|
|
20
20
|
~toBlock,
|
|
21
|
-
~
|
|
22
|
-
~contractNameByAddress,
|
|
21
|
+
~addressSet,
|
|
23
22
|
~knownHeight as _,
|
|
24
23
|
~partitionId as _,
|
|
25
24
|
~selection: FetchState.selection,
|
|
@@ -28,11 +27,11 @@ let make = (~items: array<Internal.item>, ~endBlock: int, ~chain: ChainMap.Chain
|
|
|
28
27
|
~logger as _,
|
|
29
28
|
) => {
|
|
30
29
|
// Mirror a real backend: return only the items this query would match —
|
|
31
|
-
// in the block range, part of the selection, and
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
30
|
+
// in the block range, part of the selection, and passing the same address
|
|
31
|
+
// gates a real source applies natively while routing (the emitter must be
|
|
32
|
+
// registered for the event's contract at or before the item's block, and
|
|
33
|
+
// any address-valued param filter must hold). Overlapping queries may
|
|
34
|
+
// return the same item more than once; the buffer dedups it.
|
|
36
35
|
let toBlockQueried = switch toBlock {
|
|
37
36
|
| Some(toBlock) => toBlock
|
|
38
37
|
| None => reportedHeight
|
|
@@ -49,11 +48,27 @@ let make = (~items: array<Internal.item>, ~endBlock: int, ~chain: ChainMap.Chain
|
|
|
49
48
|
false
|
|
50
49
|
} else if !(selectionEventIds->Utils.Set.has(onEventRegistration.eventConfig.id)) {
|
|
51
50
|
false
|
|
52
|
-
} else if onEventRegistration.isWildcard {
|
|
53
|
-
true
|
|
54
51
|
} else {
|
|
55
|
-
let
|
|
56
|
-
|
|
52
|
+
let contractName = onEventRegistration.eventConfig.contractName
|
|
53
|
+
let emitterAllowed =
|
|
54
|
+
onEventRegistration.isWildcard ||
|
|
55
|
+
addressSet->AddressSet.has(
|
|
56
|
+
eventItem.payload->Internal.getPayloadSrcAddress,
|
|
57
|
+
contractName,
|
|
58
|
+
blockNumber,
|
|
59
|
+
)
|
|
60
|
+
emitterAllowed &&
|
|
61
|
+
switch onEventRegistration.addressFilterParamGroups {
|
|
62
|
+
| None
|
|
63
|
+
| Some([]) => true
|
|
64
|
+
| Some(groups) =>
|
|
65
|
+
let params = eventItem.payload->Internal.getPayloadAddressParams
|
|
66
|
+
groups->Array.some(group =>
|
|
67
|
+
group->Array.every(name =>
|
|
68
|
+
addressSet->AddressSet.has(params->Dict.getUnsafe(name), contractName, blockNumber)
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
}
|
|
57
72
|
}
|
|
58
73
|
})
|
|
59
74
|
|