@factorial-finance/blueprint-node
Version:
blueprint-node-plugin
177 lines (176 loc) • 7.8 kB
JavaScript
;
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;
}