envio 3.5.0-alpha.1 → 3.5.0-alpha.3
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 +27 -0
- package/src/BatchProcessing.res.mjs +12 -0
- package/src/ChainFetching.res +5 -5
- package/src/ChainFetching.res.mjs +3 -4
- package/src/ChainState.res +48 -25
- package/src/ChainState.res.mjs +23 -29
- package/src/ChainState.resi +2 -6
- package/src/Change.res +3 -3
- package/src/Config.res +2 -6
- package/src/Config.res.mjs +2 -12
- package/src/Core.res +3 -0
- package/src/CrossChainState.res +33 -10
- package/src/CrossChainState.res.mjs +21 -6
- package/src/CrossChainState.resi +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 +510 -460
- package/src/FetchState.res.mjs +413 -428
- package/src/FinalizeBackfill.res +34 -0
- package/src/FinalizeBackfill.res.mjs +26 -0
- package/src/HandlerRegister.res +45 -0
- package/src/HandlerRegister.res.mjs +43 -0
- package/src/InMemoryStore.res +11 -4
- package/src/InMemoryTable.res +26 -24
- package/src/InMemoryTable.res.mjs +19 -18
- package/src/IndexerState.res +71 -2
- package/src/IndexerState.res.mjs +67 -3
- package/src/IndexerState.resi +5 -0
- package/src/Internal.res +17 -8
- package/src/LoadLayer.res +9 -1
- package/src/LoadLayer.res.mjs +1 -0
- package/src/LogSelection.res +2 -1
- package/src/Metrics.res +37 -6
- package/src/Metrics.res.mjs +5 -1
- package/src/Persistence.res +12 -1
- package/src/PgStorage.res +411 -57
- package/src/PgStorage.res.mjs +262 -41
- package/src/SimulateItems.res +2 -2
- package/src/TestIndexer.res +9 -5
- package/src/TestIndexer.res.mjs +5 -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/EntityFilter.res +0 -4
- package/src/db/EntityFilter.res.mjs +1 -8
- package/src/db/EntityHistory.res +16 -7
- package/src/db/EntityHistory.res.mjs +7 -6
- package/src/db/IndexRegistry.res +219 -0
- package/src/db/IndexRegistry.res.mjs +195 -0
- package/src/db/InternalTable.res +7 -0
- package/src/db/InternalTable.res.mjs +7 -0
- package/src/db/Table.res +53 -22
- package/src/db/Table.res.mjs +56 -18
- 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
|
@@ -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
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
|
|
4
|
-
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
5
4
|
|
|
6
5
|
function make(items, endBlock, chain) {
|
|
7
6
|
let reportedHeight = Primitive_int.max(endBlock, 1);
|
|
@@ -22,7 +21,7 @@ function make(items, endBlock, chain) {
|
|
|
22
21
|
height: reportedHeight,
|
|
23
22
|
requestStats: []
|
|
24
23
|
}),
|
|
25
|
-
getItemsOrThrow: (fromBlock, toBlock,
|
|
24
|
+
getItemsOrThrow: (fromBlock, toBlock, addressSet, param, param$1, selection, param$2, param$3, param$4) => {
|
|
26
25
|
let toBlockQueried = toBlock !== undefined ? toBlock : reportedHeight;
|
|
27
26
|
let selectionEventIds = new Set();
|
|
28
27
|
selection.onEventRegistrations.forEach(reg => {
|
|
@@ -37,11 +36,20 @@ function make(items, endBlock, chain) {
|
|
|
37
36
|
if (!selectionEventIds.has(onEventRegistration.eventConfig.id)) {
|
|
38
37
|
return false;
|
|
39
38
|
}
|
|
40
|
-
|
|
39
|
+
let contractName = onEventRegistration.eventConfig.contractName;
|
|
40
|
+
let emitterAllowed = onEventRegistration.isWildcard || addressSet.has(item.payload.srcAddress, contractName, blockNumber);
|
|
41
|
+
if (!emitterAllowed) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
let groups = onEventRegistration.addressFilterParamGroups;
|
|
45
|
+
if (groups === undefined) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
if (groups.length === 0) {
|
|
41
49
|
return true;
|
|
42
50
|
}
|
|
43
|
-
let
|
|
44
|
-
return
|
|
51
|
+
let params = item.payload.params;
|
|
52
|
+
return groups.some(group => group.every(name => addressSet.has(params[name], contractName, blockNumber)));
|
|
45
53
|
});
|
|
46
54
|
return Promise.resolve({
|
|
47
55
|
knownHeight: reportedHeight,
|
package/src/sources/Source.res
CHANGED
|
@@ -73,8 +73,10 @@ type t = {
|
|
|
73
73
|
getItemsOrThrow: (
|
|
74
74
|
~fromBlock: int,
|
|
75
75
|
~toBlock: option<int>,
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
// The partition's slice of the chain's address index. The source hands it
|
|
77
|
+
// straight to its Rust client, which builds the query's address filter from
|
|
78
|
+
// it and gates every returned item against the chain-wide store.
|
|
79
|
+
~addressSet: AddressSet.t,
|
|
78
80
|
~knownHeight: int,
|
|
79
81
|
~partitionId: string,
|
|
80
82
|
~selection: FetchState.selection,
|
|
@@ -754,7 +754,7 @@ let executeQuery = async (
|
|
|
754
754
|
"source": source.name,
|
|
755
755
|
"fromBlock": query.fromBlock,
|
|
756
756
|
"toBlock": toBlock,
|
|
757
|
-
"addresses": query.
|
|
757
|
+
"addresses": query.addresses->AddressSet.size,
|
|
758
758
|
"retry": retry,
|
|
759
759
|
},
|
|
760
760
|
)
|
|
@@ -763,8 +763,7 @@ let executeQuery = async (
|
|
|
763
763
|
let response = await source.getItemsOrThrow(
|
|
764
764
|
~fromBlock=query.fromBlock,
|
|
765
765
|
~toBlock,
|
|
766
|
-
~
|
|
767
|
-
~contractNameByAddress=query.addressesByContractName->FetchState.deriveContractNameByAddress,
|
|
766
|
+
~addressSet=query.addresses,
|
|
768
767
|
~partitionId=query.partitionId,
|
|
769
768
|
~knownHeight,
|
|
770
769
|
~selection=query.selection,
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import * as Utils from "../Utils.res.mjs";
|
|
4
4
|
import * as Source from "./Source.res.mjs";
|
|
5
5
|
import * as Logging from "../Logging.res.mjs";
|
|
6
|
-
import * as FetchState from "../FetchState.res.mjs";
|
|
7
6
|
import * as Performance from "../bindings/Performance.res.mjs";
|
|
8
7
|
import * as ErrorHandling from "../ErrorHandling.res.mjs";
|
|
9
8
|
import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
|
|
@@ -597,11 +596,11 @@ async function executeQuery(sourceManager, query, knownHeight, isRealtime) {
|
|
|
597
596
|
source: source.name,
|
|
598
597
|
fromBlock: query.fromBlock,
|
|
599
598
|
toBlock: toBlock,
|
|
600
|
-
addresses:
|
|
599
|
+
addresses: query.addresses.size(),
|
|
601
600
|
retry: retry
|
|
602
601
|
});
|
|
603
602
|
try {
|
|
604
|
-
let response = await source.getItemsOrThrow(query.fromBlock, toBlock, query.
|
|
603
|
+
let response = await source.getItemsOrThrow(query.fromBlock, toBlock, query.addresses, knownHeight, query.partitionId, query.selection, query.itemsTarget, retry, logger$2);
|
|
605
604
|
recordRequestStats(sourceState, response.requestStats);
|
|
606
605
|
sourceState.lastFailedAt = undefined;
|
|
607
606
|
if (response.knownHeight > sourceState.knownHeight) {
|
package/src/sources/Svm.res
CHANGED
|
@@ -100,8 +100,7 @@ let makeRPCSource = (~chain, ~rpc: string, ~sourceFor: Source.sourceFor=Sync): S
|
|
|
100
100
|
getItemsOrThrow: (
|
|
101
101
|
~fromBlock as _,
|
|
102
102
|
~toBlock as _,
|
|
103
|
-
~
|
|
104
|
-
~contractNameByAddress as _,
|
|
103
|
+
~addressSet as _,
|
|
105
104
|
~knownHeight as _,
|
|
106
105
|
~partitionId as _,
|
|
107
106
|
~selection as _,
|
package/src/sources/Svm.res.mjs
CHANGED
|
@@ -91,7 +91,7 @@ function makeRPCSource(chain, rpc, sourceForOpt) {
|
|
|
91
91
|
}]
|
|
92
92
|
};
|
|
93
93
|
},
|
|
94
|
-
getItemsOrThrow: (param, param$1, param$2, param$3, param$4, param$5, param$6, param$7, param$8
|
|
94
|
+
getItemsOrThrow: (param, param$1, param$2, param$3, param$4, param$5, param$6, param$7, param$8) => Stdlib_JsError.throwWithMessage("Svm does not support getting items")
|
|
95
95
|
};
|
|
96
96
|
}
|
|
97
97
|
|
|
@@ -191,7 +191,10 @@ module EventItems = {
|
|
|
191
191
|
// Absent means no server-side cap on the number of instructions returned.
|
|
192
192
|
maxNumInstructions?: int,
|
|
193
193
|
registrationIndexes: array<int>,
|
|
194
|
-
|
|
194
|
+
// Program names to fetch address-free even though their registrations
|
|
195
|
+
// depend on addresses (client-side filtering). None/empty means every
|
|
196
|
+
// address-dependent program is filtered server-side.
|
|
197
|
+
clientFilteredContracts: option<array<string>>,
|
|
195
198
|
}
|
|
196
199
|
|
|
197
200
|
type log = {
|
|
@@ -221,8 +224,10 @@ module EventItems = {
|
|
|
221
224
|
|
|
222
225
|
type response = {
|
|
223
226
|
nextSlot: int,
|
|
224
|
-
// One lean header per slot
|
|
225
|
-
// the
|
|
227
|
+
// One lean header per returned slot, including slots no item references —
|
|
228
|
+
// reorg detection and the batch's latest timestamp read them all. The full
|
|
229
|
+
// blocks live in the block store returned alongside, which keeps only the
|
|
230
|
+
// slots items reference.
|
|
226
231
|
blocks: array<ResponseTypes.block>,
|
|
227
232
|
items: array<item>,
|
|
228
233
|
}
|
|
@@ -240,6 +245,7 @@ type t = {
|
|
|
240
245
|
// prep.
|
|
241
246
|
getEventItems: (
|
|
242
247
|
~query: EventItems.query,
|
|
248
|
+
~addressSet: AddressSet.t,
|
|
243
249
|
) => promise<(EventItems.response, TransactionStore.t, BlockStore.t)>,
|
|
244
250
|
}
|
|
245
251
|
|
|
@@ -249,6 +255,7 @@ external classFromConfig: (
|
|
|
249
255
|
cfg,
|
|
250
256
|
string,
|
|
251
257
|
array<Registration.input>,
|
|
258
|
+
AddressStore.t,
|
|
252
259
|
) => t = "fromConfig"
|
|
253
260
|
|
|
254
261
|
let make = (
|
|
@@ -259,6 +266,7 @@ let make = (
|
|
|
259
266
|
~retryBaseMs=?,
|
|
260
267
|
~retryCeilingMs=?,
|
|
261
268
|
~eventRegistrations=[],
|
|
269
|
+
~addressStore,
|
|
262
270
|
) => {
|
|
263
271
|
let envioVersion = Utils.EnvioPackage.value.version
|
|
264
272
|
Core.getAddon().svmHyperSyncClient->classFromConfig(
|
|
@@ -272,5 +280,6 @@ let make = (
|
|
|
272
280
|
},
|
|
273
281
|
`hyperindex/${envioVersion}`,
|
|
274
282
|
eventRegistrations,
|
|
283
|
+
addressStore,
|
|
275
284
|
)
|
|
276
285
|
}
|
|
@@ -45,7 +45,7 @@ let ResponseTypes = {};
|
|
|
45
45
|
|
|
46
46
|
let EventItems = {};
|
|
47
47
|
|
|
48
|
-
function make(url, apiToken, httpReqTimeoutMillis, maxNumRetries, retryBaseMs, retryCeilingMs, eventRegistrationsOpt) {
|
|
48
|
+
function make(url, apiToken, httpReqTimeoutMillis, maxNumRetries, retryBaseMs, retryCeilingMs, eventRegistrationsOpt, addressStore) {
|
|
49
49
|
let eventRegistrations = eventRegistrationsOpt !== undefined ? eventRegistrationsOpt : [];
|
|
50
50
|
let envioVersion = Utils.EnvioPackage.value.version;
|
|
51
51
|
return Core.getAddon().SvmHyperSyncClient.fromConfig({
|
|
@@ -55,7 +55,7 @@ function make(url, apiToken, httpReqTimeoutMillis, maxNumRetries, retryBaseMs, r
|
|
|
55
55
|
maxNumRetries: maxNumRetries,
|
|
56
56
|
retryBaseMs: retryBaseMs,
|
|
57
57
|
retryCeilingMs: retryCeilingMs
|
|
58
|
-
}, `hyperindex/` + envioVersion, eventRegistrations);
|
|
58
|
+
}, `hyperindex/` + envioVersion, eventRegistrations, addressStore);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
export {
|
|
@@ -6,6 +6,8 @@ type options = {
|
|
|
6
6
|
apiToken: option<string>,
|
|
7
7
|
onEventRegistrations: array<Internal.svmOnEventRegistration>,
|
|
8
8
|
clientTimeoutMillis: int,
|
|
9
|
+
// The chain's address index; the client reads it while routing.
|
|
10
|
+
addressStore: AddressStore.t,
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
// Synthesize a stable logIndex for an SVM instruction so the FetchState
|
|
@@ -66,7 +68,7 @@ let toSvmInstruction = (
|
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
let make = (
|
|
69
|
-
{chain, endpointUrl, apiToken, onEventRegistrations, clientTimeoutMillis}: options,
|
|
71
|
+
{chain, endpointUrl, apiToken, onEventRegistrations, clientTimeoutMillis, addressStore}: options,
|
|
70
72
|
): t => {
|
|
71
73
|
let name = "SvmHyperSync"
|
|
72
74
|
|
|
@@ -80,13 +82,13 @@ let make = (
|
|
|
80
82
|
~eventRegistrations=SvmHyperSyncClient.Registration.fromOnEventRegistrations(
|
|
81
83
|
onEventRegistrations,
|
|
82
84
|
),
|
|
85
|
+
~addressStore,
|
|
83
86
|
)
|
|
84
87
|
|
|
85
88
|
let getItemsOrThrow = async (
|
|
86
89
|
~fromBlock,
|
|
87
90
|
~toBlock,
|
|
88
|
-
~
|
|
89
|
-
~contractNameByAddress as _,
|
|
91
|
+
~addressSet,
|
|
90
92
|
~knownHeight,
|
|
91
93
|
~partitionId as _,
|
|
92
94
|
~selection: FetchState.selection,
|
|
@@ -102,10 +104,13 @@ let make = (
|
|
|
102
104
|
toSlot: toBlock,
|
|
103
105
|
maxNumInstructions: ?itemsTarget,
|
|
104
106
|
registrationIndexes: selection.onEventRegistrations->Array.map(reg => reg.index),
|
|
105
|
-
|
|
107
|
+
clientFilteredContracts: selection.clientFilteredContracts,
|
|
106
108
|
}
|
|
107
109
|
|
|
108
|
-
let (resp, transactionStore, blockStore) = try await client.getEventItems(
|
|
110
|
+
let (resp, transactionStore, blockStore) = try await client.getEventItems(
|
|
111
|
+
~query,
|
|
112
|
+
~addressSet,
|
|
113
|
+
) catch {
|
|
109
114
|
| exn =>
|
|
110
115
|
throw(
|
|
111
116
|
Source.GetItemsError(
|
|
@@ -58,21 +58,22 @@ function toSvmInstruction(item, programName, instructionName) {
|
|
|
58
58
|
function make(param) {
|
|
59
59
|
let onEventRegistrations = param.onEventRegistrations;
|
|
60
60
|
let chain = param.chain;
|
|
61
|
-
let client = SvmHyperSyncClient.make(param.endpointUrl, param.apiToken, param.clientTimeoutMillis, undefined, undefined, undefined, SvmHyperSyncClient.Registration.fromOnEventRegistrations(onEventRegistrations));
|
|
62
|
-
let getItemsOrThrow = async (fromBlock, toBlock,
|
|
61
|
+
let client = SvmHyperSyncClient.make(param.endpointUrl, param.apiToken, param.clientTimeoutMillis, undefined, undefined, undefined, SvmHyperSyncClient.Registration.fromOnEventRegistrations(onEventRegistrations), param.addressStore);
|
|
62
|
+
let getItemsOrThrow = async (fromBlock, toBlock, addressSet, knownHeight, param, selection, itemsTarget, retry, param$1) => {
|
|
63
63
|
let totalTimeRef = Performance.now();
|
|
64
64
|
let pageFetchRef = Performance.now();
|
|
65
65
|
let query_registrationIndexes = selection.onEventRegistrations.map(reg => reg.index);
|
|
66
|
+
let query_clientFilteredContracts = selection.clientFilteredContracts;
|
|
66
67
|
let query = {
|
|
67
68
|
fromSlot: fromBlock,
|
|
68
69
|
toSlot: toBlock,
|
|
69
70
|
maxNumInstructions: itemsTarget,
|
|
70
71
|
registrationIndexes: query_registrationIndexes,
|
|
71
|
-
|
|
72
|
+
clientFilteredContracts: query_clientFilteredContracts
|
|
72
73
|
};
|
|
73
74
|
let match;
|
|
74
75
|
try {
|
|
75
|
-
match = await client.getEventItems(query);
|
|
76
|
+
match = await client.getEventItems(query, addressSet);
|
|
76
77
|
} catch (raw_exn) {
|
|
77
78
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
78
79
|
throw {
|