four-flap-meme-sdk 1.4.21 → 1.4.23

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.
@@ -31,6 +31,7 @@ export interface FourBundleSwapSignParams {
31
31
  buyerPrivateKey: string;
32
32
  tokenAddress: string;
33
33
  config: FourSwapSignConfig;
34
+ startNonces?: number[];
34
35
  }
35
36
  export interface FourBundleSwapParams {
36
37
  sellerPrivateKey: string;
@@ -69,6 +70,7 @@ export interface FourBatchSwapSignParams {
69
70
  buyerRatios?: number[];
70
71
  tokenAddress: string;
71
72
  config: FourSwapSignConfig;
73
+ startNonces?: number[];
72
74
  }
73
75
  /**
74
76
  * Four 批量换手结果
@@ -103,6 +105,7 @@ export interface FourQuickBatchSwapSignParams {
103
105
  buyerAmounts?: string[];
104
106
  tokenAddress: string;
105
107
  config: FourSwapSignConfig;
108
+ startNonces?: number[];
106
109
  }
107
110
  /**
108
111
  * Four 快捷批量换手结果
@@ -15,7 +15,8 @@ const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
15
15
  * Four内盘捆绑换手
16
16
  */
17
17
  export async function fourBundleSwapMerkle(params) {
18
- const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKey, tokenAddress, config } = params;
18
+ const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKey, tokenAddress, config, startNonces // ✅ 可选:前端预获取的 nonces
19
+ } = params;
19
20
  const chainIdNum = config.chainId ?? 56;
20
21
  const provider = new ethers.JsonRpcProvider(config.rpcUrl, {
21
22
  chainId: chainIdNum,
@@ -83,21 +84,21 @@ export async function fourBundleSwapMerkle(params) {
83
84
  if (extractProfit)
84
85
  sellerNonceCount++; // 利润交易
85
86
  // ✅ 优化:使用批量 nonce 获取(JSON-RPC 批量请求)
86
- // 先一次性获取 seller 和 buyer 的初始 nonce,然后分配连续 nonce
87
+ // 如果前端传入了 startNonces,直接使用;否则从链上获取
87
88
  const [sellUnsigned, buyUnsigned, noncesResult] = await Promise.all([
88
89
  tmSeller.sellToken.populateTransaction(0n, tokenAddress, sellAmountWei, 0n),
89
90
  tmBuyer.buyTokenAMAP.populateTransaction(0n, tokenAddress, buyer.address, buyerFunds, 0n, { value: buyerFunds }),
90
91
  (async () => {
91
- // ✅ 一次性获取两个地址的初始 nonce(单次网络往返)
92
+ // ✅ 如果前端传入了 startNonces,直接使用(性能优化)
93
+ if (startNonces && startNonces.length >= 2) {
94
+ const sellerNonces = Array.from({ length: sellerNonceCount }, (_, i) => startNonces[0] + i);
95
+ const buyerNonce = startNonces[1];
96
+ return { sellerNonces, buyerNonce };
97
+ }
98
+ // 否则从链上获取
92
99
  const initialNonces = await nonceManager.getNextNoncesForWallets([seller, buyer]);
93
- // seller 需要 sellerNonceCount 个连续 nonce
94
100
  const sellerNonces = Array.from({ length: sellerNonceCount }, (_, i) => initialNonces[0] + i);
95
- // buyer 只需要 1 个 nonce
96
101
  const buyerNonce = initialNonces[1];
97
- // 更新 NonceManager 缓存(seller 需要额外的 nonce)
98
- for (let i = 1; i < sellerNonceCount; i++) {
99
- await nonceManager.getNextNonce(seller); // 递增缓存
100
- }
101
102
  return { sellerNonces, buyerNonce };
102
103
  })()
103
104
  ]);
@@ -213,7 +214,8 @@ export async function fourBundleSwapMerkle(params) {
213
214
  * 限制:最多 24 个买方(服务器限制 25 笔交易,包含 1 笔利润交易)
214
215
  */
215
216
  export async function fourBatchSwapMerkle(params) {
216
- const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, tokenAddress, config } = params;
217
+ const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, tokenAddress, config, startNonces // ✅ 可选:前端预获取的 nonces
218
+ } = params;
217
219
  // ✅ 校验买方数量(最多 24 个)
218
220
  const MAX_BUYERS = 24;
219
221
  if (buyerPrivateKeys.length === 0) {
@@ -309,9 +311,12 @@ export async function fourBatchSwapMerkle(params) {
309
311
  if (needApproval)
310
312
  sellerNonceCount++; // 授权交易
311
313
  sellerNonceCount++; // 利润交易
312
- // 并行获取所有初始 nonce
314
+ // 如果前端传入了 startNonces,直接使用(性能优化)
315
+ // 否则从链上获取
313
316
  const allWallets = [seller, ...buyers];
314
- const initialNonces = await nonceManager.getNextNoncesForWallets(allWallets);
317
+ const initialNonces = startNonces && startNonces.length >= allWallets.length
318
+ ? startNonces
319
+ : await nonceManager.getNextNoncesForWallets(allWallets);
315
320
  // 分配 seller nonces
316
321
  const sellerNonces = Array.from({ length: sellerNonceCount }, (_, i) => initialNonces[0] + i);
317
322
  let idx = 0;
@@ -438,7 +443,8 @@ export async function fourBatchSwapMerkle(params) {
438
443
  * 限制:最多 23 个买方(2N + 3 ≤ 50)
439
444
  */
440
445
  export async function fourQuickBatchSwapMerkle(params) {
441
- const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerRatios, buyerAmounts, tokenAddress, config } = params;
446
+ const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerRatios, buyerAmounts, tokenAddress, config, startNonces // ✅ 可选:前端预获取的 nonces
447
+ } = params;
442
448
  // ✅ 校验买方数量
443
449
  // 贿赂(1) + 卖出(1) + 转账(N) + 买入(N) + 利润(1) ≤ 50 → 2N + 3 ≤ 50 → N ≤ 23
444
450
  const MAX_BUYERS = 23;
@@ -525,7 +531,10 @@ export async function fourQuickBatchSwapMerkle(params) {
525
531
  throw new Error(`主钱包 BNB 余额不足: 需要约 ${ethers.formatEther(sellerRequired)} BNB (贿赂: ${ethers.formatEther(bribeAmount)}, Gas: ${ethers.formatEther(sellerGasCost)}), 实际 ${ethers.formatEther(sellerBalance)} BNB`);
526
532
  }
527
533
  // ==================== 规划 Nonce ====================
528
- let sellerNonce = await nonceManager.getNextNonce(seller);
534
+ // 如果前端传入了 startNonces,直接使用(性能优化)
535
+ let sellerNonce = startNonces && startNonces.length > 0
536
+ ? startNonces[0]
537
+ : await nonceManager.getNextNonce(seller);
529
538
  // ==================== 1. 贿赂交易 ====================
530
539
  let bribeTx = null;
531
540
  if (bribeAmount > 0n) {
@@ -573,7 +582,10 @@ export async function fourQuickBatchSwapMerkle(params) {
573
582
  }));
574
583
  console.log(`[fourQuickBatchSwapMerkle] ${transferTxs.length} 笔转账交易已签名`);
575
584
  // ==================== 4. 买入交易 ====================
576
- const buyerNonces = await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
585
+ // 如果前端传入了 startNonces,使用 buyer 部分(从索引 1 开始)
586
+ const buyerNonces = startNonces && startNonces.length > 1
587
+ ? startNonces.slice(1)
588
+ : await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
577
589
  const signedBuys = await Promise.all(buyers.map(async (buyer, i) => {
578
590
  const buyAmount = transferAmountsWei[i];
579
591
  const tmBuyer = new Contract(TM_ADDRESS, TM_ABI, buyer);
@@ -38,6 +38,7 @@ export interface FlapBundleSwapSignParams {
38
38
  config: FlapSwapSignConfig;
39
39
  quoteToken?: string;
40
40
  quoteTokenDecimals?: number;
41
+ startNonces?: number[];
41
42
  }
42
43
  export interface FlapBundleSwapParams {
43
44
  chain: FlapChain;
@@ -79,6 +80,7 @@ export interface FlapBatchSwapSignParams {
79
80
  config: FlapSwapSignConfig;
80
81
  quoteToken?: string;
81
82
  quoteTokenDecimals?: number;
83
+ startNonces?: number[];
82
84
  }
83
85
  /**
84
86
  * Flap 批量换手结果
@@ -116,6 +118,7 @@ export interface FlapQuickBatchSwapSignParams {
116
118
  config: FlapSwapSignConfig;
117
119
  quoteToken?: string;
118
120
  quoteTokenDecimals?: number;
121
+ startNonces?: number[];
119
122
  }
120
123
  /**
121
124
  * Flap 快捷批量换手结果
@@ -99,7 +99,8 @@ function getNativeTokenName(chain) {
99
99
  * ✅ 支持 quoteToken:传入 USDT 等地址时,卖出得到该代币,买入使用该代币
100
100
  */
101
101
  export async function flapBundleSwapMerkle(params) {
102
- const { chain, sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKey, tokenAddress, config, quoteToken, quoteTokenDecimals } = params;
102
+ const { chain, sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKey, tokenAddress, config, quoteToken, quoteTokenDecimals, startNonces // ✅ 可选:前端预获取的 nonces
103
+ } = params;
103
104
  const chainContext = createChainContext(chain, config);
104
105
  const seller = new Wallet(sellerPrivateKey, chainContext.provider);
105
106
  const buyer = new Wallet(buyerPrivateKey, chainContext.provider);
@@ -179,14 +180,17 @@ export async function flapBundleSwapMerkle(params) {
179
180
  permitData: '0x'
180
181
  }, useNativeToken ? { value: buyerNeed.maxBuyerValue } : {} // ✅ ERC20 购买时 value=0
181
182
  ),
182
- planNonces({
183
- seller,
184
- buyer,
185
- approvalExists: !!approvalTx,
186
- extractProfit: nativeProfitAmount > 0n,
187
- needBribeTx, // ✅ 新增:是否需要贿赂交易
188
- nonceManager
189
- }),
183
+ // ✅ 如果前端传入了 startNonces,直接使用(性能优化)
184
+ startNonces && startNonces.length >= 2
185
+ ? buildNoncePlan(startNonces, !!approvalTx, nativeProfitAmount > 0n, needBribeTx)
186
+ : planNonces({
187
+ seller,
188
+ buyer,
189
+ approvalExists: !!approvalTx,
190
+ extractProfit: nativeProfitAmount > 0n,
191
+ needBribeTx,
192
+ nonceManager
193
+ }),
190
194
  validateBalances({
191
195
  buyerNeed,
192
196
  buyerAddress: buyer.address,
@@ -393,6 +397,24 @@ async function validateBalances({ buyerNeed, buyerAddress, portalGasCost, provid
393
397
  throw new Error(`卖方余额不足: 需要 ${ethers.formatEther(portalGasCost)} ${chainContext.nativeToken} (Gas),实际 ${ethers.formatEther(sellerBalance)} ${chainContext.nativeToken}`);
394
398
  }
395
399
  }
400
+ /**
401
+ * ✅ 从前端传入的 startNonces 构建 NoncePlan(用于性能优化)
402
+ * 顺序:[sellerBaseNonce, buyerNonce]
403
+ */
404
+ function buildNoncePlan(startNonces, approvalExists, extractProfit, needBribeTx) {
405
+ let sellerNonce = startNonces[0];
406
+ const buyerNonce = startNonces[1];
407
+ let bribeNonce;
408
+ let profitNonce;
409
+ if (needBribeTx)
410
+ bribeNonce = sellerNonce++;
411
+ if (approvalExists)
412
+ sellerNonce++; // 授权交易占用一个 nonce
413
+ const sellNonce = sellerNonce++;
414
+ if (extractProfit)
415
+ profitNonce = sellerNonce;
416
+ return { sellerNonce: sellNonce, buyerNonce, bribeNonce, profitNonce };
417
+ }
396
418
  /**
397
419
  * ✅ 优化:使用批量 nonce 获取(JSON-RPC 批量请求)
398
420
  * 交易顺序:贿赂 → 授权 → 卖出 → 买入 → 利润
@@ -470,7 +492,8 @@ function countTruthy(values) {
470
492
  * 限制:最多 24 个买方(服务器限制 25 笔交易,包含 1 笔利润交易)
471
493
  */
472
494
  export async function flapBatchSwapMerkle(params) {
473
- const { chain, sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, tokenAddress, config, quoteToken, quoteTokenDecimals = 18 } = params;
495
+ const { chain, sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, tokenAddress, config, quoteToken, quoteTokenDecimals = 18, startNonces // ✅ 可选:前端预获取的 nonces
496
+ } = params;
474
497
  // ✅ 校验买方数量(最多 24 个)
475
498
  const MAX_BUYERS = 24;
476
499
  if (buyerPrivateKeys.length === 0) {
@@ -581,9 +604,18 @@ export async function flapBatchSwapMerkle(params) {
581
604
  }, useNativeToken ? { value: buyAmount } : {});
582
605
  })
583
606
  ]);
584
- // ✅ 并行获取所有 nonce
585
- const sellNonce = await nonceManager.getNextNonce(seller);
586
- const buyerNonces = await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
607
+ // ✅ 并行获取所有 nonce(如果前端传入了 startNonces,直接使用)
608
+ const allWallets = [seller, ...buyers];
609
+ let sellNonce;
610
+ let buyerNonces;
611
+ if (startNonces && startNonces.length >= allWallets.length) {
612
+ sellNonce = startNonces[0];
613
+ buyerNonces = startNonces.slice(1);
614
+ }
615
+ else {
616
+ sellNonce = await nonceManager.getNextNonce(seller);
617
+ buyerNonces = await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
618
+ }
587
619
  // ✅ 贿赂交易和利润交易都由卖方发送(保持一致)
588
620
  const bribeAmount = getBribeAmount(config);
589
621
  let bribeTx = null;
@@ -682,7 +714,8 @@ export async function flapBatchSwapMerkle(params) {
682
714
  * 限制:最多 23 个买方(2N + 3 ≤ 50)
683
715
  */
684
716
  export async function flapQuickBatchSwapMerkle(params) {
685
- const { chain, sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerRatios, buyerAmounts, tokenAddress, config, quoteToken, quoteTokenDecimals = 18 } = params;
717
+ const { chain, sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerRatios, buyerAmounts, tokenAddress, config, quoteToken, quoteTokenDecimals = 18, startNonces // ✅ 可选:前端预获取的 nonces
718
+ } = params;
686
719
  // ✅ 校验买方数量
687
720
  // BNB 模式:贿赂(1) + 卖出(1) + 转账(N) + 买入(N) + 利润(1) ≤ 50 → 2N + 3 ≤ 50 → N ≤ 23
688
721
  // ERC20 模式:贿赂(1) + 卖出(1) + ERC20转账(N) + 买入(N) + 利润(1) ≤ 50 → 2N + 3 ≤ 50 → N ≤ 23
@@ -791,7 +824,10 @@ export async function flapQuickBatchSwapMerkle(params) {
791
824
  throw new Error(`主钱包 ${chainContext.nativeToken} 余额不足: 需要约 ${ethers.formatEther(sellerRequired)} (贿赂: ${ethers.formatEther(bribeAmount)}, Gas: ${ethers.formatEther(sellerGasCost)}), 实际 ${ethers.formatEther(sellerBalance)}`);
792
825
  }
793
826
  // ==================== 规划 Nonce ====================
794
- let sellerNonce = await nonceManager.getNextNonce(seller);
827
+ // 如果前端传入了 startNonces,直接使用(性能优化)
828
+ let sellerNonce = startNonces && startNonces.length > 0
829
+ ? startNonces[0]
830
+ : await nonceManager.getNextNonce(seller);
795
831
  // ==================== 1. 贿赂交易 ====================
796
832
  let bribeTx = null;
797
833
  if (bribeAmount > 0n) {
@@ -873,7 +909,10 @@ export async function flapQuickBatchSwapMerkle(params) {
873
909
  }
874
910
  console.log(`[flapQuickBatchSwapMerkle] ${transferTxs.length} 笔转账交易已签名`);
875
911
  // ==================== 4. 买入交易 ====================
876
- const buyerNonces = await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
912
+ // 如果前端传入了 startNonces,使用 buyer 部分(从索引 1 开始)
913
+ const buyerNonces = startNonces && startNonces.length > 1
914
+ ? startNonces.slice(1)
915
+ : await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
877
916
  const signedBuys = await Promise.all(buyers.map(async (buyer, i) => {
878
917
  const buyAmount = transferAmountsWei[i];
879
918
  const portalBuyer = new Contract(chainContext.portalAddress, PORTAL_ABI, buyer);
@@ -47,6 +47,7 @@ export interface PancakeBundleSwapSignParams {
47
47
  config: PancakeSwapSignConfig;
48
48
  quoteToken?: string;
49
49
  quoteTokenDecimals?: number;
50
+ startNonces?: number[];
50
51
  }
51
52
  export interface PancakeBundleSwapParams {
52
53
  sellerPrivateKey: string;
@@ -88,6 +89,7 @@ export interface PancakeBatchSwapSignParams {
88
89
  config: PancakeSwapSignConfig;
89
90
  quoteToken?: string;
90
91
  quoteTokenDecimals?: number;
92
+ startNonces?: number[];
91
93
  }
92
94
  /**
93
95
  * 批量换手结果
@@ -127,6 +129,7 @@ export interface PancakeQuickBatchSwapParams {
127
129
  config: PancakeSwapSignConfig;
128
130
  quoteToken?: string;
129
131
  quoteTokenDecimals?: number;
132
+ startNonces?: number[];
130
133
  }
131
134
  /**
132
135
  * 快捷批量换手结果
@@ -115,6 +115,30 @@ async function calculateBuyerBudget({ buyer, quotedBNBOut, reserveGasBNB, useNat
115
115
  return { buyerBalance, reserveGas, requiredBalance, buyAmountBNB, useNativeToken };
116
116
  }
117
117
  }
118
+ /**
119
+ * ✅ 从前端传入的 startNonces 构建 NoncePlan(用于性能优化)
120
+ * 顺序:[sellerBaseNonce, buyerNonce]
121
+ */
122
+ function buildNoncePlanFromNonces(startNonces, sameAddress, approvalExists, profitNeeded, needBribeTx) {
123
+ if (sameAddress) {
124
+ let idx = 0;
125
+ const bribeNonce = needBribeTx ? startNonces[0] + idx++ : undefined;
126
+ if (approvalExists)
127
+ idx++;
128
+ const sellerNonce = startNonces[0] + idx++;
129
+ const buyerNonce = startNonces[0] + idx++;
130
+ const profitNonce = profitNeeded ? startNonces[0] + idx : undefined;
131
+ return { sellerNonce, buyerNonce, bribeNonce, profitNonce };
132
+ }
133
+ let sellerIdx = 0;
134
+ const bribeNonce = needBribeTx ? startNonces[0] + sellerIdx++ : undefined;
135
+ if (approvalExists)
136
+ sellerIdx++;
137
+ const sellerNonce = startNonces[0] + sellerIdx++;
138
+ const profitNonce = profitNeeded ? startNonces[0] + sellerIdx : undefined;
139
+ const buyerNonce = startNonces[1];
140
+ return { sellerNonce, buyerNonce, bribeNonce, profitNonce };
141
+ }
118
142
  /**
119
143
  * ✅ 规划 nonce
120
144
  * 交易顺序:贿赂 → 授权 → 卖出 → 买入 → 利润
@@ -294,7 +318,8 @@ const ERC20_BALANCE_OF_ABI = ['function balanceOf(address) view returns (uint256
294
318
  * ✅ 支持 quoteToken:传入 USDT 等地址时,卖出得到该代币,买入使用该代币
295
319
  */
296
320
  export async function pancakeBundleSwapMerkle(params) {
297
- const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKey, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18 } = params;
321
+ const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKey, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, startNonces // ✅ 可选:前端预获取的 nonces
322
+ } = params;
298
323
  // ✅ 判断是否使用原生代币(BNB)或 ERC20 代币(如 USDT)
299
324
  const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
300
325
  const context = createPancakeContext(config);
@@ -358,15 +383,18 @@ export async function pancakeBundleSwapMerkle(params) {
358
383
  : 0n;
359
384
  const needBribeTx = bribeAmount > 0n;
360
385
  // ✅ 使用共享的 NonceManager 规划 nonce
361
- const noncePlan = await planNonces({
362
- seller,
363
- buyer,
364
- sameAddress,
365
- approvalExists: false, // ✅ 已移除授权
366
- profitNeeded: profitAmount > 0n,
367
- needBribeTx,
368
- nonceManager
369
- });
386
+ // 如果前端传入了 startNonces,直接使用(性能优化)
387
+ const noncePlan = startNonces && startNonces.length >= (sameAddress ? 1 : 2)
388
+ ? buildNoncePlanFromNonces(startNonces, sameAddress, false, profitAmount > 0n, needBribeTx)
389
+ : await planNonces({
390
+ seller,
391
+ buyer,
392
+ sameAddress,
393
+ approvalExists: false, // ✅ 已移除授权
394
+ profitNeeded: profitAmount > 0n,
395
+ needBribeTx,
396
+ nonceManager
397
+ });
370
398
  // ✅ 并行签名所有交易
371
399
  const signPromises = [];
372
400
  // 贿赂交易
@@ -462,7 +490,8 @@ export async function pancakeBundleSwapMerkle(params) {
462
490
  * 交易顺序:[授权(可选)] → [卖出] → [买入1, 买入2, ..., 买入N] → [利润]
463
491
  */
464
492
  export async function pancakeBatchSwapMerkle(params) {
465
- const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerAmounts, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18 } = params;
493
+ const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerAmounts, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, startNonces // ✅ 可选:前端预获取的 nonces
494
+ } = params;
466
495
  // ✅ 校验买方数量(最多 24 个)
467
496
  const MAX_BUYERS = 24;
468
497
  if (buyerPrivateKeys.length === 0) {
@@ -577,16 +606,26 @@ export async function pancakeBatchSwapMerkle(params) {
577
606
  ? ethers.parseEther(String(config.bribeAmount))
578
607
  : 0n;
579
608
  // ✅ 规划 Nonce(贿赂和利润都由卖方发送)
580
- // 卖方: [贿赂(可选)] → [授权(可选)] → [卖出] → [利润(可选)]
609
+ // 卖方: [贿赂(可选)] → [卖出] → [利润(可选)]
581
610
  let bribeNonce;
582
- let sellNonceOffset = 0;
583
- if (bribeAmount > 0n) {
584
- bribeNonce = await nonceManager.getNextNonce(seller);
585
- sellNonceOffset = 1; // 卖出交易 nonce 需要偏移
611
+ let sellNonce;
612
+ let buyerNonces;
613
+ // 如果前端传入了 startNonces,直接使用(性能优化)
614
+ if (startNonces && startNonces.length >= (1 + buyers.length)) {
615
+ let sellerIdx = 0;
616
+ if (bribeAmount > 0n) {
617
+ bribeNonce = startNonces[0] + sellerIdx++;
618
+ }
619
+ sellNonce = startNonces[0] + sellerIdx;
620
+ buyerNonces = startNonces.slice(1);
621
+ }
622
+ else {
623
+ if (bribeAmount > 0n) {
624
+ bribeNonce = await nonceManager.getNextNonce(seller);
625
+ }
626
+ sellNonce = await nonceManager.getNextNonce(seller);
627
+ buyerNonces = await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
586
628
  }
587
- const sellNonce = await nonceManager.getNextNonce(seller);
588
- // ✅ 并行获取所有买方的 nonce
589
- const buyerNonces = await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
590
629
  // ✅ 贿赂交易放在首位(由卖方发送)
591
630
  let bribeTx = null;
592
631
  if (bribeAmount > 0n && bribeNonce !== undefined) {
@@ -616,7 +655,10 @@ export async function pancakeBatchSwapMerkle(params) {
616
655
  let profitTx = null;
617
656
  if (profitAmount > 0n) {
618
657
  // ✅ 利润由卖方发送(与贿赂交易同一钱包)
619
- const profitNonce = await nonceManager.getNextNonce(seller);
658
+ // 如果使用 startNonces,利润 nonce = 卖出 nonce + 1
659
+ const profitNonce = startNonces && startNonces.length >= 1
660
+ ? sellNonce + 1
661
+ : await nonceManager.getNextNonce(seller);
620
662
  profitTx = await seller.signTransaction({
621
663
  to: PROFIT_CONFIG.RECIPIENT,
622
664
  value: profitAmount,
@@ -689,7 +731,8 @@ export async function pancakeBatchSwapMerkle(params) {
689
731
  * 限制:最多 23 个买方(转账 + 买入 = 46 笔,加上贿赂/卖出/利润 = 50 笔限制)
690
732
  */
691
733
  export async function pancakeQuickBatchSwapMerkle(params) {
692
- const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerRatios, buyerAmounts, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18 } = params;
734
+ const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerRatios, buyerAmounts, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, startNonces // ✅ 可选:前端预获取的 nonces
735
+ } = params;
693
736
  // ✅ 判断是否使用原生代币
694
737
  const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
695
738
  const WBNB = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c'.toLowerCase();
@@ -840,7 +883,10 @@ export async function pancakeQuickBatchSwapMerkle(params) {
840
883
  throw new Error(`主钱包 BNB 余额不足: 需要约 ${ethers.formatEther(sellerRequired)} BNB (贿赂: ${ethers.formatEther(bribeAmount)}, Gas: ${ethers.formatEther(sellerGasCost)}), 实际 ${ethers.formatEther(sellerBalance)} BNB`);
841
884
  }
842
885
  // ==================== 规划 Nonce ====================
843
- let sellerNonce = await nonceManager.getNextNonce(seller);
886
+ // 如果前端传入了 startNonces,直接使用(性能优化)
887
+ let sellerNonce = startNonces && startNonces.length > 0
888
+ ? startNonces[0]
889
+ : await nonceManager.getNextNonce(seller);
844
890
  const deadline = Math.floor(Date.now() / 1000) + 600;
845
891
  // ==================== 1. 贿赂交易 ====================
846
892
  let bribeTx = null;
@@ -926,7 +972,10 @@ export async function pancakeQuickBatchSwapMerkle(params) {
926
972
  }
927
973
  console.log(`[pancakeQuickBatchSwapMerkle] ${transferTxs.length} 笔转账交易已签名`);
928
974
  // ==================== 4. 买入交易 ====================
929
- const buyerNonces = await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
975
+ // 如果前端传入了 startNonces,使用 buyer 部分(从索引 1 开始)
976
+ const buyerNonces = startNonces && startNonces.length > 1
977
+ ? startNonces.slice(1)
978
+ : await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
930
979
  const signedBuys = await Promise.all(buyers.map(async (buyer, i) => {
931
980
  const buyAmount = transferAmountsWei[i];
932
981
  const proxyBuyer = new Contract(PANCAKE_PROXY_ADDRESS, PANCAKE_PROXY_ABI, buyer);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.4.21",
3
+ "version": "1.4.23",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",