UNPKG

envio

Version:

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

224 lines (211 loc) • 8.23 kB
// Generated by ReScript, PLEASE EDIT WITH CARE 'use strict'; var Js_exn = require("rescript/lib/js/js_exn.js"); var Js_dict = require("rescript/lib/js/js_dict.js"); var Belt_Array = require("rescript/lib/js/belt_Array.js"); var Belt_Option = require("rescript/lib/js/belt_Option.js"); function reorgDetectedToLogParams(reorgDetected, shouldRollbackOnReorg) { var scannedBlock = reorgDetected.scannedBlock; return { msg: "Blockchain reorg detected. " + ( shouldRollbackOnReorg ? "Initiating indexer rollback" : "NOT initiating indexer rollback due to configuration" ) + ".", blockNumber: scannedBlock.blockNumber, indexedBlockHash: scannedBlock.blockHash, receivedBlockHash: reorgDetected.receivedBlock.blockHash }; } function makeWithData(blocks, confirmedBlockThreshold, detectedReorgBlock) { var dataByBlockNumber = {}; Belt_Array.forEach(blocks, (function (block) { dataByBlockNumber[block.blockNumber.toString()] = block; })); return { confirmedBlockThreshold: confirmedBlockThreshold, dataByBlockNumber: dataByBlockNumber, detectedReorgBlock: detectedReorgBlock }; } function empty(confirmedBlockThreshold) { return { confirmedBlockThreshold: confirmedBlockThreshold, dataByBlockNumber: {}, detectedReorgBlock: undefined }; } function getDataByBlockNumberCopyInThreshold(param, currentBlockHeight) { var dataByBlockNumber = param.dataByBlockNumber; var ascBlockNumberKeys = Object.keys(dataByBlockNumber); var thresholdBlockNumber = currentBlockHeight - param.confirmedBlockThreshold | 0; var copy = {}; for(var idx = 0 ,idx_finish = ascBlockNumberKeys.length; idx < idx_finish; ++idx){ var blockNumberKey = ascBlockNumberKeys[idx]; var scannedBlock = dataByBlockNumber[blockNumberKey]; var isInReorgThreshold = scannedBlock.blockNumber >= thresholdBlockNumber; if (isInReorgThreshold) { copy[blockNumberKey] = scannedBlock; } } return copy; } function registerReorgGuard(self, reorgGuard, currentBlockHeight, shouldRollbackOnReorg) { var confirmedBlockThreshold = self.confirmedBlockThreshold; var dataByBlockNumberCopyInThreshold = getDataByBlockNumberCopyInThreshold(self, currentBlockHeight); var prevRangeLastBlock = reorgGuard.prevRangeLastBlock; var rangeLastBlock = reorgGuard.rangeLastBlock; var scannedBlock = dataByBlockNumberCopyInThreshold[String(rangeLastBlock.blockNumber)]; var maybeReorgDetected; var exit = 0; if (scannedBlock !== undefined && scannedBlock.blockHash !== rangeLastBlock.blockHash) { maybeReorgDetected = { scannedBlock: scannedBlock, receivedBlock: rangeLastBlock }; } else { exit = 1; } if (exit === 1) { if (prevRangeLastBlock !== undefined) { var scannedBlock$1 = dataByBlockNumberCopyInThreshold[String(prevRangeLastBlock.blockNumber)]; maybeReorgDetected = scannedBlock$1 !== undefined && scannedBlock$1.blockHash !== prevRangeLastBlock.blockHash ? ({ scannedBlock: scannedBlock$1, receivedBlock: prevRangeLastBlock }) : undefined; } else { maybeReorgDetected = undefined; } } if (maybeReorgDetected !== undefined) { return [ shouldRollbackOnReorg ? ({ confirmedBlockThreshold: self.confirmedBlockThreshold, dataByBlockNumber: self.dataByBlockNumber, detectedReorgBlock: maybeReorgDetected.scannedBlock }) : empty(confirmedBlockThreshold), { TAG: "ReorgDetected", _0: maybeReorgDetected } ]; } else { dataByBlockNumberCopyInThreshold[String(rangeLastBlock.blockNumber)] = rangeLastBlock; if (prevRangeLastBlock !== undefined) { dataByBlockNumberCopyInThreshold[String(prevRangeLastBlock.blockNumber)] = prevRangeLastBlock; } return [ { confirmedBlockThreshold: confirmedBlockThreshold, dataByBlockNumber: dataByBlockNumberCopyInThreshold, detectedReorgBlock: undefined }, "NoReorg" ]; } } function getLatestValidScannedBlock(self, blockNumbersAndHashes, currentBlockHeight, skipReorgDuplicationCheckOpt) { var skipReorgDuplicationCheck = skipReorgDuplicationCheckOpt !== undefined ? skipReorgDuplicationCheckOpt : false; var verifiedDataByBlockNumber = {}; for(var idx = 0 ,idx_finish = blockNumbersAndHashes.length; idx < idx_finish; ++idx){ var blockData = blockNumbersAndHashes[idx]; verifiedDataByBlockNumber[String(blockData.blockNumber)] = blockData; } var isAlreadyReorgedResponse; if (skipReorgDuplicationCheck) { isAlreadyReorgedResponse = false; } else { var detectedReorgBlock = self.detectedReorgBlock; if (detectedReorgBlock !== undefined) { var verifiedBlockData = verifiedDataByBlockNumber[String(detectedReorgBlock.blockNumber)]; isAlreadyReorgedResponse = verifiedBlockData !== undefined ? verifiedBlockData.blockHash === detectedReorgBlock.blockHash : false; } else { isAlreadyReorgedResponse = false; } } if (isAlreadyReorgedResponse) { return { TAG: "Error", _0: "AlreadyReorgedHashes" }; } var dataByBlockNumber = getDataByBlockNumberCopyInThreshold(self, currentBlockHeight); var ascBlockNumberKeys = Object.keys(dataByBlockNumber); var getPrevScannedBlock = function (idx) { var data = Belt_Option.flatMap(Belt_Array.get(ascBlockNumberKeys, idx - 1 | 0), (function (key) { return verifiedDataByBlockNumber[key]; })); if (data !== undefined) { return { TAG: "Ok", _0: data }; } else { return { TAG: "Error", _0: "NotFound" }; } }; var _idx = 0; while(true) { var idx$1 = _idx; var blockNumberKey = Belt_Array.get(ascBlockNumberKeys, idx$1); if (blockNumberKey === undefined) { return getPrevScannedBlock(idx$1); } var scannedBlock = dataByBlockNumber[blockNumberKey]; var verifiedBlockData$1 = verifiedDataByBlockNumber[blockNumberKey]; if (verifiedBlockData$1 === undefined) { return Js_exn.raiseError("Unexpected case. Couldn't find verified hash for block number " + blockNumberKey); } if (verifiedBlockData$1.blockHash !== scannedBlock.blockHash) { return getPrevScannedBlock(idx$1); } _idx = idx$1 + 1 | 0; continue ; }; } function rollbackToValidBlockNumber(param, blockNumber) { var dataByBlockNumber = param.dataByBlockNumber; var ascBlockNumberKeys = Object.keys(dataByBlockNumber); var newDataByBlockNumber = {}; var loop = function (_idx) { while(true) { var idx = _idx; var blockNumberKey = Belt_Array.get(ascBlockNumberKeys, idx); if (blockNumberKey === undefined) { return ; } var scannedBlock = dataByBlockNumber[blockNumberKey]; var shouldKeep = scannedBlock.blockNumber <= blockNumber; if (!shouldKeep) { return ; } newDataByBlockNumber[blockNumberKey] = scannedBlock; _idx = idx + 1 | 0; continue ; }; }; loop(0); return { confirmedBlockThreshold: param.confirmedBlockThreshold, dataByBlockNumber: newDataByBlockNumber, detectedReorgBlock: undefined }; } function getThresholdBlockNumbers(self, currentBlockHeight) { var dataByBlockNumberCopyInThreshold = getDataByBlockNumberCopyInThreshold(self, currentBlockHeight); return Js_dict.values(dataByBlockNumberCopyInThreshold).map(function (v) { return v.blockNumber; }); } var LastBlockScannedHashes = { makeWithData: makeWithData, empty: empty, registerReorgGuard: registerReorgGuard, getLatestValidScannedBlock: getLatestValidScannedBlock, getThresholdBlockNumbers: getThresholdBlockNumbers, rollbackToValidBlockNumber: rollbackToValidBlockNumber }; exports.reorgDetectedToLogParams = reorgDetectedToLogParams; exports.LastBlockScannedHashes = LastBlockScannedHashes; /* No side effect */