four-flap-meme-sdk 1.4.57 → 1.4.59
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/swap.d.ts +3 -0
- package/dist/contracts/tm-bundle-merkle/swap.js +13 -3
- package/dist/flap/portal-bundle-merkle/swap.d.ts +3 -0
- package/dist/flap/portal-bundle-merkle/swap.js +32 -18
- package/dist/pancake/bundle-swap.d.ts +3 -0
- package/dist/pancake/bundle-swap.js +18 -8
- package/dist/utils/bundle-helpers.d.ts +2 -1
- package/dist/utils/bundle-helpers.js +5 -9
- package/dist/utils/holders-maker.d.ts +2 -0
- package/dist/utils/holders-maker.js +15 -2
- package/package.json +1 -1
|
@@ -47,6 +47,7 @@ export interface FourBundleSwapParams {
|
|
|
47
47
|
*/
|
|
48
48
|
export type FourSwapResult = {
|
|
49
49
|
signedTransactions: string[];
|
|
50
|
+
profitHopWallets?: GeneratedWallet[];
|
|
50
51
|
metadata?: {
|
|
51
52
|
sellerAddress: string;
|
|
52
53
|
buyerAddress: string;
|
|
@@ -78,6 +79,7 @@ export interface FourBatchSwapSignParams {
|
|
|
78
79
|
*/
|
|
79
80
|
export interface FourBatchSwapResult {
|
|
80
81
|
signedTransactions: string[];
|
|
82
|
+
profitHopWallets?: GeneratedWallet[];
|
|
81
83
|
metadata?: {
|
|
82
84
|
sellerAddress: string;
|
|
83
85
|
buyerAddresses: string[];
|
|
@@ -115,6 +117,7 @@ export interface FourQuickBatchSwapSignParams {
|
|
|
115
117
|
export interface FourQuickBatchSwapResult {
|
|
116
118
|
signedTransactions: string[];
|
|
117
119
|
disperseHopWallets?: GeneratedWallet[];
|
|
120
|
+
profitHopWallets?: GeneratedWallet[];
|
|
118
121
|
metadata?: {
|
|
119
122
|
sellerAddress: string;
|
|
120
123
|
buyerAddresses: string[];
|
|
@@ -252,6 +252,7 @@ export async function fourBundleSwapMerkle(params) {
|
|
|
252
252
|
allTransactions.push(approvalTx);
|
|
253
253
|
allTransactions.push(signedSell, signedBuy);
|
|
254
254
|
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
255
|
+
let profitHopWallets;
|
|
255
256
|
if (extractProfit && profitAmount > 0n && profitNonce !== undefined) {
|
|
256
257
|
const profitHopResult = await buildProfitHopTransactions({
|
|
257
258
|
provider,
|
|
@@ -265,9 +266,11 @@ export async function fourBundleSwapMerkle(params) {
|
|
|
265
266
|
startNonce: profitNonce
|
|
266
267
|
});
|
|
267
268
|
allTransactions.push(...profitHopResult.signedTransactions);
|
|
269
|
+
profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
|
|
268
270
|
}
|
|
269
271
|
return {
|
|
270
272
|
signedTransactions: allTransactions,
|
|
273
|
+
profitHopWallets, // ✅ 导出利润多跳钱包
|
|
271
274
|
metadata: {
|
|
272
275
|
sellerAddress: seller.address,
|
|
273
276
|
buyerAddress: buyer.address,
|
|
@@ -474,6 +477,7 @@ export async function fourBatchSwapMerkle(params) {
|
|
|
474
477
|
signedTransactions.push(signedSell);
|
|
475
478
|
signedTransactions.push(...signedBuys);
|
|
476
479
|
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
480
|
+
let profitHopWallets;
|
|
477
481
|
if (profitAmount > 0n) {
|
|
478
482
|
const profitHopResult = await buildProfitHopTransactions({
|
|
479
483
|
provider,
|
|
@@ -487,9 +491,11 @@ export async function fourBatchSwapMerkle(params) {
|
|
|
487
491
|
startNonce: profitNonce
|
|
488
492
|
});
|
|
489
493
|
signedTransactions.push(...profitHopResult.signedTransactions);
|
|
494
|
+
profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
|
|
490
495
|
}
|
|
491
496
|
return {
|
|
492
497
|
signedTransactions,
|
|
498
|
+
profitHopWallets, // ✅ 导出利润多跳钱包
|
|
493
499
|
metadata: {
|
|
494
500
|
sellerAddress: seller.address,
|
|
495
501
|
buyerAddresses: buyers.map(b => b.address),
|
|
@@ -669,13 +675,14 @@ export async function fourQuickBatchSwapMerkle(params) {
|
|
|
669
675
|
}
|
|
670
676
|
else {
|
|
671
677
|
// ✅ 有多跳:构建多跳转账链
|
|
678
|
+
// ✅ 修复:payer 每次只发送 1 笔交易(到第一个hop钱包),hop钱包用自己的nonce=0
|
|
672
679
|
const hopChains = await Promise.all(hopPaths.map((path, i) => {
|
|
673
680
|
const finalAmount = transferAmountsWei[i] + reserveGas + buyerGasCost;
|
|
674
|
-
const payerNonce = sellerNonce + i
|
|
681
|
+
const payerNonce = sellerNonce + i; // ✅ payer 每个 buyer 只用 1 个 nonce
|
|
675
682
|
return buildNativeHopChain(seller, path, finalAmount, gasPrice, chainIdNum, txType, payerNonce);
|
|
676
683
|
}));
|
|
677
684
|
transferTxs = hopChains.flat();
|
|
678
|
-
sellerNonce += buyers.length
|
|
685
|
+
sellerNonce += buyers.length; // ✅ payer 只增加 buyers.length 个 nonce
|
|
679
686
|
}
|
|
680
687
|
console.log(`[fourQuickBatchSwapMerkle] ${transferTxs.length} 笔转账交易已签名 (多跳数=${disperseHopCount})`);
|
|
681
688
|
// ==================== 4. 买入交易 ====================
|
|
@@ -708,6 +715,7 @@ export async function fourQuickBatchSwapMerkle(params) {
|
|
|
708
715
|
signedTransactions.push(...transferTxs);
|
|
709
716
|
signedTransactions.push(...signedBuys);
|
|
710
717
|
// ==================== 5. 利润多跳转账(强制 2 跳中转)====================
|
|
718
|
+
let profitHopWallets;
|
|
711
719
|
if (profitAmount > 0n) {
|
|
712
720
|
const profitHopResult = await buildProfitHopTransactions({
|
|
713
721
|
provider,
|
|
@@ -721,6 +729,7 @@ export async function fourQuickBatchSwapMerkle(params) {
|
|
|
721
729
|
startNonce: sellerNonce++
|
|
722
730
|
});
|
|
723
731
|
signedTransactions.push(...profitHopResult.signedTransactions);
|
|
732
|
+
profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
|
|
724
733
|
console.log(`[fourQuickBatchSwapMerkle] 利润多跳交易已签名: ${profitHopResult.signedTransactions.length} 笔`);
|
|
725
734
|
}
|
|
726
735
|
console.log(`[fourQuickBatchSwapMerkle] 交易组装完成: ${signedTransactions.length} 笔`);
|
|
@@ -731,7 +740,8 @@ export async function fourQuickBatchSwapMerkle(params) {
|
|
|
731
740
|
console.log(` - 利润多跳: ${profitAmount > 0n ? PROFIT_HOP_COUNT + 1 : 0}`);
|
|
732
741
|
return {
|
|
733
742
|
signedTransactions,
|
|
734
|
-
disperseHopWallets: allHopWallets.length > 0 ? allHopWallets : undefined, // ✅
|
|
743
|
+
disperseHopWallets: allHopWallets.length > 0 ? allHopWallets : undefined, // ✅ 返回转账多跳钱包
|
|
744
|
+
profitHopWallets, // ✅ 返回利润多跳钱包
|
|
735
745
|
metadata: {
|
|
736
746
|
sellerAddress: seller.address,
|
|
737
747
|
buyerAddresses: buyers.map(b => b.address),
|
|
@@ -53,6 +53,7 @@ export interface FlapBundleSwapParams {
|
|
|
53
53
|
/** ✅ Flap Swap 结果(简化版) */
|
|
54
54
|
export type FlapSwapResult = {
|
|
55
55
|
signedTransactions: string[];
|
|
56
|
+
profitHopWallets?: GeneratedWallet[];
|
|
56
57
|
metadata?: {
|
|
57
58
|
sellerAddress: string;
|
|
58
59
|
buyerAddress: string;
|
|
@@ -88,6 +89,7 @@ export interface FlapBatchSwapSignParams {
|
|
|
88
89
|
*/
|
|
89
90
|
export interface FlapBatchSwapResult {
|
|
90
91
|
signedTransactions: string[];
|
|
92
|
+
profitHopWallets?: GeneratedWallet[];
|
|
91
93
|
metadata?: {
|
|
92
94
|
sellerAddress: string;
|
|
93
95
|
buyerAddresses: string[];
|
|
@@ -128,6 +130,7 @@ export interface FlapQuickBatchSwapSignParams {
|
|
|
128
130
|
export interface FlapQuickBatchSwapResult {
|
|
129
131
|
signedTransactions: string[];
|
|
130
132
|
disperseHopWallets?: GeneratedWallet[];
|
|
133
|
+
profitHopWallets?: GeneratedWallet[];
|
|
131
134
|
metadata?: {
|
|
132
135
|
sellerAddress: string;
|
|
133
136
|
buyerAddresses: string[];
|
|
@@ -406,7 +406,7 @@ export async function flapBundleSwapMerkle(params) {
|
|
|
406
406
|
allTransactions.push(approvalTx);
|
|
407
407
|
allTransactions.push(signedSell, signedBuy);
|
|
408
408
|
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
409
|
-
const
|
|
409
|
+
const profitResult = await buildProfitTransaction({
|
|
410
410
|
provider: chainContext.provider,
|
|
411
411
|
seller,
|
|
412
412
|
profitAmount: nativeProfitAmount,
|
|
@@ -415,10 +415,11 @@ export async function flapBundleSwapMerkle(params) {
|
|
|
415
415
|
chainId: chainContext.chainId,
|
|
416
416
|
txType
|
|
417
417
|
});
|
|
418
|
-
if (
|
|
419
|
-
allTransactions.push(...
|
|
418
|
+
if (profitResult)
|
|
419
|
+
allTransactions.push(...profitResult.signedTransactions);
|
|
420
420
|
return {
|
|
421
421
|
signedTransactions: allTransactions,
|
|
422
|
+
profitHopWallets: profitResult?.hopWallets, // ✅ 导出利润多跳钱包
|
|
422
423
|
metadata: {
|
|
423
424
|
sellerAddress: seller.address,
|
|
424
425
|
buyerAddress: buyer.address,
|
|
@@ -636,7 +637,10 @@ async function buildProfitTransaction({ provider, seller, profitAmount, profitNo
|
|
|
636
637
|
txType,
|
|
637
638
|
startNonce: profitNonce
|
|
638
639
|
});
|
|
639
|
-
return
|
|
640
|
+
return {
|
|
641
|
+
signedTransactions: profitHopResult.signedTransactions,
|
|
642
|
+
hopWallets: profitHopResult.hopWallets
|
|
643
|
+
};
|
|
640
644
|
}
|
|
641
645
|
function calculateProfitAmount(quotedNative) {
|
|
642
646
|
if (quotedNative <= 0n) {
|
|
@@ -834,8 +838,9 @@ export async function flapBatchSwapMerkle(params) {
|
|
|
834
838
|
signedTransactions.push(signedSell);
|
|
835
839
|
signedTransactions.push(...signedBuys);
|
|
836
840
|
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
841
|
+
let profitHopWallets;
|
|
837
842
|
if (profitNonce !== undefined && nativeProfitAmount > 0n) {
|
|
838
|
-
const
|
|
843
|
+
const profitResult = await buildProfitTransaction({
|
|
839
844
|
provider: chainContext.provider,
|
|
840
845
|
seller,
|
|
841
846
|
profitAmount: nativeProfitAmount,
|
|
@@ -844,11 +849,14 @@ export async function flapBatchSwapMerkle(params) {
|
|
|
844
849
|
chainId: chainContext.chainId,
|
|
845
850
|
txType
|
|
846
851
|
});
|
|
847
|
-
if (
|
|
848
|
-
signedTransactions.push(...
|
|
852
|
+
if (profitResult) {
|
|
853
|
+
signedTransactions.push(...profitResult.signedTransactions);
|
|
854
|
+
profitHopWallets = profitResult.hopWallets; // ✅ 收集利润多跳钱包
|
|
855
|
+
}
|
|
849
856
|
}
|
|
850
857
|
return {
|
|
851
858
|
signedTransactions,
|
|
859
|
+
profitHopWallets, // ✅ 导出利润多跳钱包
|
|
852
860
|
metadata: {
|
|
853
861
|
sellerAddress: seller.address,
|
|
854
862
|
buyerAddresses: buyers.map(b => b.address),
|
|
@@ -1091,31 +1099,33 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
1091
1099
|
// ✅ 有多跳:构建多跳转账链
|
|
1092
1100
|
if (useNativeToken) {
|
|
1093
1101
|
// 原生代币多跳转账
|
|
1102
|
+
// ✅ 修复:payer 每次只发送 1 笔交易(到第一个hop钱包),hop钱包用自己的nonce=0
|
|
1094
1103
|
const hopChains = await Promise.all(hopPaths.map((path, i) => {
|
|
1095
1104
|
const finalAmount = transferAmountsWei[i] + reserveGas + buyerGasCost;
|
|
1096
|
-
const payerNonce = sellerNonce + i
|
|
1105
|
+
const payerNonce = sellerNonce + i; // ✅ payer 每个 buyer 只用 1 个 nonce
|
|
1097
1106
|
return buildNativeHopChain(seller, path, finalAmount, gasPrice, chainContext.chainId, txType, payerNonce);
|
|
1098
1107
|
}));
|
|
1099
1108
|
transferTxs = hopChains.flat();
|
|
1100
|
-
sellerNonce += buyers.length
|
|
1109
|
+
sellerNonce += buyers.length; // ✅ payer 只增加 buyers.length 个 nonce
|
|
1101
1110
|
}
|
|
1102
1111
|
else {
|
|
1103
1112
|
// ERC20 多跳转账:先转 BNB(给中间钱包 gas),再转 ERC20
|
|
1113
|
+
// ✅ 修复:payer 每次只发送 1 笔交易(到第一个hop钱包),hop钱包用自己的nonce=0/1
|
|
1104
1114
|
// 1. 构建 BNB 多跳链
|
|
1105
1115
|
const bnbHopChains = await Promise.all(hopPaths.map((path, i) => {
|
|
1106
1116
|
const finalGasAmount = buyerGasCost;
|
|
1107
|
-
const payerNonce = sellerNonce + i
|
|
1117
|
+
const payerNonce = sellerNonce + i; // ✅ payer 每个 buyer 只用 1 个 nonce
|
|
1108
1118
|
return buildBNBHopChainForERC20(seller, path, finalGasAmount, gasPrice, chainContext.chainId, txType, payerNonce);
|
|
1109
1119
|
}));
|
|
1110
1120
|
const bnbTxs = bnbHopChains.flat();
|
|
1111
|
-
sellerNonce += buyers.length
|
|
1121
|
+
sellerNonce += buyers.length; // ✅ payer 只增加 buyers.length 个 nonce
|
|
1112
1122
|
// 2. 构建 ERC20 多跳链
|
|
1113
1123
|
const erc20HopChains = await Promise.all(hopPaths.map((path, i) => {
|
|
1114
|
-
const payerNonce = sellerNonce + i
|
|
1124
|
+
const payerNonce = sellerNonce + i; // ✅ payer 每个 buyer 只用 1 个 nonce
|
|
1115
1125
|
return buildERC20HopChain(seller, path, quoteToken, transferAmountsWei[i], gasPrice, chainContext.chainId, txType, payerNonce);
|
|
1116
1126
|
}));
|
|
1117
1127
|
const erc20Txs = erc20HopChains.flat();
|
|
1118
|
-
sellerNonce += buyers.length
|
|
1128
|
+
sellerNonce += buyers.length; // ✅ payer 只增加 buyers.length 个 nonce
|
|
1119
1129
|
transferTxs = [...bnbTxs, ...erc20Txs];
|
|
1120
1130
|
}
|
|
1121
1131
|
}
|
|
@@ -1157,8 +1167,9 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
1157
1167
|
signedTransactions.push(...transferTxs);
|
|
1158
1168
|
signedTransactions.push(...signedBuys);
|
|
1159
1169
|
// ==================== 5. 利润多跳转账(强制 2 跳中转)====================
|
|
1170
|
+
let profitHopWallets;
|
|
1160
1171
|
if (nativeProfitAmount > 0n) {
|
|
1161
|
-
const
|
|
1172
|
+
const profitResult = await buildProfitTransaction({
|
|
1162
1173
|
provider: chainContext.provider,
|
|
1163
1174
|
seller,
|
|
1164
1175
|
profitAmount: nativeProfitAmount,
|
|
@@ -1167,9 +1178,11 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
1167
1178
|
chainId: chainContext.chainId,
|
|
1168
1179
|
txType
|
|
1169
1180
|
});
|
|
1170
|
-
if (
|
|
1171
|
-
signedTransactions.push(...
|
|
1172
|
-
|
|
1181
|
+
if (profitResult) {
|
|
1182
|
+
signedTransactions.push(...profitResult.signedTransactions);
|
|
1183
|
+
profitHopWallets = profitResult.hopWallets; // ✅ 收集利润多跳钱包
|
|
1184
|
+
}
|
|
1185
|
+
console.log(`[flapQuickBatchSwapMerkle] 利润多跳交易已签名: ${profitResult?.signedTransactions.length || 0} 笔`);
|
|
1173
1186
|
}
|
|
1174
1187
|
console.log(`[flapQuickBatchSwapMerkle] 交易组装完成: ${signedTransactions.length} 笔`);
|
|
1175
1188
|
console.log(` - 贿赂: ${bribeTx ? 1 : 0}`);
|
|
@@ -1179,7 +1192,8 @@ export async function flapQuickBatchSwapMerkle(params) {
|
|
|
1179
1192
|
console.log(` - 利润多跳: ${nativeProfitAmount > 0n ? PROFIT_HOP_COUNT + 1 : 0}`);
|
|
1180
1193
|
return {
|
|
1181
1194
|
signedTransactions,
|
|
1182
|
-
disperseHopWallets: allHopWallets.length > 0 ? allHopWallets : undefined, // ✅
|
|
1195
|
+
disperseHopWallets: allHopWallets.length > 0 ? allHopWallets : undefined, // ✅ 返回转账多跳钱包
|
|
1196
|
+
profitHopWallets, // ✅ 返回利润多跳钱包
|
|
1183
1197
|
metadata: {
|
|
1184
1198
|
sellerAddress: seller.address,
|
|
1185
1199
|
buyerAddresses: buyers.map(b => b.address),
|
|
@@ -62,6 +62,7 @@ export interface PancakeBundleSwapParams {
|
|
|
62
62
|
/** ✅ Pancake Swap 结果(简化版) */
|
|
63
63
|
export type PancakeSwapResult = {
|
|
64
64
|
signedTransactions: string[];
|
|
65
|
+
profitHopWallets?: GeneratedWallet[];
|
|
65
66
|
metadata?: {
|
|
66
67
|
sellerAddress: string;
|
|
67
68
|
buyerAddress: string;
|
|
@@ -97,6 +98,7 @@ export interface PancakeBatchSwapSignParams {
|
|
|
97
98
|
*/
|
|
98
99
|
export interface PancakeBatchSwapResult {
|
|
99
100
|
signedTransactions: string[];
|
|
101
|
+
profitHopWallets?: GeneratedWallet[];
|
|
100
102
|
metadata?: {
|
|
101
103
|
sellerAddress: string;
|
|
102
104
|
buyerAddresses: string[];
|
|
@@ -139,6 +141,7 @@ export interface PancakeQuickBatchSwapParams {
|
|
|
139
141
|
export interface PancakeQuickBatchSwapResult {
|
|
140
142
|
signedTransactions: string[];
|
|
141
143
|
disperseHopWallets?: GeneratedWallet[];
|
|
144
|
+
profitHopWallets?: GeneratedWallet[];
|
|
142
145
|
metadata?: {
|
|
143
146
|
sellerAddress: string;
|
|
144
147
|
buyerAddresses: string[];
|
|
@@ -709,6 +709,7 @@ export async function pancakeBundleSwapMerkle(params) {
|
|
|
709
709
|
signedTransactions.push(bribeTx);
|
|
710
710
|
signedTransactions.push(signedSell, signedBuy);
|
|
711
711
|
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
712
|
+
let profitHopWallets;
|
|
712
713
|
if (profitAmount > 0n && noncePlan.profitNonce !== undefined) {
|
|
713
714
|
const profitHopResult = await buildProfitHopTransactions({
|
|
714
715
|
provider: context.provider,
|
|
@@ -722,9 +723,11 @@ export async function pancakeBundleSwapMerkle(params) {
|
|
|
722
723
|
startNonce: noncePlan.profitNonce
|
|
723
724
|
});
|
|
724
725
|
signedTransactions.push(...profitHopResult.signedTransactions);
|
|
726
|
+
profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
|
|
725
727
|
}
|
|
726
728
|
return {
|
|
727
729
|
signedTransactions,
|
|
730
|
+
profitHopWallets, // ✅ 导出利润多跳钱包
|
|
728
731
|
metadata: {
|
|
729
732
|
sellerAddress: seller.address,
|
|
730
733
|
buyerAddress: buyer.address,
|
|
@@ -985,6 +988,7 @@ export async function pancakeBatchSwapMerkle(params) {
|
|
|
985
988
|
signedTransactions.push(signedSell); // 卖出
|
|
986
989
|
signedTransactions.push(...signedBuys); // 多个买入
|
|
987
990
|
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
991
|
+
let profitHopWallets;
|
|
988
992
|
if (profitAmount > 0n && profitNonce !== undefined) {
|
|
989
993
|
const profitHopResult = await buildProfitHopTransactions({
|
|
990
994
|
provider: context.provider,
|
|
@@ -998,9 +1002,11 @@ export async function pancakeBatchSwapMerkle(params) {
|
|
|
998
1002
|
startNonce: profitNonce
|
|
999
1003
|
});
|
|
1000
1004
|
signedTransactions.push(...profitHopResult.signedTransactions);
|
|
1005
|
+
profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
|
|
1001
1006
|
}
|
|
1002
1007
|
return {
|
|
1003
1008
|
signedTransactions,
|
|
1009
|
+
profitHopWallets, // ✅ 导出利润多跳钱包
|
|
1004
1010
|
metadata: {
|
|
1005
1011
|
sellerAddress: seller.address,
|
|
1006
1012
|
buyerAddresses: buyers.map(b => b.address),
|
|
@@ -1316,33 +1322,34 @@ export async function pancakeQuickBatchSwapMerkle(params) {
|
|
|
1316
1322
|
// ✅ 有多跳:构建多跳转账链
|
|
1317
1323
|
if (useNativeToken) {
|
|
1318
1324
|
// BNB 多跳转账
|
|
1325
|
+
// ✅ 修复:payer 每次只发送 1 笔交易(到第一个hop钱包),hop钱包用自己的nonce=0
|
|
1319
1326
|
const hopChains = await Promise.all(hopPaths.map((path, i) => {
|
|
1320
1327
|
const finalAmount = transferAmountsWei[i] + FLAT_FEE + buyerGasCost;
|
|
1321
|
-
const payerNonce = sellerNonce + i
|
|
1328
|
+
const payerNonce = sellerNonce + i; // ✅ payer 每个 buyer 只用 1 个 nonce
|
|
1322
1329
|
return buildNativeHopChain(seller, path, finalAmount, gasPrice, context.chainId, txType, payerNonce);
|
|
1323
1330
|
}));
|
|
1324
1331
|
transferTxs = hopChains.flat();
|
|
1325
|
-
sellerNonce += buyers.length
|
|
1332
|
+
sellerNonce += buyers.length; // ✅ payer 只增加 buyers.length 个 nonce
|
|
1326
1333
|
}
|
|
1327
1334
|
else {
|
|
1328
1335
|
// ERC20 多跳转账:先转 BNB(给中间钱包 gas),再转 ERC20
|
|
1329
|
-
//
|
|
1336
|
+
// ✅ 修复:payer 每次只发送 1 笔交易(到第一个hop钱包),hop钱包用自己的nonce=0/1
|
|
1330
1337
|
// 1. 构建 BNB 多跳链(为中间钱包和最终钱包预留 gas)
|
|
1331
1338
|
const bnbHopChains = await Promise.all(hopPaths.map((path, i) => {
|
|
1332
1339
|
// 最终钱包需要的 gas(用于买入交易)
|
|
1333
1340
|
const finalGasAmount = buyerGasCost;
|
|
1334
|
-
const payerNonce = sellerNonce + i
|
|
1341
|
+
const payerNonce = sellerNonce + i; // ✅ payer 每个 buyer 只用 1 个 nonce
|
|
1335
1342
|
return buildBNBHopChainForERC20(seller, path, finalGasAmount, gasPrice, context.chainId, txType, payerNonce);
|
|
1336
1343
|
}));
|
|
1337
1344
|
const bnbTxs = bnbHopChains.flat();
|
|
1338
|
-
sellerNonce += buyers.length
|
|
1345
|
+
sellerNonce += buyers.length; // ✅ payer 只增加 buyers.length 个 nonce
|
|
1339
1346
|
// 2. 构建 ERC20 多跳链
|
|
1340
1347
|
const erc20HopChains = await Promise.all(hopPaths.map((path, i) => {
|
|
1341
|
-
const payerNonce = sellerNonce + i
|
|
1348
|
+
const payerNonce = sellerNonce + i; // ✅ payer 每个 buyer 只用 1 个 nonce
|
|
1342
1349
|
return buildERC20HopChain(seller, path, quoteToken, transferAmountsWei[i], gasPrice, context.chainId, txType, payerNonce);
|
|
1343
1350
|
}));
|
|
1344
1351
|
const erc20Txs = erc20HopChains.flat();
|
|
1345
|
-
sellerNonce += buyers.length
|
|
1352
|
+
sellerNonce += buyers.length; // ✅ payer 只增加 buyers.length 个 nonce
|
|
1346
1353
|
transferTxs = [...bnbTxs, ...erc20Txs];
|
|
1347
1354
|
}
|
|
1348
1355
|
}
|
|
@@ -1409,6 +1416,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
|
|
|
1409
1416
|
signedTransactions.push(...transferTxs);
|
|
1410
1417
|
signedTransactions.push(...signedBuys);
|
|
1411
1418
|
// ==================== 5. 利润多跳转账(强制 2 跳中转)====================
|
|
1419
|
+
let profitHopWallets;
|
|
1412
1420
|
if (profitAmount > 0n) {
|
|
1413
1421
|
const profitHopResult = await buildProfitHopTransactions({
|
|
1414
1422
|
provider: context.provider,
|
|
@@ -1422,6 +1430,7 @@ export async function pancakeQuickBatchSwapMerkle(params) {
|
|
|
1422
1430
|
startNonce: sellerNonce++
|
|
1423
1431
|
});
|
|
1424
1432
|
signedTransactions.push(...profitHopResult.signedTransactions);
|
|
1433
|
+
profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
|
|
1425
1434
|
console.log(`[pancakeQuickBatchSwapMerkle] 利润多跳交易已签名: ${profitHopResult.signedTransactions.length} 笔`);
|
|
1426
1435
|
}
|
|
1427
1436
|
console.log(`[pancakeQuickBatchSwapMerkle] 交易组装完成: ${signedTransactions.length} 笔`);
|
|
@@ -1433,7 +1442,8 @@ export async function pancakeQuickBatchSwapMerkle(params) {
|
|
|
1433
1442
|
const outputUnit = useNativeToken ? 'BNB' : 'ERC20';
|
|
1434
1443
|
return {
|
|
1435
1444
|
signedTransactions,
|
|
1436
|
-
disperseHopWallets: allHopWallets.length > 0 ? allHopWallets : undefined, // ✅
|
|
1445
|
+
disperseHopWallets: allHopWallets.length > 0 ? allHopWallets : undefined, // ✅ 返回转账多跳钱包
|
|
1446
|
+
profitHopWallets, // ✅ 返回利润多跳钱包
|
|
1437
1447
|
metadata: {
|
|
1438
1448
|
sellerAddress: seller.address,
|
|
1439
1449
|
buyerAddresses: buyers.map(b => b.address),
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* 提供可复用的 nonce 管理、gas 估算等功能
|
|
4
4
|
*/
|
|
5
5
|
import { JsonRpcProvider, Wallet } from 'ethers';
|
|
6
|
+
import { type GeneratedWallet } from './wallet.js';
|
|
6
7
|
/**
|
|
7
8
|
* Nonce 管理器
|
|
8
9
|
* 用于在 bundle 交易中管理多个钱包的 nonce
|
|
@@ -207,7 +208,7 @@ export interface ProfitHopConfig {
|
|
|
207
208
|
*/
|
|
208
209
|
export interface ProfitHopResult {
|
|
209
210
|
signedTransactions: string[];
|
|
210
|
-
hopWallets:
|
|
211
|
+
hopWallets: GeneratedWallet[];
|
|
211
212
|
totalNonceUsed: number;
|
|
212
213
|
}
|
|
213
214
|
/**
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* 提供可复用的 nonce 管理、gas 估算等功能
|
|
4
4
|
*/
|
|
5
5
|
import { ethers, Wallet } from 'ethers';
|
|
6
|
+
import { generateWallets } from './wallet.js';
|
|
6
7
|
/**
|
|
7
8
|
* Nonce 管理器
|
|
8
9
|
* 用于在 bundle 交易中管理多个钱包的 nonce
|
|
@@ -389,14 +390,9 @@ export async function buildProfitHopTransactions(config) {
|
|
|
389
390
|
// 固定 gas limit(原生代币转账,预留少量缓冲)
|
|
390
391
|
const nativeTransferGasLimit = 21055n;
|
|
391
392
|
const gasFeePerHop = nativeTransferGasLimit * gasPrice;
|
|
392
|
-
//
|
|
393
|
-
const
|
|
394
|
-
const
|
|
395
|
-
for (let i = 0; i < hopCount; i++) {
|
|
396
|
-
const wallet = Wallet.createRandom();
|
|
397
|
-
hopWallets.push(new Wallet(wallet.privateKey, provider));
|
|
398
|
-
hopPrivateKeys.push(wallet.privateKey);
|
|
399
|
-
}
|
|
393
|
+
// ✅ 生成中转钱包(使用统一的 generateWallets 函数)
|
|
394
|
+
const hopWalletsInfo = generateWallets(hopCount);
|
|
395
|
+
const hopWallets = hopWalletsInfo.map(w => new Wallet(w.privateKey, provider));
|
|
400
396
|
// 计算每个中转钱包需要的金额(从后往前)
|
|
401
397
|
// 最后一个中转钱包:只需要利润 + 自己的 gas
|
|
402
398
|
// 其他中转钱包:利润 + 自己的 gas + 下一个钱包需要的金额
|
|
@@ -445,7 +441,7 @@ export async function buildProfitHopTransactions(config) {
|
|
|
445
441
|
}
|
|
446
442
|
return {
|
|
447
443
|
signedTransactions: signedTxs,
|
|
448
|
-
hopWallets:
|
|
444
|
+
hopWallets: hopWalletsInfo, // ✅ 返回完整的钱包信息(privateKey + address)
|
|
449
445
|
totalNonceUsed: 1 // 支付者只用了 1 个 nonce
|
|
450
446
|
};
|
|
451
447
|
}
|
|
@@ -83,6 +83,8 @@ export type HoldersMakerResult = {
|
|
|
83
83
|
newWallets: GeneratedWallet[];
|
|
84
84
|
/** 分发多跳中间钱包(可选,用于导出) */
|
|
85
85
|
disperseHopWallets?: GeneratedWallet[];
|
|
86
|
+
/** 利润多跳中间钱包(可选,用于导出) */
|
|
87
|
+
profitHopWallets?: GeneratedWallet[];
|
|
86
88
|
/** 签名交易(每批一个数组) */
|
|
87
89
|
signedTransactions: string[][];
|
|
88
90
|
/** 批次结果 */
|
|
@@ -551,7 +551,8 @@ export async function holdersMaker(params) {
|
|
|
551
551
|
const result = {
|
|
552
552
|
success: false,
|
|
553
553
|
newWallets: [],
|
|
554
|
-
disperseHopWallets: [], // ✅
|
|
554
|
+
disperseHopWallets: [], // ✅ 分发多跳中间钱包
|
|
555
|
+
profitHopWallets: [], // ✅ 利润多跳中间钱包
|
|
555
556
|
signedTransactions: [],
|
|
556
557
|
batchResults: [],
|
|
557
558
|
successBatchCount: 0,
|
|
@@ -723,6 +724,7 @@ export async function holdersMaker(params) {
|
|
|
723
724
|
signedTxs.push(buyTx);
|
|
724
725
|
}
|
|
725
726
|
// (6) 利润多跳
|
|
727
|
+
let profitHopWallets;
|
|
726
728
|
if (profitPerBatch > 0n) {
|
|
727
729
|
const profitHopResult = await buildProfitHopTransactions({
|
|
728
730
|
provider,
|
|
@@ -736,12 +738,14 @@ export async function holdersMaker(params) {
|
|
|
736
738
|
startNonce: payerNonces[payerNonceIdx]
|
|
737
739
|
});
|
|
738
740
|
signedTxs.push(...profitHopResult.signedTransactions);
|
|
741
|
+
profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
|
|
739
742
|
}
|
|
740
743
|
return {
|
|
741
744
|
batchIndex: batchIdx,
|
|
742
745
|
success: true,
|
|
743
746
|
signedTransactions: signedTxs,
|
|
744
|
-
walletCount: batch.length
|
|
747
|
+
walletCount: batch.length,
|
|
748
|
+
profitHopWallets // ✅ 返回利润多跳钱包
|
|
745
749
|
};
|
|
746
750
|
}
|
|
747
751
|
catch (error) {
|
|
@@ -755,10 +759,15 @@ export async function holdersMaker(params) {
|
|
|
755
759
|
});
|
|
756
760
|
const batchResults = await Promise.all(batchPromises);
|
|
757
761
|
// 7. 处理结果
|
|
762
|
+
const allProfitHopWallets = [];
|
|
758
763
|
for (const res of batchResults) {
|
|
759
764
|
if (res.success && res.signedTransactions) {
|
|
760
765
|
result.signedTransactions.push(res.signedTransactions);
|
|
761
766
|
result.successBatchCount++;
|
|
767
|
+
// ✅ 收集利润多跳钱包
|
|
768
|
+
if (res.profitHopWallets) {
|
|
769
|
+
allProfitHopWallets.push(...res.profitHopWallets);
|
|
770
|
+
}
|
|
762
771
|
}
|
|
763
772
|
result.batchResults.push({
|
|
764
773
|
batchIndex: res.batchIndex,
|
|
@@ -768,6 +777,10 @@ export async function holdersMaker(params) {
|
|
|
768
777
|
walletCount: res.walletCount
|
|
769
778
|
});
|
|
770
779
|
}
|
|
780
|
+
// ✅ 添加利润多跳钱包到结果
|
|
781
|
+
if (allProfitHopWallets.length > 0) {
|
|
782
|
+
result.profitHopWallets = allProfitHopWallets;
|
|
783
|
+
}
|
|
771
784
|
result.success = result.successBatchCount > 0;
|
|
772
785
|
console.log(`[HoldersMaker] 完成: ${result.successBatchCount}/${result.totalBatchCount} 批成功`);
|
|
773
786
|
}
|