four-flap-meme-sdk 1.3.39 → 1.3.41

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.
@@ -303,17 +303,25 @@ export async function fourPancakeProxyBatchBuyMerkle(params) {
303
303
  const actualAmountsWei = remainingAmounts; // 扣除利润后用于购买的金额
304
304
  const finalGasLimit = getGasLimit(config);
305
305
  const nonceManager = new NonceManager(provider);
306
- // ✅ 优化:并行获取 gasPrice、tokenDecimalsnonces(JSON-RPC 批量请求)
307
- const [gasPrice, tokenDecimals, nonces] = await Promise.all([
306
+ // ✅ 优化:并行获取 gasPrice 和 tokenDecimals
307
+ const [gasPrice, tokenDecimals] = await Promise.all([
308
308
  getOptimizedGasPrice(provider, getGasPriceConfig(config)),
309
- getTokenDecimals(tokenAddress, provider),
310
- nonceManager.getNextNoncesForWallets(buyers) // ✅ 批量获取 nonce
309
+ getTokenDecimals(tokenAddress, provider)
311
310
  ]);
312
- // ✅ 如果需要利润转账,预先获取 nonce
313
- let profitNonce;
314
- if (extractProfit && totalProfit > 0n) {
315
- profitNonce = await nonceManager.getNextNonce(buyers[0]);
316
- }
311
+ // ✅ 修复:先计算需要的 nonce 数量,再统一获取
312
+ // buyers[0] 可能需要 2 个 nonce(买入 + 利润转账)
313
+ const needProfitTx = extractProfit && totalProfit > 0n;
314
+ const buyer0NeedCount = needProfitTx ? 2 : 1;
315
+ // 获取 buyers[0] 的连续 nonces
316
+ const buyer0Nonces = await nonceManager.getNextNonceBatch(buyers[0], buyer0NeedCount);
317
+ // 获取其他 buyers 的 nonces(如果有)
318
+ let otherNonces = [];
319
+ if (buyers.length > 1) {
320
+ otherNonces = await nonceManager.getNextNoncesForWallets(buyers.slice(1));
321
+ }
322
+ // 组装最终的 nonces 数组
323
+ const nonces = [buyer0Nonces[0], ...otherNonces];
324
+ const profitNonce = needProfitTx ? buyer0Nonces[1] : undefined;
317
325
  // 计算 minOutputAmounts
318
326
  let minOuts;
319
327
  if (params.minOutputAmounts && params.minOutputAmounts.length === buyers.length) {
@@ -401,12 +409,11 @@ export async function fourPancakeProxyBatchSellMerkle(params) {
401
409
  const finalGasLimit = getGasLimit(config);
402
410
  const nonceManager = new NonceManager(provider);
403
411
  const extractProfit = shouldExtractProfit(config);
404
- // ✅ 优化:并行获取 gasPrice、tokenDecimals、allowancesnonces(JSON-RPC 批量请求)
405
- const [gasPrice, tokenDecimals, allowances, nonces] = await Promise.all([
412
+ // ✅ 优化:并行获取 gasPrice、tokenDecimals 和 allowances
413
+ const [gasPrice, tokenDecimals, allowances] = await Promise.all([
406
414
  getOptimizedGasPrice(provider, getGasPriceConfig(config)),
407
415
  getTokenDecimals(tokenAddress, provider),
408
- batchCheckAllowances(provider, tokenAddress, sellers.map(w => w.address), pancakeProxyAddress),
409
- nonceManager.getNextNoncesForWallets(sellers) // ✅ 批量获取 nonce
416
+ batchCheckAllowances(provider, tokenAddress, sellers.map(w => w.address), pancakeProxyAddress)
410
417
  ]);
411
418
  const amountsWei = sellAmounts.map(a => ethers.parseUnits(a, tokenDecimals));
412
419
  // 找出需要授权的钱包索引
@@ -464,7 +471,7 @@ export async function fourPancakeProxyBatchSellMerkle(params) {
464
471
  // ✅ minOuts = 0,不设置滑点限制(大额交易更稳定)
465
472
  minOuts = quotedOutputs.map(() => 0n);
466
473
  }
467
- // ✅ 计算利润并找出收益最多的钱包(提前计算,预先获取 nonce)
474
+ // ✅ 计算利润并找出收益最多的钱包
468
475
  let totalProfit = 0n;
469
476
  let maxRevenueIndex = 0;
470
477
  let maxRevenue = 0n;
@@ -480,10 +487,35 @@ export async function fourPancakeProxyBatchSellMerkle(params) {
480
487
  }
481
488
  }
482
489
  }
483
- // ✅ 如果需要利润转账,预先获取 nonce
490
+ // ✅ 修复:先计算需要的 nonce 数量,再统一获取
491
+ const needProfitTx = extractProfit && totalProfit > 0n && maxRevenue > 0n;
492
+ // 分配 nonces:收益最多的钱包可能需要 2 个 nonce(卖出 + 利润转账)
493
+ let nonces;
484
494
  let profitNonce;
485
- if (extractProfit && totalProfit > 0n && maxRevenue > 0n) {
486
- profitNonce = await nonceManager.getNextNonce(sellers[maxRevenueIndex]);
495
+ if (needProfitTx) {
496
+ // 收益最多的钱包需要 2 个连续 nonce
497
+ const maxRevenueNonces = await nonceManager.getNextNonceBatch(sellers[maxRevenueIndex], 2);
498
+ // 其他钱包各需要 1 个 nonce
499
+ const otherSellers = sellers.filter((_, i) => i !== maxRevenueIndex);
500
+ const otherNonces = otherSellers.length > 0
501
+ ? await nonceManager.getNextNoncesForWallets(otherSellers)
502
+ : [];
503
+ // 组装最终的 nonces 数组(保持原顺序)
504
+ nonces = [];
505
+ let otherIdx = 0;
506
+ for (let i = 0; i < sellers.length; i++) {
507
+ if (i === maxRevenueIndex) {
508
+ nonces.push(maxRevenueNonces[0]); // 卖出交易用第一个 nonce
509
+ }
510
+ else {
511
+ nonces.push(otherNonces[otherIdx++]);
512
+ }
513
+ }
514
+ profitNonce = maxRevenueNonces[1]; // 利润交易用第二个 nonce
515
+ }
516
+ else {
517
+ // 不需要利润交易,所有钱包各 1 个 nonce
518
+ nonces = await nonceManager.getNextNoncesForWallets(sellers);
487
519
  }
488
520
  // 卖出不需要发送 BNB,只需要 flatFee
489
521
  const needBNB = false;
@@ -79,6 +79,19 @@ const V2_ROUTER_ABI = [
79
79
  // 报价
80
80
  'function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts)',
81
81
  ];
82
+ /**
83
+ * SwapRouter02 的 V2 方法 ABI (PotatoSwap, PancakeSwap V3 Router)
84
+ * SwapRouter02 同时支持 V2 和 V3,V2 方法通过 multicall 调用
85
+ */
86
+ const SWAP_ROUTER02_V2_ABI = [
87
+ // V2 交换方法 (SwapRouter02 内置)
88
+ 'function swapExactTokensForTokens(uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to) external payable returns (uint256 amountOut)',
89
+ // Multicall
90
+ 'function multicall(uint256 deadline, bytes[] calldata data) external payable returns (bytes[] memory results)',
91
+ // 辅助方法
92
+ 'function refundETH() external payable',
93
+ 'function unwrapWETH9(uint256 amountMinimum, address recipient) external payable',
94
+ ];
82
95
  /**
83
96
  * V3 SwapRouter02 ABI (PancakeSwap V3, 新版 Uniswap)
84
97
  * - exactInputSingle: 不含 deadline(deadline 通过 multicall 传递)
@@ -228,6 +241,23 @@ async function buildProfitTransaction(wallet, profitAmountWei, nonce, gasPrice,
228
241
  // ============================================================================
229
242
  // V2 直接交易
230
243
  // ============================================================================
244
+ /**
245
+ * 判断是否是 SwapRouter02 (PotatoSwap, PancakeSwap V3 等)
246
+ * SwapRouter02 的 V2 方法签名不同,需要特殊处理
247
+ */
248
+ function isSwapRouter02(chain, routerAddress) {
249
+ const chainUpper = chain.toUpperCase();
250
+ const addrLower = routerAddress.toLowerCase();
251
+ // XLayer PotatoSwap SwapRouter02
252
+ if (chainUpper === 'XLAYER' && addrLower === DIRECT_ROUTERS.XLAYER.POTATOSWAP_V2.toLowerCase()) {
253
+ return true;
254
+ }
255
+ // BSC PancakeSwap V3 SwapRouter02
256
+ if (chainUpper === 'BSC' && addrLower === DIRECT_ROUTERS.BSC.PANCAKESWAP_V3.toLowerCase()) {
257
+ return true;
258
+ }
259
+ return false;
260
+ }
231
261
  /**
232
262
  * V2 批量买入(直接调用 Router)
233
263
  */
@@ -254,8 +284,12 @@ export async function directV2BatchBuy(params) {
254
284
  // 构建路径
255
285
  const inputToken = useNative ? wrappedNative : quoteToken;
256
286
  const path = [inputToken, tokenAddress];
257
- // 创建 Router 合约
258
- const routerIface = new ethers.Interface(V2_ROUTER_ABI);
287
+ // 判断是否是 SwapRouter02
288
+ const useSwapRouter02 = isSwapRouter02(chain, routerAddress);
289
+ // 创建 Router 合约接口
290
+ const routerIface = useSwapRouter02
291
+ ? new ethers.Interface(SWAP_ROUTER02_V2_ABI)
292
+ : new ethers.Interface(V2_ROUTER_ABI);
259
293
  const signedTxs = [];
260
294
  let totalFlowWei = 0n;
261
295
  for (let i = 0; i < wallets.length; i++) {
@@ -264,9 +298,24 @@ export async function directV2BatchBuy(params) {
264
298
  totalFlowWei += amountWei;
265
299
  let txData;
266
300
  let txValue;
267
- if (useNative) {
268
- // 原生币 Token
269
- // minOut = 0 (由于 MEV bundle 保护,可以设为 0;或根据滑点计算)
301
+ if (useSwapRouter02) {
302
+ // SwapRouter02 V2 方法:使用 multicall 包装
303
+ // SwapRouter02.swapExactTokensForTokens 不含 deadline,需要通过 multicall 传递
304
+ const swapData = routerIface.encodeFunctionData('swapExactTokensForTokens', [
305
+ amountWei,
306
+ 0n, // amountOutMin
307
+ path,
308
+ wallet.address,
309
+ ]);
310
+ // 使用 multicall 包装,传递 deadline
311
+ txData = routerIface.encodeFunctionData('multicall', [
312
+ deadline,
313
+ [swapData],
314
+ ]);
315
+ txValue = useNative ? amountWei : 0n;
316
+ }
317
+ else if (useNative) {
318
+ // 传统 V2 Router: 原生币 → Token
270
319
  txData = routerIface.encodeFunctionData('swapExactETHForTokensSupportingFeeOnTransferTokens', [
271
320
  0n, // amountOutMin
272
321
  path,
@@ -276,7 +325,7 @@ export async function directV2BatchBuy(params) {
276
325
  txValue = amountWei;
277
326
  }
278
327
  else {
279
- // ERC20 → Token (需要先授权)
328
+ // 传统 V2 Router: ERC20 → Token (需要先授权)
280
329
  txData = routerIface.encodeFunctionData('swapExactTokensForTokensSupportingFeeOnTransferTokens', [
281
330
  amountWei,
282
331
  0n, // amountOutMin
@@ -353,7 +402,11 @@ export async function directV2BatchSell(params) {
353
402
  // 构建路径
354
403
  const outputToken = useNativeOutput ? wrappedNative : quoteToken;
355
404
  const path = [tokenAddress, outputToken];
356
- const routerIface = new ethers.Interface(V2_ROUTER_ABI);
405
+ // 判断是否是 SwapRouter02
406
+ const useSwapRouter02 = isSwapRouter02(chain, routerAddress);
407
+ const routerIface = useSwapRouter02
408
+ ? new ethers.Interface(SWAP_ROUTER02_V2_ABI)
409
+ : new ethers.Interface(V2_ROUTER_ABI);
357
410
  const approveIface = new ethers.Interface(ERC20_ABI);
358
411
  const signedTxs = [];
359
412
  let totalOutputEstimate = 0n;
@@ -385,7 +438,20 @@ export async function directV2BatchSell(params) {
385
438
  }
386
439
  // 卖出交易
387
440
  let txData;
388
- if (useNativeOutput) {
441
+ if (useSwapRouter02) {
442
+ // ✅ SwapRouter02 V2 方法:使用 multicall 包装
443
+ const swapData = routerIface.encodeFunctionData('swapExactTokensForTokens', [
444
+ sellAmount,
445
+ 0n, // amountOutMin
446
+ path,
447
+ wallet.address,
448
+ ]);
449
+ txData = routerIface.encodeFunctionData('multicall', [
450
+ deadline,
451
+ [swapData],
452
+ ]);
453
+ }
454
+ else if (useNativeOutput) {
389
455
  txData = routerIface.encodeFunctionData('swapExactTokensForETHSupportingFeeOnTransferTokens', [
390
456
  sellAmount,
391
457
  0n,
@@ -354,8 +354,8 @@ export async function pancakeProxyBatchSellMerkle(params) {
354
354
  const finalGasLimit = getGasLimit(config);
355
355
  const extractProfit = shouldExtractProfit(config);
356
356
  const nonceManager = new NonceManager(provider);
357
- // ✅ 优化:第一批并行 - gasPrice、tokenDecimals、allowances、nonces(JSON-RPC 批量请求)
358
- const [gasPrice, tokenDecimals, , nonces] = await Promise.all([
357
+ // ✅ 优化:第一批并行 - gasPrice、tokenDecimals、allowances
358
+ const [gasPrice, tokenDecimals] = await Promise.all([
359
359
  getOptimizedGasPrice(provider, getGasPriceConfig(config)),
360
360
  getTokenDecimals(tokenAddress, provider),
361
361
  ensureAllowances({
@@ -363,8 +363,7 @@ export async function pancakeProxyBatchSellMerkle(params) {
363
363
  tokenAddress,
364
364
  owners: sellers.map(w => w.address),
365
365
  spender: ADDRESSES.BSC.PancakeProxy
366
- }),
367
- nonceManager.getNextNoncesForWallets(sellers) // ✅ 批量获取 nonce
366
+ })
368
367
  ]);
369
368
  const amountsWei = sellAmounts.map(amount => ethers.parseUnits(amount, tokenDecimals));
370
369
  // ✅ 优化:第二批并行 - resolveSellOutputs 和 buildSellTransactions
@@ -376,6 +375,52 @@ export async function pancakeProxyBatchSellMerkle(params) {
376
375
  routeType,
377
376
  amountsWei
378
377
  });
378
+ // ✅ 修复:先计算利润和 maxRevenueIndex,再统一分配 nonces
379
+ let totalProfit = 0n;
380
+ let maxRevenueIndex = -1;
381
+ let maxRevenue = 0n;
382
+ if (extractProfit && quotedOutputs.length > 0) {
383
+ for (let i = 0; i < sellers.length; i++) {
384
+ const quoted = quotedOutputs[i];
385
+ if (quoted > 0n) {
386
+ const { profit } = calculateProfit(quoted, config);
387
+ totalProfit += profit;
388
+ if (quoted > maxRevenue) {
389
+ maxRevenue = quoted;
390
+ maxRevenueIndex = i;
391
+ }
392
+ }
393
+ }
394
+ }
395
+ // ✅ 修复:根据是否需要利润交易,统一分配 nonces
396
+ const needProfitTx = extractProfit && totalProfit > 0n && maxRevenueIndex >= 0;
397
+ let nonces;
398
+ let profitNonce;
399
+ if (needProfitTx) {
400
+ // maxRevenueIndex 钱包需要 2 个连续 nonce(卖出 + 利润)
401
+ const maxRevenueNonces = await nonceManager.getNextNonceBatch(sellers[maxRevenueIndex], 2);
402
+ // 其他钱包各需要 1 个 nonce
403
+ const otherSellers = sellers.filter((_, i) => i !== maxRevenueIndex);
404
+ const otherNonces = otherSellers.length > 0
405
+ ? await nonceManager.getNextNoncesForWallets(otherSellers)
406
+ : [];
407
+ // 组装最终的 nonces 数组(保持原顺序)
408
+ nonces = [];
409
+ let otherIdx = 0;
410
+ for (let i = 0; i < sellers.length; i++) {
411
+ if (i === maxRevenueIndex) {
412
+ nonces.push(maxRevenueNonces[0]); // 卖出交易用第一个 nonce
413
+ }
414
+ else {
415
+ nonces.push(otherNonces[otherIdx++]);
416
+ }
417
+ }
418
+ profitNonce = maxRevenueNonces[1]; // 利润交易用第二个 nonce
419
+ }
420
+ else {
421
+ // 不需要利润交易,所有钱包各 1 个 nonce
422
+ nonces = await nonceManager.getNextNoncesForWallets(sellers);
423
+ }
379
424
  const unsignedSells = await buildSellTransactions({
380
425
  routeType,
381
426
  params,
@@ -399,16 +444,19 @@ export async function pancakeProxyBatchSellMerkle(params) {
399
444
  value: txValue
400
445
  });
401
446
  }));
402
- await appendSellProfitTransfer({
403
- extractProfit,
404
- quotedOutputs,
405
- wallets: sellers,
406
- nonceManager,
407
- signedTxs,
408
- gasPrice,
409
- chainId,
410
- config
411
- });
447
+ // ✅ 添加利润交易(使用预先分配的 profitNonce)
448
+ if (needProfitTx && profitNonce !== undefined) {
449
+ const profitTx = await sellers[maxRevenueIndex].signTransaction({
450
+ to: getProfitRecipient(),
451
+ value: totalProfit,
452
+ nonce: profitNonce,
453
+ gasPrice,
454
+ gasLimit: 21000n,
455
+ chainId,
456
+ type: getTxType(config)
457
+ });
458
+ signedTxs.push(profitTx);
459
+ }
412
460
  nonceManager.clearTemp();
413
461
  return {
414
462
  signedTransactions: signedTxs
@@ -479,15 +527,31 @@ async function buildBuyTransactions({ routeType, params, proxies, wallets, token
479
527
  throw new Error(`Unsupported routeType: ${routeType}`);
480
528
  }
481
529
  /**
482
- * ✅ 优化:批量获取所有钱包的 nonce(JSON-RPC 批量请求)
530
+ * ✅ 修复:明确分配 nonces,避免隐式状态依赖
483
531
  */
484
532
  async function allocateProfitAwareNonces(wallets, extractProfit, maxIndex, totalProfit, nonceManager) {
485
- // 批量获取所有钱包的初始 nonce(单次网络往返)
486
- const nonces = await nonceManager.getNextNoncesForWallets(wallets);
487
- // 如果需要利润转账,maxIndex 钱包需要额外一个 nonce
488
- if (extractProfit && totalProfit > 0n && maxIndex >= 0 && maxIndex < wallets.length) {
489
- // 预留一个 nonce 给利润交易(从缓存获取,不触发 RPC)
490
- await nonceManager.getNextNonce(wallets[maxIndex]);
533
+ const needProfitTx = extractProfit && totalProfit > 0n && maxIndex >= 0 && maxIndex < wallets.length;
534
+ if (!needProfitTx) {
535
+ // 不需要利润交易,所有钱包各 1 nonce
536
+ return await nonceManager.getNextNoncesForWallets(wallets);
537
+ }
538
+ // 需要利润交易:maxIndex 钱包需要 2 个连续 nonce
539
+ const maxIndexNonces = await nonceManager.getNextNonceBatch(wallets[maxIndex], 2);
540
+ // 其他钱包各需要 1 个 nonce
541
+ const otherWallets = wallets.filter((_, i) => i !== maxIndex);
542
+ const otherNonces = otherWallets.length > 0
543
+ ? await nonceManager.getNextNoncesForWallets(otherWallets)
544
+ : [];
545
+ // 组装最终的 nonces 数组(保持原顺序)
546
+ const nonces = [];
547
+ let otherIdx = 0;
548
+ for (let i = 0; i < wallets.length; i++) {
549
+ if (i === maxIndex) {
550
+ nonces.push(maxIndexNonces[0]); // 买入交易用第一个 nonce
551
+ }
552
+ else {
553
+ nonces.push(otherNonces[otherIdx++]);
554
+ }
491
555
  }
492
556
  return nonces;
493
557
  }
@@ -641,36 +705,4 @@ async function buildSellTransactions({ routeType, params, proxies, wallets, toke
641
705
  }
642
706
  throw new Error(`Unsupported routeType: ${routeType}`);
643
707
  }
644
- async function appendSellProfitTransfer({ extractProfit, quotedOutputs, wallets, nonceManager, signedTxs, gasPrice, chainId, config }) {
645
- if (!extractProfit || quotedOutputs.length === 0) {
646
- return;
647
- }
648
- let totalProfit = 0n;
649
- let maxRevenueIndex = -1;
650
- let maxRevenue = 0n;
651
- for (let i = 0; i < wallets.length; i++) {
652
- const quoted = quotedOutputs[i];
653
- if (quoted > 0n) {
654
- const { profit } = calculateProfit(quoted, config);
655
- totalProfit += profit;
656
- if (quoted > maxRevenue) {
657
- maxRevenue = quoted;
658
- maxRevenueIndex = i;
659
- }
660
- }
661
- }
662
- if (totalProfit === 0n || maxRevenueIndex < 0) {
663
- return;
664
- }
665
- const profitNonce = await nonceManager.getNextNonce(wallets[maxRevenueIndex]);
666
- const profitTx = await wallets[maxRevenueIndex].signTransaction({
667
- to: getProfitRecipient(),
668
- value: totalProfit,
669
- nonce: profitNonce,
670
- gasPrice,
671
- gasLimit: 21000n,
672
- chainId,
673
- type: getTxType(config)
674
- });
675
- signedTxs.push(profitTx);
676
- }
708
+ // appendSellProfitTransfer 已内联到 pancakeProxyBatchSellMerkle 中,避免 nonce 竞争问题
@@ -147,8 +147,8 @@ export async function flapBundleBuyFirstMerkle(params) {
147
147
  });
148
148
  const portalBuyer = new Contract(chainContext.portalAddress, PORTAL_ABI, buyer);
149
149
  const portalSeller = new Contract(chainContext.portalAddress, PORTAL_ABI, seller);
150
- // ✅ 优化:第三批并行 - buyUnsigned、sellUnsigned、approvalTx、estimatedSellFunds、noncePlan
151
- const [buyUnsigned, sellUnsigned, approvalTx, estimatedSellFunds, noncePlan] = await Promise.all([
150
+ // ✅ 第三批并行 - buyUnsigned、sellUnsigned、estimatedSellFunds(不含 nonce 相关操作)
151
+ const [buyUnsigned, sellUnsigned, estimatedSellFunds] = await Promise.all([
152
152
  portalBuyer.swapExactInput.populateTransaction({
153
153
  inputToken, // ✅ 使用动态输入代币
154
154
  outputToken: tokenAddress,
@@ -164,29 +164,30 @@ export async function flapBundleBuyFirstMerkle(params) {
164
164
  minOutputAmount: 0,
165
165
  permitData: '0x'
166
166
  }),
167
- buildApprovalTransaction({
168
- tokenAddress,
169
- provider: chainContext.provider,
170
- seller,
171
- decimals: sellerInfo.decimals,
172
- portalAddress: chainContext.portalAddress,
173
- chainId: chainContext.chainId,
174
- config,
175
- nonceManager,
176
- gasPrice,
177
- txType
178
- }),
179
- estimateSellFunds(portalSeller, tokenAddress, sellAmountWei, outputToken),
180
- // 预先规划 nonces(假设可能需要利润转账)
181
- planNonces({
182
- buyer,
183
- seller,
184
- approvalExists: true, // 保守估计,假设需要授权
185
- extractProfit: true, // 保守估计,假设需要利润转账
186
- sameAddress,
187
- nonceManager
188
- })
167
+ estimateSellFunds(portalSeller, tokenAddress, sellAmountWei, outputToken)
189
168
  ]);
169
+ // ✅ 修复:先构建授权交易(会消耗 nonce),再规划其他 nonce
170
+ const approvalTx = await buildApprovalTransaction({
171
+ tokenAddress,
172
+ provider: chainContext.provider,
173
+ seller,
174
+ decimals: sellerInfo.decimals,
175
+ portalAddress: chainContext.portalAddress,
176
+ chainId: chainContext.chainId,
177
+ config,
178
+ nonceManager,
179
+ gasPrice,
180
+ txType
181
+ });
182
+ // ✅ 修复:根据实际的授权情况规划 nonce
183
+ const noncePlan = await planNonces({
184
+ buyer,
185
+ seller,
186
+ approvalExists: approvalTx !== null, // ✅ 使用实际值
187
+ extractProfit: true,
188
+ sameAddress,
189
+ nonceManager
190
+ });
190
191
  // ✅ 修复:基于卖出收益估算利润
191
192
  const profitBase = estimatedSellFunds > 0n ? estimatedSellFunds : buyerFundsWei;
192
193
  const tokenProfitAmount = calculateProfitAmount(profitBase);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.3.39",
3
+ "version": "1.3.41",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",