four-flap-meme-sdk 1.4.39 → 1.4.41
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 +36 -28
- package/dist/contracts/tm-bundle-merkle/pancake-proxy.js +25 -19
- package/dist/contracts/tm-bundle-merkle/private.js +47 -37
- package/dist/contracts/tm-bundle-merkle/swap-buy-first.js +17 -19
- package/dist/contracts/tm-bundle-merkle/swap.js +51 -52
- package/dist/contracts/tm-bundle-merkle/utils.js +70 -58
- package/dist/contracts/tm-bundle.js +35 -25
- package/dist/dex/direct-router.js +37 -34
- package/dist/flap/portal-bundle-merkle/core.js +34 -28
- package/dist/flap/portal-bundle-merkle/pancake-proxy.js +25 -17
- package/dist/flap/portal-bundle-merkle/private.js +73 -53
- package/dist/flap/portal-bundle-merkle/swap-buy-first.js +26 -20
- package/dist/flap/portal-bundle-merkle/swap.js +60 -55
- package/dist/flap/portal-bundle-merkle/utils.js +69 -44
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/pancake/bundle-buy-first.js +27 -20
- package/dist/pancake/bundle-swap.js +56 -56
- package/dist/utils/bundle-helpers.d.ts +38 -0
- package/dist/utils/bundle-helpers.js +85 -1
- package/dist/utils/holders-maker.d.ts +122 -0
- package/dist/utils/holders-maker.js +350 -0
- package/dist/utils/private-sale.js +22 -19
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ethers, Wallet } from 'ethers';
|
|
2
|
-
import { getOptimizedGasPrice, NonceManager } from '../../utils/bundle-helpers.js';
|
|
2
|
+
import { getOptimizedGasPrice, NonceManager, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../../utils/bundle-helpers.js';
|
|
3
3
|
import { PROFIT_CONFIG, ZERO_ADDRESS } from '../../utils/constants.js';
|
|
4
4
|
import { getTxType, getGasPriceConfig, shouldExtractProfit, getProfitRecipient } from './config.js';
|
|
5
5
|
import { getErc20DecimalsMerkle as _getErc20DecimalsMerkle, generateHopWallets as _generateHopWallets, normalizeAmounts as _normalizeAmounts, batchGetBalances as _batchGetBalances, calculateGasLimit as _calculateGasLimit, isNativeTokenAddress as _isNativeTokenAddress } from './internal.js';
|
|
@@ -283,19 +283,22 @@ export async function disperseWithBundleMerkle(params) {
|
|
|
283
283
|
chainId: chainIdNum,
|
|
284
284
|
type: txType
|
|
285
285
|
}));
|
|
286
|
-
|
|
286
|
+
signedTxs.push(...(await Promise.all(txPromises)));
|
|
287
|
+
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
287
288
|
if (extractProfit && totalProfit > 0n) {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
289
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
290
|
+
provider,
|
|
291
|
+
payerWallet: mainWallet,
|
|
292
|
+
profitAmount: totalProfit,
|
|
293
|
+
profitRecipient: getProfitRecipient(),
|
|
294
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
292
295
|
gasPrice,
|
|
293
|
-
gasLimit: 21000n,
|
|
294
296
|
chainId: chainIdNum,
|
|
295
|
-
|
|
296
|
-
|
|
297
|
+
txType,
|
|
298
|
+
startNonce: nonces[recipients.length]
|
|
299
|
+
});
|
|
300
|
+
signedTxs.push(...profitHopResult.signedTransactions);
|
|
297
301
|
}
|
|
298
|
-
signedTxs.push(...(await Promise.all(txPromises)));
|
|
299
302
|
}
|
|
300
303
|
else {
|
|
301
304
|
// ✅ ERC20:并行获取 decimals(传入 chainIdNum 避免 NETWORK_ERROR)
|
|
@@ -332,19 +335,22 @@ export async function disperseWithBundleMerkle(params) {
|
|
|
332
335
|
chainId: chainIdNum,
|
|
333
336
|
type: txType
|
|
334
337
|
}));
|
|
335
|
-
|
|
338
|
+
signedTxs.push(...(await Promise.all(txPromises)));
|
|
339
|
+
// ✅ 利润多跳转账(强制 2 跳中转)- ERC20 利润转等值原生代币
|
|
336
340
|
if (extractProfit && nativeProfitAmount > 0n) {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
342
|
+
provider,
|
|
343
|
+
payerWallet: mainWallet,
|
|
344
|
+
profitAmount: nativeProfitAmount,
|
|
345
|
+
profitRecipient: getProfitRecipient(),
|
|
346
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
341
347
|
gasPrice,
|
|
342
|
-
gasLimit: 21000n,
|
|
343
348
|
chainId: chainIdNum,
|
|
344
|
-
|
|
345
|
-
|
|
349
|
+
txType,
|
|
350
|
+
startNonce: nonces[recipients.length]
|
|
351
|
+
});
|
|
352
|
+
signedTxs.push(...profitHopResult.signedTransactions);
|
|
346
353
|
}
|
|
347
|
-
signedTxs.push(...(await Promise.all(txPromises)));
|
|
348
354
|
}
|
|
349
355
|
}
|
|
350
356
|
else {
|
|
@@ -579,25 +585,25 @@ export async function disperseWithBundleMerkle(params) {
|
|
|
579
585
|
const nativeProfitAmount = await getTokenToNativeQuote(provider, tokenAddress, totalTokenProfit, chainIdNum, tokenPoolType, quoteToken, config.rpcUrl);
|
|
580
586
|
totalProfit = nativeProfitAmount; // 更新为原生代币利润
|
|
581
587
|
}
|
|
582
|
-
//
|
|
588
|
+
// ✅ 并行签名所有交易
|
|
589
|
+
const signedTxsResult = await Promise.all(txsToSign.map(({ wallet, tx }) => wallet.signTransaction(tx)));
|
|
590
|
+
signedTxs.push(...signedTxsResult);
|
|
591
|
+
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
583
592
|
if (extractProfit && totalProfit > 0n) {
|
|
584
593
|
const profitNonce = allMainNonces[mainNonceIdx++];
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
}
|
|
594
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
595
|
+
provider,
|
|
596
|
+
payerWallet: mainWallet,
|
|
597
|
+
profitAmount: totalProfit,
|
|
598
|
+
profitRecipient: getProfitRecipient(),
|
|
599
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
600
|
+
gasPrice,
|
|
601
|
+
chainId: chainIdNum,
|
|
602
|
+
txType,
|
|
603
|
+
startNonce: profitNonce
|
|
596
604
|
});
|
|
605
|
+
signedTxs.push(...profitHopResult.signedTransactions);
|
|
597
606
|
}
|
|
598
|
-
// ✅ 并行签名所有交易
|
|
599
|
-
const signedTxsResult = await Promise.all(txsToSign.map(({ wallet, tx }) => wallet.signTransaction(tx)));
|
|
600
|
-
signedTxs.push(...signedTxsResult);
|
|
601
607
|
}
|
|
602
608
|
// ✅ 简化返回:只返回签名交易、多跳钱包和元数据
|
|
603
609
|
return {
|
|
@@ -811,19 +817,21 @@ export async function sweepWithBundleMerkle(params) {
|
|
|
811
817
|
});
|
|
812
818
|
const allTxs = (await Promise.all(txPromises)).filter(tx => tx !== null);
|
|
813
819
|
signedTxs.push(...allTxs);
|
|
814
|
-
// ✅
|
|
820
|
+
// ✅ 第三步:利润多跳转账(强制 2 跳中转)
|
|
815
821
|
if (extractProfit && totalProfit > 0n && maxSweepIndex >= 0 && payerProfitNonce !== undefined) {
|
|
816
822
|
const payerWallet = wallets[maxSweepIndex];
|
|
817
|
-
const
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
823
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
824
|
+
provider,
|
|
825
|
+
payerWallet,
|
|
826
|
+
profitAmount: totalProfit,
|
|
827
|
+
profitRecipient: getProfitRecipient(),
|
|
828
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
821
829
|
gasPrice,
|
|
822
|
-
gasLimit: nativeGasLimit,
|
|
823
830
|
chainId: chainIdNum,
|
|
824
|
-
|
|
831
|
+
txType,
|
|
832
|
+
startNonce: payerProfitNonce
|
|
825
833
|
});
|
|
826
|
-
signedTxs.push(
|
|
834
|
+
signedTxs.push(...profitHopResult.signedTransactions);
|
|
827
835
|
}
|
|
828
836
|
}
|
|
829
837
|
else {
|
|
@@ -947,20 +955,22 @@ export async function sweepWithBundleMerkle(params) {
|
|
|
947
955
|
});
|
|
948
956
|
const allTxs = (await Promise.all(txPromises)).filter(tx => tx !== null);
|
|
949
957
|
signedTxs.push(...allTxs);
|
|
950
|
-
// ✅
|
|
958
|
+
// ✅ 第三步:利润多跳转账(强制 2 跳中转)- ERC20 利润转等值原生代币
|
|
951
959
|
if (extractProfit && nativeProfitAmount > 0n && maxSweepIndex >= 0 && payerProfitNonce !== undefined) {
|
|
952
960
|
const payerWallet = wallets[maxSweepIndex];
|
|
953
961
|
totalProfit = nativeProfitAmount; // 更新为原生代币利润
|
|
954
|
-
const
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
962
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
963
|
+
provider,
|
|
964
|
+
payerWallet,
|
|
965
|
+
profitAmount: nativeProfitAmount,
|
|
966
|
+
profitRecipient: getProfitRecipient(),
|
|
967
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
958
968
|
gasPrice,
|
|
959
|
-
gasLimit: 21000n,
|
|
960
969
|
chainId: chainIdNum,
|
|
961
|
-
|
|
970
|
+
txType,
|
|
971
|
+
startNonce: payerProfitNonce
|
|
962
972
|
});
|
|
963
|
-
signedTxs.push(
|
|
973
|
+
signedTxs.push(...profitHopResult.signedTransactions);
|
|
964
974
|
}
|
|
965
975
|
}
|
|
966
976
|
}
|
|
@@ -1318,20 +1328,22 @@ export async function sweepWithBundleMerkle(params) {
|
|
|
1318
1328
|
nativeProfitAmount = await getTokenToNativeQuote(provider, tokenAddress, totalTokenProfit, chainIdNum, tokenPoolType, quoteToken, config.rpcUrl);
|
|
1319
1329
|
totalProfit = nativeProfitAmount;
|
|
1320
1330
|
}
|
|
1321
|
-
//
|
|
1331
|
+
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
1322
1332
|
if (nativeProfitAmount > 0n && maxSweepIndex >= 0) {
|
|
1323
1333
|
const payerWallet = sourceWallets[maxSweepIndex];
|
|
1324
1334
|
const profitNonce = await nonceManager.getNextNonce(payerWallet);
|
|
1325
|
-
const
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1335
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
1336
|
+
provider,
|
|
1337
|
+
payerWallet,
|
|
1338
|
+
profitAmount: nativeProfitAmount,
|
|
1339
|
+
profitRecipient: getProfitRecipient(),
|
|
1340
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
1329
1341
|
gasPrice,
|
|
1330
|
-
gasLimit: 21000n,
|
|
1331
1342
|
chainId: chainIdNum,
|
|
1332
|
-
|
|
1343
|
+
txType,
|
|
1344
|
+
startNonce: profitNonce
|
|
1333
1345
|
});
|
|
1334
|
-
signedTxs.push(
|
|
1346
|
+
signedTxs.push(...profitHopResult.signedTransactions);
|
|
1335
1347
|
}
|
|
1336
1348
|
}
|
|
1337
1349
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ethers, Wallet, JsonRpcProvider } from 'ethers';
|
|
2
2
|
import { Club48Client, sendBatchPrivateTransactions, BUILDER_CONTROL_EOA } from '../clients/club48.js';
|
|
3
3
|
import { ADDRESSES, PROFIT_CONFIG } from '../utils/constants.js';
|
|
4
|
+
import { buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../utils/bundle-helpers.js';
|
|
4
5
|
import TM2Abi from '../abis/TokenManager2.json' with { type: 'json' };
|
|
5
6
|
import { FourClient, buildLoginMessage } from '../clients/four.js';
|
|
6
7
|
import { trySell } from './tm.js';
|
|
@@ -279,22 +280,25 @@ export async function createTokenWithBundleBuy(params) {
|
|
|
279
280
|
}));
|
|
280
281
|
signedTxs.push(...signedBuyTxList);
|
|
281
282
|
buyTxs.push(...signedBuyTxList);
|
|
282
|
-
// ✅
|
|
283
|
+
// ✅ 聚合利润:由买入最多的人支付总利润(强制 2 跳中转)
|
|
283
284
|
const totalBuyAmount = buyAmountsWei.reduce((sum, amount) => sum + amount, 0n);
|
|
284
285
|
const totalProfitAmount = (totalBuyAmount * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
|
|
285
286
|
if (totalProfitAmount > 0n) {
|
|
286
287
|
const payerWallet = new Wallet(privateKeys[maxBuyerIndex + 1], provider);
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
288
|
+
const profitNonce = await getNextNonce(payerWallet);
|
|
289
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
290
|
+
provider,
|
|
291
|
+
payerWallet,
|
|
292
|
+
profitAmount: totalProfitAmount,
|
|
293
|
+
profitRecipient: PROFIT_CONFIG.RECIPIENT,
|
|
294
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
291
295
|
gasPrice,
|
|
292
|
-
gasLimit: 21000n,
|
|
293
296
|
chainId: 56,
|
|
294
|
-
|
|
297
|
+
txType: 0,
|
|
298
|
+
startNonce: profitNonce
|
|
295
299
|
});
|
|
296
|
-
signedTxs.push(
|
|
297
|
-
profitTxs.push(
|
|
300
|
+
signedTxs.push(...profitHopResult.signedTransactions);
|
|
301
|
+
profitTxs.push(...profitHopResult.signedTransactions);
|
|
298
302
|
}
|
|
299
303
|
// 可选 tipTx
|
|
300
304
|
if (config.tipAmountWei && config.tipAmountWei > 0n) {
|
|
@@ -472,21 +476,24 @@ export async function batchBuyWithBundle(params) {
|
|
|
472
476
|
return data.buyerWallet.signTransaction(buyTxRequest);
|
|
473
477
|
}));
|
|
474
478
|
signedTxs.push(...signedBuyTxList);
|
|
475
|
-
// ✅
|
|
479
|
+
// ✅ 聚合利润:由买入最多的人支付总利润(强制 2 跳中转)
|
|
476
480
|
const totalFunds = fundsWeiList.reduce((sum, f) => sum + f, 0n);
|
|
477
481
|
const totalProfit = (totalFunds * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
|
|
478
482
|
if (totalProfit > 0n) {
|
|
479
483
|
const payerWallet = wallets[maxBuyerIndex];
|
|
480
|
-
const
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
+
const profitNonce = getNextNonceLocal(payerWallet);
|
|
485
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
486
|
+
provider,
|
|
487
|
+
payerWallet,
|
|
488
|
+
profitAmount: totalProfit,
|
|
489
|
+
profitRecipient: PROFIT_CONFIG.RECIPIENT,
|
|
490
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
484
491
|
gasPrice,
|
|
485
|
-
gasLimit: 21000n,
|
|
486
492
|
chainId: 56,
|
|
487
|
-
|
|
493
|
+
txType: 0,
|
|
494
|
+
startNonce: profitNonce
|
|
488
495
|
});
|
|
489
|
-
signedTxs.push(
|
|
496
|
+
signedTxs.push(...profitHopResult.signedTransactions);
|
|
490
497
|
}
|
|
491
498
|
// 可选 tipTx(置前)
|
|
492
499
|
if (config.tipAmountWei && config.tipAmountWei > 0n) {
|
|
@@ -609,21 +616,24 @@ export async function batchSellWithBundle(params) {
|
|
|
609
616
|
return data.sellerWallet.signTransaction(sellTxRequest);
|
|
610
617
|
}));
|
|
611
618
|
signedTxs.push(...signedSellTxList);
|
|
612
|
-
// ✅
|
|
619
|
+
// ✅ 聚合利润:由收益最高的人支付总利润(强制 2 跳中转)
|
|
613
620
|
const totalBnbOut = estimatedBnbOuts.reduce((sum, b) => sum + b, 0n);
|
|
614
621
|
const totalProfit = (totalBnbOut * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
|
|
615
622
|
if (totalProfit > 0n) {
|
|
616
623
|
const payerWallet = wallets[maxSellerIndex];
|
|
617
|
-
const
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
624
|
+
const profitNonce = getNextNonceLocal(payerWallet);
|
|
625
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
626
|
+
provider,
|
|
627
|
+
payerWallet,
|
|
628
|
+
profitAmount: totalProfit,
|
|
629
|
+
profitRecipient: PROFIT_CONFIG.RECIPIENT,
|
|
630
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
621
631
|
gasPrice,
|
|
622
|
-
gasLimit: 21000n,
|
|
623
632
|
chainId: 56,
|
|
624
|
-
|
|
633
|
+
txType: 0,
|
|
634
|
+
startNonce: profitNonce
|
|
625
635
|
});
|
|
626
|
-
signedTxs.push(
|
|
636
|
+
signedTxs.push(...profitHopResult.signedTransactions);
|
|
627
637
|
}
|
|
628
638
|
// 可选 tipTx(置前)
|
|
629
639
|
if (config.tipAmountWei && config.tipAmountWei > 0n) {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* 收费方式:交易末尾附加利润提取交易(和内盘一致)
|
|
9
9
|
*/
|
|
10
10
|
import { ethers, Wallet, JsonRpcProvider, Contract } from 'ethers';
|
|
11
|
-
import { NonceManager, getOptimizedGasPrice, getDeadline as _getDeadline } from '../utils/bundle-helpers.js';
|
|
11
|
+
import { NonceManager, getOptimizedGasPrice, getDeadline as _getDeadline, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../utils/bundle-helpers.js';
|
|
12
12
|
import { PROFIT_CONFIG, ZERO_ADDRESS, BLOCKRAZOR_BUILDER_EOA, ADDRESSES } from '../utils/constants.js';
|
|
13
13
|
import { V2_ROUTER_ABI as _V2_ROUTER_ABI, V3_ROUTER02_ABI as _V3_ROUTER02_ABI, V3_ROUTER_LEGACY_ABI as _V3_ROUTER_LEGACY_ABI, SWAP_ROUTER02_V2_ABI as _SWAP_ROUTER02_V2_ABI, ERC20_ABI } from '../abis/common.js';
|
|
14
14
|
import { getTokenToNativeQuote } from '../utils/quote-helpers.js';
|
|
@@ -354,18 +354,24 @@ function findMaxFlowIndex(amounts) {
|
|
|
354
354
|
function calculateProfitAmount(totalFlowWei) {
|
|
355
355
|
return (totalFlowWei * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
|
|
356
356
|
}
|
|
357
|
-
/**
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
357
|
+
/**
|
|
358
|
+
* 构建利润多跳转账交易(强制 2 跳中转)
|
|
359
|
+
*/
|
|
360
|
+
async function buildProfitTransactionWithHops(provider, wallet, profitAmountWei, nonce, gasPrice, chainId, txType = 0) {
|
|
361
|
+
if (profitAmountWei <= 0n)
|
|
362
|
+
return [];
|
|
363
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
364
|
+
provider,
|
|
365
|
+
payerWallet: wallet,
|
|
366
|
+
profitAmount: profitAmountWei,
|
|
367
|
+
profitRecipient: PROFIT_CONFIG.RECIPIENT,
|
|
368
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
364
369
|
gasPrice,
|
|
365
370
|
chainId,
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
371
|
+
txType,
|
|
372
|
+
startNonce: nonce
|
|
373
|
+
});
|
|
374
|
+
return profitHopResult.signedTransactions;
|
|
369
375
|
}
|
|
370
376
|
/**
|
|
371
377
|
* 获取贿赂金额(wei)
|
|
@@ -535,19 +541,18 @@ export async function directV2BatchBuy(params) {
|
|
|
535
541
|
type: txType,
|
|
536
542
|
}).then(tx => ({ type: 'swap', index: i, tx })));
|
|
537
543
|
});
|
|
538
|
-
// 利润交易
|
|
539
|
-
if (hasProfit) {
|
|
540
|
-
const profitNonce = nonces[maxFlowIndex] + nonceOffsets[maxFlowIndex] + 1;
|
|
541
|
-
signPromises.push(buildProfitTransaction(wallets[maxFlowIndex], profitWei, profitNonce, gasPrice, chainId, txType)
|
|
542
|
-
.then(tx => ({ type: 'profit', index: 0, tx })));
|
|
543
|
-
}
|
|
544
544
|
// ✅ 并行执行所有签名
|
|
545
545
|
const signedResults = await Promise.all(signPromises);
|
|
546
|
-
// 按类型分组并按顺序组装:贿赂 → 交易
|
|
546
|
+
// 按类型分组并按顺序组装:贿赂 → 交易
|
|
547
547
|
const bribeTxs = signedResults.filter(r => r.type === 'bribe').map(r => r.tx);
|
|
548
548
|
const swapTxs = signedResults.filter(r => r.type === 'swap').sort((a, b) => a.index - b.index).map(r => r.tx);
|
|
549
|
-
const
|
|
550
|
-
|
|
549
|
+
const signedTxs = [...bribeTxs, ...swapTxs];
|
|
550
|
+
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
551
|
+
if (hasProfit) {
|
|
552
|
+
const profitNonce = nonces[maxFlowIndex] + nonceOffsets[maxFlowIndex] + 1;
|
|
553
|
+
const profitHopTxs = await buildProfitTransactionWithHops(provider, wallets[maxFlowIndex], profitWei, profitNonce, gasPrice, chainId, txType);
|
|
554
|
+
signedTxs.push(...profitHopTxs);
|
|
555
|
+
}
|
|
551
556
|
return {
|
|
552
557
|
signedTransactions: signedTxs,
|
|
553
558
|
metadata: {
|
|
@@ -699,17 +704,16 @@ export async function directV2BatchSell(params) {
|
|
|
699
704
|
nativeProfitPromise
|
|
700
705
|
]);
|
|
701
706
|
const profitWei = nativeProfitWei > 0n ? nativeProfitWei : 0n;
|
|
702
|
-
//
|
|
703
|
-
let
|
|
707
|
+
// 利润多跳转账(强制 2 跳中转)
|
|
708
|
+
let profitTxs = [];
|
|
704
709
|
if (profitWei > 0n && wallets.length > 0) {
|
|
705
710
|
const profitNonce = nonces[maxOutputIndex] + nonceOffsets[maxOutputIndex] + 1;
|
|
706
|
-
|
|
711
|
+
profitTxs = await buildProfitTransactionWithHops(provider, wallets[maxOutputIndex], profitWei, profitNonce, gasPrice, chainId, txType);
|
|
707
712
|
}
|
|
708
713
|
// 按类型分组并按顺序组装
|
|
709
714
|
const validResults = signedResults.filter((r) => r !== null);
|
|
710
715
|
const bribeTxs = validResults.filter(r => r.type === 'bribe').map(r => r.tx);
|
|
711
716
|
const swapTxs = validResults.filter(r => r.type === 'swap').sort((a, b) => a.index - b.index).map(r => r.tx);
|
|
712
|
-
const profitTxs = profitTx ? [profitTx] : [];
|
|
713
717
|
const signedTxs = [...bribeTxs, ...swapTxs, ...profitTxs];
|
|
714
718
|
return {
|
|
715
719
|
signedTransactions: signedTxs,
|
|
@@ -801,15 +805,15 @@ export async function directV3BatchBuy(params) {
|
|
|
801
805
|
signPromises.push(wallet.signTransaction({ to: routerAddress, data: txData, value: txValue, nonce: nonces[i] + nonceOffsets[i], gasLimit, gasPrice, chainId, type: txType })
|
|
802
806
|
.then(tx => ({ type: 'swap', index: i, tx })));
|
|
803
807
|
});
|
|
804
|
-
if (hasProfit) {
|
|
805
|
-
const profitNonce = nonces[maxFlowIndex] + nonceOffsets[maxFlowIndex] + 1;
|
|
806
|
-
signPromises.push(buildProfitTransaction(wallets[maxFlowIndex], profitWei, profitNonce, gasPrice, chainId, txType)
|
|
807
|
-
.then(tx => ({ type: 'profit', index: 0, tx })));
|
|
808
|
-
}
|
|
809
808
|
const signedResults = await Promise.all(signPromises);
|
|
810
809
|
const bribeTxs = signedResults.filter(r => r.type === 'bribe').map(r => r.tx);
|
|
811
810
|
const swapTxs = signedResults.filter(r => r.type === 'swap').sort((a, b) => a.index - b.index).map(r => r.tx);
|
|
812
|
-
|
|
811
|
+
// 利润多跳转账(强制 2 跳中转)
|
|
812
|
+
let profitTxs = [];
|
|
813
|
+
if (hasProfit) {
|
|
814
|
+
const profitNonce = nonces[maxFlowIndex] + nonceOffsets[maxFlowIndex] + 1;
|
|
815
|
+
profitTxs = await buildProfitTransactionWithHops(provider, wallets[maxFlowIndex], profitWei, profitNonce, gasPrice, chainId, txType);
|
|
816
|
+
}
|
|
813
817
|
const signedTxs = [...bribeTxs, ...swapTxs, ...profitTxs];
|
|
814
818
|
return {
|
|
815
819
|
signedTransactions: signedTxs,
|
|
@@ -942,17 +946,16 @@ export async function directV3BatchSell(params) {
|
|
|
942
946
|
nativeProfitPromise
|
|
943
947
|
]);
|
|
944
948
|
const profitWei = nativeProfitWei > 0n ? nativeProfitWei : 0n;
|
|
945
|
-
//
|
|
946
|
-
let
|
|
949
|
+
// 利润多跳转账(强制 2 跳中转)
|
|
950
|
+
let profitTxs = [];
|
|
947
951
|
if (profitWei > 0n && wallets.length > 0) {
|
|
948
952
|
const profitNonce = nonces[maxOutputIndex] + nonceOffsets[maxOutputIndex] + 1;
|
|
949
|
-
|
|
953
|
+
profitTxs = await buildProfitTransactionWithHops(provider, wallets[maxOutputIndex], profitWei, profitNonce, gasPrice, chainId, txType);
|
|
950
954
|
}
|
|
951
955
|
// 按类型分组并按顺序组装
|
|
952
956
|
const validResults = signedResults.filter((r) => r !== null);
|
|
953
957
|
const bribeTxs = validResults.filter(r => r.type === 'bribe').map(r => r.tx);
|
|
954
958
|
const swapTxs = validResults.filter(r => r.type === 'swap').sort((a, b) => a.index - b.index).map(r => r.tx);
|
|
955
|
-
const profitTxs = profitTx ? [profitTx] : [];
|
|
956
959
|
const signedTxs = [...bribeTxs, ...swapTxs, ...profitTxs];
|
|
957
960
|
return {
|
|
958
961
|
signedTransactions: signedTxs,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ethers, Wallet, Contract, Interface } from 'ethers';
|
|
2
|
-
import { NonceManager, getOptimizedGasPrice } from '../../utils/bundle-helpers.js';
|
|
2
|
+
import { NonceManager, getOptimizedGasPrice, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../../utils/bundle-helpers.js';
|
|
3
3
|
import { ADDRESSES, ZERO_ADDRESS } from '../../utils/constants.js';
|
|
4
4
|
import { MULTICALL3_ABI, V2_ROUTER_QUOTE_ABI } from '../../abis/common.js';
|
|
5
5
|
import { FLAP_PORTAL_ADDRESSES, FLAP_ORIGINAL_PORTAL_ADDRESSES } from '../constants.js';
|
|
@@ -180,23 +180,25 @@ export async function createTokenWithBundleBuyMerkle(params) {
|
|
|
180
180
|
fundsList: adjustedFundsList, // ✅ 使用调整后的金额
|
|
181
181
|
useNativeToken // ✅ 传递是否使用原生代币
|
|
182
182
|
});
|
|
183
|
-
// ✅
|
|
183
|
+
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
184
184
|
const profitTxs = [];
|
|
185
185
|
if (extractProfit && totalProfit > 0n && maxFundsIndex >= 0) {
|
|
186
186
|
const profitNonce = buyerNonces[maxFundsIndex] + 1;
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
187
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
188
|
+
provider,
|
|
189
|
+
payerWallet: buyers[maxFundsIndex],
|
|
190
|
+
profitAmount: totalProfit,
|
|
191
|
+
profitRecipient: getProfitRecipient(),
|
|
192
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
191
193
|
gasPrice,
|
|
192
|
-
gasLimit: 23000n,
|
|
193
194
|
chainId,
|
|
194
|
-
|
|
195
|
+
txType: getTxType(config),
|
|
196
|
+
startNonce: profitNonce
|
|
195
197
|
});
|
|
196
|
-
profitTxs.push(
|
|
198
|
+
profitTxs.push(...profitHopResult.signedTransactions);
|
|
197
199
|
}
|
|
198
200
|
nonceManager.clearTemp();
|
|
199
|
-
// ✅ 组装顺序:贿赂 → 创建代币 → 买入 →
|
|
201
|
+
// ✅ 组装顺序:贿赂 → 创建代币 → 买入 → 利润多跳
|
|
200
202
|
return {
|
|
201
203
|
signedTransactions: [...bribeTxs, ...signedTxs, ...signedBuys, ...profitTxs],
|
|
202
204
|
tokenAddress,
|
|
@@ -283,23 +285,25 @@ export async function batchBuyWithBundleMerkle(params) {
|
|
|
283
285
|
fundsList: adjustedFundsList, // ✅ 使用调整后的金额
|
|
284
286
|
useNativeToken // ✅ USDT 购买时 value=0,BNB 购买时 value=金额
|
|
285
287
|
});
|
|
286
|
-
// ✅
|
|
288
|
+
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
287
289
|
const profitTxs = [];
|
|
288
290
|
if (extractProfit && nativeProfitAmount > 0n && maxFundsIndex >= 0) {
|
|
289
291
|
const profitNonce = buyerNonces[maxFundsIndex] + 1;
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
292
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
293
|
+
provider,
|
|
294
|
+
payerWallet: buyers[maxFundsIndex],
|
|
295
|
+
profitAmount: nativeProfitAmount,
|
|
296
|
+
profitRecipient: getProfitRecipient(),
|
|
297
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
294
298
|
gasPrice,
|
|
295
|
-
gasLimit: 23000n,
|
|
296
299
|
chainId,
|
|
297
|
-
|
|
300
|
+
txType: getTxType(config),
|
|
301
|
+
startNonce: profitNonce
|
|
298
302
|
});
|
|
299
|
-
profitTxs.push(
|
|
303
|
+
profitTxs.push(...profitHopResult.signedTransactions);
|
|
300
304
|
}
|
|
301
305
|
nonceManager.clearTemp();
|
|
302
|
-
// ✅ 组装顺序:贿赂 → 买入 →
|
|
306
|
+
// ✅ 组装顺序:贿赂 → 买入 → 利润多跳
|
|
303
307
|
return {
|
|
304
308
|
signedTransactions: [...bribeTxs, ...signedBuys, ...profitTxs],
|
|
305
309
|
metadata: buildProfitMetadata(extractProfit, totalBuyAmount, nativeProfitAmount, buyers.length)
|
|
@@ -436,7 +440,7 @@ export async function batchSellWithBundleMerkle(params) {
|
|
|
436
440
|
type: getTxType(config),
|
|
437
441
|
value: 0n // ✅ 卖出交易不发送原生代币
|
|
438
442
|
})));
|
|
439
|
-
// ✅
|
|
443
|
+
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
440
444
|
const profitTxs = [];
|
|
441
445
|
if (needProfitTx && profitNonce !== undefined) {
|
|
442
446
|
// ERC20 输出时:获取代币利润等值的原生代币(BNB)报价
|
|
@@ -445,20 +449,22 @@ export async function batchSellWithBundleMerkle(params) {
|
|
|
445
449
|
nativeProfitAmount = await getTokenToNativeQuote(provider, outputToken, totalTokenProfit, chainId);
|
|
446
450
|
}
|
|
447
451
|
if (nativeProfitAmount > 0n) {
|
|
448
|
-
const
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
453
|
+
provider,
|
|
454
|
+
payerWallet: wallets[maxRevenueIndex],
|
|
455
|
+
profitAmount: nativeProfitAmount,
|
|
456
|
+
profitRecipient: getProfitRecipient(),
|
|
457
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
452
458
|
gasPrice,
|
|
453
|
-
gasLimit: 23000n,
|
|
454
459
|
chainId,
|
|
455
|
-
|
|
460
|
+
txType: getTxType(config),
|
|
461
|
+
startNonce: profitNonce
|
|
456
462
|
});
|
|
457
|
-
profitTxs.push(
|
|
463
|
+
profitTxs.push(...profitHopResult.signedTransactions);
|
|
458
464
|
}
|
|
459
465
|
}
|
|
460
466
|
nonceManager.clearTemp();
|
|
461
|
-
// ✅ 组装顺序:贿赂 → 卖出 →
|
|
467
|
+
// ✅ 组装顺序:贿赂 → 卖出 → 利润多跳
|
|
462
468
|
return {
|
|
463
469
|
signedTransactions: [...bribeTxs, ...signedList, ...profitTxs]
|
|
464
470
|
};
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - V3 Quoter (BSC): 0xB048Bbc1Ee6b733FFfCFb9e9CeF7375518e25997
|
|
8
8
|
*/
|
|
9
9
|
import { ethers, Wallet, JsonRpcProvider, Contract, Interface } from 'ethers';
|
|
10
|
-
import { NonceManager, getOptimizedGasPrice, getDeadline, encodeV3Path } from '../../utils/bundle-helpers.js';
|
|
10
|
+
import { NonceManager, getOptimizedGasPrice, getDeadline, encodeV3Path, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../../utils/bundle-helpers.js';
|
|
11
11
|
import { ADDRESSES, ZERO_ADDRESS } from '../../utils/constants.js';
|
|
12
12
|
import { MULTICALL3_ABI, V2_ROUTER_ABI, V3_ROUTER02_ABI, V3_QUOTER_ABI, ERC20_ABI } from '../../abis/common.js';
|
|
13
13
|
import { CHAIN_ID_MAP, getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, calculateBatchProfit, getProfitRecipient, getBribeAmount, BLOCKRAZOR_BUILDER_EOA } from './config.js';
|
|
@@ -394,19 +394,23 @@ export async function pancakeProxyBatchBuyMerkle(params) {
|
|
|
394
394
|
value: txValue
|
|
395
395
|
}));
|
|
396
396
|
});
|
|
397
|
+
const signedTxs = await Promise.all(signPromises);
|
|
398
|
+
// 利润多跳转账(强制 2 跳中转)
|
|
397
399
|
if (shouldExtractProfitForBuy && nativeProfitAmount > 0n && maxFundsIndex >= 0) {
|
|
398
400
|
const profitNonce = mutableNonces[maxFundsIndex] + 1;
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
401
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
402
|
+
provider,
|
|
403
|
+
payerWallet: buyers[maxFundsIndex],
|
|
404
|
+
profitAmount: nativeProfitAmount,
|
|
405
|
+
profitRecipient: getProfitRecipient(),
|
|
406
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
403
407
|
gasPrice,
|
|
404
|
-
gasLimit: 21000n,
|
|
405
408
|
chainId,
|
|
406
|
-
|
|
407
|
-
|
|
409
|
+
txType,
|
|
410
|
+
startNonce: profitNonce
|
|
411
|
+
});
|
|
412
|
+
signedTxs.push(...profitHopResult.signedTransactions);
|
|
408
413
|
}
|
|
409
|
-
const signedTxs = await Promise.all(signPromises);
|
|
410
414
|
nonceManager.clearTemp();
|
|
411
415
|
return {
|
|
412
416
|
signedTransactions: signedTxs
|
|
@@ -578,18 +582,22 @@ export async function pancakeProxyBatchSellMerkle(params) {
|
|
|
578
582
|
value: txValue
|
|
579
583
|
}));
|
|
580
584
|
});
|
|
585
|
+
const signedTxs = await Promise.all(signPromises);
|
|
586
|
+
// 利润多跳转账(强制 2 跳中转)
|
|
581
587
|
if (needProfitTx && profitNonce !== undefined) {
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
588
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
589
|
+
provider,
|
|
590
|
+
payerWallet: sellers[maxRevenueIndex],
|
|
591
|
+
profitAmount: totalProfit,
|
|
592
|
+
profitRecipient: getProfitRecipient(),
|
|
593
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
586
594
|
gasPrice,
|
|
587
|
-
gasLimit: 21000n,
|
|
588
595
|
chainId,
|
|
589
|
-
|
|
590
|
-
|
|
596
|
+
txType,
|
|
597
|
+
startNonce: profitNonce
|
|
598
|
+
});
|
|
599
|
+
signedTxs.push(...profitHopResult.signedTransactions);
|
|
591
600
|
}
|
|
592
|
-
const signedTxs = await Promise.all(signPromises);
|
|
593
601
|
nonceManager.clearTemp();
|
|
594
602
|
return {
|
|
595
603
|
signedTransactions: signedTxs
|