four-flap-meme-sdk 1.1.83 → 1.1.84

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.
@@ -3,7 +3,7 @@ import { MerkleClient } from '../../clients/merkle.js';
3
3
  import { NonceManager, getOptimizedGasPrice } from '../../utils/bundle-helpers.js';
4
4
  import { ADDRESSES } from '../../utils/constants.js';
5
5
  import { FourClient, buildLoginMessage } from '../../clients/four.js';
6
- import { getErrorMessage, getTxType, getBundleOptions, getGasPriceConfig, shouldExtractProfit, calculateProfit } from './config.js';
6
+ import { getErrorMessage, getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit } from './config.js';
7
7
  // ==================== TokenManager2 ABI(仅需要的方法)====================
8
8
  const TM2_ABI = [
9
9
  'function createToken(bytes args, bytes signature) payable',
@@ -201,111 +201,30 @@ export async function createTokenWithBundleBuyMerkle(params) {
201
201
  });
202
202
  signedTxs.push(profitTx);
203
203
  }
204
- // ✅ 如果配置了 skipSubmit,直接返回签名交易
205
- if (config.skipSubmit) {
206
- nonceManager.clearTemp();
207
- const emptyStatus = {
208
- bundleHash: '',
209
- txHashes: [],
210
- results: [],
211
- successCount: 0,
212
- totalGasUsed: 0n,
213
- targetBlock: 0
214
- };
215
- return {
216
- bundleHash: '',
217
- tokenAddress: predictedTokenAddress,
218
- status: emptyStatus,
219
- createTx: signedCreateTx,
220
- buyTxs: [],
221
- signedTransactions: signedTxs,
222
- metadata: extractProfit ? {
223
- totalBuyAmount: ethers.formatEther(totalBuyAmount),
224
- profitAmount: ethers.formatEther(totalProfit),
225
- profitRecipient: config.profitRecipient,
226
- buyerCount: buyers.length
227
- } : undefined
228
- };
229
- }
230
- // 5. 提交 Bundle(使用智能配置)
231
- const bundleResult = await merkle.sendBundle({
232
- transactions: signedTxs,
233
- ...getBundleOptions(config, blockOffset)
234
- });
235
- // 6. 根据配置决定是否等待确认
236
- const waitForConfirmation = config.waitForConfirmation ?? false;
237
- if (!waitForConfirmation) {
238
- const status = {
239
- bundleHash: bundleResult.bundleHash,
240
- txHashes: bundleResult.txHashes,
241
- results: [],
242
- successCount: 0,
243
- totalGasUsed: 0n,
244
- targetBlock: bundleResult.targetBlock
245
- };
246
- // 清理临时 nonce 缓存
247
- nonceManager.clearTemp();
248
- return {
249
- bundleHash: bundleResult.bundleHash,
250
- tokenAddress: undefined,
251
- status,
252
- createTx: signedCreateTx,
253
- buyTxs
254
- };
255
- }
256
- // 7. 等待确认
257
- const results = await merkle.waitForBundleConfirmation(bundleResult.txHashes, 1, config.waitTimeoutMs ?? 120000);
258
- const successCount = results.filter(r => r.success).length;
259
- const totalGasUsed = results.reduce((sum, r) => {
260
- if (r.gasUsed) {
261
- return sum + BigInt(r.gasUsed);
262
- }
263
- return sum;
264
- }, 0n);
265
- const status = {
266
- bundleHash: bundleResult.bundleHash,
267
- txHashes: bundleResult.txHashes,
268
- results,
269
- successCount,
270
- totalGasUsed,
271
- targetBlock: bundleResult.targetBlock
272
- };
273
- // 8. 解析 TokenCreate 事件
274
- let createdTokenAddress;
275
- if (results[0]?.success) {
276
- try {
277
- const createTxHash = bundleResult.txHashes[0];
278
- if (createTxHash) {
279
- const receipt = await provider.getTransactionReceipt(createTxHash);
280
- if (receipt && receipt.logs) {
281
- const tm2Interface = new ethers.Interface(TM2_ABI);
282
- for (const log of receipt.logs) {
283
- try {
284
- const parsed = tm2Interface.parseLog({ topics: log.topics, data: log.data });
285
- if (parsed && parsed.name === 'TokenCreate') {
286
- createdTokenAddress = parsed.args.token;
287
- break;
288
- }
289
- }
290
- catch (e) {
291
- // 忽略
292
- }
293
- }
294
- }
295
- }
296
- }
297
- catch (e) {
298
- console.warn('Failed to parse token address from receipt:', e);
299
- }
300
- }
301
- // 清理临时 nonce 缓存
204
+ // ✅ 清理临时 nonce 缓存
302
205
  nonceManager.clearTemp();
206
+ // ✅ 直接返回签名交易(不提交到Merkle)
207
+ const emptyStatus = {
208
+ bundleHash: '',
209
+ txHashes: [],
210
+ results: [],
211
+ successCount: 0,
212
+ totalGasUsed: 0n,
213
+ targetBlock: 0
214
+ };
303
215
  return {
304
- bundleHash: bundleResult.bundleHash,
305
- tokenAddress: createdTokenAddress,
306
- status,
216
+ bundleHash: '',
217
+ tokenAddress: predictedTokenAddress,
218
+ status: emptyStatus,
307
219
  createTx: signedCreateTx,
308
- buyTxs
220
+ buyTxs: [],
221
+ signedTransactions: signedTxs,
222
+ metadata: extractProfit ? {
223
+ totalBuyAmount: ethers.formatEther(totalBuyAmount),
224
+ profitAmount: ethers.formatEther(totalProfit),
225
+ profitRecipient: config.profitRecipient,
226
+ buyerCount: buyers.length
227
+ } : undefined
309
228
  };
310
229
  }
311
230
  /**
@@ -379,67 +298,29 @@ export async function batchBuyWithBundleMerkle(params) {
379
298
  });
380
299
  signedTxs.push(profitTx);
381
300
  }
382
- // ✅ 如果配置了 skipSubmit,直接返回签名交易
383
- if (config.skipSubmit) {
384
- nonceManager.clearTemp();
385
- const emptyStatus = {
386
- bundleHash: '',
387
- txHashes: [],
388
- results: [],
389
- successCount: 0,
390
- totalGasUsed: 0n,
391
- targetBlock: 0
392
- };
393
- return {
394
- bundleHash: '',
395
- status: emptyStatus,
396
- buyTxs: [],
397
- signedTransactions: signedTxs,
398
- metadata: extractProfit ? {
399
- totalBuyAmount: ethers.formatEther(totalBuyAmount),
400
- profitAmount: ethers.formatEther(totalProfit),
401
- profitRecipient: config.profitRecipient,
402
- buyerCount: buyers.length
403
- } : undefined
404
- };
405
- }
406
- const bundleResult = await merkle.sendBundle({
407
- transactions: signedTxs,
408
- ...getBundleOptions(config, blockOffset)
409
- });
410
- const waitForConfirmation = config.waitForConfirmation ?? false;
411
- if (!waitForConfirmation) {
412
- const status = {
413
- bundleHash: bundleResult.bundleHash,
414
- txHashes: bundleResult.txHashes,
415
- results: [],
416
- successCount: 0,
417
- totalGasUsed: 0n,
418
- targetBlock: bundleResult.targetBlock
419
- };
420
- // 清理临时 nonce 缓存
421
- nonceManager.clearTemp();
422
- return { bundleHash: bundleResult.bundleHash, status, buyTxs: signedTxs };
423
- }
424
- const results = await merkle.waitForBundleConfirmation(bundleResult.txHashes, 1, config.waitTimeoutMs ?? 120000);
425
- const successCount = results.filter(r => r.success).length;
426
- const totalGasUsed = results.reduce((sum, r) => {
427
- if (r.gasUsed) {
428
- return sum + BigInt(r.gasUsed);
429
- }
430
- return sum;
431
- }, 0n);
432
- const status = {
433
- bundleHash: bundleResult.bundleHash,
434
- txHashes: bundleResult.txHashes,
435
- results,
436
- successCount,
437
- totalGasUsed,
438
- targetBlock: bundleResult.targetBlock
439
- };
440
- // 清理临时 nonce 缓存
301
+ // ✅ 清理临时 nonce 缓存
441
302
  nonceManager.clearTemp();
442
- return { bundleHash: bundleResult.bundleHash, status, buyTxs: signedTxs };
303
+ // 直接返回签名交易(不提交到Merkle)
304
+ const emptyStatus = {
305
+ bundleHash: '',
306
+ txHashes: [],
307
+ results: [],
308
+ successCount: 0,
309
+ totalGasUsed: 0n,
310
+ targetBlock: 0
311
+ };
312
+ return {
313
+ bundleHash: '',
314
+ status: emptyStatus,
315
+ buyTxs: [],
316
+ signedTransactions: signedTxs,
317
+ metadata: extractProfit ? {
318
+ totalBuyAmount: ethers.formatEther(totalBuyAmount),
319
+ profitAmount: ethers.formatEther(totalProfit),
320
+ profitRecipient: config.profitRecipient,
321
+ buyerCount: buyers.length
322
+ } : undefined
323
+ };
443
324
  }
444
325
  /**
445
326
  * four.meme: 批量卖出(Merkle 版本)
@@ -484,40 +365,11 @@ export async function batchSellWithBundleMerkle(params) {
484
365
  console.log(` - 需要授权: ${needApprovalIndexes.length}`);
485
366
  console.log(` - 已有授权: ${sellers.length - needApprovalIndexes.length}\n`);
486
367
  // ✅ Step 2: 批量授权(如果需要)
368
+ // ⚠️ 注意:授权需要单独提交,SDK只返回签名交易
487
369
  if (needApprovalIndexes.length > 0) {
488
- console.log('🔓 提交授权交易...');
489
- const nonceManager = new NonceManager(provider);
490
- const approveSignedTxs = [];
491
- const needApprovalSellers = needApprovalIndexes.map(i => sellers[i]);
492
- const tokenContractsForApprove = needApprovalSellers.map((w) => new ethers.Contract(tokenAddress, ERC20_ABI, w));
493
- const approveUnsigned = await Promise.all(tokenContractsForApprove.map((c) => c.approve.populateTransaction(tmAddr, ethers.MaxUint256 // 授权最大额度
494
- )));
495
- const approveGasLimit = getGasLimit(config, 80000);
496
- const approveNonces = await Promise.all(needApprovalSellers.map((w) => nonceManager.getNextNonce(w)));
497
- const signedApproves = await Promise.all(approveUnsigned.map((unsigned, i) => needApprovalSellers[i].signTransaction({
498
- ...unsigned,
499
- from: needApprovalSellers[i].address,
500
- nonce: approveNonces[i],
501
- gasLimit: approveGasLimit,
502
- gasPrice: gasPrice,
503
- chainId: 56,
504
- type: getTxType(config)
505
- })));
506
- approveSignedTxs.push(...signedApproves);
507
- nonceManager.clearTemp();
508
- // 提交授权 Bundle 并等待确认
509
- const approveBundleResult = await merkle.sendBundle({
510
- transactions: approveSignedTxs,
511
- ...getBundleOptions(config, blockOffset)
512
- });
513
- console.log(` Bundle Hash: ${approveBundleResult.bundleHash}`);
514
- console.log('⏳ 等待授权确认...');
515
- const approveResults = await merkle.waitForBundleConfirmation(approveBundleResult.txHashes, 1, config.waitTimeoutMs ?? 120000);
516
- const approveSuccessCount = approveResults.filter(r => r.success).length;
517
- console.log(`✅ 授权完成: ${approveSuccessCount}/${needApprovalIndexes.length}\n`);
518
- if (approveSuccessCount !== needApprovalIndexes.length) {
519
- throw new Error(`授权失败: 只有 ${approveSuccessCount}/${needApprovalIndexes.length} 笔授权成功`);
520
- }
370
+ console.log('⚠️ 警告:检测到 ${needApprovalIndexes.length} 个钱包需要授权');
371
+ console.log(' 请先使用这些钱包的私钥调用授权方法,授权完成后再调用卖出方法');
372
+ throw new Error(`需要授权: ${needApprovalIndexes.length} 个钱包尚未授权。请先完成授权后再卖出。`);
521
373
  }
522
374
  // ✅ Step 3: 批量卖出
523
375
  console.log('💰 提交卖出交易...');
@@ -539,41 +391,21 @@ export async function batchSellWithBundleMerkle(params) {
539
391
  type: getTxType(config)
540
392
  })));
541
393
  signedTxs.push(...signedList);
542
- const bundleResult = await merkle.sendBundle({
543
- transactions: signedTxs,
544
- ...getBundleOptions(config, blockOffset)
545
- });
546
- const waitForConfirmation = config.waitForConfirmation ?? false;
547
- if (!waitForConfirmation) {
548
- const status = {
549
- bundleHash: bundleResult.bundleHash,
550
- txHashes: bundleResult.txHashes,
551
- results: [],
552
- successCount: 0,
553
- totalGasUsed: 0n,
554
- targetBlock: bundleResult.targetBlock
555
- };
556
- // 清理临时 nonce 缓存
557
- nonceManager.clearTemp();
558
- return { bundleHash: bundleResult.bundleHash, status, sellTxs: signedTxs };
559
- }
560
- const results = await merkle.waitForBundleConfirmation(bundleResult.txHashes, 1, config.waitTimeoutMs ?? 120000);
561
- const successCount = results.filter(r => r.success).length;
562
- const totalGasUsed = results.reduce((sum, r) => {
563
- if (r.gasUsed) {
564
- return sum + BigInt(r.gasUsed);
565
- }
566
- return sum;
567
- }, 0n);
568
- const status = {
569
- bundleHash: bundleResult.bundleHash,
570
- txHashes: bundleResult.txHashes,
571
- results,
572
- successCount,
573
- totalGasUsed,
574
- targetBlock: bundleResult.targetBlock
575
- };
576
- // 清理临时 nonce 缓存
394
+ // 清理临时 nonce 缓存
577
395
  nonceManager.clearTemp();
578
- return { bundleHash: bundleResult.bundleHash, status, sellTxs: signedTxs };
396
+ // 直接返回签名交易(不提交到Merkle)
397
+ const emptyStatus = {
398
+ bundleHash: '',
399
+ txHashes: [],
400
+ results: [],
401
+ successCount: 0,
402
+ totalGasUsed: 0n,
403
+ targetBlock: 0
404
+ };
405
+ return {
406
+ bundleHash: '',
407
+ status: emptyStatus,
408
+ sellTxs: [],
409
+ signedTransactions: signedTxs
410
+ };
579
411
  }
@@ -332,32 +332,21 @@ export async function fourPancakeProxyBatchBuyMerkle(params) {
332
332
  });
333
333
  signedTxs.push(profitTx);
334
334
  }
335
- // ✅ 如果配置了 skipSubmit,直接返回
336
- if (config.skipSubmit) {
337
- nonceManager.clearTemp();
338
- return {
339
- bundleHash: '',
340
- status: {
341
- bundleHash: '',
342
- txHashes: [],
343
- results: [],
344
- successCount: 0,
345
- totalGasUsed: 0n,
346
- targetBlock: 0
347
- },
348
- buyTxs: signedTxs
349
- };
350
- }
351
- const bundleResult = await merkle.sendBundle({
352
- transactions: signedTxs,
353
- ...getBundleOptions(config, blockOffset)
354
- });
335
+ // ✅ 清理临时 nonce 缓存
355
336
  nonceManager.clearTemp();
356
- const status = await waitForBundleResult(merkle, bundleResult, config.waitForConfirmation ?? false, config.waitTimeoutMs ?? 120000);
337
+ // 直接返回签名交易(不提交到Merkle)
357
338
  return {
358
- bundleHash: bundleResult.bundleHash,
359
- status,
360
- buyTxs: []
339
+ bundleHash: '',
340
+ status: {
341
+ bundleHash: '',
342
+ txHashes: [],
343
+ results: [],
344
+ successCount: 0,
345
+ totalGasUsed: 0n,
346
+ targetBlock: 0
347
+ },
348
+ buyTxs: [],
349
+ signedTransactions: signedTxs
361
350
  };
362
351
  }
363
352
  /**
@@ -397,40 +386,12 @@ export async function fourPancakeProxyBatchSellMerkle(params) {
397
386
  console.log(` - 总钱包数: ${sellers.length}`);
398
387
  console.log(` - 需要授权: ${needApprovalIndexes.length}`);
399
388
  console.log(` - 已有授权: ${sellers.length - needApprovalIndexes.length}\n`);
400
- // ✅ Step 2: 批量授权(如果需要)
389
+ // ✅ Step 2: 如果需要授权,抛出错误提示
390
+ // ⚠️ SDK不再处理授权,需要前端先单独授权
401
391
  if (needApprovalIndexes.length > 0) {
402
- console.log('🔓 提交授权交易...');
403
- const nonceManager = new NonceManager(provider);
404
- const approveSignedTxs = [];
405
- const needApprovalSellers = needApprovalIndexes.map(i => sellers[i]);
406
- const tokenContractsForApprove = needApprovalSellers.map((w) => new Contract(tokenAddress, ERC20_ABI, w));
407
- const approveUnsigned = await Promise.all(tokenContractsForApprove.map((c) => c.approve.populateTransaction(pancakeProxyAddress, ethers.MaxUint256)));
408
- const approveGasLimit = getGasLimit(config, 80000);
409
- const approveNonces = await Promise.all(needApprovalSellers.map((w) => nonceManager.getNextNonce(w)));
410
- const signedApproves = await Promise.all(approveUnsigned.map((unsigned, i) => needApprovalSellers[i].signTransaction({
411
- ...unsigned,
412
- from: needApprovalSellers[i].address,
413
- nonce: approveNonces[i],
414
- gasLimit: approveGasLimit,
415
- gasPrice: gasPrice,
416
- chainId: 56,
417
- type: getTxType(config)
418
- })));
419
- approveSignedTxs.push(...signedApproves);
420
- nonceManager.clearTemp();
421
- // 提交授权 Bundle 并等待确认
422
- const approveBundleResult = await merkle.sendBundle({
423
- transactions: approveSignedTxs,
424
- ...getBundleOptions(config, blockOffset)
425
- });
426
- console.log(` Bundle Hash: ${approveBundleResult.bundleHash}`);
427
- console.log('⏳ 等待授权确认...');
428
- const approveResults = await merkle.waitForBundleConfirmation(approveBundleResult.txHashes, 1, config.waitTimeoutMs ?? 120000);
429
- const approveSuccessCount = approveResults.filter(r => r.success).length;
430
- console.log(`✅ 授权完成: ${approveSuccessCount}/${needApprovalIndexes.length}\n`);
431
- if (approveSuccessCount !== needApprovalIndexes.length) {
432
- throw new Error(`授权失败: 只有 ${approveSuccessCount}/${needApprovalIndexes.length} 笔授权成功`);
433
- }
392
+ console.log('⚠️ 警告:检测到 ${needApprovalIndexes.length} 个钱包需要授权');
393
+ console.log(' 请先使用这些钱包完成授权后再调用卖出方法');
394
+ throw new Error(`需要授权: ${needApprovalIndexes.length} 个钱包尚未授权。请先完成授权后再卖出。`);
434
395
  }
435
396
  // ✅ Step 3: 批量卖出
436
397
  console.log('💰 提交卖出交易...');
@@ -565,54 +526,20 @@ export async function fourPancakeProxyBatchSellMerkle(params) {
565
526
  }
566
527
  }
567
528
  }
529
+ // ✅ 清理临时 nonce 缓存
568
530
  nonceManager.clearTemp();
569
- // ✅ 如果配置了 skipSubmit,直接返回
570
- if (config.skipSubmit) {
571
- return {
572
- bundleHash: '',
573
- status: {
574
- bundleHash: '',
575
- txHashes: [],
576
- results: [],
577
- successCount: 0,
578
- totalGasUsed: 0n,
579
- targetBlock: 0
580
- },
581
- sellTxs: signedTxs
582
- };
583
- }
584
- console.log('🚀 提交卖出 Bundle...\n');
585
- let bundleResult;
586
- try {
587
- bundleResult = await merkle.sendBundle({
588
- transactions: signedTxs,
589
- ...getBundleOptions(config, blockOffset)
590
- });
591
- console.log(` ✅ Bundle 已提交: ${bundleResult.bundleHash}`);
592
- }
593
- catch (error) {
594
- console.error('❌ 提交 Bundle 失败:', error.message);
595
- throw new Error(`卖出 Bundle 提交失败: ${error.message}`);
596
- }
597
- const status = await waitForBundleResult(merkle, bundleResult, config.waitForConfirmation ?? false, config.waitTimeoutMs ?? 120000);
598
- if (status.successCount === sellers.length) {
599
- console.log(`✅ 卖出完成: ${status.successCount}/${sellers.length} 全部成功\n`);
600
- }
601
- else {
602
- console.log(`⚠️ 卖出完成: ${status.successCount}/${sellers.length} 成功`);
603
- console.log(` 失败数量: ${sellers.length - status.successCount}\n`);
604
- // 打印失败详情
605
- if (status.results && status.results.length > 0) {
606
- status.results.forEach((result, i) => {
607
- if (!result.success && result.error) {
608
- console.log(` 交易 ${i + 1} 失败: ${result.error}`);
609
- }
610
- });
611
- }
612
- }
531
+ // ✅ 直接返回签名交易(不提交到Merkle)
613
532
  return {
614
- bundleHash: bundleResult.bundleHash,
615
- status,
616
- sellTxs: []
533
+ bundleHash: '',
534
+ status: {
535
+ bundleHash: '',
536
+ txHashes: [],
537
+ results: [],
538
+ successCount: 0,
539
+ totalGasUsed: 0n,
540
+ targetBlock: 0
541
+ },
542
+ sellTxs: [],
543
+ signedTransactions: signedTxs
617
544
  };
618
545
  }