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
package/dist/index.js
CHANGED
|
@@ -53,6 +53,8 @@ export { generateWallets } from './utils/wallet.js';
|
|
|
53
53
|
export { getTokenBalancesWithMulticall } from './utils/wallet.js';
|
|
54
54
|
export { validatePrivateKeys } from './utils/wallet.js';
|
|
55
55
|
export { stealthTransfer } from './utils/stealth-transfer.js';
|
|
56
|
+
// ✅ 刷持有人(一键完成:生成钱包 → 分发资金 → 批量买入)
|
|
57
|
+
export { holdersMaker, estimateHoldersMakerCost, } from './utils/holders-maker.js';
|
|
56
58
|
// ✅ 私募转账签名(带贿赂和利润提取)
|
|
57
59
|
export { privateSaleMerkle, batchPrivateSaleMerkle, } from './utils/private-sale.js';
|
|
58
60
|
export { inspectTokenLP, getFactoryFromRouter, registerDYORSwap, registerDex, getChainConfig, } from './utils/lp-inspect.js';
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* 功能:钱包B先买入代币 → 钱包A卖出相同数量 → 原子执行
|
|
5
5
|
*/
|
|
6
6
|
import { ethers, Contract, Wallet } from 'ethers';
|
|
7
|
-
import { NonceManager, getDeadline } from '../utils/bundle-helpers.js';
|
|
7
|
+
import { NonceManager, getDeadline, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../utils/bundle-helpers.js';
|
|
8
8
|
import { ADDRESSES, PROFIT_CONFIG, BLOCKRAZOR_BUILDER_EOA, ZERO_ADDRESS } from '../utils/constants.js';
|
|
9
9
|
import { quoteV2, quoteV3, getTokenToNativeQuote, getWrappedNativeAddress } from '../utils/quote-helpers.js';
|
|
10
10
|
import { V2_ROUTER_ABI, V3_ROUTER02_ABI, ERC20_BALANCE_ABI } from '../abis/common.js';
|
|
@@ -149,15 +149,6 @@ export async function pancakeBundleBuyFirstMerkle(params) {
|
|
|
149
149
|
chainId: context.chainId,
|
|
150
150
|
type: txType
|
|
151
151
|
});
|
|
152
|
-
// ✅ 利润交易放在末尾
|
|
153
|
-
const profitTx = await buildProfitTransaction({
|
|
154
|
-
seller,
|
|
155
|
-
profitAmount,
|
|
156
|
-
profitNonce: noncePlan.profitNonce,
|
|
157
|
-
gasPrice,
|
|
158
|
-
chainId: context.chainId,
|
|
159
|
-
txType
|
|
160
|
-
});
|
|
161
152
|
nonceManager.clearTemp();
|
|
162
153
|
validateFinalBalances({
|
|
163
154
|
sameAddress,
|
|
@@ -171,13 +162,23 @@ export async function pancakeBundleBuyFirstMerkle(params) {
|
|
|
171
162
|
provider: context.provider,
|
|
172
163
|
buyerAddress: buyer.address
|
|
173
164
|
});
|
|
174
|
-
// ✅ 组装顺序:贿赂 → 买入 → 卖出
|
|
165
|
+
// ✅ 组装顺序:贿赂 → 买入 → 卖出
|
|
175
166
|
const allTransactions = [];
|
|
176
167
|
if (bribeTx)
|
|
177
168
|
allTransactions.push(bribeTx);
|
|
178
169
|
allTransactions.push(signedBuy, signedSell);
|
|
179
|
-
|
|
180
|
-
|
|
170
|
+
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
171
|
+
const profitTxs = await buildProfitTransaction({
|
|
172
|
+
provider: context.provider,
|
|
173
|
+
seller,
|
|
174
|
+
profitAmount,
|
|
175
|
+
profitNonce: noncePlan.profitNonce,
|
|
176
|
+
gasPrice,
|
|
177
|
+
chainId: context.chainId,
|
|
178
|
+
txType
|
|
179
|
+
});
|
|
180
|
+
if (profitTxs)
|
|
181
|
+
allTransactions.push(...profitTxs);
|
|
181
182
|
return {
|
|
182
183
|
signedTransactions: allTransactions,
|
|
183
184
|
metadata: {
|
|
@@ -411,19 +412,25 @@ async function planNonces({ buyer, seller, sameAddress, extractProfit, needBribe
|
|
|
411
412
|
]);
|
|
412
413
|
return { buyerNonce, sellerNonce };
|
|
413
414
|
}
|
|
414
|
-
|
|
415
|
+
/**
|
|
416
|
+
* 构建利润多跳转账交易(强制 2 跳中转)
|
|
417
|
+
*/
|
|
418
|
+
async function buildProfitTransaction({ provider, seller, profitAmount, profitNonce, gasPrice, chainId, txType }) {
|
|
415
419
|
if (profitNonce === undefined || profitAmount === 0n) {
|
|
416
420
|
return null;
|
|
417
421
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
423
|
+
provider,
|
|
424
|
+
payerWallet: seller,
|
|
425
|
+
profitAmount,
|
|
426
|
+
profitRecipient: PROFIT_CONFIG.RECIPIENT,
|
|
427
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
422
428
|
gasPrice,
|
|
423
|
-
gasLimit: 21000n,
|
|
424
429
|
chainId,
|
|
425
|
-
|
|
430
|
+
txType,
|
|
431
|
+
startNonce: profitNonce
|
|
426
432
|
});
|
|
433
|
+
return profitHopResult.signedTransactions;
|
|
427
434
|
}
|
|
428
435
|
async function validateFinalBalances({ sameAddress, buyerFundsWei, buyerBalance, reserveGas, gasLimit, gasPrice, useNativeToken = true, quoteTokenDecimals = 18, provider, buyerAddress }) {
|
|
429
436
|
const gasCost = gasLimit * gasPrice;
|
|
@@ -299,7 +299,7 @@ function countTruthy(values) {
|
|
|
299
299
|
*/
|
|
300
300
|
import { ethers, Contract, Wallet } from 'ethers';
|
|
301
301
|
import { calculateSellAmount } from '../utils/swap-helpers.js';
|
|
302
|
-
import { NonceManager, getDeadline } from '../utils/bundle-helpers.js';
|
|
302
|
+
import { NonceManager, getDeadline, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../utils/bundle-helpers.js';
|
|
303
303
|
import { ADDRESSES, PROFIT_CONFIG, BLOCKRAZOR_BUILDER_EOA } from '../utils/constants.js';
|
|
304
304
|
import { quoteV2, quoteV3 } from '../utils/quote-helpers.js';
|
|
305
305
|
import { V2_ROUTER_ABI, V3_ROUTER02_ABI, ERC20_BALANCE_ABI } from '../abis/common.js';
|
|
@@ -457,25 +457,12 @@ export async function pancakeBundleSwapMerkle(params) {
|
|
|
457
457
|
chainId: context.chainId,
|
|
458
458
|
type: txType
|
|
459
459
|
}).then(tx => ({ type: 'buy', tx })));
|
|
460
|
-
// 利润交易
|
|
461
|
-
if (profitAmount > 0n && noncePlan.profitNonce !== undefined) {
|
|
462
|
-
signPromises.push(seller.signTransaction({
|
|
463
|
-
to: PROFIT_CONFIG.RECIPIENT,
|
|
464
|
-
value: profitAmount,
|
|
465
|
-
nonce: noncePlan.profitNonce,
|
|
466
|
-
gasPrice,
|
|
467
|
-
gasLimit: 21000n,
|
|
468
|
-
chainId: context.chainId,
|
|
469
|
-
type: txType
|
|
470
|
-
}).then(tx => ({ type: 'profit', tx })));
|
|
471
|
-
}
|
|
472
460
|
// ✅ 并行执行所有签名
|
|
473
461
|
const signedResults = await Promise.all(signPromises);
|
|
474
462
|
// 按类型提取结果
|
|
475
463
|
const bribeTx = signedResults.find(r => r.type === 'bribe')?.tx || null;
|
|
476
464
|
const signedSell = signedResults.find(r => r.type === 'sell').tx;
|
|
477
465
|
const signedBuy = signedResults.find(r => r.type === 'buy').tx;
|
|
478
|
-
const profitTx = signedResults.find(r => r.type === 'profit')?.tx || null;
|
|
479
466
|
nonceManager.clearTemp();
|
|
480
467
|
validateFinalBalances({
|
|
481
468
|
sameAddress,
|
|
@@ -489,13 +476,26 @@ export async function pancakeBundleSwapMerkle(params) {
|
|
|
489
476
|
provider: context.provider,
|
|
490
477
|
buyerAddress: buyer.address
|
|
491
478
|
});
|
|
492
|
-
// ✅ 组装顺序:贿赂 → 卖出 → 买入
|
|
479
|
+
// ✅ 组装顺序:贿赂 → 卖出 → 买入
|
|
493
480
|
const signedTransactions = [];
|
|
494
481
|
if (bribeTx)
|
|
495
482
|
signedTransactions.push(bribeTx);
|
|
496
483
|
signedTransactions.push(signedSell, signedBuy);
|
|
497
|
-
|
|
498
|
-
|
|
484
|
+
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
485
|
+
if (profitAmount > 0n && noncePlan.profitNonce !== undefined) {
|
|
486
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
487
|
+
provider: context.provider,
|
|
488
|
+
payerWallet: seller,
|
|
489
|
+
profitAmount,
|
|
490
|
+
profitRecipient: PROFIT_CONFIG.RECIPIENT,
|
|
491
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
492
|
+
gasPrice,
|
|
493
|
+
chainId: context.chainId,
|
|
494
|
+
txType,
|
|
495
|
+
startNonce: noncePlan.profitNonce
|
|
496
|
+
});
|
|
497
|
+
signedTransactions.push(...profitHopResult.signedTransactions);
|
|
498
|
+
}
|
|
499
499
|
return {
|
|
500
500
|
signedTransactions,
|
|
501
501
|
metadata: {
|
|
@@ -720,23 +720,10 @@ export async function pancakeBatchSwapMerkle(params) {
|
|
|
720
720
|
profitAmount = calculateProfitAmount(estimatedBNBValue);
|
|
721
721
|
console.log(`[pancakeBatchSwapMerkle] ERC20→BNB 报价: ${ethers.formatUnits(estimatedBNBOut, quoteTokenDecimals)} → ${ethers.formatEther(estimatedBNBValue)} BNB, 利润: ${ethers.formatEther(profitAmount)} BNB`);
|
|
722
722
|
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
const profitNonce = startNonces && startNonces.length >= 1
|
|
728
|
-
? sellNonce + 1
|
|
729
|
-
: await nonceManager.getNextNonce(seller);
|
|
730
|
-
profitTx = await seller.signTransaction({
|
|
731
|
-
to: PROFIT_CONFIG.RECIPIENT,
|
|
732
|
-
value: profitAmount,
|
|
733
|
-
nonce: profitNonce,
|
|
734
|
-
gasPrice,
|
|
735
|
-
gasLimit: 21000n,
|
|
736
|
-
chainId: context.chainId,
|
|
737
|
-
type: txType
|
|
738
|
-
});
|
|
739
|
-
}
|
|
723
|
+
// 计算利润 nonce
|
|
724
|
+
const profitNonce = profitAmount > 0n
|
|
725
|
+
? (startNonces && startNonces.length >= 1 ? sellNonce + 1 : await nonceManager.getNextNonce(seller))
|
|
726
|
+
: undefined;
|
|
740
727
|
nonceManager.clearTemp();
|
|
741
728
|
// ✅ 并行签名所有交易
|
|
742
729
|
// 1. 签名卖出交易
|
|
@@ -764,14 +751,27 @@ export async function pancakeBatchSwapMerkle(params) {
|
|
|
764
751
|
signedSellPromise,
|
|
765
752
|
...signedBuyPromises
|
|
766
753
|
]);
|
|
767
|
-
// 4. 按顺序组装交易数组:贿赂 → 卖出 → 买入
|
|
754
|
+
// 4. 按顺序组装交易数组:贿赂 → 卖出 → 买入
|
|
768
755
|
const signedTransactions = [];
|
|
769
756
|
if (bribeTx)
|
|
770
757
|
signedTransactions.push(bribeTx); // 贿赂(首位)
|
|
771
758
|
signedTransactions.push(signedSell); // 卖出
|
|
772
759
|
signedTransactions.push(...signedBuys); // 多个买入
|
|
773
|
-
|
|
774
|
-
|
|
760
|
+
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
761
|
+
if (profitAmount > 0n && profitNonce !== undefined) {
|
|
762
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
763
|
+
provider: context.provider,
|
|
764
|
+
payerWallet: seller,
|
|
765
|
+
profitAmount,
|
|
766
|
+
profitRecipient: PROFIT_CONFIG.RECIPIENT,
|
|
767
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
768
|
+
gasPrice,
|
|
769
|
+
chainId: context.chainId,
|
|
770
|
+
txType,
|
|
771
|
+
startNonce: profitNonce
|
|
772
|
+
});
|
|
773
|
+
signedTransactions.push(...profitHopResult.signedTransactions);
|
|
774
|
+
}
|
|
775
775
|
return {
|
|
776
776
|
signedTransactions,
|
|
777
777
|
metadata: {
|
|
@@ -1115,38 +1115,38 @@ export async function pancakeQuickBatchSwapMerkle(params) {
|
|
|
1115
1115
|
});
|
|
1116
1116
|
}));
|
|
1117
1117
|
console.log(`[pancakeQuickBatchSwapMerkle] ${signedBuys.length} 笔买入交易已签名`);
|
|
1118
|
-
// ==================== 5. 利润交易 ====================
|
|
1119
|
-
let profitTx = null;
|
|
1120
|
-
if (profitAmount > 0n) {
|
|
1121
|
-
profitTx = await seller.signTransaction({
|
|
1122
|
-
to: PROFIT_CONFIG.RECIPIENT,
|
|
1123
|
-
value: profitAmount,
|
|
1124
|
-
nonce: sellerNonce++,
|
|
1125
|
-
gasPrice,
|
|
1126
|
-
gasLimit: 21000n,
|
|
1127
|
-
chainId: context.chainId,
|
|
1128
|
-
type: txType
|
|
1129
|
-
});
|
|
1130
|
-
console.log(`[pancakeQuickBatchSwapMerkle] 利润交易已签名`);
|
|
1131
|
-
}
|
|
1132
1118
|
nonceManager.clearTemp();
|
|
1133
1119
|
// ==================== 组装交易数组 ====================
|
|
1134
|
-
// BNB 模式:贿赂 → 卖出 → 转账 → 买入 →
|
|
1135
|
-
// ERC20 模式:贿赂 → 卖出 → ERC20转账 → BNB Gas转账 → 买入 →
|
|
1120
|
+
// BNB 模式:贿赂 → 卖出 → 转账 → 买入 → 利润多跳
|
|
1121
|
+
// ERC20 模式:贿赂 → 卖出 → ERC20转账 → BNB Gas转账 → 买入 → 利润多跳
|
|
1136
1122
|
const signedTransactions = [];
|
|
1137
1123
|
if (bribeTx)
|
|
1138
1124
|
signedTransactions.push(bribeTx);
|
|
1139
1125
|
signedTransactions.push(signedSell);
|
|
1140
1126
|
signedTransactions.push(...transferTxs);
|
|
1141
1127
|
signedTransactions.push(...signedBuys);
|
|
1142
|
-
|
|
1143
|
-
|
|
1128
|
+
// ==================== 5. 利润多跳转账(强制 2 跳中转)====================
|
|
1129
|
+
if (profitAmount > 0n) {
|
|
1130
|
+
const profitHopResult = await buildProfitHopTransactions({
|
|
1131
|
+
provider: context.provider,
|
|
1132
|
+
payerWallet: seller,
|
|
1133
|
+
profitAmount,
|
|
1134
|
+
profitRecipient: PROFIT_CONFIG.RECIPIENT,
|
|
1135
|
+
hopCount: PROFIT_HOP_COUNT,
|
|
1136
|
+
gasPrice,
|
|
1137
|
+
chainId: context.chainId,
|
|
1138
|
+
txType,
|
|
1139
|
+
startNonce: sellerNonce++
|
|
1140
|
+
});
|
|
1141
|
+
signedTransactions.push(...profitHopResult.signedTransactions);
|
|
1142
|
+
console.log(`[pancakeQuickBatchSwapMerkle] 利润多跳交易已签名: ${profitHopResult.signedTransactions.length} 笔`);
|
|
1143
|
+
}
|
|
1144
1144
|
console.log(`[pancakeQuickBatchSwapMerkle] 交易组装完成: ${signedTransactions.length} 笔`);
|
|
1145
1145
|
console.log(` - 贿赂: ${bribeTx ? 1 : 0}`);
|
|
1146
1146
|
console.log(` - 卖出: 1`);
|
|
1147
1147
|
console.log(` - 转账: ${transferTxs.length}`);
|
|
1148
1148
|
console.log(` - 买入: ${signedBuys.length}`);
|
|
1149
|
-
console.log(` -
|
|
1149
|
+
console.log(` - 利润多跳: ${profitAmount > 0n ? PROFIT_HOP_COUNT + 1 : 0}`);
|
|
1150
1150
|
const outputUnit = useNativeToken ? 'BNB' : 'ERC20';
|
|
1151
1151
|
return {
|
|
1152
1152
|
signedTransactions,
|
|
@@ -188,3 +188,41 @@ export declare function decodeV3Path(path: string): {
|
|
|
188
188
|
tokens: string[];
|
|
189
189
|
fees: number[];
|
|
190
190
|
};
|
|
191
|
+
/**
|
|
192
|
+
* 利润多跳转账配置
|
|
193
|
+
*/
|
|
194
|
+
export interface ProfitHopConfig {
|
|
195
|
+
provider: JsonRpcProvider;
|
|
196
|
+
payerWallet: Wallet;
|
|
197
|
+
profitAmount: bigint;
|
|
198
|
+
profitRecipient: string;
|
|
199
|
+
hopCount?: number;
|
|
200
|
+
gasPrice: bigint;
|
|
201
|
+
chainId: number;
|
|
202
|
+
txType: number;
|
|
203
|
+
startNonce?: number;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* 利润多跳结果
|
|
207
|
+
*/
|
|
208
|
+
export interface ProfitHopResult {
|
|
209
|
+
signedTransactions: string[];
|
|
210
|
+
hopWallets: string[];
|
|
211
|
+
totalNonceUsed: number;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* 强制 2 跳的利润转账常量
|
|
215
|
+
*/
|
|
216
|
+
export declare const PROFIT_HOP_COUNT = 2;
|
|
217
|
+
/**
|
|
218
|
+
* 生成利润多跳转账交易
|
|
219
|
+
*
|
|
220
|
+
* 流程(2 跳):
|
|
221
|
+
* 1. 支付者 → 中转1(gas + 利润 + 中转1的gas)
|
|
222
|
+
* 2. 中转1 → 中转2(gas + 利润)
|
|
223
|
+
* 3. 中转2 → 利润地址(利润)
|
|
224
|
+
*
|
|
225
|
+
* @param config 配置参数
|
|
226
|
+
* @returns 签名交易和中转钱包私钥
|
|
227
|
+
*/
|
|
228
|
+
export declare function buildProfitHopTransactions(config: ProfitHopConfig): Promise<ProfitHopResult>;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Bundle 交易辅助工具
|
|
3
3
|
* 提供可复用的 nonce 管理、gas 估算等功能
|
|
4
4
|
*/
|
|
5
|
-
import { ethers } from 'ethers';
|
|
5
|
+
import { ethers, Wallet } from 'ethers';
|
|
6
6
|
/**
|
|
7
7
|
* Nonce 管理器
|
|
8
8
|
* 用于在 bundle 交易中管理多个钱包的 nonce
|
|
@@ -365,3 +365,87 @@ export function decodeV3Path(path) {
|
|
|
365
365
|
}
|
|
366
366
|
return { tokens, fees };
|
|
367
367
|
}
|
|
368
|
+
/**
|
|
369
|
+
* 强制 2 跳的利润转账常量
|
|
370
|
+
*/
|
|
371
|
+
export const PROFIT_HOP_COUNT = 2;
|
|
372
|
+
/**
|
|
373
|
+
* 生成利润多跳转账交易
|
|
374
|
+
*
|
|
375
|
+
* 流程(2 跳):
|
|
376
|
+
* 1. 支付者 → 中转1(gas + 利润 + 中转1的gas)
|
|
377
|
+
* 2. 中转1 → 中转2(gas + 利润)
|
|
378
|
+
* 3. 中转2 → 利润地址(利润)
|
|
379
|
+
*
|
|
380
|
+
* @param config 配置参数
|
|
381
|
+
* @returns 签名交易和中转钱包私钥
|
|
382
|
+
*/
|
|
383
|
+
export async function buildProfitHopTransactions(config) {
|
|
384
|
+
const { provider, payerWallet, profitAmount, profitRecipient, hopCount = PROFIT_HOP_COUNT, gasPrice, chainId, txType, startNonce } = config;
|
|
385
|
+
// 如果利润为 0,返回空结果
|
|
386
|
+
if (profitAmount <= 0n) {
|
|
387
|
+
return { signedTransactions: [], hopWallets: [], totalNonceUsed: 0 };
|
|
388
|
+
}
|
|
389
|
+
// 固定 gas limit(原生代币转账)
|
|
390
|
+
const nativeTransferGasLimit = 21000n;
|
|
391
|
+
const gasFeePerHop = nativeTransferGasLimit * gasPrice;
|
|
392
|
+
// 生成中转钱包
|
|
393
|
+
const hopWallets = [];
|
|
394
|
+
const hopPrivateKeys = [];
|
|
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
|
+
}
|
|
400
|
+
// 计算每个中转钱包需要的金额(从后往前)
|
|
401
|
+
// 最后一个中转钱包:只需要利润 + 自己的 gas
|
|
402
|
+
// 其他中转钱包:利润 + 自己的 gas + 下一个钱包需要的金额
|
|
403
|
+
const hopAmounts = [];
|
|
404
|
+
for (let i = hopCount - 1; i >= 0; i--) {
|
|
405
|
+
if (i === hopCount - 1) {
|
|
406
|
+
// 最后一个中转钱包:利润 + 自己转账的 gas
|
|
407
|
+
hopAmounts.unshift(profitAmount + gasFeePerHop);
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
// 其他中转钱包:下一个需要的金额 + 自己转账的 gas
|
|
411
|
+
hopAmounts.unshift(hopAmounts[0] + gasFeePerHop);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
const signedTxs = [];
|
|
415
|
+
const nonceManager = new NonceManager(provider);
|
|
416
|
+
// 获取支付者的 nonce
|
|
417
|
+
const payerNonce = startNonce ?? await nonceManager.getNextNonce(payerWallet);
|
|
418
|
+
// 1. 支付者 → 第一个中转钱包(包含所有后续的 gas 和利润)
|
|
419
|
+
const payerTx = await payerWallet.signTransaction({
|
|
420
|
+
to: hopWallets[0].address,
|
|
421
|
+
value: hopAmounts[0],
|
|
422
|
+
nonce: payerNonce,
|
|
423
|
+
gasPrice,
|
|
424
|
+
gasLimit: nativeTransferGasLimit,
|
|
425
|
+
chainId,
|
|
426
|
+
type: txType
|
|
427
|
+
});
|
|
428
|
+
signedTxs.push(payerTx);
|
|
429
|
+
// 2. 中转钱包逐层传递
|
|
430
|
+
for (let i = 0; i < hopCount; i++) {
|
|
431
|
+
const fromWallet = hopWallets[i];
|
|
432
|
+
const isLastHop = i === hopCount - 1;
|
|
433
|
+
const toAddress = isLastHop ? profitRecipient : hopWallets[i + 1].address;
|
|
434
|
+
const value = isLastHop ? profitAmount : hopAmounts[i + 1];
|
|
435
|
+
const hopTx = await fromWallet.signTransaction({
|
|
436
|
+
to: toAddress,
|
|
437
|
+
value,
|
|
438
|
+
nonce: 0, // 中转钱包都是新生成的,nonce 从 0 开始
|
|
439
|
+
gasPrice,
|
|
440
|
+
gasLimit: nativeTransferGasLimit,
|
|
441
|
+
chainId,
|
|
442
|
+
type: txType
|
|
443
|
+
});
|
|
444
|
+
signedTxs.push(hopTx);
|
|
445
|
+
}
|
|
446
|
+
return {
|
|
447
|
+
signedTransactions: signedTxs,
|
|
448
|
+
hopWallets: hopPrivateKeys,
|
|
449
|
+
totalNonceUsed: 1 // 支付者只用了 1 个 nonce
|
|
450
|
+
};
|
|
451
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ============================================================================
|
|
3
|
+
* 刷持有人(Holders Maker)
|
|
4
|
+
* ============================================================================
|
|
5
|
+
* 一键完成:生成钱包 → 分发资金 → 批量买入
|
|
6
|
+
* 支持原生代币(BNB/MON)和 ERC20 代币(USDT/USDC)作为购买资金
|
|
7
|
+
*/
|
|
8
|
+
import { type GeneratedWallet } from './wallet.js';
|
|
9
|
+
/** 链类型 */
|
|
10
|
+
export type HoldersMakerChain = 'BSC' | 'MONAD';
|
|
11
|
+
/** 交易类型 */
|
|
12
|
+
export type TradeType = 'four' | 'flap';
|
|
13
|
+
/** 基础代币类型 */
|
|
14
|
+
export type BaseTokenType = 'native' | 'usdt' | 'usdc';
|
|
15
|
+
/** 刷持有人配置 */
|
|
16
|
+
export type HoldersMakerConfig = {
|
|
17
|
+
/** RPC URL */
|
|
18
|
+
rpcUrl: string;
|
|
19
|
+
/** 链类型 */
|
|
20
|
+
chain?: HoldersMakerChain;
|
|
21
|
+
/** 链 ID(可选,不传则自动获取) */
|
|
22
|
+
chainId?: number;
|
|
23
|
+
/** 交易类型(four 或 flap) */
|
|
24
|
+
tradeType?: TradeType;
|
|
25
|
+
/** Gas Limit */
|
|
26
|
+
gasLimit?: number;
|
|
27
|
+
/** Gas Price (Gwei) */
|
|
28
|
+
gasPriceGwei?: number;
|
|
29
|
+
/** 贿赂金额(BNB) */
|
|
30
|
+
bribeAmount?: number;
|
|
31
|
+
/** 交易类型(0 = Legacy, 2 = EIP-1559) */
|
|
32
|
+
txType?: 0 | 2;
|
|
33
|
+
/** 每批最大钱包数 */
|
|
34
|
+
maxWalletsPerBatch?: number;
|
|
35
|
+
/** Four API URL */
|
|
36
|
+
fourApiUrl?: string;
|
|
37
|
+
/** ✅ 多跳数量(0=不多跳,1-10=经过N个中转钱包) */
|
|
38
|
+
hopCount?: number;
|
|
39
|
+
};
|
|
40
|
+
/** 刷持有人参数 */
|
|
41
|
+
export type HoldersMakerParams = {
|
|
42
|
+
/** 支付钱包私钥 */
|
|
43
|
+
payerPrivateKey: string;
|
|
44
|
+
/** 新增持有人数量 */
|
|
45
|
+
holdersCount: number;
|
|
46
|
+
/** 每个地址购买金额(原生代币单位,如 0.0001 BNB) */
|
|
47
|
+
buyAmountPerHolder: string;
|
|
48
|
+
/** 代币合约地址 */
|
|
49
|
+
tokenAddress: string;
|
|
50
|
+
/** 基础代币类型(native=原生代币, usdt, usdc) */
|
|
51
|
+
baseToken?: BaseTokenType;
|
|
52
|
+
/** 基础代币地址(USDT/USDC 时需要) */
|
|
53
|
+
baseTokenAddress?: string;
|
|
54
|
+
/** 基础代币精度(默认 18,USDC 为 6) */
|
|
55
|
+
baseTokenDecimals?: number;
|
|
56
|
+
/** 配置 */
|
|
57
|
+
config: HoldersMakerConfig;
|
|
58
|
+
};
|
|
59
|
+
/** 批次结果 */
|
|
60
|
+
export type BatchResult = {
|
|
61
|
+
batchIndex: number;
|
|
62
|
+
success: boolean;
|
|
63
|
+
phase: 'disperse_native' | 'disperse_erc20' | 'approve' | 'buy';
|
|
64
|
+
signedTransactions?: string[];
|
|
65
|
+
txHashes?: string[];
|
|
66
|
+
error?: string;
|
|
67
|
+
walletCount: number;
|
|
68
|
+
};
|
|
69
|
+
/** 刷持有人结果 */
|
|
70
|
+
export type HoldersMakerResult = {
|
|
71
|
+
/** 是否成功 */
|
|
72
|
+
success: boolean;
|
|
73
|
+
/** 生成的新钱包 */
|
|
74
|
+
newWallets: GeneratedWallet[];
|
|
75
|
+
/** 各阶段签名交易 */
|
|
76
|
+
allSignedTransactions: {
|
|
77
|
+
disperseNative: string[][];
|
|
78
|
+
disperseErc20?: string[][];
|
|
79
|
+
approve?: string[][];
|
|
80
|
+
buy: string[][];
|
|
81
|
+
};
|
|
82
|
+
/** ✅ 多跳钱包私钥(按批次分组,每批次按接收者分组) */
|
|
83
|
+
hopWallets: string[][][];
|
|
84
|
+
/** 批次结果 */
|
|
85
|
+
batchResults: BatchResult[];
|
|
86
|
+
/** 成功的批次数 */
|
|
87
|
+
successBatchCount: number;
|
|
88
|
+
/** 总批次数 */
|
|
89
|
+
totalBatchCount: number;
|
|
90
|
+
/** 错误信息 */
|
|
91
|
+
error?: string;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* 刷持有人(一键完成)
|
|
95
|
+
*
|
|
96
|
+
* 流程:
|
|
97
|
+
* 1. 生成新钱包
|
|
98
|
+
* 2. 分发原生代币(Gas 费 + 购买金额 / 仅 Gas 费)
|
|
99
|
+
* 3. 如果使用 ERC20 基础代币,分发 ERC20 代币
|
|
100
|
+
* 4. 如果使用 ERC20 基础代币,授权
|
|
101
|
+
* 5. 批量买入目标代币
|
|
102
|
+
*
|
|
103
|
+
* @returns 包含所有阶段签名交易的结果,由前端提交
|
|
104
|
+
*/
|
|
105
|
+
export declare function holdersMaker(params: HoldersMakerParams): Promise<HoldersMakerResult>;
|
|
106
|
+
/**
|
|
107
|
+
* 获取刷持有人预估费用
|
|
108
|
+
*/
|
|
109
|
+
export declare function estimateHoldersMakerCost(params: {
|
|
110
|
+
holdersCount: number;
|
|
111
|
+
buyAmountPerHolder: string;
|
|
112
|
+
gasLimit?: number;
|
|
113
|
+
gasPriceGwei?: number;
|
|
114
|
+
baseToken?: BaseTokenType;
|
|
115
|
+
hopCount?: number;
|
|
116
|
+
}): {
|
|
117
|
+
totalNativeCost: string;
|
|
118
|
+
totalBaseTokenCost: string;
|
|
119
|
+
gasEstimate: string;
|
|
120
|
+
batchCount: number;
|
|
121
|
+
hopWalletCount: number;
|
|
122
|
+
};
|