UNPKG

@ledgerhq/coin-tron

Version:
183 lines 7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getBlockInfo = getBlockInfo; exports.getBlock = getBlock; const logs_1 = require("@ledgerhq/logs"); const bignumber_js_1 = __importDefault(require("bignumber.js")); const network_1 = require("../network"); const format_1 = require("../network/format"); const trongrid_adapters_1 = require("../network/trongrid/trongrid-adapters"); const utils_1 = require("../network/utils"); async function getBlockInfo(height) { if (!Number.isSafeInteger(height) || height <= 0) { throw new Error(`Invalid block height: ${height}`); } const block = await (0, network_1.getBlock)(height); return { height: block.height, hash: block.hash, time: block.time ?? new Date(0), }; } async function getBlock(height) { if (!Number.isSafeInteger(height) || height <= 0) { throw new Error(`Invalid block height: ${height}`); } const [data, txInfos] = await Promise.all([ (0, network_1.getBlockWithTransactions)(height), (0, network_1.getTransactionInfoByBlockNum)(height).catch(error => { (0, logs_1.log)("tron/getBlock", "Failed to fetch transaction info, falling back to ret fees", { height, error, }); return []; }), ]); const header = data.block_header.raw_data; const blockTimestamp = header.timestamp ?? 0; const info = { height: header.number ?? height, hash: data.blockID, time: blockTimestamp ? new Date(blockTimestamp) : new Date(0), }; if (header.parentHash && info.height > 1) { info.parent = { height: info.height - 1, hash: header.parentHash }; } const rawTxs = data.transactions ?? []; const txInfoById = buildTxInfoMap(txInfos); const transactions = rawTxs .map(tx => toBlockTransaction(tx, blockTimestamp, info.height, txInfoById)) .filter((tx) => tx !== null); return { info, transactions }; } function buildTxInfoMap(txInfos) { return new Map(txInfos.map(tx => [tx.id, tx])); } function toBlockTransaction(tx, blockTimestamp, blockHeight, txInfoById) { const txInfo = formatBlockTransaction(tx, blockTimestamp, blockHeight); if (!txInfo) return null; const txDetail = txInfoById.get(tx.txID); const fee = txDetail?.fee ?? tx.ret?.[0]?.fee ?? 0; return { hash: txInfo.txID, failed: txInfo.hasFailed, fees: BigInt(fee), feesPayer: txInfo.from, operations: txInfo.hasFailed ? [] : toBlockOperations(txInfo), }; } function formatBlockTransaction(tx, blockTimestamp, blockHeight) { try { const contract = tx.raw_data.contract[0]; if (!contract) return null; const type = contract.type; const params = contract.parameter.value; const ownerAddress = params.owner_address; if (!ownerAddress) return null; const from = (0, format_1.encode58Check)(ownerAddress); const contractRet = tx.ret?.[0]?.contractRet ?? "SUCCESS"; const hasFailed = contractRet !== "SUCCESS"; const isTrc20 = type === "TriggerSmartContract" && params.contract_address; const isTrc10 = type === "TransferAssetContract"; const tokenType = isTrc10 ? "trc10" : isTrc20 ? "trc20" : undefined; let to; let value; if (isTrc20 && params.data) { const decoded = (0, utils_1.abiDecodeTrc20Transfer)(params.data); if (decoded) { to = (0, format_1.encode58Check)(decoded.to); value = decoded.amount; } else { value = new bignumber_js_1.default(0); } } else { to = params.to_address ? (0, format_1.encode58Check)(params.to_address) : undefined; value = params.amount ? new bignumber_js_1.default(params.amount) : new bignumber_js_1.default(0); } const tokenId = isTrc10 ? decodeHexAssetName(params.asset_name) : isTrc20 && params.contract_address ? (0, format_1.encode58Check)(params.contract_address) : undefined; return { txID: tx.txID, date: new Date(blockTimestamp), type, tokenId, tokenType, tokenAddress: isTrc20 && params.contract_address ? (0, format_1.encode58Check)(params.contract_address) : undefined, from, to, value, blockHeight, hasFailed, }; } catch (error) { (0, logs_1.log)("tron/getBlock", "formatBlockTransaction error", { txId: tx.txID, error, }); return null; } } function toBlockOperations(txInfo) { if (isTransfer(txInfo) && txInfo.to && txInfo.value && !txInfo.value.isZero()) { const asset = (0, trongrid_adapters_1.inferAssetInfo)(txInfo); const value = txInfo.value; if (value.isNaN() || !value.isFinite()) { return [{ type: "other", operationType: "NONE", contractType: txInfo.type }]; } const amount = BigInt(value.integerValue().toFixed(0)); return [ { type: "transfer", address: txInfo.from, peer: txInfo.to, asset, amount: -amount }, { type: "transfer", address: txInfo.to, peer: txInfo.from, asset, amount }, ]; } const operationType = getOperationType(txInfo.type); return [{ type: "other", operationType: operationType, contractType: txInfo.type }]; } function isTransfer(txInfo) { return (txInfo.type === "TransferContract" || txInfo.type === "TransferAssetContract" || (txInfo.type === "TriggerSmartContract" && txInfo.tokenType === "trc20")); } function getOperationType(contractType) { switch (contractType) { case "ContractApproval": return "APPROVE"; case "ExchangeTransactionContract": return "OUT"; case "VoteWitnessContract": return "VOTE"; case "WithdrawBalanceContract": return "REWARD"; case "FreezeBalanceContract": case "FreezeBalanceV2Contract": return "FREEZE"; case "UnfreezeBalanceV2Contract": return "UNFREEZE"; case "WithdrawExpireUnfreezeContract": return "WITHDRAW_EXPIRE_UNFREEZE"; case "UnDelegateResourceContract": return "UNDELEGATE_RESOURCE"; case "UnfreezeBalanceContract": return "LEGACY_UNFREEZE"; default: return "NONE"; } } function decodeHexAssetName(hexAssetName) { if (!hexAssetName) return undefined; return Buffer.from(hexAssetName, "hex").toString("utf8"); } //# sourceMappingURL=getBlock.js.map