UNPKG

envio

Version:

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

451 lines (430 loc) • 17.3 kB
// Generated by ReScript, PLEASE EDIT WITH CARE 'use strict'; var Rest = require("../vendored/Rest.res.js"); var Hrtime = require("../bindings/Hrtime.res.js"); var Js_exn = require("rescript/lib/js/js_exn.js"); var Source = require("./Source.res.js"); var Logging = require("../Logging.res.js"); var $$Promise = require("../bindings/Promise.res.js"); var HyperFuel = require("./HyperFuel.res.js"); var HyperSync = require("./HyperSync.res.js"); var Belt_Array = require("rescript/lib/js/belt_Array.js"); var Belt_Option = require("rescript/lib/js/belt_Option.js"); var EventRouter = require("./EventRouter.res.js"); var ErrorHandling = require("../ErrorHandling.res.js"); var Caml_exceptions = require("rescript/lib/js/caml_exceptions.js"); var Caml_js_exceptions = require("rescript/lib/js/caml_js_exceptions.js"); var EventRoutingFailed = /* @__PURE__ */Caml_exceptions.create("HyperFuelSource.EventRoutingFailed"); var mintEventTag = "mint"; var burnEventTag = "burn"; var transferEventTag = "transfer"; var callEventTag = "call"; var logDataReceiptTypeSelection = [6]; var txStatusSelection = [1]; function makeGetNormalRecieptsSelection(nonWildcardLogDataRbsByContract, nonLogDataReceiptTypesByContract, contractNames) { return function (addressesByContractName) { var selection = []; contractNames.forEach(function (contractName) { var addresses = addressesByContractName[contractName]; if (addresses === undefined) { return ; } if (addresses.length === 0) { return ; } var receiptTypes = nonLogDataReceiptTypesByContract[contractName]; if (receiptTypes !== undefined) { selection.push({ rootContractId: addresses, receiptType: receiptTypes, txStatus: txStatusSelection }); } var nonWildcardLogDataRbs = nonWildcardLogDataRbsByContract[contractName]; if (nonWildcardLogDataRbs !== undefined && nonWildcardLogDataRbs.length !== 0) { selection.push({ rootContractId: addresses, receiptType: logDataReceiptTypeSelection, rb: nonWildcardLogDataRbs, txStatus: txStatusSelection }); return ; } }); return selection; }; } function makeWildcardRecieptsSelection(wildcardLogDataRbs, nonLogDataWildcardReceiptTypes) { var selection = []; if (nonLogDataWildcardReceiptTypes.length !== 0) { selection.push({ receiptType: nonLogDataWildcardReceiptTypes, txStatus: txStatusSelection }); } if (wildcardLogDataRbs.length !== 0) { selection.push({ receiptType: logDataReceiptTypeSelection, rb: wildcardLogDataRbs, txStatus: txStatusSelection }); } return selection; } function getSelectionConfig(selection, chain) { var eventRouter = EventRouter.empty(); var nonWildcardLogDataRbsByContract = {}; var wildcardLogDataRbs = []; var nonLogDataReceiptTypesByContract = {}; var nonLogDataWildcardReceiptTypes = []; var addNonLogDataWildcardReceiptTypes = function (receiptType) { nonLogDataWildcardReceiptTypes.push(receiptType); }; var addNonLogDataReceiptType = function (contractName, receiptType) { var receiptTypes = nonLogDataReceiptTypesByContract[contractName]; if (receiptTypes !== undefined) { receiptTypes.push(receiptType); } else { nonLogDataReceiptTypesByContract[contractName] = [receiptType]; } }; var contractNames = new Set(); Belt_Array.forEach(selection.eventConfigs, (function (eventConfig) { var contractName = eventConfig.contractName; if (!eventConfig.isWildcard) { contractNames.add(contractName); } EventRouter.addOrThrow(eventRouter, eventConfig.id, eventConfig, contractName, eventConfig.isWildcard, eventConfig.name, chain); var isWildcard = eventConfig.isWildcard; if (isWildcard) { var tmp = eventConfig.kind; if (typeof tmp !== "object") { switch (tmp) { case "Mint" : return addNonLogDataWildcardReceiptTypes(11); case "Burn" : return addNonLogDataWildcardReceiptTypes(12); case "Transfer" : addNonLogDataWildcardReceiptTypes(7); return addNonLogDataWildcardReceiptTypes(8); case "Call" : return addNonLogDataWildcardReceiptTypes(0); } } } var match = eventConfig.kind; if (typeof match !== "object") { switch (match) { case "Mint" : return addNonLogDataReceiptType(contractName, 11); case "Burn" : return addNonLogDataReceiptType(contractName, 12); case "Transfer" : addNonLogDataReceiptType(contractName, 7); return addNonLogDataReceiptType(contractName, 8); case "Call" : return Js_exn.raiseError("Call receipt indexing currently supported only in wildcard mode"); } } else { var rb = BigInt(match.logId); if (isWildcard) { wildcardLogDataRbs.push(rb); return ; } var arr = nonWildcardLogDataRbsByContract[contractName]; if (arr !== undefined) { arr.push(rb); } else { nonWildcardLogDataRbsByContract[contractName] = [rb]; } return ; } })); var tmp; if (selection.dependsOnAddresses) { tmp = makeGetNormalRecieptsSelection(nonWildcardLogDataRbsByContract, nonLogDataReceiptTypesByContract, contractNames); } else { var recieptsSelection = makeWildcardRecieptsSelection(wildcardLogDataRbs, nonLogDataWildcardReceiptTypes); tmp = (function (param) { return recieptsSelection; }); } return { getRecieptsSelection: tmp, eventRouter: eventRouter }; } function memoGetSelectionConfig(chain) { var cache = new WeakMap(); return function (selection) { var c = cache.get(selection); if (c !== undefined) { return c; } var c$1 = getSelectionConfig(selection, chain); cache.set(selection, c$1); return c$1; }; } function make(param) { var endpointUrl = param.endpointUrl; var chain = param.chain; var getSelectionConfig = memoGetSelectionConfig(chain); var getItemsOrThrow = async function (fromBlock, toBlock, addressesByContractName, indexingContracts, currentBlockHeight, param, selection, retry, logger) { var mkLogAndRaise = function (extra, extra$1) { return ErrorHandling.mkLogAndRaise(logger, extra, extra$1); }; var totalTimeRef = Hrtime.makeTimer(); var selectionConfig = getSelectionConfig(selection); var recieptsSelection = selectionConfig.getRecieptsSelection(addressesByContractName); var startFetchingBatchTimeRef = Hrtime.makeTimer(); var pageUnsafe; try { pageUnsafe = await HyperFuel.GetLogs.query(endpointUrl, fromBlock, toBlock, recieptsSelection); } catch (raw_error){ var error = Caml_js_exceptions.internalToOCamlException(raw_error); if (error.RE_EXN_ID === HyperSync.GetLogs.$$Error) { var error$1 = error._1; var tmp; if (typeof error$1 !== "object") { var backoffMillis = retry !== 0 ? Math.imul(500, retry) : 100; tmp = { TAG: "WithBackoff", message: "Block #" + String(fromBlock) + " not found in HyperFuel. HyperFuel has multiple instances and it's possible that they drift independently slightly from the head. Indexing should continue correctly after retrying the query in " + String(backoffMillis) + "ms.", backoffMillis: backoffMillis }; } else { tmp = { TAG: "ImpossibleForTheQuery", message: "Source returned invalid data with missing required fields: " + error$1.missingParams.join(", ") }; } throw { RE_EXN_ID: Source.GetItemsError, _1: { TAG: "FailedGettingItems", exn: null, attemptedToBlock: Belt_Option.getWithDefault(toBlock, currentBlockHeight), retry: tmp }, Error: new Error() }; } throw { RE_EXN_ID: Source.GetItemsError, _1: { TAG: "FailedGettingItems", exn: error, attemptedToBlock: Belt_Option.getWithDefault(toBlock, currentBlockHeight), retry: { TAG: "WithBackoff", message: "Unexpected issue while fetching events from HyperFuel client. Attempt a retry.", backoffMillis: retry !== 0 ? Math.imul(1000, retry) : 500 } }, Error: new Error() }; } var pageFetchTime = Hrtime.intFromMillis(Hrtime.toMillis(Hrtime.timeSince(startFetchingBatchTimeRef))); var currentBlockHeight$1 = pageUnsafe.archiveHeight; var heighestBlockQueried = pageUnsafe.nextBlock - 1 | 0; var match = Belt_Array.get(pageUnsafe.items, pageUnsafe.items.length - 1 | 0); var lastBlockQueriedPromise; var exit = 0; if (match !== undefined) { var block = match.block; if (block.height === heighestBlockQueried) { lastBlockQueriedPromise = Promise.resolve({ blockHash: block.id, blockNumber: block.height, blockTimestamp: block.time }); } else { exit = 1; } } else { exit = 1; } if (exit === 1) { lastBlockQueriedPromise = $$Promise.$$catch(HyperFuel.queryBlockData(endpointUrl, heighestBlockQueried, logger).then(function (res) { if (res !== undefined) { return res; } else { return mkLogAndRaise("Failure, blockData for block " + String(heighestBlockQueried) + " unexpectedly returned None", { RE_EXN_ID: "Not_found" }); } }), (function (exn) { return mkLogAndRaise("Failed to query blockData for block " + String(heighestBlockQueried), exn); })); } var parsingTimeRef = Hrtime.makeTimer(); var parsedQueueItems = Belt_Array.map(pageUnsafe.items, (function (item) { var block = item.block; var receiptIndex = item.receiptIndex; var receipt = item.receipt; var contractAddress = item.contractId; var eventId; switch (receipt.receiptType) { case 0 : eventId = callEventTag; break; case 6 : eventId = receipt.rb.toString(); break; case 7 : case 8 : eventId = transferEventTag; break; case 11 : eventId = mintEventTag; break; case 12 : eventId = burnEventTag; break; } var eventConfig = EventRouter.get(selectionConfig.eventRouter, eventId, contractAddress, block.height, indexingContracts); var eventConfig$1; if (eventConfig !== undefined) { eventConfig$1 = eventConfig; } else { var logger$1 = Logging.createChildFrom(logger, { chainId: chain, blockNumber: block.height, logIndex: receiptIndex, contractAddress: contractAddress, eventId: eventId }); eventConfig$1 = ErrorHandling.mkLogAndRaise(logger$1, "Failed to route registered event", { RE_EXN_ID: EventRoutingFailed }); } var match = eventConfig$1.kind; var params; var exit = 0; if (typeof match !== "object" || receipt.receiptType !== 6) { exit = 1; } else { try { params = match.decode(receipt.data); } catch (raw_exn){ var exn = Caml_js_exceptions.internalToOCamlException(raw_exn); var params$1 = { chainId: chain, blockNumber: block.height, logIndex: receiptIndex }; var logger$2 = Logging.createChildFrom(logger, params$1); params = ErrorHandling.mkLogAndRaise(logger$2, "Failed to decode Fuel LogData receipt, please double check your ABI.", exn); } } if (exit === 1) { switch (receipt.receiptType) { case 0 : params = { to: receipt.to, assetId: receipt.assetId, amount: receipt.amount }; break; case 6 : params = Js_exn.raiseError("Unexpected bug in the event routing logic"); break; case 7 : params = { to: receipt.to, assetId: receipt.assetId, amount: receipt.amount }; break; case 8 : params = { to: receipt.toAddress, assetId: receipt.assetId, amount: receipt.amount }; break; case 11 : case 12 : params = { subId: receipt.subId, amount: receipt.val }; break; } } return { kind: 0, eventConfig: eventConfig$1, timestamp: block.time, chain: chain, blockNumber: block.height, logIndex: receiptIndex, event: { params: params, chainId: chain, srcAddress: contractAddress, logIndex: receiptIndex, transaction: { id: item.transactionId }, block: block } }; })); var parsingTimeElapsed = Hrtime.intFromMillis(Hrtime.toMillis(Hrtime.timeSince(parsingTimeRef))); var rangeLastBlock = await lastBlockQueriedPromise; var reorgGuard = { rangeLastBlock: rangeLastBlock, prevRangeLastBlock: undefined }; var totalTimeElapsed = Hrtime.intFromMillis(Hrtime.toMillis(Hrtime.timeSince(totalTimeRef))); var stats_parsing$unknowntime$unknown$lparms$rpar = parsingTimeElapsed; var stats_page$unknownfetch$unknowntime$unknown$lparms$rpar = pageFetchTime; var stats = { "total time elapsed (ms)": totalTimeElapsed, "parsing time (ms)": stats_parsing$unknowntime$unknown$lparms$rpar, "page fetch time (ms)": stats_page$unknownfetch$unknowntime$unknown$lparms$rpar }; return { currentBlockHeight: currentBlockHeight$1, reorgGuard: reorgGuard, parsedQueueItems: parsedQueueItems, fromBlockQueried: fromBlock, latestFetchedBlockNumber: rangeLastBlock.blockNumber, latestFetchedBlockTimestamp: rangeLastBlock.blockTimestamp, stats: stats }; }; var getBlockHashes = function (param, param$1) { return Js_exn.raiseError("HyperFuel does not support getting block hashes"); }; var jsonApiClient = Rest.client(endpointUrl, undefined); return { name: "HyperFuel", sourceFor: "Sync", chain: chain, poweredByHyperSync: true, pollingInterval: 100, getBlockHashes: getBlockHashes, getHeightOrThrow: (function () { return Rest.$$fetch(HyperFuel.heightRoute, undefined, jsonApiClient); }), getItemsOrThrow: getItemsOrThrow }; } exports.EventRoutingFailed = EventRoutingFailed; exports.mintEventTag = mintEventTag; exports.burnEventTag = burnEventTag; exports.transferEventTag = transferEventTag; exports.callEventTag = callEventTag; exports.logDataReceiptTypeSelection = logDataReceiptTypeSelection; exports.txStatusSelection = txStatusSelection; exports.makeGetNormalRecieptsSelection = makeGetNormalRecieptsSelection; exports.makeWildcardRecieptsSelection = makeWildcardRecieptsSelection; exports.getSelectionConfig = getSelectionConfig; exports.memoGetSelectionConfig = memoGetSelectionConfig; exports.make = make; /* Rest Not a pure module */