four-flap-meme-sdk 1.4.16 → 1.4.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,8 @@ import { ethers, Contract, Wallet } from 'ethers';
7
7
  import { NonceManager, getOptimizedGasPrice } from '../../utils/bundle-helpers.js';
8
8
  import { ADDRESSES } from '../../utils/constants.js';
9
9
  import { TM_ABI, HELPER3_ABI, TM_ADDRESS } from './swap-internal.js';
10
- import { getTxType, getGasPriceConfig, getProfitRecipient, getProfitRateBps, getBribeAmount } from './config.js';
10
+ import { getTxType, getGasPriceConfig, getProfitRecipient, getBribeAmount } from './config.js';
11
+ import { PROFIT_CONFIG } from '../../utils/constants.js';
11
12
  import { trySell } from '../tm.js';
12
13
  // ✅ BlockRazor Builder EOA 地址(用于贿赂)
13
14
  const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
@@ -88,7 +89,7 @@ export async function fourBundleBuyFirstMerkle(params) {
88
89
  const minBuyAmount = 0n;
89
90
  // 预先规划 nonces
90
91
  const extractProfit = true;
91
- const profitRateBps = getProfitRateBps();
92
+ const profitRateBps = PROFIT_CONFIG.RATE_BPS_CAPITAL; // 万分之三
92
93
  // ✅ 获取贿赂金额
93
94
  const bribeAmount = getBribeAmount(config);
94
95
  const needBribeTx = bribeAmount > 0n;
@@ -101,25 +102,17 @@ export async function fourBundleBuyFirstMerkle(params) {
101
102
  sellerNonceCount++; // 授权交易
102
103
  if (extractProfit)
103
104
  sellerNonceCount++; // 利润交易
104
- // ✅ 优化:使用批量 nonce 获取(JSON-RPC 批量请求)
105
- // 同一地址时使用 getNextNonceBatch 获取连续 nonce
106
- // 不同地址时使用 getNextNoncesForWallets 一次性获取两个地址的初始 nonce
105
+ // ✅ 优化:使用批量 nonce 获取(单次网络往返)
107
106
  const getNoncesPromise = sameAddress
108
107
  ? nonceManager.getNextNonceBatch(seller, buyerNonceCount + sellerNonceCount)
109
108
  .then(nonces => ({ buyerNonces: [], sellerNonces: nonces }))
110
- : (async () => {
111
- // 优化:一次性获取两个地址的初始 nonce(单次网络往返)
112
- const initialNonces = await nonceManager.getNextNoncesForWallets([buyer, seller]);
109
+ : nonceManager.getNextNoncesForWallets([buyer, seller])
110
+ .then(initialNonces => ({
113
111
  // buyer 只需要 1 个 nonce
114
- const buyerNonces = [initialNonces[0]];
112
+ buyerNonces: [initialNonces[0]],
115
113
  // seller 需要 sellerNonceCount 个连续 nonce,从初始 nonce 开始
116
- const sellerNonces = Array.from({ length: sellerNonceCount }, (_, i) => initialNonces[1] + i);
117
- // 更新 NonceManager 缓存
118
- for (let i = 1; i < sellerNonceCount; i++) {
119
- await nonceManager.getNextNonce(seller); // 递增缓存
120
- }
121
- return { buyerNonces, sellerNonces };
122
- })();
114
+ sellerNonces: Array.from({ length: sellerNonceCount }, (_, i) => initialNonces[1] + i)
115
+ }));
123
116
  const [sellResult, buyUnsigned, sellUnsigned, noncesResult] = await Promise.all([
124
117
  trySell('BSC', config.rpcUrl, tokenAddress, sellAmountWei),
125
118
  tmBuyer.buyTokenAMAP.populateTransaction(0n, tokenAddress, buyer.address, buyerFundsWei, minBuyAmount, { value: buyerFundsWei }),
@@ -64,7 +64,7 @@ export async function fourBundleSwapMerkle(params) {
64
64
  const needApproval = currentAllowance < APPROVAL_THRESHOLD;
65
65
  // 利润配置
66
66
  const extractProfit = true;
67
- const profitRateBps = PROFIT_CONFIG.RATE_BPS;
67
+ const profitRateBps = PROFIT_CONFIG.RATE_BPS_CAPITAL;
68
68
  const profitAmount = extractProfit && sellerWillGetBNB > 0n
69
69
  ? (sellerWillGetBNB * BigInt(profitRateBps)) / 10000n
70
70
  : 0n;
@@ -282,7 +282,7 @@ export async function fourBatchSwapMerkle(params) {
282
282
  const APPROVAL_THRESHOLD = ethers.parseUnits('1000000000', decimals);
283
283
  const needApproval = currentAllowance < APPROVAL_THRESHOLD;
284
284
  // 利润配置
285
- const profitRateBps = PROFIT_CONFIG.RATE_BPS;
285
+ const profitRateBps = PROFIT_CONFIG.RATE_BPS_CAPITAL;
286
286
  const profitAmount = totalBuyerFunds > 0n
287
287
  ? (totalBuyerFunds * BigInt(profitRateBps)) / 10000n
288
288
  : 0n;
@@ -489,8 +489,8 @@ export async function fourQuickBatchSwapMerkle(params) {
489
489
  const estimatedBNBOut = sellQuote.funds;
490
490
  console.log(`[fourQuickBatchSwapMerkle] 卖出数量: ${ethers.formatUnits(sellAmountWei, decimals)}`);
491
491
  console.log(`[fourQuickBatchSwapMerkle] 预估卖出所得: ${ethers.formatEther(estimatedBNBOut)} BNB`);
492
- // ✅ 计算利润
493
- const profitRateBps = PROFIT_CONFIG.RATE_BPS;
492
+ // ✅ 计算利润(万分之三)
493
+ const profitRateBps = PROFIT_CONFIG.RATE_BPS_CAPITAL;
494
494
  const profitAmount = estimatedBNBOut > 0n
495
495
  ? (estimatedBNBOut * BigInt(profitRateBps)) / 10000n
496
496
  : 0n;
@@ -553,24 +553,24 @@ export async function fourQuickBatchSwapMerkle(params) {
553
553
  type: txType
554
554
  });
555
555
  console.log(`[fourQuickBatchSwapMerkle] 卖出交易已签名`);
556
- // ==================== 3. 转账交易 ====================
557
- const transferTxs = [];
556
+ // ==================== 3. 转账交易(并行签名)====================
558
557
  const reserveGas = ethers.parseEther((config.reserveGasBNB || 0.0005).toString());
559
- for (let i = 0; i < buyers.length; i++) {
560
- // 转账金额 = 买入金额 + Gas 预留
561
- const buyerGasCost = gasPrice * finalGasLimit;
558
+ const buyerGasCost = gasPrice * finalGasLimit;
559
+ // 预分配 nonce,然后并行签名
560
+ const transferNonces = buyers.map((_, i) => sellerNonce + i);
561
+ sellerNonce += buyers.length; // 更新 sellerNonce
562
+ const transferTxs = await Promise.all(buyers.map((buyer, i) => {
562
563
  const transferValue = transferAmountsWei[i] + reserveGas + buyerGasCost;
563
- const transferTx = await seller.signTransaction({
564
- to: buyers[i].address,
564
+ return seller.signTransaction({
565
+ to: buyer.address,
565
566
  value: transferValue,
566
- nonce: sellerNonce++,
567
+ nonce: transferNonces[i],
567
568
  gasPrice,
568
569
  gasLimit: 21000n,
569
570
  chainId: chainIdNum,
570
571
  type: txType
571
572
  });
572
- transferTxs.push(transferTx);
573
- }
573
+ }));
574
574
  console.log(`[fourQuickBatchSwapMerkle] ${transferTxs.length} 笔转账交易已签名`);
575
575
  // ==================== 4. 买入交易 ====================
576
576
  const buyerNonces = await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
@@ -1,8 +1,19 @@
1
1
  import { ethers, Wallet, Contract } from 'ethers';
2
2
  // import { MerkleClient } from '../../clients/merkle.js';
3
3
  import { getOptimizedGasPrice, NonceManager } from '../../utils/bundle-helpers.js';
4
- import { getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, getProfitRecipient } from './config.js';
4
+ import { PROFIT_CONFIG } from '../../utils/constants.js';
5
+ import { getTxType, getGasPriceConfig, shouldExtractProfit, getProfitRecipient } from './config.js';
5
6
  import { getErc20DecimalsMerkle as _getErc20DecimalsMerkle, generateHopWallets as _generateHopWallets, normalizeAmounts as _normalizeAmounts, batchGetBalances as _batchGetBalances, calculateGasLimit as _calculateGasLimit, isNativeTokenAddress as _isNativeTokenAddress } from './internal.js';
7
+ // ==================== 本地利润计算(万分之三)====================
8
+ /**
9
+ * 计算利润金额(万分之三)
10
+ * ✅ 归集和分散专用:3 bps = 0.03%
11
+ */
12
+ function calculateProfit(amount) {
13
+ const profit = (amount * BigInt(PROFIT_CONFIG.RATE_BPS_CAPITAL)) / 10000n;
14
+ const remaining = amount - profit;
15
+ return { profit, remaining };
16
+ }
6
17
  // ==================== ERC20 → 原生代币报价 ====================
7
18
  // BSC 链常量
8
19
  const BSC_PANCAKE_V2_ROUTER = '0x10ED43C718714eb63d5aA57B78B54704E256024E';
@@ -122,7 +133,7 @@ export async function disperseWithBundleMerkle(params) {
122
133
  totalAmountBeforeProfit += originalAmount;
123
134
  let actualAmount = originalAmount;
124
135
  if (extractProfit) {
125
- const { profit, remaining } = calculateProfit(originalAmount, config);
136
+ const { profit, remaining } = calculateProfit(originalAmount);
126
137
  actualAmount = remaining;
127
138
  totalProfit += profit;
128
139
  }
@@ -163,7 +174,7 @@ export async function disperseWithBundleMerkle(params) {
163
174
  totalAmountBeforeProfit += originalAmount;
164
175
  let actualAmount = originalAmount;
165
176
  if (extractProfit) {
166
- const { profit, remaining } = calculateProfit(originalAmount, config);
177
+ const { profit, remaining } = calculateProfit(originalAmount);
167
178
  actualAmount = remaining;
168
179
  totalTokenProfit += profit; // 累计 ERC20 代币利润
169
180
  }
@@ -249,7 +260,7 @@ export async function disperseWithBundleMerkle(params) {
249
260
  totalAmountBeforeProfit += originalAmountWei;
250
261
  let amountWei = originalAmountWei;
251
262
  if (extractProfit) {
252
- const { profit, remaining } = calculateProfit(originalAmountWei, config);
263
+ const { profit, remaining } = calculateProfit(originalAmountWei);
253
264
  amountWei = remaining;
254
265
  if (isNative) {
255
266
  totalProfit += profit; // 原生币直接累加
@@ -519,7 +530,7 @@ export async function sweepWithBundleMerkle(params) {
519
530
  }
520
531
  // 累计总利润
521
532
  if (extractProfit && toSend > 0n) {
522
- const { profit } = calculateProfit(toSend, config);
533
+ const { profit } = calculateProfit(toSend);
523
534
  totalProfit += profit;
524
535
  }
525
536
  }
@@ -537,7 +548,7 @@ export async function sweepWithBundleMerkle(params) {
537
548
  totalProfit = 0n;
538
549
  for (let i = 0; i < sweepAmounts.length; i++) {
539
550
  if (sweepAmounts[i] > 0n) {
540
- totalProfit += calculateProfit(sweepAmounts[i], config).profit;
551
+ totalProfit += calculateProfit(sweepAmounts[i]).profit;
541
552
  }
542
553
  }
543
554
  }
@@ -666,7 +677,7 @@ export async function sweepWithBundleMerkle(params) {
666
677
  }
667
678
  // 累计总代币利润(ERC20 归集)
668
679
  if (extractProfit && toSend > 0n) {
669
- const { profit } = calculateProfit(toSend, config);
680
+ const { profit } = calculateProfit(toSend);
670
681
  totalProfit += profit; // 先累计代币利润
671
682
  }
672
683
  }
@@ -1013,7 +1024,7 @@ export async function sweepWithBundleMerkle(params) {
1013
1024
  let totalTokenProfit = 0n;
1014
1025
  for (let i = 0; i < sweepAmounts.length; i++) {
1015
1026
  if (sweepAmounts[i] > 0n) {
1016
- const { profit } = calculateProfit(sweepAmounts[i], config);
1027
+ const { profit } = calculateProfit(sweepAmounts[i]);
1017
1028
  if (isNative) {
1018
1029
  totalProfit += profit; // 原生币直接累加
1019
1030
  }
@@ -393,26 +393,8 @@ function calculateProfitAmount(expectedFunds) {
393
393
  if (expectedFunds <= 0n) {
394
394
  return 0n;
395
395
  }
396
- return (expectedFunds * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
397
- }
398
- async function validateNativeBalances({ sameAddress, buyerBalance, buyerFundsWei, gasLimit, gasPrice, buyer, seller, provider, nativeToken }) {
399
- const effectiveGasPrice = gasPrice;
400
- const gasCost = gasLimit * effectiveGasPrice;
401
- if (sameAddress) {
402
- const combinedRequired = buyerFundsWei + gasCost * 2n;
403
- if (buyerBalance < combinedRequired) {
404
- throw new Error(`账户余额不足: 需要 ${ethers.formatEther(combinedRequired)} ${nativeToken}(${ethers.formatEther(buyerFundsWei)} 购买 + ${ethers.formatEther(gasCost * 2n)} 两笔Gas),实际 ${ethers.formatEther(buyerBalance)} ${nativeToken}`);
405
- }
406
- return;
407
- }
408
- const buyerRequiredBalance = buyerFundsWei + gasCost;
409
- if (buyerBalance < buyerRequiredBalance) {
410
- throw new Error(`买方余额不足: 需要 ${ethers.formatEther(buyerRequiredBalance)} ${nativeToken}(${ethers.formatEther(buyerFundsWei)} 购买 + ${ethers.formatEther(gasCost)} Gas),实际 ${ethers.formatEther(buyerBalance)} ${nativeToken}`);
411
- }
412
- const sellerBalance = await provider.getBalance(seller.address);
413
- if (sellerBalance < gasCost) {
414
- throw new Error(`卖方余额不足: 需要 ${ethers.formatEther(gasCost)} ${nativeToken} (Gas),实际 ${ethers.formatEther(sellerBalance)} ${nativeToken}`);
415
- }
396
+ // 万分之三
397
+ return (expectedFunds * BigInt(PROFIT_CONFIG.RATE_BPS_CAPITAL)) / 10000n;
416
398
  }
417
399
  /**
418
400
  * ✅ 优化:使用批量 nonce 获取
@@ -458,7 +458,7 @@ function calculateProfitAmount(quotedNative) {
458
458
  if (quotedNative <= 0n) {
459
459
  return 0n;
460
460
  }
461
- return (quotedNative * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
461
+ return (quotedNative * BigInt(PROFIT_CONFIG.RATE_BPS_CAPITAL)) / 10000n;
462
462
  }
463
463
  function countTruthy(values) {
464
464
  return values.filter(Boolean).length;
@@ -736,7 +736,7 @@ export async function flapQuickBatchSwapMerkle(params) {
736
736
  console.log(`[flapQuickBatchSwapMerkle] 模式: ${useNativeToken ? '原生代币' : 'ERC20'}`);
737
737
  console.log(`[flapQuickBatchSwapMerkle] 卖出数量: ${ethers.formatUnits(sellAmountWei, decimals)}`);
738
738
  console.log(`[flapQuickBatchSwapMerkle] 预估卖出所得: ${outputFormatted}`);
739
- // ✅ 计算利润(基于原生代币价值)
739
+ // ✅ 计算利润(万分之三)
740
740
  let tokenProfitAmount = calculateProfitAmount(estimatedOutput);
741
741
  let nativeProfitAmount = tokenProfitAmount;
742
742
  if (!useNativeToken && tokenProfitAmount > 0n) {
@@ -827,48 +827,49 @@ export async function flapQuickBatchSwapMerkle(params) {
827
827
  });
828
828
  const signedSell = await seller.signTransaction(sellTx);
829
829
  console.log(`[flapQuickBatchSwapMerkle] 卖出交易已签名`);
830
- // ==================== 3. 转账交易 ====================
831
- const transferTxs = [];
830
+ // ==================== 3. 转账交易(并行签名)====================
832
831
  const reserveGas = ethers.parseEther((config.reserveGasETH || 0.0005).toString());
832
+ const buyerGasCost = gasPrice * finalGasLimit;
833
+ // ✅ 预分配 nonce,然后并行签名
834
+ const transferNonces = buyers.map((_, i) => sellerNonce + i);
835
+ sellerNonce += buyers.length; // 更新 sellerNonce
836
+ let transferTxs;
833
837
  if (useNativeToken) {
834
- // 原生代币模式:直接转账
835
- for (let i = 0; i < buyers.length; i++) {
836
- const buyerGasCost = gasPrice * finalGasLimit;
838
+ // 原生代币模式:直接转账(并行签名)
839
+ transferTxs = await Promise.all(buyers.map((buyer, i) => {
837
840
  const transferValue = transferAmountsWei[i] + reserveGas + buyerGasCost;
838
- const transferTx = await seller.signTransaction({
839
- to: buyers[i].address,
841
+ return seller.signTransaction({
842
+ to: buyer.address,
840
843
  value: transferValue,
841
- nonce: sellerNonce++,
844
+ nonce: transferNonces[i],
842
845
  gasPrice,
843
846
  gasLimit: 21000n,
844
847
  chainId: chainContext.chainId,
845
848
  type: txType
846
849
  });
847
- transferTxs.push(transferTx);
848
- }
850
+ }));
849
851
  }
850
852
  else {
851
- // ERC20 模式:ERC20 transfer(子钱包已预留原生代币)
853
+ // ERC20 模式:ERC20 transfer(并行签名)
852
854
  const erc20Interface = new ethers.Interface([
853
855
  'function transfer(address to, uint256 amount) returns (bool)'
854
856
  ]);
855
- for (let i = 0; i < buyers.length; i++) {
857
+ transferTxs = await Promise.all(buyers.map((buyer, i) => {
856
858
  const transferData = erc20Interface.encodeFunctionData('transfer', [
857
- buyers[i].address,
859
+ buyer.address,
858
860
  transferAmountsWei[i]
859
861
  ]);
860
- const transferTx = await seller.signTransaction({
862
+ return seller.signTransaction({
861
863
  to: quoteToken,
862
864
  data: transferData,
863
865
  value: 0n,
864
- nonce: sellerNonce++,
866
+ nonce: transferNonces[i],
865
867
  gasPrice,
866
868
  gasLimit: ERC20_TRANSFER_GAS,
867
869
  chainId: chainContext.chainId,
868
870
  type: txType
869
871
  });
870
- transferTxs.push(transferTx);
871
- }
872
+ }));
872
873
  }
873
874
  console.log(`[flapQuickBatchSwapMerkle] ${transferTxs.length} 笔转账交易已签名`);
874
875
  // ==================== 4. 买入交易 ====================
package/dist/index.d.ts CHANGED
@@ -34,6 +34,7 @@ export { generateWallets, type GeneratedWallet } from './utils/wallet.js';
34
34
  export { getTokenBalancesWithMulticall, type MulticallResult, type MultiTokenBalancesResult } from './utils/wallet.js';
35
35
  export { validatePrivateKeys, type PrivateKeyValidation } from './utils/wallet.js';
36
36
  export { stealthTransfer, type StealthTransferResult, type StealthTransferSimpleParams } from './utils/stealth-transfer.js';
37
+ export { privateSaleMerkle, batchPrivateSaleMerkle, type PrivateSaleSignConfig, type PrivateSaleTransferParams, type BatchPrivateSaleParams, type PrivateSaleResult, } from './utils/private-sale.js';
37
38
  export { inspectTokenLP, getFactoryFromRouter, registerDYORSwap, registerDex, getChainConfig, type LPInfo, type LPPlatform, type InspectOptions, type DexConfig, type ChainDexConfig, } from './utils/lp-inspect.js';
38
39
  export { disperseWithBundle, sweepWithBundle, type DisperseSignParams, type SweepSignParams, type SignedTransactionsResult, type DisperseParams, type SweepParams, type BundleSubmitResult } from './utils/airdrop-sweep.js';
39
40
  export { fourBundleSwapMerkle, fourBatchSwapMerkle, fourQuickBatchSwapMerkle, type FourSwapSignConfig, type FourSwapConfig, type FourBundleSwapSignParams, type FourBundleSwapParams, type FourSwapResult, type FourBatchSwapSignParams, type FourBatchSwapResult, type FourQuickBatchSwapSignParams, type FourQuickBatchSwapResult } from './contracts/tm-bundle-merkle/swap.js';
package/dist/index.js CHANGED
@@ -46,6 +46,8 @@ export { generateWallets } from './utils/wallet.js';
46
46
  export { getTokenBalancesWithMulticall } from './utils/wallet.js';
47
47
  export { validatePrivateKeys } from './utils/wallet.js';
48
48
  export { stealthTransfer } from './utils/stealth-transfer.js';
49
+ // ✅ 私募转账签名(带贿赂和利润提取)
50
+ export { privateSaleMerkle, batchPrivateSaleMerkle, } from './utils/private-sale.js';
49
51
  export { inspectTokenLP, getFactoryFromRouter, registerDYORSwap, registerDex, getChainConfig, } from './utils/lp-inspect.js';
50
52
  export { disperseWithBundle, sweepWithBundle } from './utils/airdrop-sweep.js';
51
53
  // ============================================================
@@ -6,6 +6,7 @@
6
6
  import { ethers, Contract, Wallet } from 'ethers';
7
7
  import { NonceManager } from '../utils/bundle-helpers.js';
8
8
  import { ADDRESSES, PROFIT_CONFIG } from '../utils/constants.js';
9
+ import { quoteV2, quoteV3, getTokenToNativeQuote, getWrappedNativeAddress } from '../utils/quote-helpers.js';
9
10
  // ✅ BlockRazor Builder EOA 地址(用于贿赂)
10
11
  // 参考文档: https://blockrazor.gitbook.io/blockrazor/bsc/block-builder/send-bundle
11
12
  const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
@@ -38,18 +39,7 @@ const PANCAKE_PROXY_ABI = [
38
39
  'function swapV3Single(address tokenIn, address tokenOut, uint24 fee, uint256 amountIn, uint256 amountOutMin, address to) payable returns (uint256)',
39
40
  'function swapV3MultiHop(address[] calldata lpAddresses, address exactTokenIn, uint256 amountIn, uint256 amountOutMin, address to) payable returns (uint256)'
40
41
  ];
41
- // Pancake V2 Router ABI(用于报价)
42
- const PANCAKE_V2_ROUTER_ABI = [
43
- 'function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts)'
44
- ];
45
- // Pancake V3 QuoterV2 ABI(用于报价)
46
- const PANCAKE_V3_QUOTER_ABI = [
47
- 'function quoteExactInputSingle((address tokenIn, address tokenOut, uint256 amountIn, uint24 fee, uint160 sqrtPriceLimitX96)) external returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)',
48
- 'function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut, uint160[] memory sqrtPriceX96AfterList, uint32[] memory initializedTicksCrossedList, uint256 gasEstimate)'
49
- ];
50
42
  const PANCAKE_PROXY_ADDRESS = ADDRESSES.BSC.PancakeProxy;
51
- const PANCAKE_V2_ROUTER_ADDRESS = '0x10ED43C718714eb63d5aA57B78B54704E256024E';
52
- const PANCAKE_V3_QUOTER_ADDRESS = '0xB048Bbc1Ee6b733FFfCFb9e9CeF7375518e25997';
53
43
  const FLAT_FEE = 0n; // ✅ 已移除合约固定手续费
54
44
  const WBNB_ADDRESS = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c';
55
45
  const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
@@ -96,7 +86,8 @@ export async function pancakeBundleBuyFirstMerkle(params) {
96
86
  const quotedNative = await quoteSellerNative({
97
87
  provider: context.provider,
98
88
  tokenAddress,
99
- sellAmountToken: quoteResult.quotedTokenOut
89
+ sellAmountToken: quoteResult.quotedTokenOut,
90
+ routeParams // ✅ 传递路由参数
100
91
  });
101
92
  const buyerNeed = calculateBuyerNeed({
102
93
  quotedNative,
@@ -123,9 +114,11 @@ export async function pancakeBundleBuyFirstMerkle(params) {
123
114
  const estimatedProfitFromSell = await estimateProfitAmount({
124
115
  provider: context.provider,
125
116
  tokenAddress,
126
- sellAmountToken: quoteResult.quotedTokenOut
117
+ sellAmountToken: quoteResult.quotedTokenOut,
118
+ routeParams // ✅ 传递路由参数
127
119
  });
128
- const profitBase = estimatedProfitFromSell > 0n ? estimatedProfitFromSell : (buyerFundsInfo.buyerFundsWei * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
120
+ // 万分之三
121
+ const profitBase = estimatedProfitFromSell > 0n ? estimatedProfitFromSell : (buyerFundsInfo.buyerFundsWei * BigInt(PROFIT_CONFIG.RATE_BPS_CAPITAL)) / 10000n;
129
122
  const profitAmount = profitBase;
130
123
  // ✅ 获取贿赂金额
131
124
  const bribeAmount = config.bribeAmount && config.bribeAmount > 0
@@ -277,56 +270,55 @@ async function calculateBuyerFunds({ buyer, buyerFunds, buyerFundsPercentage, re
277
270
  }
278
271
  return { buyerFundsWei, buyerBalance, reserveGas: reserveGasWei };
279
272
  }
273
+ /**
274
+ * ✅ 使用 quote-helpers 统一报价
275
+ */
280
276
  async function quoteTokenOutput({ routeParams, buyerFundsWei, provider }) {
277
+ // V2 路由
281
278
  if (routeParams.routeType === 'v2') {
282
279
  const { v2Path } = routeParams;
283
- const v2Router = new Contract(PANCAKE_V2_ROUTER_ADDRESS, PANCAKE_V2_ROUTER_ABI, provider);
284
- const amounts = await v2Router.getAmountsOut(buyerFundsWei, v2Path);
285
- return { quotedTokenOut: amounts[amounts.length - 1] };
280
+ const tokenIn = v2Path[0];
281
+ const tokenOut = v2Path[v2Path.length - 1];
282
+ const result = await quoteV2(provider, tokenIn, tokenOut, buyerFundsWei, 'BSC');
283
+ if (result.amountOut <= 0n) {
284
+ throw new Error('V2 报价失败');
285
+ }
286
+ return { quotedTokenOut: result.amountOut };
286
287
  }
288
+ // V3 Single 路由
287
289
  if (routeParams.routeType === 'v3-single') {
288
290
  const paramsV3 = routeParams;
289
- const quoter = new Contract(PANCAKE_V3_QUOTER_ADDRESS, PANCAKE_V3_QUOTER_ABI, provider);
290
- try {
291
- const result = await quoter.quoteExactInputSingle.staticCall({
292
- tokenIn: paramsV3.v3TokenIn,
293
- tokenOut: paramsV3.v3TokenOut,
294
- amountIn: buyerFundsWei,
295
- fee: paramsV3.v3Fee,
296
- sqrtPriceLimitX96: 0
297
- });
298
- return { quotedTokenOut: result[0] };
299
- }
300
- catch {
301
- if (paramsV3.v2Path && paramsV3.v2Path.length >= 2) {
302
- const v2Router = new Contract(PANCAKE_V2_ROUTER_ADDRESS, PANCAKE_V2_ROUTER_ABI, provider);
303
- const amounts = await v2Router.getAmountsOut(buyerFundsWei, paramsV3.v2Path);
304
- return { quotedTokenOut: amounts[amounts.length - 1] };
305
- }
306
- throw new Error('V3 报价失败且未提供 v2Path 备用');
291
+ const result = await quoteV3(provider, paramsV3.v3TokenIn, paramsV3.v3TokenOut, buyerFundsWei, 'BSC', paramsV3.v3Fee);
292
+ if (result.amountOut <= 0n) {
293
+ throw new Error('V3 报价失败');
307
294
  }
295
+ return { quotedTokenOut: result.amountOut };
308
296
  }
297
+ // V3 Multi 路由
309
298
  const paramsV3m = routeParams;
310
- if (paramsV3m.v2Path && paramsV3m.v2Path.length >= 2) {
311
- const v2Router = new Contract(PANCAKE_V2_ROUTER_ADDRESS, PANCAKE_V2_ROUTER_ABI, provider);
312
- const amounts = await v2Router.getAmountsOut(buyerFundsWei, paramsV3m.v2Path);
313
- return { quotedTokenOut: amounts[amounts.length - 1] };
299
+ if (!paramsV3m.v2Path || paramsV3m.v2Path.length < 2) {
300
+ throw new Error('V3 多跳需要提供 v2Path 用于路径推断');
301
+ }
302
+ const tokenIn = paramsV3m.v2Path[0];
303
+ const tokenOut = paramsV3m.v2Path[paramsV3m.v2Path.length - 1];
304
+ const result = await quoteV3(provider, tokenIn, tokenOut, buyerFundsWei, 'BSC');
305
+ if (result.amountOut <= 0n) {
306
+ throw new Error('V3 多跳报价失败');
314
307
  }
315
- throw new Error('V3 多跳需要提供 v2Path 用于价格预估');
308
+ return { quotedTokenOut: result.amountOut };
316
309
  }
317
310
  async function getTokenDecimals(provider, tokenAddress) {
318
311
  const erc20 = new Contract(tokenAddress, ['function decimals() view returns (uint8)'], provider);
319
312
  return await erc20.decimals();
320
313
  }
321
- async function quoteSellerNative({ provider, tokenAddress, sellAmountToken }) {
322
- try {
323
- const v2Router = new Contract(PANCAKE_V2_ROUTER_ADDRESS, PANCAKE_V2_ROUTER_ABI, provider);
324
- const amounts = await v2Router.getAmountsOut(sellAmountToken, [tokenAddress, WBNB_ADDRESS]);
325
- return amounts[amounts.length - 1];
326
- }
327
- catch {
328
- return 0n;
329
- }
314
+ /**
315
+ * ✅ 使用 quote-helpers 统一报价(卖出 → 原生代币)
316
+ */
317
+ async function quoteSellerNative({ provider, tokenAddress, sellAmountToken, routeParams }) {
318
+ const wbnb = getWrappedNativeAddress('BSC');
319
+ const version = routeParams.routeType === 'v2' ? 'v2' : 'v3';
320
+ const fee = routeParams.routeType === 'v3-single' ? routeParams.v3Fee : undefined;
321
+ return await getTokenToNativeQuote(provider, tokenAddress, sellAmountToken, 'BSC', version, fee);
330
322
  }
331
323
  function calculateBuyerNeed({ quotedNative, buyerBalance, reserveGas }) {
332
324
  // ✅ 已移除滑点保护:直接使用报价金额
@@ -391,12 +383,19 @@ async function buildRouteTransactions({ routeParams, buyerFundsWei, sellAmountTo
391
383
  const sellUnsigned = await proxySeller.swapV3MultiHop.populateTransaction(v3LpAddresses, exactTokenOut, sellAmountToken, 0n, seller.address, { value: FLAT_FEE });
392
384
  return { buyUnsigned, sellUnsigned };
393
385
  }
394
- async function estimateProfitAmount({ provider, tokenAddress, sellAmountToken }) {
386
+ /**
387
+ * ✅ 使用 quote-helpers 统一报价(估算利润)
388
+ */
389
+ async function estimateProfitAmount({ provider, tokenAddress, sellAmountToken, routeParams }) {
395
390
  try {
396
- const v2Router = new Contract(PANCAKE_V2_ROUTER_ADDRESS, PANCAKE_V2_ROUTER_ABI, provider);
397
- const amounts = await v2Router.getAmountsOut(sellAmountToken, [tokenAddress, WBNB_ADDRESS]);
398
- const estimatedSellFunds = amounts[amounts.length - 1];
399
- return (estimatedSellFunds * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
391
+ const version = routeParams.routeType === 'v2' ? 'v2' : 'v3';
392
+ const fee = routeParams.routeType === 'v3-single' ? routeParams.v3Fee : undefined;
393
+ const estimatedSellFunds = await getTokenToNativeQuote(provider, tokenAddress, sellAmountToken, 'BSC', version, fee);
394
+ if (estimatedSellFunds <= 0n) {
395
+ return 0n;
396
+ }
397
+ // 万分之三
398
+ return (estimatedSellFunds * BigInt(PROFIT_CONFIG.RATE_BPS_CAPITAL)) / 10000n;
400
399
  }
401
400
  catch {
402
401
  return 0n;
@@ -161,7 +161,7 @@ function calculateProfitAmount(estimatedBNBOut) {
161
161
  if (estimatedBNBOut <= 0n) {
162
162
  return 0n;
163
163
  }
164
- return (estimatedBNBOut * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
164
+ return (estimatedBNBOut * BigInt(PROFIT_CONFIG.RATE_BPS_CAPITAL)) / 10000n;
165
165
  }
166
166
  /**
167
167
  * ✅ 获取 ERC20 代币 → 原生代币(BNB)的报价
@@ -779,7 +779,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
779
779
  ? ethers.formatEther(estimatedOutput)
780
780
  : ethers.formatUnits(estimatedOutput, quoteTokenDecimals);
781
781
  console.log(`[pancakeQuickBatchSwapMerkle] 预估卖出所得: ${outputFormatted} ${useNativeToken ? 'BNB' : 'ERC20'}`);
782
- // ✅ 计算利润(基于 BNB 价值)
782
+ // ✅ 计算利润(万分之三)
783
783
  let profitAmount;
784
784
  if (useNativeToken) {
785
785
  profitAmount = calculateProfitAmount(estimatedOutput);
@@ -881,47 +881,48 @@ export async function pancakeQuickBatchSwapMerkle(params) {
881
881
  type: txType
882
882
  });
883
883
  console.log(`[pancakeQuickBatchSwapMerkle] 卖出交易已签名`);
884
- // ==================== 3. 转账交易 ====================
885
- const transferTxs = [];
884
+ // ==================== 3. 转账交易(并行签名)====================
885
+ const buyerGasCost = gasPrice * finalGasLimit;
886
+ // ✅ 预分配 nonce,然后并行签名
887
+ const transferNonces = buyers.map((_, i) => sellerNonce + i);
888
+ sellerNonce += buyers.length; // 更新 sellerNonce
889
+ let transferTxs;
886
890
  if (useNativeToken) {
887
- // ✅ 原生代币模式:直接 BNB 转账
888
- for (let i = 0; i < buyers.length; i++) {
889
- const buyerGasCost = gasPrice * finalGasLimit;
891
+ // ✅ 原生代币模式:直接 BNB 转账(并行签名)
892
+ transferTxs = await Promise.all(buyers.map((buyer, i) => {
890
893
  const transferValue = transferAmountsWei[i] + FLAT_FEE + buyerGasCost;
891
- const transferTx = await seller.signTransaction({
892
- to: buyers[i].address,
894
+ return seller.signTransaction({
895
+ to: buyer.address,
893
896
  value: transferValue,
894
- nonce: sellerNonce++,
897
+ nonce: transferNonces[i],
895
898
  gasPrice,
896
899
  gasLimit: 21000n,
897
900
  chainId: context.chainId,
898
901
  type: txType
899
902
  });
900
- transferTxs.push(transferTx);
901
- }
903
+ }));
902
904
  }
903
905
  else {
904
- // ✅ ERC20 模式:ERC20 transfer 调用(子钱包已预留 BNB,不需要转 Gas)
906
+ // ✅ ERC20 模式:ERC20 transfer(并行签名)
905
907
  const erc20Interface = new ethers.Interface([
906
908
  'function transfer(address to, uint256 amount) returns (bool)'
907
909
  ]);
908
- for (let i = 0; i < buyers.length; i++) {
910
+ transferTxs = await Promise.all(buyers.map((buyer, i) => {
909
911
  const transferData = erc20Interface.encodeFunctionData('transfer', [
910
- buyers[i].address,
912
+ buyer.address,
911
913
  transferAmountsWei[i]
912
914
  ]);
913
- const transferTx = await seller.signTransaction({
915
+ return seller.signTransaction({
914
916
  to: quoteToken,
915
917
  data: transferData,
916
918
  value: 0n,
917
- nonce: sellerNonce++,
919
+ nonce: transferNonces[i],
918
920
  gasPrice,
919
921
  gasLimit: ERC20_TRANSFER_GAS,
920
922
  chainId: context.chainId,
921
923
  type: txType
922
924
  });
923
- transferTxs.push(transferTx);
924
- }
925
+ }));
925
926
  }
926
927
  console.log(`[pancakeQuickBatchSwapMerkle] ${transferTxs.length} 笔转账交易已签名`);
927
928
  // ==================== 4. 买入交易 ====================
@@ -1,8 +1,10 @@
1
1
  export declare const PROFIT_CONFIG: {
2
2
  /** 利润接收地址 */
3
3
  readonly RECIPIENT: "0xe8D0334fAf713884133640CAEe4ECdd2106AF103";
4
- /** 利润比例(基点):30 bps = 0.3% = 千分之三 */
4
+ /** 利润比例(基点):30 bps = 0.3% = 千分之三(普通模式) */
5
5
  readonly RATE_BPS: 30;
6
+ /** 利润比例(基点):3 bps = 0.03% = 万分之三(资金利用率模式) */
7
+ readonly RATE_BPS_CAPITAL: 3;
6
8
  };
7
9
  export declare const CHAIN: {
8
10
  BSC: {
@@ -2,8 +2,10 @@
2
2
  export const PROFIT_CONFIG = {
3
3
  /** 利润接收地址 */
4
4
  RECIPIENT: '0xe8D0334fAf713884133640CAEe4ECdd2106AF103',
5
- /** 利润比例(基点):30 bps = 0.3% = 千分之三 */
5
+ /** 利润比例(基点):30 bps = 0.3% = 千分之三(普通模式) */
6
6
  RATE_BPS: 30,
7
+ /** 利润比例(基点):3 bps = 0.03% = 万分之三(资金利用率模式) */
8
+ RATE_BPS_CAPITAL: 3,
7
9
  };
8
10
  export const CHAIN = {
9
11
  BSC: {
@@ -0,0 +1,87 @@
1
+ /**
2
+ * 私募转账签名工具
3
+ *
4
+ * ✅ 优化:能批量的批量,能并行的并行
5
+ * - 贿赂交易:向 BlockRazor Builder EOA 转账 BNB 提高优先级
6
+ * - 利润提取:千分之三(30 bps)
7
+ */
8
+ /** 私募签名配置 */
9
+ export interface PrivateSaleSignConfig {
10
+ /** RPC URL */
11
+ rpcUrl: string;
12
+ /** 链 ID */
13
+ chainId?: number;
14
+ /** Gas Limit(默认 21000) */
15
+ gasLimit?: number;
16
+ /** Gas Price(Gwei,默认 0.1) */
17
+ gasPriceGwei?: number;
18
+ /** 贿赂金额(BNB,默认 0.000001) */
19
+ bribeAmount?: number;
20
+ /** 是否提取利润(默认 true) */
21
+ extractProfit?: boolean;
22
+ /** 利润比例基点(默认 30 = 千分之三) */
23
+ profitBps?: number;
24
+ }
25
+ /** 单个转账参数 */
26
+ export interface PrivateSaleTransferParams {
27
+ /** 发送者私钥 */
28
+ senderPrivateKey: string;
29
+ /** 接收者地址(合约地址) */
30
+ recipient: string;
31
+ /** 转账金额(单位:原生代币,如 BNB) */
32
+ amount: number;
33
+ }
34
+ /** 批量转账参数 */
35
+ export interface BatchPrivateSaleParams {
36
+ /** 转账列表 */
37
+ transfers: PrivateSaleTransferParams[];
38
+ /** 签名配置 */
39
+ config: PrivateSaleSignConfig;
40
+ }
41
+ /** 私募结果 */
42
+ export interface PrivateSaleResult {
43
+ /** 签名交易数组(包含贿赂 + 转账 + 利润) */
44
+ signedTransactions: string[];
45
+ /** 元数据 */
46
+ metadata: {
47
+ /** 总交易数 */
48
+ totalCount: number;
49
+ /** 贿赂交易数 */
50
+ bribeCount: number;
51
+ /** 转账交易数 */
52
+ transferCount: number;
53
+ /** 利润交易数 */
54
+ profitCount: number;
55
+ /** 总转账金额(Wei) */
56
+ totalAmountWei: string;
57
+ /** 总利润金额(Wei) */
58
+ totalProfitWei: string;
59
+ /** 贿赂金额(Wei) */
60
+ bribeAmountWei: string;
61
+ };
62
+ }
63
+ /**
64
+ * 生成私募转账签名交易(带贿赂和利润提取)
65
+ *
66
+ * ✅ 优化:
67
+ * 1. 批量获取 nonce(单次 RPC 请求)
68
+ * 2. 并行签名所有交易(贿赂 + 转账 + 利润)
69
+ * 3. 批量创建钱包实例
70
+ *
71
+ * 交易顺序:
72
+ * 1. 贿赂交易(第一个发送者 → BlockRazor)
73
+ * 2. 转账交易(各发送者 → 合约)
74
+ * 3. 利润交易(第一个发送者 → 利润地址)
75
+ *
76
+ * @param params 批量转账参数
77
+ * @returns 签名交易结果
78
+ */
79
+ export declare function batchPrivateSaleMerkle(params: BatchPrivateSaleParams): Promise<PrivateSaleResult>;
80
+ /**
81
+ * 生成单笔私募转账签名交易(带贿赂和利润提取)
82
+ *
83
+ * @param transfer 转账参数
84
+ * @param config 签名配置
85
+ * @returns 签名交易结果
86
+ */
87
+ export declare function privateSaleMerkle(transfer: PrivateSaleTransferParams, config: PrivateSaleSignConfig): Promise<PrivateSaleResult>;
@@ -0,0 +1,166 @@
1
+ /**
2
+ * 私募转账签名工具
3
+ *
4
+ * ✅ 优化:能批量的批量,能并行的并行
5
+ * - 贿赂交易:向 BlockRazor Builder EOA 转账 BNB 提高优先级
6
+ * - 利润提取:千分之三(30 bps)
7
+ */
8
+ import { ethers, Wallet, JsonRpcProvider } from 'ethers';
9
+ import { PROFIT_CONFIG } from './constants.js';
10
+ import { BLOCKRAZOR_BUILDER_EOA } from '../clients/blockrazor.js';
11
+ import { NonceManager } from './bundle-helpers.js';
12
+ // ============================================================================
13
+ // 核心功能
14
+ // ============================================================================
15
+ /**
16
+ * 生成私募转账签名交易(带贿赂和利润提取)
17
+ *
18
+ * ✅ 优化:
19
+ * 1. 批量获取 nonce(单次 RPC 请求)
20
+ * 2. 并行签名所有交易(贿赂 + 转账 + 利润)
21
+ * 3. 批量创建钱包实例
22
+ *
23
+ * 交易顺序:
24
+ * 1. 贿赂交易(第一个发送者 → BlockRazor)
25
+ * 2. 转账交易(各发送者 → 合约)
26
+ * 3. 利润交易(第一个发送者 → 利润地址)
27
+ *
28
+ * @param params 批量转账参数
29
+ * @returns 签名交易结果
30
+ */
31
+ export async function batchPrivateSaleMerkle(params) {
32
+ const { transfers, config } = params;
33
+ if (transfers.length === 0) {
34
+ throw new Error('转账列表不能为空');
35
+ }
36
+ // ✅ 配置参数(提前计算,避免重复)
37
+ const chainId = config.chainId || 56;
38
+ const gasLimit = BigInt(config.gasLimit || 21000);
39
+ const gasPrice = ethers.parseUnits(String(config.gasPriceGwei || 0.1), 'gwei');
40
+ const bribeAmount = ethers.parseEther(String(config.bribeAmount || 0.000001));
41
+ const extractProfit = config.extractProfit !== false;
42
+ const profitBps = config.profitBps ?? PROFIT_CONFIG.RATE_BPS;
43
+ // 创建 Provider
44
+ const provider = new JsonRpcProvider(config.rpcUrl);
45
+ const nonceManager = new NonceManager(provider);
46
+ // ✅ 批量创建钱包实例(使用 Map 去重)
47
+ const walletMap = new Map();
48
+ const transferWallets = [];
49
+ for (const transfer of transfers) {
50
+ const key = new Wallet(transfer.senderPrivateKey).address.toLowerCase();
51
+ if (!walletMap.has(key)) {
52
+ const wallet = new Wallet(transfer.senderPrivateKey, provider);
53
+ walletMap.set(key, wallet);
54
+ }
55
+ transferWallets.push(walletMap.get(key));
56
+ }
57
+ // 第一个发送者(负责贿赂和利润交易)
58
+ const firstWallet = transferWallets[0];
59
+ const firstWalletKey = firstWallet.address.toLowerCase();
60
+ // ✅ 批量计算总金额(使用 reduce)
61
+ const totalAmountWei = transfers.reduce((sum, t) => sum + ethers.parseEther(String(t.amount)), 0n);
62
+ const profitWei = extractProfit ? (totalAmountWei * BigInt(profitBps)) / 10000n : 0n;
63
+ const hasProfit = extractProfit && profitWei > 0n;
64
+ // ✅ 批量获取所有 nonce(单次 RPC 请求)
65
+ const uniqueWallets = Array.from(walletMap.values());
66
+ const noncesArray = await nonceManager.getNextNoncesForWallets(uniqueWallets);
67
+ // 构建 nonce 映射
68
+ const nonceMap = new Map();
69
+ uniqueWallets.forEach((wallet, i) => {
70
+ nonceMap.set(wallet.address.toLowerCase(), noncesArray[i]);
71
+ });
72
+ // ✅ 预计算每个钱包的 nonce 分配
73
+ // 第一个钱包:baseNonce(贿赂) → baseNonce+1...+N(转账) → 最后(利润)
74
+ const firstWalletBaseNonce = nonceMap.get(firstWalletKey);
75
+ // 统计第一个钱包的转账数量
76
+ let firstWalletTransferCount = 0;
77
+ for (let i = 0; i < transfers.length; i++) {
78
+ if (transferWallets[i].address.toLowerCase() === firstWalletKey) {
79
+ firstWalletTransferCount++;
80
+ }
81
+ }
82
+ // ✅ 为每个转账预分配 nonce
83
+ const transferNonces = [];
84
+ const currentNonces = new Map();
85
+ // 初始化 nonce(第一个钱包跳过贿赂交易的 nonce)
86
+ for (const [key, nonce] of nonceMap) {
87
+ currentNonces.set(key, key === firstWalletKey ? nonce + 1 : nonce);
88
+ }
89
+ // 为每个转账分配 nonce
90
+ for (let i = 0; i < transfers.length; i++) {
91
+ const walletKey = transferWallets[i].address.toLowerCase();
92
+ const nonce = currentNonces.get(walletKey);
93
+ transferNonces.push(nonce);
94
+ currentNonces.set(walletKey, nonce + 1);
95
+ }
96
+ // 利润交易的 nonce
97
+ const profitNonce = hasProfit ? currentNonces.get(firstWalletKey) : 0;
98
+ // ✅ 并行签名所有交易
99
+ const allSignPromises = [];
100
+ // 1. 贿赂交易签名
101
+ allSignPromises.push(firstWallet.signTransaction({
102
+ to: BLOCKRAZOR_BUILDER_EOA,
103
+ value: bribeAmount,
104
+ gasLimit,
105
+ gasPrice,
106
+ nonce: firstWalletBaseNonce,
107
+ chainId,
108
+ type: 0,
109
+ }));
110
+ // 2. 转账交易签名(并行)
111
+ for (let i = 0; i < transfers.length; i++) {
112
+ const transfer = transfers[i];
113
+ const wallet = transferWallets[i];
114
+ const nonce = transferNonces[i];
115
+ allSignPromises.push(wallet.signTransaction({
116
+ to: transfer.recipient,
117
+ value: ethers.parseEther(String(transfer.amount)),
118
+ gasLimit,
119
+ gasPrice,
120
+ nonce,
121
+ chainId,
122
+ type: 0,
123
+ }));
124
+ }
125
+ // 3. 利润交易签名
126
+ if (hasProfit) {
127
+ allSignPromises.push(firstWallet.signTransaction({
128
+ to: PROFIT_CONFIG.RECIPIENT,
129
+ value: profitWei,
130
+ gasLimit,
131
+ gasPrice,
132
+ nonce: profitNonce,
133
+ chainId,
134
+ type: 0,
135
+ }));
136
+ }
137
+ // ✅ 并行执行所有签名
138
+ const allSignedTxs = await Promise.all(allSignPromises);
139
+ // 按顺序组装结果:贿赂(1) + 转账(N) + 利润(0或1)
140
+ const signedTransactions = allSignedTxs;
141
+ return {
142
+ signedTransactions,
143
+ metadata: {
144
+ totalCount: signedTransactions.length,
145
+ bribeCount: 1,
146
+ transferCount: transfers.length,
147
+ profitCount: hasProfit ? 1 : 0,
148
+ totalAmountWei: totalAmountWei.toString(),
149
+ totalProfitWei: profitWei.toString(),
150
+ bribeAmountWei: bribeAmount.toString(),
151
+ },
152
+ };
153
+ }
154
+ /**
155
+ * 生成单笔私募转账签名交易(带贿赂和利润提取)
156
+ *
157
+ * @param transfer 转账参数
158
+ * @param config 签名配置
159
+ * @returns 签名交易结果
160
+ */
161
+ export async function privateSaleMerkle(transfer, config) {
162
+ return batchPrivateSaleMerkle({
163
+ transfers: [transfer],
164
+ config,
165
+ });
166
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.4.16",
3
+ "version": "1.4.18",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",