UNPKG

flashloan-profit-calculator

Version:

A library for analyzing flashloan transactions and calculating profits

175 lines (174 loc) 7.7 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.flashloanContracts = exports.globalContractAddress = exports.globalSenderAddress = exports.globalGasCostWei = exports.globalGasCostETH = exports.globalBlockNumber = exports.FlashloanAnalysisClient = void 0; exports.calculateProfitFromTxHash = calculateProfitFromTxHash; exports.calculateProfit = calculateProfit; exports.displayProfitResults = displayProfitResults; const constants_1 = require("./constants"); const transferProcessor_1 = require("./transferProcessor"); const profitCalculator_1 = require("./profitCalculator"); __exportStar(require("./types"), exports); __exportStar(require("./constants"), exports); __exportStar(require("./utils"), exports); __exportStar(require("./transferProcessor"), exports); __exportStar(require("./profitCalculator"), exports); __exportStar(require("./api/types"), exports); var client_1 = require("./api/client"); Object.defineProperty(exports, "FlashloanAnalysisClient", { enumerable: true, get: function () { return __importDefault(client_1).default; } }); exports.flashloanContracts = []; /** * Calculate profit from a transaction hash */ async function calculateProfitFromTxHash(txHash) { try { // Get transaction details let transactionDetails; try { transactionDetails = await (0, transferProcessor_1.getTransactionDetails)(txHash); } catch (error) { console.error(`Failed - Could not get transaction details: ${error}`); throw error; } const { blockNumber, senderAddress, contractAddress, trace, logs, gasCostETH, gasCostWei, } = transactionDetails; exports.globalBlockNumber = transactionDetails.blockNumber; exports.globalGasCostETH = gasCostETH; exports.globalGasCostWei = gasCostWei; exports.globalSenderAddress = senderAddress; exports.globalContractAddress = contractAddress; // Calculate profit using the extracted data console.log(`Calculating profit for tx ${txHash}...`); let profit; try { profit = await calculateProfit(logs, trace, blockNumber, contractAddress, senderAddress); // Log profit summary console.log("Profit Summary:"); for (const item of profit) { console.log(` Token: ${item.token}, Profit: ${item.profit.toString()}`); } } catch (error) { console.error(`Failed - Could not calculate profit: ${error}`); throw error; } console.log(`========== COMPLETED ANALYSIS FOR TX: ${txHash} ==========`); return profit; } catch (error) { console.error(`ANALYSIS FAILED FOR TX ${txHash}: ${error}`); console.error(`Stack trace: ${error.stack}`); throw error; } } /** * Main function to calculate profit from a transaction */ async function calculateProfit(logs, trace, blockNumber, contract, sender) { try { console.log(`Starting profit calculation: Block ${blockNumber}, Contract ${contract}, Sender ${sender}`); // Reset state for clean calculation (0, transferProcessor_1.resetState)(); (0, profitCalculator_1.resetProfitTakers)(); console.log("State reset complete"); // Setup the processor try { await (0, transferProcessor_1.updateBuilderAddress)(blockNumber); console.log(`Builder address updated: ${blockNumber}`); } catch (error) { console.error(`Failed to update builder address: ${error}`); // Continue with processing even if this fails } (0, transferProcessor_1.setupProcessor)(contract, sender); console.log(`Processor setup complete: Contract ${contract}, Sender ${sender}`); // Process transfer logs and trace data const filteredLogs = logs.filter((log) => log.name === "Transfer" || (log.name === "Withdrawal" && constants_1.WETH_LIKE_TOKENS.has(log.raw.address)) || (log.name === "Deposit" && constants_1.WETH_LIKE_TOKENS.has(log.raw.address))); try { for (const log of filteredLogs) { console.log(`Processing log: ${log.name}`); try { (0, transferProcessor_1.processTransferLog)(log); } catch (error) { console.error(`Error processing log: ${error}`); // Continue with next log } } } catch (error) { console.error(`Failed to process logs: ${error}`); // Continue with trace processing } try { console.log(`Processing ${trace.length} trace calls`); await (0, transferProcessor_1.processTraceCall)(trace); console.log("Trace processing complete"); } catch (error) { console.error(`Failed to process trace calls: ${error}`); // Continue with profit calculation } // Calculate profit try { console.log("Calculating profit..."); const profit = await (0, profitCalculator_1.calculateProfitByToken)(); console.log(`Profit calculation complete. Found ${profit.length} tokens`); return profit; } catch (error) { console.error(`Failed to calculate profit: ${error}`); throw error; } } catch (error) { console.error(`Fatal error in calculateProfit: ${error}`); console.error(`Stack trace: ${error.stack}`); throw error; } } /** * Format and display profit results */ async function displayProfitResults(profitResults) { console.log("Profit Summary:"); let totalProfit = 0; for (const result of profitResults) { try { // Try to get token metadata for better display const metadata = await (0, transferProcessor_1.getTokenMetadata)(result.token); const decimals = metadata.decimals || 18; const symbol = metadata.symbol || "ETH"; // Calculate human-readable profit const profit = Number(result.profit) / 10 ** decimals; const usd = result.usd * profit; totalProfit += usd; console.log(`Token: ${result.token} (${symbol}), Profit: ${profit.toFixed(decimals)} ${symbol}, USD: $${usd.toFixed(2)}`); } catch (error) { // If metadata can't be retrieved, display raw data const usd = (result.usd * Number(result.profit)) / 1e18; totalProfit += usd; console.log(`Token: ${result.token}, Profit: ${Number(result.profit) / 1e18} (raw), USD: $${usd.toFixed(2)}`); } } console.log(`Total Profit: $${totalProfit.toFixed(2)}`); }