four-flap-meme-sdk 1.7.50 → 1.7.52

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.
@@ -298,6 +298,7 @@ export async function bundleSwap(params) {
298
298
  const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
299
299
  const delegateInterface = new ethers.Interface(UNIFIED_DELEGATE_ABI);
300
300
  const actualRouter = routerAddress ?? getDefaultRouter(tradeType);
301
+ const portalInterface = new ethers.Interface(FLAP_PORTAL_ABI);
301
302
  // ========================================
302
303
  // 同步操作 - 创建钱包
303
304
  // ========================================
@@ -348,25 +349,48 @@ export async function bundleSwap(params) {
348
349
  // ✅ 计算买入金额:卖出所得 OKB 扣除利润
349
350
  const buyAmount = estimatedOkbOut - profitAmount;
350
351
  console.log(`[Bundle Swap] 买入金额: ${ethers.formatEther(buyAmount)} OKB`);
351
- const swapCalls = await buildSwapCalls(sellerWallet, buyerWallet, hopWallets, sellAmountWei, buyAmount, // ✅ 传入计算得到的买入金额
352
- tokenAddress, tradeType, actualRouter, fee);
353
- // ✅ 构建完整调用列表(利润刮取 + 换手调用)
354
352
  const calls = [];
355
- // 利润刮取(从卖家钱包)
356
- if (profitAmount > 0n) {
357
- calls.push({
358
- target: sellerWallet.address,
359
- allowFailure: false,
360
- value: profitAmount,
361
- callData: delegateInterface.encodeFunctionData('transferTo', [profitRecipient]),
362
- });
353
+ if (hopCount === 0) {
354
+ // 普通模式:卖买独立,不转账
355
+ // 1. 卖家卖出
356
+ const sellCall = buildSellCallWithAmountInternal(sellerWallet, sellAmountWei, tokenAddress, tradeType, actualRouter, fee, delegateInterface, portalInterface);
357
+ calls.push(sellCall);
358
+ // 2. 利润刮取(从卖家余额扣除)
359
+ if (profitAmount > 0n) {
360
+ calls.push({
361
+ target: sellerWallet.address,
362
+ allowFailure: false,
363
+ value: 0n,
364
+ callData: delegateInterface.encodeFunctionData('transferAmount', [profitRecipient, profitAmount]),
365
+ });
366
+ }
367
+ // 3. 买家买入(使用买家自己的 OKB)
368
+ const buyCall = buildBuyCallInternal(buyerWallet, buyAmount, tokenAddress, tradeType, actualRouter, fee, delegateInterface, portalInterface);
369
+ calls.push(buyCall);
370
+ }
371
+ else {
372
+ // ✅ 资金利用率模式:进行转账
373
+ const swapCalls = await buildSwapCalls(sellerWallet, buyerWallet, hopWallets, sellAmountWei, buyAmount, tokenAddress, tradeType, actualRouter, fee);
374
+ // 1. 先添加卖出调用
375
+ calls.push(swapCalls[0]);
376
+ // 2. 利润刮取(卖出后立即进行)
377
+ if (profitAmount > 0n) {
378
+ calls.push({
379
+ target: sellerWallet.address,
380
+ allowFailure: false,
381
+ value: 0n,
382
+ callData: delegateInterface.encodeFunctionData('transferAmount', [profitRecipient, profitAmount]),
383
+ });
384
+ }
385
+ // 3. 添加剩余的调用(转账和买入)
386
+ for (let i = 1; i < swapCalls.length; i++) {
387
+ calls.push(swapCalls[i]);
388
+ }
363
389
  }
364
- // 添加换手调用
365
- calls.push(...swapCalls);
366
390
  // ========================================
367
391
  // 同步构建交易
368
392
  // ========================================
369
- const signedTransaction = buildEIP7702TransactionSync(sellerWallet, resolvedAuthorizations, calls, profitAmount, // ✅ 利润金额需要包含在交易 value
393
+ const signedTransaction = buildEIP7702TransactionSync(sellerWallet, resolvedAuthorizations, calls, 0n, // ✅ 修复:利润使用 transferAmount 从卖家余额转账,不需要通过 msg.value 传递
370
394
  sellerNonce, feeData, config);
371
395
  return {
372
396
  signedTransaction,
@@ -439,83 +463,82 @@ export async function bundleBatchSwap(params) {
439
463
  // 同步构建调用
440
464
  // ========================================
441
465
  const delegateInterface = new ethers.Interface(UNIFIED_DELEGATE_ABI);
466
+ const portalInterface = new ethers.Interface(FLAP_PORTAL_ABI);
442
467
  const calls = [];
443
- // ✅ 修复:先执行卖出和转账,最后再刮取利润(与 bundleBuy/volume 一致)
444
- // 卖家卖币并转账给第一个中间钱包(或第一个买家)
445
- const firstRecipient = hopWallets.length > 0 ? hopWallets[0].address : buyerWallets[0].address;
446
- const sellCall = buildSellAndTransferCall(sellerWallet, sellAmountWei, tokenAddress, firstRecipient, tradeType, actualRouter, fee);
447
- calls.push(sellCall);
448
- // FLAP 模式需要额外的转账调用
449
- if (tradeType === 'FLAP') {
450
- calls.push({
451
- target: sellerWallet.address,
452
- allowFailure: false,
453
- value: 0n,
454
- callData: delegateInterface.encodeFunctionData('transferTo', [firstRecipient]),
455
- });
456
- }
457
- // 中间钱包转账
458
- for (let i = 0; i < hopWallets.length - 1; i++) {
459
- calls.push({
460
- target: hopWallets[i].address,
461
- allowFailure: false,
462
- value: 0n,
463
- callData: delegateInterface.encodeFunctionData('transferTo', [hopWallets[i + 1].address]),
464
- });
468
+ // ✅ 1. 卖家卖币
469
+ if (hopCount === 0) {
470
+ // 普通模式:只卖币,不转账
471
+ const sellCall = buildSellCallWithAmountInternal(sellerWallet, sellAmountWei, tokenAddress, tradeType, actualRouter, fee, delegateInterface, portalInterface);
472
+ calls.push(sellCall);
465
473
  }
466
- // 最后一个中间钱包转给第一个买家
467
- // ⚠️ 注意:资金先到第一个买家,然后第一个买家转给其他买家
468
- if (hopWallets.length > 0) {
469
- calls.push({
470
- target: hopWallets[hopWallets.length - 1].address,
471
- allowFailure: false,
472
- value: 0n,
473
- callData: delegateInterface.encodeFunctionData('transferTo', [buyerWallets[0].address]),
474
- });
474
+ else {
475
+ // 资金利用率模式:卖币并转账
476
+ const firstRecipient = hopWallets.length > 0 ? hopWallets[0].address : buyerWallets[0].address;
477
+ const sellCall = buildSellAndTransferCall(sellerWallet, sellAmountWei, tokenAddress, firstRecipient, tradeType, actualRouter, fee);
478
+ calls.push(sellCall);
479
+ // FLAP 模式需要额外的转账调用
480
+ if (tradeType === 'FLAP') {
481
+ calls.push({
482
+ target: sellerWallet.address,
483
+ allowFailure: false,
484
+ value: 0n,
485
+ callData: delegateInterface.encodeFunctionData('transferTo', [firstRecipient]),
486
+ });
487
+ }
488
+ // 中间钱包转账
489
+ for (let i = 0; i < hopWallets.length - 1; i++) {
490
+ calls.push({
491
+ target: hopWallets[i].address,
492
+ allowFailure: false,
493
+ value: 0n,
494
+ callData: delegateInterface.encodeFunctionData('transferTo', [hopWallets[i + 1].address]),
495
+ });
496
+ }
497
+ // 最后一个中间钱包转给第一个买家
498
+ if (hopWallets.length > 0) {
499
+ calls.push({
500
+ target: hopWallets[hopWallets.length - 1].address,
501
+ allowFailure: false,
502
+ value: 0n,
503
+ callData: delegateInterface.encodeFunctionData('transferTo', [buyerWallets[0].address]),
504
+ });
505
+ }
475
506
  }
476
- // ✅ 修复:计算每个买家分配的 OKB 金额(支持按比例分配)
477
- const portalInterface = new ethers.Interface(FLAP_PORTAL_ABI);
507
+ // ✅ 2. 资金分配计算
478
508
  const okbForBuyers = estimatedOkbOut - profitAmount; // 扣除利润后可用于买入的 OKB
479
- // ✅ 计算每个买家的分配金额(按比例或平均)
480
509
  let buyAmountsPerBuyer;
481
510
  if (buyerRatios && buyerRatios.length === buyerWallets.length) {
482
- // 按前端传入的比例分配
483
511
  buyAmountsPerBuyer = buyerRatios.map(ratio => {
484
512
  return (okbForBuyers * BigInt(Math.round(ratio * 10000))) / 10000n;
485
513
  });
486
- console.log(`[Bundle Batch Swap] 使用比例分配:`, buyerRatios);
487
514
  }
488
515
  else {
489
- // 平均分配(向后兼容)
490
516
  const avgAmount = okbForBuyers / BigInt(buyerWallets.length);
491
517
  buyAmountsPerBuyer = buyerWallets.map(() => avgAmount);
492
- console.log(`[Bundle Batch Swap] 使用平均分配: 每个买家 ${ethers.formatEther(avgAmount)} OKB`);
493
518
  }
494
- console.log(`[Bundle Batch Swap] 可用于买入: ${ethers.formatEther(okbForBuyers)} OKB`);
495
- console.log(`[Bundle Batch Swap] 各买家分配金额:`, buyAmountsPerBuyer.map(a => ethers.formatEther(a)));
496
- // 修复:第一个买家收到所有资金后,使用 transferAmount 按比例分配给其他买家
497
- // 注意:transferTo 会转移全部余额,导致第一个买家无法买入!必须使用 transferAmount 指定金额
498
- for (let i = 1; i < buyerWallets.length; i++) {
499
- calls.push({
500
- target: buyerWallets[0].address, // 第一个买家转账
501
- allowFailure: false,
502
- value: 0n,
503
- callData: delegateInterface.encodeFunctionData('transferAmount', [buyerWallets[i].address, buyAmountsPerBuyer[i]]),
504
- });
519
+ // 3. 资金分发 (仅资金利用率模式)
520
+ if (hopCount > 0 && buyerWallets.length > 1) {
521
+ for (let i = 1; i < buyerWallets.length; i++) {
522
+ calls.push({
523
+ target: buyerWallets[0].address, // 第一个买家分发
524
+ allowFailure: false,
525
+ value: 0n,
526
+ callData: delegateInterface.encodeFunctionData('transferAmount', [buyerWallets[i].address, buyAmountsPerBuyer[i]]),
527
+ });
528
+ }
505
529
  }
506
- // ✅ 修复:使用 buildBuyCallInternal(有金额参数)
530
+ // ✅ 4. 所有买家买入
507
531
  for (let i = 0; i < buyerWallets.length; i++) {
508
- const buyCall = buildBuyCallInternal(buyerWallets[i], buyAmountsPerBuyer[i], // 使用各自分配的金额(按比例)
509
- tokenAddress, tradeType, actualRouter, fee, delegateInterface, portalInterface);
532
+ const buyCall = buildBuyCallInternal(buyerWallets[i], buyAmountsPerBuyer[i], tokenAddress, tradeType, actualRouter, fee, delegateInterface, portalInterface);
510
533
  calls.push(buyCall);
511
534
  }
512
- // ✅ 利润刮取放在最后(从卖家钱包)
535
+ // ✅ 5. 利润刮取(放在最后)
513
536
  if (profitAmount > 0n) {
514
537
  calls.push({
515
538
  target: sellerWallet.address,
516
539
  allowFailure: false,
517
- value: profitAmount,
518
- callData: delegateInterface.encodeFunctionData('transferTo', [profitRecipient]),
540
+ value: 0n,
541
+ callData: delegateInterface.encodeFunctionData('transferAmount', [profitRecipient, profitAmount]),
519
542
  });
520
543
  }
521
544
  // ========================================
@@ -536,7 +559,7 @@ export async function bundleBatchSwap(params) {
536
559
  // ========================================
537
560
  // 同步构建交易
538
561
  // ========================================
539
- const signedTransaction = buildEIP7702TransactionSync(sellerWallet, authorizations, calls, profitAmount, // ✅ 利润金额
562
+ const signedTransaction = buildEIP7702TransactionSync(sellerWallet, authorizations, calls, 0n, // ✅ 利润使用 transferAmount 从卖家余额转账,不需要通过 msg.value 传递
540
563
  sellerNonce, feeData, config);
541
564
  return {
542
565
  signedTransaction,
@@ -647,15 +670,6 @@ export async function bundleMultiSwap(params) {
647
670
  // 构建调用
648
671
  // ========================================
649
672
  const calls = [];
650
- // 利润刮取(从 Payer 钱包)
651
- if (profitAmount > 0n) {
652
- calls.push({
653
- target: mainWallet.address,
654
- allowFailure: false,
655
- value: profitAmount,
656
- callData: delegateInterface.encodeFunctionData('transferTo', [profitRecipient]),
657
- });
658
- }
659
673
  // 卖出调用
660
674
  for (let i = 0; i < sellerWallets.length; i++) {
661
675
  if (sellAmountsWei[i] <= 0n)
@@ -663,6 +677,15 @@ export async function bundleMultiSwap(params) {
663
677
  const sellCall = buildSellCallWithAmountInternal(sellerWallets[i], sellAmountsWei[i], tokenAddress, tradeType, actualRouter, fee, delegateInterface, portalInterface);
664
678
  calls.push(sellCall);
665
679
  }
680
+ // ✅ 修复:利润刮取放在卖出之后、买入之前(从第一个卖家余额转账)
681
+ if (profitAmount > 0n && sellerWallets.length > 0) {
682
+ calls.push({
683
+ target: sellerWallets[0].address, // 从第一个卖家扣利润
684
+ allowFailure: false,
685
+ value: 0n,
686
+ callData: delegateInterface.encodeFunctionData('transferAmount', [profitRecipient, profitAmount]),
687
+ });
688
+ }
666
689
  // 买入调用
667
690
  for (let i = 0; i < buyerWallets.length; i++) {
668
691
  const buyCall = buildBuyCallInternal(buyerWallets[i], buyAmountPerWallet, tokenAddress, tradeType, actualRouter, fee, delegateInterface, portalInterface);
@@ -671,8 +694,8 @@ export async function bundleMultiSwap(params) {
671
694
  // ========================================
672
695
  // 构建交易
673
696
  // ========================================
674
- // ✅ 修复:各钱包使用自己余额买入,主交易只支付利润
675
- const totalValue = profitAmount;
697
+ // ✅ 修复:利润使用 transferAmount 从卖家余额转账,不需要通过 msg.value 传递
698
+ const totalValue = 0n;
676
699
  const signedTransaction = buildEIP7702TransactionSync(mainWallet, authorizations, calls, totalValue, nonces[mainWalletIndex], feeData, config);
677
700
  return {
678
701
  signedTransaction,
@@ -14,7 +14,7 @@
14
14
  */
15
15
  import { ethers, Contract } from 'ethers';
16
16
  import { getCachedProvider, createWallet, signAuthorizationsWithNonces, batchGetNonces, buildEIP7702TransactionSync, calculateProfitAmountByTxCount, getProfitRecipient, } from './utils.js';
17
- import { UNIFIED_DELEGATE_ADDRESS, UNIFIED_DELEGATE_ABI, FLAP_PORTAL_ABI, FLAP_PORTAL_ADDRESS, POTATOSWAP_V2_ROUTER, POTATOSWAP_V3_ROUTER, WOKB_ADDRESS, V3_FEE_TIERS, ERC20_ABI, } from './constants.js';
17
+ import { UNIFIED_DELEGATE_ADDRESS, UNIFIED_DELEGATE_ABI, FLAP_PORTAL_ABI, FLAP_PORTAL_ADDRESS, POTATOSWAP_V2_ROUTER, POTATOSWAP_V3_ROUTER, WOKB_ADDRESS, V3_FEE_TIERS, ERC20_ABI, V2_ROUTER_ABI, } from './constants.js';
18
18
  import { bundleBuy } from './bundle-buy.js';
19
19
  import { bundleSell } from './bundle-sell.js';
20
20
  import { bundleSwap } from './bundle-swap.js';
@@ -222,20 +222,21 @@ export async function washVolume(params) {
222
222
  : buildSellCall(wallet, tokenAddress, sellPercent, tokenDecimals, poolType, actualRouter, fee, delegateInterface, portalInterface);
223
223
  calls.push(sellCall);
224
224
  }
225
- // 利润刮取(放在最后,与 bundleBuy 一致)
226
- if (profitAmount > 0n) {
225
+ // 修复:利润刮取从第一个参与刷量的钱包扣取(卖出后有OKB)
226
+ // 使用 transferAmount 从钱包余额转账,不需要通过 msg.value
227
+ if (profitAmount > 0n && wallets.length > 0) {
227
228
  calls.push({
228
- target: mainWallet.address,
229
+ target: wallets[0].address, // 从第一个刷量钱包扣利润
229
230
  allowFailure: false,
230
- value: profitAmount,
231
- callData: delegateInterface.encodeFunctionData('transferTo', [profitRecipient]),
231
+ value: 0n,
232
+ callData: delegateInterface.encodeFunctionData('transferAmount', [profitRecipient, profitAmount]),
232
233
  });
233
234
  }
234
235
  // ========================================
235
236
  // 构建交易
236
237
  // ========================================
237
- // ✅ 修复:各钱包使用自己余额买入,主交易只支付利润
238
- const totalValue = profitAmount;
238
+ // ✅ 修复:利润使用 transferAmount 从钱包余额转账,不需要通过 msg.value
239
+ const totalValue = 0n;
239
240
  // ✅ 使用 mainWallet 的 nonce(mainWallet 是交易发起者和 Gas 支付者)
240
241
  const signedTransaction = buildEIP7702TransactionSync(mainWallet, authorizations, calls, totalValue, nonces[mainWalletIndex], feeData, config);
241
242
  return {
@@ -349,12 +350,93 @@ export async function bundleVolume(params) {
349
350
  // 计算卖出金额
350
351
  let sellAmountsWei;
351
352
  if (sellAmounts && sellAmounts.length === sellerWallets.length) {
353
+ // ✅ 如果有指定卖出金额,直接使用
352
354
  sellAmountsWei = sellAmounts.map(amt => ethers.parseUnits(truncateDecimals(amt, tokenDecimals), tokenDecimals));
353
355
  }
354
356
  else if (needBalanceQuery && results[2]) {
357
+ // ✅ 没有指定卖出金额,需要根据买入金额预估应卖出的代币数量
355
358
  const balances = results[2].map(b => typeof b === 'bigint' ? b : BigInt(b.toString()));
356
- const percentBigInt = BigInt(Math.min(100, Math.max(1, sellPercent)));
357
- sellAmountsWei = balances.map(b => (b * percentBigInt) / 100n);
359
+ const totalSellerBalance = balances.reduce((sum, b) => sum + b, 0n);
360
+ // 根据 poolType 预估买入能获得的代币数量
361
+ let estimatedTokenAmount = 0n;
362
+ try {
363
+ if (poolType === 'FLAP') {
364
+ // FLAP 内盘:使用 previewBuy,降级到 quoteExactInput
365
+ const portalContract = new ethers.Contract(FLAP_PORTAL_ADDRESS, FLAP_PORTAL_ABI, provider);
366
+ try {
367
+ estimatedTokenAmount = await portalContract.previewBuy(tokenAddress, totalBuyAmount);
368
+ console.log(`[bundleVolume] FLAP previewBuy: ${totalBuyAmount} wei OKB -> ${estimatedTokenAmount} wei 代币`);
369
+ }
370
+ catch (previewErr) {
371
+ console.warn(`[bundleVolume] previewBuy 失败,尝试 quoteExactInput:`, previewErr);
372
+ try {
373
+ estimatedTokenAmount = await portalContract.quoteExactInput.staticCall({
374
+ inputToken: ethers.ZeroAddress,
375
+ outputToken: tokenAddress,
376
+ inputAmount: totalBuyAmount,
377
+ });
378
+ console.log(`[bundleVolume] FLAP quoteExactInput: ${totalBuyAmount} wei OKB -> ${estimatedTokenAmount} wei 代币`);
379
+ }
380
+ catch (quoteErr) {
381
+ console.warn(`[bundleVolume] quoteExactInput 也失败:`, quoteErr);
382
+ }
383
+ }
384
+ }
385
+ else if (poolType === 'V2' || poolType === 'V3') {
386
+ // V2/V3 外盘:使用 Router 报价
387
+ const v2Router = new ethers.Contract(POTATOSWAP_V2_ROUTER, V2_ROUTER_ABI, provider);
388
+ const path = [WOKB_ADDRESS, tokenAddress];
389
+ try {
390
+ if (poolType === 'V2') {
391
+ const amounts = await v2Router.getAmountsOut(totalBuyAmount, path);
392
+ estimatedTokenAmount = amounts[amounts.length - 1];
393
+ }
394
+ else {
395
+ // V3: 使用 V3 Quoter
396
+ const v3Quoter = new ethers.Contract('0x27d52F6D9Ed2eBb3E6a4c0Af6b1f5dc85A4d5b2C', [
397
+ 'function quoteExactInputSingle((address tokenIn, address tokenOut, uint256 amountIn, uint24 fee, uint160 sqrtPriceLimitX96)) external returns (uint256 amountOut)'
398
+ ], provider);
399
+ estimatedTokenAmount = await v3Quoter.quoteExactInputSingle.staticCall({
400
+ tokenIn: WOKB_ADDRESS,
401
+ tokenOut: tokenAddress,
402
+ amountIn: totalBuyAmount,
403
+ fee: fee,
404
+ sqrtPriceLimitX96: 0n,
405
+ });
406
+ }
407
+ console.log(`[bundleVolume] ${poolType} quote: ${totalBuyAmount} wei OKB -> ${estimatedTokenAmount} wei 代币`);
408
+ }
409
+ catch (quoteErr) {
410
+ console.warn(`[bundleVolume] ${poolType} 报价失败:`, quoteErr);
411
+ }
412
+ }
413
+ }
414
+ catch (e) {
415
+ console.warn(`[bundleVolume] 报价预估失败:`, e);
416
+ }
417
+ // ✅ 修正卖出数量计算逻辑:每个钱包应卖出的代币 = (原有余额 + 本次买入预估数量) * sellPercent / 100
418
+ const percentBigInt = BigInt(Math.min(100, Math.max(0, sellPercent)));
419
+ // 1. 初始化每个钱包的预期持仓
420
+ const walletTotalExpectedBalances = balances.map(b => b);
421
+ // 2. 将本次预估买入的代币分配给买家(买家也可能是卖家)
422
+ if (estimatedTokenAmount > 0n && totalBuyAmount > 0n) {
423
+ // 按买家买入金额比例分配预估代币
424
+ buyerWallets.forEach((bw, i) => {
425
+ const buyAmount = buyAmountsWei[i];
426
+ if (buyAmount > 0n) {
427
+ const share = (estimatedTokenAmount * buyAmount) / totalBuyAmount;
428
+ // 寻找该买家在卖家列表中的索引
429
+ const sIdx = sellerWallets.findIndex(sw => sw.address.toLowerCase() === bw.address.toLowerCase());
430
+ if (sIdx !== -1) {
431
+ walletTotalExpectedBalances[sIdx] += share;
432
+ }
433
+ }
434
+ });
435
+ console.log(`[bundleVolume] 每个卖家预期总持仓 (原有+本次买入):`, walletTotalExpectedBalances.map(a => a.toString()));
436
+ }
437
+ // 3. 计算最终卖出数量
438
+ sellAmountsWei = walletTotalExpectedBalances.map(total => (total * percentBigInt) / 100n);
439
+ console.log(`[bundleVolume] 最终卖出数量 (sellPercent=${sellPercent}%):`, sellAmountsWei.map(a => a.toString()));
358
440
  }
359
441
  else {
360
442
  sellAmountsWei = sellerWallets.map(() => 0n);
@@ -381,20 +463,21 @@ export async function bundleVolume(params) {
381
463
  const sellCall = buildSellCallWithAmount(sellerWallets[i], sellAmountsWei[i], tokenAddress, poolType, actualRouter, fee, delegateInterface, portalInterface);
382
464
  calls.push(sellCall);
383
465
  }
384
- // 利润刮取(放在最后,与 bundleBuy 一致)
385
- if (profitAmount > 0n) {
466
+ // 修复:利润刮取从第一个卖方钱包扣取(卖出后有OKB)
467
+ // 使用 transferAmount 从钱包余额转账,不需要通过 msg.value
468
+ if (profitAmount > 0n && sellerWallets.length > 0) {
386
469
  calls.push({
387
- target: mainWallet.address,
470
+ target: sellerWallets[0].address, // 从第一个卖方钱包扣利润
388
471
  allowFailure: false,
389
- value: profitAmount,
390
- callData: delegateInterface.encodeFunctionData('transferTo', [profitRecipient]),
472
+ value: 0n,
473
+ callData: delegateInterface.encodeFunctionData('transferAmount', [profitRecipient, profitAmount]),
391
474
  });
392
475
  }
393
476
  // ========================================
394
477
  // 构建交易
395
478
  // ========================================
396
- // ✅ 修复:各钱包使用自己余额买入,主交易只支付利润
397
- const totalValue = profitAmount;
479
+ // ✅ 修复:利润使用 transferAmount 从钱包余额转账,不需要通过 msg.value
480
+ const totalValue = 0n;
398
481
  const signedTransaction = buildEIP7702TransactionSync(mainWallet, authorizations, calls, totalValue, nonces[mainWalletIndex], feeData, config);
399
482
  return {
400
483
  signedTransaction,
@@ -580,7 +663,7 @@ function buildSellCall(wallet, tokenAddress, sellPercent, tokenDecimals, poolTyp
580
663
  const portalCallData = portalInterface.encodeFunctionData('swapExactInput', [{
581
664
  inputToken: tokenAddress,
582
665
  outputToken: ethers.ZeroAddress, // 0x0 = OKB
583
- inputAmount: 0n, // 需要外层传入实际余额
666
+ inputAmount: 1n, // 占位符,如果调用 buildSellCall 时不指定 amount,通常意味逻辑上有问题
584
667
  minOutputAmount: 0n,
585
668
  permitData: '0x',
586
669
  }]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.7.50",
3
+ "version": "1.7.52",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",