envio
Version:
A latency and sync speed optimized, developer friendly blockchain data indexer.
1,081 lines (1,034 loc) • 43 kB
JavaScript
// Generated by ReScript, PLEASE EDIT WITH CARE
'use strict';
var Caml = require("rescript/lib/js/caml.js");
var Utils = require("./Utils.res.js");
var Js_exn = require("rescript/lib/js/js_exn.js");
var Js_dict = require("rescript/lib/js/js_dict.js");
var Js_math = require("rescript/lib/js/js_math.js");
var Logging = require("./Logging.res.js");
var Belt_Int = require("rescript/lib/js/belt_Int.js");
var Belt_Array = require("rescript/lib/js/belt_Array.js");
var Caml_int32 = require("rescript/lib/js/caml_int32.js");
var Prometheus = require("./Prometheus.res.js");
var Belt_Option = require("rescript/lib/js/belt_Option.js");
var Belt_Result = require("rescript/lib/js/belt_Result.js");
var Caml_exceptions = require("rescript/lib/js/caml_exceptions.js");
function mergeIntoPartition(p, target, maxAddrInPartition) {
if (!p.selection.dependsOnAddresses) {
return [
p,
target
];
}
if (!target.selection.dependsOnAddresses) {
return [
p,
target
];
}
var latestFetchedBlock = target.latestFetchedBlock;
var mergedAddresses = {};
var allowedAddressesNumber = {
contents: maxAddrInPartition
};
Utils.Dict.forEachWithKey(target.addressesByContractName, (function (addresses, contractName) {
allowedAddressesNumber.contents = allowedAddressesNumber.contents - addresses.length | 0;
mergedAddresses[contractName] = addresses;
}));
Utils.Dict.forEachWithKey(p.addressesByContractName, (function (addresses, contractName) {
allowedAddressesNumber.contents = allowedAddressesNumber.contents - addresses.length | 0;
var targetAddresses = mergedAddresses[contractName];
if (targetAddresses !== undefined) {
mergedAddresses[contractName] = Belt_Array.concat(targetAddresses, addresses);
} else {
mergedAddresses[contractName] = addresses;
}
}));
var rest;
if (allowedAddressesNumber.contents < 0) {
var restAddresses = {};
Utils.Dict.forEachWithKey(mergedAddresses, (function (addresses, contractName) {
if (allowedAddressesNumber.contents === 0) {
return ;
}
if (addresses.length <= (-allowedAddressesNumber.contents | 0)) {
allowedAddressesNumber.contents = allowedAddressesNumber.contents + addresses.length | 0;
Utils.Dict.deleteInPlace(mergedAddresses, contractName);
restAddresses[contractName] = addresses;
return ;
}
var restFrom = addresses.length + allowedAddressesNumber.contents | 0;
mergedAddresses[contractName] = addresses.slice(0, restFrom);
restAddresses[contractName] = addresses.slice(restFrom);
allowedAddressesNumber.contents = 0;
}));
rest = {
id: p.id,
status: {
fetchingStateId: undefined
},
latestFetchedBlock: latestFetchedBlock,
selection: target.selection,
addressesByContractName: restAddresses
};
} else {
rest = undefined;
}
return [
{
id: target.id,
status: {
fetchingStateId: undefined
},
latestFetchedBlock: latestFetchedBlock,
selection: target.selection,
addressesByContractName: mergedAddresses
},
rest
];
}
function bufferBlockNumber(param) {
var latestOnBlockBlockNumber = param.latestOnBlockBlockNumber;
var latestFullyFetchedBlock = param.latestFullyFetchedBlock;
if (latestOnBlockBlockNumber < latestFullyFetchedBlock.blockNumber) {
return latestOnBlockBlockNumber;
} else {
return latestFullyFetchedBlock.blockNumber;
}
}
function bufferBlock(param) {
var latestOnBlockBlockNumber = param.latestOnBlockBlockNumber;
var latestFullyFetchedBlock = param.latestFullyFetchedBlock;
if (latestOnBlockBlockNumber < latestFullyFetchedBlock.blockNumber) {
return {
blockNumber: latestOnBlockBlockNumber,
blockTimestamp: 0
};
} else {
return latestFullyFetchedBlock;
}
}
function compareBufferItem(a, b) {
var blockDiff = a.blockNumber - b.blockNumber | 0;
if (blockDiff === 0) {
return a.logIndex - b.logIndex | 0;
} else {
return blockDiff;
}
}
function updateInternal(fetchState, partitionsOpt, nextPartitionIndexOpt, indexingContractsOpt, mutItems, blockLagOpt) {
var partitions = partitionsOpt !== undefined ? partitionsOpt : fetchState.partitions;
var nextPartitionIndex = nextPartitionIndexOpt !== undefined ? nextPartitionIndexOpt : fetchState.nextPartitionIndex;
var indexingContracts = indexingContractsOpt !== undefined ? indexingContractsOpt : fetchState.indexingContracts;
var blockLag = blockLagOpt !== undefined ? blockLagOpt : fetchState.blockLag;
var firstPartition = partitions[0];
var latestFullyFetchedBlock = firstPartition.latestFetchedBlock;
for(var idx = 0 ,idx_finish = partitions.length; idx < idx_finish; ++idx){
var p = partitions[idx];
if (latestFullyFetchedBlock.blockNumber > p.latestFetchedBlock.blockNumber) {
latestFullyFetchedBlock = p.latestFetchedBlock;
}
}
var latestFullyFetchedBlock$1 = latestFullyFetchedBlock;
var mutItemsRef = mutItems;
var onBlockConfigs = fetchState.onBlockConfigs;
var latestOnBlockBlockNumber;
if (onBlockConfigs.length !== 0) {
var mutItems$1 = mutItemsRef;
var item = Belt_Array.get(mutItems$1 !== undefined ? mutItems$1 : fetchState.buffer, fetchState.targetBufferSize - 1 | 0);
var maxBlockNumber = item !== undefined ? item.blockNumber : latestFullyFetchedBlock$1.blockNumber;
var mutItems$2 = mutItemsRef;
var mutItems$3 = mutItems$2 !== undefined ? mutItems$2 : fetchState.buffer.slice(0);
mutItemsRef = mutItems$3;
var newItemsCounter = 0;
var latestOnBlockBlockNumber$1 = fetchState.latestOnBlockBlockNumber;
while(latestOnBlockBlockNumber$1 < maxBlockNumber && newItemsCounter <= fetchState.targetBufferSize) {
var blockNumber = latestOnBlockBlockNumber$1 + 1 | 0;
latestOnBlockBlockNumber$1 = blockNumber;
for(var configIdx = 0 ,configIdx_finish = onBlockConfigs.length; configIdx < configIdx_finish; ++configIdx){
var onBlockConfig = onBlockConfigs[configIdx];
var startBlock = onBlockConfig.startBlock;
var handlerStartBlock = startBlock !== undefined ? startBlock : fetchState.startBlock;
var tmp = false;
if (blockNumber >= handlerStartBlock) {
var endBlock = onBlockConfig.endBlock;
tmp = endBlock !== undefined ? blockNumber <= endBlock : true;
}
if (tmp && Caml_int32.mod_(blockNumber - handlerStartBlock | 0, onBlockConfig.interval) === 0) {
mutItems$3.push({
kind: 1,
onBlockConfig: onBlockConfig,
blockNumber: blockNumber,
logIndex: 16777216 + onBlockConfig.index | 0
});
newItemsCounter = newItemsCounter + 1 | 0;
}
}
};
latestOnBlockBlockNumber = latestOnBlockBlockNumber$1;
} else {
latestOnBlockBlockNumber = latestFullyFetchedBlock$1.blockNumber;
}
var mutItems$4 = mutItemsRef;
var updatedFetchState_startBlock = fetchState.startBlock;
var updatedFetchState_endBlock = fetchState.endBlock;
var updatedFetchState_maxAddrInPartition = fetchState.maxAddrInPartition;
var updatedFetchState_normalSelection = fetchState.normalSelection;
var updatedFetchState_contractConfigs = fetchState.contractConfigs;
var updatedFetchState_chainId = fetchState.chainId;
var updatedFetchState_buffer = mutItems$4 !== undefined ? mutItems$4.sort(compareBufferItem) : fetchState.buffer;
var updatedFetchState_targetBufferSize = fetchState.targetBufferSize;
var updatedFetchState_onBlockConfigs = fetchState.onBlockConfigs;
var updatedFetchState = {
partitions: partitions,
nextPartitionIndex: nextPartitionIndex,
startBlock: updatedFetchState_startBlock,
endBlock: updatedFetchState_endBlock,
maxAddrInPartition: updatedFetchState_maxAddrInPartition,
normalSelection: updatedFetchState_normalSelection,
indexingContracts: indexingContracts,
contractConfigs: updatedFetchState_contractConfigs,
chainId: updatedFetchState_chainId,
latestFullyFetchedBlock: latestFullyFetchedBlock$1,
latestOnBlockBlockNumber: latestOnBlockBlockNumber,
blockLag: blockLag,
buffer: updatedFetchState_buffer,
targetBufferSize: updatedFetchState_targetBufferSize,
onBlockConfigs: updatedFetchState_onBlockConfigs
};
Prometheus.IndexingPartitions.set(partitions.length, fetchState.chainId);
Prometheus.IndexingBufferSize.set(updatedFetchState_buffer.length, fetchState.chainId);
Prometheus.IndexingBufferBlockNumber.set(latestOnBlockBlockNumber < latestFullyFetchedBlock$1.blockNumber ? latestOnBlockBlockNumber : latestFullyFetchedBlock$1.blockNumber, fetchState.chainId);
return updatedFetchState;
}
function numAddresses(fetchState) {
return Object.keys(fetchState.indexingContracts).length;
}
function warnDifferentContractType(fetchState, existingContract, dc) {
var logger = Logging.createChild({
chainId: fetchState.chainId,
contractAddress: dc.address,
existingContractType: existingContract.contractName,
newContractType: dc.contractName
});
Logging.childWarn(logger, "Skipping contract registration: Contract address is already registered for one contract and cannot be registered for another contract.");
}
function registerDynamicContracts(fetchState, items) {
if (Utils.$$Array.isEmpty(fetchState.normalSelection.eventConfigs)) {
Js_exn.raiseError("Invalid configuration. No events to fetch for the dynamic contract registration.");
}
var indexingContracts = fetchState.indexingContracts;
var registeringContracts = {};
var addressesByContractName = {};
var earliestRegisteringEventBlockNumber = Infinity;
var hasDCWithFilterByAddresses = false;
for(var itemIdx = 0 ,itemIdx_finish = items.length; itemIdx < itemIdx_finish; ++itemIdx){
var item = items[itemIdx];
var dcs = item.dcs;
if (dcs !== undefined) {
var idx = 0;
while(idx < dcs.length) {
var dc = dcs[idx];
var shouldRemove = false;
var match = fetchState.contractConfigs[dc.contractName];
if (match !== undefined) {
var existingContract = indexingContracts[dc.address];
if (existingContract !== undefined) {
if (existingContract.contractName !== dc.contractName) {
warnDifferentContractType(fetchState, existingContract, dc);
} else if (existingContract.startBlock > dc.startBlock) {
var logger = Logging.createChild({
chainId: fetchState.chainId,
contractAddress: dc.address,
existingBlockNumber: existingContract.startBlock,
newBlockNumber: dc.startBlock
});
Logging.childWarn(logger, "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.");
}
shouldRemove = true;
} else {
var registeringContract = registeringContracts[dc.address];
var shouldUpdate;
if (registeringContract !== undefined) {
if (registeringContract.contractName !== dc.contractName) {
warnDifferentContractType(fetchState, registeringContract, dc);
shouldUpdate = false;
} else {
shouldUpdate = false;
}
} else {
hasDCWithFilterByAddresses = hasDCWithFilterByAddresses || match.filterByAddresses;
Utils.Dict.push(addressesByContractName, dc.contractName, dc.address);
shouldUpdate = true;
}
if (shouldUpdate) {
earliestRegisteringEventBlockNumber = earliestRegisteringEventBlockNumber < dc.startBlock ? earliestRegisteringEventBlockNumber : dc.startBlock;
registeringContracts[dc.address] = dc;
} else {
shouldRemove = true;
}
}
} else {
var logger$1 = Logging.createChild({
chainId: fetchState.chainId,
contractAddress: dc.address,
contractName: dc.contractName
});
Logging.childWarn(logger$1, "Skipping contract registration: Contract doesn't have any events to fetch.");
shouldRemove = true;
}
if (shouldRemove) {
dcs.splice(idx, 1);
} else {
idx = idx + 1 | 0;
}
};
}
}
var dcsToStore = Js_dict.values(registeringContracts);
if (dcsToStore.length === 0) {
return fetchState;
}
var newPartitions;
if (dcsToStore.length <= fetchState.maxAddrInPartition && !hasDCWithFilterByAddresses) {
newPartitions = [{
id: String(fetchState.nextPartitionIndex),
status: {
fetchingStateId: undefined
},
latestFetchedBlock: {
blockNumber: earliestRegisteringEventBlockNumber - 1 | 0,
blockTimestamp: 0
},
selection: fetchState.normalSelection,
addressesByContractName: addressesByContractName
}];
} else {
var partitions = [];
var earliestRegisteringEventBlockNumber$1 = {
contents: Infinity
};
var pendingAddressesByContractName = {
contents: {}
};
var pendingCount = 0;
var addPartition = function () {
partitions.push({
id: String(fetchState.nextPartitionIndex + partitions.length | 0),
status: {
fetchingStateId: undefined
},
latestFetchedBlock: {
blockNumber: earliestRegisteringEventBlockNumber$1.contents - 1 | 0,
blockTimestamp: 0
},
selection: fetchState.normalSelection,
addressesByContractName: pendingAddressesByContractName.contents
});
};
for(var idx$1 = 0 ,idx_finish = Object.keys(addressesByContractName).length; idx$1 < idx_finish; ++idx$1){
var contractName = Object.keys(addressesByContractName)[idx$1];
var addresses = addressesByContractName[contractName];
var contractConfig = fetchState.contractConfigs[contractName];
if (contractConfig.filterByAddresses) {
var byStartBlock = {};
for(var jdx = 0 ,jdx_finish = addresses.length; jdx < jdx_finish; ++jdx){
var address = addresses[jdx];
var indexingContract = registeringContracts[address];
Utils.Dict.push(byStartBlock, String(indexingContract.startBlock), address);
}
Object.keys(byStartBlock).forEach((function(contractName,byStartBlock){
return function (startBlockKey) {
var addresses = byStartBlock[startBlockKey];
var addressesByContractName = {};
addressesByContractName[contractName] = addresses;
partitions.push({
id: String(fetchState.nextPartitionIndex + partitions.length | 0),
status: {
fetchingStateId: undefined
},
latestFetchedBlock: {
blockNumber: Caml.int_max(Belt_Option.getExn(Belt_Int.fromString(startBlockKey)) - 1 | 0, 0),
blockTimestamp: 0
},
selection: fetchState.normalSelection,
addressesByContractName: addressesByContractName
});
}
}(contractName,byStartBlock)));
} else {
for(var jdx$1 = 0 ,jdx_finish$1 = addresses.length; jdx$1 < jdx_finish$1; ++jdx$1){
var address$1 = addresses[jdx$1];
if (pendingCount === fetchState.maxAddrInPartition) {
addPartition();
pendingAddressesByContractName.contents = {};
pendingCount = 0;
earliestRegisteringEventBlockNumber$1.contents = Infinity;
}
var indexingContract$1 = registeringContracts[address$1];
pendingCount = pendingCount + 1 | 0;
Utils.Dict.push(pendingAddressesByContractName.contents, contractName, address$1);
earliestRegisteringEventBlockNumber$1.contents = earliestRegisteringEventBlockNumber$1.contents < indexingContract$1.startBlock ? earliestRegisteringEventBlockNumber$1.contents : indexingContract$1.startBlock;
}
}
}
if (pendingCount > 0) {
addPartition();
}
newPartitions = partitions;
}
Prometheus.IndexingAddresses.set(Object.keys(fetchState.indexingContracts).length + dcsToStore.length | 0, fetchState.chainId);
return updateInternal(fetchState, fetchState.partitions.concat(newPartitions), fetchState.nextPartitionIndex + newPartitions.length | 0, Object.assign(registeringContracts, indexingContracts), undefined, undefined);
}
var UnexpectedPartitionNotFound = /* @__PURE__ */Caml_exceptions.create("FetchState.UnexpectedPartitionNotFound");
var UnexpectedMergeQueryResponse = /* @__PURE__ */Caml_exceptions.create("FetchState.UnexpectedMergeQueryResponse");
function handleQueryResult(fetchState, query, latestFetchedBlock, newItems) {
var partitions = fetchState.partitions;
var partitionId = query.partitionId;
var pIndex = Belt_Array.getIndexBy(partitions, (function (p) {
return p.id === partitionId;
}));
var tmp;
if (pIndex !== undefined) {
var p = partitions[pIndex];
var updatedPartition_id = p.id;
var updatedPartition_status = {
fetchingStateId: undefined
};
var updatedPartition_selection = p.selection;
var updatedPartition_addressesByContractName = p.addressesByContractName;
var updatedPartition = {
id: updatedPartition_id,
status: updatedPartition_status,
latestFetchedBlock: latestFetchedBlock,
selection: updatedPartition_selection,
addressesByContractName: updatedPartition_addressesByContractName
};
var match = query.target;
var exit = 0;
if (typeof match !== "object" || match.TAG === "EndBlock") {
exit = 1;
} else {
var intoPartitionId = match.intoPartitionId;
var targetIndex = Belt_Array.getIndexBy(partitions, (function (p) {
return p.id === intoPartitionId;
}));
var exit$1 = 0;
if (targetIndex !== undefined && partitions[targetIndex].latestFetchedBlock.blockNumber === latestFetchedBlock.blockNumber) {
var target = partitions[targetIndex];
var match$1 = mergeIntoPartition(updatedPartition, target, fetchState.maxAddrInPartition);
var rest = match$1[1];
var updatedPartitions = Utils.$$Array.setIndexImmutable(partitions, targetIndex, match$1[0]);
var updatedPartitions$1 = rest !== undefined ? (updatedPartitions[pIndex] = rest, updatedPartitions) : Utils.$$Array.removeAtIndex(updatedPartitions, pIndex);
tmp = {
TAG: "Ok",
_0: updatedPartitions$1
};
} else {
exit$1 = 2;
}
if (exit$1 === 2) {
tmp = {
TAG: "Ok",
_0: Utils.$$Array.setIndexImmutable(partitions, pIndex, updatedPartition)
};
}
}
if (exit === 1) {
tmp = {
TAG: "Ok",
_0: Utils.$$Array.setIndexImmutable(partitions, pIndex, updatedPartition)
};
}
} else {
tmp = {
TAG: "Error",
_0: {
RE_EXN_ID: UnexpectedPartitionNotFound,
partitionId: partitionId
}
};
}
return Belt_Result.map(tmp, (function (partitions) {
return updateInternal(fetchState, partitions, undefined, undefined, newItems.length !== 0 ? Belt_Array.concat(fetchState.buffer, newItems) : undefined, undefined);
}));
}
function makePartitionQuery(p, indexingContracts, endBlock, mergeTarget) {
var latestFetchedBlockNumber = p.latestFetchedBlock.blockNumber;
var fromBlock = latestFetchedBlockNumber !== 0 ? latestFetchedBlockNumber + 1 | 0 : 0;
var tmp;
var exit = 0;
if (endBlock !== undefined) {
if (fromBlock > endBlock) {
tmp = undefined;
} else if (mergeTarget !== undefined) {
exit = 1;
} else {
tmp = {
TAG: "EndBlock",
toBlock: endBlock
};
}
} else if (mergeTarget !== undefined) {
exit = 1;
} else {
tmp = "Head";
}
if (exit === 1) {
tmp = {
TAG: "Merge",
intoPartitionId: mergeTarget.id,
toBlock: mergeTarget.latestFetchedBlock.blockNumber
};
}
return Belt_Option.map(tmp, (function (target) {
return {
partitionId: p.id,
fromBlock: fromBlock,
selection: p.selection,
addressesByContractName: p.addressesByContractName,
target: target,
indexingContracts: indexingContracts
};
}));
}
function startFetchingQueries(param, queries, stateId) {
var partitions = param.partitions;
Belt_Array.forEach(queries, (function (q) {
var p = partitions.find(function (p) {
return p.id === q.partitionId;
});
if (p !== undefined) {
p.status.fetchingStateId = stateId;
return ;
} else {
return Js_exn.raiseError("Unexpected case: Couldn't find partition for the fetching query");
}
}));
}
function addressesByContractNameCount(addressesByContractName) {
var numAddresses = 0;
var contractNames = Object.keys(addressesByContractName);
for(var idx = 0 ,idx_finish = contractNames.length; idx < idx_finish; ++idx){
var contractName = contractNames[idx];
numAddresses = numAddresses + addressesByContractName[contractName].length | 0;
}
return numAddresses;
}
function addressesByContractNameGetAll(addressesByContractName) {
var all = [];
var contractNames = Object.keys(addressesByContractName);
for(var idx = 0 ,idx_finish = contractNames.length; idx < idx_finish; ++idx){
var contractName = contractNames[idx];
all = Belt_Array.concat(all, addressesByContractName[contractName]);
}
return all;
}
function isFullPartition(p, maxAddrInPartition) {
if (p.selection.dependsOnAddresses) {
return addressesByContractNameCount(p.addressesByContractName) >= maxAddrInPartition;
} else {
return true;
}
}
function getNextQuery(param, concurrencyLimit, currentBlockHeight, stateId) {
var blockLag = param.blockLag;
var indexingContracts = param.indexingContracts;
var maxAddrInPartition = param.maxAddrInPartition;
var endBlock = param.endBlock;
var partitions = param.partitions;
var headBlock = currentBlockHeight - blockLag | 0;
if (headBlock <= 0) {
return "WaitingForNewBlock";
}
if (concurrencyLimit === 0) {
return "ReachedMaxConcurrency";
}
var fullPartitions = [];
var mergingPartitions = [];
var areMergingPartitionsFetching = false;
var mostBehindMergingPartition;
var mergingPartitionTarget;
var shouldWaitForNewBlock = endBlock !== undefined ? headBlock < endBlock : true;
var checkIsFetchingPartition = function (p) {
var fetchingStateId = p.status.fetchingStateId;
if (fetchingStateId !== undefined) {
return stateId <= fetchingStateId;
} else {
return false;
}
};
for(var idx = 0 ,idx_finish = partitions.length; idx < idx_finish; ++idx){
var p = partitions[idx];
var isFetching = checkIsFetchingPartition(p);
var hasReachedTheHead = p.latestFetchedBlock.blockNumber >= headBlock;
if (isFetching || !hasReachedTheHead) {
shouldWaitForNewBlock = false;
}
if (p.selection.dependsOnAddresses ? addressesByContractNameCount(p.addressesByContractName) >= maxAddrInPartition : true) {
fullPartitions.push(p);
} else {
mergingPartitions.push(p);
var mostBehindMergingPartition$1 = mostBehindMergingPartition;
var tmp;
if (mostBehindMergingPartition$1 !== undefined) {
if (mostBehindMergingPartition$1.latestFetchedBlock.blockNumber === p.latestFetchedBlock.blockNumber) {
tmp = mostBehindMergingPartition$1;
} else if (mostBehindMergingPartition$1.latestFetchedBlock.blockNumber < p.latestFetchedBlock.blockNumber) {
var mergingPartitionTarget$1 = mergingPartitionTarget;
mergingPartitionTarget = mergingPartitionTarget$1 !== undefined && mergingPartitionTarget$1.latestFetchedBlock.blockNumber < p.latestFetchedBlock.blockNumber ? mergingPartitionTarget$1 : p;
tmp = mostBehindMergingPartition$1;
} else {
mergingPartitionTarget = mostBehindMergingPartition$1;
tmp = p;
}
} else {
tmp = p;
}
mostBehindMergingPartition = tmp;
if (isFetching) {
areMergingPartitionsFetching = true;
}
}
}
var item = Belt_Array.get(param.buffer, param.targetBufferSize - 1 | 0);
var maxQueryBlockNumber = item !== undefined && item.blockNumber < currentBlockHeight ? item.blockNumber : currentBlockHeight;
var queries = [];
var registerPartitionQuery = function (p, mergeTarget) {
if (!(!checkIsFetchingPartition(p) && p.latestFetchedBlock.blockNumber < maxQueryBlockNumber)) {
return ;
}
var endBlock$1 = blockLag !== 0 ? (
endBlock !== undefined ? (
headBlock < endBlock ? headBlock : endBlock
) : headBlock
) : endBlock;
var match = maxQueryBlockNumber < currentBlockHeight;
var endBlock$2 = endBlock$1 !== undefined ? (
match ? (
maxQueryBlockNumber < endBlock$1 ? maxQueryBlockNumber : endBlock$1
) : endBlock$1
) : (
match ? maxQueryBlockNumber : endBlock$1
);
var q = makePartitionQuery(p, indexingContracts, endBlock$2, mergeTarget);
if (q !== undefined) {
queries.push(q);
return ;
}
};
Belt_Array.forEach(fullPartitions, (function (p) {
registerPartitionQuery(p, undefined);
}));
if (!areMergingPartitionsFetching) {
var len = mergingPartitions.length;
if (len !== 1) {
if (len !== 0) {
var match = mostBehindMergingPartition;
var match$1 = mergingPartitionTarget;
if (match !== undefined) {
if (match$1 !== undefined) {
registerPartitionQuery(match, match$1);
} else {
registerPartitionQuery(match, undefined);
}
} else {
Js_exn.raiseError("Unexpected case, should always have a most behind partition.");
}
}
} else {
var p$1 = mergingPartitions[0];
registerPartitionQuery(p$1, undefined);
}
}
if (Utils.$$Array.isEmpty(queries)) {
if (shouldWaitForNewBlock) {
return "WaitingForNewBlock";
} else {
return "NothingToQuery";
}
} else {
return {
TAG: "Ready",
_0: queries.length > concurrencyLimit ? queries.sort(function (a, b) {
return a.fromBlock - b.fromBlock | 0;
}).slice(0, concurrencyLimit) : queries
};
}
}
function getTimestampAt(fetchState, index) {
var match = Belt_Array.get(fetchState.buffer, index);
if (match !== undefined) {
if (match.kind === 0) {
return match.timestamp;
} else {
return Js_exn.raiseError("Block handlers are not supported for ordered multichain mode.");
}
}
var latestOnBlockBlockNumber = fetchState.latestOnBlockBlockNumber;
var latestFullyFetchedBlock = fetchState.latestFullyFetchedBlock;
return (
latestOnBlockBlockNumber < latestFullyFetchedBlock.blockNumber ? ({
blockNumber: latestOnBlockBlockNumber,
blockTimestamp: 0
}) : latestFullyFetchedBlock
).blockTimestamp;
}
function hasReadyItem(fetchState) {
var item = Belt_Array.get(fetchState.buffer, 0);
if (item === undefined) {
return false;
}
var latestOnBlockBlockNumber = fetchState.latestOnBlockBlockNumber;
var latestFullyFetchedBlock = fetchState.latestFullyFetchedBlock;
return item.blockNumber <= (
latestOnBlockBlockNumber < latestFullyFetchedBlock.blockNumber ? latestOnBlockBlockNumber : latestFullyFetchedBlock.blockNumber
);
}
function getReadyItemsCount(fetchState, targetSize, fromItem) {
var latestOnBlockBlockNumber = fetchState.latestOnBlockBlockNumber;
var latestFullyFetchedBlock = fetchState.latestFullyFetchedBlock;
var readyBlockNumber = latestOnBlockBlockNumber < latestFullyFetchedBlock.blockNumber ? latestOnBlockBlockNumber : latestFullyFetchedBlock.blockNumber;
var acc = 0;
var isFinished = false;
while(!isFinished) {
var item = Belt_Array.get(fetchState.buffer, fromItem + acc | 0);
if (item !== undefined) {
var itemBlockNumber = item.blockNumber;
if (itemBlockNumber <= readyBlockNumber) {
acc = acc + 1 | 0;
if (acc === targetSize) {
readyBlockNumber = itemBlockNumber;
}
} else {
isFinished = true;
}
} else {
isFinished = true;
}
};
return acc;
}
function make(startBlock, endBlock, eventConfigs, contracts, maxAddrInPartition, chainId, targetBufferSize, progressBlockNumberOpt, onBlockConfigsOpt, blockLagOpt) {
var progressBlockNumber = progressBlockNumberOpt !== undefined ? progressBlockNumberOpt : startBlock - 1 | 0;
var onBlockConfigs = onBlockConfigsOpt !== undefined ? onBlockConfigsOpt : [];
var blockLag = blockLagOpt !== undefined ? blockLagOpt : 0;
var latestFetchedBlock = {
blockNumber: progressBlockNumber,
blockTimestamp: 0
};
var notDependingOnAddresses = [];
var normalEventConfigs = [];
var contractNamesWithNormalEvents = new Set();
var indexingContracts = {};
var contractConfigs = {};
Belt_Array.forEach(eventConfigs, (function (ec) {
var match = contractConfigs[ec.contractName];
if (match !== undefined) {
contractConfigs[ec.contractName] = {
filterByAddresses: match.filterByAddresses || ec.filterByAddresses
};
} else {
contractConfigs[ec.contractName] = {
filterByAddresses: ec.filterByAddresses
};
}
if (ec.dependsOnAddresses) {
normalEventConfigs.push(ec);
contractNamesWithNormalEvents.add(ec.contractName);
} else {
notDependingOnAddresses.push(ec);
}
}));
var partitions = [];
if (notDependingOnAddresses.length !== 0) {
partitions.push({
id: String(partitions.length),
status: {
fetchingStateId: undefined
},
latestFetchedBlock: latestFetchedBlock,
selection: {
eventConfigs: notDependingOnAddresses,
dependsOnAddresses: false
},
addressesByContractName: {}
});
}
var normalSelection = {
eventConfigs: normalEventConfigs,
dependsOnAddresses: true
};
if (normalEventConfigs.length !== 0) {
var makePendingNormalPartition = function () {
return {
id: String(partitions.length),
status: {
fetchingStateId: undefined
},
latestFetchedBlock: latestFetchedBlock,
selection: normalSelection,
addressesByContractName: {}
};
};
var pendingNormalPartition = {
contents: makePendingNormalPartition()
};
Belt_Array.forEach(contracts, (function (contract) {
var contractName = contract.contractName;
if (!contractNamesWithNormalEvents.has(contractName)) {
return ;
}
var pendingPartition = pendingNormalPartition.contents;
Utils.Dict.push(pendingPartition.addressesByContractName, contractName, contract.address);
indexingContracts[contract.address] = contract;
if (addressesByContractNameCount(pendingPartition.addressesByContractName) === maxAddrInPartition) {
partitions.push(pendingPartition);
pendingNormalPartition.contents = makePendingNormalPartition();
return ;
}
}));
if (addressesByContractNameCount(pendingNormalPartition.contents.addressesByContractName) > 0) {
partitions.push(pendingNormalPartition.contents);
}
}
if (partitions.length === 0) {
Js_exn.raiseError("Invalid configuration: Nothing to fetch. Make sure that you provided at least one contract address to index, or have events with Wildcard mode enabled.");
}
var numAddresses = Object.keys(indexingContracts).length;
Prometheus.IndexingAddresses.set(numAddresses, chainId);
Prometheus.IndexingPartitions.set(partitions.length, chainId);
Prometheus.IndexingBufferSize.set(0, chainId);
Prometheus.IndexingBufferBlockNumber.set(progressBlockNumber, chainId);
if (endBlock !== undefined) {
Prometheus.IndexingEndBlock.set(endBlock, chainId);
}
return {
partitions: partitions,
nextPartitionIndex: partitions.length,
startBlock: startBlock,
endBlock: endBlock,
maxAddrInPartition: maxAddrInPartition,
normalSelection: normalSelection,
indexingContracts: indexingContracts,
contractConfigs: contractConfigs,
chainId: chainId,
latestFullyFetchedBlock: latestFetchedBlock,
latestOnBlockBlockNumber: progressBlockNumber,
blockLag: blockLag,
buffer: [],
targetBufferSize: targetBufferSize,
onBlockConfigs: onBlockConfigs
};
}
function bufferSize(param) {
return param.buffer.length;
}
function rollbackPartition(p, targetBlockNumber, addressesToRemove) {
var shouldRollbackFetched = p.latestFetchedBlock.blockNumber > targetBlockNumber;
var latestFetchedBlock = shouldRollbackFetched ? ({
blockNumber: targetBlockNumber,
blockTimestamp: 0
}) : p.latestFetchedBlock;
if (!p.selection.dependsOnAddresses) {
return {
id: p.id,
status: {
fetchingStateId: undefined
},
latestFetchedBlock: latestFetchedBlock,
selection: p.selection,
addressesByContractName: p.addressesByContractName
};
}
var rollbackedAddressesByContractName = {};
Utils.Dict.forEachWithKey(p.addressesByContractName, (function (addresses, contractName) {
var keptAddresses = Belt_Array.keep(addresses, (function (address) {
return !addressesToRemove.has(address);
}));
if (keptAddresses.length !== 0) {
rollbackedAddressesByContractName[contractName] = keptAddresses;
return ;
}
}));
if (Object.keys(rollbackedAddressesByContractName).length === 0) {
return ;
} else {
return {
id: p.id,
status: {
fetchingStateId: undefined
},
latestFetchedBlock: latestFetchedBlock,
selection: p.selection,
addressesByContractName: rollbackedAddressesByContractName
};
}
}
function rollback(fetchState, targetBlockNumber) {
var addressesToRemove = new Set();
var indexingContracts = {};
Belt_Array.forEach(Object.keys(fetchState.indexingContracts), (function (address) {
var indexingContract = fetchState.indexingContracts[address];
var registrationBlock = indexingContract.registrationBlock;
if (registrationBlock !== undefined && registrationBlock > targetBlockNumber) {
addressesToRemove.add(address);
} else {
indexingContracts[address] = indexingContract;
}
}));
var partitions = Belt_Array.keepMap(fetchState.partitions, (function (p) {
return rollbackPartition(p, targetBlockNumber, addressesToRemove);
}));
return updateInternal({
partitions: fetchState.partitions,
nextPartitionIndex: fetchState.nextPartitionIndex,
startBlock: fetchState.startBlock,
endBlock: fetchState.endBlock,
maxAddrInPartition: fetchState.maxAddrInPartition,
normalSelection: fetchState.normalSelection,
indexingContracts: fetchState.indexingContracts,
contractConfigs: fetchState.contractConfigs,
chainId: fetchState.chainId,
latestFullyFetchedBlock: fetchState.latestFullyFetchedBlock,
latestOnBlockBlockNumber: targetBlockNumber,
blockLag: fetchState.blockLag,
buffer: fetchState.buffer,
targetBufferSize: fetchState.targetBufferSize,
onBlockConfigs: fetchState.onBlockConfigs
}, partitions, undefined, indexingContracts, Belt_Array.keep(fetchState.buffer, (function (item) {
var tmp;
tmp = item.kind === 0 ? item.blockNumber : item.blockNumber;
return tmp <= targetBlockNumber;
})), undefined);
}
function isActivelyIndexing(fetchState) {
var endBlock = fetchState.endBlock;
if (endBlock === undefined) {
return true;
}
var latestOnBlockBlockNumber = fetchState.latestOnBlockBlockNumber;
var latestFullyFetchedBlock = fetchState.latestFullyFetchedBlock;
var isPastEndblock = (
latestOnBlockBlockNumber < latestFullyFetchedBlock.blockNumber ? latestOnBlockBlockNumber : latestFullyFetchedBlock.blockNumber
) >= endBlock;
if (isPastEndblock) {
return bufferSize(fetchState) > 0;
} else {
return true;
}
}
function isReadyToEnterReorgThreshold(fetchState, currentBlockHeight) {
var blockLag = fetchState.blockLag;
var endBlock = fetchState.endBlock;
var latestOnBlockBlockNumber = fetchState.latestOnBlockBlockNumber;
var latestFullyFetchedBlock = fetchState.latestFullyFetchedBlock;
var bufferBlockNumber = latestOnBlockBlockNumber < latestFullyFetchedBlock.blockNumber ? latestOnBlockBlockNumber : latestFullyFetchedBlock.blockNumber;
if (currentBlockHeight !== 0 && (
endBlock !== undefined && bufferBlockNumber >= endBlock ? true : bufferBlockNumber >= (currentBlockHeight - blockLag | 0)
)) {
return Utils.$$Array.isEmpty(fetchState.buffer);
} else {
return false;
}
}
function hasFullBatch(fetchState, batchSizeTarget) {
var item = Belt_Array.get(fetchState.buffer, batchSizeTarget - 1 | 0);
if (item === undefined) {
return false;
}
var latestOnBlockBlockNumber = fetchState.latestOnBlockBlockNumber;
var latestFullyFetchedBlock = fetchState.latestFullyFetchedBlock;
return item.blockNumber <= (
latestOnBlockBlockNumber < latestFullyFetchedBlock.blockNumber ? latestOnBlockBlockNumber : latestFullyFetchedBlock.blockNumber
);
}
function sortForUnorderedBatch(fetchStates, batchSizeTarget) {
return fetchStates.slice(0).sort(function (a, b) {
var match = hasFullBatch(a, batchSizeTarget);
var match$1 = hasFullBatch(b, batchSizeTarget);
var exit = 0;
if (match) {
if (!match$1) {
return -1;
}
exit = 1;
} else {
if (match$1) {
return 1;
}
exit = 1;
}
if (exit === 1) {
var match$2 = Belt_Array.get(a.buffer, 0);
var match$3 = Belt_Array.get(b.buffer, 0);
var exit$1 = 0;
if (match$2 !== undefined) {
if (match$2.kind !== 0) {
return Js_math.random_int(-1, 1);
}
if (match$3 === undefined) {
return -1;
}
if (match$3.kind === 0) {
return match$2.timestamp - match$3.timestamp | 0;
}
exit$1 = 2;
} else {
if (match$3 === undefined) {
return 0;
}
exit$1 = 2;
}
if (exit$1 === 2) {
if (match$3.kind === 0) {
return 1;
} else {
return Js_math.random_int(-1, 1);
}
}
}
});
}
function getUnorderedMultichainProgressBlockNumberAt(fetchState, index) {
var latestOnBlockBlockNumber = fetchState.latestOnBlockBlockNumber;
var latestFullyFetchedBlock = fetchState.latestFullyFetchedBlock;
var bufferBlockNumber = latestOnBlockBlockNumber < latestFullyFetchedBlock.blockNumber ? latestOnBlockBlockNumber : latestFullyFetchedBlock.blockNumber;
var item = Belt_Array.get(fetchState.buffer, index);
if (item !== undefined && bufferBlockNumber >= item.blockNumber) {
return item.blockNumber - 1 | 0;
} else {
return bufferBlockNumber;
}
}
var blockItemLogIndex = 16777216;
exports.mergeIntoPartition = mergeIntoPartition;
exports.bufferBlockNumber = bufferBlockNumber;
exports.bufferBlock = bufferBlock;
exports.compareBufferItem = compareBufferItem;
exports.blockItemLogIndex = blockItemLogIndex;
exports.updateInternal = updateInternal;
exports.numAddresses = numAddresses;
exports.warnDifferentContractType = warnDifferentContractType;
exports.registerDynamicContracts = registerDynamicContracts;
exports.UnexpectedPartitionNotFound = UnexpectedPartitionNotFound;
exports.UnexpectedMergeQueryResponse = UnexpectedMergeQueryResponse;
exports.handleQueryResult = handleQueryResult;
exports.makePartitionQuery = makePartitionQuery;
exports.startFetchingQueries = startFetchingQueries;
exports.addressesByContractNameCount = addressesByContractNameCount;
exports.addressesByContractNameGetAll = addressesByContractNameGetAll;
exports.isFullPartition = isFullPartition;
exports.getNextQuery = getNextQuery;
exports.getTimestampAt = getTimestampAt;
exports.hasReadyItem = hasReadyItem;
exports.getReadyItemsCount = getReadyItemsCount;
exports.make = make;
exports.bufferSize = bufferSize;
exports.rollbackPartition = rollbackPartition;
exports.rollback = rollback;
exports.isActivelyIndexing = isActivelyIndexing;
exports.isReadyToEnterReorgThreshold = isReadyToEnterReorgThreshold;
exports.sortForUnorderedBatch = sortForUnorderedBatch;
exports.getUnorderedMultichainProgressBlockNumberAt = getUnorderedMultichainProgressBlockNumberAt;
/* Utils Not a pure module */