four-flap-meme-sdk 1.4.56 → 1.4.57

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.
@@ -4,6 +4,7 @@
4
4
  * 功能:钱包A卖出代币 → 钱包B买入相同数量 → 原子执行
5
5
  */
6
6
  import { CommonBundleConfig } from '../../utils/bundle-helpers.js';
7
+ import { type GeneratedWallet } from '../../utils/wallet.js';
7
8
  export interface FourSwapSignConfig {
8
9
  rpcUrl: string;
9
10
  gasLimit?: number | bigint;
@@ -105,6 +106,7 @@ export interface FourQuickBatchSwapSignParams {
105
106
  buyerAmounts?: string[];
106
107
  tokenAddress: string;
107
108
  config: FourSwapSignConfig;
109
+ disperseHopCount?: number;
108
110
  startNonces?: number[];
109
111
  }
110
112
  /**
@@ -112,6 +114,7 @@ export interface FourQuickBatchSwapSignParams {
112
114
  */
113
115
  export interface FourQuickBatchSwapResult {
114
116
  signedTransactions: string[];
117
+ disperseHopWallets?: GeneratedWallet[];
115
118
  metadata?: {
116
119
  sellerAddress: string;
117
120
  buyerAddresses: string[];
@@ -119,18 +122,20 @@ export interface FourQuickBatchSwapResult {
119
122
  estimatedBNBOut: string;
120
123
  transferAmounts: string[];
121
124
  profitAmount?: string;
125
+ disperseHopCount?: number;
122
126
  };
123
127
  }
124
128
  /**
125
129
  * Four 内盘快捷批量换手(资金利用率模式)
126
130
  *
127
- * 流程:[贿赂] → [卖出] → [转账1, 转账2, ...] → [买入1, 买入2, ...] → [利润]
131
+ * 流程:[贿赂] → [卖出] → [转账多跳...] → [买入1, 买入2, ...] → [利润]
128
132
  *
129
133
  * 特点:
130
134
  * - 子钱包不需要预先有 BNB
131
135
  * - 资金来自主钱包卖出代币所得
132
136
  * - 提升资金利用率
137
+ * - ✅ 支持转账多跳,隐藏资金流向
133
138
  *
134
- * 限制:最多 23 个买方(2N + 3 ≤ 50)
139
+ * 限制:根据多跳数动态计算最大买方数量
135
140
  */
136
141
  export declare function fourQuickBatchSwapMerkle(params: FourQuickBatchSwapSignParams): Promise<FourQuickBatchSwapResult>;
@@ -9,6 +9,79 @@ import { NonceManager, getOptimizedGasPrice, getGasLimit, getGasPriceConfig, get
9
9
  import { ADDRESSES, PROFIT_CONFIG, BLOCKRAZOR_BUILDER_EOA } from '../../utils/constants.js';
10
10
  import { TM_ABI, HELPER3_ABI, TM_ADDRESS } from './swap-internal.js';
11
11
  import { getBribeAmount, getProfitRecipient } from './config.js';
12
+ import { generateWallets } from '../../utils/wallet.js';
13
+ // ==================== 多跳转账常量 ====================
14
+ const NATIVE_TRANSFER_GAS_LIMIT = 21055n;
15
+ /**
16
+ * 生成分发多跳路径
17
+ */
18
+ function generateDisperseHopPaths(targetAddresses, hopCount, provider) {
19
+ if (hopCount <= 0) {
20
+ return targetAddresses.map(addr => ({
21
+ targetAddress: addr,
22
+ hopWallets: [],
23
+ hopWalletsInfo: []
24
+ }));
25
+ }
26
+ return targetAddresses.map(targetAddress => {
27
+ const hopWalletsInfo = generateWallets(hopCount);
28
+ const hopWallets = hopWalletsInfo.map(w => new Wallet(w.privateKey, provider));
29
+ return { targetAddress, hopWallets, hopWalletsInfo };
30
+ });
31
+ }
32
+ /**
33
+ * 构建原生代币多跳转账链
34
+ */
35
+ async function buildNativeHopChain(payer, path, finalAmount, gasPrice, chainId, txType, payerNonce) {
36
+ const signedTxs = [];
37
+ const hopCount = path.hopWallets.length;
38
+ if (hopCount === 0) {
39
+ const tx = {
40
+ to: path.targetAddress,
41
+ value: finalAmount,
42
+ nonce: payerNonce,
43
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
44
+ gasPrice,
45
+ chainId,
46
+ type: txType
47
+ };
48
+ signedTxs.push(await payer.signTransaction(tx));
49
+ return signedTxs;
50
+ }
51
+ const hopGasCost = NATIVE_TRANSFER_GAS_LIMIT * gasPrice;
52
+ // 计算每跳需要的金额
53
+ const amountsPerHop = [];
54
+ for (let i = 0; i < hopCount; i++) {
55
+ const remainingHops = hopCount - i;
56
+ amountsPerHop.push(finalAmount + hopGasCost * BigInt(remainingHops));
57
+ }
58
+ // payer → hop1
59
+ signedTxs.push(await payer.signTransaction({
60
+ to: path.hopWallets[0].address,
61
+ value: amountsPerHop[0],
62
+ nonce: payerNonce,
63
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
64
+ gasPrice,
65
+ chainId,
66
+ type: txType
67
+ }));
68
+ // hop1 → hop2 → ... → target
69
+ for (let i = 0; i < hopCount; i++) {
70
+ const fromWallet = path.hopWallets[i];
71
+ const toAddress = i === hopCount - 1 ? path.targetAddress : path.hopWallets[i + 1].address;
72
+ const amount = i === hopCount - 1 ? finalAmount : amountsPerHop[i + 1];
73
+ signedTxs.push(await fromWallet.signTransaction({
74
+ to: toAddress,
75
+ value: amount,
76
+ nonce: 0,
77
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
78
+ gasPrice,
79
+ chainId,
80
+ type: txType
81
+ }));
82
+ }
83
+ return signedTxs;
84
+ }
12
85
  /**
13
86
  * Four内盘捆绑换手
14
87
  */
@@ -430,26 +503,33 @@ export async function fourBatchSwapMerkle(params) {
430
503
  /**
431
504
  * Four 内盘快捷批量换手(资金利用率模式)
432
505
  *
433
- * 流程:[贿赂] → [卖出] → [转账1, 转账2, ...] → [买入1, 买入2, ...] → [利润]
506
+ * 流程:[贿赂] → [卖出] → [转账多跳...] → [买入1, 买入2, ...] → [利润]
434
507
  *
435
508
  * 特点:
436
509
  * - 子钱包不需要预先有 BNB
437
510
  * - 资金来自主钱包卖出代币所得
438
511
  * - 提升资金利用率
512
+ * - ✅ 支持转账多跳,隐藏资金流向
439
513
  *
440
- * 限制:最多 23 个买方(2N + 3 ≤ 50)
514
+ * 限制:根据多跳数动态计算最大买方数量
441
515
  */
442
516
  export async function fourQuickBatchSwapMerkle(params) {
443
- const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerRatios, buyerAmounts, tokenAddress, config, startNonces // ✅ 可选:前端预获取的 nonces
517
+ const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerRatios, buyerAmounts, tokenAddress, config, disperseHopCount = 0, // ✅ 转账多跳数(默认0=直接转账)
518
+ startNonces // ✅ 可选:前端预获取的 nonces
444
519
  } = params;
445
- // ✅ 校验买方数量
446
- // 贿赂(1) + 卖出(1) + 转账(N) + 买入(N) + 利润(1) ≤ 50 → 2N + 3 ≤ 50 → N ≤ 23
447
- const MAX_BUYERS = 23;
520
+ // ✅ 动态计算最大买方数量(根据多跳数)
521
+ // 固定开销: 贿赂(1) + 卖出(1) + 利润多跳(PROFIT_HOP_COUNT + 1)
522
+ // 转账(N*(H+1)) + 买入(N) = N*(H+2)
523
+ const fixedOverhead = 1 + 1 + PROFIT_HOP_COUNT + 1;
524
+ const maxTxs = 50 - fixedOverhead;
525
+ let MAX_BUYERS = Math.floor(maxTxs / (disperseHopCount + 2));
526
+ MAX_BUYERS = Math.max(1, MAX_BUYERS);
527
+ console.log(`[fourQuickBatchSwapMerkle] 多跳数: ${disperseHopCount}, 最大买方数: ${MAX_BUYERS}`);
448
528
  if (buyerPrivateKeys.length === 0) {
449
529
  throw new Error('至少需要一个买方钱包');
450
530
  }
451
531
  if (buyerPrivateKeys.length > MAX_BUYERS) {
452
- throw new Error(`资金利用率模式买方钱包数量超过限制: ${buyerPrivateKeys.length} > ${MAX_BUYERS}`);
532
+ throw new Error(`资金利用率模式(${disperseHopCount}跳)买方钱包数量超过限制: ${buyerPrivateKeys.length} > ${MAX_BUYERS}`);
453
533
  }
454
534
  // ✅ 校验分配模式
455
535
  if (!buyerRatios && !buyerAmounts) {
@@ -559,25 +639,45 @@ export async function fourQuickBatchSwapMerkle(params) {
559
639
  type: txType
560
640
  });
561
641
  console.log(`[fourQuickBatchSwapMerkle] 卖出交易已签名`);
562
- // ==================== 3. 转账交易(并行签名)====================
642
+ // ==================== 3. 转账交易(支持多跳)====================
563
643
  const reserveGas = ethers.parseEther((config.reserveGasBNB || 0.0005).toString());
564
644
  const buyerGasCost = gasPrice * finalGasLimit;
565
- // ✅ 预分配 nonce,然后并行签名
566
- const transferNonces = buyers.map((_, i) => sellerNonce + i);
567
- sellerNonce += buyers.length; // 更新 sellerNonce
568
- const transferTxs = await Promise.all(buyers.map((buyer, i) => {
569
- const transferValue = transferAmountsWei[i] + reserveGas + buyerGasCost;
570
- return seller.signTransaction({
571
- to: buyer.address,
572
- value: transferValue,
573
- nonce: transferNonces[i],
574
- gasPrice,
575
- gasLimit: 21000n,
576
- chainId: chainIdNum,
577
- type: txType
578
- });
579
- }));
580
- console.log(`[fourQuickBatchSwapMerkle] ${transferTxs.length} 笔转账交易已签名`);
645
+ // ✅ 生成多跳路径
646
+ const hopPaths = generateDisperseHopPaths(buyers.map(b => b.address), disperseHopCount, provider);
647
+ // 收集所有中间钱包信息
648
+ const allHopWallets = [];
649
+ hopPaths.forEach(path => {
650
+ allHopWallets.push(...path.hopWalletsInfo);
651
+ });
652
+ let transferTxs = [];
653
+ if (disperseHopCount === 0) {
654
+ // ✅ 无多跳:直接转账
655
+ const transferNonces = buyers.map((_, i) => sellerNonce + i);
656
+ sellerNonce += buyers.length;
657
+ transferTxs = await Promise.all(buyers.map((buyer, i) => {
658
+ const transferValue = transferAmountsWei[i] + reserveGas + buyerGasCost;
659
+ return seller.signTransaction({
660
+ to: buyer.address,
661
+ value: transferValue,
662
+ nonce: transferNonces[i],
663
+ gasPrice,
664
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
665
+ chainId: chainIdNum,
666
+ type: txType
667
+ });
668
+ }));
669
+ }
670
+ else {
671
+ // ✅ 有多跳:构建多跳转账链
672
+ const hopChains = await Promise.all(hopPaths.map((path, i) => {
673
+ const finalAmount = transferAmountsWei[i] + reserveGas + buyerGasCost;
674
+ const payerNonce = sellerNonce + i * (disperseHopCount + 1);
675
+ return buildNativeHopChain(seller, path, finalAmount, gasPrice, chainIdNum, txType, payerNonce);
676
+ }));
677
+ transferTxs = hopChains.flat();
678
+ sellerNonce += buyers.length * (disperseHopCount + 1);
679
+ }
680
+ console.log(`[fourQuickBatchSwapMerkle] ${transferTxs.length} 笔转账交易已签名 (多跳数=${disperseHopCount})`);
581
681
  // ==================== 4. 买入交易 ====================
582
682
  // ✅ 如果前端传入了 startNonces,使用 buyer 部分(从索引 1 开始)
583
683
  const buyerNonces = startNonces && startNonces.length > 1
@@ -631,13 +731,15 @@ export async function fourQuickBatchSwapMerkle(params) {
631
731
  console.log(` - 利润多跳: ${profitAmount > 0n ? PROFIT_HOP_COUNT + 1 : 0}`);
632
732
  return {
633
733
  signedTransactions,
734
+ disperseHopWallets: allHopWallets.length > 0 ? allHopWallets : undefined, // ✅ 返回中间钱包信息
634
735
  metadata: {
635
736
  sellerAddress: seller.address,
636
737
  buyerAddresses: buyers.map(b => b.address),
637
738
  sellAmount: ethers.formatUnits(sellAmountWei, decimals),
638
739
  estimatedBNBOut: ethers.formatEther(estimatedBNBOut),
639
740
  transferAmounts: transferAmountsWei.map(amt => ethers.formatEther(amt)),
640
- profitAmount: profitAmount > 0n ? ethers.formatEther(profitAmount) : undefined
741
+ profitAmount: profitAmount > 0n ? ethers.formatEther(profitAmount) : undefined,
742
+ disperseHopCount: disperseHopCount > 0 ? disperseHopCount : undefined // ✅ 返回多跳数
641
743
  }
642
744
  };
643
745
  }
@@ -4,6 +4,7 @@
4
4
  * 功能:钱包A卖出代币 → 钱包B买入相同数量 → 原子执行
5
5
  */
6
6
  import { CommonBundleConfig } from '../../utils/bundle-helpers.js';
7
+ import { type GeneratedWallet } from '../../utils/wallet.js';
7
8
  export interface FlapSwapSignConfig {
8
9
  rpcUrl: string;
9
10
  gasLimit?: number | bigint;
@@ -118,6 +119,7 @@ export interface FlapQuickBatchSwapSignParams {
118
119
  config: FlapSwapSignConfig;
119
120
  quoteToken?: string;
120
121
  quoteTokenDecimals?: number;
122
+ disperseHopCount?: number;
121
123
  startNonces?: number[];
122
124
  }
123
125
  /**
@@ -125,6 +127,7 @@ export interface FlapQuickBatchSwapSignParams {
125
127
  */
126
128
  export interface FlapQuickBatchSwapResult {
127
129
  signedTransactions: string[];
130
+ disperseHopWallets?: GeneratedWallet[];
128
131
  metadata?: {
129
132
  sellerAddress: string;
130
133
  buyerAddresses: string[];
@@ -133,19 +136,21 @@ export interface FlapQuickBatchSwapResult {
133
136
  transferAmounts: string[];
134
137
  profitAmount?: string;
135
138
  useNativeToken: boolean;
139
+ disperseHopCount?: number;
136
140
  };
137
141
  }
138
142
  /**
139
143
  * Flap 内盘快捷批量换手(资金利用率模式)
140
144
  *
141
- * 流程:[贿赂] → [卖出] → [转账1, 转账2, ...] → [买入1, 买入2, ...] → [利润]
145
+ * 流程:[贿赂] → [卖出] → [转账多跳...] → [买入1, 买入2, ...] → [利润]
142
146
  *
143
147
  * 特点:
144
148
  * - 子钱包不需要预先有余额
145
149
  * - 资金来自主钱包卖出代币所得
146
150
  * - 提升资金利用率
147
151
  * - 支持原生代币(BNB/OKB/ETH)和 ERC20(如 USDT)两种模式
152
+ * - ✅ 支持转账多跳,隐藏资金流向
148
153
  *
149
- * 限制:最多 23 个买方(2N + 3 ≤ 50)
154
+ * 限制:根据多跳数动态计算最大买方数量
150
155
  */
151
156
  export declare function flapQuickBatchSwapMerkle(params: FlapQuickBatchSwapSignParams): Promise<FlapQuickBatchSwapResult>;
@@ -8,8 +8,176 @@ import { calculateSellAmount } from '../../utils/swap-helpers.js';
8
8
  import { NonceManager, getOptimizedGasPrice, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../../utils/bundle-helpers.js';
9
9
  import { FLAP_PORTAL_ADDRESSES } from '../constants.js';
10
10
  import { PROFIT_CONFIG, ADDRESSES, ZERO_ADDRESS } from '../../utils/constants.js';
11
- import { ERC20_ALLOWANCE_ABI, V2_ROUTER_QUOTE_ABI, ERC20_BALANCE_ABI } from '../../abis/common.js';
11
+ import { ERC20_ALLOWANCE_ABI, V2_ROUTER_QUOTE_ABI, ERC20_BALANCE_ABI, ERC20_ABI } from '../../abis/common.js';
12
12
  import { getGasPriceConfig, getTxType, getProfitRecipient, getBribeAmount, BLOCKRAZOR_BUILDER_EOA, PORTAL_ABI } from './config.js';
13
+ import { generateWallets } from '../../utils/wallet.js';
14
+ // ==================== 多跳转账常量 ====================
15
+ const NATIVE_TRANSFER_GAS_LIMIT = 21055n;
16
+ const ERC20_TRANSFER_GAS_LIMIT_HOP = 65000n;
17
+ /**
18
+ * 生成分发多跳路径
19
+ */
20
+ function generateDisperseHopPaths(targetAddresses, hopCount, provider) {
21
+ if (hopCount <= 0) {
22
+ return targetAddresses.map(addr => ({
23
+ targetAddress: addr,
24
+ hopWallets: [],
25
+ hopWalletsInfo: []
26
+ }));
27
+ }
28
+ return targetAddresses.map(targetAddress => {
29
+ const hopWalletsInfo = generateWallets(hopCount);
30
+ const hopWallets = hopWalletsInfo.map(w => new Wallet(w.privateKey, provider));
31
+ return { targetAddress, hopWallets, hopWalletsInfo };
32
+ });
33
+ }
34
+ /**
35
+ * 构建原生代币多跳转账链
36
+ */
37
+ async function buildNativeHopChain(payer, path, finalAmount, gasPrice, chainId, txType, payerNonce) {
38
+ const signedTxs = [];
39
+ const hopCount = path.hopWallets.length;
40
+ if (hopCount === 0) {
41
+ signedTxs.push(await payer.signTransaction({
42
+ to: path.targetAddress,
43
+ value: finalAmount,
44
+ nonce: payerNonce,
45
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
46
+ gasPrice,
47
+ chainId,
48
+ type: txType
49
+ }));
50
+ return signedTxs;
51
+ }
52
+ const hopGasCost = NATIVE_TRANSFER_GAS_LIMIT * gasPrice;
53
+ // 计算每跳需要的金额
54
+ const amountsPerHop = [];
55
+ for (let i = 0; i < hopCount; i++) {
56
+ const remainingHops = hopCount - i;
57
+ amountsPerHop.push(finalAmount + hopGasCost * BigInt(remainingHops));
58
+ }
59
+ // payer → hop1
60
+ signedTxs.push(await payer.signTransaction({
61
+ to: path.hopWallets[0].address,
62
+ value: amountsPerHop[0],
63
+ nonce: payerNonce,
64
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
65
+ gasPrice,
66
+ chainId,
67
+ type: txType
68
+ }));
69
+ // hop1 → hop2 → ... → target
70
+ for (let i = 0; i < hopCount; i++) {
71
+ const fromWallet = path.hopWallets[i];
72
+ const toAddress = i === hopCount - 1 ? path.targetAddress : path.hopWallets[i + 1].address;
73
+ const amount = i === hopCount - 1 ? finalAmount : amountsPerHop[i + 1];
74
+ signedTxs.push(await fromWallet.signTransaction({
75
+ to: toAddress,
76
+ value: amount,
77
+ nonce: 0,
78
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
79
+ gasPrice,
80
+ chainId,
81
+ type: txType
82
+ }));
83
+ }
84
+ return signedTxs;
85
+ }
86
+ /**
87
+ * 构建 ERC20 多跳转账链
88
+ */
89
+ async function buildERC20HopChain(payer, path, erc20Address, erc20Amount, gasPrice, chainId, txType, payerNonce) {
90
+ const signedTxs = [];
91
+ const hopCount = path.hopWallets.length;
92
+ const erc20Interface = new ethers.Interface(ERC20_ABI);
93
+ if (hopCount === 0) {
94
+ const data = erc20Interface.encodeFunctionData('transfer', [path.targetAddress, erc20Amount]);
95
+ signedTxs.push(await payer.signTransaction({
96
+ to: erc20Address,
97
+ data,
98
+ value: 0n,
99
+ nonce: payerNonce,
100
+ gasLimit: ERC20_TRANSFER_GAS_LIMIT_HOP,
101
+ gasPrice,
102
+ chainId,
103
+ type: txType
104
+ }));
105
+ return signedTxs;
106
+ }
107
+ // payer → hop1
108
+ const firstData = erc20Interface.encodeFunctionData('transfer', [path.hopWallets[0].address, erc20Amount]);
109
+ signedTxs.push(await payer.signTransaction({
110
+ to: erc20Address,
111
+ data: firstData,
112
+ value: 0n,
113
+ nonce: payerNonce,
114
+ gasLimit: ERC20_TRANSFER_GAS_LIMIT_HOP,
115
+ gasPrice,
116
+ chainId,
117
+ type: txType
118
+ }));
119
+ // hop1 → hop2 → ... → target (nonce=1,nonce=0 用于 BNB 转发)
120
+ for (let i = 0; i < hopCount; i++) {
121
+ const fromWallet = path.hopWallets[i];
122
+ const toAddress = i === hopCount - 1 ? path.targetAddress : path.hopWallets[i + 1].address;
123
+ const data = erc20Interface.encodeFunctionData('transfer', [toAddress, erc20Amount]);
124
+ signedTxs.push(await fromWallet.signTransaction({
125
+ to: erc20Address,
126
+ data,
127
+ value: 0n,
128
+ nonce: 1, // nonce=0 已用于 BNB 转发
129
+ gasLimit: ERC20_TRANSFER_GAS_LIMIT_HOP,
130
+ gasPrice,
131
+ chainId,
132
+ type: txType
133
+ }));
134
+ }
135
+ return signedTxs;
136
+ }
137
+ /**
138
+ * 构建 BNB 多跳转账链(为 ERC20 中间钱包预留 gas)
139
+ */
140
+ async function buildBNBHopChainForERC20(payer, path, finalGasAmount, gasPrice, chainId, txType, payerNonce) {
141
+ const signedTxs = [];
142
+ const hopCount = path.hopWallets.length;
143
+ if (hopCount === 0) {
144
+ return signedTxs;
145
+ }
146
+ const hopGasCost = NATIVE_TRANSFER_GAS_LIMIT * gasPrice;
147
+ const erc20GasCost = ERC20_TRANSFER_GAS_LIMIT_HOP * gasPrice;
148
+ const gasPerHop = hopGasCost + erc20GasCost * 2n;
149
+ const amountsPerHop = [];
150
+ for (let i = 0; i < hopCount; i++) {
151
+ const remainingHops = hopCount - i;
152
+ amountsPerHop.push(finalGasAmount + gasPerHop * BigInt(remainingHops));
153
+ }
154
+ // payer → hop1
155
+ signedTxs.push(await payer.signTransaction({
156
+ to: path.hopWallets[0].address,
157
+ value: amountsPerHop[0],
158
+ nonce: payerNonce,
159
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
160
+ gasPrice,
161
+ chainId,
162
+ type: txType
163
+ }));
164
+ // hop1 → hop2 → ... → target (nonce=0)
165
+ for (let i = 0; i < hopCount; i++) {
166
+ const fromWallet = path.hopWallets[i];
167
+ const toAddress = i === hopCount - 1 ? path.targetAddress : path.hopWallets[i + 1].address;
168
+ const amount = i === hopCount - 1 ? finalGasAmount : amountsPerHop[i + 1];
169
+ signedTxs.push(await fromWallet.signTransaction({
170
+ to: toAddress,
171
+ value: amount,
172
+ nonce: 0,
173
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
174
+ gasPrice,
175
+ chainId,
176
+ type: txType
177
+ }));
178
+ }
179
+ return signedTxs;
180
+ }
13
181
  /**
14
182
  * 获取 Gas Limit
15
183
  */
@@ -696,28 +864,44 @@ export async function flapBatchSwapMerkle(params) {
696
864
  /**
697
865
  * Flap 内盘快捷批量换手(资金利用率模式)
698
866
  *
699
- * 流程:[贿赂] → [卖出] → [转账1, 转账2, ...] → [买入1, 买入2, ...] → [利润]
867
+ * 流程:[贿赂] → [卖出] → [转账多跳...] → [买入1, 买入2, ...] → [利润]
700
868
  *
701
869
  * 特点:
702
870
  * - 子钱包不需要预先有余额
703
871
  * - 资金来自主钱包卖出代币所得
704
872
  * - 提升资金利用率
705
873
  * - 支持原生代币(BNB/OKB/ETH)和 ERC20(如 USDT)两种模式
874
+ * - ✅ 支持转账多跳,隐藏资金流向
706
875
  *
707
- * 限制:最多 23 个买方(2N + 3 ≤ 50)
876
+ * 限制:根据多跳数动态计算最大买方数量
708
877
  */
709
878
  export async function flapQuickBatchSwapMerkle(params) {
710
- const { chain, sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerRatios, buyerAmounts, tokenAddress, config, quoteToken, quoteTokenDecimals = 18, startNonces // ✅ 可选:前端预获取的 nonces
879
+ const { chain, sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerRatios, buyerAmounts, tokenAddress, config, quoteToken, quoteTokenDecimals = 18, disperseHopCount = 0, // ✅ 转账多跳数(默认0=直接转账)
880
+ startNonces // ✅ 可选:前端预获取的 nonces
711
881
  } = params;
712
- // ✅ 校验买方数量
713
- // BNB 模式:贿赂(1) + 卖出(1) + 转账(N) + 买入(N) + 利润(1) ≤ 50 → 2N + 3 ≤ 50 → N ≤ 23
714
- // ERC20 模式:贿赂(1) + 卖出(1) + ERC20转账(N) + 买入(N) + 利润(1) ≤ 50 → 2N + 3 ≤ 50 → N ≤ 23
715
- const MAX_BUYERS = 23;
882
+ // ✅ 判断是否使用原生代币
883
+ const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
884
+ // 动态计算最大买方数量(根据多跳数)
885
+ // 固定开销: 贿赂(1) + 卖出(1) + 利润多跳(PROFIT_HOP_COUNT + 1)
886
+ const fixedOverhead = 1 + 1 + PROFIT_HOP_COUNT + 1;
887
+ const maxTxs = 50 - fixedOverhead;
888
+ let MAX_BUYERS;
889
+ if (useNativeToken) {
890
+ // 原生代币模式: N*(H+2) <= maxTxs
891
+ MAX_BUYERS = Math.floor(maxTxs / (disperseHopCount + 2));
892
+ }
893
+ else {
894
+ // ERC20 模式: N*(2H+3) <= maxTxs
895
+ MAX_BUYERS = Math.floor(maxTxs / (2 * disperseHopCount + 3));
896
+ }
897
+ MAX_BUYERS = Math.max(1, MAX_BUYERS);
898
+ console.log(`[flapQuickBatchSwapMerkle] 多跳数: ${disperseHopCount}, 最大买方数: ${MAX_BUYERS}`);
716
899
  if (buyerPrivateKeys.length === 0) {
717
900
  throw new Error('至少需要一个买方钱包');
718
901
  }
719
902
  if (buyerPrivateKeys.length > MAX_BUYERS) {
720
- throw new Error(`资金利用率模式买方钱包数量超过限制: ${buyerPrivateKeys.length} > ${MAX_BUYERS}`);
903
+ const mode = useNativeToken ? '原生代币' : 'ERC20';
904
+ throw new Error(`资金利用率模式(${mode}, ${disperseHopCount}跳)买方钱包数量超过限制: ${buyerPrivateKeys.length} > ${MAX_BUYERS}`);
721
905
  }
722
906
  // ✅ 校验分配模式
723
907
  if (!buyerRatios && !buyerAmounts) {
@@ -729,8 +913,6 @@ export async function flapQuickBatchSwapMerkle(params) {
729
913
  if (buyerAmounts && buyerAmounts.length !== buyerPrivateKeys.length) {
730
914
  throw new Error(`buyerAmounts 长度 (${buyerAmounts.length}) 与 buyerPrivateKeys 长度 (${buyerPrivateKeys.length}) 不匹配`);
731
915
  }
732
- // ✅ 判断是否使用原生代币
733
- const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
734
916
  const outputToken = useNativeToken ? ZERO_ADDRESS : quoteToken;
735
917
  const ERC20_TRANSFER_GAS = 65000n;
736
918
  const chainContext = createChainContext(chain, config);
@@ -856,51 +1038,88 @@ export async function flapQuickBatchSwapMerkle(params) {
856
1038
  });
857
1039
  const signedSell = await seller.signTransaction(sellTx);
858
1040
  console.log(`[flapQuickBatchSwapMerkle] 卖出交易已签名`);
859
- // ==================== 3. 转账交易(并行签名)====================
1041
+ // ==================== 3. 转账交易(支持多跳)====================
860
1042
  const reserveGas = ethers.parseEther((config.reserveGasETH || 0.0005).toString());
861
1043
  const buyerGasCost = gasPrice * finalGasLimit;
862
- // ✅ 预分配 nonce,然后并行签名
863
- const transferNonces = buyers.map((_, i) => sellerNonce + i);
864
- sellerNonce += buyers.length; // 更新 sellerNonce
865
- let transferTxs;
866
- if (useNativeToken) {
867
- // 原生代币模式:直接转账(并行签名)
868
- transferTxs = await Promise.all(buyers.map((buyer, i) => {
869
- const transferValue = transferAmountsWei[i] + reserveGas + buyerGasCost;
870
- return seller.signTransaction({
871
- to: buyer.address,
872
- value: transferValue,
873
- nonce: transferNonces[i],
874
- gasPrice,
875
- gasLimit: 21000n,
876
- chainId: chainContext.chainId,
877
- type: txType
878
- });
879
- }));
1044
+ // ✅ 生成多跳路径
1045
+ const hopPaths = generateDisperseHopPaths(buyers.map(b => b.address), disperseHopCount, chainContext.provider);
1046
+ // 收集所有中间钱包信息
1047
+ const allHopWallets = [];
1048
+ hopPaths.forEach(path => {
1049
+ allHopWallets.push(...path.hopWalletsInfo);
1050
+ });
1051
+ let transferTxs = [];
1052
+ if (disperseHopCount === 0) {
1053
+ // ✅ 无多跳:直接转账
1054
+ const transferNonces = buyers.map((_, i) => sellerNonce + i);
1055
+ sellerNonce += buyers.length;
1056
+ if (useNativeToken) {
1057
+ transferTxs = await Promise.all(buyers.map((buyer, i) => {
1058
+ const transferValue = transferAmountsWei[i] + reserveGas + buyerGasCost;
1059
+ return seller.signTransaction({
1060
+ to: buyer.address,
1061
+ value: transferValue,
1062
+ nonce: transferNonces[i],
1063
+ gasPrice,
1064
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
1065
+ chainId: chainContext.chainId,
1066
+ type: txType
1067
+ });
1068
+ }));
1069
+ }
1070
+ else {
1071
+ const erc20Interface = new ethers.Interface(ERC20_ABI);
1072
+ transferTxs = await Promise.all(buyers.map((buyer, i) => {
1073
+ const transferData = erc20Interface.encodeFunctionData('transfer', [
1074
+ buyer.address,
1075
+ transferAmountsWei[i]
1076
+ ]);
1077
+ return seller.signTransaction({
1078
+ to: quoteToken,
1079
+ data: transferData,
1080
+ value: 0n,
1081
+ nonce: transferNonces[i],
1082
+ gasPrice,
1083
+ gasLimit: ERC20_TRANSFER_GAS,
1084
+ chainId: chainContext.chainId,
1085
+ type: txType
1086
+ });
1087
+ }));
1088
+ }
880
1089
  }
881
1090
  else {
882
- // ERC20 模式:ERC20 transfer(并行签名)
883
- const erc20Interface = new ethers.Interface([
884
- 'function transfer(address to, uint256 amount) returns (bool)'
885
- ]);
886
- transferTxs = await Promise.all(buyers.map((buyer, i) => {
887
- const transferData = erc20Interface.encodeFunctionData('transfer', [
888
- buyer.address,
889
- transferAmountsWei[i]
890
- ]);
891
- return seller.signTransaction({
892
- to: quoteToken,
893
- data: transferData,
894
- value: 0n,
895
- nonce: transferNonces[i],
896
- gasPrice,
897
- gasLimit: ERC20_TRANSFER_GAS,
898
- chainId: chainContext.chainId,
899
- type: txType
900
- });
901
- }));
1091
+ // 有多跳:构建多跳转账链
1092
+ if (useNativeToken) {
1093
+ // 原生代币多跳转账
1094
+ const hopChains = await Promise.all(hopPaths.map((path, i) => {
1095
+ const finalAmount = transferAmountsWei[i] + reserveGas + buyerGasCost;
1096
+ const payerNonce = sellerNonce + i * (disperseHopCount + 1);
1097
+ return buildNativeHopChain(seller, path, finalAmount, gasPrice, chainContext.chainId, txType, payerNonce);
1098
+ }));
1099
+ transferTxs = hopChains.flat();
1100
+ sellerNonce += buyers.length * (disperseHopCount + 1);
1101
+ }
1102
+ else {
1103
+ // ERC20 多跳转账:先转 BNB(给中间钱包 gas),再转 ERC20
1104
+ // 1. 构建 BNB 多跳链
1105
+ const bnbHopChains = await Promise.all(hopPaths.map((path, i) => {
1106
+ const finalGasAmount = buyerGasCost;
1107
+ const payerNonce = sellerNonce + i * (disperseHopCount + 1);
1108
+ return buildBNBHopChainForERC20(seller, path, finalGasAmount, gasPrice, chainContext.chainId, txType, payerNonce);
1109
+ }));
1110
+ const bnbTxs = bnbHopChains.flat();
1111
+ sellerNonce += buyers.length * (disperseHopCount + 1);
1112
+ // 2. 构建 ERC20 多跳链
1113
+ const erc20HopChains = await Promise.all(hopPaths.map((path, i) => {
1114
+ const payerNonce = sellerNonce + i * (disperseHopCount + 1);
1115
+ return buildERC20HopChain(seller, path, quoteToken, transferAmountsWei[i], gasPrice, chainContext.chainId, txType, payerNonce);
1116
+ }));
1117
+ const erc20Txs = erc20HopChains.flat();
1118
+ sellerNonce += buyers.length * (disperseHopCount + 1);
1119
+ transferTxs = [...bnbTxs, ...erc20Txs];
1120
+ }
902
1121
  }
903
- console.log(`[flapQuickBatchSwapMerkle] ${transferTxs.length} 笔转账交易已签名`);
1122
+ console.log(`[flapQuickBatchSwapMerkle] ${transferTxs.length} 笔转账交易已签名 (多跳数=${disperseHopCount})`);
904
1123
  // ==================== 4. 买入交易 ====================
905
1124
  // ✅ 如果前端传入了 startNonces,使用 buyer 部分(从索引 1 开始)
906
1125
  const buyerNonces = startNonces && startNonces.length > 1
@@ -960,6 +1179,7 @@ export async function flapQuickBatchSwapMerkle(params) {
960
1179
  console.log(` - 利润多跳: ${nativeProfitAmount > 0n ? PROFIT_HOP_COUNT + 1 : 0}`);
961
1180
  return {
962
1181
  signedTransactions,
1182
+ disperseHopWallets: allHopWallets.length > 0 ? allHopWallets : undefined, // ✅ 返回中间钱包信息
963
1183
  metadata: {
964
1184
  sellerAddress: seller.address,
965
1185
  buyerAddresses: buyers.map(b => b.address),
@@ -971,7 +1191,8 @@ export async function flapQuickBatchSwapMerkle(params) {
971
1191
  ? ethers.formatEther(amt)
972
1192
  : ethers.formatUnits(amt, quoteTokenDecimals)),
973
1193
  profitAmount: nativeProfitAmount > 0n ? ethers.formatEther(nativeProfitAmount) : undefined,
974
- useNativeToken
1194
+ useNativeToken,
1195
+ disperseHopCount: disperseHopCount > 0 ? disperseHopCount : undefined // ✅ 返回多跳数
975
1196
  }
976
1197
  };
977
1198
  }
@@ -1,4 +1,5 @@
1
1
  import { CommonBundleConfig } from '../utils/bundle-helpers.js';
2
+ import { type GeneratedWallet } from '../utils/wallet.js';
2
3
  export interface PancakeSwapSignConfig {
3
4
  rpcUrl: string;
4
5
  gasLimit?: number | bigint;
@@ -129,6 +130,7 @@ export interface PancakeQuickBatchSwapParams {
129
130
  config: PancakeSwapSignConfig;
130
131
  quoteToken?: string;
131
132
  quoteTokenDecimals?: number;
133
+ disperseHopCount?: number;
132
134
  startNonces?: number[];
133
135
  }
134
136
  /**
@@ -136,6 +138,7 @@ export interface PancakeQuickBatchSwapParams {
136
138
  */
137
139
  export interface PancakeQuickBatchSwapResult {
138
140
  signedTransactions: string[];
141
+ disperseHopWallets?: GeneratedWallet[];
139
142
  metadata?: {
140
143
  sellerAddress: string;
141
144
  buyerAddresses: string[];
@@ -144,19 +147,21 @@ export interface PancakeQuickBatchSwapResult {
144
147
  transferAmounts: string[];
145
148
  profitAmount?: string;
146
149
  useNativeToken: boolean;
150
+ disperseHopCount?: number;
147
151
  };
148
152
  }
149
153
  /**
150
154
  * PancakeSwap 快捷批量换手(资金自动流转)
151
155
  *
152
- * 流程:[贿赂] → [卖出] → [转账1, 转账2, ...] → [买入1, 买入2, ...] → [利润]
156
+ * 流程:[贿赂] → [卖出] → [转账多跳...] → [买入1, 买入2, ...] → [利润]
153
157
  *
154
158
  * 特点:
155
159
  * - 子钱包不需要预先有余额
156
160
  * - 资金来自主钱包卖出代币所得
157
161
  * - 提升资金利用率
158
162
  * - 支持 BNB 和 ERC20(如 USDT)两种模式
163
+ * - ✅ 支持转账多跳,隐藏资金流向
159
164
  *
160
- * 限制:最多 23 个买方(转账 + 买入 = 46 笔,加上贿赂/卖出/利润 = 50 笔限制)
165
+ * 限制:根据多跳数动态计算最大买方数量
161
166
  */
162
167
  export declare function pancakeQuickBatchSwapMerkle(params: PancakeQuickBatchSwapParams): Promise<PancakeQuickBatchSwapResult>;
@@ -1,3 +1,229 @@
1
+ // ==================== 多跳转账常量 ====================
2
+ const NATIVE_TRANSFER_GAS_LIMIT = 21055n;
3
+ const ERC20_TRANSFER_GAS_LIMIT_HOP = 65000n;
4
+ /**
5
+ * 生成分发多跳路径
6
+ */
7
+ function generateDisperseHopPaths(targetAddresses, hopCount, provider) {
8
+ if (hopCount <= 0) {
9
+ return targetAddresses.map(addr => ({
10
+ targetAddress: addr,
11
+ hopWallets: [],
12
+ hopWalletsInfo: []
13
+ }));
14
+ }
15
+ return targetAddresses.map(targetAddress => {
16
+ const hopWalletsInfo = generateWallets(hopCount);
17
+ const hopWallets = hopWalletsInfo.map(w => new Wallet(w.privateKey, provider));
18
+ return { targetAddress, hopWallets, hopWalletsInfo };
19
+ });
20
+ }
21
+ /**
22
+ * 构建原生代币多跳转账链
23
+ */
24
+ async function buildNativeHopChain(payer, path, finalAmount, gasPrice, chainId, txType, payerNonce) {
25
+ const signedTxs = [];
26
+ const hopCount = path.hopWallets.length;
27
+ if (hopCount === 0) {
28
+ const tx = {
29
+ to: path.targetAddress,
30
+ value: finalAmount,
31
+ nonce: payerNonce,
32
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
33
+ chainId,
34
+ type: txType
35
+ };
36
+ if (txType === 2) {
37
+ tx.maxFeePerGas = gasPrice;
38
+ tx.maxPriorityFeePerGas = gasPrice / 10n || 1n;
39
+ }
40
+ else {
41
+ tx.gasPrice = gasPrice;
42
+ }
43
+ signedTxs.push(await payer.signTransaction(tx));
44
+ return signedTxs;
45
+ }
46
+ const hopGasCost = NATIVE_TRANSFER_GAS_LIMIT * gasPrice;
47
+ // 计算每跳需要的金额
48
+ const amountsPerHop = [];
49
+ for (let i = 0; i < hopCount; i++) {
50
+ const remainingHops = hopCount - i;
51
+ amountsPerHop.push(finalAmount + hopGasCost * BigInt(remainingHops));
52
+ }
53
+ // payer → hop1
54
+ const firstTx = {
55
+ to: path.hopWallets[0].address,
56
+ value: amountsPerHop[0],
57
+ nonce: payerNonce,
58
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
59
+ chainId,
60
+ type: txType
61
+ };
62
+ if (txType === 2) {
63
+ firstTx.maxFeePerGas = gasPrice;
64
+ firstTx.maxPriorityFeePerGas = gasPrice / 10n || 1n;
65
+ }
66
+ else {
67
+ firstTx.gasPrice = gasPrice;
68
+ }
69
+ signedTxs.push(await payer.signTransaction(firstTx));
70
+ // hop1 → hop2 → ... → target
71
+ for (let i = 0; i < hopCount; i++) {
72
+ const fromWallet = path.hopWallets[i];
73
+ const toAddress = i === hopCount - 1 ? path.targetAddress : path.hopWallets[i + 1].address;
74
+ const amount = i === hopCount - 1 ? finalAmount : amountsPerHop[i + 1];
75
+ const tx = {
76
+ to: toAddress,
77
+ value: amount,
78
+ nonce: 0,
79
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
80
+ chainId,
81
+ type: txType
82
+ };
83
+ if (txType === 2) {
84
+ tx.maxFeePerGas = gasPrice;
85
+ tx.maxPriorityFeePerGas = gasPrice / 10n || 1n;
86
+ }
87
+ else {
88
+ tx.gasPrice = gasPrice;
89
+ }
90
+ signedTxs.push(await fromWallet.signTransaction(tx));
91
+ }
92
+ return signedTxs;
93
+ }
94
+ /**
95
+ * 构建 ERC20 多跳转账链(需要配合 BNB 多跳使用)
96
+ */
97
+ async function buildERC20HopChain(payer, path, erc20Address, erc20Amount, gasPrice, chainId, txType, payerNonce) {
98
+ const signedTxs = [];
99
+ const hopCount = path.hopWallets.length;
100
+ const erc20Interface = new ethers.Interface(ERC20_ABI);
101
+ if (hopCount === 0) {
102
+ const data = erc20Interface.encodeFunctionData('transfer', [path.targetAddress, erc20Amount]);
103
+ const tx = {
104
+ to: erc20Address,
105
+ data,
106
+ value: 0n,
107
+ nonce: payerNonce,
108
+ gasLimit: ERC20_TRANSFER_GAS_LIMIT_HOP,
109
+ chainId,
110
+ type: txType
111
+ };
112
+ if (txType === 2) {
113
+ tx.maxFeePerGas = gasPrice;
114
+ tx.maxPriorityFeePerGas = gasPrice / 10n || 1n;
115
+ }
116
+ else {
117
+ tx.gasPrice = gasPrice;
118
+ }
119
+ signedTxs.push(await payer.signTransaction(tx));
120
+ return signedTxs;
121
+ }
122
+ // payer → hop1
123
+ const firstData = erc20Interface.encodeFunctionData('transfer', [path.hopWallets[0].address, erc20Amount]);
124
+ const firstTx = {
125
+ to: erc20Address,
126
+ data: firstData,
127
+ value: 0n,
128
+ nonce: payerNonce,
129
+ gasLimit: ERC20_TRANSFER_GAS_LIMIT_HOP,
130
+ chainId,
131
+ type: txType
132
+ };
133
+ if (txType === 2) {
134
+ firstTx.maxFeePerGas = gasPrice;
135
+ firstTx.maxPriorityFeePerGas = gasPrice / 10n || 1n;
136
+ }
137
+ else {
138
+ firstTx.gasPrice = gasPrice;
139
+ }
140
+ signedTxs.push(await payer.signTransaction(firstTx));
141
+ // hop1 → hop2 → ... → target (nonce=1,nonce=0 用于 BNB 转发)
142
+ for (let i = 0; i < hopCount; i++) {
143
+ const fromWallet = path.hopWallets[i];
144
+ const toAddress = i === hopCount - 1 ? path.targetAddress : path.hopWallets[i + 1].address;
145
+ const data = erc20Interface.encodeFunctionData('transfer', [toAddress, erc20Amount]);
146
+ const tx = {
147
+ to: erc20Address,
148
+ data,
149
+ value: 0n,
150
+ nonce: 1, // nonce=0 已用于 BNB 转发
151
+ gasLimit: ERC20_TRANSFER_GAS_LIMIT_HOP,
152
+ chainId,
153
+ type: txType
154
+ };
155
+ if (txType === 2) {
156
+ tx.maxFeePerGas = gasPrice;
157
+ tx.maxPriorityFeePerGas = gasPrice / 10n || 1n;
158
+ }
159
+ else {
160
+ tx.gasPrice = gasPrice;
161
+ }
162
+ signedTxs.push(await fromWallet.signTransaction(tx));
163
+ }
164
+ return signedTxs;
165
+ }
166
+ /**
167
+ * 构建 BNB 多跳转账链(为 ERC20 中间钱包预留 gas)
168
+ */
169
+ async function buildBNBHopChainForERC20(payer, path, finalGasAmount, gasPrice, chainId, txType, payerNonce) {
170
+ const signedTxs = [];
171
+ const hopCount = path.hopWallets.length;
172
+ if (hopCount === 0) {
173
+ // 无多跳时不需要转 gas
174
+ return signedTxs;
175
+ }
176
+ const hopGasCost = NATIVE_TRANSFER_GAS_LIMIT * gasPrice;
177
+ const erc20GasCost = ERC20_TRANSFER_GAS_LIMIT_HOP * gasPrice;
178
+ // 每个中间钱包需要: BNB 转发 gas + ERC20 转发 gas
179
+ const gasPerHop = hopGasCost + erc20GasCost * 2n; // 2倍安全系数
180
+ // 计算每跳需要的金额
181
+ const amountsPerHop = [];
182
+ for (let i = 0; i < hopCount; i++) {
183
+ const remainingHops = hopCount - i;
184
+ amountsPerHop.push(finalGasAmount + gasPerHop * BigInt(remainingHops));
185
+ }
186
+ // payer → hop1
187
+ const firstTx = {
188
+ to: path.hopWallets[0].address,
189
+ value: amountsPerHop[0],
190
+ nonce: payerNonce,
191
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
192
+ chainId,
193
+ type: txType
194
+ };
195
+ if (txType === 2) {
196
+ firstTx.maxFeePerGas = gasPrice;
197
+ firstTx.maxPriorityFeePerGas = gasPrice / 10n || 1n;
198
+ }
199
+ else {
200
+ firstTx.gasPrice = gasPrice;
201
+ }
202
+ signedTxs.push(await payer.signTransaction(firstTx));
203
+ // hop1 → hop2 → ... → target (nonce=0)
204
+ for (let i = 0; i < hopCount; i++) {
205
+ const fromWallet = path.hopWallets[i];
206
+ const toAddress = i === hopCount - 1 ? path.targetAddress : path.hopWallets[i + 1].address;
207
+ const amount = i === hopCount - 1 ? finalGasAmount : amountsPerHop[i + 1];
208
+ const tx = {
209
+ to: toAddress,
210
+ value: amount,
211
+ nonce: 0,
212
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
213
+ chainId,
214
+ type: txType
215
+ };
216
+ if (txType === 2) {
217
+ tx.maxFeePerGas = gasPrice;
218
+ tx.maxPriorityFeePerGas = gasPrice / 10n || 1n;
219
+ }
220
+ else {
221
+ tx.gasPrice = gasPrice;
222
+ }
223
+ signedTxs.push(await fromWallet.signTransaction(tx));
224
+ }
225
+ return signedTxs;
226
+ }
1
227
  // ==================== 工具函数 ====================
2
228
  function createPancakeContext(config) {
3
229
  const chainId = config.chainId ?? 56;
@@ -302,7 +528,8 @@ import { calculateSellAmount } from '../utils/swap-helpers.js';
302
528
  import { NonceManager, getDeadline, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../utils/bundle-helpers.js';
303
529
  import { ADDRESSES, PROFIT_CONFIG, BLOCKRAZOR_BUILDER_EOA } from '../utils/constants.js';
304
530
  import { quoteV2, quoteV3 } from '../utils/quote-helpers.js';
305
- import { V2_ROUTER_ABI, V3_ROUTER02_ABI, ERC20_BALANCE_ABI } from '../abis/common.js';
531
+ import { V2_ROUTER_ABI, V3_ROUTER02_ABI, ERC20_BALANCE_ABI, ERC20_ABI } from '../abis/common.js';
532
+ import { generateWallets } from '../utils/wallet.js';
306
533
  /**
307
534
  * 获取 Gas Limit
308
535
  */
@@ -788,32 +1015,49 @@ export async function pancakeBatchSwapMerkle(params) {
788
1015
  /**
789
1016
  * PancakeSwap 快捷批量换手(资金自动流转)
790
1017
  *
791
- * 流程:[贿赂] → [卖出] → [转账1, 转账2, ...] → [买入1, 买入2, ...] → [利润]
1018
+ * 流程:[贿赂] → [卖出] → [转账多跳...] → [买入1, 买入2, ...] → [利润]
792
1019
  *
793
1020
  * 特点:
794
1021
  * - 子钱包不需要预先有余额
795
1022
  * - 资金来自主钱包卖出代币所得
796
1023
  * - 提升资金利用率
797
1024
  * - 支持 BNB 和 ERC20(如 USDT)两种模式
1025
+ * - ✅ 支持转账多跳,隐藏资金流向
798
1026
  *
799
- * 限制:最多 23 个买方(转账 + 买入 = 46 笔,加上贿赂/卖出/利润 = 50 笔限制)
1027
+ * 限制:根据多跳数动态计算最大买方数量
800
1028
  */
801
1029
  export async function pancakeQuickBatchSwapMerkle(params) {
802
- const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerRatios, buyerAmounts, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, startNonces // ✅ 可选:前端预获取的 nonces
1030
+ const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerRatios, buyerAmounts, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, disperseHopCount = 0, // ✅ 转账多跳数(默认0=直接转账)
1031
+ startNonces // ✅ 可选:前端预获取的 nonces
803
1032
  } = params;
804
1033
  // ✅ 判断是否使用原生代币
805
1034
  const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
806
1035
  const WBNB = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c'.toLowerCase();
807
- // ✅ 校验买方数量(子钱包已预留 BNB,不需要主钱包转 Gas)
808
- // BNB 模式:贿赂(1) + 卖出(1) + 转账(N) + 买入(N) + 利润(1) ≤ 50 → 2N + 3 ≤ 50 → N ≤ 23
809
- // ERC20 模式:贿赂(1) + 卖出(1) + ERC20转账(N) + 买入(N) + 利润(1) ≤ 50 → 2N + 3 ≤ 50 → N ≤ 23
810
- const MAX_BUYERS = 23;
1036
+ // ✅ 动态计算最大买方数量(根据多跳数)
1037
+ // 固定开销: 贿赂(1) + 卖出(1) + 利润多跳(PROFIT_HOP_COUNT + 1)
1038
+ // BNB 模式(无多跳): 转账(N) + 买入(N) = 2N
1039
+ // BNB 模式(有多跳H): 转账(N*(H+1)) + 买入(N) = N*(H+2)
1040
+ // ERC20 模式(无多跳): 转账(N) + 买入(N) = 2N
1041
+ // ERC20 模式(有多跳H): BNB转账(N*(H+1)) + ERC20转账(N*(H+1)) + 买入(N) = N*(2H+3)
1042
+ const fixedOverhead = 1 + 1 + PROFIT_HOP_COUNT + 1; // 贿赂 + 卖出 + 利润多跳
1043
+ const maxTxs = 50 - fixedOverhead;
1044
+ let MAX_BUYERS;
1045
+ if (useNativeToken) {
1046
+ // BNB 模式: N*(H+2) <= maxTxs => N <= maxTxs / (H+2)
1047
+ MAX_BUYERS = Math.floor(maxTxs / (disperseHopCount + 2));
1048
+ }
1049
+ else {
1050
+ // ERC20 模式: N*(2H+3) <= maxTxs => N <= maxTxs / (2H+3)
1051
+ MAX_BUYERS = Math.floor(maxTxs / (2 * disperseHopCount + 3));
1052
+ }
1053
+ MAX_BUYERS = Math.max(1, MAX_BUYERS); // 至少1个
1054
+ console.log(`[pancakeQuickBatchSwapMerkle] 多跳数: ${disperseHopCount}, 最大买方数: ${MAX_BUYERS}`);
811
1055
  if (buyerPrivateKeys.length === 0) {
812
1056
  throw new Error('至少需要一个买方钱包');
813
1057
  }
814
1058
  if (buyerPrivateKeys.length > MAX_BUYERS) {
815
1059
  const mode = useNativeToken ? 'BNB' : 'ERC20';
816
- throw new Error(`资金利用率模式(${mode})买方钱包数量超过限制: ${buyerPrivateKeys.length} > ${MAX_BUYERS}`);
1060
+ throw new Error(`资金利用率模式(${mode}, ${disperseHopCount}跳)买方钱包数量超过限制: ${buyerPrivateKeys.length} > ${MAX_BUYERS}`);
817
1061
  }
818
1062
  // ✅ 校验分配模式
819
1063
  if (!buyerRatios && !buyerAmounts) {
@@ -1020,50 +1264,89 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1020
1264
  type: txType
1021
1265
  });
1022
1266
  console.log(`[pancakeQuickBatchSwapMerkle] 卖出交易已签名`);
1023
- // ==================== 3. 转账交易(并行签名)====================
1267
+ // ==================== 3. 转账交易(支持多跳)====================
1024
1268
  const buyerGasCost = gasPrice * finalGasLimit;
1025
- // ✅ 预分配 nonce,然后并行签名
1026
- const transferNonces = buyers.map((_, i) => sellerNonce + i);
1027
- sellerNonce += buyers.length; // 更新 sellerNonce
1028
- let transferTxs;
1029
- if (useNativeToken) {
1030
- // ✅ 原生代币模式:直接 BNB 转账(并行签名)
1031
- transferTxs = await Promise.all(buyers.map((buyer, i) => {
1032
- const transferValue = transferAmountsWei[i] + FLAT_FEE + buyerGasCost;
1033
- return seller.signTransaction({
1034
- to: buyer.address,
1035
- value: transferValue,
1036
- nonce: transferNonces[i],
1037
- gasPrice,
1038
- gasLimit: 21000n,
1039
- chainId: context.chainId,
1040
- type: txType
1041
- });
1042
- }));
1269
+ // ✅ 生成多跳路径
1270
+ const hopPaths = generateDisperseHopPaths(buyers.map(b => b.address), disperseHopCount, context.provider);
1271
+ // 收集所有中间钱包信息
1272
+ const allHopWallets = [];
1273
+ hopPaths.forEach(path => {
1274
+ allHopWallets.push(...path.hopWalletsInfo);
1275
+ });
1276
+ let transferTxs = [];
1277
+ if (disperseHopCount === 0) {
1278
+ // ✅ 无多跳:直接转账
1279
+ const transferNonces = buyers.map((_, i) => sellerNonce + i);
1280
+ sellerNonce += buyers.length;
1281
+ if (useNativeToken) {
1282
+ transferTxs = await Promise.all(buyers.map((buyer, i) => {
1283
+ const transferValue = transferAmountsWei[i] + FLAT_FEE + buyerGasCost;
1284
+ return seller.signTransaction({
1285
+ to: buyer.address,
1286
+ value: transferValue,
1287
+ nonce: transferNonces[i],
1288
+ gasPrice,
1289
+ gasLimit: NATIVE_TRANSFER_GAS_LIMIT,
1290
+ chainId: context.chainId,
1291
+ type: txType
1292
+ });
1293
+ }));
1294
+ }
1295
+ else {
1296
+ const erc20Interface = new ethers.Interface(ERC20_ABI);
1297
+ transferTxs = await Promise.all(buyers.map((buyer, i) => {
1298
+ const transferData = erc20Interface.encodeFunctionData('transfer', [
1299
+ buyer.address,
1300
+ transferAmountsWei[i]
1301
+ ]);
1302
+ return seller.signTransaction({
1303
+ to: quoteToken,
1304
+ data: transferData,
1305
+ value: 0n,
1306
+ nonce: transferNonces[i],
1307
+ gasPrice,
1308
+ gasLimit: ERC20_TRANSFER_GAS,
1309
+ chainId: context.chainId,
1310
+ type: txType
1311
+ });
1312
+ }));
1313
+ }
1043
1314
  }
1044
1315
  else {
1045
- // ✅ ERC20 模式:ERC20 transfer(并行签名)
1046
- const erc20Interface = new ethers.Interface([
1047
- 'function transfer(address to, uint256 amount) returns (bool)'
1048
- ]);
1049
- transferTxs = await Promise.all(buyers.map((buyer, i) => {
1050
- const transferData = erc20Interface.encodeFunctionData('transfer', [
1051
- buyer.address,
1052
- transferAmountsWei[i]
1053
- ]);
1054
- return seller.signTransaction({
1055
- to: quoteToken,
1056
- data: transferData,
1057
- value: 0n,
1058
- nonce: transferNonces[i],
1059
- gasPrice,
1060
- gasLimit: ERC20_TRANSFER_GAS,
1061
- chainId: context.chainId,
1062
- type: txType
1063
- });
1064
- }));
1316
+ // ✅ 有多跳:构建多跳转账链
1317
+ if (useNativeToken) {
1318
+ // BNB 多跳转账
1319
+ const hopChains = await Promise.all(hopPaths.map((path, i) => {
1320
+ const finalAmount = transferAmountsWei[i] + FLAT_FEE + buyerGasCost;
1321
+ const payerNonce = sellerNonce + i * (disperseHopCount + 1);
1322
+ return buildNativeHopChain(seller, path, finalAmount, gasPrice, context.chainId, txType, payerNonce);
1323
+ }));
1324
+ transferTxs = hopChains.flat();
1325
+ sellerNonce += buyers.length * (disperseHopCount + 1);
1326
+ }
1327
+ else {
1328
+ // ERC20 多跳转账:先转 BNB(给中间钱包 gas),再转 ERC20
1329
+ // 每个 buyer 需要 (H+1) 笔 BNB 转账 + (H+1) 笔 ERC20 转账
1330
+ // 1. 构建 BNB 多跳链(为中间钱包和最终钱包预留 gas)
1331
+ const bnbHopChains = await Promise.all(hopPaths.map((path, i) => {
1332
+ // 最终钱包需要的 gas(用于买入交易)
1333
+ const finalGasAmount = buyerGasCost;
1334
+ const payerNonce = sellerNonce + i * (disperseHopCount + 1);
1335
+ return buildBNBHopChainForERC20(seller, path, finalGasAmount, gasPrice, context.chainId, txType, payerNonce);
1336
+ }));
1337
+ const bnbTxs = bnbHopChains.flat();
1338
+ sellerNonce += buyers.length * (disperseHopCount + 1);
1339
+ // 2. 构建 ERC20 多跳链
1340
+ const erc20HopChains = await Promise.all(hopPaths.map((path, i) => {
1341
+ const payerNonce = sellerNonce + i * (disperseHopCount + 1);
1342
+ return buildERC20HopChain(seller, path, quoteToken, transferAmountsWei[i], gasPrice, context.chainId, txType, payerNonce);
1343
+ }));
1344
+ const erc20Txs = erc20HopChains.flat();
1345
+ sellerNonce += buyers.length * (disperseHopCount + 1);
1346
+ transferTxs = [...bnbTxs, ...erc20Txs];
1347
+ }
1065
1348
  }
1066
- console.log(`[pancakeQuickBatchSwapMerkle] ${transferTxs.length} 笔转账交易已签名`);
1349
+ console.log(`[pancakeQuickBatchSwapMerkle] ${transferTxs.length} 笔转账交易已签名 (多跳数=${disperseHopCount})`);
1067
1350
  // ==================== 4. 买入交易 ====================
1068
1351
  // ✅ 如果前端传入了 startNonces,使用 buyer 部分(从索引 1 开始)
1069
1352
  const buyerNonces = startNonces && startNonces.length > 1
@@ -1150,6 +1433,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1150
1433
  const outputUnit = useNativeToken ? 'BNB' : 'ERC20';
1151
1434
  return {
1152
1435
  signedTransactions,
1436
+ disperseHopWallets: allHopWallets.length > 0 ? allHopWallets : undefined, // ✅ 返回中间钱包信息
1153
1437
  metadata: {
1154
1438
  sellerAddress: seller.address,
1155
1439
  buyerAddresses: buyers.map(b => b.address),
@@ -1161,7 +1445,8 @@ export async function pancakeQuickBatchSwapMerkle(params) {
1161
1445
  ? ethers.formatEther(amt)
1162
1446
  : ethers.formatUnits(amt, quoteTokenDecimals)),
1163
1447
  profitAmount: profitAmount > 0n ? ethers.formatEther(profitAmount) : undefined,
1164
- useNativeToken
1448
+ useNativeToken,
1449
+ disperseHopCount: disperseHopCount > 0 ? disperseHopCount : undefined // ✅ 返回多跳数
1165
1450
  }
1166
1451
  };
1167
1452
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.4.56",
3
+ "version": "1.4.57",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",