envio 3.15.0 → 3.16.0-subgraph
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/README.md +40 -34
- package/evm.schema.json +11 -2
- package/fuel.schema.json +10 -1
- package/index.d.ts +6 -0
- package/licenses/README.md +1 -1
- package/package.json +10 -9
- package/src/Batch.res.mjs +5 -5
- package/src/BatchProcessing.res +1 -0
- package/src/BatchProcessing.res.mjs +1 -0
- package/src/Bin.res +7 -0
- package/src/Bin.res.mjs +8 -0
- package/src/ChainFetching.res +450 -16
- package/src/ChainFetching.res.mjs +403 -32
- package/src/ChainState.res +124 -7
- package/src/ChainState.res.mjs +128 -67
- package/src/ChainState.resi +26 -0
- package/src/Clock.res +57 -0
- package/src/Clock.res.mjs +72 -0
- package/src/Config.res +31 -3
- package/src/Config.res.mjs +15 -4
- package/src/ContractRegisterContext.res +3 -6
- package/src/ContractRegisterContext.res.mjs +4 -2
- package/src/Core.res +95 -36
- package/src/Core.res.mjs +90 -1
- package/src/CrossChainState.res +12 -2
- package/src/CrossChainState.res.mjs +3 -3
- package/src/Ecosystem.res +7 -4
- package/src/Ecosystem.res.mjs +8 -8
- package/src/EffectCacheLookup.res +98 -0
- package/src/EffectCacheLookup.res.mjs +116 -0
- package/src/EffectState.res +10 -2
- package/src/EffectState.res.mjs +8 -4
- package/src/EffectState.resi +3 -1
- package/src/EntityId.res +2 -7
- package/src/EntityId.res.mjs +1 -8
- package/src/EntityTables.res +4 -1
- package/src/EntityTables.res.mjs +1 -1
- package/src/Env.res +20 -0
- package/src/Env.res.mjs +16 -0
- package/src/EventProcessing.res +38 -1
- package/src/EventProcessing.res.mjs +28 -1
- package/src/FetchState.res +408 -73
- package/src/FetchState.res.mjs +361 -91
- package/src/FinalizeBackfill.res +2 -4
- package/src/FinalizeBackfill.res.mjs +3 -4
- package/src/HandlerLoader.res +39 -15
- package/src/HandlerLoader.res.mjs +27 -8
- package/src/HandlerRegister.res +4 -0
- package/src/HandlerRegister.res.mjs +5 -2
- package/src/HandlerRegister.resi +2 -0
- package/src/InMemoryTable.res +17 -16
- package/src/InMemoryTable.res.mjs +14 -15
- package/src/IndexerState.res +28 -4
- package/src/IndexerState.res.mjs +19 -6
- package/src/IndexerState.resi +4 -0
- package/src/Internal.res +61 -49
- package/src/Internal.res.mjs +36 -80
- package/src/LoadLayer.res +54 -15
- package/src/LoadLayer.res.mjs +75 -45
- package/src/LoadLayer.resi +26 -0
- package/src/Main.res +14 -1
- package/src/Main.res.mjs +4 -3
- package/src/Persistence.res +3 -23
- package/src/Persistence.res.mjs +3 -3
- package/src/PreloadLookahead.res +202 -0
- package/src/PreloadLookahead.res.mjs +218 -0
- package/src/Rollback.res +0 -1
- package/src/Rollback.res.mjs +1 -1
- package/src/RunScope.res +3 -0
- package/src/SafeCheckpointTracking.res +4 -4
- package/src/SafeCheckpointTracking.res.mjs +1 -1
- package/src/SimulateItems.res +42 -26
- package/src/SimulateItems.res.mjs +40 -16
- package/src/StagedRows.res +106 -0
- package/src/StagedRows.res.mjs +102 -0
- package/src/Staging.res +32 -14
- package/src/Staging.res.mjs +17 -20
- package/src/Storage.res +303 -948
- package/src/Storage.res.mjs +229 -708
- package/src/SubgraphLog.res +19 -0
- package/src/SubgraphLog.res.mjs +26 -0
- package/src/Supervisor.res +75 -56
- package/src/Supervisor.res.mjs +55 -26
- package/src/SyncWrites.res +107 -0
- package/src/SyncWrites.res.mjs +98 -0
- package/src/TestIndexer.res +22 -27
- package/src/TestIndexer.res.mjs +20 -17
- package/src/Throttler.res +15 -8
- package/src/Throttler.res.mjs +9 -6
- package/src/Throttler.resi +1 -1
- package/src/UserContext.res +419 -46
- package/src/UserContext.res.mjs +318 -30
- package/src/Utils.res +17 -6
- package/src/Utils.res.mjs +12 -6
- package/src/Writing.res +0 -1
- package/src/Writing.res.mjs +1 -1
- package/src/bindings/ClickHouse.res +0 -322
- package/src/bindings/ClickHouse.res.mjs +0 -338
- package/src/bindings/StorageClient.res +108 -174
- package/src/bindings/StorageClient.res.mjs +19 -8
- package/src/bindings/Vitest.res +0 -26
- package/src/bindings/Vitest.res.mjs +0 -3
- package/src/db/Table.res +24 -150
- package/src/db/Table.res.mjs +38 -272
- package/src/sources/AddressSet.res +2 -0
- package/src/sources/AddressStore.res +3 -0
- package/src/sources/CallSource.res +274 -0
- package/src/sources/CallSource.res.mjs +196 -0
- package/src/sources/ChainSources.res +2 -0
- package/src/sources/ChainSources.res.mjs +2 -2
- package/src/sources/EvmChain.res +10 -1
- package/src/sources/EvmChain.res.mjs +6 -3
- package/src/sources/EvmHyperSyncSource.res +2 -2
- package/src/sources/EvmHyperSyncSource.res.mjs +1 -1
- package/src/sources/EvmRpcClient.res +13 -3
- package/src/sources/EvmRpcClient.res.mjs +4 -3
- package/src/sources/EvmRpcWs.res +4 -3
- package/src/sources/EvmRpcWs.res.mjs +2 -2
- package/src/sources/HeightFeed.res +31 -10
- package/src/sources/HeightFeed.res.mjs +10 -6
- package/src/sources/HeightStream.res +32 -17
- package/src/sources/HeightStream.res.mjs +10 -10
- package/src/sources/HyperSync.res +2 -1
- package/src/sources/HyperSync.res.mjs +2 -1
- package/src/sources/HyperSyncSSE.res +4 -6
- package/src/sources/HyperSyncSSE.res.mjs +2 -2
- package/src/sources/RpcSource.res +10 -1
- package/src/sources/RpcSource.res.mjs +4 -3
- package/src/sources/Source.res +3 -0
- package/src/sources/SourceManager.res +84 -77
- package/src/sources/SourceManager.res.mjs +17 -20
- package/src/sources/SourceManager.resi +3 -4
- package/src/sources/StartBlockResolver.res +1 -0
- package/src/sources/StartBlockResolver.res.mjs +3 -2
- package/src/sources/SvmHyperSyncSource.res +2 -2
- package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
- package/src/subgraph/abi-types.ts +84 -0
- package/src/subgraph/aggregations.ts +745 -0
- package/src/subgraph/as-package.ts +143 -0
- package/src/subgraph/assemblyscript-regex.ts +67 -0
- package/src/subgraph/assemblyscript.ts +731 -0
- package/src/subgraph/blocks.ts +398 -0
- package/src/subgraph/calls-source.ts +702 -0
- package/src/subgraph/calls.ts +258 -0
- package/src/subgraph/conformance.ts +106 -0
- package/src/subgraph/errors.ts +85 -0
- package/src/subgraph/graft.ts +73 -0
- package/src/subgraph/graph-cli-worker.mjs +35 -0
- package/src/subgraph/graph-cli.ts +900 -0
- package/src/subgraph/graph-node-decimal.ts +199 -0
- package/src/subgraph/graph-ts-enums.ts +28 -0
- package/src/subgraph/graph-ts-types/VERSION +2 -0
- package/src/subgraph/graph-ts-types/chain/arweave.d.ts +70 -0
- package/src/subgraph/graph-ts-types/chain/cosmos.d.ts +327 -0
- package/src/subgraph/graph-ts-types/chain/ethereum.d.ts +233 -0
- package/src/subgraph/graph-ts-types/chain/near.d.ts +253 -0
- package/src/subgraph/graph-ts-types/chain/starknet.d.ts +32 -0
- package/src/subgraph/graph-ts-types/common/collections.d.ts +136 -0
- package/src/subgraph/graph-ts-types/common/conversion.d.ts +11 -0
- package/src/subgraph/graph-ts-types/common/datasource.d.ts +30 -0
- package/src/subgraph/graph-ts-types/common/eager-offset.d.ts +0 -0
- package/src/subgraph/graph-ts-types/common/json.d.ts +17 -0
- package/src/subgraph/graph-ts-types/common/numbers.d.ts +120 -0
- package/src/subgraph/graph-ts-types/common/value.d.ts +120 -0
- package/src/subgraph/graph-ts-types/common/yaml.d.ts +90 -0
- package/src/subgraph/graph-ts-types/global/global.d.ts +194 -0
- package/src/subgraph/graph-ts-types/helper-functions.d.ts +22 -0
- package/src/subgraph/graph-ts-types/index.d.ts +102 -0
- package/src/subgraph/graph-ts.ts +4339 -0
- package/src/subgraph/hosts.ts +554 -0
- package/src/subgraph/log.ts +28 -0
- package/src/subgraph/receipts.ts +184 -0
- package/src/subgraph/register-slots.ts +93 -0
- package/src/subgraph/rollup.ts +109 -0
- package/src/subgraph/rpc.ts +337 -0
- package/src/subgraph/runtime.ts +2059 -0
- package/src/subgraph/scope.ts +176 -0
- package/src/subgraph/stats.ts +42 -0
- package/src/subgraph/template-instances.ts +66 -0
- package/src/subgraph/toolchain.ts +327 -0
- package/src/subgraph/transient.ts +176 -0
- package/svm.schema.json +11 -2
- package/src/PgWriting.res +0 -36
- package/src/PgWriting.res.mjs +0 -34
- package/src/db/IndexDefinition.res +0 -47
- package/src/db/IndexDefinition.res.mjs +0 -67
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
// Subgraph mode only. A subgraph's call handlers run on calls, which a log
|
|
2
|
+
// source never sees, so each source of a chain is wrapped: it fetches the logs
|
|
3
|
+
// of a query as before, and the calls of the same block range from a trace
|
|
4
|
+
// backend (`subgraph/calls-source.ts`). A call comes back as the event item it
|
|
5
|
+
// travels as for the rest of envio — partitioning, ordering, the register
|
|
6
|
+
// pass and rollback never tell it from a log.
|
|
7
|
+
|
|
8
|
+
type callRegistration = {
|
|
9
|
+
index: int,
|
|
10
|
+
contractName: string,
|
|
11
|
+
eventName: string,
|
|
12
|
+
selector: Nullable.t<string>,
|
|
13
|
+
rank: int,
|
|
14
|
+
isWildcard: bool,
|
|
15
|
+
startBlock: Nullable.t<int>,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type request = {
|
|
19
|
+
chainId: ChainId.t,
|
|
20
|
+
fromBlock: int,
|
|
21
|
+
toBlock: int,
|
|
22
|
+
registrations: array<callRegistration>,
|
|
23
|
+
addresses: dict<array<string>>,
|
|
24
|
+
rpcUrls: array<string>,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
type callItem = {
|
|
28
|
+
registrationIndex: int,
|
|
29
|
+
blockNumber: int,
|
|
30
|
+
transactionIndex: int,
|
|
31
|
+
traceAddress: array<int>,
|
|
32
|
+
payload: Internal.eventPayload,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type response = {
|
|
36
|
+
items: array<callItem>,
|
|
37
|
+
latestFetchedBlockNumber: int,
|
|
38
|
+
blocks: array<BlockStore.inputBlock>,
|
|
39
|
+
knownHeight: Nullable.t<int>,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
type installed = {
|
|
43
|
+
fetchCalls: request => promise<response>,
|
|
44
|
+
rpcUrls: array<string>,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let installed: ref<option<installed>> = ref(None)
|
|
48
|
+
|
|
49
|
+
let install = (~fetchCalls, ~rpcUrls) => {
|
|
50
|
+
installed := Some({fetchCalls, rpcUrls})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// The block range one call query covers when the partition's own is open-ended.
|
|
54
|
+
let openEndedSpan = 1_000_000
|
|
55
|
+
|
|
56
|
+
let callRankOf = (registration: Internal.onEventRegistration) =>
|
|
57
|
+
Internal.callRankOfEventName(registration.eventConfig.name)
|
|
58
|
+
|
|
59
|
+
// `__envio_call_<8 hex digits>_<function>`
|
|
60
|
+
let selectorOf = (registration: Internal.onEventRegistration) =>
|
|
61
|
+
switch registration->callRankOf {
|
|
62
|
+
| Some(1) =>
|
|
63
|
+
Nullable.Value(
|
|
64
|
+
"0x" ++ registration.eventConfig.name->String.slice(~start=13, ~end=21)->String.toLowerCase,
|
|
65
|
+
)
|
|
66
|
+
| _ => Nullable.null
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let wrap = (
|
|
70
|
+
source: Source.t,
|
|
71
|
+
~addressStore: AddressStore.t,
|
|
72
|
+
~ecosystem: Ecosystem.name,
|
|
73
|
+
installed: installed,
|
|
74
|
+
): Source.t => {
|
|
75
|
+
...source,
|
|
76
|
+
getItemsOrThrow: async (
|
|
77
|
+
~fromBlock,
|
|
78
|
+
~toBlock,
|
|
79
|
+
~addressSet,
|
|
80
|
+
~reorgableFrom,
|
|
81
|
+
~knownHeight,
|
|
82
|
+
~partitionId,
|
|
83
|
+
~selection: FetchState.selection,
|
|
84
|
+
~itemsTarget,
|
|
85
|
+
~retry,
|
|
86
|
+
~logger,
|
|
87
|
+
) => {
|
|
88
|
+
let callRegistrations =
|
|
89
|
+
selection.onEventRegistrations->Array.filter(registration =>
|
|
90
|
+
registration->callRankOf->Option.isSome
|
|
91
|
+
)
|
|
92
|
+
if callRegistrations->Utils.Array.isEmpty {
|
|
93
|
+
await source.getItemsOrThrow(
|
|
94
|
+
~fromBlock,
|
|
95
|
+
~toBlock,
|
|
96
|
+
~addressSet,
|
|
97
|
+
~reorgableFrom,
|
|
98
|
+
~knownHeight,
|
|
99
|
+
~partitionId,
|
|
100
|
+
~selection,
|
|
101
|
+
~itemsTarget,
|
|
102
|
+
~retry,
|
|
103
|
+
~logger,
|
|
104
|
+
)
|
|
105
|
+
} else {
|
|
106
|
+
let logRegistrations =
|
|
107
|
+
selection.onEventRegistrations->Array.filter(registration =>
|
|
108
|
+
registration->callRankOf->Option.isNone
|
|
109
|
+
)
|
|
110
|
+
let logs = if (
|
|
111
|
+
logRegistrations->Utils.Array.isEmpty && selection.onBlockRegistrations->Utils.Array.isEmpty
|
|
112
|
+
) {
|
|
113
|
+
None
|
|
114
|
+
} else {
|
|
115
|
+
Some(
|
|
116
|
+
await source.getItemsOrThrow(
|
|
117
|
+
~fromBlock,
|
|
118
|
+
~toBlock,
|
|
119
|
+
~addressSet,
|
|
120
|
+
~reorgableFrom,
|
|
121
|
+
~knownHeight,
|
|
122
|
+
~partitionId,
|
|
123
|
+
~selection={...selection, onEventRegistrations: logRegistrations},
|
|
124
|
+
~itemsTarget,
|
|
125
|
+
~retry,
|
|
126
|
+
~logger,
|
|
127
|
+
),
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Calls are asked for only as far as the logs were: a source may stop a
|
|
132
|
+
// page short, and the two have to agree on where the answer ends.
|
|
133
|
+
let rangeEnd = switch (logs, toBlock) {
|
|
134
|
+
| (Some(logs), _) => logs.latestFetchedBlockNumber
|
|
135
|
+
| (None, Some(toBlock)) => toBlock
|
|
136
|
+
| (None, None) => Math.Int.min(knownHeight, fromBlock + openEndedSpan)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
let clientFiltered = contractName =>
|
|
140
|
+
switch selection.clientFilteredContracts {
|
|
141
|
+
| Some(contractNames) => contractNames->Array.includes(contractName)
|
|
142
|
+
| None => false
|
|
143
|
+
}
|
|
144
|
+
let addresses = Dict.make()
|
|
145
|
+
callRegistrations->Array.forEach(registration => {
|
|
146
|
+
let contractName = registration.eventConfig.contractName
|
|
147
|
+
if !registration.isWildcard && addresses->Dict.get(contractName)->Option.isNone {
|
|
148
|
+
addresses->Dict.set(
|
|
149
|
+
contractName,
|
|
150
|
+
clientFiltered(contractName)
|
|
151
|
+
? addressStore->AddressStore.contractAddresses(contractName, ~shouldChecksum=false)
|
|
152
|
+
: addressSet->AddressSet.addressesOf(contractName),
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
let startedAt = Performance.now()
|
|
158
|
+
let response = try await installed.fetchCalls({
|
|
159
|
+
chainId: source.chainId,
|
|
160
|
+
fromBlock,
|
|
161
|
+
toBlock: rangeEnd,
|
|
162
|
+
registrations: callRegistrations->Array.map(registration => {
|
|
163
|
+
index: registration.index,
|
|
164
|
+
contractName: registration.eventConfig.contractName,
|
|
165
|
+
eventName: registration.eventConfig.name,
|
|
166
|
+
selector: registration->selectorOf,
|
|
167
|
+
rank: registration->callRankOf->Option.getOr(1),
|
|
168
|
+
isWildcard: registration.isWildcard,
|
|
169
|
+
startBlock: registration.startBlock->Nullable.fromOption,
|
|
170
|
+
}),
|
|
171
|
+
addresses: addresses->(Utils.magic: dict<array<Address.t>> => dict<array<string>>),
|
|
172
|
+
rpcUrls: installed.rpcUrls,
|
|
173
|
+
}) catch {
|
|
174
|
+
| exn =>
|
|
175
|
+
throw(
|
|
176
|
+
Source.GetItemsError(
|
|
177
|
+
Source.FailedGettingItems({
|
|
178
|
+
exn,
|
|
179
|
+
attemptedToBlock: rangeEnd,
|
|
180
|
+
retry: WithBackoff({
|
|
181
|
+
message: `Failed reading the calls of blocks ${fromBlock->Int.toString} to ${rangeEnd->Int.toString}. Attempt a retry.`,
|
|
182
|
+
backoffMillis: switch retry {
|
|
183
|
+
| 0 => 500
|
|
184
|
+
| _ => 1000 * retry
|
|
185
|
+
},
|
|
186
|
+
}),
|
|
187
|
+
requestStats: [],
|
|
188
|
+
}),
|
|
189
|
+
),
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
let callSeconds = startedAt->Performance.secondsSince
|
|
193
|
+
|
|
194
|
+
let registrationByIndex = Dict.make()
|
|
195
|
+
callRegistrations->Array.forEach(registration =>
|
|
196
|
+
registrationByIndex->Dict.set(registration.index->Int.toString, registration)
|
|
197
|
+
)
|
|
198
|
+
let latest = response.latestFetchedBlockNumber
|
|
199
|
+
let callItems = response.items->Array.filterMap(callItem => {
|
|
200
|
+
let registration =
|
|
201
|
+
registrationByIndex->Dict.getUnsafe(callItem.registrationIndex->Int.toString)
|
|
202
|
+
let contractName = registration.eventConfig.contractName
|
|
203
|
+
// The partition's own slice of the contract's addresses, as a log's
|
|
204
|
+
// router applies it; a client-filtered contract answers to the store.
|
|
205
|
+
let ownsCall =
|
|
206
|
+
registration.isWildcard || {
|
|
207
|
+
let address = callItem.payload->Internal.getPayloadSrcAddress
|
|
208
|
+
if clientFiltered(contractName) {
|
|
209
|
+
addressStore->AddressStore.isIndexedAt(address, contractName, callItem.blockNumber)
|
|
210
|
+
} else {
|
|
211
|
+
addressSet->AddressSet.containsAt(address, contractName, callItem.blockNumber)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if callItem.blockNumber <= latest && ownsCall {
|
|
215
|
+
let item = Internal.Event({
|
|
216
|
+
onEventRegistration: registration,
|
|
217
|
+
chainId: source.chainId,
|
|
218
|
+
blockNumber: callItem.blockNumber,
|
|
219
|
+
logIndex: 0,
|
|
220
|
+
orderPath: callItem.traceAddress,
|
|
221
|
+
transactionIndex: callItem.transactionIndex,
|
|
222
|
+
payload: callItem.payload,
|
|
223
|
+
})
|
|
224
|
+
item->Internal.markItemCall(~rank=registration->callRankOf->Option.getOr(1))
|
|
225
|
+
Some(item)
|
|
226
|
+
} else {
|
|
227
|
+
None
|
|
228
|
+
}
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
let callBlocks = BlockStore.fromJs(response.blocks, ~ecosystem)
|
|
232
|
+
let callRequestStat = {Source.method: "getCalls", seconds: callSeconds}
|
|
233
|
+
switch logs {
|
|
234
|
+
| Some(logs) =>
|
|
235
|
+
logs.blockStore->BlockStore.appendPage(callBlocks)
|
|
236
|
+
{
|
|
237
|
+
...logs,
|
|
238
|
+
parsedQueueItems: Array.concat(
|
|
239
|
+
logs.parsedQueueItems->Array.filter(item =>
|
|
240
|
+
item->Internal.getItemBlockNumber <= latest
|
|
241
|
+
),
|
|
242
|
+
callItems,
|
|
243
|
+
),
|
|
244
|
+
latestFetchedBlockNumber: Math.Int.min(logs.latestFetchedBlockNumber, latest),
|
|
245
|
+
requestStats: Array.concat(logs.requestStats, [callRequestStat]),
|
|
246
|
+
}
|
|
247
|
+
| None => {
|
|
248
|
+
Source.knownHeight: response.knownHeight->Nullable.getOr(knownHeight),
|
|
249
|
+
parsedQueueItems: callItems,
|
|
250
|
+
transactionStore: None,
|
|
251
|
+
blockStore: callBlocks,
|
|
252
|
+
latestFetchedBlockNumber: latest,
|
|
253
|
+
stats: {totalTimeElapsed: callSeconds},
|
|
254
|
+
requestStats: [callRequestStat],
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Wraps every source of a chain when its registrations hold a call trigger
|
|
262
|
+
// and the subgraph runtime has installed the backend that reads them.
|
|
263
|
+
let wrapSources = (
|
|
264
|
+
sources: array<Source.t>,
|
|
265
|
+
~onEventRegistrations: array<Internal.onEventRegistration>,
|
|
266
|
+
~addressStore,
|
|
267
|
+
~ecosystem,
|
|
268
|
+
) =>
|
|
269
|
+
switch installed.contents {
|
|
270
|
+
| Some(installed)
|
|
271
|
+
if onEventRegistrations->Array.some(registration => registration->callRankOf->Option.isSome) =>
|
|
272
|
+
sources->Array.map(source => source->wrap(~addressStore, ~ecosystem, installed))
|
|
273
|
+
| _ => sources
|
|
274
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Utils from "../Utils.res.mjs";
|
|
4
|
+
import * as Source from "./Source.res.mjs";
|
|
5
|
+
import * as Internal from "../Internal.res.mjs";
|
|
6
|
+
import * as BlockStore from "./BlockStore.res.mjs";
|
|
7
|
+
import * as Performance from "../bindings/Performance.res.mjs";
|
|
8
|
+
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
9
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
10
|
+
import * as Stdlib_Nullable from "@rescript/runtime/lib/es6/Stdlib_Nullable.js";
|
|
11
|
+
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
12
|
+
|
|
13
|
+
let installed = {
|
|
14
|
+
contents: undefined
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function install(fetchCalls, rpcUrls) {
|
|
18
|
+
installed.contents = {
|
|
19
|
+
fetchCalls: fetchCalls,
|
|
20
|
+
rpcUrls: rpcUrls
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function callRankOf(registration) {
|
|
25
|
+
return Internal.callRankOfEventName(registration.eventConfig.name);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function selectorOf(registration) {
|
|
29
|
+
let match = Internal.callRankOfEventName(registration.eventConfig.name);
|
|
30
|
+
if (match === 1) {
|
|
31
|
+
return "0x" + registration.eventConfig.name.slice(13, 21).toLowerCase();
|
|
32
|
+
} else {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function wrap(source, addressStore, ecosystem, installed) {
|
|
38
|
+
let newrecord = {...source};
|
|
39
|
+
newrecord.getItemsOrThrow = async (fromBlock, toBlock, addressSet, reorgableFrom, knownHeight, partitionId, selection, itemsTarget, retry, logger) => {
|
|
40
|
+
let callRegistrations = selection.onEventRegistrations.filter(registration => Stdlib_Option.isSome(Internal.callRankOfEventName(registration.eventConfig.name)));
|
|
41
|
+
if (Utils.$$Array.isEmpty(callRegistrations)) {
|
|
42
|
+
return await source.getItemsOrThrow(fromBlock, toBlock, addressSet, reorgableFrom, knownHeight, partitionId, selection, itemsTarget, retry, logger);
|
|
43
|
+
}
|
|
44
|
+
let logRegistrations = selection.onEventRegistrations.filter(registration => Stdlib_Option.isNone(Internal.callRankOfEventName(registration.eventConfig.name)));
|
|
45
|
+
let logs;
|
|
46
|
+
if (Utils.$$Array.isEmpty(logRegistrations) && Utils.$$Array.isEmpty(selection.onBlockRegistrations)) {
|
|
47
|
+
logs = undefined;
|
|
48
|
+
} else {
|
|
49
|
+
let newrecord = {...selection};
|
|
50
|
+
logs = await source.getItemsOrThrow(fromBlock, toBlock, addressSet, reorgableFrom, knownHeight, partitionId, (newrecord.onEventRegistrations = logRegistrations, newrecord), itemsTarget, retry, logger);
|
|
51
|
+
}
|
|
52
|
+
let rangeEnd = logs !== undefined ? logs.latestFetchedBlockNumber : (
|
|
53
|
+
toBlock !== undefined ? toBlock : Math.min(knownHeight, fromBlock + 1000000 | 0)
|
|
54
|
+
);
|
|
55
|
+
let clientFiltered = contractName => {
|
|
56
|
+
let contractNames = selection.clientFilteredContracts;
|
|
57
|
+
if (contractNames !== undefined) {
|
|
58
|
+
return contractNames.includes(contractName);
|
|
59
|
+
} else {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
let addresses = {};
|
|
64
|
+
callRegistrations.forEach(registration => {
|
|
65
|
+
let contractName = registration.eventConfig.contractName;
|
|
66
|
+
if (!registration.isWildcard && Stdlib_Option.isNone(addresses[contractName])) {
|
|
67
|
+
addresses[contractName] = clientFiltered(contractName) ? addressStore.contractAddresses(contractName, false) : addressSet.addressesOf(contractName);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
let startedAt = Performance.now();
|
|
72
|
+
let response;
|
|
73
|
+
try {
|
|
74
|
+
response = await installed.fetchCalls({
|
|
75
|
+
chainId: source.chainId,
|
|
76
|
+
fromBlock: fromBlock,
|
|
77
|
+
toBlock: rangeEnd,
|
|
78
|
+
registrations: callRegistrations.map(registration => ({
|
|
79
|
+
index: registration.index,
|
|
80
|
+
contractName: registration.eventConfig.contractName,
|
|
81
|
+
eventName: registration.eventConfig.name,
|
|
82
|
+
selector: selectorOf(registration),
|
|
83
|
+
rank: Stdlib_Option.getOr(Internal.callRankOfEventName(registration.eventConfig.name), 1),
|
|
84
|
+
isWildcard: registration.isWildcard,
|
|
85
|
+
startBlock: Stdlib_Nullable.fromOption(registration.startBlock)
|
|
86
|
+
})),
|
|
87
|
+
addresses: addresses,
|
|
88
|
+
rpcUrls: installed.rpcUrls
|
|
89
|
+
});
|
|
90
|
+
} catch (raw_exn) {
|
|
91
|
+
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
92
|
+
throw {
|
|
93
|
+
RE_EXN_ID: Source.GetItemsError,
|
|
94
|
+
_1: {
|
|
95
|
+
TAG: "FailedGettingItems",
|
|
96
|
+
exn: exn,
|
|
97
|
+
attemptedToBlock: rangeEnd,
|
|
98
|
+
retry: {
|
|
99
|
+
TAG: "WithBackoff",
|
|
100
|
+
message: `Failed reading the calls of blocks ` + fromBlock.toString() + ` to ` + rangeEnd.toString() + `. Attempt a retry.`,
|
|
101
|
+
backoffMillis: retry !== 0 ? 1000 * retry | 0 : 500
|
|
102
|
+
},
|
|
103
|
+
requestStats: []
|
|
104
|
+
},
|
|
105
|
+
Error: new Error()
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
let callSeconds = Performance.secondsSince(startedAt);
|
|
109
|
+
let registrationByIndex = {};
|
|
110
|
+
callRegistrations.forEach(registration => {
|
|
111
|
+
registrationByIndex[registration.index.toString()] = registration;
|
|
112
|
+
});
|
|
113
|
+
let latest = response.latestFetchedBlockNumber;
|
|
114
|
+
let callItems = Stdlib_Array.filterMap(response.items, callItem => {
|
|
115
|
+
let registration = registrationByIndex[callItem.registrationIndex.toString()];
|
|
116
|
+
let contractName = registration.eventConfig.contractName;
|
|
117
|
+
let ownsCall = true;
|
|
118
|
+
if (!registration.isWildcard) {
|
|
119
|
+
let address = callItem.payload.srcAddress;
|
|
120
|
+
ownsCall = clientFiltered(contractName) ? addressStore.isIndexedAt(address, contractName, callItem.blockNumber) : addressSet.containsAt(address, contractName, callItem.blockNumber);
|
|
121
|
+
}
|
|
122
|
+
if (!(callItem.blockNumber <= latest && ownsCall)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
let item_1 = source.chainId;
|
|
126
|
+
let item_2 = callItem.blockNumber;
|
|
127
|
+
let item_4 = callItem.traceAddress;
|
|
128
|
+
let item_5 = callItem.transactionIndex;
|
|
129
|
+
let item_6 = callItem.payload;
|
|
130
|
+
let item = {
|
|
131
|
+
kind: 0,
|
|
132
|
+
onEventRegistration: registration,
|
|
133
|
+
chainId: item_1,
|
|
134
|
+
blockNumber: item_2,
|
|
135
|
+
logIndex: 0,
|
|
136
|
+
orderPath: item_4,
|
|
137
|
+
transactionIndex: item_5,
|
|
138
|
+
payload: item_6
|
|
139
|
+
};
|
|
140
|
+
Internal.markItemCall(item, Stdlib_Option.getOr(Internal.callRankOfEventName(registration.eventConfig.name), 1));
|
|
141
|
+
return item;
|
|
142
|
+
});
|
|
143
|
+
let callBlocks = BlockStore.fromJs(response.blocks, ecosystem);
|
|
144
|
+
let callRequestStat = {
|
|
145
|
+
method: "getCalls",
|
|
146
|
+
seconds: callSeconds
|
|
147
|
+
};
|
|
148
|
+
if (logs !== undefined) {
|
|
149
|
+
logs.blockStore.appendPage(callBlocks);
|
|
150
|
+
return {
|
|
151
|
+
knownHeight: logs.knownHeight,
|
|
152
|
+
parsedQueueItems: logs.parsedQueueItems.filter(item => item.blockNumber <= latest).concat(callItems),
|
|
153
|
+
transactionStore: logs.transactionStore,
|
|
154
|
+
blockStore: logs.blockStore,
|
|
155
|
+
latestFetchedBlockNumber: Math.min(logs.latestFetchedBlockNumber, latest),
|
|
156
|
+
stats: logs.stats,
|
|
157
|
+
requestStats: logs.requestStats.concat([callRequestStat])
|
|
158
|
+
};
|
|
159
|
+
} else {
|
|
160
|
+
return {
|
|
161
|
+
knownHeight: Stdlib_Nullable.getOr(response.knownHeight, knownHeight),
|
|
162
|
+
parsedQueueItems: callItems,
|
|
163
|
+
transactionStore: undefined,
|
|
164
|
+
blockStore: callBlocks,
|
|
165
|
+
latestFetchedBlockNumber: latest,
|
|
166
|
+
stats: {
|
|
167
|
+
"total time elapsed (s)": callSeconds
|
|
168
|
+
},
|
|
169
|
+
requestStats: [callRequestStat]
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
return newrecord;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function wrapSources(sources, onEventRegistrations, addressStore, ecosystem) {
|
|
177
|
+
let installed$1 = installed.contents;
|
|
178
|
+
if (installed$1 !== undefined && onEventRegistrations.some(registration => Stdlib_Option.isSome(Internal.callRankOfEventName(registration.eventConfig.name)))) {
|
|
179
|
+
return sources.map(source => wrap(source, addressStore, ecosystem, installed$1));
|
|
180
|
+
} else {
|
|
181
|
+
return sources;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
let openEndedSpan = 1000000;
|
|
186
|
+
|
|
187
|
+
export {
|
|
188
|
+
installed,
|
|
189
|
+
install,
|
|
190
|
+
openEndedSpan,
|
|
191
|
+
callRankOf,
|
|
192
|
+
selectorOf,
|
|
193
|
+
wrap,
|
|
194
|
+
wrapSources,
|
|
195
|
+
}
|
|
196
|
+
/* Utils Not a pure module */
|
|
@@ -10,6 +10,7 @@ let make = (
|
|
|
10
10
|
~blockStore: BlockStore.t,
|
|
11
11
|
~transactionStore: TransactionStore.t,
|
|
12
12
|
~logger: Logger.t,
|
|
13
|
+
~maxAddressesPerRequest: int,
|
|
13
14
|
): array<Source.t> => {
|
|
14
15
|
let chainId = chainConfig.id
|
|
15
16
|
switch chainConfig.sourceConfig {
|
|
@@ -39,6 +40,7 @@ let make = (
|
|
|
39
40
|
~blockStore,
|
|
40
41
|
~transactionStore,
|
|
41
42
|
~logger,
|
|
43
|
+
~maxAddressesPerRequest,
|
|
42
44
|
)
|
|
43
45
|
| Config.FuelSourceConfig({hypersync}) => [
|
|
44
46
|
FuelHyperSyncSource.make({
|
|
@@ -7,7 +7,7 @@ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js
|
|
|
7
7
|
import * as SvmHyperSyncSource from "./SvmHyperSyncSource.res.mjs";
|
|
8
8
|
import * as FuelHyperSyncSource from "./FuelHyperSyncSource.res.mjs";
|
|
9
9
|
|
|
10
|
-
function make(chainConfig, onEventRegistrations, onBlockRegistrationsOpt, addressStore, lowercaseAddresses, blockStore, transactionStore, logger) {
|
|
10
|
+
function make(chainConfig, onEventRegistrations, onBlockRegistrationsOpt, addressStore, lowercaseAddresses, blockStore, transactionStore, logger, maxAddressesPerRequest) {
|
|
11
11
|
let onBlockRegistrations = onBlockRegistrationsOpt !== undefined ? onBlockRegistrationsOpt : [];
|
|
12
12
|
let chainId = chainConfig.id;
|
|
13
13
|
let sources = chainConfig.sourceConfig;
|
|
@@ -25,7 +25,7 @@ function make(chainConfig, onEventRegistrations, onBlockRegistrationsOpt, addres
|
|
|
25
25
|
headers: headers
|
|
26
26
|
};
|
|
27
27
|
});
|
|
28
|
-
return EvmChain.makeSources(chainId, onEventRegistrations, onBlockRegistrations, sources.hypersync, evmRpcs, lowercaseAddresses, addressStore, blockStore, transactionStore, logger);
|
|
28
|
+
return EvmChain.makeSources(chainId, onEventRegistrations, onBlockRegistrations, sources.hypersync, evmRpcs, lowercaseAddresses, addressStore, blockStore, transactionStore, logger, maxAddressesPerRequest);
|
|
29
29
|
case "FuelSourceConfig" :
|
|
30
30
|
return [FuelHyperSyncSource.make({
|
|
31
31
|
chainId: chainId,
|
package/src/sources/EvmChain.res
CHANGED
|
@@ -50,6 +50,7 @@ let makeSources = (
|
|
|
50
50
|
~blockStore,
|
|
51
51
|
~transactionStore,
|
|
52
52
|
~logger,
|
|
53
|
+
~maxAddressesPerRequest,
|
|
53
54
|
) => {
|
|
54
55
|
let sources = switch hyperSync {
|
|
55
56
|
| Some(endpointUrl) => [
|
|
@@ -84,9 +85,17 @@ let makeSources = (
|
|
|
84
85
|
transactionStore,
|
|
85
86
|
?ws,
|
|
86
87
|
?headers,
|
|
88
|
+
maxAddressesPerRequest,
|
|
89
|
+
logger,
|
|
87
90
|
})
|
|
88
91
|
let _ = sources->Array.push(source)
|
|
89
92
|
})
|
|
90
93
|
|
|
91
|
-
sources
|
|
94
|
+
sources->CallSource.wrapSources(
|
|
95
|
+
~onEventRegistrations=onEventRegistrations->(
|
|
96
|
+
Utils.magic: array<Internal.evmOnEventRegistration> => array<Internal.onEventRegistration>
|
|
97
|
+
),
|
|
98
|
+
~addressStore,
|
|
99
|
+
~ecosystem=Evm,
|
|
100
|
+
)
|
|
92
101
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as Env from "../Env.res.mjs";
|
|
4
4
|
import * as RpcSource from "./RpcSource.res.mjs";
|
|
5
|
+
import * as CallSource from "./CallSource.res.mjs";
|
|
5
6
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
7
|
import * as EvmHyperSyncSource from "./EvmHyperSyncSource.res.mjs";
|
|
7
8
|
|
|
@@ -19,7 +20,7 @@ function getSyncConfig(param) {
|
|
|
19
20
|
};
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
function makeSources(chainId, onEventRegistrations, onBlockRegistrations, hyperSync, rpcs, lowercaseAddresses, addressStore, blockStore, transactionStore, logger) {
|
|
23
|
+
function makeSources(chainId, onEventRegistrations, onBlockRegistrations, hyperSync, rpcs, lowercaseAddresses, addressStore, blockStore, transactionStore, logger, maxAddressesPerRequest) {
|
|
23
24
|
let sources = hyperSync !== undefined ? [EvmHyperSyncSource.make({
|
|
24
25
|
chainId: chainId,
|
|
25
26
|
endpointUrl: hyperSync,
|
|
@@ -47,11 +48,13 @@ function makeSources(chainId, onEventRegistrations, onBlockRegistrations, hyperS
|
|
|
47
48
|
blockStore: blockStore,
|
|
48
49
|
transactionStore: transactionStore,
|
|
49
50
|
ws: param.ws,
|
|
50
|
-
headers: param.headers
|
|
51
|
+
headers: param.headers,
|
|
52
|
+
maxAddressesPerRequest: maxAddressesPerRequest,
|
|
53
|
+
logger: logger
|
|
51
54
|
});
|
|
52
55
|
sources.push(source);
|
|
53
56
|
});
|
|
54
|
-
return sources;
|
|
57
|
+
return CallSource.wrapSources(sources, onEventRegistrations, addressStore, "evm");
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
export {
|
|
@@ -202,7 +202,7 @@ let make = (
|
|
|
202
202
|
{height, requestStats: [{method: "getHeight", seconds}]}
|
|
203
203
|
},
|
|
204
204
|
getItemsOrThrow,
|
|
205
|
-
createHeightSubscription: (~onHeight, ~onStatus) =>
|
|
206
|
-
HyperSyncSSE.subscribe(~hyperSyncUrl=endpointUrl, ~apiToken, ~onHeight, ~onStatus),
|
|
205
|
+
createHeightSubscription: (~clock, ~onHeight, ~onStatus) =>
|
|
206
|
+
HyperSyncSSE.subscribe(~clock, ~hyperSyncUrl=endpointUrl, ~apiToken, ~onHeight, ~onStatus),
|
|
207
207
|
}
|
|
208
208
|
}
|
|
@@ -149,7 +149,7 @@ function make(param) {
|
|
|
149
149
|
};
|
|
150
150
|
},
|
|
151
151
|
getItemsOrThrow: getItemsOrThrow,
|
|
152
|
-
createHeightSubscription: (onHeight, onStatus) => HyperSyncSSE.subscribe(endpointUrl, apiToken, onHeight, onStatus)
|
|
152
|
+
createHeightSubscription: (clock, onHeight, onStatus) => HyperSyncSSE.subscribe(clock, endpointUrl, apiToken, onHeight, onStatus)
|
|
153
153
|
};
|
|
154
154
|
}
|
|
155
155
|
|
|
@@ -8,6 +8,7 @@ type cfg = {
|
|
|
8
8
|
intervalCeiling: int,
|
|
9
9
|
backoffMillis: int,
|
|
10
10
|
queryTimeoutMillis: int,
|
|
11
|
+
maxAddressesPerRequest: int,
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
type nextPageParams = {
|
|
@@ -18,10 +19,12 @@ type nextPageParams = {
|
|
|
18
19
|
onBlockRegistrationIndexes: array<int>,
|
|
19
20
|
clientFilteredContracts: option<array<string>>,
|
|
20
21
|
retry: int,
|
|
21
|
-
// Blocks at or above this one can still be reorged, so
|
|
22
|
-
//
|
|
23
|
-
// handler block in range. None when the range is
|
|
22
|
+
// Blocks at or above this one can still be reorged, so each of them in the
|
|
23
|
+
// page has its header read and its logs checked against it, even a
|
|
24
|
+
// blocks-only page with no handler block in range. None when the range is
|
|
25
|
+
// final.
|
|
24
26
|
reorgableFrom?: int,
|
|
27
|
+
knownHeight: int,
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
// Rust reports what to do about a page it could not read rather than throwing
|
|
@@ -77,6 +80,8 @@ external classNew: (
|
|
|
77
80
|
array<BlockItem.registrationInput>,
|
|
78
81
|
~checksumAddresses: bool,
|
|
79
82
|
~addressStore: AddressStore.t,
|
|
83
|
+
Logger.native,
|
|
84
|
+
array<string>,
|
|
80
85
|
) => t = "new"
|
|
81
86
|
|
|
82
87
|
let make = (
|
|
@@ -88,6 +93,8 @@ let make = (
|
|
|
88
93
|
~eventRegistrations=[],
|
|
89
94
|
~onBlockRegistrations=[],
|
|
90
95
|
~addressStore,
|
|
96
|
+
~maxAddressesPerRequest,
|
|
97
|
+
~logger: Logger.t,
|
|
91
98
|
) =>
|
|
92
99
|
Core.getAddon().evmRpcClient->classNew(
|
|
93
100
|
{
|
|
@@ -100,9 +107,12 @@ let make = (
|
|
|
100
107
|
intervalCeiling: syncConfig.intervalCeiling,
|
|
101
108
|
backoffMillis: syncConfig.backoffMillis,
|
|
102
109
|
queryTimeoutMillis: syncConfig.queryTimeoutMillis,
|
|
110
|
+
maxAddressesPerRequest,
|
|
103
111
|
},
|
|
104
112
|
eventRegistrations,
|
|
105
113
|
onBlockRegistrations->BlockItem.toRegistrationInputs,
|
|
106
114
|
~checksumAddresses,
|
|
107
115
|
~addressStore,
|
|
116
|
+
logger.output.native,
|
|
117
|
+
logger.boundFieldsJson,
|
|
108
118
|
)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import * as Core from "../Core.res.mjs";
|
|
4
4
|
import * as BlockItem from "./BlockItem.res.mjs";
|
|
5
5
|
|
|
6
|
-
function make(url, checksumAddresses, syncConfig, maxConcurrentRequests, headers, eventRegistrationsOpt, onBlockRegistrationsOpt, addressStore) {
|
|
6
|
+
function make(url, checksumAddresses, syncConfig, maxConcurrentRequests, headers, eventRegistrationsOpt, onBlockRegistrationsOpt, addressStore, maxAddressesPerRequest, logger) {
|
|
7
7
|
let eventRegistrations = eventRegistrationsOpt !== undefined ? eventRegistrationsOpt : [];
|
|
8
8
|
let onBlockRegistrations = onBlockRegistrationsOpt !== undefined ? onBlockRegistrationsOpt : [];
|
|
9
9
|
return Core.getAddon().EvmRpcClient.new({
|
|
@@ -15,8 +15,9 @@ function make(url, checksumAddresses, syncConfig, maxConcurrentRequests, headers
|
|
|
15
15
|
accelerationAdditive: syncConfig.accelerationAdditive,
|
|
16
16
|
intervalCeiling: syncConfig.intervalCeiling,
|
|
17
17
|
backoffMillis: syncConfig.backoffMillis,
|
|
18
|
-
queryTimeoutMillis: syncConfig.queryTimeoutMillis
|
|
19
|
-
|
|
18
|
+
queryTimeoutMillis: syncConfig.queryTimeoutMillis,
|
|
19
|
+
maxAddressesPerRequest: maxAddressesPerRequest
|
|
20
|
+
}, eventRegistrations, BlockItem.toRegistrationInputs(onBlockRegistrations), checksumAddresses, addressStore, logger.output.native, logger.boundFieldsJson);
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export {
|
package/src/sources/EvmRpcWs.res
CHANGED
|
@@ -81,8 +81,8 @@ let wsMessageSchema = S.union([
|
|
|
81
81
|
}),
|
|
82
82
|
])
|
|
83
83
|
|
|
84
|
-
let subscribe = (~wsUrl, ~onHeight, ~onStatus) =>
|
|
85
|
-
HeightStream.subscribe(~staleTimeout, ~onHeight, ~onStatus, ~connect=driver => {
|
|
84
|
+
let subscribe = (~clock, ~wsUrl, ~onHeight, ~onStatus) =>
|
|
85
|
+
HeightStream.subscribe(~clock, ~staleTimeout, ~onHeight, ~onStatus, ~connect=driver => {
|
|
86
86
|
let ws = WebSocket.create(wsUrl)
|
|
87
87
|
let subscribed = ref(false)
|
|
88
88
|
|
|
@@ -103,7 +103,8 @@ let subscribe = (~wsUrl, ~onHeight, ~onStatus) =>
|
|
|
103
103
|
| Some(Response({id: Some(id), isError: false})) if id === subscribeRequestIdText =>
|
|
104
104
|
subscribed := true
|
|
105
105
|
driver.onConnected()
|
|
106
|
-
| Some(Response({id, isError: true}))
|
|
106
|
+
| Some(Response({id, isError: true}))
|
|
107
|
+
if id->refusesSubscribe(~subscribed=subscribed.contents) =>
|
|
107
108
|
driver.onFailure(~reason=SubscribeRejected, ~detail=text)
|
|
108
109
|
// A provider talking about something other than the subscription this
|
|
109
110
|
// socket asked for — a rate limit, a request nobody here made. Read
|