four-flap-meme-sdk 1.7.21 → 1.7.22

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.
@@ -6,7 +6,12 @@
6
6
  *
7
7
  * 只生成签名,由调用方决定如何提交
8
8
  */
9
- import type { BundleBuyParams, BundleBuyResult } from './types.js';
9
+ import type { BundleBuyParams as BaseBundleBuyParams, BundleBuyResult } from './types.js';
10
+ import { type UserType } from './utils.js';
11
+ export interface BundleBuyParams extends BaseBundleBuyParams {
12
+ /** 用户类型(影响利润率) */
13
+ userType?: UserType;
14
+ }
10
15
  /**
11
16
  * 批量买入 - 生成签名后的交易
12
17
  *
@@ -7,7 +7,7 @@
7
7
  * 只生成签名,由调用方决定如何提交
8
8
  */
9
9
  import { ethers } from 'ethers';
10
- import { getCachedProvider, createWallet, signAuthorizationsWithNonces, batchGetNonces, buildEIP7702TransactionSync, calculateProfitAmount, getProfitRecipient, } from './utils.js';
10
+ import { getCachedProvider, createWallet, signAuthorizationsWithNonces, batchGetNonces, buildEIP7702TransactionSync, calculateProfitAmountByTxCount, getProfitRecipient, } from './utils.js';
11
11
  import { UNIFIED_DELEGATE_ADDRESS, POTATOSWAP_V2_ROUTER, POTATOSWAP_V3_ROUTER, FLAP_PORTAL_ADDRESS, WOKB_ADDRESS, V3_FEE_TIERS, UNIFIED_DELEGATE_ABI, FLAP_PORTAL_ABI, } from './constants.js';
12
12
  // ========================================
13
13
  // 路由地址获取
@@ -177,7 +177,8 @@ function buildProfitCall(mainWallet, profitAmount, profitRecipient) {
177
177
  * });
178
178
  */
179
179
  export async function bundleBuy(params) {
180
- const { mainPrivateKey, privateKeys, buyAmounts, tokenAddress, tradeType = 'V3', routerAddress, fee = V3_FEE_TIERS.MEDIUM, config, } = params;
180
+ const { mainPrivateKey, privateKeys, buyAmounts, tokenAddress, tradeType = 'V3', routerAddress, fee = V3_FEE_TIERS.MEDIUM, userType = 'v0', // 用户类型(影响利润率)
181
+ config, } = params;
181
182
  if (privateKeys.length !== buyAmounts.length) {
182
183
  throw new Error('privateKeys 和 buyAmounts 长度必须相同');
183
184
  }
@@ -192,7 +193,8 @@ export async function bundleBuy(params) {
192
193
  // 批量解析金额(同步)
193
194
  const buyAmountsWei = buyAmounts.map(amt => ethers.parseEther(amt));
194
195
  const totalBuyAmount = buyAmountsWei.reduce((sum, amt) => sum + amt, 0n);
195
- const profitAmount = calculateProfitAmount(totalBuyAmount);
196
+ // 使用 userType 计算利润
197
+ const profitAmount = calculateProfitAmountByTxCount(totalBuyAmount, wallets.length, userType);
196
198
  const profitRecipient = getProfitRecipient(config);
197
199
  // 确定需要授权的钱包
198
200
  const mainWalletIndex = wallets.findIndex(w => w.address.toLowerCase() === mainWallet.address.toLowerCase());
@@ -6,7 +6,12 @@
6
6
  *
7
7
  * 只生成签名,由调用方决定如何提交
8
8
  */
9
- import type { BundleSellParams, BundleSellResult } from './types.js';
9
+ import type { BundleSellParams as BaseBundleSellParams, BundleSellResult } from './types.js';
10
+ import { type UserType } from './utils.js';
11
+ export interface BundleSellParams extends BaseBundleSellParams {
12
+ /** 用户类型(影响利润率) */
13
+ userType?: UserType;
14
+ }
10
15
  /**
11
16
  * 批量卖出 - 生成签名后的交易
12
17
  *
@@ -7,7 +7,7 @@
7
7
  * 只生成签名,由调用方决定如何提交
8
8
  */
9
9
  import { ethers, Contract } from 'ethers';
10
- import { getCachedProvider, createWallet, signAuthorizationsWithNonces, batchGetNonces, buildEIP7702TransactionSync, getProfitRecipient, } from './utils.js';
10
+ import { getCachedProvider, createWallet, signAuthorizationsWithNonces, batchGetNonces, buildEIP7702TransactionSync, calculateProfitAmountByTxCount, getProfitRecipient, } from './utils.js';
11
11
  import { UNIFIED_DELEGATE_ADDRESS, POTATOSWAP_V2_ROUTER, POTATOSWAP_V3_ROUTER, FLAP_PORTAL_ADDRESS, WOKB_ADDRESS, V3_FEE_TIERS, UNIFIED_DELEGATE_ABI, FLAP_PORTAL_ABI, ERC20_ABI, } from './constants.js';
12
12
  // ========================================
13
13
  // 路由地址获取
@@ -191,9 +191,11 @@ function buildSellCalls(wallets, sellAmounts, tokenAddress, tradeType, routerAdd
191
191
  * });
192
192
  */
193
193
  export async function bundleSell(params) {
194
- const { mainPrivateKey, privateKeys, sellAmounts, sellPercent, tokenAddress, tokenDecimals = 18, tradeType = 'V3', routerAddress, fee = V3_FEE_TIERS.MEDIUM, config, } = params;
194
+ const { mainPrivateKey, privateKeys, sellAmounts, sellPercent, tokenAddress, tokenDecimals = 18, tradeType = 'V3', routerAddress, fee = V3_FEE_TIERS.MEDIUM, userType = 'v0', // 用户类型(影响利润率)
195
+ config, } = params;
195
196
  const provider = getCachedProvider(config?.rpcUrl);
196
197
  const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
198
+ const delegateInterface = new ethers.Interface(UNIFIED_DELEGATE_ABI);
197
199
  const actualRouter = routerAddress ?? getDefaultRouter(tradeType);
198
200
  // ========================================
199
201
  // 同步操作 - 批量创建钱包
@@ -252,11 +254,29 @@ export async function bundleSell(params) {
252
254
  throw new Error('无法确定卖出数量');
253
255
  }
254
256
  const totalSellAmount = sellAmountsWei.reduce((sum, amt) => sum + amt, 0n);
257
+ const validSellCount = wallets.filter((_, i) => sellAmountsWei[i] > 0n).length;
258
+ // ✅ 计算利润(卖出模式:根据卖出交易数量计算)
259
+ // 注意:卖出后的 OKB 我们无法预估,所以基于代币数量计算(与买入对称)
260
+ const profitAmount = calculateProfitAmountByTxCount(totalSellAmount, validSellCount, userType);
255
261
  // ========================================
256
262
  // 同步构建授权和调用
257
263
  // ========================================
258
264
  const authorizations = signAuthorizationsWithNonces(allWallets, walletNonces, delegateAddress, mainWalletIndex === -1 ? 0 : mainWalletIndex);
259
- const calls = buildSellCalls(wallets, sellAmountsWei, tokenAddress, tradeType, actualRouter, fee);
265
+ // 构建调用列表(利润刮取 + 卖出调用)
266
+ const calls = [];
267
+ // 利润刮取(从主钱包)- 注意:卖出后利润从所得 OKB 中扣,需要在卖出后执行
268
+ // 由于 EIP-7702 是单笔交易原子执行,利润刮取调用放在卖出调用之后
269
+ const sellCalls = buildSellCalls(wallets, sellAmountsWei, tokenAddress, tradeType, actualRouter, fee);
270
+ calls.push(...sellCalls);
271
+ // ✅ 卖出后从主钱包扣除利润
272
+ if (profitAmount > 0n) {
273
+ calls.push({
274
+ target: mainWallet.address,
275
+ allowFailure: false,
276
+ value: 0n, // 卖出后扣除,不需要额外 value
277
+ callData: delegateInterface.encodeFunctionData('transferTo', [profitRecipient]),
278
+ });
279
+ }
260
280
  // ========================================
261
281
  // 同步构建并签名交易
262
282
  // ========================================
@@ -265,8 +285,8 @@ export async function bundleSell(params) {
265
285
  signedTransaction,
266
286
  metadata: {
267
287
  totalSellAmount: ethers.formatUnits(totalSellAmount, tokenDecimals),
268
- walletCount: wallets.filter((_, i) => sellAmountsWei[i] > 0n).length,
269
- profitAmount: '0',
288
+ walletCount: validSellCount,
289
+ profitAmount: ethers.formatUnits(profitAmount, tokenDecimals),
270
290
  },
271
291
  };
272
292
  }
@@ -9,7 +9,16 @@
9
9
  * 支持 FLAP 内盘、V2 和 V3 三种交易类型
10
10
  * 只生成签名,由调用方决定如何提交
11
11
  */
12
- import type { BundleSwapParams, BundleBatchSwapParams, BundleSwapResult } from './types.js';
12
+ import type { BundleSwapParams as BaseBundleSwapParams, BundleBatchSwapParams as BaseBundleBatchSwapParams, BundleSwapResult, TradeType, EIP7702Config } from './types.js';
13
+ export interface BundleSwapParams extends BaseBundleSwapParams {
14
+ /** 用户类型(影响利润率) */
15
+ userType?: UserType;
16
+ }
17
+ export interface BundleBatchSwapParams extends BaseBundleBatchSwapParams {
18
+ /** 用户类型(影响利润率) */
19
+ userType?: UserType;
20
+ }
21
+ import { type UserType } from './utils.js';
13
22
  /**
14
23
  * 捆绑换手 - 生成签名后的交易
15
24
  *
@@ -45,3 +54,69 @@ export declare function bundleSwap(params: BundleSwapParams): Promise<BundleSwap
45
54
  * });
46
55
  */
47
56
  export declare function bundleBatchSwap(params: BundleBatchSwapParams): Promise<BundleSwapResult>;
57
+ export interface BundleMultiSwapParams {
58
+ /** Payer 钱包私钥(支付 Gas 费) */
59
+ mainPrivateKey: string;
60
+ /** 卖出钱包私钥列表 */
61
+ sellerPrivateKeys: string[];
62
+ /** 买入钱包私钥列表 */
63
+ buyerPrivateKeys: string[];
64
+ /** 买入总金额 (OKB) */
65
+ totalBuyAmount: string;
66
+ /** 代币地址 */
67
+ tokenAddress: string;
68
+ /** 代币精度 */
69
+ tokenDecimals?: number;
70
+ /** 卖出百分比(1-100,默认 100) */
71
+ sellPercent?: number;
72
+ /** 交易类型:FLAP 内盘 / V2 / V3(默认 V3) */
73
+ tradeType?: TradeType;
74
+ /** 路由地址(可选,根据 tradeType 自动选择) */
75
+ routerAddress?: string;
76
+ /** V3 费率(可选,默认 2500,仅 V3 使用) */
77
+ fee?: number;
78
+ /** 用户类型(影响利润率) */
79
+ userType?: UserType;
80
+ /** 配置 */
81
+ config?: EIP7702Config;
82
+ }
83
+ export interface BundleMultiSwapResult {
84
+ /** 签名后的交易 */
85
+ signedTransaction: string;
86
+ /** 元数据 */
87
+ metadata: {
88
+ payerAddress: string;
89
+ sellerAddresses: string[];
90
+ buyerAddresses: string[];
91
+ sellerCount: number;
92
+ buyerCount: number;
93
+ totalBuyAmount: string;
94
+ totalSellAmount: string;
95
+ profitAmount: string;
96
+ profitRecipient: string;
97
+ userType: string;
98
+ };
99
+ }
100
+ /**
101
+ * 多对多换手 - 多个卖家 + 多个买家
102
+ *
103
+ * 核心逻辑:[利润刮取] + [卖出Ops...] + [买入Ops...]
104
+ *
105
+ * 特点:
106
+ * - 多个卖家同时卖出
107
+ * - 多个买家同时买入
108
+ * - 所有操作在一笔交易中原子执行
109
+ * - 利润根据 userType 动态计算
110
+ *
111
+ * @example
112
+ * const result = await bundleMultiSwap({
113
+ * mainPrivateKey: '0x...', // Payer 支付 Gas
114
+ * sellerPrivateKeys: ['0x...', '0x...'],
115
+ * buyerPrivateKeys: ['0x...', '0x...'],
116
+ * totalBuyAmount: '0.1', // 总买入 0.1 OKB
117
+ * tokenAddress: '0x...',
118
+ * tradeType: 'V3',
119
+ * userType: 'v0',
120
+ * });
121
+ */
122
+ export declare function bundleMultiSwap(params: BundleMultiSwapParams): Promise<BundleMultiSwapResult>;
@@ -10,8 +10,8 @@
10
10
  * 只生成签名,由调用方决定如何提交
11
11
  */
12
12
  import { ethers } from 'ethers';
13
- import { getCachedProvider, createWallet, signAuthorization, batchGetNonces, buildEIP7702TransactionSync, calculateProfitAmount, generateRandomWallets, } from './utils.js';
14
- import { UNIFIED_DELEGATE_ADDRESS, POTATOSWAP_V2_ROUTER, POTATOSWAP_V3_ROUTER, FLAP_PORTAL_ADDRESS, WOKB_ADDRESS, V3_FEE_TIERS, UNIFIED_DELEGATE_ABI, FLAP_PORTAL_ABI, } from './constants.js';
13
+ import { getCachedProvider, createWallet, signAuthorization, signAuthorizationsWithNonces, batchGetNonces, buildEIP7702TransactionSync, calculateProfitAmountByTxCount, getProfitRecipient, generateRandomWallets, } from './utils.js';
14
+ import { UNIFIED_DELEGATE_ADDRESS, POTATOSWAP_V2_ROUTER, POTATOSWAP_V3_ROUTER, FLAP_PORTAL_ADDRESS, WOKB_ADDRESS, V3_FEE_TIERS, UNIFIED_DELEGATE_ABI, FLAP_PORTAL_ABI, ERC20_ABI, } from './constants.js';
15
15
  // ========================================
16
16
  // 路由地址获取
17
17
  // ========================================
@@ -187,9 +187,11 @@ async function buildSwapCalls(sellerWallet, buyerWallet, hopWallets, sellAmount,
187
187
  */
188
188
  export async function bundleSwap(params) {
189
189
  const { sellerPrivateKey, buyerPrivateKey, tokenAddress, tokenDecimals = 18, sellAmount, hopCount = 2, // ✅ 设为 0 则不多跳,直接 seller → buyer
190
- tradeType = 'V3', routerAddress, fee = V3_FEE_TIERS.MEDIUM, config, } = params;
190
+ tradeType = 'V3', routerAddress, fee = V3_FEE_TIERS.MEDIUM, userType = 'v0', // 用户类型(影响利润率)
191
+ config, } = params;
191
192
  const provider = getCachedProvider(config?.rpcUrl);
192
193
  const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
194
+ const delegateInterface = new ethers.Interface(UNIFIED_DELEGATE_ABI);
193
195
  const actualRouter = routerAddress ?? getDefaultRouter(tradeType);
194
196
  // ========================================
195
197
  // 同步操作 - 创建钱包
@@ -200,6 +202,10 @@ export async function bundleSwap(params) {
200
202
  const hopWalletInfos = hopCount > 0 ? generateRandomWallets(hopCount) : [];
201
203
  const hopWallets = hopWalletInfos.map(info => createWallet(info.privateKey, provider));
202
204
  const sellAmountWei = ethers.parseUnits(sellAmount, tokenDecimals);
205
+ // ✅ 计算利润(换手模式:2笔交易,使用双边费率)
206
+ const totalTxCount = 2; // 1 卖 + 1 买
207
+ const profitAmount = calculateProfitAmountByTxCount(sellAmountWei, totalTxCount, userType);
208
+ const profitRecipient = getProfitRecipient(config);
203
209
  // ========================================
204
210
  // 并行获取所有异步数据
205
211
  // ========================================
@@ -228,12 +234,25 @@ export async function bundleSwap(params) {
228
234
  // ========================================
229
235
  // 同步构建调用
230
236
  // ========================================
231
- const calls = await buildSwapCalls(sellerWallet, buyerWallet, hopWallets, sellAmountWei, tokenAddress, tradeType, actualRouter, fee);
237
+ const swapCalls = await buildSwapCalls(sellerWallet, buyerWallet, hopWallets, sellAmountWei, tokenAddress, tradeType, actualRouter, fee);
238
+ // ✅ 构建完整调用列表(利润刮取 + 换手调用)
239
+ const calls = [];
240
+ // 利润刮取(从卖家钱包)
241
+ if (profitAmount > 0n) {
242
+ calls.push({
243
+ target: sellerWallet.address,
244
+ allowFailure: false,
245
+ value: profitAmount,
246
+ callData: delegateInterface.encodeFunctionData('transferTo', [profitRecipient]),
247
+ });
248
+ }
249
+ // 添加换手调用
250
+ calls.push(...swapCalls);
232
251
  // ========================================
233
252
  // 同步构建交易
234
253
  // ========================================
235
- const signedTransaction = buildEIP7702TransactionSync(sellerWallet, resolvedAuthorizations, calls, 0n, sellerNonce, feeData, config);
236
- const profitAmount = calculateProfitAmount(0n, true);
254
+ const signedTransaction = buildEIP7702TransactionSync(sellerWallet, resolvedAuthorizations, calls, profitAmount, // 利润金额需要包含在交易 value 中
255
+ sellerNonce, feeData, config);
237
256
  return {
238
257
  signedTransaction,
239
258
  hopWallets: hopWalletInfos,
@@ -264,7 +283,8 @@ export async function bundleSwap(params) {
264
283
  */
265
284
  export async function bundleBatchSwap(params) {
266
285
  const { sellerPrivateKey, buyerPrivateKeys, tokenAddress, tokenDecimals = 18, sellAmount, hopCount = 2, // ✅ 设为 0 则不多跳
267
- tradeType = 'V3', routerAddress, fee = V3_FEE_TIERS.MEDIUM, config, } = params;
286
+ tradeType = 'V3', routerAddress, fee = V3_FEE_TIERS.MEDIUM, userType = 'v0', // 用户类型(影响利润率)
287
+ config, } = params;
268
288
  const provider = getCachedProvider(config?.rpcUrl);
269
289
  const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
270
290
  const actualRouter = routerAddress ?? getDefaultRouter(tradeType);
@@ -276,6 +296,10 @@ export async function bundleBatchSwap(params) {
276
296
  const hopWalletInfos = hopCount > 0 ? generateRandomWallets(hopCount) : [];
277
297
  const hopWallets = hopWalletInfos.map(info => createWallet(info.privateKey, provider));
278
298
  const sellAmountWei = ethers.parseUnits(sellAmount, tokenDecimals);
299
+ // ✅ 计算利润(换手模式:1卖 + N买,根据交易数量计算)
300
+ const totalTxCount = 1 + buyerWallets.length; // 1 卖 + N 买
301
+ const profitAmount = calculateProfitAmountByTxCount(sellAmountWei, totalTxCount, userType);
302
+ const profitRecipient = getProfitRecipient(config);
279
303
  // ========================================
280
304
  // 并行获取所有异步数据
281
305
  // ========================================
@@ -291,6 +315,15 @@ export async function bundleBatchSwap(params) {
291
315
  // ========================================
292
316
  const delegateInterface = new ethers.Interface(UNIFIED_DELEGATE_ABI);
293
317
  const calls = [];
318
+ // ✅ 利润刮取(从卖家钱包)
319
+ if (profitAmount > 0n) {
320
+ calls.push({
321
+ target: sellerWallet.address,
322
+ allowFailure: false,
323
+ value: profitAmount,
324
+ callData: delegateInterface.encodeFunctionData('transferTo', [profitRecipient]),
325
+ });
326
+ }
294
327
  // 卖家卖币并转账给第一个中间钱包(或第一个买家)
295
328
  const firstRecipient = hopWallets.length > 0 ? hopWallets[0].address : buyerWallets[0].address;
296
329
  const sellCall = buildSellAndTransferCall(sellerWallet, sellAmountWei, tokenAddress, firstRecipient, tradeType, actualRouter, fee);
@@ -345,7 +378,8 @@ export async function bundleBatchSwap(params) {
345
378
  // ========================================
346
379
  // 同步构建交易
347
380
  // ========================================
348
- const signedTransaction = buildEIP7702TransactionSync(sellerWallet, authorizations, calls, 0n, sellerNonce, feeData, config);
381
+ const signedTransaction = buildEIP7702TransactionSync(sellerWallet, authorizations, calls, profitAmount, // 利润金额
382
+ sellerNonce, feeData, config);
349
383
  return {
350
384
  signedTransaction,
351
385
  hopWallets: hopWalletInfos,
@@ -354,7 +388,214 @@ export async function bundleBatchSwap(params) {
354
388
  buyerAddresses: buyerWallets.map(w => w.address),
355
389
  sellAmount: ethers.formatUnits(sellAmountWei, tokenDecimals),
356
390
  estimatedBuyAmount: '0',
357
- profitAmount: '0',
391
+ profitAmount: ethers.formatEther(profitAmount),
358
392
  },
359
393
  };
360
394
  }
395
+ /**
396
+ * 多对多换手 - 多个卖家 + 多个买家
397
+ *
398
+ * 核心逻辑:[利润刮取] + [卖出Ops...] + [买入Ops...]
399
+ *
400
+ * 特点:
401
+ * - 多个卖家同时卖出
402
+ * - 多个买家同时买入
403
+ * - 所有操作在一笔交易中原子执行
404
+ * - 利润根据 userType 动态计算
405
+ *
406
+ * @example
407
+ * const result = await bundleMultiSwap({
408
+ * mainPrivateKey: '0x...', // Payer 支付 Gas
409
+ * sellerPrivateKeys: ['0x...', '0x...'],
410
+ * buyerPrivateKeys: ['0x...', '0x...'],
411
+ * totalBuyAmount: '0.1', // 总买入 0.1 OKB
412
+ * tokenAddress: '0x...',
413
+ * tradeType: 'V3',
414
+ * userType: 'v0',
415
+ * });
416
+ */
417
+ export async function bundleMultiSwap(params) {
418
+ const { mainPrivateKey, sellerPrivateKeys, buyerPrivateKeys, totalBuyAmount, tokenAddress, tokenDecimals = 18, sellPercent = 100, tradeType = 'V3', routerAddress, fee = V3_FEE_TIERS.MEDIUM, userType = 'v0', config, } = params;
419
+ // ✅ 验证私钥格式的辅助函数
420
+ const isValidPrivateKey = (pk) => {
421
+ const trimmed = (pk || '').trim();
422
+ return trimmed.length >= 64 && (trimmed.startsWith('0x') || /^[0-9a-fA-F]{64}$/.test(trimmed));
423
+ };
424
+ if (!mainPrivateKey || !isValidPrivateKey(mainPrivateKey)) {
425
+ throw new Error('必须提供有效的 mainPrivateKey(Payer 钱包私钥)');
426
+ }
427
+ // ✅ 验证卖家私钥
428
+ const validSellerPrivateKeys = sellerPrivateKeys.filter(pk => isValidPrivateKey(pk));
429
+ if (validSellerPrivateKeys.length === 0) {
430
+ throw new Error('没有有效的卖家私钥');
431
+ }
432
+ // ✅ 验证买家私钥
433
+ const validBuyerPrivateKeys = buyerPrivateKeys.filter(pk => isValidPrivateKey(pk));
434
+ if (validBuyerPrivateKeys.length === 0) {
435
+ throw new Error('没有有效的买家私钥');
436
+ }
437
+ if (validSellerPrivateKeys.length !== sellerPrivateKeys.length || validBuyerPrivateKeys.length !== buyerPrivateKeys.length) {
438
+ console.warn(`[bundleMultiSwap] 跳过无效私钥: 卖家 ${sellerPrivateKeys.length - validSellerPrivateKeys.length} 个, 买家 ${buyerPrivateKeys.length - validBuyerPrivateKeys.length} 个`);
439
+ }
440
+ const provider = getCachedProvider(config?.rpcUrl);
441
+ // ✅ 空字符串也使用默认值
442
+ const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
443
+ const delegateInterface = new ethers.Interface(UNIFIED_DELEGATE_ABI);
444
+ const portalInterface = new ethers.Interface(FLAP_PORTAL_ABI);
445
+ const actualRouter = routerAddress ?? getDefaultRouter(tradeType);
446
+ // ✅ 创建 Payer 钱包(支付 Gas 费)
447
+ const mainWallet = createWallet(mainPrivateKey, provider);
448
+ // 创建钱包
449
+ const sellerWallets = validSellerPrivateKeys.map(pk => createWallet(pk, provider));
450
+ const buyerWallets = validBuyerPrivateKeys.map(pk => createWallet(pk, provider));
451
+ // 合并所有钱包(去重,包括 mainWallet)
452
+ const allWalletsMap = new Map();
453
+ allWalletsMap.set(mainWallet.address.toLowerCase(), mainWallet);
454
+ sellerWallets.forEach(w => allWalletsMap.set(w.address.toLowerCase(), w));
455
+ buyerWallets.forEach(w => allWalletsMap.set(w.address.toLowerCase(), w));
456
+ const allWallets = Array.from(allWalletsMap.values());
457
+ // 找出 mainWallet 在 allWallets 中的索引
458
+ const mainWalletIndex = allWallets.findIndex(w => w.address.toLowerCase() === mainWallet.address.toLowerCase());
459
+ // 计算买入金额
460
+ const totalBuyAmountWei = ethers.parseEther(totalBuyAmount);
461
+ const buyAmountPerWallet = totalBuyAmountWei / BigInt(buyerWallets.length);
462
+ // ✅ 计算利润(根据 userType 和交易数量)
463
+ const totalTxCount = sellerWallets.length + buyerWallets.length;
464
+ const profitAmount = calculateProfitAmountByTxCount(totalBuyAmountWei, totalTxCount, userType);
465
+ const profitRecipient = getProfitRecipient(config);
466
+ // ========================================
467
+ // 并行获取数据
468
+ // ========================================
469
+ const allAddresses = allWallets.map(w => w.address);
470
+ // 获取卖出钱包的代币余额
471
+ const tokenContract = new ethers.Contract(tokenAddress, ERC20_ABI, provider);
472
+ const [nonces, feeData, sellerBalances] = await Promise.all([
473
+ batchGetNonces(allAddresses, provider),
474
+ provider.getFeeData(),
475
+ Promise.all(sellerWallets.map(w => tokenContract.balanceOf(w.address))),
476
+ ]);
477
+ // 计算每个卖家的卖出金额(按百分比)
478
+ const percentBigInt = BigInt(Math.min(100, Math.max(1, sellPercent)));
479
+ const sellAmountsWei = sellerBalances.map((balance) => (BigInt(balance.toString()) * percentBigInt) / 100n);
480
+ const totalSellAmount = sellAmountsWei.reduce((sum, amt) => sum + amt, 0n);
481
+ // ========================================
482
+ // 同步签署授权
483
+ // ========================================
484
+ const authorizations = signAuthorizationsWithNonces(allWallets, nonces, delegateAddress, mainWalletIndex);
485
+ // ========================================
486
+ // 构建调用
487
+ // ========================================
488
+ const calls = [];
489
+ // 利润刮取(从 Payer 钱包)
490
+ if (profitAmount > 0n) {
491
+ calls.push({
492
+ target: mainWallet.address,
493
+ allowFailure: false,
494
+ value: profitAmount,
495
+ callData: delegateInterface.encodeFunctionData('transferTo', [profitRecipient]),
496
+ });
497
+ }
498
+ // 卖出调用
499
+ for (let i = 0; i < sellerWallets.length; i++) {
500
+ if (sellAmountsWei[i] <= 0n)
501
+ continue;
502
+ const sellCall = buildSellCallWithAmountInternal(sellerWallets[i], sellAmountsWei[i], tokenAddress, tradeType, actualRouter, fee, delegateInterface, portalInterface);
503
+ calls.push(sellCall);
504
+ }
505
+ // 买入调用
506
+ for (let i = 0; i < buyerWallets.length; i++) {
507
+ const buyCall = buildBuyCallInternal(buyerWallets[i], buyAmountPerWallet, tokenAddress, tradeType, actualRouter, fee, delegateInterface, portalInterface);
508
+ calls.push(buyCall);
509
+ }
510
+ // ========================================
511
+ // 构建交易
512
+ // ========================================
513
+ const totalValue = totalBuyAmountWei + profitAmount;
514
+ const signedTransaction = buildEIP7702TransactionSync(mainWallet, authorizations, calls, totalValue, nonces[mainWalletIndex], feeData, config);
515
+ return {
516
+ signedTransaction,
517
+ metadata: {
518
+ payerAddress: mainWallet.address,
519
+ sellerAddresses: sellerWallets.map(w => w.address),
520
+ buyerAddresses: buyerWallets.map(w => w.address),
521
+ sellerCount: sellerWallets.filter((_, i) => sellAmountsWei[i] > 0n).length,
522
+ buyerCount: buyerWallets.length,
523
+ totalBuyAmount: ethers.formatEther(totalBuyAmountWei),
524
+ totalSellAmount: ethers.formatUnits(totalSellAmount, tokenDecimals),
525
+ profitAmount: ethers.formatEther(profitAmount),
526
+ profitRecipient,
527
+ userType,
528
+ },
529
+ };
530
+ }
531
+ // ========================================
532
+ // 内部工具函数
533
+ // ========================================
534
+ function buildBuyCallInternal(wallet, amount, tokenAddress, tradeType, routerAddress, fee, delegateInterface, portalInterface) {
535
+ switch (tradeType) {
536
+ case 'FLAP': {
537
+ const portalCallData = portalInterface.encodeFunctionData('buy', [tokenAddress]);
538
+ const batchCalls = [{ target: FLAP_PORTAL_ADDRESS, value: amount, data: portalCallData }];
539
+ return {
540
+ target: wallet.address,
541
+ allowFailure: false,
542
+ value: amount,
543
+ callData: delegateInterface.encodeFunctionData('executeBatch', [batchCalls]),
544
+ };
545
+ }
546
+ case 'V2': {
547
+ const path = [WOKB_ADDRESS, tokenAddress];
548
+ return {
549
+ target: wallet.address,
550
+ allowFailure: false,
551
+ value: amount,
552
+ callData: delegateInterface.encodeFunctionData('executeBuyV2', [routerAddress, path, 0]),
553
+ };
554
+ }
555
+ case 'V3': {
556
+ return {
557
+ target: wallet.address,
558
+ allowFailure: false,
559
+ value: amount,
560
+ callData: delegateInterface.encodeFunctionData('executeBuy', [
561
+ routerAddress, WOKB_ADDRESS, tokenAddress, fee, 0
562
+ ]),
563
+ };
564
+ }
565
+ }
566
+ }
567
+ function buildSellCallWithAmountInternal(wallet, amount, tokenAddress, tradeType, routerAddress, fee, delegateInterface, portalInterface) {
568
+ switch (tradeType) {
569
+ case 'FLAP': {
570
+ const portalCallData = portalInterface.encodeFunctionData('sell', [tokenAddress, amount, 0]);
571
+ const batchCalls = [{ target: FLAP_PORTAL_ADDRESS, value: 0n, data: portalCallData }];
572
+ return {
573
+ target: wallet.address,
574
+ allowFailure: false,
575
+ value: 0n,
576
+ callData: delegateInterface.encodeFunctionData('executeBatch', [batchCalls]),
577
+ };
578
+ }
579
+ case 'V2': {
580
+ const path = [tokenAddress, WOKB_ADDRESS];
581
+ return {
582
+ target: wallet.address,
583
+ allowFailure: false,
584
+ value: 0n,
585
+ // ✅ 传 0 让合约自动查询余额
586
+ callData: delegateInterface.encodeFunctionData('executeSellV2', [routerAddress, path, 0]),
587
+ };
588
+ }
589
+ case 'V3': {
590
+ return {
591
+ target: wallet.address,
592
+ allowFailure: false,
593
+ value: 0n,
594
+ // ✅ 传 0 让合约自动查询余额
595
+ callData: delegateInterface.encodeFunctionData('executeSell', [
596
+ routerAddress, tokenAddress, WOKB_ADDRESS, fee, 0
597
+ ]),
598
+ };
599
+ }
600
+ }
601
+ }
@@ -26,10 +26,18 @@ export declare const USDT0_ADDRESS = "0x779ded0c9e1022225f8e0630b35a9b54be713736
26
26
  export declare const PROFIT_CONFIG: {
27
27
  /** 利润接收地址 */
28
28
  readonly RECIPIENT: "0x8a365e4359247D7FdbE8a73B547566A03E4e9Ed8";
29
- /** 利润比例(基点):40 bps = 0.4% */
29
+ /** 利润比例(基点):40 bps = 0.4%(普通模式) */
30
30
  readonly RATE_BPS: 40;
31
31
  /** 利润比例(换手模式):6 bps = 0.06% */
32
32
  readonly RATE_BPS_SWAP: 6;
33
+ /** 利润比例(单边基点):8 bps = 0.08%(用户类型 v0) */
34
+ readonly RATE_BPS_V0: 8;
35
+ /** 利润比例(双边基点):4 bps = 0.04%(用户类型 v0) */
36
+ readonly RATE_BPS_V0_DOUBLE: 4;
37
+ /** 利润比例(单边基点):10 bps = 0.10%(用户类型 v1) */
38
+ readonly RATE_BPS_V1: 10;
39
+ /** 利润比例(双边基点):5 bps = 0.05%(用户类型 v1) */
40
+ readonly RATE_BPS_V1_DOUBLE: 5;
33
41
  };
34
42
  export declare const DEFAULT_GAS_LIMIT = 2000000n;
35
43
  export declare const DEFAULT_DEADLINE_MINUTES = 20;
@@ -38,10 +38,18 @@ export const USDT0_ADDRESS = '0x779ded0c9e1022225f8e0630b35a9b54be713736';
38
38
  export const PROFIT_CONFIG = {
39
39
  /** 利润接收地址 */
40
40
  RECIPIENT: '0x8a365e4359247D7FdbE8a73B547566A03E4e9Ed8',
41
- /** 利润比例(基点):40 bps = 0.4% */
41
+ /** 利润比例(基点):40 bps = 0.4%(普通模式) */
42
42
  RATE_BPS: 40,
43
43
  /** 利润比例(换手模式):6 bps = 0.06% */
44
44
  RATE_BPS_SWAP: 6,
45
+ /** 利润比例(单边基点):8 bps = 0.08%(用户类型 v0) */
46
+ RATE_BPS_V0: 8,
47
+ /** 利润比例(双边基点):4 bps = 0.04%(用户类型 v0) */
48
+ RATE_BPS_V0_DOUBLE: 4,
49
+ /** 利润比例(单边基点):10 bps = 0.10%(用户类型 v1) */
50
+ RATE_BPS_V1: 10,
51
+ /** 利润比例(双边基点):5 bps = 0.05%(用户类型 v1) */
52
+ RATE_BPS_V1_DOUBLE: 5,
45
53
  };
46
54
  // ========================================
47
55
  // 默认配置
@@ -15,20 +15,21 @@
15
15
  */
16
16
  export * from './constants.js';
17
17
  export * from './types.js';
18
- export { bigintToBytes, addressToBytes, hexToBytes, trimLeadingZeros, getCachedProvider, clearProviderCache, createWallet, generateRandomWallet, generateRandomWallets, signAuthorization, signAuthorizationWithNonce, signAuthorizationsBatch, buildEIP7702Transaction, calculateProfitAmount, getProfitRecipient, getDeadline, delay, } from './utils.js';
18
+ export { bigintToBytes, addressToBytes, hexToBytes, trimLeadingZeros, getCachedProvider, clearProviderCache, createWallet, generateRandomWallet, generateRandomWallets, signAuthorization, signAuthorizationWithNonce, signAuthorizationsBatch, buildEIP7702Transaction, calculateProfitAmount, calculateProfitAmountByUserType, calculateProfitAmountByTxCount, getProfitRateBps, getProfitRateBpsDouble, getProfitRecipient, getDeadline, delay, type UserType, } from './utils.js';
19
19
  export { bundleBuy, } from './bundle-buy.js';
20
20
  export { bundleSell, } from './bundle-sell.js';
21
- export { bundleSwap, bundleBatchSwap, } from './bundle-swap.js';
21
+ export { bundleSwap, bundleBatchSwap, bundleMultiSwap, type BundleMultiSwapParams, type BundleMultiSwapResult, } from './bundle-swap.js';
22
22
  export { disperse, sweep, pairwiseTransfer, disperseWithHops, sweepWithHops, type DisperseParams, type SweepParams, type PairwiseTransferParams, type PairwiseTransferResult, type TransferResult, } from './multi-hop-transfer.js';
23
23
  export { bundleApprove, checkApprovalStatus, } from './bundle-approve.js';
24
24
  export { bundleCreateBuy, bundleCreateToDex, bundleGraduateBuy, } from './bundle-create.js';
25
25
  export type { TokenInfo, CreateTokenParams, AmountMode, BundleCreateBuyParams, BundleCreateBuyResult, BundleCreateToDexParams, BundleCreateToDexResult, BundleGraduateBuyParams, BundleGraduateBuyResult, } from './types.js';
26
26
  export { washVolume, bundleVolume, singleRoundVolume, makeVolume, makeVolumeWithSwap, type VolumeMode, type PoolType, type VolumeProgress, type WashVolumeParams, type WashVolumeResult, type BundleVolumeParams, type BundleVolumeResult, type SingleRoundVolumeResult, type MakeVolumeParams, type MakeVolumeSignResult, type SwapVolumeSignResult, } from './volume.js';
27
27
  export declare const eip7702: {
28
- bundleBuy: (params: import("./types.js").BundleBuyParams) => Promise<import("./types.js").BundleBuyResult>;
29
- bundleSell: (params: import("./types.js").BundleSellParams) => Promise<import("./types.js").BundleSellResult>;
30
- bundleSwap: (params: import("./types.js").BundleSwapParams) => Promise<import("./types.js").BundleSwapResult>;
31
- bundleBatchSwap: (params: import("./types.js").BundleBatchSwapParams) => Promise<import("./types.js").BundleSwapResult>;
28
+ bundleBuy: (params: import("./bundle-buy.js").BundleBuyParams) => Promise<import("./types.js").BundleBuyResult>;
29
+ bundleSell: (params: import("./bundle-sell.js").BundleSellParams) => Promise<import("./types.js").BundleSellResult>;
30
+ bundleSwap: (params: import("./bundle-swap.js").BundleSwapParams) => Promise<import("./types.js").BundleSwapResult>;
31
+ bundleBatchSwap: (params: import("./bundle-swap.js").BundleBatchSwapParams) => Promise<import("./types.js").BundleSwapResult>;
32
+ bundleMultiSwap: (params: import("./bundle-swap.js").BundleMultiSwapParams) => Promise<import("./bundle-swap.js").BundleMultiSwapResult>;
32
33
  disperse: (params: import("./multi-hop-transfer.js").DisperseParams) => Promise<import("./multi-hop-transfer.js").TransferResult>;
33
34
  sweep: (params: import("./multi-hop-transfer.js").SweepParams) => Promise<import("./multi-hop-transfer.js").TransferResult>;
34
35
  pairwiseTransfer: (params: import("./multi-hop-transfer.js").PairwiseTransferParams) => Promise<import("./multi-hop-transfer.js").PairwiseTransferResult>;
@@ -24,7 +24,7 @@ export * from './types.js';
24
24
  // ============================================================================
25
25
  // 工具函数
26
26
  // ============================================================================
27
- export { bigintToBytes, addressToBytes, hexToBytes, trimLeadingZeros, getCachedProvider, clearProviderCache, createWallet, generateRandomWallet, generateRandomWallets, signAuthorization, signAuthorizationWithNonce, signAuthorizationsBatch, buildEIP7702Transaction, calculateProfitAmount, getProfitRecipient, getDeadline, delay, } from './utils.js';
27
+ export { bigintToBytes, addressToBytes, hexToBytes, trimLeadingZeros, getCachedProvider, clearProviderCache, createWallet, generateRandomWallet, generateRandomWallets, signAuthorization, signAuthorizationWithNonce, signAuthorizationsBatch, buildEIP7702Transaction, calculateProfitAmount, calculateProfitAmountByUserType, calculateProfitAmountByTxCount, getProfitRateBps, getProfitRateBpsDouble, getProfitRecipient, getDeadline, delay, } from './utils.js';
28
28
  // ============================================================================
29
29
  // 批量买入
30
30
  // ============================================================================
@@ -36,7 +36,7 @@ export { bundleSell, } from './bundle-sell.js';
36
36
  // ============================================================================
37
37
  // 捆绑换手
38
38
  // ============================================================================
39
- export { bundleSwap, bundleBatchSwap, } from './bundle-swap.js';
39
+ export { bundleSwap, bundleBatchSwap, bundleMultiSwap, } from './bundle-swap.js';
40
40
  // ============================================================================
41
41
  // 转账功能(分散/归集/多对多)
42
42
  // ============================================================================
@@ -96,6 +96,10 @@ export const eip7702 = {
96
96
  const { bundleBatchSwap } = await import('./bundle-swap.js');
97
97
  return bundleBatchSwap(...args);
98
98
  },
99
+ bundleMultiSwap: async (...args) => {
100
+ const { bundleMultiSwap } = await import('./bundle-swap.js');
101
+ return bundleMultiSwap(...args);
102
+ },
99
103
  // 转账功能
100
104
  disperse: async (...args) => {
101
105
  const { disperse } = await import('./multi-hop-transfer.js');
@@ -34,7 +34,39 @@ export declare function buildEIP7702TransactionSync(mainWallet: Wallet, authoriz
34
34
  maxPriorityFeePerGas: bigint | null;
35
35
  maxFeePerGas: bigint | null;
36
36
  }, config?: EIP7702Config): string;
37
+ export type UserType = 'v0' | 'v1' | 'default';
38
+ /**
39
+ * 根据用户类型获取利润率(单边模式)
40
+ * - v0: 8 bps = 0.08%
41
+ * - v1: 10 bps = 0.10%
42
+ * - default: 8 bps = 0.08%
43
+ */
44
+ export declare function getProfitRateBps(userType?: UserType): number;
45
+ /**
46
+ * 根据用户类型获取利润率(双边/换手模式)
47
+ * - v0: 4 bps = 0.04%
48
+ * - v1: 5 bps = 0.05%
49
+ * - default: 4 bps = 0.04%
50
+ */
51
+ export declare function getProfitRateBpsDouble(userType?: UserType): number;
52
+ /**
53
+ * 计算利润金额(旧版兼容)
54
+ */
37
55
  export declare function calculateProfitAmount(totalFlowWei: bigint, isSwapMode?: boolean): bigint;
56
+ /**
57
+ * 计算利润金额(基于用户类型)
58
+ * @param totalFlowWei 总资金流水
59
+ * @param userType 用户类型
60
+ * @param isDoubleMode 是否双边模式(换手模式)
61
+ */
62
+ export declare function calculateProfitAmountByUserType(totalFlowWei: bigint, userType?: UserType, isDoubleMode?: boolean): bigint;
63
+ /**
64
+ * 根据交易数量计算利润金额
65
+ * @param totalFlowWei 总资金流水
66
+ * @param txCount 交易数量
67
+ * @param userType 用户类型
68
+ */
69
+ export declare function calculateProfitAmountByTxCount(totalFlowWei: bigint, txCount: number, userType?: UserType): bigint;
38
70
  export declare function getProfitRecipient(config?: EIP7702Config): string;
39
71
  export declare function getDeadline(minutes?: number): number;
40
72
  export declare function delay(ms: number): Promise<void>;
@@ -266,13 +266,64 @@ export function buildEIP7702TransactionSync(mainWallet, authorizations, calls, t
266
266
  signedTx.set(signedRlp, 1);
267
267
  return ethers.hexlify(signedTx);
268
268
  }
269
- // ========================================
270
- // 利润计算
271
- // ========================================
269
+ /**
270
+ * 根据用户类型获取利润率(单边模式)
271
+ * - v0: 8 bps = 0.08%
272
+ * - v1: 10 bps = 0.10%
273
+ * - default: 8 bps = 0.08%
274
+ */
275
+ export function getProfitRateBps(userType) {
276
+ if (userType === 'v0')
277
+ return PROFIT_CONFIG.RATE_BPS_V0;
278
+ if (userType === 'v1')
279
+ return PROFIT_CONFIG.RATE_BPS_V1;
280
+ return PROFIT_CONFIG.RATE_BPS_V0; // 默认使用 v0 费率
281
+ }
282
+ /**
283
+ * 根据用户类型获取利润率(双边/换手模式)
284
+ * - v0: 4 bps = 0.04%
285
+ * - v1: 5 bps = 0.05%
286
+ * - default: 4 bps = 0.04%
287
+ */
288
+ export function getProfitRateBpsDouble(userType) {
289
+ if (userType === 'v0')
290
+ return PROFIT_CONFIG.RATE_BPS_V0_DOUBLE;
291
+ if (userType === 'v1')
292
+ return PROFIT_CONFIG.RATE_BPS_V1_DOUBLE;
293
+ return PROFIT_CONFIG.RATE_BPS_V0_DOUBLE; // 默认使用 v0 费率
294
+ }
295
+ /**
296
+ * 计算利润金额(旧版兼容)
297
+ */
272
298
  export function calculateProfitAmount(totalFlowWei, isSwapMode = false) {
273
299
  const rateBps = isSwapMode ? PROFIT_CONFIG.RATE_BPS_SWAP : PROFIT_CONFIG.RATE_BPS;
274
300
  return (totalFlowWei * BigInt(rateBps)) / 10000n;
275
301
  }
302
+ /**
303
+ * 计算利润金额(基于用户类型)
304
+ * @param totalFlowWei 总资金流水
305
+ * @param userType 用户类型
306
+ * @param isDoubleMode 是否双边模式(换手模式)
307
+ */
308
+ export function calculateProfitAmountByUserType(totalFlowWei, userType, isDoubleMode = false) {
309
+ if (totalFlowWei <= 0n)
310
+ return 0n;
311
+ const rateBps = isDoubleMode ? getProfitRateBpsDouble(userType) : getProfitRateBps(userType);
312
+ return (totalFlowWei * BigInt(rateBps)) / 10000n;
313
+ }
314
+ /**
315
+ * 根据交易数量计算利润金额
316
+ * @param totalFlowWei 总资金流水
317
+ * @param txCount 交易数量
318
+ * @param userType 用户类型
319
+ */
320
+ export function calculateProfitAmountByTxCount(totalFlowWei, txCount, userType) {
321
+ if (totalFlowWei <= 0n || txCount <= 0)
322
+ return 0n;
323
+ const rateBpsPerTx = getProfitRateBps(userType);
324
+ const totalRateBps = rateBpsPerTx * txCount;
325
+ return (totalFlowWei * BigInt(totalRateBps)) / 10000n;
326
+ }
276
327
  export function getProfitRecipient(config) {
277
328
  return config?.profitRecipient ?? PROFIT_CONFIG.RECIPIENT;
278
329
  }
@@ -13,6 +13,7 @@
13
13
  * 只生成签名,由调用方决定如何提交
14
14
  */
15
15
  import type { EIP7702Config, TradeType, GeneratedWallet } from './types.js';
16
+ import { type UserType } from './utils.js';
16
17
  export type VolumeMode = 'wash' | 'bundle';
17
18
  export type PoolType = 'FLAP' | 'V2' | 'V3';
18
19
  export interface VolumeProgress {
@@ -40,6 +41,8 @@ export interface WashVolumeParams {
40
41
  routerAddress?: string;
41
42
  /** V3 费率 */
42
43
  fee?: number;
44
+ /** 用户类型(影响利润率) */
45
+ userType?: UserType;
43
46
  /** EIP-7702 配置 */
44
47
  config?: EIP7702Config;
45
48
  }
@@ -97,6 +100,8 @@ export interface BundleVolumeParams {
97
100
  routerAddress?: string;
98
101
  /** V3 费率 */
99
102
  fee?: number;
103
+ /** 用户类型(影响利润率) */
104
+ userType?: UserType;
100
105
  /** EIP-7702 配置 */
101
106
  config?: EIP7702Config;
102
107
  }
@@ -13,7 +13,7 @@
13
13
  * 只生成签名,由调用方决定如何提交
14
14
  */
15
15
  import { ethers } from 'ethers';
16
- import { getCachedProvider, createWallet, signAuthorizationsWithNonces, batchGetNonces, buildEIP7702TransactionSync, calculateProfitAmount, getProfitRecipient, } from './utils.js';
16
+ import { getCachedProvider, createWallet, signAuthorizationsWithNonces, batchGetNonces, buildEIP7702TransactionSync, calculateProfitAmountByTxCount, getProfitRecipient, } from './utils.js';
17
17
  import { UNIFIED_DELEGATE_ADDRESS, UNIFIED_DELEGATE_ABI, FLAP_PORTAL_ABI, FLAP_PORTAL_ADDRESS, POTATOSWAP_V2_ROUTER, POTATOSWAP_V3_ROUTER, WOKB_ADDRESS, V3_FEE_TIERS, ERC20_ABI, } from './constants.js';
18
18
  import { bundleBuy } from './bundle-buy.js';
19
19
  import { bundleSell } from './bundle-sell.js';
@@ -38,7 +38,8 @@ import { bundleSwap } from './bundle-swap.js';
38
38
  * });
39
39
  */
40
40
  export async function washVolume(params) {
41
- const { mainPrivateKey, privateKeys, tokenAddress, tokenDecimals = 18, buyAmountPerWallet, sellPercent = 100, poolType = 'V3', routerAddress, fee = V3_FEE_TIERS.MEDIUM, config, } = params;
41
+ const { mainPrivateKey, privateKeys, tokenAddress, tokenDecimals = 18, buyAmountPerWallet, sellPercent = 100, poolType = 'V3', routerAddress, fee = V3_FEE_TIERS.MEDIUM, userType = 'v0', // 用户类型(影响利润率)
42
+ config, } = params;
42
43
  if (!mainPrivateKey) {
43
44
  throw new Error('必须提供 mainPrivateKey(Payer 钱包私钥)');
44
45
  }
@@ -73,10 +74,11 @@ export async function washVolume(params) {
73
74
  const mainWallet = createWallet(mainPrivateKey, provider);
74
75
  // 创建交易钱包(使用验证后的私钥)
75
76
  const wallets = actualPrivateKeys.map(pk => createWallet(pk, provider));
76
- // 计算金额
77
+ // 计算金额(无币刷量:每个钱包 1买 + 1卖 = 2笔交易)
77
78
  const buyAmountWei = ethers.parseEther(buyAmountPerWallet);
78
79
  const totalBuyAmount = buyAmountWei * BigInt(wallets.length);
79
- const profitAmount = calculateProfitAmount(totalBuyAmount);
80
+ const totalTxCount = wallets.length * 2; // 每个钱包 1买 + 1卖
81
+ const profitAmount = calculateProfitAmountByTxCount(totalBuyAmount, totalTxCount, userType);
80
82
  const profitRecipient = getProfitRecipient(config);
81
83
  // ========================================
82
84
  // 合并所有钱包(去重)
@@ -163,7 +165,8 @@ export async function washVolume(params) {
163
165
  * });
164
166
  */
165
167
  export async function bundleVolume(params) {
166
- const { mainPrivateKey, buyerPrivateKeys, buyAmounts, sellerPrivateKeys, sellAmounts, sellPercent = 100, tokenAddress, tokenDecimals = 18, poolType = 'V3', routerAddress, fee = V3_FEE_TIERS.MEDIUM, config, } = params;
168
+ const { mainPrivateKey, buyerPrivateKeys, buyAmounts, sellerPrivateKeys, sellAmounts, sellPercent = 100, tokenAddress, tokenDecimals = 18, poolType = 'V3', routerAddress, fee = V3_FEE_TIERS.MEDIUM, userType = 'v0', // 用户类型(影响利润率)
169
+ config, } = params;
167
170
  // ✅ 验证私钥格式的辅助函数
168
171
  const isValidPrivateKey = (pk) => {
169
172
  const trimmed = (pk || '').trim();
@@ -216,8 +219,9 @@ export async function bundleVolume(params) {
216
219
  // 计算买入金额(使用验证后的金额数组)
217
220
  const buyAmountsWei = validBuyAmounts.map(amt => ethers.parseEther(amt));
218
221
  const totalBuyAmount = buyAmountsWei.reduce((sum, amt) => sum + amt, 0n);
219
- // 计算利润
220
- const profitAmount = calculateProfitAmount(totalBuyAmount);
222
+ // ✅ 计算利润(捆绑刷量:买家数 + 卖家数 = 总交易数)
223
+ const totalTxCount = buyerWallets.length + sellerWallets.length;
224
+ const profitAmount = calculateProfitAmountByTxCount(totalBuyAmount, totalTxCount, userType);
221
225
  const profitRecipient = getProfitRecipient(config);
222
226
  // ========================================
223
227
  // 并行获取数据
package/dist/index.d.ts CHANGED
@@ -59,4 +59,4 @@ type XLayerEoaSwapConfig, type XLayerQuickBatchSwapParams, type XLayerQuickBatch
59
59
  type XLayerPureCrossSwapResult, // ✅ 真正的交叉换手结果
60
60
  type BuyFirstParams as XLayerBuyFirstParams, type BuyFirstResult as XLayerBuyFirstResult, type BuyFirstVolumeParams as XLayerBuyFirstVolumeParams, type BuyFirstVolumeResult as XLayerBuyFirstVolumeResult, type HandleOpsResult as XLayerHandleOpsResult, type AAAccount as XLayerAAAccount, type UserOperation as XLayerUserOperation, type GeneratedAAWallet as XLayerGeneratedAAWallet, type GenerateAAWalletsParams as XLayerGenerateAAWalletsParams, type GenerateAAWalletsResult as XLayerGenerateAAWalletsResult, } from './xlayer/index.js';
61
61
  export * as XLayerEIP7702 from './eip7702/xlayer/index.js';
62
- export { bundleBuy as xlayerEip7702BundleBuy, bundleSell as xlayerEip7702BundleSell, bundleApprove as xlayerEip7702BundleApprove, bundleSwap as xlayerEip7702BundleSwap, bundleBatchSwap as xlayerEip7702BundleBatchSwap, disperse as xlayerEip7702Disperse, sweep as xlayerEip7702Sweep, pairwiseTransfer as xlayerEip7702PairwiseTransfer, disperseWithHops as xlayerEip7702DisperseWithHops, sweepWithHops as xlayerEip7702SweepWithHops, washVolume as xlayerEip7702WashVolume, bundleVolume as xlayerEip7702BundleVolume, singleRoundVolume as xlayerEip7702SingleRoundVolume, makeVolume as xlayerEip7702MakeVolume, makeVolumeWithSwap as xlayerEip7702MakeVolumeWithSwap, checkApprovalStatus as xlayerEip7702CheckApprovalStatus, getProfitRecipient as xlayerEip7702GetProfitRecipient, calculateProfitAmount as xlayerEip7702CalculateProfitAmount, buildEIP7702Transaction as xlayerEip7702BuildTransaction, signAuthorization as xlayerEip7702SignAuthorization, signAuthorizationsBatch as xlayerEip7702SignAuthorizationsBatch, UNIFIED_DELEGATE_ADDRESS as XLAYER_EIP7702_DELEGATE_ADDRESS, MULTICALL3_ADDRESS as XLAYER_EIP7702_MULTICALL3, PROFIT_CONFIG as XLAYER_EIP7702_PROFIT_CONFIG, WOKB_ADDRESS as XLAYER_EIP7702_WOKB_ADDRESS, POTATOSWAP_V2_ROUTER as XLAYER_EIP7702_V2_ROUTER, POTATOSWAP_V3_ROUTER as XLAYER_EIP7702_V3_ROUTER, DYORSWAP_ROUTER as XLAYER_EIP7702_DYORSWAP_ROUTER, FLAP_PORTAL_ADDRESS as XLAYER_EIP7702_FLAP_PORTAL, type BundleBuyParams as XLayerEip7702BundleBuyParams, type BundleBuyResult as XLayerEip7702BundleBuyResult, type BundleSellParams as XLayerEip7702BundleSellParams, type BundleSellResult as XLayerEip7702BundleSellResult, type BundleApproveParams as XLayerEip7702BundleApproveParams, type BundleApproveResult as XLayerEip7702BundleApproveResult, type BundleSwapParams as XLayerEip7702BundleSwapParams, type BundleSwapResult as XLayerEip7702BundleSwapResult, type DisperseParams as XLayerEip7702DisperseParams, type SweepParams as XLayerEip7702SweepParams, type PairwiseTransferParams as XLayerEip7702PairwiseTransferParams, type PairwiseTransferResult as XLayerEip7702PairwiseTransferResult, type TransferResult as XLayerEip7702TransferResult, type WashVolumeParams as XLayerEip7702WashVolumeParams, type WashVolumeResult as XLayerEip7702WashVolumeResult, type BundleVolumeParams as XLayerEip7702BundleVolumeParams, type BundleVolumeResult as XLayerEip7702BundleVolumeResult, type MakeVolumeParams as XLayerEip7702MakeVolumeParams, type MakeVolumeSignResult as XLayerEip7702MakeVolumeResult, type VolumeMode as XLayerEip7702VolumeMode, type PoolType as XLayerEip7702PoolType, type VolumeProgress as XLayerEip7702VolumeProgress, type EIP7702Config as XLayerEip7702Config, type UserType as XLayerEip7702UserType, type Authorization as XLayerEip7702Authorization, type Call3Value as XLayerEip7702Call, type GeneratedWallet as XLayerEip7702GeneratedWallet, type TradeType as XLayerEip7702TradeType, type RouterType as XLayerEip7702RouterType, bundleCreateBuy as xlayerEip7702BundleCreateBuy, bundleCreateToDex as xlayerEip7702BundleCreateToDex, bundleGraduateBuy as xlayerEip7702BundleGraduateBuy, type TokenInfo as XLayerEip7702TokenInfo, type CreateTokenParams as XLayerEip7702CreateTokenParams, type AmountMode as XLayerEip7702AmountMode, type BundleCreateBuyParams as XLayerEip7702BundleCreateBuyParams, type BundleCreateBuyResult as XLayerEip7702BundleCreateBuyResult, type BundleCreateToDexParams as XLayerEip7702BundleCreateToDexParams, type BundleCreateToDexResult as XLayerEip7702BundleCreateToDexResult, type BundleGraduateBuyParams as XLayerEip7702BundleGraduateBuyParams, type BundleGraduateBuyResult as XLayerEip7702BundleGraduateBuyResult, } from './eip7702/xlayer/index.js';
62
+ export { bundleBuy as xlayerEip7702BundleBuy, bundleSell as xlayerEip7702BundleSell, bundleApprove as xlayerEip7702BundleApprove, bundleSwap as xlayerEip7702BundleSwap, bundleBatchSwap as xlayerEip7702BundleBatchSwap, bundleMultiSwap as xlayerEip7702BundleMultiSwap, disperse as xlayerEip7702Disperse, sweep as xlayerEip7702Sweep, pairwiseTransfer as xlayerEip7702PairwiseTransfer, disperseWithHops as xlayerEip7702DisperseWithHops, sweepWithHops as xlayerEip7702SweepWithHops, washVolume as xlayerEip7702WashVolume, bundleVolume as xlayerEip7702BundleVolume, singleRoundVolume as xlayerEip7702SingleRoundVolume, makeVolume as xlayerEip7702MakeVolume, makeVolumeWithSwap as xlayerEip7702MakeVolumeWithSwap, checkApprovalStatus as xlayerEip7702CheckApprovalStatus, getProfitRecipient as xlayerEip7702GetProfitRecipient, calculateProfitAmount as xlayerEip7702CalculateProfitAmount, calculateProfitAmountByUserType as xlayerEip7702CalculateProfitAmountByUserType, calculateProfitAmountByTxCount as xlayerEip7702CalculateProfitAmountByTxCount, getProfitRateBps as xlayerEip7702GetProfitRateBps, getProfitRateBpsDouble as xlayerEip7702GetProfitRateBpsDouble, buildEIP7702Transaction as xlayerEip7702BuildTransaction, signAuthorization as xlayerEip7702SignAuthorization, signAuthorizationsBatch as xlayerEip7702SignAuthorizationsBatch, UNIFIED_DELEGATE_ADDRESS as XLAYER_EIP7702_DELEGATE_ADDRESS, MULTICALL3_ADDRESS as XLAYER_EIP7702_MULTICALL3, PROFIT_CONFIG as XLAYER_EIP7702_PROFIT_CONFIG, WOKB_ADDRESS as XLAYER_EIP7702_WOKB_ADDRESS, POTATOSWAP_V2_ROUTER as XLAYER_EIP7702_V2_ROUTER, POTATOSWAP_V3_ROUTER as XLAYER_EIP7702_V3_ROUTER, DYORSWAP_ROUTER as XLAYER_EIP7702_DYORSWAP_ROUTER, FLAP_PORTAL_ADDRESS as XLAYER_EIP7702_FLAP_PORTAL, type BundleBuyParams as XLayerEip7702BundleBuyParams, type BundleBuyResult as XLayerEip7702BundleBuyResult, type BundleSellParams as XLayerEip7702BundleSellParams, type BundleSellResult as XLayerEip7702BundleSellResult, type BundleApproveParams as XLayerEip7702BundleApproveParams, type BundleApproveResult as XLayerEip7702BundleApproveResult, type BundleSwapParams as XLayerEip7702BundleSwapParams, type BundleSwapResult as XLayerEip7702BundleSwapResult, type BundleMultiSwapParams as XLayerEip7702BundleMultiSwapParams, type BundleMultiSwapResult as XLayerEip7702BundleMultiSwapResult, type UserType as XLayerEip7702UserType, type DisperseParams as XLayerEip7702DisperseParams, type SweepParams as XLayerEip7702SweepParams, type PairwiseTransferParams as XLayerEip7702PairwiseTransferParams, type PairwiseTransferResult as XLayerEip7702PairwiseTransferResult, type TransferResult as XLayerEip7702TransferResult, type WashVolumeParams as XLayerEip7702WashVolumeParams, type WashVolumeResult as XLayerEip7702WashVolumeResult, type BundleVolumeParams as XLayerEip7702BundleVolumeParams, type BundleVolumeResult as XLayerEip7702BundleVolumeResult, type MakeVolumeParams as XLayerEip7702MakeVolumeParams, type MakeVolumeSignResult as XLayerEip7702MakeVolumeResult, type VolumeMode as XLayerEip7702VolumeMode, type PoolType as XLayerEip7702PoolType, type VolumeProgress as XLayerEip7702VolumeProgress, type EIP7702Config as XLayerEip7702Config, type Authorization as XLayerEip7702Authorization, type Call3Value as XLayerEip7702Call, type GeneratedWallet as XLayerEip7702GeneratedWallet, type TradeType as XLayerEip7702TradeType, type RouterType as XLayerEip7702RouterType, bundleCreateBuy as xlayerEip7702BundleCreateBuy, bundleCreateToDex as xlayerEip7702BundleCreateToDex, bundleGraduateBuy as xlayerEip7702BundleGraduateBuy, type TokenInfo as XLayerEip7702TokenInfo, type CreateTokenParams as XLayerEip7702CreateTokenParams, type AmountMode as XLayerEip7702AmountMode, type BundleCreateBuyParams as XLayerEip7702BundleCreateBuyParams, type BundleCreateBuyResult as XLayerEip7702BundleCreateBuyResult, type BundleCreateToDexParams as XLayerEip7702BundleCreateToDexParams, type BundleCreateToDexResult as XLayerEip7702BundleCreateToDexResult, type BundleGraduateBuyParams as XLayerEip7702BundleGraduateBuyParams, type BundleGraduateBuyResult as XLayerEip7702BundleGraduateBuyResult, } from './eip7702/xlayer/index.js';
package/dist/index.js CHANGED
@@ -142,7 +142,7 @@ xlayerQuickBatchSwapMerkle, xlayerCrossSwapMerkle, xlayerPureCrossSwapMerkle, //
142
142
  // ============================================================
143
143
  export * as XLayerEIP7702 from './eip7702/xlayer/index.js';
144
144
  // EIP-7702 批量操作(注意使用 eip7702 前缀避免与 AA 模式冲突)
145
- export { bundleBuy as xlayerEip7702BundleBuy, bundleSell as xlayerEip7702BundleSell, bundleApprove as xlayerEip7702BundleApprove, bundleSwap as xlayerEip7702BundleSwap, bundleBatchSwap as xlayerEip7702BundleBatchSwap,
145
+ export { bundleBuy as xlayerEip7702BundleBuy, bundleSell as xlayerEip7702BundleSell, bundleApprove as xlayerEip7702BundleApprove, bundleSwap as xlayerEip7702BundleSwap, bundleBatchSwap as xlayerEip7702BundleBatchSwap, bundleMultiSwap as xlayerEip7702BundleMultiSwap,
146
146
  // 转账功能
147
147
  disperse as xlayerEip7702Disperse, sweep as xlayerEip7702Sweep, pairwiseTransfer as xlayerEip7702PairwiseTransfer,
148
148
  // 向后兼容
@@ -150,7 +150,7 @@ disperseWithHops as xlayerEip7702DisperseWithHops, sweepWithHops as xlayerEip770
150
150
  // 刷量
151
151
  washVolume as xlayerEip7702WashVolume, bundleVolume as xlayerEip7702BundleVolume, singleRoundVolume as xlayerEip7702SingleRoundVolume, makeVolume as xlayerEip7702MakeVolume, makeVolumeWithSwap as xlayerEip7702MakeVolumeWithSwap,
152
152
  // 工具函数
153
- checkApprovalStatus as xlayerEip7702CheckApprovalStatus, getProfitRecipient as xlayerEip7702GetProfitRecipient, calculateProfitAmount as xlayerEip7702CalculateProfitAmount, buildEIP7702Transaction as xlayerEip7702BuildTransaction, signAuthorization as xlayerEip7702SignAuthorization, signAuthorizationsBatch as xlayerEip7702SignAuthorizationsBatch,
153
+ checkApprovalStatus as xlayerEip7702CheckApprovalStatus, getProfitRecipient as xlayerEip7702GetProfitRecipient, calculateProfitAmount as xlayerEip7702CalculateProfitAmount, calculateProfitAmountByUserType as xlayerEip7702CalculateProfitAmountByUserType, calculateProfitAmountByTxCount as xlayerEip7702CalculateProfitAmountByTxCount, getProfitRateBps as xlayerEip7702GetProfitRateBps, getProfitRateBpsDouble as xlayerEip7702GetProfitRateBpsDouble, buildEIP7702Transaction as xlayerEip7702BuildTransaction, signAuthorization as xlayerEip7702SignAuthorization, signAuthorizationsBatch as xlayerEip7702SignAuthorizationsBatch,
154
154
  // 常量
155
155
  UNIFIED_DELEGATE_ADDRESS as XLAYER_EIP7702_DELEGATE_ADDRESS, MULTICALL3_ADDRESS as XLAYER_EIP7702_MULTICALL3, PROFIT_CONFIG as XLAYER_EIP7702_PROFIT_CONFIG, WOKB_ADDRESS as XLAYER_EIP7702_WOKB_ADDRESS, POTATOSWAP_V2_ROUTER as XLAYER_EIP7702_V2_ROUTER, POTATOSWAP_V3_ROUTER as XLAYER_EIP7702_V3_ROUTER, DYORSWAP_ROUTER as XLAYER_EIP7702_DYORSWAP_ROUTER, FLAP_PORTAL_ADDRESS as XLAYER_EIP7702_FLAP_PORTAL,
156
156
  // 代币创建与发射
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.7.21",
3
+ "version": "1.7.22",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",