UNPKG

four-flap-meme-sdk

Version:

SDK for Flap bonding curve and four.meme TokenManager

644 lines (643 loc) 28.4 kB
/** * Four.meme 内盘捆绑换手(Merkle Bundle) * * 功能:钱包A卖出代币 → 钱包B买入相同数量 → 原子执行 */ import { ethers, Contract, Wallet } from 'ethers'; import { calculateSellAmount } from '../../utils/swap-helpers.js'; import { NonceManager, getOptimizedGasPrice, getGasLimit, getGasPriceConfig, getTxType, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../../utils/bundle-helpers.js'; import { ADDRESSES, PROFIT_CONFIG, BLOCKRAZOR_BUILDER_EOA } from '../../utils/constants.js'; import { TM_ABI, HELPER3_ABI, TM_ADDRESS } from './swap-internal.js'; import { getBribeAmount, getProfitRecipient } from './config.js'; /** * Four内盘捆绑换手 */ export async function fourBundleSwapMerkle(params) { const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKey, tokenAddress, config, startNonces // ✅ 可选:前端预获取的 nonces } = params; const chainIdNum = config.chainId ?? 56; const provider = new ethers.JsonRpcProvider(config.rpcUrl, { chainId: chainIdNum, name: 'BSC' }); const seller = new Wallet(sellerPrivateKey, provider); const buyer = new Wallet(buyerPrivateKey, provider); const nonceManager = new NonceManager(provider); // ✅ 创建适配的配置对象 const bundleConfig = { minGasPriceGwei: config.minGasPriceGwei, maxGasPriceGwei: config.maxGasPriceGwei, gasLimit: typeof config.gasLimit === 'bigint' ? Number(config.gasLimit) : config.gasLimit, gasLimitMultiplier: config.gasLimitMultiplier, txType: config.txType, chainId: config.chainId }; const finalGasLimit = getGasLimit(bundleConfig); const txType = getTxType(bundleConfig); // ✅ 优化:第一批并行 - calculateSellAmount、gasPrice const [sellAmountResult, gasPrice] = await Promise.all([ calculateSellAmount(provider, tokenAddress, seller.address, sellAmount, sellPercentage), getOptimizedGasPrice(provider, getGasPriceConfig(bundleConfig)) ]); const { amount: sellAmountWei, decimals } = sellAmountResult; // ✅ 优化:第二批并行 - sellQuote、allowance、buyerBalance const helper3 = new Contract(ADDRESSES.BSC.TokenManagerHelper3, HELPER3_ABI, provider); const erc20Contract = new Contract(tokenAddress, ['function allowance(address,address) view returns (uint256)'], provider); const [sellQuote, currentAllowance, buyerBalance] = await Promise.all([ helper3.trySell(tokenAddress, sellAmountWei), erc20Contract.allowance(seller.address, TM_ADDRESS), provider.getBalance(buyer.address) ]); const sellerWillGetBNB = sellQuote.funds; const buyerFunds = sellerWillGetBNB; // 验证买方余额 const reserveGas = ethers.parseEther((config.reserveGasBNB || 0.0005).toString()); const requiredBalance = buyerFunds + reserveGas; if (buyerBalance < requiredBalance) { throw new Error(`买方余额不足:\n` + ` - 需要: ${ethers.formatEther(requiredBalance)} BNB\n` + ` - 实际: ${ethers.formatEther(buyerBalance)} BNB`); } // 检查是否需要授权 const APPROVAL_THRESHOLD = ethers.parseUnits('1000000000', decimals); const needApproval = currentAllowance < APPROVAL_THRESHOLD; // 利润配置 const extractProfit = true; const profitRateBps = PROFIT_CONFIG.RATE_BPS_SWAP; const profitAmount = extractProfit && sellerWillGetBNB > 0n ? (sellerWillGetBNB * BigInt(profitRateBps)) / 10000n : 0n; // ✅ 获取贿赂金额 const bribeAmount = getBribeAmount(config); const needBribeTx = bribeAmount > 0n; // ✅ 优化:第三批并行 - 构建交易、获取 nonces const tmSeller = new Contract(TM_ADDRESS, TM_ABI, seller); const tmBuyer = new Contract(TM_ADDRESS, TM_ABI, buyer); // 计算需要的 nonce 数量 let sellerNonceCount = 1; // 卖出交易 if (needBribeTx) sellerNonceCount++; // 贿赂交易 if (needApproval) sellerNonceCount++; // 授权交易 if (extractProfit) sellerNonceCount++; // 利润交易 // ✅ 优化:使用批量 nonce 获取(JSON-RPC 批量请求) // 如果前端传入了 startNonces,直接使用;否则从链上获取 const [sellUnsigned, buyUnsigned, noncesResult] = await Promise.all([ tmSeller.sellToken.populateTransaction(0n, tokenAddress, sellAmountWei, 0n), tmBuyer.buyTokenAMAP.populateTransaction(0n, tokenAddress, buyer.address, buyerFunds, 0n, { value: buyerFunds }), (async () => { // ✅ 如果前端传入了 startNonces,直接使用(性能优化) if (startNonces && startNonces.length >= 2) { const sellerNonces = Array.from({ length: sellerNonceCount }, (_, i) => startNonces[0] + i); const buyerNonce = startNonces[1]; return { sellerNonces, buyerNonce }; } // 否则从链上获取 const initialNonces = await nonceManager.getNextNoncesForWallets([seller, buyer]); const sellerNonces = Array.from({ length: sellerNonceCount }, (_, i) => initialNonces[0] + i); const buyerNonce = initialNonces[1]; return { sellerNonces, buyerNonce }; })() ]); const { sellerNonces, buyerNonce } = noncesResult; // 分配 nonces let idx = 0; let bribeNonce; let approvalNonce; if (needBribeTx) bribeNonce = sellerNonces[idx++]; if (needApproval) approvalNonce = sellerNonces[idx++]; const sellerNonce = sellerNonces[idx++]; const profitNonce = extractProfit ? sellerNonces[idx] : undefined; // ✅ 并行签名所有交易 const signPromises = []; // ✅ 贿赂交易放在首位 if (needBribeTx && bribeNonce !== undefined) { signPromises.push(seller.signTransaction({ to: BLOCKRAZOR_BUILDER_EOA, value: bribeAmount, nonce: bribeNonce, gasPrice, gasLimit: 21000n, chainId: chainIdNum, type: txType })); } // 授权交易 if (needApproval && approvalNonce !== undefined) { const approveInterface = new ethers.Interface(['function approve(address,uint256) returns (bool)']); const approveData = approveInterface.encodeFunctionData('approve', [TM_ADDRESS, ethers.MaxUint256]); signPromises.push(seller.signTransaction({ to: tokenAddress, data: approveData, value: 0n, nonce: approvalNonce, gasLimit: 80000n, gasPrice, chainId: chainIdNum, type: txType })); } // 卖出和买入交易 signPromises.push(seller.signTransaction({ ...sellUnsigned, from: seller.address, nonce: sellerNonce, gasLimit: finalGasLimit, gasPrice, chainId: chainIdNum, type: txType }), buyer.signTransaction({ ...buyUnsigned, from: buyer.address, nonce: buyerNonce, gasLimit: finalGasLimit, gasPrice, chainId: chainIdNum, type: txType, value: buyerFunds })); const signedTxs = await Promise.all(signPromises); // 解析签名结果 let signIdx = 0; let bribeTx = null; let approvalTx = null; if (needBribeTx) bribeTx = signedTxs[signIdx++]; if (needApproval) approvalTx = signedTxs[signIdx++]; const signedSell = signedTxs[signIdx++]; const signedBuy = signedTxs[signIdx++]; nonceManager.clearTemp(); // ✅ 组装交易列表:贿赂 → 授权 → 卖出 → 买入 const allTransactions = []; if (bribeTx) allTransactions.push(bribeTx); if (approvalTx) allTransactions.push(approvalTx); allTransactions.push(signedSell, signedBuy); // ✅ 利润多跳转账(强制 2 跳中转) if (extractProfit && profitAmount > 0n && profitNonce !== undefined) { const profitHopResult = await buildProfitHopTransactions({ provider, payerWallet: seller, profitAmount: profitAmount, profitRecipient: getProfitRecipient(), hopCount: PROFIT_HOP_COUNT, gasPrice, chainId: chainIdNum, txType, startNonce: profitNonce }); allTransactions.push(...profitHopResult.signedTransactions); } return { signedTransactions: allTransactions, metadata: { sellerAddress: seller.address, buyerAddress: buyer.address, sellAmount: ethers.formatUnits(sellAmountWei, decimals), buyAmount: ethers.formatEther(buyerFunds), hasApproval: !!approvalTx, profitAmount: extractProfit ? ethers.formatEther(profitAmount) : undefined } }; } /** * Four 内盘批量换手(一卖多买) * * 功能:主钱包一次卖出 → 多个子钱包同时买入 → 在同一个区块中完成 * 限制:最多 24 个买方(服务器限制 25 笔交易,包含 1 笔利润交易) */ export async function fourBatchSwapMerkle(params) { const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, tokenAddress, config, startNonces // ✅ 可选:前端预获取的 nonces } = params; // ✅ 校验买方数量(最多 24 个) const MAX_BUYERS = 24; if (buyerPrivateKeys.length === 0) { throw new Error('至少需要一个买方钱包'); } if (buyerPrivateKeys.length > MAX_BUYERS) { throw new Error(`买方钱包数量超过限制: ${buyerPrivateKeys.length} > ${MAX_BUYERS}`); } const chainIdNum = config.chainId ?? 56; const provider = new ethers.JsonRpcProvider(config.rpcUrl, { chainId: chainIdNum, name: 'BSC' }); const seller = new Wallet(sellerPrivateKey, provider); const buyers = buyerPrivateKeys.map(pk => new Wallet(pk, provider)); const nonceManager = new NonceManager(provider); // 创建适配的配置对象 const bundleConfig = { minGasPriceGwei: config.minGasPriceGwei, maxGasPriceGwei: config.maxGasPriceGwei, gasLimit: typeof config.gasLimit === 'bigint' ? Number(config.gasLimit) : config.gasLimit, gasLimitMultiplier: config.gasLimitMultiplier, txType: config.txType, chainId: config.chainId }; const finalGasLimit = getGasLimit(bundleConfig); const txType = getTxType(bundleConfig); // ✅ 并行获取:卖出数量、gasPrice const [sellAmountResult, gasPrice] = await Promise.all([ calculateSellAmount(provider, tokenAddress, seller.address, sellAmount, sellPercentage), getOptimizedGasPrice(provider, getGasPriceConfig(bundleConfig)) ]); const { amount: sellAmountWei, decimals } = sellAmountResult; // ✅ 并行获取:sellQuote、allowance、所有买方余额 const helper3 = new Contract(ADDRESSES.BSC.TokenManagerHelper3, HELPER3_ABI, provider); const erc20Contract = new Contract(tokenAddress, ['function allowance(address,address) view returns (uint256)'], provider); const [sellQuote, currentAllowance, ...buyerBalances] = await Promise.all([ helper3.trySell(tokenAddress, sellAmountWei), erc20Contract.allowance(seller.address, TM_ADDRESS), ...buyers.map(buyer => provider.getBalance(buyer.address)) ]); const totalBuyerFunds = sellQuote.funds; // ✅ 计算每个买方的买入金额(按比例分配) let buyAmountsWei; if (params.buyerRatios && params.buyerRatios.length === buyers.length) { // 按比例分配 buyAmountsWei = params.buyerRatios.map((ratio, index) => { const amount = (totalBuyerFunds * BigInt(Math.round(ratio * 10000))) / 10000n; return amount; }); } else { // 平均分配 const amountPerBuyer = totalBuyerFunds / BigInt(buyers.length); buyAmountsWei = buyers.map(() => amountPerBuyer); } // ✅ 验证所有买方余额 const reserveGas = ethers.parseEther((config.reserveGasBNB || 0.0005).toString()); buyers.forEach((buyer, i) => { const required = buyAmountsWei[i] + reserveGas; if (buyerBalances[i] < required) { throw new Error(`买方 ${i + 1} 余额不足: 需要 ${ethers.formatEther(required)} BNB, 实际 ${ethers.formatEther(buyerBalances[i])} BNB`); } }); // 检查是否需要授权 const APPROVAL_THRESHOLD = ethers.parseUnits('1000000000', decimals); const needApproval = currentAllowance < APPROVAL_THRESHOLD; // 利润配置 const profitRateBps = PROFIT_CONFIG.RATE_BPS_SWAP; const profitAmount = totalBuyerFunds > 0n ? (totalBuyerFunds * BigInt(profitRateBps)) / 10000n : 0n; // ✅ 获取贿赂金额 const bribeAmount = getBribeAmount(config); const needBribeTx = bribeAmount > 0n; // ✅ 并行构建所有交易 const tmSeller = new Contract(TM_ADDRESS, TM_ABI, seller); const [sellUnsigned, ...buyUnsignedList] = await Promise.all([ // 卖出交易 tmSeller.sellToken.populateTransaction(0n, tokenAddress, sellAmountWei, 0n), // 所有买入交易 ...buyers.map((buyer, i) => { const tmBuyer = new Contract(TM_ADDRESS, TM_ABI, buyer); const buyAmount = buyAmountsWei[i]; return tmBuyer.buyTokenAMAP.populateTransaction(0n, tokenAddress, buyer.address, buyAmount, 0n, { value: buyAmount }); }) ]); // ✅ 计算 nonce // seller 需要的 nonce 数量 let sellerNonceCount = 1; // 卖出交易 if (needBribeTx) sellerNonceCount++; // 贿赂交易 if (needApproval) sellerNonceCount++; // 授权交易 sellerNonceCount++; // 利润交易 // ✅ 如果前端传入了 startNonces,直接使用(性能优化) // 否则从链上获取 const allWallets = [seller, ...buyers]; const initialNonces = startNonces && startNonces.length >= allWallets.length ? startNonces : await nonceManager.getNextNoncesForWallets(allWallets); // 分配 seller nonces const sellerNonces = Array.from({ length: sellerNonceCount }, (_, i) => initialNonces[0] + i); let idx = 0; let bribeNonce; let approvalNonce; if (needBribeTx) bribeNonce = sellerNonces[idx++]; if (needApproval) approvalNonce = sellerNonces[idx++]; const sellerNonce = sellerNonces[idx++]; const profitNonce = sellerNonces[idx]; // buyer nonces const buyerNonces = initialNonces.slice(1); // ✅ 并行签名所有交易 const signPromises = []; // ✅ 贿赂交易放在首位 if (needBribeTx && bribeNonce !== undefined) { signPromises.push(seller.signTransaction({ to: BLOCKRAZOR_BUILDER_EOA, value: bribeAmount, nonce: bribeNonce, gasPrice, gasLimit: 21000n, chainId: chainIdNum, type: txType })); } // 授权交易 if (needApproval && approvalNonce !== undefined) { const approveInterface = new ethers.Interface(['function approve(address,uint256) returns (bool)']); const approveData = approveInterface.encodeFunctionData('approve', [TM_ADDRESS, ethers.MaxUint256]); signPromises.push(seller.signTransaction({ to: tokenAddress, data: approveData, value: 0n, nonce: approvalNonce, gasLimit: 80000n, gasPrice, chainId: chainIdNum, type: txType })); } // 卖出交易 signPromises.push(seller.signTransaction({ ...sellUnsigned, from: seller.address, nonce: sellerNonce, gasLimit: finalGasLimit, gasPrice, chainId: chainIdNum, type: txType })); // 所有买入交易 buyers.forEach((buyer, i) => { signPromises.push(buyer.signTransaction({ ...buyUnsignedList[i], from: buyer.address, nonce: buyerNonces[i], gasLimit: finalGasLimit, gasPrice, chainId: chainIdNum, type: txType, value: buyAmountsWei[i] })); }); const signedTxs = await Promise.all(signPromises); // 解析签名结果 let signIdx = 0; let bribeTx = null; let approvalTx = null; if (needBribeTx) bribeTx = signedTxs[signIdx++]; if (needApproval) approvalTx = signedTxs[signIdx++]; const signedSell = signedTxs[signIdx++]; const signedBuys = signedTxs.slice(signIdx, signIdx + buyers.length); nonceManager.clearTemp(); // ✅ 按顺序组装交易数组:贿赂 → 授权 → 卖出 → 买入 const signedTransactions = []; if (bribeTx) signedTransactions.push(bribeTx); if (approvalTx) signedTransactions.push(approvalTx); signedTransactions.push(signedSell); signedTransactions.push(...signedBuys); // ✅ 利润多跳转账(强制 2 跳中转) if (profitAmount > 0n) { const profitHopResult = await buildProfitHopTransactions({ provider, payerWallet: seller, profitAmount: profitAmount, profitRecipient: getProfitRecipient(), hopCount: PROFIT_HOP_COUNT, gasPrice, chainId: chainIdNum, txType, startNonce: profitNonce }); signedTransactions.push(...profitHopResult.signedTransactions); } return { signedTransactions, metadata: { sellerAddress: seller.address, buyerAddresses: buyers.map(b => b.address), sellAmount: ethers.formatUnits(sellAmountWei, decimals), buyAmounts: buyAmountsWei.map(amt => ethers.formatEther(amt)), hasApproval: !!approvalTx, profitAmount: ethers.formatEther(profitAmount) } }; } /** * Four 内盘快捷批量换手(资金利用率模式) * * 流程:[贿赂] → [卖出] → [转账1, 转账2, ...] → [买入1, 买入2, ...] → [利润] * * 特点: * - 子钱包不需要预先有 BNB * - 资金来自主钱包卖出代币所得 * - 提升资金利用率 * * 限制:最多 23 个买方(2N + 3 ≤ 50) */ export async function fourQuickBatchSwapMerkle(params) { const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerRatios, buyerAmounts, tokenAddress, config, startNonces // ✅ 可选:前端预获取的 nonces } = params; // ✅ 校验买方数量 // 贿赂(1) + 卖出(1) + 转账(N) + 买入(N) + 利润(1) ≤ 50 → 2N + 3 ≤ 50 → N ≤ 23 const MAX_BUYERS = 23; if (buyerPrivateKeys.length === 0) { throw new Error('至少需要一个买方钱包'); } if (buyerPrivateKeys.length > MAX_BUYERS) { throw new Error(`资金利用率模式买方钱包数量超过限制: ${buyerPrivateKeys.length} > ${MAX_BUYERS}`); } // ✅ 校验分配模式 if (!buyerRatios && !buyerAmounts) { throw new Error('必须提供 buyerRatios 或 buyerAmounts'); } if (buyerRatios && buyerRatios.length !== buyerPrivateKeys.length) { throw new Error(`buyerRatios 长度 (${buyerRatios.length}) 与 buyerPrivateKeys 长度 (${buyerPrivateKeys.length}) 不匹配`); } if (buyerAmounts && buyerAmounts.length !== buyerPrivateKeys.length) { throw new Error(`buyerAmounts 长度 (${buyerAmounts.length}) 与 buyerPrivateKeys 长度 (${buyerPrivateKeys.length}) 不匹配`); } const chainIdNum = config.chainId ?? 56; const provider = new ethers.JsonRpcProvider(config.rpcUrl, { chainId: chainIdNum, name: 'BSC' }); const seller = new Wallet(sellerPrivateKey, provider); const buyers = buyerPrivateKeys.map(pk => new Wallet(pk, provider)); const nonceManager = new NonceManager(provider); // 创建适配的配置对象 const bundleConfig = { minGasPriceGwei: config.minGasPriceGwei, maxGasPriceGwei: config.maxGasPriceGwei, gasLimit: typeof config.gasLimit === 'bigint' ? Number(config.gasLimit) : config.gasLimit, gasLimitMultiplier: config.gasLimitMultiplier, txType: config.txType, chainId: config.chainId }; const finalGasLimit = getGasLimit(bundleConfig); const txType = getTxType(bundleConfig); // ✅ 并行获取:卖出数量、gasPrice const [sellAmountResult, gasPrice] = await Promise.all([ calculateSellAmount(provider, tokenAddress, seller.address, sellAmount, sellPercentage), getOptimizedGasPrice(provider, getGasPriceConfig(bundleConfig)) ]); const { amount: sellAmountWei, decimals } = sellAmountResult; // ✅ 获取卖出报价 const helper3 = new Contract(ADDRESSES.BSC.TokenManagerHelper3, HELPER3_ABI, provider); const sellQuote = await helper3.trySell(tokenAddress, sellAmountWei); const estimatedBNBOut = sellQuote.funds; console.log(`[fourQuickBatchSwapMerkle] 卖出数量: ${ethers.formatUnits(sellAmountWei, decimals)}`); console.log(`[fourQuickBatchSwapMerkle] 预估卖出所得: ${ethers.formatEther(estimatedBNBOut)} BNB`); // ✅ 计算利润(万分之六) const profitRateBps = PROFIT_CONFIG.RATE_BPS_SWAP; const profitAmount = estimatedBNBOut > 0n ? (estimatedBNBOut * BigInt(profitRateBps)) / 10000n : 0n; const distributableAmount = estimatedBNBOut - profitAmount; // ✅ 计算每个买方分到的金额 let transferAmountsWei; if (buyerAmounts && buyerAmounts.length === buyers.length) { // 数量模式 transferAmountsWei = buyerAmounts.map(amt => ethers.parseEther(amt)); const totalTransfer = transferAmountsWei.reduce((a, b) => a + b, 0n); if (totalTransfer > distributableAmount) { throw new Error(`指定的买入总金额超过可分配金额 (${ethers.formatEther(distributableAmount)} BNB)`); } } else if (buyerRatios && buyerRatios.length === buyers.length) { // 比例模式 transferAmountsWei = buyerRatios.map(ratio => { return (distributableAmount * BigInt(Math.round(ratio * 10000))) / 10000n; }); } else { throw new Error('必须提供 buyerRatios 或 buyerAmounts'); } // ✅ 获取贿赂金额 const bribeAmount = getBribeAmount(config); // ✅ 验证主钱包余额 const sellerBalance = await seller.provider.getBalance(seller.address); // 主钱包只需要支付:贿赂 + Gas(卖出后有 BNB 可用于转账和利润) const sellerGasCost = gasPrice * (21000n + finalGasLimit + 21000n * BigInt(buyers.length) + 21000n); const sellerRequired = bribeAmount + sellerGasCost; if (sellerBalance < sellerRequired) { throw new Error(`主钱包 BNB 余额不足: 需要约 ${ethers.formatEther(sellerRequired)} BNB (贿赂: ${ethers.formatEther(bribeAmount)}, Gas: ${ethers.formatEther(sellerGasCost)}), 实际 ${ethers.formatEther(sellerBalance)} BNB`); } // ==================== 规划 Nonce ==================== // ✅ 如果前端传入了 startNonces,直接使用(性能优化) let sellerNonce = startNonces && startNonces.length > 0 ? startNonces[0] : await nonceManager.getNextNonce(seller); // ==================== 1. 贿赂交易 ==================== let bribeTx = null; if (bribeAmount > 0n) { bribeTx = await seller.signTransaction({ to: BLOCKRAZOR_BUILDER_EOA, value: bribeAmount, nonce: sellerNonce++, gasPrice, gasLimit: 21000n, chainId: chainIdNum, type: txType }); console.log(`[fourQuickBatchSwapMerkle] 贿赂交易已签名`); } // ==================== 2. 卖出交易 ==================== const tmSeller = new Contract(TM_ADDRESS, TM_ABI, seller); const sellUnsigned = await tmSeller.sellToken.populateTransaction(0n, tokenAddress, sellAmountWei, 0n); const signedSell = await seller.signTransaction({ ...sellUnsigned, from: seller.address, nonce: sellerNonce++, gasLimit: finalGasLimit, gasPrice, chainId: chainIdNum, type: txType }); console.log(`[fourQuickBatchSwapMerkle] 卖出交易已签名`); // ==================== 3. 转账交易(并行签名)==================== const reserveGas = ethers.parseEther((config.reserveGasBNB || 0.0005).toString()); const buyerGasCost = gasPrice * finalGasLimit; // ✅ 预分配 nonce,然后并行签名 const transferNonces = buyers.map((_, i) => sellerNonce + i); sellerNonce += buyers.length; // 更新 sellerNonce const transferTxs = await Promise.all(buyers.map((buyer, i) => { const transferValue = transferAmountsWei[i] + reserveGas + buyerGasCost; return seller.signTransaction({ to: buyer.address, value: transferValue, nonce: transferNonces[i], gasPrice, gasLimit: 21000n, chainId: chainIdNum, type: txType }); })); console.log(`[fourQuickBatchSwapMerkle] ${transferTxs.length} 笔转账交易已签名`); // ==================== 4. 买入交易 ==================== // ✅ 如果前端传入了 startNonces,使用 buyer 部分(从索引 1 开始) const buyerNonces = startNonces && startNonces.length > 1 ? startNonces.slice(1) : await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer))); const signedBuys = await Promise.all(buyers.map(async (buyer, i) => { const buyAmount = transferAmountsWei[i]; const tmBuyer = new Contract(TM_ADDRESS, TM_ABI, buyer); const buyUnsigned = await tmBuyer.buyTokenAMAP.populateTransaction(0n, tokenAddress, buyer.address, buyAmount, 0n, { value: buyAmount }); return buyer.signTransaction({ ...buyUnsigned, from: buyer.address, nonce: buyerNonces[i], gasLimit: finalGasLimit, gasPrice, chainId: chainIdNum, type: txType, value: buyAmount }); })); console.log(`[fourQuickBatchSwapMerkle] ${signedBuys.length} 笔买入交易已签名`); nonceManager.clearTemp(); // ==================== 组装交易数组 ==================== const signedTransactions = []; if (bribeTx) signedTransactions.push(bribeTx); signedTransactions.push(signedSell); signedTransactions.push(...transferTxs); signedTransactions.push(...signedBuys); // ==================== 5. 利润多跳转账(强制 2 跳中转)==================== if (profitAmount > 0n) { const profitHopResult = await buildProfitHopTransactions({ provider, payerWallet: seller, profitAmount: profitAmount, profitRecipient: getProfitRecipient(), hopCount: PROFIT_HOP_COUNT, gasPrice, chainId: chainIdNum, txType, startNonce: sellerNonce++ }); signedTransactions.push(...profitHopResult.signedTransactions); console.log(`[fourQuickBatchSwapMerkle] 利润多跳交易已签名: ${profitHopResult.signedTransactions.length} 笔`); } console.log(`[fourQuickBatchSwapMerkle] 交易组装完成: ${signedTransactions.length} 笔`); console.log(` - 贿赂: ${bribeTx ? 1 : 0}`); console.log(` - 卖出: 1`); console.log(` - 转账: ${transferTxs.length}`); console.log(` - 买入: ${signedBuys.length}`); console.log(` - 利润多跳: ${profitAmount > 0n ? PROFIT_HOP_COUNT + 1 : 0}`); return { signedTransactions, metadata: { sellerAddress: seller.address, buyerAddresses: buyers.map(b => b.address), sellAmount: ethers.formatUnits(sellAmountWei, decimals), estimatedBNBOut: ethers.formatEther(estimatedBNBOut), transferAmounts: transferAmountsWei.map(amt => ethers.formatEther(amt)), profitAmount: profitAmount > 0n ? ethers.formatEther(profitAmount) : undefined } }; }