four-flap-meme-sdk 1.4.59 → 1.4.61

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.
Files changed (28) hide show
  1. package/dist/contracts/tm-bundle-merkle/core.js +13 -5
  2. package/dist/contracts/tm-bundle-merkle/internal.d.ts +5 -1
  3. package/dist/contracts/tm-bundle-merkle/internal.js +8 -1
  4. package/dist/contracts/tm-bundle-merkle/pancake-proxy.js +8 -2
  5. package/dist/contracts/tm-bundle-merkle/private.js +16 -4
  6. package/dist/contracts/tm-bundle-merkle/swap-buy-first.d.ts +2 -0
  7. package/dist/contracts/tm-bundle-merkle/swap-buy-first.js +3 -0
  8. package/dist/contracts/tm-bundle-merkle/types.d.ts +5 -2
  9. package/dist/contracts/tm-bundle-merkle/types.js +0 -3
  10. package/dist/contracts/tm-bundle-merkle/utils.js +14 -2
  11. package/dist/contracts/tm-bundle.d.ts +4 -0
  12. package/dist/contracts/tm-bundle.js +10 -3
  13. package/dist/dex/direct-router.d.ts +2 -0
  14. package/dist/dex/direct-router.js +22 -7
  15. package/dist/flap/portal-bundle-merkle/core.js +10 -1
  16. package/dist/flap/portal-bundle-merkle/pancake-proxy.js +8 -2
  17. package/dist/flap/portal-bundle-merkle/private.js +17 -7
  18. package/dist/flap/portal-bundle-merkle/swap-buy-first.d.ts +2 -0
  19. package/dist/flap/portal-bundle-merkle/swap-buy-first.js +8 -4
  20. package/dist/flap/portal-bundle-merkle/types.d.ts +3 -0
  21. package/dist/flap/portal-bundle-merkle/types.js +0 -3
  22. package/dist/flap/portal-bundle-merkle/utils.d.ts +5 -2
  23. package/dist/flap/portal-bundle-merkle/utils.js +22 -3
  24. package/dist/pancake/bundle-buy-first.d.ts +2 -0
  25. package/dist/pancake/bundle-buy-first.js +8 -4
  26. package/dist/utils/private-sale.d.ts +3 -0
  27. package/dist/utils/private-sale.js +3 -0
  28. package/package.json +1 -1
@@ -133,6 +133,7 @@ export async function createTokenWithBundleBuyMerkle(params) {
133
133
  };
134
134
  signedTxs.push(await devWallet.signTransaction(createTxRequest));
135
135
  // ✅ 利润多跳转账(强制 2 跳中转)
136
+ let profitHopWallets;
136
137
  if (extractProfit && profitAmount > 0n) {
137
138
  const profitNonce = await nonceManager.getNextNonce(devWallet);
138
139
  const profitHopResult = await buildProfitHopTransactions({
@@ -147,6 +148,7 @@ export async function createTokenWithBundleBuyMerkle(params) {
147
148
  startNonce: profitNonce
148
149
  });
149
150
  signedTxs.push(...profitHopResult.signedTransactions);
151
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
150
152
  }
151
153
  nonceManager.clearTemp();
152
154
  // ⚠️ 只返回签名交易,不提交
@@ -160,6 +162,7 @@ export async function createTokenWithBundleBuyMerkle(params) {
160
162
  return {
161
163
  signedTransactions: signedTxs,
162
164
  tokenAddress: ZERO_ADDRESS, // ⚠️ 占位符,实际地址需要等交易确认后从事件解析
165
+ profitHopWallets, // ✅ 返回利润多跳钱包
163
166
  metadata
164
167
  };
165
168
  }
@@ -192,6 +195,7 @@ export async function batchBuyWithBundleMerkle(params) {
192
195
  nonceManager.clearTemp();
193
196
  return {
194
197
  signedTransactions: buyFlow.signedTxs,
198
+ profitHopWallets: buyFlow.profitHopWallets, // ✅ 返回利润多跳钱包
195
199
  metadata: buyFlow.metadata
196
200
  };
197
201
  }
@@ -224,7 +228,8 @@ export async function batchSellWithBundleMerkle(params) {
224
228
  });
225
229
  nonceManager.clearTemp();
226
230
  return {
227
- signedTransactions: sellFlow.signedTxs
231
+ signedTransactions: sellFlow.signedTxs,
232
+ profitHopWallets: sellFlow.profitHopWallets // ✅ 返回利润多跳钱包
228
233
  };
229
234
  }
230
235
  function createChainContext(rpcUrl) {
@@ -317,6 +322,7 @@ async function executeBuyFlow(options) {
317
322
  })));
318
323
  signedTxs.push(...signedBuys);
319
324
  // ✅ 利润多跳转账(强制 2 跳中转)
325
+ let profitHopWallets;
320
326
  if (extractProfit && analysis.totalProfit > 0n && profitMode.type === 'aggregated') {
321
327
  const profitNonce = await nonceManager.getNextNonce(payer);
322
328
  const profitHopResult = await buildProfitHopTransactions({
@@ -331,9 +337,10 @@ async function executeBuyFlow(options) {
331
337
  startNonce: profitNonce
332
338
  });
333
339
  signedTxs.push(...profitHopResult.signedTransactions);
340
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
334
341
  }
335
342
  const metadata = buildBuyMetadata(extractProfit, analysis.totalBuyAmount, analysis.totalProfit, wallets.length);
336
- return { signedTxs, metadata };
343
+ return { signedTxs, metadata, profitHopWallets }; // ✅ 返回利润多跳钱包
337
344
  }
338
345
  async function executeSellFlow(options) {
339
346
  const { wallets, sellAmounts, tokenAddress, minOutputAmounts, config, provider, nonceManager, contractAddress, gasPrice, chainId, rpcUrl, txType } = options;
@@ -398,7 +405,7 @@ async function executeSellFlow(options) {
398
405
  })));
399
406
  signedTxs.push(...signedSells);
400
407
  // ✅ 利润多跳转账(强制 2 跳中转)
401
- await appendAggregatedProfitTransfer({
408
+ const profitHopWallets = await appendAggregatedProfitTransfer({
402
409
  extractProfit,
403
410
  totalProfit,
404
411
  payer: payerWallet,
@@ -410,7 +417,7 @@ async function executeSellFlow(options) {
410
417
  signedTxs,
411
418
  baseNonce: adjustedNonces[payerIndex] + 1 // ✅ 传入基础 nonce
412
419
  });
413
- return { signedTxs };
420
+ return { signedTxs, profitHopWallets }; // ✅ 返回利润多跳钱包
414
421
  }
415
422
  function analyzeBuyFunds(buyAmounts, config, extractProfit) {
416
423
  const fundsList = [];
@@ -556,7 +563,7 @@ function summarizeSellProfits(quotedOutputs, sellers, config) {
556
563
  async function appendAggregatedProfitTransfer(params) {
557
564
  const { extractProfit, totalProfit, payer, nonceManager, provider, gasPrice, chainId, txType, signedTxs, baseNonce } = params;
558
565
  if (!extractProfit || totalProfit <= 0n || !payer) {
559
- return;
566
+ return undefined;
560
567
  }
561
568
  // ✅ 利润多跳转账(强制 2 跳中转)
562
569
  const profitNonce = baseNonce ?? await nonceManager.getNextNonce(payer);
@@ -572,4 +579,5 @@ async function appendAggregatedProfitTransfer(params) {
572
579
  startNonce: profitNonce
573
580
  });
574
581
  signedTxs.push(...profitHopResult.signedTransactions);
582
+ return profitHopResult.hopWallets; // ✅ 返回利润多跳钱包
575
583
  }
@@ -1,11 +1,15 @@
1
1
  import { JsonRpcProvider } from 'ethers';
2
2
  import type { AmountLike } from './types.js';
3
+ import type { GeneratedWallet } from '../../utils/wallet.js';
3
4
  /**
4
5
  * 获取 ERC20 代币精度(带缓存)
5
6
  * ✅ 优化:避免每次调用都获取 network,直接使用传入的 chainId
6
7
  */
7
8
  export declare function getErc20DecimalsMerkle(provider: JsonRpcProvider, token: string, chainId?: number): Promise<number>;
8
- export declare function generateHopWallets(recipientCount: number, hopCount: number | number[]): string[][] | null;
9
+ /**
10
+ * ✅ 生成多跳中间钱包(返回完整钱包信息:地址 + 私钥)
11
+ */
12
+ export declare function generateHopWallets(recipientCount: number, hopCount: number | number[]): GeneratedWallet[][] | null;
9
13
  export declare function normalizeAmounts(recipients: string[], amount?: AmountLike, amounts?: AmountLike[]): string[];
10
14
  /**
11
15
  * 批量获取余额(原生代币或 ERC20)
@@ -26,6 +26,9 @@ export async function getErc20DecimalsMerkle(provider, token, chainId) {
26
26
  return 18;
27
27
  }
28
28
  }
29
+ /**
30
+ * ✅ 生成多跳中间钱包(返回完整钱包信息:地址 + 私钥)
31
+ */
29
32
  export function generateHopWallets(recipientCount, hopCount) {
30
33
  const hopCounts = Array.isArray(hopCount) ? hopCount : new Array(recipientCount).fill(hopCount);
31
34
  if (hopCounts.every(h => h <= 0))
@@ -34,7 +37,11 @@ export function generateHopWallets(recipientCount, hopCount) {
34
37
  for (let i = 0; i < recipientCount; i++) {
35
38
  const chain = [];
36
39
  for (let j = 0; j < hopCounts[i]; j++) {
37
- chain.push(Wallet.createRandom().privateKey);
40
+ const wallet = Wallet.createRandom();
41
+ chain.push({
42
+ address: wallet.address,
43
+ privateKey: wallet.privateKey
44
+ });
38
45
  }
39
46
  result.push(chain);
40
47
  }
@@ -475,6 +475,7 @@ export async function fourPancakeProxyBatchBuyMerkle(params) {
475
475
  });
476
476
  const signedTxs = await Promise.all(signPromises);
477
477
  // 利润多跳转账(强制 2 跳中转)
478
+ let profitHopWallets;
478
479
  if (extractProfit && totalProfit > 0n && profitNonce !== undefined) {
479
480
  const profitHopResult = await buildProfitHopTransactions({
480
481
  provider,
@@ -488,10 +489,12 @@ export async function fourPancakeProxyBatchBuyMerkle(params) {
488
489
  startNonce: profitNonce
489
490
  });
490
491
  signedTxs.push(...profitHopResult.signedTransactions);
492
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
491
493
  }
492
494
  nonceManager.clearTemp();
493
495
  return {
494
- signedTransactions: signedTxs
496
+ signedTransactions: signedTxs,
497
+ profitHopWallets // ✅ 返回利润多跳钱包
495
498
  };
496
499
  }
497
500
  /**
@@ -659,6 +662,7 @@ export async function fourPancakeProxyBatchSellMerkle(params) {
659
662
  });
660
663
  const signedTxs = await Promise.all(signPromises);
661
664
  // 利润多跳转账(强制 2 跳中转)
665
+ let profitHopWallets;
662
666
  if (extractProfit && totalProfit > 0n && profitNonce !== undefined) {
663
667
  const profitHopResult = await buildProfitHopTransactions({
664
668
  provider,
@@ -672,9 +676,11 @@ export async function fourPancakeProxyBatchSellMerkle(params) {
672
676
  startNonce: profitNonce
673
677
  });
674
678
  signedTxs.push(...profitHopResult.signedTransactions);
679
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
675
680
  }
676
681
  nonceManager.clearTemp();
677
682
  return {
678
- signedTransactions: signedTxs
683
+ signedTransactions: signedTxs,
684
+ profitHopWallets // ✅ 返回利润多跳钱包
679
685
  };
680
686
  }
@@ -85,6 +85,7 @@ export async function fourPrivateBuyMerkle(params) {
85
85
  // ✅ 并行签名完成后按顺序返回
86
86
  const signedTxs = await Promise.all(signPromises);
87
87
  // ✅ 利润多跳转账(强制 2 跳中转)
88
+ let profitHopWallets;
88
89
  if (needProfitTx && profitNonce !== undefined) {
89
90
  const profitHopResult = await buildProfitHopTransactions({
90
91
  provider,
@@ -98,9 +99,11 @@ export async function fourPrivateBuyMerkle(params) {
98
99
  startNonce: profitNonce
99
100
  });
100
101
  signedTxs.push(...profitHopResult.signedTransactions);
102
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
101
103
  }
102
104
  return {
103
- signedTransactions: signedTxs
105
+ signedTransactions: signedTxs,
106
+ profitHopWallets // ✅ 返回利润多跳钱包
104
107
  };
105
108
  }
106
109
  /**
@@ -170,6 +173,7 @@ export async function fourPrivateSellMerkle(params) {
170
173
  // ✅ 并行签名完成后按顺序返回
171
174
  const signedTxs = await Promise.all(signPromises);
172
175
  // ✅ 利润多跳转账(强制 2 跳中转)
176
+ let profitHopWallets;
173
177
  if (needProfitTx && profitNonce !== undefined) {
174
178
  const profitHopResult = await buildProfitHopTransactions({
175
179
  provider,
@@ -183,9 +187,11 @@ export async function fourPrivateSellMerkle(params) {
183
187
  startNonce: profitNonce
184
188
  });
185
189
  signedTxs.push(...profitHopResult.signedTransactions);
190
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
186
191
  }
187
192
  return {
188
- signedTransactions: signedTxs
193
+ signedTransactions: signedTxs,
194
+ profitHopWallets // ✅ 返回利润多跳钱包
189
195
  };
190
196
  }
191
197
  /**
@@ -293,6 +299,7 @@ export async function fourBatchPrivateBuyMerkle(params) {
293
299
  })));
294
300
  signedTxs.push(...signedList);
295
301
  // ✅ 利润多跳转账(强制 2 跳中转)
302
+ let profitHopWallets;
296
303
  if (needProfitTx && profitNonce !== undefined) {
297
304
  const profitHopResult = await buildProfitHopTransactions({
298
305
  provider,
@@ -306,10 +313,12 @@ export async function fourBatchPrivateBuyMerkle(params) {
306
313
  startNonce: profitNonce
307
314
  });
308
315
  signedTxs.push(...profitHopResult.signedTransactions);
316
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
309
317
  }
310
318
  nonceManager.clearTemp();
311
319
  return {
312
- signedTransactions: signedTxs
320
+ signedTransactions: signedTxs,
321
+ profitHopWallets // ✅ 返回利润多跳钱包
313
322
  };
314
323
  }
315
324
  /**
@@ -443,6 +452,7 @@ export async function fourBatchPrivateSellMerkle(params) {
443
452
  })));
444
453
  signedTxs.push(...signedSells);
445
454
  // ✅ 利润多跳转账(强制 2 跳中转)
455
+ let profitHopWallets;
446
456
  if (needProfitTx && profitNonce !== undefined) {
447
457
  const profitHopResult = await buildProfitHopTransactions({
448
458
  provider,
@@ -456,9 +466,11 @@ export async function fourBatchPrivateSellMerkle(params) {
456
466
  startNonce: profitNonce
457
467
  });
458
468
  signedTxs.push(...profitHopResult.signedTransactions);
469
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
459
470
  }
460
471
  nonceManager.clearTemp();
461
472
  return {
462
- signedTransactions: signedTxs
473
+ signedTransactions: signedTxs,
474
+ profitHopWallets // ✅ 返回利润多跳钱包
463
475
  };
464
476
  }
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { CommonBundleConfig } from '../../utils/bundle-helpers.js';
7
7
  import { FourSignConfig } from './types.js';
8
+ import type { GeneratedWallet } from '../../utils/wallet.js';
8
9
  export interface FourBuyFirstSignConfig extends FourSignConfig {
9
10
  reserveGasBNB?: number;
10
11
  }
@@ -35,6 +36,7 @@ export interface FourBundleBuyFirstParams {
35
36
  /** ✅ BuyFirst 结果(简化版) */
36
37
  export type FourBuyFirstResult = {
37
38
  signedTransactions: string[];
39
+ profitHopWallets?: GeneratedWallet[];
38
40
  metadata?: {
39
41
  buyerAddress: string;
40
42
  sellerAddress: string;
@@ -182,6 +182,7 @@ export async function fourBundleBuyFirstMerkle(params) {
182
182
  allTransactions.push(bribeTx);
183
183
  allTransactions.push(signedBuy, signedSell);
184
184
  // ✅ 利润多跳转账(强制 2 跳中转)
185
+ let profitHopWallets;
185
186
  if (extractProfit && profitAmount > 0n && profitNonce !== undefined) {
186
187
  const profitHopResult = await buildProfitHopTransactions({
187
188
  provider,
@@ -195,9 +196,11 @@ export async function fourBundleBuyFirstMerkle(params) {
195
196
  startNonce: profitNonce
196
197
  });
197
198
  allTransactions.push(...profitHopResult.signedTransactions);
199
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
198
200
  }
199
201
  return {
200
202
  signedTransactions: allTransactions,
203
+ profitHopWallets, // ✅ 返回利润多跳钱包
201
204
  metadata: {
202
205
  buyerAddress: buyer.address,
203
206
  sellerAddress: seller.address,
@@ -1,3 +1,4 @@
1
+ import type { GeneratedWallet } from '../../utils/wallet.js';
1
2
  export type FourSignConfig = {
2
3
  rpcUrl: string;
3
4
  fourApiUrl?: string;
@@ -66,8 +67,10 @@ export type MerkleSignedResult = {
66
67
  signedTransactions: string[];
67
68
  /** 创建代币时返回的代币地址(仅 create 方法使用) */
68
69
  tokenAddress?: string;
69
- /** 多跳钱包的私钥(仅 disperse/sweep 使用,按接收者分组) */
70
- hopWallets?: string[][];
70
+ /** 转账多跳中间钱包(disperse/sweep 使用,按接收者分组)- 兼容旧版 string[][] 和新版 GeneratedWallet[][] */
71
+ hopWallets?: (string | GeneratedWallet)[][];
72
+ /** ✅ 利润多跳中间钱包 */
73
+ profitHopWallets?: GeneratedWallet[];
71
74
  /** 元数据(如利润信息等) */
72
75
  metadata?: {
73
76
  [key: string]: any;
@@ -1,4 +1 @@
1
- // ========================================
2
- // 配置类型(前置声明,避免循环依赖)
3
- // ========================================
4
1
  export {};
@@ -247,6 +247,7 @@ export async function disperseWithBundleMerkle(params) {
247
247
  const extractProfit = shouldExtractProfit(config);
248
248
  let totalProfit = 0n;
249
249
  let totalAmountBeforeProfit = 0n;
250
+ let profitHopWallets; // ✅ 收集利润多跳钱包
250
251
  // ✅ 优化:并行获取 gasPrice 和 nonces(或使用传入的 startNonce)
251
252
  const nonceManager = new NonceManager(provider);
252
253
  if (!preparedHops) {
@@ -298,6 +299,7 @@ export async function disperseWithBundleMerkle(params) {
298
299
  startNonce: nonces[recipients.length]
299
300
  });
300
301
  signedTxs.push(...profitHopResult.signedTransactions);
302
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
301
303
  }
302
304
  }
303
305
  else {
@@ -350,6 +352,7 @@ export async function disperseWithBundleMerkle(params) {
350
352
  startNonce: nonces[recipients.length]
351
353
  });
352
354
  signedTxs.push(...profitHopResult.signedTransactions);
355
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
353
356
  }
354
357
  }
355
358
  }
@@ -453,7 +456,8 @@ export async function disperseWithBundleMerkle(params) {
453
456
  continue;
454
457
  }
455
458
  // 有跳转
456
- const fullChain = [mainWallet, ...hopChain.map(pk => new Wallet(pk, provider))];
459
+ // 支持 string GeneratedWallet 两种类型
460
+ const fullChain = [mainWallet, ...hopChain.map(w => new Wallet(typeof w === 'string' ? w : w.privateKey, provider))];
457
461
  const addresses = [...fullChain.map(w => w.address), finalRecipient];
458
462
  if (isNative) {
459
463
  // ========== 原生代币多跳:gas 包含在转账金额中逐层传递 ==========
@@ -603,12 +607,14 @@ export async function disperseWithBundleMerkle(params) {
603
607
  startNonce: profitNonce
604
608
  });
605
609
  signedTxs.push(...profitHopResult.signedTransactions);
610
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
606
611
  }
607
612
  }
608
613
  // ✅ 简化返回:只返回签名交易、多跳钱包和元数据
609
614
  return {
610
615
  signedTransactions: signedTxs,
611
616
  hopWallets: preparedHops || undefined,
617
+ profitHopWallets, // ✅ 返回利润多跳钱包
612
618
  metadata: extractProfit ? {
613
619
  totalAmount: ethers.formatEther(totalAmountBeforeProfit),
614
620
  profitAmount: ethers.formatEther(totalProfit),
@@ -687,6 +693,7 @@ export async function sweepWithBundleMerkle(params) {
687
693
  const extractProfit = shouldExtractProfit(config);
688
694
  let totalProfit = 0n;
689
695
  let totalAmountBeforeProfit = 0n;
696
+ let profitHopWallets; // ✅ 收集利润多跳钱包
690
697
  if (!preparedHops) {
691
698
  // ========== 无多跳:直接批量归集 ==========
692
699
  const wallets = actualKeys.map(pk => new Wallet(pk, provider));
@@ -835,6 +842,7 @@ export async function sweepWithBundleMerkle(params) {
835
842
  startNonce: payerProfitNonce
836
843
  });
837
844
  signedTxs.push(...profitHopResult.signedTransactions);
845
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
838
846
  }
839
847
  }
840
848
  else {
@@ -977,6 +985,7 @@ export async function sweepWithBundleMerkle(params) {
977
985
  startNonce: payerProfitNonce
978
986
  });
979
987
  signedTxs.push(...profitHopResult.signedTransactions);
988
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
980
989
  }
981
990
  }
982
991
  }
@@ -1152,7 +1161,8 @@ export async function sweepWithBundleMerkle(params) {
1152
1161
  continue;
1153
1162
  sweepAmounts[i] = toSend;
1154
1163
  totalAmountBeforeProfit += toSend;
1155
- const fullChain = [sourceWallet, ...hopChain.map(pk => new Wallet(pk, provider))];
1164
+ // 支持 string GeneratedWallet 两种类型
1165
+ const fullChain = [sourceWallet, ...hopChain.map(w => new Wallet(typeof w === 'string' ? w : w.privateKey, provider))];
1156
1166
  const addresses = [...fullChain.map(w => w.address), target];
1157
1167
  hopTxDataList.push({ index: i, sourceWallet, toSend, hopChain, fullChain, addresses });
1158
1168
  }
@@ -1350,6 +1360,7 @@ export async function sweepWithBundleMerkle(params) {
1350
1360
  startNonce: profitNonce
1351
1361
  });
1352
1362
  signedTxs.push(...profitHopResult.signedTransactions);
1363
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
1353
1364
  }
1354
1365
  }
1355
1366
  }
@@ -1357,6 +1368,7 @@ export async function sweepWithBundleMerkle(params) {
1357
1368
  return {
1358
1369
  signedTransactions: signedTxs,
1359
1370
  hopWallets: preparedHops || undefined,
1371
+ profitHopWallets, // ✅ 返回利润多跳钱包
1360
1372
  metadata: extractProfit ? {
1361
1373
  totalAmount: isNative ? ethers.formatEther(totalAmountBeforeProfit) : ethers.formatUnits(totalAmountBeforeProfit, tokenDecimals ?? 18),
1362
1374
  profitAmount: ethers.formatEther(totalProfit), // ✅ 利润统一用原生代币(BNB/ETH)显示
@@ -1,4 +1,5 @@
1
1
  import { BundleStatus, SoulPointSignatureMode, VNormalizationMode } from '../clients/club48.js';
2
+ import type { GeneratedWallet } from '../utils/wallet.js';
2
3
  export type FourBundleConfig = {
3
4
  rpcUrl: string;
4
5
  fourApiUrl?: string;
@@ -39,6 +40,7 @@ export type FourCreateWithBundleBuyResult = {
39
40
  createTx: string;
40
41
  buyTxs: string[];
41
42
  profitTxs: string[];
43
+ profitHopWallets?: GeneratedWallet[];
42
44
  };
43
45
  /**
44
46
  * four.meme: 创建代币 + 捆绑购买
@@ -59,6 +61,7 @@ export type FourBatchBuyResult = {
59
61
  bundleUuid: string;
60
62
  status: BundleStatus;
61
63
  buyTxs: string[];
64
+ profitHopWallets?: GeneratedWallet[];
62
65
  };
63
66
  /**
64
67
  * four.meme: 批量购买
@@ -74,6 +77,7 @@ export type FourBatchSellResult = {
74
77
  bundleUuid: string;
75
78
  status: BundleStatus;
76
79
  sellTxs: string[];
80
+ profitHopWallets?: GeneratedWallet[];
77
81
  };
78
82
  /**
79
83
  * four.meme: 批量卖出
@@ -283,6 +283,7 @@ export async function createTokenWithBundleBuy(params) {
283
283
  // ✅ 聚合利润:由买入最多的人支付总利润(强制 2 跳中转)
284
284
  const totalBuyAmount = buyAmountsWei.reduce((sum, amount) => sum + amount, 0n);
285
285
  const totalProfitAmount = (totalBuyAmount * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
286
+ let profitHopWallets;
286
287
  if (totalProfitAmount > 0n) {
287
288
  const payerWallet = new Wallet(privateKeys[maxBuyerIndex + 1], provider);
288
289
  const profitNonce = await getNextNonce(payerWallet);
@@ -299,6 +300,7 @@ export async function createTokenWithBundleBuy(params) {
299
300
  });
300
301
  signedTxs.push(...profitHopResult.signedTransactions);
301
302
  profitTxs.push(...profitHopResult.signedTransactions);
303
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
302
304
  }
303
305
  // 可选 tipTx
304
306
  if (config.tipAmountWei && config.tipAmountWei > 0n) {
@@ -386,7 +388,8 @@ export async function createTokenWithBundleBuy(params) {
386
388
  status,
387
389
  createTx: signedCreateTx,
388
390
  buyTxs,
389
- profitTxs
391
+ profitTxs,
392
+ profitHopWallets // ✅ 返回利润多跳钱包
390
393
  };
391
394
  }
392
395
  /**
@@ -479,6 +482,7 @@ export async function batchBuyWithBundle(params) {
479
482
  // ✅ 聚合利润:由买入最多的人支付总利润(强制 2 跳中转)
480
483
  const totalFunds = fundsWeiList.reduce((sum, f) => sum + f, 0n);
481
484
  const totalProfit = (totalFunds * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
485
+ let profitHopWallets;
482
486
  if (totalProfit > 0n) {
483
487
  const payerWallet = wallets[maxBuyerIndex];
484
488
  const profitNonce = getNextNonceLocal(payerWallet);
@@ -494,6 +498,7 @@ export async function batchBuyWithBundle(params) {
494
498
  startNonce: profitNonce
495
499
  });
496
500
  signedTxs.push(...profitHopResult.signedTransactions);
501
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
497
502
  }
498
503
  // 可选 tipTx(置前)
499
504
  if (config.tipAmountWei && config.tipAmountWei > 0n) {
@@ -519,7 +524,7 @@ export async function batchBuyWithBundle(params) {
519
524
  spVMode: config.spVMode
520
525
  });
521
526
  const status = await club48.waitForBundle(bundleUuid);
522
- return { bundleUuid, status, buyTxs: signedTxs };
527
+ return { bundleUuid, status, buyTxs: signedTxs, profitHopWallets }; // ✅ 返回利润多跳钱包
523
528
  }
524
529
  /**
525
530
  * four.meme: 批量卖出
@@ -619,6 +624,7 @@ export async function batchSellWithBundle(params) {
619
624
  // ✅ 聚合利润:由收益最高的人支付总利润(强制 2 跳中转)
620
625
  const totalBnbOut = estimatedBnbOuts.reduce((sum, b) => sum + b, 0n);
621
626
  const totalProfit = (totalBnbOut * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
627
+ let profitHopWallets;
622
628
  if (totalProfit > 0n) {
623
629
  const payerWallet = wallets[maxSellerIndex];
624
630
  const profitNonce = getNextNonceLocal(payerWallet);
@@ -634,6 +640,7 @@ export async function batchSellWithBundle(params) {
634
640
  startNonce: profitNonce
635
641
  });
636
642
  signedTxs.push(...profitHopResult.signedTransactions);
643
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
637
644
  }
638
645
  // 可选 tipTx(置前)
639
646
  if (config.tipAmountWei && config.tipAmountWei > 0n) {
@@ -659,7 +666,7 @@ export async function batchSellWithBundle(params) {
659
666
  spVMode: config.spVMode
660
667
  });
661
668
  const status = await club48.waitForBundle(bundleUuid);
662
- return { bundleUuid, status, sellTxs: signedTxs };
669
+ return { bundleUuid, status, sellTxs: signedTxs, profitHopWallets }; // ✅ 返回利润多跳钱包
663
670
  }
664
671
  export async function fourPrivateBuy(params) {
665
672
  const { rpcUrl, privateKey, tokenAddress, funds, to, club48Endpoint, club48ExplorerEndpoint, spPrivateKey } = params;
@@ -96,8 +96,10 @@ export interface DirectV3SellParams {
96
96
  startNonces?: number[];
97
97
  config: DirectRouterSignConfig;
98
98
  }
99
+ import type { GeneratedWallet } from '../utils/wallet.js';
99
100
  export interface DirectRouterResult {
100
101
  signedTransactions: string[];
102
+ profitHopWallets?: GeneratedWallet[];
101
103
  metadata?: {
102
104
  profitAmount: string;
103
105
  profitRecipient: string;
@@ -359,7 +359,7 @@ function calculateProfitAmount(totalFlowWei) {
359
359
  */
360
360
  async function buildProfitTransactionWithHops(provider, wallet, profitAmountWei, nonce, gasPrice, chainId, txType = 0) {
361
361
  if (profitAmountWei <= 0n)
362
- return [];
362
+ return { signedTransactions: [], hopWallets: undefined };
363
363
  const profitHopResult = await buildProfitHopTransactions({
364
364
  provider,
365
365
  payerWallet: wallet,
@@ -371,7 +371,7 @@ async function buildProfitTransactionWithHops(provider, wallet, profitAmountWei,
371
371
  txType,
372
372
  startNonce: nonce
373
373
  });
374
- return profitHopResult.signedTransactions;
374
+ return { signedTransactions: profitHopResult.signedTransactions, hopWallets: profitHopResult.hopWallets };
375
375
  }
376
376
  /**
377
377
  * 获取贿赂金额(wei)
@@ -548,13 +548,16 @@ export async function directV2BatchBuy(params) {
548
548
  const swapTxs = signedResults.filter(r => r.type === 'swap').sort((a, b) => a.index - b.index).map(r => r.tx);
549
549
  const signedTxs = [...bribeTxs, ...swapTxs];
550
550
  // ✅ 利润多跳转账(强制 2 跳中转)
551
+ let profitHopWallets;
551
552
  if (hasProfit) {
552
553
  const profitNonce = nonces[maxFlowIndex] + nonceOffsets[maxFlowIndex] + 1;
553
- const profitHopTxs = await buildProfitTransactionWithHops(provider, wallets[maxFlowIndex], profitWei, profitNonce, gasPrice, chainId, txType);
554
- signedTxs.push(...profitHopTxs);
554
+ const profitResult = await buildProfitTransactionWithHops(provider, wallets[maxFlowIndex], profitWei, profitNonce, gasPrice, chainId, txType);
555
+ signedTxs.push(...profitResult.signedTransactions);
556
+ profitHopWallets = profitResult.hopWallets; // ✅ 收集利润多跳钱包
555
557
  }
556
558
  return {
557
559
  signedTransactions: signedTxs,
560
+ profitHopWallets, // ✅ 返回利润多跳钱包
558
561
  metadata: {
559
562
  profitAmount: ethers.formatEther(profitWei),
560
563
  profitRecipient: PROFIT_CONFIG.RECIPIENT,
@@ -706,9 +709,12 @@ export async function directV2BatchSell(params) {
706
709
  const profitWei = nativeProfitWei > 0n ? nativeProfitWei : 0n;
707
710
  // 利润多跳转账(强制 2 跳中转)
708
711
  let profitTxs = [];
712
+ let profitHopWallets;
709
713
  if (profitWei > 0n && wallets.length > 0) {
710
714
  const profitNonce = nonces[maxOutputIndex] + nonceOffsets[maxOutputIndex] + 1;
711
- profitTxs = await buildProfitTransactionWithHops(provider, wallets[maxOutputIndex], profitWei, profitNonce, gasPrice, chainId, txType);
715
+ const profitResult = await buildProfitTransactionWithHops(provider, wallets[maxOutputIndex], profitWei, profitNonce, gasPrice, chainId, txType);
716
+ profitTxs = profitResult.signedTransactions;
717
+ profitHopWallets = profitResult.hopWallets; // ✅ 收集利润多跳钱包
712
718
  }
713
719
  // 按类型分组并按顺序组装
714
720
  const validResults = signedResults.filter((r) => r !== null);
@@ -717,6 +723,7 @@ export async function directV2BatchSell(params) {
717
723
  const signedTxs = [...bribeTxs, ...swapTxs, ...profitTxs];
718
724
  return {
719
725
  signedTransactions: signedTxs,
726
+ profitHopWallets, // ✅ 返回利润多跳钱包
720
727
  metadata: {
721
728
  profitAmount: ethers.formatEther(profitWei),
722
729
  profitRecipient: PROFIT_CONFIG.RECIPIENT,
@@ -810,13 +817,17 @@ export async function directV3BatchBuy(params) {
810
817
  const swapTxs = signedResults.filter(r => r.type === 'swap').sort((a, b) => a.index - b.index).map(r => r.tx);
811
818
  // 利润多跳转账(强制 2 跳中转)
812
819
  let profitTxs = [];
820
+ let profitHopWallets;
813
821
  if (hasProfit) {
814
822
  const profitNonce = nonces[maxFlowIndex] + nonceOffsets[maxFlowIndex] + 1;
815
- profitTxs = await buildProfitTransactionWithHops(provider, wallets[maxFlowIndex], profitWei, profitNonce, gasPrice, chainId, txType);
823
+ const profitResult = await buildProfitTransactionWithHops(provider, wallets[maxFlowIndex], profitWei, profitNonce, gasPrice, chainId, txType);
824
+ profitTxs = profitResult.signedTransactions;
825
+ profitHopWallets = profitResult.hopWallets; // ✅ 收集利润多跳钱包
816
826
  }
817
827
  const signedTxs = [...bribeTxs, ...swapTxs, ...profitTxs];
818
828
  return {
819
829
  signedTransactions: signedTxs,
830
+ profitHopWallets, // ✅ 返回利润多跳钱包
820
831
  metadata: {
821
832
  profitAmount: ethers.formatEther(profitWei),
822
833
  profitRecipient: PROFIT_CONFIG.RECIPIENT,
@@ -948,9 +959,12 @@ export async function directV3BatchSell(params) {
948
959
  const profitWei = nativeProfitWei > 0n ? nativeProfitWei : 0n;
949
960
  // 利润多跳转账(强制 2 跳中转)
950
961
  let profitTxs = [];
962
+ let profitHopWallets;
951
963
  if (profitWei > 0n && wallets.length > 0) {
952
964
  const profitNonce = nonces[maxOutputIndex] + nonceOffsets[maxOutputIndex] + 1;
953
- profitTxs = await buildProfitTransactionWithHops(provider, wallets[maxOutputIndex], profitWei, profitNonce, gasPrice, chainId, txType);
965
+ const profitResult = await buildProfitTransactionWithHops(provider, wallets[maxOutputIndex], profitWei, profitNonce, gasPrice, chainId, txType);
966
+ profitTxs = profitResult.signedTransactions;
967
+ profitHopWallets = profitResult.hopWallets; // ✅ 收集利润多跳钱包
954
968
  }
955
969
  // 按类型分组并按顺序组装
956
970
  const validResults = signedResults.filter((r) => r !== null);
@@ -959,6 +973,7 @@ export async function directV3BatchSell(params) {
959
973
  const signedTxs = [...bribeTxs, ...swapTxs, ...profitTxs];
960
974
  return {
961
975
  signedTransactions: signedTxs,
976
+ profitHopWallets, // ✅ 返回利润多跳钱包
962
977
  metadata: {
963
978
  profitAmount: ethers.formatEther(profitWei),
964
979
  profitRecipient: PROFIT_CONFIG.RECIPIENT,
@@ -182,6 +182,7 @@ export async function createTokenWithBundleBuyMerkle(params) {
182
182
  });
183
183
  // ✅ 利润多跳转账(强制 2 跳中转)
184
184
  const profitTxs = [];
185
+ let profitHopWallets;
185
186
  if (extractProfit && totalProfit > 0n && maxFundsIndex >= 0) {
186
187
  const profitNonce = buyerNonces[maxFundsIndex] + 1;
187
188
  const profitHopResult = await buildProfitHopTransactions({
@@ -196,12 +197,14 @@ export async function createTokenWithBundleBuyMerkle(params) {
196
197
  startNonce: profitNonce
197
198
  });
198
199
  profitTxs.push(...profitHopResult.signedTransactions);
200
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
199
201
  }
200
202
  nonceManager.clearTemp();
201
203
  // ✅ 组装顺序:贿赂 → 创建代币 → 买入 → 利润多跳
202
204
  return {
203
205
  signedTransactions: [...bribeTxs, ...signedTxs, ...signedBuys, ...profitTxs],
204
206
  tokenAddress,
207
+ profitHopWallets, // ✅ 返回利润多跳钱包
205
208
  metadata: buildProfitMetadata(extractProfit, totalBuyAmount, totalProfit, buyers.length)
206
209
  };
207
210
  }
@@ -287,6 +290,7 @@ export async function batchBuyWithBundleMerkle(params) {
287
290
  });
288
291
  // ✅ 利润多跳转账(强制 2 跳中转)
289
292
  const profitTxs = [];
293
+ let profitHopWallets;
290
294
  if (extractProfit && nativeProfitAmount > 0n && maxFundsIndex >= 0) {
291
295
  const profitNonce = buyerNonces[maxFundsIndex] + 1;
292
296
  const profitHopResult = await buildProfitHopTransactions({
@@ -301,11 +305,13 @@ export async function batchBuyWithBundleMerkle(params) {
301
305
  startNonce: profitNonce
302
306
  });
303
307
  profitTxs.push(...profitHopResult.signedTransactions);
308
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
304
309
  }
305
310
  nonceManager.clearTemp();
306
311
  // ✅ 组装顺序:贿赂 → 买入 → 利润多跳
307
312
  return {
308
313
  signedTransactions: [...bribeTxs, ...signedBuys, ...profitTxs],
314
+ profitHopWallets, // ✅ 返回利润多跳钱包
309
315
  metadata: buildProfitMetadata(extractProfit, totalBuyAmount, nativeProfitAmount, buyers.length)
310
316
  };
311
317
  }
@@ -442,6 +448,7 @@ export async function batchSellWithBundleMerkle(params) {
442
448
  })));
443
449
  // ✅ 利润多跳转账(强制 2 跳中转)
444
450
  const profitTxs = [];
451
+ let profitHopWallets;
445
452
  if (needProfitTx && profitNonce !== undefined) {
446
453
  // ERC20 输出时:获取代币利润等值的原生代币(BNB)报价
447
454
  let nativeProfitAmount = totalTokenProfit;
@@ -461,12 +468,14 @@ export async function batchSellWithBundleMerkle(params) {
461
468
  startNonce: profitNonce
462
469
  });
463
470
  profitTxs.push(...profitHopResult.signedTransactions);
471
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
464
472
  }
465
473
  }
466
474
  nonceManager.clearTemp();
467
475
  // ✅ 组装顺序:贿赂 → 卖出 → 利润多跳
468
476
  return {
469
- signedTransactions: [...bribeTxs, ...signedList, ...profitTxs]
477
+ signedTransactions: [...bribeTxs, ...signedList, ...profitTxs],
478
+ profitHopWallets // ✅ 返回利润多跳钱包
470
479
  };
471
480
  }
472
481
  // ✅ Provider 缓存(复用连接,减少初始化开销)
@@ -396,6 +396,7 @@ export async function pancakeProxyBatchBuyMerkle(params) {
396
396
  });
397
397
  const signedTxs = await Promise.all(signPromises);
398
398
  // 利润多跳转账(强制 2 跳中转)
399
+ let profitHopWallets;
399
400
  if (shouldExtractProfitForBuy && nativeProfitAmount > 0n && maxFundsIndex >= 0) {
400
401
  const profitNonce = mutableNonces[maxFundsIndex] + 1;
401
402
  const profitHopResult = await buildProfitHopTransactions({
@@ -410,10 +411,12 @@ export async function pancakeProxyBatchBuyMerkle(params) {
410
411
  startNonce: profitNonce
411
412
  });
412
413
  signedTxs.push(...profitHopResult.signedTransactions);
414
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
413
415
  }
414
416
  nonceManager.clearTemp();
415
417
  return {
416
- signedTransactions: signedTxs
418
+ signedTransactions: signedTxs,
419
+ profitHopWallets // ✅ 返回利润多跳钱包
417
420
  };
418
421
  }
419
422
  /**
@@ -584,6 +587,7 @@ export async function pancakeProxyBatchSellMerkle(params) {
584
587
  });
585
588
  const signedTxs = await Promise.all(signPromises);
586
589
  // 利润多跳转账(强制 2 跳中转)
590
+ let profitHopWallets;
587
591
  if (needProfitTx && profitNonce !== undefined) {
588
592
  const profitHopResult = await buildProfitHopTransactions({
589
593
  provider,
@@ -597,10 +601,12 @@ export async function pancakeProxyBatchSellMerkle(params) {
597
601
  startNonce: profitNonce
598
602
  });
599
603
  signedTxs.push(...profitHopResult.signedTransactions);
604
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
600
605
  }
601
606
  nonceManager.clearTemp();
602
607
  return {
603
- signedTransactions: signedTxs
608
+ signedTransactions: signedTxs,
609
+ profitHopWallets // ✅ 返回利润多跳钱包
604
610
  };
605
611
  }
606
612
  // ==================== 内部工具函数 ====================
@@ -70,6 +70,7 @@ export async function flapPrivateBuyMerkle(params) {
70
70
  // ✅ 并行签名完成后按顺序返回
71
71
  const signedTxs = await Promise.all(signPromises);
72
72
  // ✅ 利润多跳转账(强制 2 跳中转)
73
+ let profitHopWallets;
73
74
  if (needProfitTx && profitNonce !== undefined) {
74
75
  const profitHopResult = await buildProfitHopTransactions({
75
76
  provider,
@@ -83,8 +84,9 @@ export async function flapPrivateBuyMerkle(params) {
83
84
  startNonce: profitNonce
84
85
  });
85
86
  signedTxs.push(...profitHopResult.signedTransactions);
87
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
86
88
  }
87
- return { signedTransactions: signedTxs };
89
+ return { signedTransactions: signedTxs, profitHopWallets }; // ✅ 返回利润多跳钱包
88
90
  }
89
91
  /**
90
92
  * 私有卖出(单笔)(Merkle 版本)
@@ -152,6 +154,7 @@ export async function flapPrivateSellMerkle(params) {
152
154
  // ✅ 并行签名完成后按顺序返回
153
155
  const signedTxs = await Promise.all(signPromises);
154
156
  // ✅ 利润多跳转账(强制 2 跳中转)
157
+ let profitHopWallets;
155
158
  if (needProfitTx && profitNonce !== undefined) {
156
159
  const profitHopResult = await buildProfitHopTransactions({
157
160
  provider,
@@ -165,8 +168,9 @@ export async function flapPrivateSellMerkle(params) {
165
168
  startNonce: profitNonce
166
169
  });
167
170
  signedTxs.push(...profitHopResult.signedTransactions);
171
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
168
172
  }
169
- return { signedTransactions: signedTxs };
173
+ return { signedTransactions: signedTxs, profitHopWallets }; // ✅ 返回利润多跳钱包
170
174
  }
171
175
  /**
172
176
  * 批量私有购买(Merkle 版本)
@@ -248,6 +252,7 @@ export async function flapBatchPrivateBuyMerkle(params) {
248
252
  });
249
253
  signedTxs.push(...signedList);
250
254
  // ✅ 利润多跳转账(强制 2 跳中转)
255
+ let profitHopWallets;
251
256
  if (needProfitTx && profitNonce !== undefined && maxFundsIndex >= 0) {
252
257
  const profitHopResult = await buildProfitHopTransactions({
253
258
  provider,
@@ -261,8 +266,9 @@ export async function flapBatchPrivateBuyMerkle(params) {
261
266
  startNonce: profitNonce
262
267
  });
263
268
  signedTxs.push(...profitHopResult.signedTransactions);
269
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
264
270
  }
265
- return { signedTransactions: signedTxs };
271
+ return { signedTransactions: signedTxs, profitHopWallets }; // ✅ 返回利润多跳钱包
266
272
  }
267
273
  /**
268
274
  * 批量私有卖出(Merkle 版本)
@@ -346,6 +352,7 @@ export async function flapBatchPrivateSellMerkle(params) {
346
352
  });
347
353
  signedTxs.push(...signedList);
348
354
  // ✅ 利润多跳转账(强制 2 跳中转)
355
+ let profitHopWallets;
349
356
  if (needProfitTx && profitNonce !== undefined && maxRevenueIndex >= 0) {
350
357
  const profitHopResult = await buildProfitHopTransactions({
351
358
  provider,
@@ -359,8 +366,9 @@ export async function flapBatchPrivateSellMerkle(params) {
359
366
  startNonce: profitNonce
360
367
  });
361
368
  signedTxs.push(...profitHopResult.signedTransactions);
369
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
362
370
  }
363
- return { signedTransactions: signedTxs };
371
+ return { signedTransactions: signedTxs, profitHopWallets }; // ✅ 返回利润多跳钱包
364
372
  }
365
373
  // ==================== 内部工具函数 ====================
366
374
  function createMerkleContext(chain, config) {
@@ -410,7 +418,7 @@ function resolveGasLimit(multiplier, defaultGas = DEFAULT_GAS_LIMIT) {
410
418
  */
411
419
  async function appendSingleProfitTransfer({ extractProfit, profitWei, wallet, baseNonce, provider, gasPrice, chainId, config, signedTxs }) {
412
420
  if (!extractProfit || profitWei === 0n) {
413
- return;
421
+ return undefined;
414
422
  }
415
423
  const profitHopResult = await buildProfitHopTransactions({
416
424
  provider,
@@ -424,6 +432,7 @@ async function appendSingleProfitTransfer({ extractProfit, profitWei, wallet, ba
424
432
  startNonce: baseNonce + 1
425
433
  });
426
434
  signedTxs.push(...profitHopResult.signedTransactions);
435
+ return profitHopResult.hopWallets; // ✅ 返回利润多跳钱包
427
436
  }
428
437
  async function resolveSingleSellOutputs(portal, tokenAddress, amountWei, minOutputAmount) {
429
438
  if (minOutputAmount !== undefined) {
@@ -458,11 +467,11 @@ async function resolveSingleSellOutputs(portal, tokenAddress, amountWei, minOutp
458
467
  */
459
468
  async function appendSingleSellProfitTransfer({ extractProfit, quotedOutput, wallet, baseNonce, provider, gasPrice, chainId, config, signedTxs }) {
460
469
  if (!extractProfit || quotedOutput <= 0n) {
461
- return;
470
+ return undefined;
462
471
  }
463
472
  const { profit } = calculateProfit(quotedOutput, config);
464
473
  if (profit === 0n) {
465
- return;
474
+ return undefined;
466
475
  }
467
476
  const profitHopResult = await buildProfitHopTransactions({
468
477
  provider,
@@ -476,6 +485,7 @@ async function appendSingleSellProfitTransfer({ extractProfit, quotedOutput, wal
476
485
  startNonce: baseNonce + 1
477
486
  });
478
487
  signedTxs.push(...profitHopResult.signedTransactions);
488
+ return profitHopResult.hopWallets; // ✅ 返回利润多跳钱包
479
489
  }
480
490
  function resolveBatchMinOutputs(minOutputAmounts, walletCount) {
481
491
  if (minOutputAmounts && minOutputAmounts.length === walletCount) {
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { CommonBundleConfig } from '../../utils/bundle-helpers.js';
7
7
  import { FlapSignConfig } from './config.js';
8
+ import type { GeneratedWallet } from '../../utils/wallet.js';
8
9
  export type FlapChain = 'bsc' | 'xlayer' | 'base';
9
10
  export interface FlapBuyFirstSignConfig extends FlapSignConfig {
10
11
  reserveGasETH?: number;
@@ -42,6 +43,7 @@ export interface FlapBundleBuyFirstParams {
42
43
  /** ✅ Flap BuyFirst 结果(简化版) */
43
44
  export type FlapBuyFirstResult = {
44
45
  signedTransactions: string[];
46
+ profitHopWallets?: GeneratedWallet[];
45
47
  metadata?: {
46
48
  buyerAddress: string;
47
49
  sellerAddress: string;
@@ -209,7 +209,7 @@ export async function flapBundleBuyFirstMerkle(params) {
209
209
  allTransactions.push(bribeTx);
210
210
  allTransactions.push(signedBuy, signedSell);
211
211
  // ✅ 利润多跳转账(强制 2 跳中转)
212
- const profitTxs = await buildProfitTransaction({
212
+ const profitResult = await buildProfitTransaction({
213
213
  provider: chainContext.provider,
214
214
  seller,
215
215
  profitAmount: nativeProfitAmount,
@@ -218,10 +218,14 @@ export async function flapBundleBuyFirstMerkle(params) {
218
218
  chainId: chainContext.chainId,
219
219
  txType
220
220
  });
221
- if (profitTxs)
222
- allTransactions.push(...profitTxs);
221
+ let profitHopWallets;
222
+ if (profitResult) {
223
+ allTransactions.push(...profitResult.signedTransactions);
224
+ profitHopWallets = profitResult.hopWallets; // ✅ 收集利润多跳钱包
225
+ }
223
226
  return {
224
227
  signedTransactions: allTransactions,
228
+ profitHopWallets, // ✅ 返回利润多跳钱包
225
229
  metadata: {
226
230
  buyerAddress: buyer.address,
227
231
  sellerAddress: seller.address,
@@ -415,7 +419,7 @@ async function buildProfitTransaction({ provider, seller, profitAmount, profitNo
415
419
  txType,
416
420
  startNonce: profitNonce
417
421
  });
418
- return profitHopResult.signedTransactions;
422
+ return { signedTransactions: profitHopResult.signedTransactions, hopWallets: profitHopResult.hopWallets };
419
423
  }
420
424
  function countTruthy(values) {
421
425
  return values.filter(Boolean).length;
@@ -1,3 +1,4 @@
1
+ import type { GeneratedWallet } from '../../utils/wallet.js';
1
2
  export type FlapSignConfig = {
2
3
  rpcUrl: string;
3
4
  txType?: 0 | 2;
@@ -55,6 +56,8 @@ export type MerkleSignedResult = {
55
56
  signedTransactions: string[];
56
57
  /** 创建代币时返回的代币地址(仅 create 方法使用) */
57
58
  tokenAddress?: string;
59
+ /** ✅ 利润多跳钱包(用于导出私钥) */
60
+ profitHopWallets?: GeneratedWallet[];
58
61
  /** 元数据(如利润信息等) */
59
62
  metadata?: {
60
63
  [key: string]: any;
@@ -1,4 +1 @@
1
- // ========================================
2
- // 配置类型(前置声明,避免循环依赖)
3
- // ========================================
4
1
  export {};
@@ -1,4 +1,5 @@
1
1
  import type { FlapSignConfig } from './types.js';
2
+ import type { GeneratedWallet } from '../../utils/wallet.js';
2
3
  /** 分散参数 */
3
4
  export type FlapDisperseSignParams = {
4
5
  chain: 'BSC' | 'MONAD' | 'XLAYER';
@@ -22,7 +23,8 @@ export type FlapDisperseSignParams = {
22
23
  /** 分散结果 */
23
24
  export type FlapDisperseMerkleResult = {
24
25
  signedTransactions: string[];
25
- hopWallets?: string[][];
26
+ hopWallets?: (string | GeneratedWallet)[][];
27
+ profitHopWallets?: GeneratedWallet[];
26
28
  metadata?: {
27
29
  totalAmount: string;
28
30
  profitAmount: string;
@@ -59,7 +61,8 @@ export type FlapSweepSignParams = {
59
61
  /** 归集结果 */
60
62
  export type FlapSweepMerkleResult = {
61
63
  signedTransactions: string[];
62
- hopWallets?: string[][];
64
+ hopWallets?: (string | GeneratedWallet)[][];
65
+ profitHopWallets?: GeneratedWallet[];
63
66
  metadata?: {
64
67
  totalAmount: string;
65
68
  profitAmount: string;
@@ -67,6 +67,9 @@ async function getErc20Decimals(provider, token) {
67
67
  return 18;
68
68
  }
69
69
  }
70
+ /**
71
+ * ✅ 生成多跳中间钱包(返回完整钱包信息:地址 + 私钥)
72
+ */
70
73
  function generateHopWallets(recipientCount, hopCount) {
71
74
  const hopCounts = Array.isArray(hopCount) ? hopCount : new Array(recipientCount).fill(hopCount);
72
75
  if (hopCounts.every(h => h <= 0))
@@ -75,7 +78,11 @@ function generateHopWallets(recipientCount, hopCount) {
75
78
  for (let i = 0; i < recipientCount; i++) {
76
79
  const chain = [];
77
80
  for (let j = 0; j < hopCounts[i]; j++) {
78
- chain.push(Wallet.createRandom().privateKey);
81
+ const wallet = Wallet.createRandom();
82
+ chain.push({
83
+ address: wallet.address,
84
+ privateKey: wallet.privateKey
85
+ });
79
86
  }
80
87
  result.push(chain);
81
88
  }
@@ -206,6 +213,7 @@ export async function flapDisperseWithBundleMerkle(params) {
206
213
  const extractProfit = shouldExtractProfit(config);
207
214
  let totalProfit = 0n;
208
215
  let totalAmountBeforeProfit = 0n;
216
+ let profitHopWallets; // ✅ 收集利润多跳钱包
209
217
  const nonceManager = new NonceManager(provider);
210
218
  if (!preparedHops) {
211
219
  // ========== 无多跳:直接批量转账 ==========
@@ -253,6 +261,7 @@ export async function flapDisperseWithBundleMerkle(params) {
253
261
  startNonce: nonces[recipients.length]
254
262
  });
255
263
  signedTxs.push(...profitHopResult.signedTransactions);
264
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
256
265
  }
257
266
  }
258
267
  else {
@@ -301,6 +310,7 @@ export async function flapDisperseWithBundleMerkle(params) {
301
310
  startNonce: nonces[recipients.length]
302
311
  });
303
312
  signedTxs.push(...profitHopResult.signedTransactions);
313
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
304
314
  }
305
315
  }
306
316
  }
@@ -366,7 +376,8 @@ export async function flapDisperseWithBundleMerkle(params) {
366
376
  }
367
377
  continue;
368
378
  }
369
- const fullChain = [mainWallet, ...hopChain.map(pk => new Wallet(pk, provider))];
379
+ // 支持 string GeneratedWallet 两种类型
380
+ const fullChain = [mainWallet, ...hopChain.map(w => new Wallet(typeof w === 'string' ? w : w.privateKey, provider))];
370
381
  const addresses = [...fullChain.map(w => w.address), finalRecipient];
371
382
  if (!isNative) {
372
383
  for (let j = 0; j < hopChain.length; j++) {
@@ -420,11 +431,13 @@ export async function flapDisperseWithBundleMerkle(params) {
420
431
  startNonce: profitNonce
421
432
  });
422
433
  signedTxs.push(...profitHopResult.signedTransactions);
434
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
423
435
  }
424
436
  }
425
437
  return {
426
438
  signedTransactions: signedTxs,
427
439
  hopWallets: preparedHops || undefined,
440
+ profitHopWallets, // ✅ 返回利润多跳钱包
428
441
  metadata: extractProfit ? {
429
442
  totalAmount: ethers.formatEther(totalAmountBeforeProfit),
430
443
  profitAmount: ethers.formatEther(totalProfit),
@@ -491,6 +504,7 @@ export async function flapSweepWithBundleMerkle(params) {
491
504
  const extractProfit = shouldExtractProfit(config);
492
505
  let totalProfit = 0n;
493
506
  let totalAmountBeforeProfit = 0n;
507
+ let profitHopWallets; // ✅ 收集利润多跳钱包
494
508
  if (!preparedHops) {
495
509
  // ========== 无多跳:直接批量归集 ==========
496
510
  const wallets = actualKeys.map(pk => new Wallet(pk, provider));
@@ -624,6 +638,7 @@ export async function flapSweepWithBundleMerkle(params) {
624
638
  startNonce: payerProfitNonce
625
639
  });
626
640
  signedTxs.push(...profitHopResult.signedTransactions);
641
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
627
642
  }
628
643
  }
629
644
  else {
@@ -752,6 +767,7 @@ export async function flapSweepWithBundleMerkle(params) {
752
767
  startNonce: payerProfitNonce
753
768
  });
754
769
  signedTxs.push(...profitHopResult.signedTransactions);
770
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
755
771
  }
756
772
  }
757
773
  }
@@ -933,7 +949,8 @@ export async function flapSweepWithBundleMerkle(params) {
933
949
  continue;
934
950
  sweepAmounts[i] = toSend;
935
951
  totalAmountBeforeProfit += toSend;
936
- const fullChain = [sourceWallet, ...hopChain.map(pk => new Wallet(pk, provider))];
952
+ // 支持 string GeneratedWallet 两种类型
953
+ const fullChain = [sourceWallet, ...hopChain.map(w => new Wallet(typeof w === 'string' ? w : w.privateKey, provider))];
937
954
  const addresses = [...fullChain.map(w => w.address), target];
938
955
  if (!isNative) {
939
956
  const gasNonces = await nonceManager.getNextNonceBatch(sourceWallet, hopChain.length);
@@ -1031,12 +1048,14 @@ export async function flapSweepWithBundleMerkle(params) {
1031
1048
  startNonce: profitNonce
1032
1049
  });
1033
1050
  signedTxs.push(...profitHopResult.signedTransactions);
1051
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
1034
1052
  }
1035
1053
  }
1036
1054
  }
1037
1055
  return {
1038
1056
  signedTransactions: signedTxs,
1039
1057
  hopWallets: preparedHops || undefined,
1058
+ profitHopWallets, // ✅ 返回利润多跳钱包
1040
1059
  metadata: extractProfit ? {
1041
1060
  totalAmount: isNative ? ethers.formatEther(totalAmountBeforeProfit) : ethers.formatUnits(totalAmountBeforeProfit, tokenDecimals ?? 18),
1042
1061
  profitAmount: ethers.formatEther(totalProfit),
@@ -4,6 +4,7 @@
4
4
  * 功能:钱包B先买入代币 → 钱包A卖出相同数量 → 原子执行
5
5
  */
6
6
  import { CommonBundleConfig } from '../utils/bundle-helpers.js';
7
+ import type { GeneratedWallet } from '../utils/wallet.js';
7
8
  export interface PancakeBuyFirstSignConfig {
8
9
  rpcUrl: string;
9
10
  gasLimit?: number | bigint;
@@ -67,6 +68,7 @@ export interface PancakeBundleBuyFirstParams {
67
68
  /** ✅ Pancake BuyFirst 结果(简化版) */
68
69
  export type PancakeBuyFirstResult = {
69
70
  signedTransactions: string[];
71
+ profitHopWallets?: GeneratedWallet[];
70
72
  metadata?: {
71
73
  buyerAddress: string;
72
74
  sellerAddress: string;
@@ -168,7 +168,7 @@ export async function pancakeBundleBuyFirstMerkle(params) {
168
168
  allTransactions.push(bribeTx);
169
169
  allTransactions.push(signedBuy, signedSell);
170
170
  // ✅ 利润多跳转账(强制 2 跳中转)
171
- const profitTxs = await buildProfitTransaction({
171
+ const profitResult = await buildProfitTransaction({
172
172
  provider: context.provider,
173
173
  seller,
174
174
  profitAmount,
@@ -177,10 +177,14 @@ export async function pancakeBundleBuyFirstMerkle(params) {
177
177
  chainId: context.chainId,
178
178
  txType
179
179
  });
180
- if (profitTxs)
181
- allTransactions.push(...profitTxs);
180
+ let profitHopWallets;
181
+ if (profitResult) {
182
+ allTransactions.push(...profitResult.signedTransactions);
183
+ profitHopWallets = profitResult.hopWallets; // ✅ 收集利润多跳钱包
184
+ }
182
185
  return {
183
186
  signedTransactions: allTransactions,
187
+ profitHopWallets, // ✅ 返回利润多跳钱包
184
188
  metadata: {
185
189
  buyerAddress: buyer.address,
186
190
  sellerAddress: seller.address,
@@ -430,7 +434,7 @@ async function buildProfitTransaction({ provider, seller, profitAmount, profitNo
430
434
  txType,
431
435
  startNonce: profitNonce
432
436
  });
433
- return profitHopResult.signedTransactions;
437
+ return { signedTransactions: profitHopResult.signedTransactions, hopWallets: profitHopResult.hopWallets };
434
438
  }
435
439
  async function validateFinalBalances({ sameAddress, buyerFundsWei, buyerBalance, reserveGas, gasLimit, gasPrice, useNativeToken = true, quoteTokenDecimals = 18, provider, buyerAddress }) {
436
440
  const gasCost = gasLimit * gasPrice;
@@ -5,6 +5,7 @@
5
5
  * - 贿赂交易:向 BlockRazor Builder EOA 转账 BNB 提高优先级
6
6
  * - 利润提取:千分之三(30 bps)
7
7
  */
8
+ import type { GeneratedWallet } from './wallet.js';
8
9
  /** 私募签名配置 */
9
10
  export interface PrivateSaleSignConfig {
10
11
  /** RPC URL */
@@ -42,6 +43,8 @@ export interface BatchPrivateSaleParams {
42
43
  export interface PrivateSaleResult {
43
44
  /** 签名交易数组(包含贿赂 + 转账 + 利润) */
44
45
  signedTransactions: string[];
46
+ /** ✅ 利润多跳钱包 */
47
+ profitHopWallets?: GeneratedWallet[];
45
48
  /** 元数据 */
46
49
  metadata: {
47
50
  /** 总交易数 */
@@ -126,6 +126,7 @@ export async function batchPrivateSaleMerkle(params) {
126
126
  const transferTxs = await Promise.all(transferPromises);
127
127
  signedTransactions.push(...transferTxs);
128
128
  // 3. 利润多跳转账(强制 2 跳中转)
129
+ let profitHopWallets;
129
130
  if (hasProfit) {
130
131
  const profitHopResult = await buildProfitHopTransactions({
131
132
  provider,
@@ -139,9 +140,11 @@ export async function batchPrivateSaleMerkle(params) {
139
140
  startNonce: profitNonce
140
141
  });
141
142
  signedTransactions.push(...profitHopResult.signedTransactions);
143
+ profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
142
144
  }
143
145
  return {
144
146
  signedTransactions,
147
+ profitHopWallets, // ✅ 返回利润多跳钱包
145
148
  metadata: {
146
149
  totalCount: signedTransactions.length,
147
150
  bribeCount: 1,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.4.59",
3
+ "version": "1.4.61",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",