four-flap-meme-sdk
Version:
SDK for Flap bonding curve and four.meme TokenManager
644 lines (643 loc) • 28.4 kB
JavaScript
/**
* 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
}
};
}