UNPKG

@factorial-finance/blueprint-node

Version:

blueprint-node-plugin

177 lines (176 loc) 7.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.logFlattenTransactions = logFlattenTransactions; const chalk_1 = __importDefault(require("chalk")); const logger_1 = require("./logger"); const defaults_1 = require("../constants/defaults"); const colors_1 = require("../constants/colors"); async function logFlattenTransactions(flattenTxs, aliasService, blockchainService) { // Pre-cache contract info for deployed contracts for (const flatTx of flattenTxs) { if (flatTx.deploy && flatTx.initCode && flatTx.on) { const addressStr = flatTx.on.toString(); const codeHash = flatTx.initCode.hash().toString('hex'); const contractName = aliasService.findContractNameByCodeHash(codeHash) || 'Unknown'; aliasService.cacheContractInfo(addressStr, codeHash, contractName); } } // Build transaction tree const nodes = buildTransactionTree(flattenTxs); // Generate address aliases const addressAliases = generateAddressAliases(flattenTxs); // Log the transaction tree await logTransactionTree(flattenTxs, nodes, addressAliases, aliasService, blockchainService); } function buildTransactionTree(flattenTxs) { const nodes = flattenTxs.map((_, i) => ({ index: i, children: [] })); // Track outgoing messages for each address const outgoingMessages = new Map(); // Build parent-child relationships for (let i = 0; i < flattenTxs.length; i++) { const flatTx = flattenTxs[i]; if (!flatTx.on) continue; // Record outgoing messages from this transaction if (flatTx.outMessagesCount > 0) { const addr = flatTx.on.toString(); if (!outgoingMessages.has(addr)) { outgoingMessages.set(addr, []); } outgoingMessages.get(addr).push({ txIndex: i, msgCount: flatTx.outMessagesCount, usedCount: 0 }); } // Find parent of this transaction if (flatTx.from) { const fromAddr = flatTx.from.toString(); const senders = outgoingMessages.get(fromAddr) || []; // Find the most recent transaction that sent a message for (let j = senders.length - 1; j >= 0; j--) { const sender = senders[j]; if (sender.txIndex < i && sender.usedCount < sender.msgCount) { nodes[i].parentIndex = sender.txIndex; nodes[sender.txIndex].children.push(i); sender.usedCount++; break; } } } } return nodes; } function generateAddressAliases(flattenTxs) { const addressAliases = new Map(); let aliasCounter = 0; // Generate alphabet aliases (A, B, C, ..., Z, AA, AB, ...) const getNextAlias = () => { let alias = ''; let num = aliasCounter; do { alias = String.fromCharCode(defaults_1.DEFAULTS.ASCII_UPPERCASE_A + (num % defaults_1.DEFAULTS.ALPHABET_SIZE)) + alias; num = Math.floor(num / defaults_1.DEFAULTS.ALPHABET_SIZE) - 1; } while (num >= 0); aliasCounter++; return alias; }; // Assign aliases to unique addresses for (const flatTx of flattenTxs) { if (flatTx.on) { const addressStr = flatTx.on.toString(); if (!addressAliases.has(addressStr)) { addressAliases.set(addressStr, getNextAlias()); } } } return addressAliases; } async function logTransactionTree(flattenTxs, nodes, addressAliases, aliasService, blockchainService) { const logged = new Set(); const logTree = async (index, depth = 0, isLast = true, prefix = '') => { if (logged.has(index)) return; logged.add(index); const flatTx = flattenTxs[index]; if (!flatTx.on) return; const addressStr = flatTx.on.toString(); const currentPrefix = depth === 0 ? '' : (isLast ? ' └─ ' : ' ├─ '); const indent = prefix + currentPrefix; const addressAlias = addressAliases.get(addressStr); // Get contract name let contractName = aliasService.getCachedContractName(addressStr); if (!contractName) { const codeHash = await blockchainService.getCodeHash(flatTx.on); if (codeHash) { contractName = aliasService.findContractNameByCodeHash(codeHash) || 'Unknown'; aliasService.cacheContractInfo(addressStr, codeHash, contractName); } else { contractName = 'Unknown'; } } // Build log message const logMsg = buildLogMessage(indent, contractName, addressStr, addressAlias, flatTx, aliasService); // Log the transaction if (!flatTx.success) { logger_1.Logger.warn(logMsg); } else { logger_1.Logger.info(logMsg); } // Log children const children = nodes[index].children; for (let i = 0; i < children.length; i++) { const isLastChild = i === children.length - 1; const childPrefix = depth === 0 ? '' : prefix + (isLast ? ' ' : ' │ '); await logTree(children[i], depth + 1, isLastChild, childPrefix); } }; // Start from root transactions for (let i = 0; i < nodes.length; i++) { if (nodes[i].parentIndex === undefined) { await logTree(i); } } } function buildLogMessage(indent, contractName, addressStr, addressAlias, flatTx, aliasService) { // Contract name with colors let contractDisplay; if (contractName === 'Unknown') { contractDisplay = chalk_1.default[colors_1.LOG_COLORS.CONTRACT_UNKNOWN](`[${contractName}]`); } else { contractDisplay = chalk_1.default[colors_1.LOG_COLORS.CONTRACT_KNOWN](`[${contractName}]`); } let logMsg = `${indent}${contractDisplay} ${chalk_1.default[colors_1.LOG_COLORS.GRAY](addressStr)} ${chalk_1.default[colors_1.LOG_COLORS.ADDRESS_ALIAS](`(${addressAlias})`)}`; // Add operation info if (flatTx.op !== undefined) { const aliasInfo = aliasService.findActionAlias(flatTx.op, contractName !== 'Unknown' ? contractName : undefined); if (aliasInfo) { logMsg += ` ${chalk_1.default[colors_1.LOG_COLORS.OPERATION_ARROW]('→')} ${chalk_1.default[colors_1.LOG_COLORS.OPERATION_NAME](aliasInfo.alias)}${chalk_1.default[colors_1.LOG_COLORS.OPERATION_CODE](`(0x${flatTx.op.toString(16)})`)}`; } else { logMsg += ` ${chalk_1.default[colors_1.LOG_COLORS.OPERATION_ARROW]('→')} ${chalk_1.default[colors_1.LOG_COLORS.OPERATION_CODE](`UnknownOp:0x${flatTx.op.toString(16)}`)}`; } } // Add error info if (!flatTx.success && flatTx.exitCode !== undefined && flatTx.exitCode !== 0) { const errorAlias = aliasService.findErrorAlias(flatTx.exitCode, contractName !== 'Unknown' ? contractName : undefined); if (errorAlias) { logMsg += ` ${chalk_1.default[colors_1.LOG_COLORS.ERROR_ICON]('✗')} ${chalk_1.default[colors_1.LOG_COLORS.ERROR_MESSAGE](errorAlias.alias)}`; } else { logMsg += ` ${chalk_1.default[colors_1.LOG_COLORS.ERROR_ICON]('✗')} ${chalk_1.default[colors_1.LOG_COLORS.ERROR_ICON](`error:${flatTx.exitCode}`)}`; } } // Add deployment info if (flatTx.deploy) { logMsg += ` ${chalk_1.default[colors_1.LOG_COLORS.DEPLOY_MESSAGE]('DEPLOYED')}`; } return logMsg; }