UNPKG

envio

Version:

A latency and sync speed optimized, developer friendly blockchain data indexer.

1,124 lines (1,074 loc) • 45.4 kB
// 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 Caml_obj = require("rescript/lib/js/caml_obj.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_option = require("rescript/lib/js/caml_option.js"); var Caml_exceptions = require("rescript/lib/js/caml_exceptions.js"); function copy(fetchState) { return { partitions: fetchState.partitions, nextPartitionIndex: fetchState.nextPartitionIndex, startBlock: fetchState.startBlock, endBlock: fetchState.endBlock, maxAddrInPartition: fetchState.maxAddrInPartition, normalSelection: fetchState.normalSelection, indexingContracts: fetchState.indexingContracts, contractConfigs: fetchState.contractConfigs, dcsToStore: fetchState.dcsToStore, chainId: fetchState.chainId, latestFullyFetchedBlock: fetchState.latestFullyFetchedBlock, latestOnBlockBlockNumber: fetchState.latestOnBlockBlockNumber, blockLag: fetchState.blockLag, queue: fetchState.queue.slice(0), targetBufferSize: fetchState.targetBufferSize, onBlockConfigs: fetchState.onBlockConfigs }; } 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 (contractName, addresses) { allowedAddressesNumber.contents = allowedAddressesNumber.contents - addresses.length | 0; mergedAddresses[contractName] = addresses; })); Utils.Dict.forEachWithKey(p.addressesByContractName, (function (contractName, addresses) { 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 (contractName, addresses) { 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 = b.blockNumber - a.blockNumber | 0; if (blockDiff === 0) { return b.logIndex - a.logIndex | 0; } else { return blockDiff; } } function updateInternal(fetchState, partitionsOpt, nextPartitionIndexOpt, indexingContractsOpt, dcsToStoreOpt, mutItems, blockLagOpt) { var partitions = partitionsOpt !== undefined ? partitionsOpt : fetchState.partitions; var nextPartitionIndex = nextPartitionIndexOpt !== undefined ? nextPartitionIndexOpt : fetchState.nextPartitionIndex; var indexingContracts = indexingContractsOpt !== undefined ? indexingContractsOpt : fetchState.indexingContracts; var dcsToStore = dcsToStoreOpt !== undefined ? Caml_option.valFromOption(dcsToStoreOpt) : fetchState.dcsToStore; 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 = ( mutItems$1 !== undefined ? mutItems$1 : fetchState.queue ).at(-fetchState.targetBufferSize | 0); var maxBlockNumber = item !== undefined ? item.blockNumber : latestFullyFetchedBlock$1.blockNumber; var mutItems$2 = mutItemsRef; var mutItems$3 = mutItems$2 !== undefined ? mutItems$2 : fetchState.queue.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_queue = mutItems$4 !== undefined ? mutItems$4.sort(compareBufferItem) : fetchState.queue; 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, dcsToStore: dcsToStore, chainId: updatedFetchState_chainId, latestFullyFetchedBlock: latestFullyFetchedBlock$1, latestOnBlockBlockNumber: latestOnBlockBlockNumber, blockLag: blockLag, queue: updatedFetchState_queue, targetBufferSize: updatedFetchState_targetBufferSize, onBlockConfigs: updatedFetchState_onBlockConfigs }; Prometheus.IndexingPartitions.set(partitions.length, fetchState.chainId); Prometheus.IndexingBufferSize.set(updatedFetchState_queue.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, dynamicContracts) { 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 idx = 0 ,idx_finish = dynamicContracts.length; idx < idx_finish; ++idx){ var dc = dynamicContracts[idx]; 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."); } } else { var registeringContract = registeringContracts[dc.address]; var shouldUpdate; if (registeringContract !== undefined) { if (registeringContract.contractName !== dc.contractName) { warnDifferentContractType(fetchState, registeringContract, dc); shouldUpdate = false; } else { var match$1 = registeringContract.register; var match$2 = dc.register; shouldUpdate = typeof match$1 !== "object" || typeof match$2 !== "object" ? Js_exn.raiseError("Unexpected case: Config registration should be handled in a different function") : registeringContract.startBlock > dc.startBlock || registeringContract.startBlock === dc.startBlock && match$1.registeringEventLogIndex > match$2.registeringEventLogIndex; } } 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 { 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."); } } 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$1 = Object.keys(addressesByContractName).length; idx$1 < idx_finish$1; ++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); var existingDcs = fetchState.dcsToStore; return updateInternal(fetchState, fetchState.partitions.concat(newPartitions), fetchState.nextPartitionIndex + newPartitions.length | 0, Object.assign(registeringContracts, indexingContracts), Caml_option.some(existingDcs !== undefined ? Belt_Array.concat(existingDcs, dcsToStore) : dcsToStore), 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, undefined, newItems.length !== 0 ? Belt_Array.concat(fetchState.queue, 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 queue = param.queue; 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 targetBlockIdx = queue.length - param.targetBufferSize | 0; var maxQueryBlockNumber; if (targetBlockIdx < 0) { maxQueryBlockNumber = currentBlockHeight; } else { var item = Belt_Array.get(queue, targetBlockIdx); 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 makeNoItem(param) { return { TAG: "NoItem", latestFetchedBlock: param.latestFetchedBlock }; } function getEarliestEvent(fetchState) { var queue = fetchState.queue; var item = Utils.$$Array.last(fetchState.queue); if (item !== undefined) { var latestOnBlockBlockNumber = fetchState.latestOnBlockBlockNumber; var latestFullyFetchedBlock = fetchState.latestFullyFetchedBlock; if (item.blockNumber <= ( latestOnBlockBlockNumber < latestFullyFetchedBlock.blockNumber ? latestOnBlockBlockNumber : latestFullyFetchedBlock.blockNumber )) { return { TAG: "Item", _0: { item: item, popItemOffQueue: (function () { queue.pop(); }) } }; } var latestOnBlockBlockNumber$1 = fetchState.latestOnBlockBlockNumber; var latestFullyFetchedBlock$1 = fetchState.latestFullyFetchedBlock; return { TAG: "NoItem", latestFetchedBlock: latestOnBlockBlockNumber$1 < latestFullyFetchedBlock$1.blockNumber ? ({ blockNumber: latestOnBlockBlockNumber$1, blockTimestamp: 0 }) : latestFullyFetchedBlock$1 }; } else { var latestOnBlockBlockNumber$2 = fetchState.latestOnBlockBlockNumber; var latestFullyFetchedBlock$2 = fetchState.latestFullyFetchedBlock; return { TAG: "NoItem", latestFetchedBlock: latestOnBlockBlockNumber$2 < latestFullyFetchedBlock$2.blockNumber ? ({ blockNumber: latestOnBlockBlockNumber$2, blockTimestamp: 0 }) : latestFullyFetchedBlock$2 }; } } 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, dcsToStore: undefined, chainId: chainId, latestFullyFetchedBlock: latestFetchedBlock, latestOnBlockBlockNumber: progressBlockNumber, blockLag: blockLag, queue: [], targetBufferSize: targetBufferSize, onBlockConfigs: onBlockConfigs }; } function bufferSize(param) { return param.queue.length; } function pruneQueueFromFirstChangeEvent(queue, firstChangeEvent) { return Belt_Array.keep(queue, (function (item) { var tmp; tmp = item.kind === 0 ? [ item.blockNumber, item.logIndex ] : [ item.blockNumber, item.logIndex ]; return Caml_obj.lessthan(tmp, [ firstChangeEvent.blockNumber, firstChangeEvent.logIndex ]); })); } function rollbackPartition(p, firstChangeEvent, addressesToRemove) { if (!p.selection.dependsOnAddresses) { return { id: p.id, status: { fetchingStateId: undefined }, latestFetchedBlock: p.latestFetchedBlock, selection: p.selection, addressesByContractName: p.addressesByContractName }; } var rollbackedAddressesByContractName = {}; Utils.Dict.forEachWithKey(p.addressesByContractName, (function (contractName, addresses) { 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 ; } var shouldRollbackFetched = p.latestFetchedBlock.blockNumber >= firstChangeEvent.blockNumber; return { id: p.id, status: { fetchingStateId: undefined }, latestFetchedBlock: shouldRollbackFetched ? ({ blockNumber: firstChangeEvent.blockNumber - 1 | 0, blockTimestamp: 0 }) : p.latestFetchedBlock, selection: p.selection, addressesByContractName: rollbackedAddressesByContractName }; } function rollback(fetchState, firstChangeEvent) { var addressesToRemove = new Set(); var indexingContracts = {}; Belt_Array.forEach(Object.keys(fetchState.indexingContracts), (function (address) { var indexingContract = fetchState.indexingContracts[address]; var dc = indexingContract.register; var tmp; tmp = typeof dc !== "object" ? true : indexingContract.startBlock < firstChangeEvent.blockNumber || indexingContract.startBlock === firstChangeEvent.blockNumber && dc.registeringEventLogIndex < firstChangeEvent.logIndex; if (tmp) { indexingContracts[address] = indexingContract; } else { addressesToRemove.add(address); } })); var partitions = Belt_Array.keepMap(fetchState.partitions, (function (p) { return rollbackPartition(p, firstChangeEvent, addressesToRemove); })); var dcsToStore = fetchState.dcsToStore; var tmp; if (dcsToStore !== undefined) { var filtered = dcsToStore.filter(function (dc) { return !addressesToRemove.has(dc.address); }); tmp = filtered.length !== 0 ? filtered : undefined; } else { tmp = undefined; } 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, dcsToStore: fetchState.dcsToStore, chainId: fetchState.chainId, latestFullyFetchedBlock: fetchState.latestFullyFetchedBlock, latestOnBlockBlockNumber: firstChangeEvent.blockNumber - 1 | 0, blockLag: fetchState.blockLag, queue: fetchState.queue, targetBufferSize: fetchState.targetBufferSize, onBlockConfigs: fetchState.onBlockConfigs }, partitions, undefined, indexingContracts, Caml_option.some(tmp), pruneQueueFromFirstChangeEvent(fetchState.queue, firstChangeEvent), 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.queue); } else { return false; } } function hasBatchItem(fetchState) { var item = Utils.$$Array.last(fetchState.queue); if (item === undefined) { return false; } var latestOnBlockBlockNumber = fetchState.latestOnBlockBlockNumber; var latestFullyFetchedBlock = fetchState.latestFullyFetchedBlock; return item.blockNumber <= ( latestOnBlockBlockNumber < latestFullyFetchedBlock.blockNumber ? latestOnBlockBlockNumber : latestFullyFetchedBlock.blockNumber ); } function hasFullBatch(fetchState, maxBatchSize) { var queue = fetchState.queue; var targetBlockIdx = queue.length - maxBatchSize | 0; if (targetBlockIdx < 0) { return false; } var latestOnBlockBlockNumber = fetchState.latestOnBlockBlockNumber; var latestFullyFetchedBlock = fetchState.latestFullyFetchedBlock; return queue[targetBlockIdx].blockNumber <= ( latestOnBlockBlockNumber < latestFullyFetchedBlock.blockNumber ? latestOnBlockBlockNumber : latestFullyFetchedBlock.blockNumber ); } function filterAndSortForUnorderedBatch(fetchStates, maxBatchSize) { return Belt_Array.keepU(fetchStates, hasBatchItem).sort(function (a, b) { var match = hasFullBatch(a, maxBatchSize); var match$1 = hasFullBatch(b, maxBatchSize); if (match) { if (!match$1) { return -1; } } else if (match$1) { return 1; } var match$2 = Utils.$$Array.lastUnsafe(a.queue); var match$3 = Utils.$$Array.lastUnsafe(b.queue); if (match$2.kind === 0 && match$3.kind === 0) { return match$2.timestamp - match$3.timestamp | 0; } else { return Js_math.random_int(-1, 1); } }); } function getProgressBlockNumber(fetchState) { var latestOnBlockBlockNumber = fetchState.latestOnBlockBlockNumber; var latestFullyFetchedBlock = fetchState.latestFullyFetchedBlock; var bufferBlockNumber = latestOnBlockBlockNumber < latestFullyFetchedBlock.blockNumber ? latestOnBlockBlockNumber : latestFullyFetchedBlock.blockNumber; var item = Utils.$$Array.last(fetchState.queue); if (item !== undefined && bufferBlockNumber >= item.blockNumber) { return item.blockNumber - 1 | 0; } else { return bufferBlockNumber; } } function getProgressNextBlockLogIndex(fetchState) { var match = Utils.$$Array.last(fetchState.queue); if (match === undefined) { return ; } if (match.kind !== 0) { return ; } var logIndex = match.logIndex; var latestOnBlockBlockNumber = fetchState.latestOnBlockBlockNumber; var latestFullyFetchedBlock = fetchState.latestFullyFetchedBlock; if (( latestOnBlockBlockNumber < latestFullyFetchedBlock.blockNumber ? latestOnBlockBlockNumber : latestFullyFetchedBlock.blockNumber ) >= match.blockNumber && logIndex > 0) { return logIndex - 1 | 0; } } var blockItemLogIndex = 16777216; exports.copy = copy; 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.makeNoItem = makeNoItem; exports.getEarliestEvent = getEarliestEvent; exports.make = make; exports.bufferSize = bufferSize; exports.pruneQueueFromFirstChangeEvent = pruneQueueFromFirstChangeEvent; exports.rollbackPartition = rollbackPartition; exports.rollback = rollback; exports.isActivelyIndexing = isActivelyIndexing; exports.isReadyToEnterReorgThreshold = isReadyToEnterReorgThreshold; exports.filterAndSortForUnorderedBatch = filterAndSortForUnorderedBatch; exports.getProgressBlockNumber = getProgressBlockNumber; exports.getProgressNextBlockLogIndex = getProgressNextBlockLogIndex; /* Utils Not a pure module */