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.
- package/dist/contracts/tm-bundle-merkle/core.js +13 -5
- package/dist/contracts/tm-bundle-merkle/internal.d.ts +5 -1
- package/dist/contracts/tm-bundle-merkle/internal.js +8 -1
- package/dist/contracts/tm-bundle-merkle/pancake-proxy.js +8 -2
- package/dist/contracts/tm-bundle-merkle/private.js +16 -4
- package/dist/contracts/tm-bundle-merkle/swap-buy-first.d.ts +2 -0
- package/dist/contracts/tm-bundle-merkle/swap-buy-first.js +3 -0
- package/dist/contracts/tm-bundle-merkle/types.d.ts +5 -2
- package/dist/contracts/tm-bundle-merkle/types.js +0 -3
- package/dist/contracts/tm-bundle-merkle/utils.js +14 -2
- package/dist/contracts/tm-bundle.d.ts +4 -0
- package/dist/contracts/tm-bundle.js +10 -3
- package/dist/dex/direct-router.d.ts +2 -0
- package/dist/dex/direct-router.js +22 -7
- package/dist/flap/portal-bundle-merkle/core.js +10 -1
- package/dist/flap/portal-bundle-merkle/pancake-proxy.js +8 -2
- package/dist/flap/portal-bundle-merkle/private.js +17 -7
- package/dist/flap/portal-bundle-merkle/swap-buy-first.d.ts +2 -0
- package/dist/flap/portal-bundle-merkle/swap-buy-first.js +8 -4
- package/dist/flap/portal-bundle-merkle/types.d.ts +3 -0
- package/dist/flap/portal-bundle-merkle/types.js +0 -3
- package/dist/flap/portal-bundle-merkle/utils.d.ts +5 -2
- package/dist/flap/portal-bundle-merkle/utils.js +22 -3
- package/dist/pancake/bundle-buy-first.d.ts +2 -0
- package/dist/pancake/bundle-buy-first.js +8 -4
- package/dist/utils/private-sale.d.ts +3 -0
- package/dist/utils/private-sale.js +3 -0
- 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
|
-
|
|
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
|
-
|
|
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
|
-
/**
|
|
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;
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
|
554
|
-
signedTxs.push(...
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
222
|
-
|
|
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,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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
181
|
-
|
|
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,
|