envio 3.7.0 → 3.9.0-resolvers.0
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 +2 -2
- package/evm.schema.json +7 -0
- package/fuel.schema.json +7 -0
- package/index.d.ts +674 -161
- package/index.js +10 -0
- package/package.json +6 -7
- package/src/AddressRows.res +121 -0
- package/src/AddressRows.res.mjs +143 -0
- package/src/Batch.res +11 -0
- package/src/Batch.res.mjs +2 -1
- package/src/Bin.res +47 -0
- package/src/Bin.res.mjs +34 -1
- package/src/ChainState.res +108 -98
- package/src/ChainState.res.mjs +86 -67
- package/src/ChainState.resi +28 -15
- package/src/Config.res +61 -131
- package/src/Config.res.mjs +47 -79
- package/src/ContractMapping.res +66 -0
- package/src/ContractMapping.res.mjs +73 -0
- package/src/Core.res +24 -0
- package/src/Core.res.mjs +4 -0
- package/src/Ecosystem.res +7 -2
- package/src/Env.res +128 -1
- package/src/Env.res.mjs +123 -1
- package/src/Envio.res +54 -76
- package/src/EventConfigBuilder.res +316 -46
- package/src/EventConfigBuilder.res.mjs +231 -28
- package/src/FetchState.res +59 -67
- package/src/FetchState.res.mjs +34 -44
- package/src/HandlerRegister.res +26 -15
- package/src/HandlerRegister.res.mjs +27 -7
- package/src/Hasura.res +30 -22
- package/src/Hasura.res.mjs +11 -5
- package/src/InMemoryStore.res +23 -38
- package/src/InMemoryStore.res.mjs +13 -27
- package/src/IndexerState.res +40 -3
- package/src/IndexerState.res.mjs +30 -4
- package/src/IndexerState.resi +4 -1
- package/src/Internal.res +49 -30
- package/src/Internal.res.mjs +12 -16
- package/src/Main.res +27 -20
- package/src/Main.res.mjs +19 -14
- package/src/Metrics.res +15 -1
- package/src/Metrics.res.mjs +5 -1
- package/src/Persistence.res +46 -21
- package/src/Persistence.res.mjs +8 -5
- package/src/PgStorage.res +238 -79
- package/src/PgStorage.res.mjs +115 -73
- package/src/PruneStaleHistory.res +1 -1
- package/src/PruneStaleHistory.res.mjs +1 -1
- package/src/Rollback.res +62 -41
- package/src/Rollback.res.mjs +61 -19
- package/src/RollbackCommit.res +7 -9
- package/src/RollbackCommit.res.mjs +5 -6
- package/src/SimulateItems.res +254 -9
- package/src/SimulateItems.res.mjs +214 -47
- package/src/Sink.res +35 -26
- package/src/Sink.res.mjs +20 -16
- package/src/TestIndexer.res +121 -123
- package/src/TestIndexer.res.mjs +97 -102
- package/src/Utils.res +38 -0
- package/src/Utils.res.mjs +39 -2
- package/src/Writing.res +4 -2
- package/src/Writing.res.mjs +3 -2
- package/src/bindings/ClickHouse.res +311 -656
- package/src/bindings/ClickHouse.res.mjs +294 -395
- package/src/bindings/ClickHouseSink.res +303 -0
- package/src/bindings/ClickHouseSink.res.mjs +216 -0
- package/src/bindings/NodeJs.res +9 -0
- package/src/bindings/NodeJs.res.mjs +8 -1
- package/src/bindings/Postgres.res +9 -0
- package/src/bindings/Postgres.res.mjs +3 -0
- package/src/db/EntityHistory.res +29 -24
- package/src/db/EntityHistory.res.mjs +11 -19
- package/src/db/InternalTable.res +258 -83
- package/src/db/InternalTable.res.mjs +223 -85
- package/src/db/RollbackScope.res +29 -0
- package/src/db/RollbackScope.res.mjs +31 -0
- package/src/db/Table.res +28 -1
- package/src/db/Table.res.mjs +26 -2
- package/src/resolvers/ResolverProcess.res +809 -0
- package/src/resolvers/ResolverProcess.res.mjs +667 -0
- package/src/resolvers/ResolverQuery.res +317 -0
- package/src/resolvers/ResolverQuery.res.mjs +220 -0
- package/src/resolvers/collisions.js +108 -0
- package/src/resolvers/db.js +363 -0
- package/src/resolvers/dispatch.js +165 -0
- package/src/resolvers/errors.js +30 -0
- package/src/resolvers/graphqlSelection.js +292 -0
- package/src/resolvers/hasuraAction.js +84 -0
- package/src/resolvers/hasuraApply.js +323 -0
- package/src/resolvers/hasuraMetadata.js +119 -0
- package/src/resolvers/index.js +95 -0
- package/src/resolvers/manifest.js +370 -0
- package/src/resolvers/server.js +270 -0
- package/src/sources/AddressSet.res +0 -22
- package/src/sources/AddressStore.res +48 -88
- package/src/sources/AddressStore.res.mjs +11 -22
- package/src/sources/Evm.res +2 -0
- package/src/sources/Evm.res.mjs +2 -0
- package/src/sources/EvmHyperSyncSource.res +3 -2
- package/src/sources/Fuel.res +2 -0
- package/src/sources/Fuel.res.mjs +2 -0
- package/src/sources/SimulateSource.res +8 -4
- package/src/sources/SimulateSource.res.mjs +7 -3
- package/src/sources/Svm.res +36 -7
- package/src/sources/Svm.res.mjs +34 -4
- package/src/sources/SvmHyperSyncClient.res +20 -116
- package/src/sources/SvmHyperSyncClient.res.mjs +5 -7
- package/src/sources/SvmHyperSyncSource.res +89 -37
- package/src/sources/SvmHyperSyncSource.res.mjs +71 -39
- package/src/sources/TransactionStore.res +38 -0
- package/src/sources/TransactionStore.res.mjs +5 -0
- package/src/tui/Tui.res +1 -1
- package/src/tui/Tui.res.mjs +1 -1
- package/svm.schema.json +44 -156
- package/src/MemoryStorage.res +0 -724
- package/src/MemoryStorage.res.mjs +0 -601
package/src/FetchState.res.mjs
CHANGED
|
@@ -1123,25 +1123,16 @@ function warnRejectedRegistration(verdict, chainId, contractAddress, contractNam
|
|
|
1123
1123
|
contractName: contractName
|
|
1124
1124
|
}, `Skipping contract registration: Not a valid address for this chain's ecosystem.`);
|
|
1125
1125
|
}
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
}, `Skipping contract registration: Contract address is already registered at a later block number. Currently registration of the same contract address is not supported by Envio. Reach out to us if it's a problem for you.`);
|
|
1137
|
-
} else {
|
|
1138
|
-
return;
|
|
1139
|
-
}
|
|
1140
|
-
case "Conflict" :
|
|
1141
|
-
return warnAddressRegistration(chainId, contractAddress, {
|
|
1142
|
-
existingContractType: verdict.existingContractName,
|
|
1143
|
-
newContractType: contractName
|
|
1144
|
-
}, `Skipping contract registration: Contract address is already registered for one contract and cannot be registered for another contract.`);
|
|
1126
|
+
if (verdict.TAG === "Added") {
|
|
1127
|
+
return;
|
|
1128
|
+
}
|
|
1129
|
+
let existingEffectiveStartBlock = verdict.existingEffectiveStartBlock;
|
|
1130
|
+
let effectiveStartBlock = verdict.effectiveStartBlock;
|
|
1131
|
+
if (existingEffectiveStartBlock > effectiveStartBlock) {
|
|
1132
|
+
return warnAddressRegistration(chainId, contractAddress, {
|
|
1133
|
+
existingBlockNumber: existingEffectiveStartBlock,
|
|
1134
|
+
newBlockNumber: effectiveStartBlock
|
|
1135
|
+
}, `Skipping same-contract re-registration: the address is already registered for this contract. The start block does not move earlier.`);
|
|
1145
1136
|
}
|
|
1146
1137
|
}
|
|
1147
1138
|
|
|
@@ -1727,7 +1718,7 @@ function getReadyItemsCount(fetchState, targetSize, fromItem) {
|
|
|
1727
1718
|
return acc;
|
|
1728
1719
|
}
|
|
1729
1720
|
|
|
1730
|
-
function make$1(startBlock, endBlock, onEventRegistrations, addressStore,
|
|
1721
|
+
function make$1(startBlock, endBlock, onEventRegistrations, addressStore, addressRows, maxAddrInPartition, chainId, maxOnBlockBufferSize, knownHeight, progressBlockNumberOpt, onBlockRegistrationsOpt, blockLagOpt, firstEventBlockOpt, clientFilterAddressThresholdOpt, isResumedOpt) {
|
|
1731
1722
|
let progressBlockNumber = progressBlockNumberOpt !== undefined ? progressBlockNumberOpt : startBlock - 1 | 0;
|
|
1732
1723
|
let onBlockRegistrations = onBlockRegistrationsOpt !== undefined ? onBlockRegistrationsOpt : [];
|
|
1733
1724
|
let blockLag = blockLagOpt !== undefined ? blockLagOpt : 0;
|
|
@@ -1762,29 +1753,24 @@ function make$1(startBlock, endBlock, onEventRegistrations, addressStore, addres
|
|
|
1762
1753
|
});
|
|
1763
1754
|
}
|
|
1764
1755
|
let normalSelection = makeSelection(normalRegistrations, true, undefined);
|
|
1765
|
-
AddressStore.
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
}
|
|
1770
|
-
let contract = addresses[idx];
|
|
1771
|
-
warnRejectedRegistration(verdict, chainId, contract.address, contract.contractName);
|
|
1772
|
-
});
|
|
1756
|
+
AddressStore.seedRows(addressStore, addressRows).forEach(rejected => warnAddressRegistration(chainId, rejected.address, {
|
|
1757
|
+
contractName: rejected.contractName,
|
|
1758
|
+
existingBlockNumber: rejected.existingEffectiveStartBlock,
|
|
1759
|
+
newBlockNumber: rejected.effectiveStartBlock
|
|
1760
|
+
}, `Skipping a stored address: it is already registered for this contract.`));
|
|
1773
1761
|
let dynamicContracts = new Set();
|
|
1774
1762
|
let clientFilteredContracts = new Set();
|
|
1775
1763
|
let registeringSetsByContract = {};
|
|
1776
|
-
|
|
1777
|
-
|
|
1764
|
+
Array.from(contractNamesWithNormalEvents).forEach(contractName => {
|
|
1765
|
+
if (addressStore.contractCount(contractName) > 0) {
|
|
1766
|
+
registeringSetsByContract[contractName] = AddressStore.makeSet(addressStore, contractName, undefined);
|
|
1767
|
+
return;
|
|
1768
|
+
}
|
|
1769
|
+
});
|
|
1770
|
+
addressStore.dynamicContractNames().forEach(contractName => {
|
|
1778
1771
|
if (contractNamesWithNormalEvents.has(contractName)) {
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
}
|
|
1782
|
-
if (contract.registrationBlock !== -1) {
|
|
1783
|
-
dynamicContracts.add(contractName);
|
|
1784
|
-
return;
|
|
1785
|
-
} else {
|
|
1786
|
-
return;
|
|
1787
|
-
}
|
|
1772
|
+
dynamicContracts.add(contractName);
|
|
1773
|
+
return;
|
|
1788
1774
|
}
|
|
1789
1775
|
});
|
|
1790
1776
|
if (clientFilterAddressThreshold !== undefined) {
|
|
@@ -1797,7 +1783,7 @@ function make$1(startBlock, endBlock, onEventRegistrations, addressStore, addres
|
|
|
1797
1783
|
}
|
|
1798
1784
|
let optimizedPartitions = createPartitions(registeringSetsByContract, addressStore, dynamicContracts, clientFilteredContracts, normalSelection, maxAddrInPartition, partitions.length, partitions, progressBlockNumber, knownHeight);
|
|
1799
1785
|
if (optimizedPartitions.idsInAscOrder.length === 0 && Utils.$$Array.isEmpty(onBlockRegistrations)) {
|
|
1800
|
-
Stdlib_JsError.throwWithMessage(`Invalid configuration: Nothing to fetch on chain ` + ChainId.toString(chainId) + `. ` + (`addresses=` + addresses.length.toString() + `, `) + (`onEventRegistrations=` + onEventRegistrations.length.toString() + `, `) + (`normalRegistrations=` + normalRegistrations.length.toString() + `. `) + `Make sure that you provided at least one contract address to index, or have events with Wildcard mode enabled, or have onBlock handlers.`);
|
|
1786
|
+
Stdlib_JsError.throwWithMessage(`Invalid configuration: Nothing to fetch on chain ` + ChainId.toString(chainId) + `. ` + (`addresses=` + addressRows.addresses.length.toString() + `, `) + (`onEventRegistrations=` + onEventRegistrations.length.toString() + `, `) + (`normalRegistrations=` + normalRegistrations.length.toString() + `. `) + `Make sure that you provided at least one contract address to index, or have events with Wildcard mode enabled, or have onBlock handlers.`);
|
|
1801
1787
|
}
|
|
1802
1788
|
let buffer = [];
|
|
1803
1789
|
let latestOnBlockBlockNumber;
|
|
@@ -1861,8 +1847,8 @@ function rollbackPendingQueries(mutPendingQueries, targetBlockNumber) {
|
|
|
1861
1847
|
return adjusted;
|
|
1862
1848
|
}
|
|
1863
1849
|
|
|
1864
|
-
function rollback(fetchState,
|
|
1865
|
-
|
|
1850
|
+
function rollback(fetchState, rolledBackAddressStore, targetBlockNumber) {
|
|
1851
|
+
let rolledBackAddresses = rolledBackAddressStore.rollback(targetBlockNumber);
|
|
1866
1852
|
let keptPartitions = [];
|
|
1867
1853
|
let nextKeptIdRef = 0;
|
|
1868
1854
|
let registeringSetsByContract = {};
|
|
@@ -1921,8 +1907,8 @@ function rollback(fetchState, addressStore, targetBlockNumber) {
|
|
|
1921
1907
|
});
|
|
1922
1908
|
}
|
|
1923
1909
|
}
|
|
1924
|
-
let optimizedPartitions = createPartitions(registeringSetsByContract,
|
|
1925
|
-
|
|
1910
|
+
let optimizedPartitions = createPartitions(registeringSetsByContract, rolledBackAddressStore, fetchState.optimizedPartitions.dynamicContracts, fetchState.optimizedPartitions.clientFilteredContracts, fetchState.normalSelection, fetchState.optimizedPartitions.maxAddrInPartition, nextKeptIdRef, keptPartitions, targetBlockNumber, fetchState.knownHeight);
|
|
1911
|
+
let rolledBack = updateInternal({
|
|
1926
1912
|
optimizedPartitions: fetchState.optimizedPartitions,
|
|
1927
1913
|
startBlock: fetchState.startBlock,
|
|
1928
1914
|
endBlock: fetchState.endBlock,
|
|
@@ -1941,6 +1927,10 @@ function rollback(fetchState, addressStore, targetBlockNumber) {
|
|
|
1941
1927
|
tmp = item.kind === 0 ? item.blockNumber : item.blockNumber;
|
|
1942
1928
|
return tmp <= targetBlockNumber;
|
|
1943
1929
|
}), true, undefined, undefined);
|
|
1930
|
+
return {
|
|
1931
|
+
fetchState: rolledBack,
|
|
1932
|
+
rolledBackAddresses: rolledBackAddresses
|
|
1933
|
+
};
|
|
1944
1934
|
}
|
|
1945
1935
|
|
|
1946
1936
|
function resetPendingQueries(fetchState) {
|
package/src/HandlerRegister.res
CHANGED
|
@@ -154,6 +154,8 @@ let buildOnEventRegistrationWith = (
|
|
|
154
154
|
~isWildcard,
|
|
155
155
|
~handler,
|
|
156
156
|
~contractRegister,
|
|
157
|
+
~where,
|
|
158
|
+
~fieldSelection?,
|
|
157
159
|
~startBlock?,
|
|
158
160
|
) :> Internal.onEventRegistration)
|
|
159
161
|
| Evm =>
|
|
@@ -299,21 +301,29 @@ let addOnEventRegistration = (
|
|
|
299
301
|
let fieldSelection = switch eventOptions->Option.flatMap(v => v.fields) {
|
|
300
302
|
| None => None
|
|
301
303
|
| Some(fields) =>
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
304
|
+
switch registration.config.ecosystem.name {
|
|
305
|
+
| Evm =>
|
|
306
|
+
Some(
|
|
307
|
+
EventConfigBuilder.resolveInlineFieldSelection(
|
|
308
|
+
fields,
|
|
309
|
+
~contractName,
|
|
310
|
+
~eventName,
|
|
311
|
+
~enableRawEvents=registration.config.enableRawEvents,
|
|
312
|
+
),
|
|
313
|
+
)
|
|
314
|
+
| Svm =>
|
|
315
|
+
Some(
|
|
316
|
+
EventConfigBuilder.resolveSvmInlineFieldSelection(
|
|
317
|
+
fields,
|
|
318
|
+
~contractName,
|
|
319
|
+
~eventName,
|
|
320
|
+
),
|
|
321
|
+
)
|
|
322
|
+
| Fuel =>
|
|
305
323
|
JsError.throwWithMessage(
|
|
306
|
-
`The fields option of the "${eventName}" event registration on contract "${contractName}" is
|
|
324
|
+
`The fields option of the "${eventName}" event registration on contract "${contractName}" is not supported on Fuel. Select the fields in your config instead.`,
|
|
307
325
|
)
|
|
308
326
|
}
|
|
309
|
-
Some(
|
|
310
|
-
EventConfigBuilder.resolveInlineFieldSelection(
|
|
311
|
-
fields,
|
|
312
|
-
~contractName,
|
|
313
|
-
~eventName,
|
|
314
|
-
~enableRawEvents=registration.config.enableRawEvents,
|
|
315
|
-
),
|
|
316
|
-
)
|
|
317
327
|
}
|
|
318
328
|
let matched = ref(false)
|
|
319
329
|
registration.config.chainMap
|
|
@@ -350,17 +360,18 @@ let addOnEventRegistration = (
|
|
|
350
360
|
if !matched.contents {
|
|
351
361
|
let (contractNames, eventNames) = registration->describeConfigured(~contractName)
|
|
352
362
|
let listOr = (names, empty) =>
|
|
353
|
-
names->Utils.Array.isEmpty ? empty : names->Array.
|
|
363
|
+
names->Utils.Array.isEmpty ? empty : names->Utils.Array.quotedJoin
|
|
364
|
+
let {contractNoun, eventNoun} = registration.config.ecosystem
|
|
354
365
|
if eventNames->Utils.Array.isEmpty {
|
|
355
366
|
JsError.throwWithMessage(
|
|
356
|
-
|
|
367
|
+
`${contractNoun->Utils.String.capitalize} "${contractName}" is not configured on any chain, so its handler for "${eventName}" would never run. Add it to your config, or remove the registration. Configured ${contractNoun}s: ${listOr(
|
|
357
368
|
contractNames,
|
|
358
369
|
"none",
|
|
359
370
|
)}.`,
|
|
360
371
|
)
|
|
361
372
|
} else {
|
|
362
373
|
JsError.throwWithMessage(
|
|
363
|
-
|
|
374
|
+
`${eventNoun->Utils.String.capitalize} "${eventName}" is not configured on ${contractNoun} "${contractName}", so its handler would never run. Add it to your config, or remove the registration. Configured ${eventNoun}s on "${contractName}": ${listOr(
|
|
364
375
|
eventNames,
|
|
365
376
|
"none",
|
|
366
377
|
)}.`,
|
|
@@ -102,7 +102,7 @@ function buildOnEventRegistrationWith(config, chainId, eventConfig, isWildcard,
|
|
|
102
102
|
case "fuel" :
|
|
103
103
|
return EventConfigBuilder.buildFuelOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, startBlock);
|
|
104
104
|
case "svm" :
|
|
105
|
-
return EventConfigBuilder.buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, startBlock);
|
|
105
|
+
return EventConfigBuilder.buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, where, fieldSelection, startBlock);
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
|
|
@@ -200,7 +200,24 @@ function addOnEventRegistration(registration, contractName, eventName, handler,
|
|
|
200
200
|
let isWildcard = Stdlib_Option.getOr(Stdlib_Option.flatMap(eventOptions, v => v.wildcard), false);
|
|
201
201
|
let where = Stdlib_Option.flatMap(eventOptions, v => v.where);
|
|
202
202
|
let fields = Stdlib_Option.flatMap(eventOptions, v => v.fields);
|
|
203
|
-
let fieldSelection
|
|
203
|
+
let fieldSelection;
|
|
204
|
+
if (fields !== undefined) {
|
|
205
|
+
let fields$1 = Primitive_option.valFromOption(fields);
|
|
206
|
+
let match = registration.config.ecosystem.name;
|
|
207
|
+
switch (match) {
|
|
208
|
+
case "evm" :
|
|
209
|
+
fieldSelection = EventConfigBuilder.resolveInlineFieldSelection(fields$1, contractName, eventName, registration.config.enableRawEvents);
|
|
210
|
+
break;
|
|
211
|
+
case "fuel" :
|
|
212
|
+
fieldSelection = Stdlib_JsError.throwWithMessage(`The fields option of the "` + eventName + `" event registration on contract "` + contractName + `" is not supported on Fuel. Select the fields in your config instead.`);
|
|
213
|
+
break;
|
|
214
|
+
case "svm" :
|
|
215
|
+
fieldSelection = EventConfigBuilder.resolveSvmInlineFieldSelection(fields$1, contractName, eventName);
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
fieldSelection = undefined;
|
|
220
|
+
}
|
|
204
221
|
let matched = {
|
|
205
222
|
contents: false
|
|
206
223
|
};
|
|
@@ -220,19 +237,22 @@ function addOnEventRegistration(registration, contractName, eventName, handler,
|
|
|
220
237
|
if (matched.contents) {
|
|
221
238
|
return;
|
|
222
239
|
}
|
|
223
|
-
let match = describeConfigured(registration, contractName);
|
|
224
|
-
let eventNames = match[1];
|
|
240
|
+
let match$1 = describeConfigured(registration, contractName);
|
|
241
|
+
let eventNames = match$1[1];
|
|
225
242
|
let listOr = (names, empty) => {
|
|
226
243
|
if (Utils.$$Array.isEmpty(names)) {
|
|
227
244
|
return empty;
|
|
228
245
|
} else {
|
|
229
|
-
return
|
|
246
|
+
return Utils.$$Array.quotedJoin(names);
|
|
230
247
|
}
|
|
231
248
|
};
|
|
249
|
+
let match$2 = registration.config.ecosystem;
|
|
250
|
+
let eventNoun = match$2.eventNoun;
|
|
251
|
+
let contractNoun = match$2.contractNoun;
|
|
232
252
|
if (Utils.$$Array.isEmpty(eventNames)) {
|
|
233
|
-
return Stdlib_JsError.throwWithMessage(`
|
|
253
|
+
return Stdlib_JsError.throwWithMessage(Utils.$$String.capitalize(contractNoun) + ` "` + contractName + `" is not configured on any chain, so its handler for "` + eventName + `" would never run. Add it to your config, or remove the registration. Configured ` + contractNoun + `s: ` + listOr(match$1[0], "none") + `.`);
|
|
234
254
|
} else {
|
|
235
|
-
return Stdlib_JsError.throwWithMessage(`
|
|
255
|
+
return Stdlib_JsError.throwWithMessage(Utils.$$String.capitalize(eventNoun) + ` "` + eventName + `" is not configured on ` + contractNoun + ` "` + contractName + `", so its handler would never run. Add it to your config, or remove the registration. Configured ` + eventNoun + `s on "` + contractName + `": ` + listOr(eventNames, "none") + `.`);
|
|
236
256
|
}
|
|
237
257
|
}
|
|
238
258
|
|
package/src/Hasura.res
CHANGED
|
@@ -286,9 +286,7 @@ let createSelectPermission = async (
|
|
|
286
286
|
// column joins alongside the id — without it the relationship would resolve to
|
|
287
287
|
// another chain's row with the same id.
|
|
288
288
|
let makeColumnMapping = (~relationalKey, ~isDerivedFrom, ~chainIdColumn) => {
|
|
289
|
-
let pairs = [
|
|
290
|
-
isDerivedFrom ? `"id": "${relationalKey}"` : `"${relationalKey}": "id"`,
|
|
291
|
-
]
|
|
289
|
+
let pairs = [isDerivedFrom ? `"id": "${relationalKey}"` : `"${relationalKey}": "id"`]
|
|
292
290
|
switch chainIdColumn {
|
|
293
291
|
| Some(column) => pairs->Array.push(`"${column}": "${column}"`)->ignore
|
|
294
292
|
| None => ()
|
|
@@ -309,7 +307,6 @@ let createEntityRelationship = async (
|
|
|
309
307
|
~chainIdColumn: option<string>,
|
|
310
308
|
~comment: option<string>=?,
|
|
311
309
|
) => {
|
|
312
|
-
|
|
313
310
|
let tableJson = {
|
|
314
311
|
"schema": pgSchema,
|
|
315
312
|
"name": tableName,
|
|
@@ -347,15 +344,7 @@ let createEntityRelationship = async (
|
|
|
347
344
|
)
|
|
348
345
|
}
|
|
349
346
|
|
|
350
|
-
let
|
|
351
|
-
~endpoint,
|
|
352
|
-
~auth,
|
|
353
|
-
~pgSchema,
|
|
354
|
-
~userEntities: array<Internal.entityConfig>,
|
|
355
|
-
~aggregateEntities,
|
|
356
|
-
~responseLimit,
|
|
357
|
-
~schema,
|
|
358
|
-
) => {
|
|
347
|
+
let makeTableConfigs = (~userEntities: array<Internal.entityConfig>) => {
|
|
359
348
|
let exposedInternalTableConfigs = [
|
|
360
349
|
{
|
|
361
350
|
tableName: InternalTable.RawEvents.table.tableName,
|
|
@@ -373,12 +362,27 @@ let trackDatabase = async (
|
|
|
373
362
|
columnConfigs: dict{},
|
|
374
363
|
},
|
|
375
364
|
]
|
|
376
|
-
let userTableConfigs =
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
365
|
+
let userTableConfigs =
|
|
366
|
+
userEntities
|
|
367
|
+
->Array.filter(entity => !entity.internal)
|
|
368
|
+
->Array.map(entity => {
|
|
369
|
+
tableName: entity.table.tableName,
|
|
370
|
+
description: entity.table.description,
|
|
371
|
+
columnConfigs: entity.table->makeColumnConfigs,
|
|
372
|
+
})
|
|
373
|
+
[exposedInternalTableConfigs, userTableConfigs]->Array.flat
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
let trackDatabase = async (
|
|
377
|
+
~endpoint,
|
|
378
|
+
~auth,
|
|
379
|
+
~pgSchema,
|
|
380
|
+
~userEntities: array<Internal.entityConfig>,
|
|
381
|
+
~aggregateEntities,
|
|
382
|
+
~responseLimit,
|
|
383
|
+
~schema,
|
|
384
|
+
) => {
|
|
385
|
+
let tableConfigs = makeTableConfigs(~userEntities)
|
|
382
386
|
let tableNames = tableConfigs->Array.map(c => c.tableName)
|
|
383
387
|
|
|
384
388
|
Logging.info("Tracking tables in Hasura")
|
|
@@ -414,10 +418,14 @@ let trackDatabase = async (
|
|
|
414
418
|
->Option.flatMap(e => e.table->Table.getChainIdField)
|
|
415
419
|
->Option.map(Table.getPgDbFieldName)
|
|
416
420
|
|
|
417
|
-
|
|
418
|
-
|
|
421
|
+
// Relationships to an @internal entity can't exist here: codegen rejects a
|
|
422
|
+
// reference from an exposed entity to an @internal one.
|
|
423
|
+
let exposedEntities = userEntities->Array.filter(e => !e.internal)
|
|
424
|
+
for i in 0 to exposedEntities->Array.length - 1 {
|
|
425
|
+
let entityConfig = exposedEntities->Array.getUnsafe(i)
|
|
419
426
|
let {tableName} = entityConfig.table
|
|
420
|
-
let ownChainIdColumn =
|
|
427
|
+
let ownChainIdColumn =
|
|
428
|
+
entityConfig.table->Table.getChainIdField->Option.map(Table.getPgDbFieldName)
|
|
421
429
|
let sharedChainIdColumn = mappedEntity =>
|
|
422
430
|
switch (ownChainIdColumn, chainIdColumnOf(mappedEntity)) {
|
|
423
431
|
| (Some(column), Some(_)) => Some(column)
|
package/src/Hasura.res.mjs
CHANGED
|
@@ -285,7 +285,7 @@ async function createEntityRelationship(endpoint, auth, pgSchema, tableName, rel
|
|
|
285
285
|
});
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
-
|
|
288
|
+
function makeTableConfigs(userEntities) {
|
|
289
289
|
let exposedInternalTableConfigs = [
|
|
290
290
|
{
|
|
291
291
|
tableName: InternalTable.RawEvents.table.tableName,
|
|
@@ -303,15 +303,19 @@ async function trackDatabase(endpoint, auth, pgSchema, userEntities, aggregateEn
|
|
|
303
303
|
columnConfigs: {}
|
|
304
304
|
}
|
|
305
305
|
];
|
|
306
|
-
let userTableConfigs = userEntities.map(entity => ({
|
|
306
|
+
let userTableConfigs = userEntities.filter(entity => !entity.internal).map(entity => ({
|
|
307
307
|
tableName: entity.table.tableName,
|
|
308
308
|
description: entity.table.description,
|
|
309
309
|
columnConfigs: makeColumnConfigs(entity.table)
|
|
310
310
|
}));
|
|
311
|
-
|
|
311
|
+
return [
|
|
312
312
|
exposedInternalTableConfigs,
|
|
313
313
|
userTableConfigs
|
|
314
314
|
].flat();
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
async function trackDatabase(endpoint, auth, pgSchema, userEntities, aggregateEntities, responseLimit, schema) {
|
|
318
|
+
let tableConfigs = makeTableConfigs(userEntities);
|
|
315
319
|
let tableNames = tableConfigs.map(c => c.tableName);
|
|
316
320
|
Logging.info("Tracking tables in Hasura");
|
|
317
321
|
await clearHasuraMetadata(endpoint, auth);
|
|
@@ -322,8 +326,9 @@ async function trackDatabase(endpoint, auth, pgSchema, userEntities, aggregateEn
|
|
|
322
326
|
await createSelectPermission(endpoint, auth, tableName, pgSchema, responseLimit, aggregateEntities);
|
|
323
327
|
}
|
|
324
328
|
let chainIdColumnOf = entityName => Stdlib_Option.map(Stdlib_Option.flatMap(userEntities.find(e => e.name === entityName), e => Table.getChainIdField(e.table)), Table.getPgDbFieldName);
|
|
325
|
-
|
|
326
|
-
|
|
329
|
+
let exposedEntities = userEntities.filter(e => !e.internal);
|
|
330
|
+
for (let i$1 = 0, i_finish$1 = exposedEntities.length; i$1 < i_finish$1; ++i$1) {
|
|
331
|
+
let entityConfig = exposedEntities[i$1];
|
|
327
332
|
let match = entityConfig.table;
|
|
328
333
|
let tableName$1 = match.tableName;
|
|
329
334
|
let ownChainIdColumn = Stdlib_Option.map(Table.getChainIdField(entityConfig.table), Table.getPgDbFieldName);
|
|
@@ -365,6 +370,7 @@ export {
|
|
|
365
370
|
createSelectPermission,
|
|
366
371
|
makeColumnMapping,
|
|
367
372
|
createEntityRelationship,
|
|
373
|
+
makeTableConfigs,
|
|
368
374
|
trackDatabase,
|
|
369
375
|
}
|
|
370
376
|
/* Rest Not a pure module */
|
package/src/InMemoryStore.res
CHANGED
|
@@ -127,14 +127,18 @@ let dropCommittedEffects = (
|
|
|
127
127
|
|
|
128
128
|
let prepareRollbackDiff = async (
|
|
129
129
|
state: IndexerState.t,
|
|
130
|
+
~rollbackScope: RollbackScope.t,
|
|
130
131
|
~rollbackTargetCheckpointId,
|
|
131
132
|
~rollbackDiffCheckpointId,
|
|
132
|
-
~
|
|
133
|
+
~progressedChains,
|
|
134
|
+
~rolledBackAddresses,
|
|
133
135
|
) => {
|
|
134
136
|
state->IndexerState.beginRollbackDiff(
|
|
135
137
|
~targetCheckpointId=rollbackTargetCheckpointId,
|
|
136
138
|
~diffCheckpointId=rollbackDiffCheckpointId,
|
|
137
|
-
~
|
|
139
|
+
~scope=rollbackScope,
|
|
140
|
+
~progressedChains,
|
|
141
|
+
~rolledBackAddresses,
|
|
138
142
|
)
|
|
139
143
|
let persistence = state->IndexerState.persistence
|
|
140
144
|
let committedCheckpointId = state->IndexerState.committedCheckpointId
|
|
@@ -148,8 +152,9 @@ let prepareRollbackDiff = async (
|
|
|
148
152
|
let _ = await persistence.allEntities
|
|
149
153
|
->Array.filter(entityConfig => entityConfig.storage.postgres)
|
|
150
154
|
->Array.map(async entityConfig => {
|
|
151
|
-
let (removals,
|
|
155
|
+
let (removals, restoredEntities) = await persistence.storage.getRollbackData(
|
|
152
156
|
~entityConfig,
|
|
157
|
+
~scope=rollbackScope,
|
|
153
158
|
~rollbackTargetCheckpointId,
|
|
154
159
|
)
|
|
155
160
|
|
|
@@ -166,11 +171,6 @@ let prepareRollbackDiff = async (
|
|
|
166
171
|
)
|
|
167
172
|
})
|
|
168
173
|
|
|
169
|
-
let restoredEntities =
|
|
170
|
-
restoredEntitiesResult
|
|
171
|
-
->S.parseOrThrow(entityConfig.table->Table.pgRowsSchema)
|
|
172
|
-
->(Utils.magic: array<unknown> => array<Internal.entity>)
|
|
173
|
-
|
|
174
174
|
restoredEntities->Array.forEach((entity: Internal.entity) => {
|
|
175
175
|
let scope = entity->takeRowScope(~entityConfig)
|
|
176
176
|
setEntities->Utils.Dict.push(entityConfig.name, entity.id)
|
|
@@ -199,12 +199,6 @@ let prepareRollbackDiff = async (
|
|
|
199
199
|
// registered them: the store is where they already live, and it knows which
|
|
200
200
|
// ones the database hasn't seen yet.
|
|
201
201
|
let setBatchDcs = (state: IndexerState.t, ~batch: Batch.t) => {
|
|
202
|
-
let inMemTable = state->getInMemTable(
|
|
203
|
-
~entityConfig=InternalTable.EnvioAddresses.entityConfig,
|
|
204
|
-
~scope=CrossChain,
|
|
205
|
-
)
|
|
206
|
-
let committedCheckpointId = state->IndexerState.committedCheckpointId
|
|
207
|
-
|
|
208
202
|
batch.progressedChainsById->Utils.Dict.forEach(progressedChain => {
|
|
209
203
|
let chainId = progressedChain.fetchState.chainId
|
|
210
204
|
let chainState = state->IndexerState.getChainState(~chainId)
|
|
@@ -224,31 +218,22 @@ let setBatchDcs = (state: IndexerState.t, ~batch: Batch.t) => {
|
|
|
224
218
|
}
|
|
225
219
|
}
|
|
226
220
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
->Array.forEach(dc => {
|
|
233
|
-
let entity: InternalTable.EnvioAddresses.t = {
|
|
234
|
-
id: InternalTable.EnvioAddresses.makeId(~chainId, ~address=dc.address),
|
|
235
|
-
chainId,
|
|
236
|
-
contractName: dc.contractName,
|
|
237
|
-
registrationBlock: dc.registrationBlock,
|
|
238
|
-
// Only ever written, never read back. Kept on the table so the column
|
|
239
|
-
// doesn't need a migration.
|
|
240
|
-
registrationLogIndex: -1,
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
inMemTable->InMemoryTable.Entity.set(
|
|
244
|
-
~committedCheckpointId,
|
|
245
|
-
Set({
|
|
246
|
-
entityId: entity.id->EntityId.unsafeOfString,
|
|
247
|
-
checkpointId: checkpointIds->Array.getUnsafe(dc.checkpointIdx),
|
|
248
|
-
entity: entity->InternalTable.EnvioAddresses.castToInternal,
|
|
249
|
-
}),
|
|
221
|
+
batch.registeredAddresses->Array.pushMany(
|
|
222
|
+
chainState
|
|
223
|
+
->ChainState.drainAddressesForWrite(
|
|
224
|
+
~toBlockInclusive=progressedChain.progressBlockNumber,
|
|
225
|
+
~checkpointBlockNumbers,
|
|
250
226
|
)
|
|
251
|
-
|
|
227
|
+
->Array.map((dc): AddressRows.staged => {
|
|
228
|
+
row: {
|
|
229
|
+
chainId,
|
|
230
|
+
address: dc.address,
|
|
231
|
+
contractId: dc.contractId,
|
|
232
|
+
registrationBlock: dc.registrationBlock,
|
|
233
|
+
},
|
|
234
|
+
checkpointId: checkpointIds->Array.getUnsafe(dc.checkpointIdx),
|
|
235
|
+
}),
|
|
236
|
+
)->ignore
|
|
252
237
|
}
|
|
253
238
|
})
|
|
254
239
|
}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import * as Table from "./db/Table.res.mjs";
|
|
4
4
|
import * as Utils from "./Utils.res.mjs";
|
|
5
|
-
import * as Config from "./Config.res.mjs";
|
|
6
5
|
import * as Internal from "./Internal.res.mjs";
|
|
7
6
|
import * as ChainState from "./ChainState.res.mjs";
|
|
8
7
|
import * as EffectState from "./EffectState.res.mjs";
|
|
@@ -12,7 +11,6 @@ import * as InMemoryTable from "./InMemoryTable.res.mjs";
|
|
|
12
11
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
13
12
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
14
13
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
15
|
-
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
16
14
|
|
|
17
15
|
function getInMemTable(state, entityConfig, scope) {
|
|
18
16
|
let tmp;
|
|
@@ -108,14 +106,14 @@ function dropCommittedEffects(inMemTable, committedCheckpointId, keepLoadedFromD
|
|
|
108
106
|
inMemTable.changesCount = inMemTable.changesCount - keysToDelete.length;
|
|
109
107
|
}
|
|
110
108
|
|
|
111
|
-
async function prepareRollbackDiff(state, rollbackTargetCheckpointId, rollbackDiffCheckpointId,
|
|
112
|
-
IndexerState.beginRollbackDiff(state, rollbackTargetCheckpointId, rollbackDiffCheckpointId,
|
|
109
|
+
async function prepareRollbackDiff(state, rollbackScope, rollbackTargetCheckpointId, rollbackDiffCheckpointId, progressedChains, rolledBackAddresses) {
|
|
110
|
+
IndexerState.beginRollbackDiff(state, rollbackTargetCheckpointId, rollbackDiffCheckpointId, rollbackScope, progressedChains, rolledBackAddresses);
|
|
113
111
|
let persistence = IndexerState.persistence(state);
|
|
114
112
|
let committedCheckpointId = IndexerState.committedCheckpointId(state);
|
|
115
113
|
let deletedEntities = {};
|
|
116
114
|
let setEntities = {};
|
|
117
115
|
await Promise.all(persistence.allEntities.filter(entityConfig => entityConfig.storage.postgres).map(async entityConfig => {
|
|
118
|
-
let match = await persistence.storage.getRollbackData(entityConfig, rollbackTargetCheckpointId);
|
|
116
|
+
let match = await persistence.storage.getRollbackData(entityConfig, rollbackScope, rollbackTargetCheckpointId);
|
|
119
117
|
match[0].forEach(param => {
|
|
120
118
|
let entityId = param.entityId;
|
|
121
119
|
Utils.Dict.push(deletedEntities, entityConfig.name, entityId);
|
|
@@ -125,8 +123,7 @@ async function prepareRollbackDiff(state, rollbackTargetCheckpointId, rollbackDi
|
|
|
125
123
|
checkpointId: rollbackDiffCheckpointId
|
|
126
124
|
});
|
|
127
125
|
});
|
|
128
|
-
|
|
129
|
-
restoredEntities.forEach(entity => {
|
|
126
|
+
match[1].forEach(entity => {
|
|
130
127
|
let scope = takeRowScope(entity, entityConfig);
|
|
131
128
|
Utils.Dict.push(setEntities, entityConfig.name, entity.id);
|
|
132
129
|
InMemoryTable.Entity.set(getInMemTable(state, entityConfig, scope), committedCheckpointId, {
|
|
@@ -144,8 +141,6 @@ async function prepareRollbackDiff(state, rollbackTargetCheckpointId, rollbackDi
|
|
|
144
141
|
}
|
|
145
142
|
|
|
146
143
|
function setBatchDcs(state, batch) {
|
|
147
|
-
let inMemTable = getInMemTable(state, Config.EnvioAddresses.entityConfig, "crossChain");
|
|
148
|
-
let committedCheckpointId = IndexerState.committedCheckpointId(state);
|
|
149
144
|
Utils.Dict.forEach(batch.progressedChainsById, progressedChain => {
|
|
150
145
|
let chainId = progressedChain.fetchState.chainId;
|
|
151
146
|
let chainState = IndexerState.getChainState(state, chainId);
|
|
@@ -160,24 +155,15 @@ function setBatchDcs(state, batch) {
|
|
|
160
155
|
checkpointBlockNumbers.push(batch.checkpointBlockNumbers[idx]);
|
|
161
156
|
}
|
|
162
157
|
}
|
|
163
|
-
ChainState.drainAddressesForWrite(chainState, progressedChain.progressBlockNumber, checkpointBlockNumbers).
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
contract_name: entity_contract_name
|
|
173
|
-
};
|
|
174
|
-
InMemoryTable.Entity.set(inMemTable, committedCheckpointId, {
|
|
175
|
-
type: "SET",
|
|
176
|
-
entityId: entity_id,
|
|
177
|
-
entity: entity,
|
|
178
|
-
checkpointId: checkpointIds[dc.checkpointIdx]
|
|
179
|
-
});
|
|
180
|
-
});
|
|
158
|
+
batch.registeredAddresses.push(...ChainState.drainAddressesForWrite(chainState, progressedChain.progressBlockNumber, checkpointBlockNumbers).map(dc => ({
|
|
159
|
+
row: {
|
|
160
|
+
chainId: chainId,
|
|
161
|
+
address: dc.address,
|
|
162
|
+
contractId: dc.contractId,
|
|
163
|
+
registrationBlock: dc.registrationBlock
|
|
164
|
+
},
|
|
165
|
+
checkpointId: checkpointIds[dc.checkpointIdx]
|
|
166
|
+
})));
|
|
181
167
|
});
|
|
182
168
|
}
|
|
183
169
|
|