four-flap-meme-sdk 1.1.99 → 1.2.2

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.
@@ -5,6 +5,7 @@ import { ADDRESSES } from '../../utils/constants.js';
5
5
  import { FourClient, buildLoginMessage } from '../../clients/four.js';
6
6
  import { getErrorMessage, getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit } from './config.js';
7
7
  import { batchCheckAllowances } from '../../utils/erc20.js';
8
+ import { trySell } from '../tm.js';
8
9
  // ==================== TokenManager2 ABI(仅需要的方法)====================
9
10
  const TM2_ABI = [
10
11
  'function createToken(bytes args, bytes signature) payable',
@@ -322,28 +323,35 @@ export async function batchSellWithBundleMerkle(params) {
322
323
  const gasPrice = await getOptimizedGasPrice(provider, getGasPriceConfig(config));
323
324
  const sellers = privateKeys.map((k) => new Wallet(k, provider));
324
325
  const amountsWei = sellAmounts.map((a) => ethers.parseUnits(a, 18));
325
- // ⚠️ Four.meme 内盘代币通过 TokenManager bonding curve 定价,不在 PancakeSwap 上
326
- // ✅ 使用用户提供的 minOutputAmounts,或默认为 0(不限制最小输出)
326
+ // ⚠️ Four.meme 内盘代币通过 TokenManager bonding curve 定价
327
+ // ✅ 优先使用用户提供的 minOutputAmounts,否则自动调用 trySell 获取
327
328
  let minOuts;
328
329
  let quotedOutputs = [];
329
330
  if (minOutputAmounts && minOutputAmounts.length === sellers.length) {
330
- // 用户提供了 minOutputAmounts,优先使用
331
+ // 用户提供了 minOutputAmounts,用于滑点保护和利润计算
331
332
  minOuts = minOutputAmounts.map(m => typeof m === 'string' ? ethers.parseEther(m) : m);
332
- quotedOutputs = minOuts.map(m => m * 100n / 95n); // 反推报价(用于利润计算)
333
- console.log(`📝 使用用户提供的 minOutputAmounts`);
334
- console.log(`💰 minOutputAmounts:`);
335
- minOuts.forEach((minOut, i) => {
336
- console.log(` 钱包 ${i}: ${ethers.formatEther(minOut)} BNB`);
337
- });
333
+ quotedOutputs = minOuts.map(m => m * 100n / 95n);
338
334
  }
339
335
  else {
340
- // Four.meme 内盘代币:默认 minOutputAmount = 0(不限制),不提取利润
341
- minOuts = new Array(sellers.length).fill(0n);
342
- quotedOutputs = new Array(sellers.length).fill(0n);
343
- console.log(`📝 Four.meme 内盘代币:minOutputAmount = 0(不限制最小输出)`);
344
- console.log(`⚠️ 无法自动计算卖出收益,建议手动传入 minOutputAmounts 以提取利润`);
336
+ // 自动调用 trySell 获取每个钱包的预期收益
337
+ console.log('💰 自动获取卖出报价...');
338
+ const rpcUrl = config.customRpcUrl;
339
+ quotedOutputs = await Promise.all(amountsWei.map(async (amount, i) => {
340
+ try {
341
+ const result = await trySell('BSC', rpcUrl, tokenAddress, amount);
342
+ const quoted = result.funds; // 预期收益
343
+ console.log(` 钱包 ${i}: 卖出 ${ethers.formatUnits(amount, 18)} 代币 → 预期收益 ${ethers.formatEther(quoted)} BNB`);
344
+ return quoted;
345
+ }
346
+ catch (error) {
347
+ console.log(` ⚠️ 钱包 ${i}: 报价失败,使用 minOut = 0`);
348
+ return 0n;
349
+ }
350
+ }));
351
+ // minOuts 设为预期收益的 95%(作为滑点保护)
352
+ minOuts = quotedOutputs.map(q => q * 95n / 100n);
353
+ console.log('');
345
354
  }
346
- console.log('');
347
355
  // ✅ Step 1: 检查代币余额和授权状态
348
356
  const ERC20_ABI = [
349
357
  'function approve(address spender, uint256 amount) returns (bool)',
@@ -351,60 +359,29 @@ export async function batchSellWithBundleMerkle(params) {
351
359
  'function balanceOf(address owner) view returns (uint256)'
352
360
  ];
353
361
  // 检查代币余额
354
- console.log('🔍 检查代币余额...');
355
362
  const tokenContract = new ethers.Contract(tokenAddress, ERC20_ABI, provider);
356
363
  const balances = await Promise.all(sellers.map(w => tokenContract.balanceOf(w.address)));
357
364
  for (let i = 0; i < sellers.length; i++) {
358
- const balance = balances[i];
359
- const sellAmount = amountsWei[i];
360
- const balanceFormatted = ethers.formatUnits(balance, 18);
361
- const sellAmountFormatted = ethers.formatUnits(sellAmount, 18);
362
- console.log(` 钱包 ${i} (${sellers[i].address.slice(0, 6)}...${sellers[i].address.slice(-4)}):`);
363
- console.log(` 代币余额: ${balanceFormatted}`);
364
- console.log(` 卖出数量: ${sellAmountFormatted}`);
365
- if (balance < sellAmount) {
366
- throw new Error(`钱包 ${i} (${sellers[i].address}) 代币余额不足\n` +
367
- `需要: ${sellAmountFormatted}\n` +
368
- `实际: ${balanceFormatted}`);
365
+ if (balances[i] < amountsWei[i]) {
366
+ throw new Error(`钱包 ${i} 代币余额不足:` +
367
+ `需要 ${ethers.formatUnits(amountsWei[i], 18)},` +
368
+ `实际 ${ethers.formatUnits(balances[i], 18)}`);
369
369
  }
370
370
  }
371
- console.log('\n🔍 使用 Multicall3 批量检查授权状态...');
372
371
  const allowances = await batchCheckAllowances(provider, tokenAddress, sellers.map(w => w.address), tmAddr);
373
372
  // 找出需要授权的钱包索引
374
373
  // ✅ 检查授权额度是否足够卖出
375
374
  const needApprovalIndexes = [];
376
375
  for (let i = 0; i < sellers.length; i++) {
377
- const allowance = allowances[i];
378
- const sellAmount = amountsWei[i];
379
- const allowanceFormatted = allowance === ethers.MaxUint256 ? 'MAX (无限)' : ethers.formatUnits(allowance, 18);
380
- const sellAmountFormatted = ethers.formatUnits(sellAmount, 18);
381
- console.log(` 钱包 ${i}:`);
382
- console.log(` 当前授权: ${allowanceFormatted}`);
383
- console.log(` 需要授权: ${sellAmountFormatted}`);
384
- // ✅ 检查授权额度是否 >= 卖出数量
385
- if (allowance < sellAmount) {
376
+ if (allowances[i] < amountsWei[i]) {
386
377
  needApprovalIndexes.push(i);
387
- console.log(` ❌ 授权不足!`);
388
- }
389
- else {
390
- console.log(` ✅ 授权充足`);
391
378
  }
392
379
  }
393
- console.log(`\n 📊 授权统计:`);
394
- console.log(` 总钱包数: ${sellers.length}`);
395
- console.log(` 需要授权: ${needApprovalIndexes.length}`);
396
- console.log(` 已有授权: ${sellers.length - needApprovalIndexes.length}\n`);
397
- // ✅ Step 2: 批量授权(如果需要)
398
- // ⚠️ 注意:授权需要单独提交,SDK只返回签名交易
380
+ // ✅ Step 2: 检查授权
399
381
  if (needApprovalIndexes.length > 0) {
400
- console.log(`⚠️ 警告:检测到 ${needApprovalIndexes.length} 个钱包需要授权`);
401
- console.log(' 请先使用 approveFourTokenManagerBatch 方法授权');
402
- console.log(' ⚠️ 重要:请使用 amounts: ["max", "max", ...] 授权,避免重复授权');
403
- throw new Error(`需要授权: ${needApprovalIndexes.length} 个钱包授权额度不足。\n` +
404
- `解决方案:调用 approveFourTokenManagerBatch({ amounts: ['max', 'max', ...] })`);
382
+ throw new Error(`${needApprovalIndexes.length} 个钱包需要授权。` +
383
+ `请先调用 approveFourTokenManagerBatch({ amounts: ['max', ...] })`);
405
384
  }
406
- // ✅ Step 3: 批量卖出
407
- console.log('💰 提交卖出交易...');
408
385
  const nonceManager = new NonceManager(provider);
409
386
  const signedTxs = [];
410
387
  const tm2Contracts = sellers.map((w) => new ethers.Contract(tmAddr, TM2_ABI, w));
@@ -423,17 +400,13 @@ export async function batchSellWithBundleMerkle(params) {
423
400
  type: getTxType(config)
424
401
  })));
425
402
  signedTxs.push(...signedList);
426
- // ✅ 基于报价金额为每个钱包添加利润转账
403
+ // ✅ 提取利润
427
404
  const extractProfit = shouldExtractProfit(config);
428
405
  if (extractProfit && quotedOutputs.length > 0) {
429
- console.log(`💰 提取利润交易...`);
430
- let totalProfitExtracted = 0n;
431
- // 为每个钱包添加利润转账(基于完整报价金额,而非 minOut)
432
406
  for (let i = 0; i < sellers.length; i++) {
433
- if (quotedOutputs[i] > 0n) { // 只对报价成功的交易提取利润
407
+ if (quotedOutputs[i] > 0n) {
434
408
  const { profit } = calculateProfit(quotedOutputs[i], config);
435
409
  if (profit > 0n) {
436
- console.log(` ✅ 钱包 ${i}: 从 ${ethers.formatEther(quotedOutputs[i])} BNB 中提取 ${ethers.formatEther(profit)} BNB (${config.profitRateBps / 100}%)`);
437
410
  const profitNonce = await nonceManager.getNextNonce(sellers[i]);
438
411
  const profitTx = await sellers[i].signTransaction({
439
412
  to: config.profitRecipient,
@@ -445,11 +418,9 @@ export async function batchSellWithBundleMerkle(params) {
445
418
  type: getTxType(config)
446
419
  });
447
420
  signedTxs.push(profitTx);
448
- totalProfitExtracted += profit;
449
421
  }
450
422
  }
451
423
  }
452
- console.log(` 💵 总利润: ${ethers.formatEther(totalProfitExtracted)} BNB → ${config.profitRecipient}\n`);
453
424
  }
454
425
  // ✅ 清理临时 nonce 缓存
455
426
  nonceManager.clearTemp();
@@ -4,6 +4,7 @@ import { NonceManager, getOptimizedGasPrice } from '../../utils/bundle-helpers.j
4
4
  import { ADDRESSES } from '../../utils/constants.js';
5
5
  import { getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, calculateBatchProfit } from './config.js';
6
6
  import { batchCheckAllowances } from '../../utils/erc20.js';
7
+ import { trySell } from '../tm.js';
7
8
  // ==================== TokenManager2 ABI(仅需要的方法)====================
8
9
  const TM2_ABI = [
9
10
  'function buyTokenAMAP(uint256 origin, address token, address to, uint256 funds, uint256 minAmount) payable',
@@ -229,16 +230,6 @@ export async function fourBatchPrivateSellMerkle(params) {
229
230
  if (privateKeys.length !== amounts.length) {
230
231
  throw new Error('privateKeys and amounts length mismatch');
231
232
  }
232
- // ⚠️ 友好提示:利润提取需要 minFundsEach
233
- if (!minFundsEach && shouldExtractProfit(config)) {
234
- console.log('\n⚠️ 重要提示:未传入 minFundsEach 参数,将无法提取利润!');
235
- console.log(' Four.meme 内盘代币无法自动报价,需要手动估算预期收益');
236
- console.log(' 建议步骤:');
237
- console.log(' 1. 在 four.meme 网站查看卖出预期收益');
238
- console.log(' 2. 传入 minFundsEach 参数');
239
- console.log(' 示例: minFundsEach: 0.1 (预计每个钱包收到 0.1 BNB)');
240
- console.log(' 如果只是测试卖出,可以忽略此提示\n');
241
- }
242
233
  const merkle = new MerkleClient({
243
234
  apiKey: config.apiKey,
244
235
  chainId: 56,
@@ -248,118 +239,76 @@ export async function fourBatchPrivateSellMerkle(params) {
248
239
  const tmAddr = ADDRESSES.BSC.TokenManagerOriginal;
249
240
  const gasPrice = await getOptimizedGasPrice(provider, getGasPriceConfig(config));
250
241
  const gasMultiplier = config.gasLimitMultiplier ?? 1.0;
251
- const minOut = minFundsEach ?? 0n;
252
242
  const sellGasLimit = BigInt(Math.ceil(800000 * gasMultiplier));
253
243
  const signedTxs = [];
254
244
  const nonceManager = new NonceManager(provider);
255
245
  const wallets = privateKeys.map((k) => new Wallet(k, provider));
256
- // ⚠️ Four.meme 可能对小数精度敏感,建议使用整数
257
- const amountsWei = amounts.map((a, idx) => {
258
- const amountWei = ethers.parseUnits(a, 18);
259
- const hasDecimals = a.includes('.');
260
- if (hasDecimals) {
261
- console.log(`⚠️ 钱包 ${idx}: 检测到小数卖出数量 ${a}`);
262
- console.log(` 建议: 使用整数数量(如 42988 而非 42988.04)可能提高成功率`);
263
- }
264
- return amountWei;
265
- });
246
+ const amountsWei = amounts.map((a) => ethers.parseUnits(a, 18));
247
+ // 自动获取每个钱包的预期收益(用于利润计算和滑点保护)
248
+ let quotedOutputs;
249
+ let minOuts;
250
+ if (minFundsEach !== undefined) {
251
+ // 用户提供了 minFundsEach,所有钱包使用相同的 minOut
252
+ const minOutWei = typeof minFundsEach === 'string' ? ethers.parseEther(minFundsEach) : minFundsEach;
253
+ minOuts = new Array(wallets.length).fill(minOutWei);
254
+ quotedOutputs = minOuts.map(m => m * 100n / 95n);
255
+ }
256
+ else {
257
+ // ✅ 自动调用 trySell 获取每个钱包的预期收益
258
+ console.log('💰 自动获取卖出报价...');
259
+ const rpcUrl = config.customRpcUrl;
260
+ quotedOutputs = await Promise.all(amountsWei.map(async (amount, i) => {
261
+ try {
262
+ const result = await trySell('BSC', rpcUrl, tokenAddress, amount);
263
+ const quoted = result.funds;
264
+ console.log(` 钱包 ${i}: 卖出 ${ethers.formatUnits(amount, 18)} 代币 → 预期收益 ${ethers.formatEther(quoted)} BNB`);
265
+ return quoted;
266
+ }
267
+ catch (error) {
268
+ console.log(` ⚠️ 钱包 ${i}: 报价失败,使用 minOut = 0`);
269
+ return 0n;
270
+ }
271
+ }));
272
+ // minOuts 设为预期收益的 95%(作为滑点保护)
273
+ minOuts = quotedOutputs.map(q => q * 95n / 100n);
274
+ console.log('');
275
+ }
266
276
  // ✅ Step 0: 检查代币余额
267
- console.log('🔍 检查代币余额...');
268
277
  const tokenContract = new ethers.Contract(tokenAddress, ERC20_ABI, provider);
269
278
  const balances = await Promise.all(wallets.map(w => tokenContract.balanceOf(w.address)));
270
279
  for (let i = 0; i < wallets.length; i++) {
271
- const balance = balances[i];
272
- const sellAmount = amountsWei[i];
273
- const balanceFormatted = ethers.formatUnits(balance, 18);
274
- const sellAmountFormatted = ethers.formatUnits(sellAmount, 18);
275
- console.log(` 钱包 ${i} (${wallets[i].address.slice(0, 6)}...${wallets[i].address.slice(-4)}):`);
276
- console.log(` 代币余额: ${balanceFormatted}`);
277
- console.log(` 卖出数量: ${sellAmountFormatted}`);
278
- if (balance < sellAmount) {
279
- throw new Error(`钱包 ${i} (${wallets[i].address}) 代币余额不足\n` +
280
- `需要: ${sellAmountFormatted}\n` +
281
- `实际: ${balanceFormatted}`);
280
+ if (balances[i] < amountsWei[i]) {
281
+ throw new Error(`钱包 ${i} 代币余额不足:` +
282
+ `需要 ${ethers.formatUnits(amountsWei[i], 18)},` +
283
+ `实际 ${ethers.formatUnits(balances[i], 18)}`);
282
284
  }
283
285
  }
284
- // ✅ Step 1: 使用 Multicall3 批量检查授权状态
285
- console.log('\n🔍 使用 Multicall3 批量检查授权状态...');
286
+ // ✅ Step 1: 检查授权状态
286
287
  const allowances = await batchCheckAllowances(provider, tokenAddress, wallets.map(w => w.address), tmAddr);
287
- // 找出需要授权的钱包索引
288
- // ✅ 检查授权额度是否足够卖出
289
288
  const needApprovalIndexes = [];
290
289
  for (let i = 0; i < wallets.length; i++) {
291
- const allowance = allowances[i];
292
- const sellAmount = amountsWei[i];
293
- const allowanceFormatted = allowance === ethers.MaxUint256 ? 'MAX (无限)' : ethers.formatUnits(allowance, 18);
294
- const sellAmountFormatted = ethers.formatUnits(sellAmount, 18);
295
- console.log(` 钱包 ${i}:`);
296
- console.log(` 当前授权: ${allowanceFormatted}`);
297
- console.log(` 需要授权: ${sellAmountFormatted}`);
298
- // ✅ 检查授权额度是否 >= 卖出数量
299
- if (allowance < sellAmount) {
290
+ if (allowances[i] < amountsWei[i]) {
300
291
  needApprovalIndexes.push(i);
301
- console.log(` ❌ 授权不足!`);
302
- }
303
- else {
304
- console.log(` ✅ 授权充足`);
305
292
  }
306
293
  }
307
- console.log(`\n 📊 授权统计:`);
308
- console.log(` 总钱包数: ${wallets.length}`);
309
- console.log(` 需要授权: ${needApprovalIndexes.length}`);
310
- console.log(` 已有授权: ${wallets.length - needApprovalIndexes.length}\n`);
311
- // ✅ Step 2: 如果需要授权,抛出错误提示
312
- // ⚠️ SDK不再处理授权,需要前端先单独授权
313
294
  if (needApprovalIndexes.length > 0) {
314
- console.log(`⚠️ 警告:检测到 ${needApprovalIndexes.length} 个钱包需要授权`);
315
- console.log(' 请先使用 approveFourTokenManagerBatch 方法授权');
316
- console.log(' ⚠️ 重要:请使用 amounts: ["max", "max", ...] 授权,避免重复授权');
317
- throw new Error(`需要授权: ${needApprovalIndexes.length} 个钱包授权额度不足。\n` +
318
- `解决方案:调用 approveFourTokenManagerBatch({ amounts: ['max', 'max', ...] })`);
295
+ throw new Error(`${needApprovalIndexes.length} 个钱包需要授权。` +
296
+ `请先调用 approveFourTokenManagerBatch({ amounts: ['max', ...] })`);
319
297
  }
320
- // ✅ Step 3: 检查 BNB 余额(用于支付 gas)
321
- console.log('💰 检查 BNB 余额(用于支付 gas 费)...');
298
+ // ✅ Step 2: 检查 BNB 余额(用于支付 gas)
322
299
  const bnbBalances = await Promise.all(wallets.map(w => provider.getBalance(w.address)));
323
300
  const estimatedGasCost = sellGasLimit * gasPrice;
324
301
  for (let i = 0; i < wallets.length; i++) {
325
- const bnbBalance = bnbBalances[i];
326
- const bnbFormatted = ethers.formatEther(bnbBalance);
327
- const gasFormatted = ethers.formatEther(estimatedGasCost);
328
- console.log(` 钱包 ${i}:`);
329
- console.log(` BNB 余额: ${bnbFormatted}`);
330
- console.log(` 预计 Gas: ${gasFormatted}`);
331
- if (bnbBalance < estimatedGasCost) {
332
- console.log(` ❌ BNB 不足!`);
333
- throw new Error(`钱包 ${i} BNB 余额不足支付 gas 费\n` +
334
- `需要: ${gasFormatted} BNB\n` +
335
- `实际: ${bnbFormatted} BNB\n` +
336
- `缺少: ${ethers.formatEther(estimatedGasCost - bnbBalance)} BNB`);
337
- }
338
- else {
339
- const remaining = bnbBalance - estimatedGasCost;
340
- console.log(` ✅ BNB 充足(剩余 ${ethers.formatEther(remaining)})`);
302
+ if (bnbBalances[i] < estimatedGasCost) {
303
+ throw new Error(`钱包 ${i} BNB 不足:` +
304
+ `需要 ${ethers.formatEther(estimatedGasCost)} BNB,` +
305
+ `实际 ${ethers.formatEther(bnbBalances[i])} BNB`);
341
306
  }
342
307
  }
343
- // ✅ Step 4: 为每个钱包生成卖出交易
344
- console.log('\n💰 构建卖出交易...');
345
- console.log(` TokenManager 合约: ${tmAddr}`);
346
- console.log(` 代币地址: ${tokenAddress}`);
347
- console.log(` minFundsEach (最小收益): ${minOut === 0n ? '0 (不限制)' : ethers.formatEther(minOut) + ' BNB'}`);
308
+ // ✅ Step 3: 构建卖出交易
348
309
  const tm2Contracts = wallets.map((w) => new ethers.Contract(tmAddr, TM2_ABI, w));
349
- // 显示每个交易的详细参数
350
- console.log(`\n 📋 交易参数:`);
351
- for (let i = 0; i < wallets.length; i++) {
352
- console.log(` 钱包 ${i}:`);
353
- console.log(` 卖出数量: ${ethers.formatUnits(amountsWei[i], 18)} 代币`);
354
- console.log(` 最小收益: ${minOut === 0n ? '0 BNB (接受任何价格)' : ethers.formatEther(minOut) + ' BNB'}`);
355
- console.log(` 合约方法: sellToken(origin=0, token=${tokenAddress.slice(0, 8)}..., amount=${ethers.formatUnits(amountsWei[i], 18)}, minFunds=${minOut})`);
356
- }
357
- const sellUnsigned = await Promise.all(tm2Contracts.map((c, i) => c.sellToken.populateTransaction(0n, tokenAddress, amountsWei[i], minOut)));
310
+ const sellUnsigned = await Promise.all(tm2Contracts.map((c, i) => c.sellToken.populateTransaction(0n, tokenAddress, amountsWei[i], minOuts[i])));
358
311
  const sellGasLimits = new Array(wallets.length).fill(sellGasLimit);
359
- console.log(`\n ⛽ Gas 设置:`);
360
- console.log(` Gas Limit: ${sellGasLimit}`);
361
- console.log(` Gas Price: ${ethers.formatUnits(gasPrice, 'gwei')} Gwei`);
362
- console.log(` 预计 Gas 费: ${ethers.formatEther(sellGasLimit * gasPrice)} BNB (每笔)\n`);
363
312
  const sellNonces = await Promise.all(wallets.map((w) => nonceManager.getNextNonce(w)));
364
313
  const signedSells = await Promise.all(sellUnsigned.map((unsigned, i) => wallets[i].signTransaction({
365
314
  ...unsigned,
@@ -371,42 +320,29 @@ export async function fourBatchPrivateSellMerkle(params) {
371
320
  type: getTxType(config)
372
321
  })));
373
322
  signedTxs.push(...signedSells);
374
- console.log(`✅ 已生成 ${signedSells.length} 个卖出交易签名\n`);
375
- // ✅ 基于 minFunds 为每个钱包添加利润转账
323
+ // 提取利润(基于每个钱包的预期收益)
376
324
  const extractProfit = shouldExtractProfit(config);
377
325
  if (extractProfit) {
378
- if (minOut > 0n) {
379
- const { profit } = calculateProfit(minOut, config);
380
- if (profit > 0n) {
381
- console.log(`💰 提取利润交易...`);
382
- console.log(` 每个钱包从 ${ethers.formatEther(minOut)} BNB 中提取 ${ethers.formatEther(profit)} BNB (${config.profitRateBps / 100}%)`);
383
- // 为每个钱包添加利润转账
384
- const profitNonces = await Promise.all(wallets.map(w => nonceManager.getNextNonce(w)));
385
- const profitTxs = await Promise.all(wallets.map((wallet, i) => wallet.signTransaction({
386
- to: config.profitRecipient,
387
- value: profit,
388
- nonce: profitNonces[i],
389
- gasPrice,
390
- gasLimit: 21000n,
391
- chainId: 56,
392
- type: getTxType(config)
393
- })));
394
- signedTxs.push(...profitTxs);
395
- console.log(` ✅ 已添加 ${wallets.length} 个利润转账交易\n`);
326
+ for (let i = 0; i < wallets.length; i++) {
327
+ if (quotedOutputs[i] > 0n) {
328
+ const { profit } = calculateProfit(quotedOutputs[i], config);
329
+ if (profit > 0n) {
330
+ const profitNonce = await nonceManager.getNextNonce(wallets[i]);
331
+ const profitTx = await wallets[i].signTransaction({
332
+ to: config.profitRecipient,
333
+ value: profit,
334
+ nonce: profitNonce,
335
+ gasPrice,
336
+ gasLimit: 21000n,
337
+ chainId: 56,
338
+ type: getTxType(config)
339
+ });
340
+ signedTxs.push(profitTx);
341
+ }
396
342
  }
397
343
  }
398
- else {
399
- console.log(`⚠️ minFundsEach = 0,无法提取利润(建议传入 minFundsEach 参数)\n`);
400
- }
401
344
  }
402
- // ✅ 清理临时 nonce 缓存
403
345
  nonceManager.clearTemp();
404
- console.log(`📦 Bundle 摘要:`);
405
- console.log(` 总交易数: ${signedTxs.length}`);
406
- console.log(` - 卖出交易: ${signedSells.length}`);
407
- console.log(` - 利润交易: ${signedTxs.length - signedSells.length}`);
408
- console.log(`\n⚠️ 注意: 交易已签名,但尚未提交到链上`);
409
- console.log(` 请将 signedTransactions 提交到服务器,由服务器调用 Merkle API\n`);
410
346
  // ✅ 简化返回:只返回签名交易
411
347
  return {
412
348
  signedTransactions: signedTxs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.1.99",
3
+ "version": "1.2.2",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",