four-flap-meme-sdk 1.7.82 → 1.7.83

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.
@@ -0,0 +1,87 @@
1
+ /**
2
+ * BSC Bundle Merkle 配置
3
+ * - 贿赂交易
4
+ * - 利润多跳
5
+ * - Gas 配置
6
+ */
7
+ /** BSC 链 ID */
8
+ export declare const BSC_CHAIN_ID = 56;
9
+ /** BSC 链名称 */
10
+ export declare const BSC_CHAIN_NAME = "BSC";
11
+ /** BlockRazor Builder EOA 地址(用于 BSC 链贿赂) */
12
+ export declare const BLOCKRAZOR_BUILDER_EOA = "0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20";
13
+ /** 利润多跳次数(固定 2 跳中转) */
14
+ export declare const PROFIT_HOP_COUNT = 2;
15
+ /** 最低利润(Wei):报价成功但金额过低时的阈值 */
16
+ export declare const MIN_PROFIT_WEI = 10000000000n;
17
+ /** 原生代币转账 Gas Limit */
18
+ export declare const NATIVE_TRANSFER_GAS_LIMIT = 21000n;
19
+ /** 利润多跳 Gas Limit */
20
+ export declare const PROFIT_HOP_GAS_LIMIT = 21055n;
21
+ /** ERC20 转账 Gas Limit(多跳场景) */
22
+ export declare const ERC20_TRANSFER_GAS_LIMIT = 65000n;
23
+ /** 贿赂交易 Gas Limit */
24
+ export declare const BRIBE_GAS_LIMIT = 21000n;
25
+ /** BSC 配置接口 */
26
+ export interface BscBundleConfig {
27
+ /** RPC URL */
28
+ rpcUrl: string;
29
+ /** 链 ID(默认 56) */
30
+ chainId?: number;
31
+ /** 交易类型(0: legacy, 2: EIP-1559) */
32
+ txType?: 0 | 2;
33
+ /** Gas 价格配置 */
34
+ gasPriceConfig?: {
35
+ type?: 'auto' | 'fast' | 'instant';
36
+ multiplier?: number;
37
+ };
38
+ /** 贿赂金额(BNB) */
39
+ bribeAmount?: number;
40
+ /** 是否提取利润 */
41
+ extractProfit?: boolean;
42
+ /** 利润接收地址 */
43
+ profitRecipient?: string;
44
+ /** Gas Limit */
45
+ gasLimit?: number;
46
+ /** 是否使用 21000 作为原生代币 Gas Limit */
47
+ prefer21000ForNative?: boolean;
48
+ /** 检查 BNB 余额(ERC20 无多跳时) */
49
+ checkBnbForErc20NoHop?: boolean;
50
+ }
51
+ /** 池子类型 */
52
+ export type TokenPoolType = 'v2' | 'v3' | 'four' | 'flap';
53
+ /** 报价代币类型 */
54
+ export type QuoteTokenType = 'native' | 'usdt' | 'usdc';
55
+ /** 用户类型(影响利润率) */
56
+ export type UserType = 'v0' | 'v1';
57
+ /**
58
+ * 判断是否为 BSC 链
59
+ */
60
+ export declare function isBscChain(chainId?: number): boolean;
61
+ /**
62
+ * 从配置中读取贿赂金额,转换为 Wei
63
+ */
64
+ export declare function getBribeAmount(config?: BscBundleConfig): bigint;
65
+ /**
66
+ * 判断是否需要贿赂交易
67
+ */
68
+ export declare function needsBribeTx(config?: BscBundleConfig, chainId?: number): boolean;
69
+ /**
70
+ * 获取交易类型
71
+ */
72
+ export declare function getTxType(config?: BscBundleConfig): number;
73
+ /**
74
+ * 获取 Gas 价格配置
75
+ */
76
+ export declare function getGasPriceConfig(config?: BscBundleConfig): {
77
+ type?: "auto" | "fast" | "instant";
78
+ multiplier?: number;
79
+ };
80
+ /**
81
+ * 判断是否提取利润
82
+ */
83
+ export declare function shouldExtractProfit(config?: BscBundleConfig): boolean;
84
+ /**
85
+ * 获取利润接收地址
86
+ */
87
+ export declare function getProfitRecipient(config?: BscBundleConfig): string;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * BSC Bundle Merkle 配置
3
+ * - 贿赂交易
4
+ * - 利润多跳
5
+ * - Gas 配置
6
+ */
7
+ import { ethers } from 'ethers';
8
+ // ==================== BSC 链常量 ====================
9
+ /** BSC 链 ID */
10
+ export const BSC_CHAIN_ID = 56;
11
+ /** BSC 链名称 */
12
+ export const BSC_CHAIN_NAME = 'BSC';
13
+ /** BlockRazor Builder EOA 地址(用于 BSC 链贿赂) */
14
+ export const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
15
+ /** 利润多跳次数(固定 2 跳中转) */
16
+ export const PROFIT_HOP_COUNT = 2;
17
+ /** 最低利润(Wei):报价成功但金额过低时的阈值 */
18
+ export const MIN_PROFIT_WEI = 10000000000n; // 0.00000001 BNB
19
+ // ==================== Gas 配置 ====================
20
+ /** 原生代币转账 Gas Limit */
21
+ export const NATIVE_TRANSFER_GAS_LIMIT = 21000n;
22
+ /** 利润多跳 Gas Limit */
23
+ export const PROFIT_HOP_GAS_LIMIT = 21055n;
24
+ /** ERC20 转账 Gas Limit(多跳场景) */
25
+ export const ERC20_TRANSFER_GAS_LIMIT = 65000n;
26
+ /** 贿赂交易 Gas Limit */
27
+ export const BRIBE_GAS_LIMIT = 21000n;
28
+ // ==================== 工具函数 ====================
29
+ /**
30
+ * 判断是否为 BSC 链
31
+ */
32
+ export function isBscChain(chainId) {
33
+ return chainId === BSC_CHAIN_ID;
34
+ }
35
+ /**
36
+ * 从配置中读取贿赂金额,转换为 Wei
37
+ */
38
+ export function getBribeAmount(config) {
39
+ if (!config || !config.bribeAmount || config.bribeAmount <= 0) {
40
+ return 0n;
41
+ }
42
+ return ethers.parseEther(String(config.bribeAmount));
43
+ }
44
+ /**
45
+ * 判断是否需要贿赂交易
46
+ */
47
+ export function needsBribeTx(config, chainId) {
48
+ return isBscChain(chainId) && getBribeAmount(config) > 0n;
49
+ }
50
+ /**
51
+ * 获取交易类型
52
+ */
53
+ export function getTxType(config) {
54
+ return config?.txType ?? 0; // BSC 默认使用 legacy 交易
55
+ }
56
+ /**
57
+ * 获取 Gas 价格配置
58
+ */
59
+ export function getGasPriceConfig(config) {
60
+ return config?.gasPriceConfig ?? { type: 'auto', multiplier: 1.0 };
61
+ }
62
+ /**
63
+ * 判断是否提取利润
64
+ */
65
+ export function shouldExtractProfit(config) {
66
+ return config?.extractProfit !== false; // 默认提取
67
+ }
68
+ /**
69
+ * 获取利润接收地址
70
+ */
71
+ export function getProfitRecipient(config) {
72
+ // 默认利润地址
73
+ const DEFAULT_PROFIT_RECIPIENT = '0x0000000000000000000000000000000000000000'; // TODO: 设置真实地址
74
+ return config?.profitRecipient ?? DEFAULT_PROFIT_RECIPIENT;
75
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * BSC 分发模块 - 完全独立实现
3
+ *
4
+ * 特点:
5
+ * - ✅ 支持贿赂交易(BlockRazor)
6
+ * - ✅ 支持利润多跳
7
+ * - ✅ 支持原生币和 ERC20
8
+ * - ✅ 支持转账多跳
9
+ */
10
+ import type { BscDisperseParams, BscSignedResult } from './types.js';
11
+ /**
12
+ * BSC 分发(完全独立实现)
13
+ */
14
+ export declare function bscDisperse(params: BscDisperseParams): Promise<BscSignedResult>;
15
+ export declare function bscDisperseERC20(params: Omit<BscDisperseParams, 'tokenAddress'> & {
16
+ tokenAddress: string;
17
+ }): Promise<BscSignedResult>;
18
+ export declare function bscDisperseBNB(params: Omit<BscDisperseParams, 'tokenAddress' | 'tokenDecimals'>): Promise<BscSignedResult>;
19
+ export type { BscDisperseParams, BscSignedResult } from './types.js';
@@ -0,0 +1,408 @@
1
+ /**
2
+ * BSC 分发模块 - 完全独立实现
3
+ *
4
+ * 特点:
5
+ * - ✅ 支持贿赂交易(BlockRazor)
6
+ * - ✅ 支持利润多跳
7
+ * - ✅ 支持原生币和 ERC20
8
+ * - ✅ 支持转账多跳
9
+ */
10
+ import { ethers, Wallet, JsonRpcProvider } from 'ethers';
11
+ import { getOptimizedGasPrice, NonceManager, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../../utils/bundle-helpers.js';
12
+ import { PROFIT_CONFIG, ADDRESSES } from '../../utils/constants.js';
13
+ import { getErc20DecimalsMerkle, generateHopWallets, normalizeAmounts, calculateGasLimit, isNativeTokenAddress, } from '../../contracts/tm-bundle-merkle/internal.js';
14
+ import { quoteV2, quoteV3 } from '../../utils/quote-helpers.js';
15
+ import { BSC_CHAIN_ID, BLOCKRAZOR_BUILDER_EOA, MIN_PROFIT_WEI, BRIBE_GAS_LIMIT, getBribeAmount, getTxType, shouldExtractProfit, getProfitRecipient, } from './config.js';
16
+ // ==================== ERC20 → BNB 报价 ====================
17
+ async function getTokenToNativeQuote(provider, tokenAddress, tokenAmount, _chainId, tokenPoolType, _quoteToken, _rpcUrl) {
18
+ if (tokenAmount <= 0n)
19
+ return 0n;
20
+ try {
21
+ const wbnb = ADDRESSES.BSC.WBNB;
22
+ const version = tokenPoolType === 'v3' ? 'v3' : 'v2';
23
+ let result;
24
+ if (version === 'v3') {
25
+ result = await quoteV3(provider, tokenAddress, wbnb, tokenAmount, 'BSC');
26
+ }
27
+ else {
28
+ result = await quoteV2(provider, tokenAddress, wbnb, tokenAmount, 'BSC');
29
+ }
30
+ console.log(`[getTokenToNativeQuote] ${version} 报价成功: ${result.amountOut} wei`);
31
+ return result.amountOut;
32
+ }
33
+ catch (error) {
34
+ console.warn(`[getTokenToNativeQuote] 报价失败:`, error);
35
+ return 0n;
36
+ }
37
+ }
38
+ function getProfitRateBps(userType) {
39
+ if (userType === 'v1')
40
+ return PROFIT_CONFIG.RATE_BPS_V1_DOUBLE;
41
+ return PROFIT_CONFIG.RATE_BPS_V0_DOUBLE;
42
+ }
43
+ function calculateProfit(amount, userType) {
44
+ const rateBps = getProfitRateBps(userType);
45
+ const profit = (amount * BigInt(rateBps)) / 10000n;
46
+ const remaining = amount - profit;
47
+ return { profit, remaining };
48
+ }
49
+ // ==================== 主函数 ====================
50
+ /**
51
+ * BSC 分发(完全独立实现)
52
+ */
53
+ export async function bscDisperse(params) {
54
+ const { fromPrivateKey, recipients: inputRecipients, amount, amounts, tokenAddress, tokenDecimals, hopCount = 0, hopPrivateKeys, items, config, startNonce, tokenPoolType = 'v2', quoteToken = 'native', userType = 'v0', } = params;
55
+ // ==================== 参数处理 ====================
56
+ // 声明式输入转换
57
+ const recipients = items ? items.map(i => i.to) : inputRecipients;
58
+ const normalizedAmounts = items
59
+ ? items.map(i => (typeof i.amount === 'bigint' ? i.amount.toString() : String(i.amount)))
60
+ : normalizeAmounts(recipients, amount, amounts);
61
+ // 初始化
62
+ const chainIdNum = BSC_CHAIN_ID;
63
+ const provider = new JsonRpcProvider(config.rpcUrl, { chainId: chainIdNum, name: 'BSC' });
64
+ const mainWallet = new Wallet(fromPrivateKey, provider);
65
+ const txType = getTxType(config);
66
+ const isNative = isNativeTokenAddress(tokenAddress);
67
+ // 多跳钱包处理
68
+ const providedHops = hopPrivateKeys?.every(h => h.length === 0) ? null : hopPrivateKeys ?? null;
69
+ const itemHops = items?.map(i => i.hopPrivateKeys ?? []);
70
+ const itemHopsNull = itemHops?.every(h => h.length === 0) ? null : itemHops;
71
+ const hopCountInput = items ? items.map(i => i.hopCount ?? 0) : hopCount;
72
+ const preparedHops = providedHops ?? itemHopsNull ?? generateHopWallets(recipients.length, hopCountInput);
73
+ const hasHops = preparedHops !== null;
74
+ const maxHopCount = hasHops ? Math.max(...preparedHops.map(h => h.length)) : 0;
75
+ // Gas 配置
76
+ const finalGasLimit = calculateGasLimit(config, isNative, hasHops, maxHopCount);
77
+ const nativeGasLimit = config.prefer21000ForNative ? 21000n : finalGasLimit;
78
+ // 利润和贿赂配置
79
+ const extractProfit = shouldExtractProfit(config);
80
+ const bribeAmount = getBribeAmount(config);
81
+ const needBribeTx = bribeAmount > 0n;
82
+ // 结果数组
83
+ const signedTxs = [];
84
+ let totalProfit = 0n;
85
+ let totalAmountBeforeProfit = 0n;
86
+ let profitHopWallets;
87
+ const nonceManager = new NonceManager(provider);
88
+ // ==================== 无多跳场景 ====================
89
+ if (!preparedHops) {
90
+ const extraTxCount = (extractProfit ? 1 : 0) + (needBribeTx ? 1 : 0);
91
+ const totalTxCount = recipients.length + extraTxCount;
92
+ const [gasPrice, nonces] = await Promise.all([
93
+ getOptimizedGasPrice(provider),
94
+ startNonce !== undefined
95
+ ? Promise.resolve(Array.from({ length: totalTxCount }, (_, i) => startNonce + i))
96
+ : nonceManager.getNextNonceBatch(mainWallet, totalTxCount)
97
+ ]);
98
+ let nonceOffset = 0;
99
+ // ✅ 贿赂交易(放在最前面)
100
+ if (needBribeTx) {
101
+ const bribeTx = await mainWallet.signTransaction({
102
+ to: BLOCKRAZOR_BUILDER_EOA,
103
+ value: bribeAmount,
104
+ nonce: nonces[nonceOffset++],
105
+ gasPrice,
106
+ gasLimit: BRIBE_GAS_LIMIT,
107
+ chainId: chainIdNum,
108
+ type: txType
109
+ });
110
+ signedTxs.push(bribeTx);
111
+ console.log(`[bscDisperse] 贿赂交易已添加: ${ethers.formatEther(bribeAmount)} BNB`);
112
+ }
113
+ if (isNative) {
114
+ // ✅ 原生币分发
115
+ const txDataList = recipients.map((to, i) => {
116
+ const originalAmount = ethers.parseEther(normalizedAmounts[i]);
117
+ totalAmountBeforeProfit += originalAmount;
118
+ let actualAmount = originalAmount;
119
+ if (extractProfit) {
120
+ const { profit, remaining } = calculateProfit(originalAmount, userType);
121
+ actualAmount = remaining;
122
+ totalProfit += profit;
123
+ }
124
+ return { to, value: actualAmount, nonce: nonces[nonceOffset + i] };
125
+ });
126
+ const txPromises = txDataList.map(({ to, value, nonce }) => mainWallet.signTransaction({
127
+ to,
128
+ value,
129
+ nonce,
130
+ gasPrice,
131
+ gasLimit: nativeGasLimit,
132
+ chainId: chainIdNum,
133
+ type: txType
134
+ }));
135
+ signedTxs.push(...(await Promise.all(txPromises)));
136
+ // ✅ 利润多跳
137
+ if (extractProfit && totalProfit > 0n) {
138
+ const profitHopResult = await buildProfitHopTransactions({
139
+ provider,
140
+ payerWallet: mainWallet,
141
+ profitAmount: totalProfit,
142
+ profitRecipient: getProfitRecipient(config),
143
+ hopCount: PROFIT_HOP_COUNT,
144
+ gasPrice,
145
+ chainId: chainIdNum,
146
+ txType,
147
+ startNonce: nonces[nonceOffset + recipients.length]
148
+ });
149
+ signedTxs.push(...profitHopResult.signedTransactions);
150
+ profitHopWallets = profitHopResult.hopWallets;
151
+ console.log(`[bscDisperse] 利润多跳已添加: ${ethers.formatEther(totalProfit)} BNB`);
152
+ }
153
+ }
154
+ else {
155
+ // ✅ ERC20 分发
156
+ const decimals = tokenDecimals ?? await getErc20DecimalsMerkle(provider, tokenAddress, chainIdNum);
157
+ const iface = new ethers.Interface(['function transfer(address,uint256) returns (bool)']);
158
+ const originalAmounts = [];
159
+ let totalTokenProfit = 0n;
160
+ for (let i = 0; i < recipients.length; i++) {
161
+ const originalAmount = ethers.parseUnits(normalizedAmounts[i], decimals);
162
+ originalAmounts.push(originalAmount);
163
+ totalAmountBeforeProfit += originalAmount;
164
+ if (extractProfit) {
165
+ const { profit } = calculateProfit(originalAmount, userType);
166
+ totalTokenProfit += profit;
167
+ }
168
+ }
169
+ // ✅ ERC20 → BNB 报价
170
+ let nativeProfitAmount = 0n;
171
+ let profitIsNative = false;
172
+ if (extractProfit && totalTokenProfit > 0n) {
173
+ nativeProfitAmount = await getTokenToNativeQuote(provider, tokenAddress, totalTokenProfit, chainIdNum, tokenPoolType, quoteToken, config.rpcUrl);
174
+ profitIsNative = nativeProfitAmount > MIN_PROFIT_WEI;
175
+ if (profitIsNative) {
176
+ totalProfit = nativeProfitAmount;
177
+ console.log(`[bscDisperse ERC20] 报价成功,以 BNB 扣除利润: ${ethers.formatEther(nativeProfitAmount)} BNB`);
178
+ }
179
+ else {
180
+ console.log(`[bscDisperse ERC20] 报价失败或过低,以 ERC20 扣除利润: ${ethers.formatUnits(totalTokenProfit, decimals)} Token`);
181
+ }
182
+ }
183
+ const txDataList = recipients.map((to, i) => {
184
+ const originalAmount = originalAmounts[i];
185
+ let actualAmount = originalAmount;
186
+ if (extractProfit && !profitIsNative) {
187
+ const { remaining } = calculateProfit(originalAmount, userType);
188
+ actualAmount = remaining;
189
+ }
190
+ const data = iface.encodeFunctionData('transfer', [to, actualAmount]);
191
+ return { data, nonce: nonces[nonceOffset + i] };
192
+ });
193
+ const txPromises = txDataList.map(({ data, nonce }) => mainWallet.signTransaction({
194
+ to: tokenAddress,
195
+ data,
196
+ value: 0n,
197
+ nonce,
198
+ gasPrice,
199
+ gasLimit: finalGasLimit,
200
+ chainId: chainIdNum,
201
+ type: txType
202
+ }));
203
+ signedTxs.push(...(await Promise.all(txPromises)));
204
+ // ✅ 利润多跳(仅报价成功时)
205
+ if (extractProfit && profitIsNative && nativeProfitAmount > 0n) {
206
+ const profitHopResult = await buildProfitHopTransactions({
207
+ provider,
208
+ payerWallet: mainWallet,
209
+ profitAmount: nativeProfitAmount,
210
+ profitRecipient: getProfitRecipient(config),
211
+ hopCount: PROFIT_HOP_COUNT,
212
+ gasPrice,
213
+ chainId: chainIdNum,
214
+ txType,
215
+ startNonce: nonces[nonceOffset + recipients.length]
216
+ });
217
+ signedTxs.push(...profitHopResult.signedTransactions);
218
+ profitHopWallets = profitHopResult.hopWallets;
219
+ console.log(`[bscDisperse ERC20] 利润多跳已添加: ${ethers.formatEther(nativeProfitAmount)} BNB`);
220
+ }
221
+ }
222
+ }
223
+ else {
224
+ // ==================== 有多跳场景 ====================
225
+ const [gasPrice, decimals] = await Promise.all([
226
+ getOptimizedGasPrice(provider),
227
+ isNative ? Promise.resolve(18) : Promise.resolve(tokenDecimals ?? await getErc20DecimalsMerkle(provider, tokenAddress, chainIdNum))
228
+ ]);
229
+ const iface = isNative ? null : new ethers.Interface(['function transfer(address,uint256) returns (bool)']);
230
+ const nativeTransferGasLimit = 21000n;
231
+ const erc20TransferGasLimit = 65000n;
232
+ const nativeHopGasFee = nativeTransferGasLimit * gasPrice;
233
+ const erc20HopGasFee = erc20TransferGasLimit * gasPrice;
234
+ const nativeHopGasFeeForErc20 = nativeTransferGasLimit * gasPrice;
235
+ // 计算主钱包需要的 nonce 数量
236
+ let mainWalletNonceCount = needBribeTx ? 1 : 0;
237
+ for (let i = 0; i < recipients.length; i++) {
238
+ const hopChain = preparedHops[i];
239
+ if (hopChain.length === 0) {
240
+ mainWalletNonceCount += 1;
241
+ }
242
+ else {
243
+ mainWalletNonceCount += isNative ? 1 : 2;
244
+ }
245
+ }
246
+ if (extractProfit)
247
+ mainWalletNonceCount += 1;
248
+ const allMainNonces = startNonce !== undefined
249
+ ? Array.from({ length: mainWalletNonceCount }, (_, i) => startNonce + i)
250
+ : await nonceManager.getNextNonceBatch(mainWallet, mainWalletNonceCount);
251
+ let mainNonceIdx = 0;
252
+ // ✅ 贿赂交易(放在最前面)
253
+ if (needBribeTx) {
254
+ const bribeTx = await mainWallet.signTransaction({
255
+ to: BLOCKRAZOR_BUILDER_EOA,
256
+ value: bribeAmount,
257
+ nonce: allMainNonces[mainNonceIdx++],
258
+ gasPrice,
259
+ gasLimit: BRIBE_GAS_LIMIT,
260
+ chainId: chainIdNum,
261
+ type: txType
262
+ });
263
+ signedTxs.push(bribeTx);
264
+ console.log(`[bscDisperse with hops] 贿赂交易已添加: ${ethers.formatEther(bribeAmount)} BNB`);
265
+ }
266
+ const txsToSign = [];
267
+ let totalTokenProfit = 0n;
268
+ for (let i = 0; i < recipients.length; i++) {
269
+ const finalRecipient = recipients[i];
270
+ const originalAmountWei = isNative
271
+ ? ethers.parseEther(normalizedAmounts[i])
272
+ : ethers.parseUnits(normalizedAmounts[i], decimals);
273
+ totalAmountBeforeProfit += originalAmountWei;
274
+ let amountWei = originalAmountWei;
275
+ if (extractProfit) {
276
+ const { profit, remaining } = calculateProfit(originalAmountWei, userType);
277
+ amountWei = remaining;
278
+ if (isNative) {
279
+ totalProfit += profit;
280
+ }
281
+ else {
282
+ totalTokenProfit += profit;
283
+ }
284
+ }
285
+ const hopChain = preparedHops[i];
286
+ if (hopChain.length === 0) {
287
+ const nonce = allMainNonces[mainNonceIdx++];
288
+ if (isNative) {
289
+ txsToSign.push({
290
+ wallet: mainWallet,
291
+ tx: { to: finalRecipient, value: amountWei, nonce, gasPrice, gasLimit: nativeGasLimit, chainId: chainIdNum, type: txType }
292
+ });
293
+ }
294
+ else {
295
+ const data = iface.encodeFunctionData('transfer', [finalRecipient, amountWei]);
296
+ txsToSign.push({
297
+ wallet: mainWallet,
298
+ tx: { to: tokenAddress, data, value: 0n, nonce, gasPrice, gasLimit: finalGasLimit, chainId: chainIdNum, type: txType }
299
+ });
300
+ }
301
+ continue;
302
+ }
303
+ // 有多跳的情况
304
+ const hopWallets = hopChain.map(h => new Wallet(typeof h === 'string' ? h : h.privateKey, provider));
305
+ const fullChain = [mainWallet, ...hopWallets];
306
+ const addresses = [...fullChain.map(w => w.address), finalRecipient];
307
+ if (isNative) {
308
+ const mainNonce = allMainNonces[mainNonceIdx++];
309
+ for (let j = 0; j < addresses.length - 1; j++) {
310
+ const fromWallet = fullChain[j];
311
+ const toAddress = addresses[j + 1];
312
+ const nonce = j === 0 ? mainNonce : 0;
313
+ const remainingHops = addresses.length - 2 - j;
314
+ const additionalGas = nativeHopGasFee * BigInt(remainingHops);
315
+ const transferValue = amountWei + additionalGas;
316
+ txsToSign.push({
317
+ wallet: fromWallet,
318
+ tx: { to: toAddress, value: transferValue, nonce, gasPrice, gasLimit: nativeTransferGasLimit, chainId: chainIdNum, type: txType }
319
+ });
320
+ }
321
+ }
322
+ else {
323
+ // ERC20 多跳: 主钱包需要 2 个 nonce(转 gas + 转 ERC20)
324
+ const mainGasNonce = allMainNonces[mainNonceIdx++];
325
+ const mainErc20Nonce = allMainNonces[mainNonceIdx++];
326
+ const hop1 = hopWallets[0];
327
+ const totalGasNeeded = (nativeHopGasFeeForErc20 + erc20HopGasFee) * BigInt(hopWallets.length);
328
+ txsToSign.push({
329
+ wallet: mainWallet,
330
+ tx: { to: hop1.address, value: totalGasNeeded, nonce: mainGasNonce, gasPrice, gasLimit: nativeTransferGasLimit, chainId: chainIdNum, type: txType }
331
+ });
332
+ const erc20Data = iface.encodeFunctionData('transfer', [hop1.address, amountWei]);
333
+ txsToSign.push({
334
+ wallet: mainWallet,
335
+ tx: { to: tokenAddress, data: erc20Data, value: 0n, nonce: mainErc20Nonce, gasPrice, gasLimit: erc20TransferGasLimit, chainId: chainIdNum, type: txType }
336
+ });
337
+ for (let j = 0; j < hopWallets.length; j++) {
338
+ const fromWallet = hopWallets[j];
339
+ const toAddress = j === hopWallets.length - 1 ? finalRecipient : hopWallets[j + 1].address;
340
+ const remainingHops = hopWallets.length - 1 - j;
341
+ if (remainingHops > 0) {
342
+ const gasToForward = (nativeHopGasFeeForErc20 + erc20HopGasFee) * BigInt(remainingHops);
343
+ txsToSign.push({
344
+ wallet: fromWallet,
345
+ tx: { to: toAddress, value: gasToForward, nonce: 0, gasPrice, gasLimit: nativeTransferGasLimit, chainId: chainIdNum, type: txType }
346
+ });
347
+ }
348
+ const erc20DataHop = iface.encodeFunctionData('transfer', [toAddress, amountWei]);
349
+ txsToSign.push({
350
+ wallet: fromWallet,
351
+ tx: { to: tokenAddress, data: erc20DataHop, value: 0n, nonce: remainingHops > 0 ? 1 : 0, gasPrice, gasLimit: erc20TransferGasLimit, chainId: chainIdNum, type: txType }
352
+ });
353
+ }
354
+ }
355
+ }
356
+ // 签名所有交易
357
+ const signedTransfers = await Promise.all(txsToSign.map(({ wallet, tx }) => wallet.signTransaction(tx)));
358
+ signedTxs.push(...signedTransfers);
359
+ // ✅ ERC20 多跳利润处理
360
+ if (!isNative && extractProfit && totalTokenProfit > 0n) {
361
+ const nativeProfitAmount = await getTokenToNativeQuote(provider, tokenAddress, totalTokenProfit, chainIdNum, tokenPoolType, quoteToken, config.rpcUrl);
362
+ if (nativeProfitAmount > MIN_PROFIT_WEI) {
363
+ totalProfit = nativeProfitAmount;
364
+ }
365
+ }
366
+ // ✅ 利润多跳
367
+ if (extractProfit && totalProfit > 0n) {
368
+ const profitNonce = allMainNonces[mainNonceIdx++];
369
+ const profitHopResult = await buildProfitHopTransactions({
370
+ provider,
371
+ payerWallet: mainWallet,
372
+ profitAmount: totalProfit,
373
+ profitRecipient: getProfitRecipient(config),
374
+ hopCount: PROFIT_HOP_COUNT,
375
+ gasPrice,
376
+ chainId: chainIdNum,
377
+ txType,
378
+ startNonce: profitNonce
379
+ });
380
+ signedTxs.push(...profitHopResult.signedTransactions);
381
+ profitHopWallets = profitHopResult.hopWallets;
382
+ console.log(`[bscDisperse with hops] 利润多跳已添加: ${ethers.formatEther(totalProfit)} BNB`);
383
+ }
384
+ }
385
+ // ==================== 返回结果 ====================
386
+ return {
387
+ signedTransactions: signedTxs,
388
+ hopWallets: preparedHops || undefined,
389
+ profitHopWallets,
390
+ metadata: extractProfit ? {
391
+ totalAmount: ethers.formatEther(totalAmountBeforeProfit),
392
+ profitAmount: ethers.formatEther(totalProfit),
393
+ profitRecipient: getProfitRecipient(config),
394
+ recipientCount: recipients.length,
395
+ isNative,
396
+ tokenAddress: isNative ? undefined : tokenAddress,
397
+ hasBribeTx: needBribeTx,
398
+ bribeAmount: needBribeTx ? ethers.formatEther(bribeAmount) : undefined
399
+ } : undefined
400
+ };
401
+ }
402
+ // ==================== 便捷函数 ====================
403
+ export async function bscDisperseERC20(params) {
404
+ return bscDisperse(params);
405
+ }
406
+ export async function bscDisperseBNB(params) {
407
+ return bscDisperse({ ...params, tokenAddress: undefined });
408
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * BSC Bundle Merkle 模块入口
3
+ *
4
+ * 提供 BSC 链上的分发、归集、多对多转账功能
5
+ * 支持贿赂交易和利润多跳
6
+ */
7
+ export { bscDisperse, bscDisperseERC20, bscDisperseBNB, } from './disperse.js';
8
+ export { bscSweep, bscSweepERC20, bscSweepBNB, } from './sweep.js';
9
+ export { bscPairwiseTransfer, bscPairwiseTransferERC20, bscPairwiseTransferBNB, } from './pairwise.js';
10
+ export { BSC_CHAIN_ID, BSC_CHAIN_NAME, BLOCKRAZOR_BUILDER_EOA, PROFIT_HOP_COUNT, MIN_PROFIT_WEI, NATIVE_TRANSFER_GAS_LIMIT, PROFIT_HOP_GAS_LIMIT, ERC20_TRANSFER_GAS_LIMIT, BRIBE_GAS_LIMIT, isBscChain, getBribeAmount, needsBribeTx, getTxType, getGasPriceConfig, shouldExtractProfit, getProfitRecipient, } from './config.js';
11
+ export type { BscBundleConfig, TokenPoolType, QuoteTokenType, UserType, } from './config.js';
12
+ export type { AmountLike, BscSignedResult, BscDisperseParams, BscSweepParams, BscPairwiseParams, } from './types.js';
@@ -0,0 +1,14 @@
1
+ /**
2
+ * BSC Bundle Merkle 模块入口
3
+ *
4
+ * 提供 BSC 链上的分发、归集、多对多转账功能
5
+ * 支持贿赂交易和利润多跳
6
+ */
7
+ // ==================== 分发 ====================
8
+ export { bscDisperse, bscDisperseERC20, bscDisperseBNB, } from './disperse.js';
9
+ // ==================== 归集 ====================
10
+ export { bscSweep, bscSweepERC20, bscSweepBNB, } from './sweep.js';
11
+ // ==================== 多对多 ====================
12
+ export { bscPairwiseTransfer, bscPairwiseTransferERC20, bscPairwiseTransferBNB, } from './pairwise.js';
13
+ // ==================== 配置 ====================
14
+ export { BSC_CHAIN_ID, BSC_CHAIN_NAME, BLOCKRAZOR_BUILDER_EOA, PROFIT_HOP_COUNT, MIN_PROFIT_WEI, NATIVE_TRANSFER_GAS_LIMIT, PROFIT_HOP_GAS_LIMIT, ERC20_TRANSFER_GAS_LIMIT, BRIBE_GAS_LIMIT, isBscChain, getBribeAmount, needsBribeTx, getTxType, getGasPriceConfig, shouldExtractProfit, getProfitRecipient, } from './config.js';
@@ -0,0 +1,19 @@
1
+ /**
2
+ * BSC 多对多转账模块 - 完全独立实现
3
+ *
4
+ * 特点:
5
+ * - ✅ 支持贿赂交易(由第一个 sender 支付)
6
+ * - ✅ 支持利润多跳
7
+ * - ✅ 支持原生币和 ERC20
8
+ * - ✅ 支持转账多跳
9
+ */
10
+ import type { BscPairwiseParams, BscSignedResult } from './types.js';
11
+ /**
12
+ * BSC 多对多转账(完全独立实现)
13
+ */
14
+ export declare function bscPairwiseTransfer(params: BscPairwiseParams): Promise<BscSignedResult>;
15
+ export declare function bscPairwiseTransferERC20(params: Omit<BscPairwiseParams, 'tokenAddress'> & {
16
+ tokenAddress: string;
17
+ }): Promise<BscSignedResult>;
18
+ export declare function bscPairwiseTransferBNB(params: Omit<BscPairwiseParams, 'tokenAddress' | 'tokenDecimals'>): Promise<BscSignedResult>;
19
+ export type { BscPairwiseParams } from './types.js';