envio 3.5.0-alpha.0 → 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/Bin.res +2 -2
- package/src/ChainFetching.res +5 -5
- package/src/ChainFetching.res.mjs +3 -4
- package/src/ChainState.res +44 -36
- package/src/ChainState.res.mjs +36 -31
- package/src/ChainState.resi +2 -12
- package/src/Change.res +3 -3
- package/src/Config.res +4 -4
- package/src/Config.res.mjs +1 -10
- package/src/Core.res +4 -35
- package/src/Core.res.mjs +1 -31
- package/src/CrossChainState.res +2 -20
- package/src/CrossChainState.res.mjs +2 -6
- package/src/EntityId.res +15 -0
- package/src/EntityId.res.mjs +9 -0
- package/src/Env.res +16 -0
- package/src/Env.res.mjs +6 -0
- package/src/EventConfigBuilder.res +1 -58
- package/src/EventConfigBuilder.res.mjs +1 -33
- package/src/FetchState.res +663 -484
- package/src/FetchState.res.mjs +491 -440
- 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 +9 -9
- package/src/sources/EvmHyperSyncSource.res.mjs +3 -3
- package/src/sources/EvmRpcClient.res +10 -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 +9 -5
- package/src/sources/HyperSync.res.mjs +3 -3
- package/src/sources/HyperSync.resi +3 -2
- package/src/sources/HyperSyncClient.res +24 -10
- package/src/sources/HyperSyncClient.res.mjs +4 -4
- package/src/sources/RpcSource.res +71 -67
- package/src/sources/RpcSource.res.mjs +4 -4
- package/src/sources/SimulateSource.res +26 -11
- package/src/sources/SimulateSource.res.mjs +13 -5
- package/src/sources/Source.res +8 -4
- 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 +14 -4
- package/src/sources/SvmHyperSyncClient.res.mjs +2 -2
- package/src/sources/SvmHyperSyncSource.res +11 -6
- package/src/sources/SvmHyperSyncSource.res.mjs +5 -4
- package/src/IndexingAddresses.res +0 -108
- package/src/IndexingAddresses.res.mjs +0 -101
- package/src/IndexingAddresses.resi +0 -34
|
@@ -97,7 +97,6 @@ let getErrorMessage = (exn: exn): option<string> =>
|
|
|
97
97
|
| _ => None
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
|
|
101
100
|
// `EvmRpcClient.getNextPage` throws a napi error whose message is a JSON
|
|
102
101
|
// payload describing the retry decision:
|
|
103
102
|
// `{"kind":"Retry","attemptedToBlock":int,"errorMessage":string|null,
|
|
@@ -618,6 +617,8 @@ type options = {
|
|
|
618
617
|
// The chain's registrations, indexed by their sequential `index`.
|
|
619
618
|
onEventRegistrations: array<Internal.evmOnEventRegistration>,
|
|
620
619
|
lowercaseAddresses: bool,
|
|
620
|
+
// The chain's address index; the client reads it while routing.
|
|
621
|
+
addressStore: AddressStore.t,
|
|
621
622
|
ws?: string,
|
|
622
623
|
headers?: dict<string>,
|
|
623
624
|
}
|
|
@@ -630,6 +631,7 @@ let make = (
|
|
|
630
631
|
chain,
|
|
631
632
|
onEventRegistrations,
|
|
632
633
|
lowercaseAddresses,
|
|
634
|
+
addressStore,
|
|
633
635
|
?ws,
|
|
634
636
|
?headers,
|
|
635
637
|
}: options,
|
|
@@ -647,12 +649,11 @@ let make = (
|
|
|
647
649
|
let client = Rpc.makeClient(url, ~headers?)
|
|
648
650
|
let rpcClient = EvmRpcClient.make(
|
|
649
651
|
~url,
|
|
650
|
-
~eventRegistrations=HyperSyncClient.Registration.fromOnEventRegistrations(
|
|
651
|
-
onEventRegistrations,
|
|
652
|
-
),
|
|
652
|
+
~eventRegistrations=HyperSyncClient.Registration.fromOnEventRegistrations(onEventRegistrations),
|
|
653
653
|
~checksumAddresses=!lowercaseAddresses,
|
|
654
654
|
~syncConfig,
|
|
655
655
|
~headers?,
|
|
656
|
+
~addressStore,
|
|
656
657
|
)
|
|
657
658
|
|
|
658
659
|
// Requests are made from shared, memoized loaders, so they can't be
|
|
@@ -799,8 +800,7 @@ let make = (
|
|
|
799
800
|
let getItemsOrThrow = async (
|
|
800
801
|
~fromBlock,
|
|
801
802
|
~toBlock,
|
|
802
|
-
~
|
|
803
|
-
~contractNameByAddress as _,
|
|
803
|
+
~addressSet,
|
|
804
804
|
~knownHeight,
|
|
805
805
|
~partitionId,
|
|
806
806
|
~selection: FetchState.selection,
|
|
@@ -833,13 +833,16 @@ let make = (
|
|
|
833
833
|
)
|
|
834
834
|
}
|
|
835
835
|
|
|
836
|
-
let {items, toBlock: queriedToBlock, requestStats} = try await rpcClient.getNextPage(
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
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 {
|
|
843
846
|
| exn =>
|
|
844
847
|
switch exn->parseGetNextPageRetryError {
|
|
845
848
|
| Some((attemptedToBlock, retry, requestStats)) =>
|
|
@@ -879,63 +882,64 @@ let make = (
|
|
|
879
882
|
onEventRegistration.eventConfig->(
|
|
880
883
|
Utils.magic: Internal.eventConfig => Internal.evmEventConfig
|
|
881
884
|
)
|
|
885
|
+
|
|
882
886
|
(
|
|
883
887
|
async () => {
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
logIndex: log.logIndex,
|
|
917
|
-
}),
|
|
918
|
-
),
|
|
919
|
-
)
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
Internal.Event({
|
|
923
|
-
onEventRegistration: (onEventRegistration :> Internal.onEventRegistration),
|
|
924
|
-
blockNumber: block->getBlockNumber,
|
|
925
|
-
chain,
|
|
888
|
+
let (block, transaction) = try await Promise.all2((
|
|
889
|
+
log->getEventBlockOrThrow(~selectedBlockFields=eventConfig.selectedBlockFields),
|
|
890
|
+
log->getEventTransactionOrThrow(
|
|
891
|
+
~selectedTransactionFields=eventConfig.selectedTransactionFields->(
|
|
892
|
+
Utils.magic: Utils.Set.t<string> => Utils.Set.t<Internal.evmTransactionField>
|
|
893
|
+
),
|
|
894
|
+
),
|
|
895
|
+
)) catch {
|
|
896
|
+
| TransactionDataNotFound({message}) =>
|
|
897
|
+
let backoffMillis = switch retry {
|
|
898
|
+
| 0 => 100
|
|
899
|
+
| _ => 500 * retry
|
|
900
|
+
}
|
|
901
|
+
throw(
|
|
902
|
+
Source.GetItemsError(
|
|
903
|
+
FailedGettingItems({
|
|
904
|
+
exn: %raw(`null`),
|
|
905
|
+
attemptedToBlock: toBlock,
|
|
906
|
+
retry: WithBackoff({
|
|
907
|
+
message: `${message}. The RPC provider might be load-balanced between nodes that drift independently slightly from the head. Indexing should continue correctly after retrying the query in ${backoffMillis->Int.toString}ms.`,
|
|
908
|
+
backoffMillis,
|
|
909
|
+
}),
|
|
910
|
+
}),
|
|
911
|
+
),
|
|
912
|
+
)
|
|
913
|
+
| exn =>
|
|
914
|
+
throw(
|
|
915
|
+
Source.GetItemsError(
|
|
916
|
+
FailedGettingFieldSelection({
|
|
917
|
+
message: "Failed getting selected fields. Please double-check your RPC provider returns correct data.",
|
|
918
|
+
exn,
|
|
919
|
+
blockNumber: log.blockNumber,
|
|
926
920
|
logIndex: log.logIndex,
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
921
|
+
}),
|
|
922
|
+
),
|
|
923
|
+
)
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
Internal.Event({
|
|
927
|
+
onEventRegistration: (onEventRegistration :> Internal.onEventRegistration),
|
|
928
|
+
blockNumber: block->getBlockNumber,
|
|
929
|
+
chain,
|
|
930
|
+
logIndex: log.logIndex,
|
|
931
|
+
transactionIndex: log.transactionIndex,
|
|
932
|
+
payload: {
|
|
933
|
+
contractName: eventConfig.contractName,
|
|
934
|
+
eventName: eventConfig.name,
|
|
935
|
+
chainId: chain->ChainMap.Chain.toChainId,
|
|
936
|
+
params: decoded,
|
|
937
|
+
block,
|
|
938
|
+
transaction,
|
|
939
|
+
srcAddress: log.address,
|
|
940
|
+
logIndex: log.logIndex,
|
|
941
|
+
}->Evm.fromPayload,
|
|
942
|
+
})
|
|
939
943
|
}
|
|
940
944
|
)()
|
|
941
945
|
})
|
|
@@ -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,8 +841,8 @@ function make(param) {
|
|
|
841
841
|
toBlockCeiling: toBlock$1,
|
|
842
842
|
partitionId: partitionId,
|
|
843
843
|
registrationIndexes: selection.onEventRegistrations.map(reg => reg.index),
|
|
844
|
-
|
|
845
|
-
});
|
|
844
|
+
clientFilteredContracts: selection.clientFilteredContracts
|
|
845
|
+
}, addressSet);
|
|
846
846
|
} catch (raw_exn) {
|
|
847
847
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
848
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,
|
|
@@ -82,8 +84,10 @@ type t = {
|
|
|
82
84
|
// source should ask its backend for, from the query's own estResponseSize.
|
|
83
85
|
// A HyperSync-backed source enforces it server-side, so a wrong estimate
|
|
84
86
|
// truncates the response instead of overshooting the shared buffer. Sources
|
|
85
|
-
// without an equivalent lever (RPC, Fuel, Simulate) ignore it.
|
|
86
|
-
|
|
87
|
+
// without an equivalent lever (RPC, Fuel, Simulate) ignore it. None means no
|
|
88
|
+
// cap: bounded chunk queries fetch their whole range even if denser than
|
|
89
|
+
// expected, so client-side-filtered items can't truncate the range short.
|
|
90
|
+
~itemsTarget: option<int>,
|
|
87
91
|
~retry: int,
|
|
88
92
|
~logger: Pino.t,
|
|
89
93
|
) => promise<blockRangeFetchResponse>,
|
|
@@ -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
|
|
|
@@ -188,9 +188,13 @@ module EventItems = {
|
|
|
188
188
|
fromSlot: int,
|
|
189
189
|
// Inclusive; None queries to the end of available data.
|
|
190
190
|
toSlot: option<int>,
|
|
191
|
-
|
|
191
|
+
// Absent means no server-side cap on the number of instructions returned.
|
|
192
|
+
maxNumInstructions?: int,
|
|
192
193
|
registrationIndexes: array<int>,
|
|
193
|
-
|
|
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>>,
|
|
194
198
|
}
|
|
195
199
|
|
|
196
200
|
type log = {
|
|
@@ -220,8 +224,10 @@ module EventItems = {
|
|
|
220
224
|
|
|
221
225
|
type response = {
|
|
222
226
|
nextSlot: int,
|
|
223
|
-
// One lean header per slot
|
|
224
|
-
// 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.
|
|
225
231
|
blocks: array<ResponseTypes.block>,
|
|
226
232
|
items: array<item>,
|
|
227
233
|
}
|
|
@@ -239,6 +245,7 @@ type t = {
|
|
|
239
245
|
// prep.
|
|
240
246
|
getEventItems: (
|
|
241
247
|
~query: EventItems.query,
|
|
248
|
+
~addressSet: AddressSet.t,
|
|
242
249
|
) => promise<(EventItems.response, TransactionStore.t, BlockStore.t)>,
|
|
243
250
|
}
|
|
244
251
|
|
|
@@ -248,6 +255,7 @@ external classFromConfig: (
|
|
|
248
255
|
cfg,
|
|
249
256
|
string,
|
|
250
257
|
array<Registration.input>,
|
|
258
|
+
AddressStore.t,
|
|
251
259
|
) => t = "fromConfig"
|
|
252
260
|
|
|
253
261
|
let make = (
|
|
@@ -258,6 +266,7 @@ let make = (
|
|
|
258
266
|
~retryBaseMs=?,
|
|
259
267
|
~retryCeilingMs=?,
|
|
260
268
|
~eventRegistrations=[],
|
|
269
|
+
~addressStore,
|
|
261
270
|
) => {
|
|
262
271
|
let envioVersion = Utils.EnvioPackage.value.version
|
|
263
272
|
Core.getAddon().svmHyperSyncClient->classFromConfig(
|
|
@@ -271,5 +280,6 @@ let make = (
|
|
|
271
280
|
},
|
|
272
281
|
`hyperindex/${envioVersion}`,
|
|
273
282
|
eventRegistrations,
|
|
283
|
+
addressStore,
|
|
274
284
|
)
|
|
275
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,
|
|
@@ -100,12 +102,15 @@ let make = (
|
|
|
100
102
|
let query: SvmHyperSyncClient.EventItems.query = {
|
|
101
103
|
fromSlot: fromBlock,
|
|
102
104
|
toSlot: toBlock,
|
|
103
|
-
maxNumInstructions: itemsTarget,
|
|
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 {
|