envio
Version:
A latency and sync speed optimized, developer friendly blockchain data indexer.
451 lines (430 loc) • 17.3 kB
JavaScript
// Generated by ReScript, PLEASE EDIT WITH CARE
;
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 */