four-flap-meme-sdk 1.3.80 → 1.3.81

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.
@@ -21,5 +21,6 @@ export type ApproveFourTokenManagerBatchResult = {
21
21
  * ✅ 不需要 Merkle API Key,使用普通 RPC 即可
22
22
  * ✅ 专门用于授权给 TokenManagerOriginal 合约
23
23
  * ✅ 用于 fourBatchPrivateSell 和 fourBatchSellWithBundleMerkle
24
+ * ✅ 优化:并行获取 gasPrice、decimals、allowances
24
25
  */
25
26
  export declare function approveFourTokenManagerBatch(params: ApproveFourTokenManagerBatchParams): Promise<ApproveFourTokenManagerBatchResult>;
@@ -15,6 +15,7 @@ const ERC20_ABI = [
15
15
  * ✅ 不需要 Merkle API Key,使用普通 RPC 即可
16
16
  * ✅ 专门用于授权给 TokenManagerOriginal 合约
17
17
  * ✅ 用于 fourBatchPrivateSell 和 fourBatchSellWithBundleMerkle
18
+ * ✅ 优化:并行获取 gasPrice、decimals、allowances
18
19
  */
19
20
  export async function approveFourTokenManagerBatch(params) {
20
21
  const { privateKeys, tokenAddress, amounts, config } = params;
@@ -28,27 +29,25 @@ export async function approveFourTokenManagerBatch(params) {
28
29
  chainId: chainId,
29
30
  name: 'BSC'
30
31
  });
31
- const gasPrice = await getOptimizedGasPrice(provider, getGasPriceConfig(config));
32
- // ✅ 优化:如果所有金额都是 'max',则不需要查询 decimals
33
- const allMax = amounts.every(a => a === 'max');
34
- let decimals = 18; // 默认值
35
- if (!allMax) {
36
- try {
37
- const tokenContract = new ethers.Contract(tokenAddress, ERC20_ABI, provider);
38
- decimals = await tokenContract.decimals();
39
- }
40
- catch (error) {
41
- throw new Error(`查询代币 decimals 失败: ${error.message}`);
42
- }
43
- }
44
32
  const wallets = privateKeys.map(k => new Wallet(k, provider));
33
+ const allMax = amounts.every(a => a === 'max');
34
+ // ✅ 优化:并行获取 gasPrice、decimals(如果需要)、allowances
35
+ const [gasPrice, decimals, allowances] = await Promise.all([
36
+ getOptimizedGasPrice(provider, getGasPriceConfig(config)),
37
+ allMax
38
+ ? Promise.resolve(18) // 如果都是 'max',不需要查询 decimals
39
+ : (async () => {
40
+ try {
41
+ const tokenContract = new ethers.Contract(tokenAddress, ERC20_ABI, provider);
42
+ return await tokenContract.decimals();
43
+ }
44
+ catch (error) {
45
+ throw new Error(`查询代币 decimals 失败: ${error.message}`);
46
+ }
47
+ })(),
48
+ batchCheckAllowances(provider, tokenAddress, wallets.map(w => w.address), tmAddr)
49
+ ]);
45
50
  const amountsBigInt = amounts.map(a => a === 'max' ? ethers.MaxUint256 : ethers.parseUnits(a, decimals));
46
- // ✅ 检查是否有非 'max' 的授权
47
- const hasNonMaxAmount = amounts.some(a => a !== 'max');
48
- if (hasNonMaxAmount) {
49
- }
50
- // 检查现有授权,过滤掉已经足够的
51
- const allowances = await batchCheckAllowances(provider, tokenAddress, wallets.map(w => w.address), tmAddr);
52
51
  // 只授权不足的
53
52
  // ✅ 策略:如果授权额度 < MaxUint256 / 2n,就重新授权(确保授权足够大)
54
53
  const APPROVAL_THRESHOLD = ethers.MaxUint256 / 2n;
@@ -64,10 +63,7 @@ export async function approveFourTokenManagerBatch(params) {
64
63
  message: '所有钱包已授权,无需重复授权'
65
64
  };
66
65
  }
67
- // 构建授权交易
68
- const needApprovalTokens = needApproval.map(w => new ethers.Contract(tokenAddress, ERC20_ABI, w));
69
- const unsignedApprovals = await Promise.all(needApprovalTokens.map((token, i) => token.approve.populateTransaction(tmAddr, needApprovalAmounts[i])));
70
- // 使用前端传入的 gasLimit,否则使用默认值
66
+ // ✅ 优化:计算 gasLimit(不需要 RPC)
71
67
  const getGasLimit = (cfg) => {
72
68
  if (cfg.gasLimit)
73
69
  return BigInt(cfg.gasLimit);
@@ -76,9 +72,15 @@ export async function approveFourTokenManagerBatch(params) {
76
72
  return 60000n; // 默认授权 gas limit
77
73
  };
78
74
  const finalGasLimit = getGasLimit(config);
79
- // 签名授权交易
75
+ const txType = getTxType(config);
76
+ // ✅ 优化:并行获取 nonces 和构建未签名交易
80
77
  const nonceManager = new NonceManager(provider);
81
- const nonces = await Promise.all(needApproval.map(w => nonceManager.getNextNonce(w)));
78
+ const needApprovalTokens = needApproval.map(w => new ethers.Contract(tokenAddress, ERC20_ABI, w));
79
+ const [nonces, unsignedApprovals] = await Promise.all([
80
+ nonceManager.getNextNoncesForWallets(needApproval), // ✅ 批量获取 nonces(JSON-RPC 批量请求)
81
+ Promise.all(needApprovalTokens.map((token, i) => token.approve.populateTransaction(tmAddr, needApprovalAmounts[i])))
82
+ ]);
83
+ // ✅ 并行签名所有授权交易
82
84
  const signedTxs = await Promise.all(unsignedApprovals.map((unsigned, i) => needApproval[i].signTransaction({
83
85
  ...unsigned,
84
86
  from: needApproval[i].address,
@@ -86,14 +88,14 @@ export async function approveFourTokenManagerBatch(params) {
86
88
  gasLimit: finalGasLimit,
87
89
  gasPrice,
88
90
  chainId,
89
- type: getTxType(config)
91
+ type: txType
90
92
  })));
91
93
  nonceManager.clearTemp();
92
94
  try {
93
- // 广播所有授权交易
95
+ // ✅ 并行广播所有授权交易
94
96
  const txResponses = await Promise.all(signedTxs.map(tx => provider.broadcastTransaction(tx)));
95
97
  const txHashes = txResponses.map(r => r.hash);
96
- // 等待所有授权交易确认(至少1个确认)
98
+ // ✅ 并行等待所有授权交易确认(至少1个确认)
97
99
  await Promise.all(txResponses.map(tx => tx.wait(1)));
98
100
  return {
99
101
  success: true,
@@ -1,8 +1,16 @@
1
1
  import { JsonRpcProvider } from 'ethers';
2
2
  import type { AmountLike } from './types.js';
3
- export declare function getErc20DecimalsMerkle(provider: JsonRpcProvider, token: string): Promise<number>;
3
+ /**
4
+ * 获取 ERC20 代币精度(带缓存)
5
+ * ✅ 优化:避免每次调用都获取 network,使用 provider._network 或传入 chainId
6
+ */
7
+ export declare function getErc20DecimalsMerkle(provider: JsonRpcProvider, token: string, chainId?: number): Promise<number>;
4
8
  export declare function generateHopWallets(recipientCount: number, hopCount: number | number[]): string[][] | null;
5
9
  export declare function normalizeAmounts(recipients: string[], amount?: AmountLike, amounts?: AmountLike[]): string[];
10
+ /**
11
+ * 批量获取余额(原生代币或 ERC20)
12
+ * ✅ 优化:原生代币也使用 Multicall3 批量获取,减少 RPC 调用
13
+ */
6
14
  export declare function batchGetBalances(provider: JsonRpcProvider, addresses: string[], tokenAddress?: string): Promise<bigint[]>;
7
15
  export declare function calculateGasLimit(config: any, isNative: boolean, hasHops: boolean, hopCount?: number): bigint;
8
16
  export declare function isNativeTokenAddress(tokenAddress?: string): boolean;
@@ -1,9 +1,14 @@
1
1
  import { ethers, Wallet } from 'ethers';
2
2
  // 内部缓存:ERC20 小数位
3
3
  const decimalsCache = new Map();
4
- export async function getErc20DecimalsMerkle(provider, token) {
5
- const network = await provider.getNetwork();
6
- const key = `${network.chainId}_${token.toLowerCase()}`;
4
+ /**
5
+ * 获取 ERC20 代币精度(带缓存)
6
+ * 优化:避免每次调用都获取 network,使用 provider._network 或传入 chainId
7
+ */
8
+ export async function getErc20DecimalsMerkle(provider, token, chainId) {
9
+ // ✅ 优化:优先使用传入的 chainId,其次使用 provider 内部缓存的 network
10
+ const resolvedChainId = chainId ?? (provider._network?.chainId ? Number(provider._network.chainId) : 56);
11
+ const key = `${resolvedChainId}_${token.toLowerCase()}`;
7
12
  if (decimalsCache.has(key))
8
13
  return decimalsCache.get(key);
9
14
  try {
@@ -44,18 +49,49 @@ export function normalizeAmounts(recipients, amount, amounts) {
44
49
  }
45
50
  throw new Error('Either amount or amounts must be provided');
46
51
  }
52
+ /**
53
+ * 批量获取余额(原生代币或 ERC20)
54
+ * ✅ 优化:原生代币也使用 Multicall3 批量获取,减少 RPC 调用
55
+ */
47
56
  export async function batchGetBalances(provider, addresses, tokenAddress) {
48
57
  if (addresses.length === 0)
49
58
  return [];
59
+ const MULTICALL3_ADDRESS = '0xcA11bde05977b3631167028862bE2a173976CA11';
60
+ const MULTICALL3_ABI = [
61
+ 'function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) view returns (tuple(bool success, bytes returnData)[] returnData)',
62
+ 'function getEthBalance(address addr) view returns (uint256 balance)' // ✅ 新增:原生代币余额查询
63
+ ];
64
+ const multicall = new ethers.Contract(MULTICALL3_ADDRESS, MULTICALL3_ABI, provider);
50
65
  if (!tokenAddress) {
51
- return Promise.all(addresses.map(addr => provider.getBalance(addr).catch(() => 0n)));
66
+ // 优化:原生代币使用 Multicall3.getEthBalance 批量获取(单次 RPC 调用)
67
+ const multicallIface = new ethers.Interface(MULTICALL3_ABI);
68
+ const calls = addresses.map(addr => ({
69
+ target: MULTICALL3_ADDRESS,
70
+ allowFailure: true,
71
+ callData: multicallIface.encodeFunctionData('getEthBalance', [addr])
72
+ }));
73
+ try {
74
+ const results = await multicall.aggregate3(calls);
75
+ return results.map((result) => {
76
+ if (result.success && result.returnData && result.returnData !== '0x') {
77
+ try {
78
+ const decoded = multicallIface.decodeFunctionResult('getEthBalance', result.returnData);
79
+ return decoded[0];
80
+ }
81
+ catch {
82
+ return 0n;
83
+ }
84
+ }
85
+ return 0n;
86
+ });
87
+ }
88
+ catch {
89
+ // ✅ 回退:并行调用(如果 Multicall3 失败)
90
+ return Promise.all(addresses.map(addr => provider.getBalance(addr).catch(() => 0n)));
91
+ }
52
92
  }
53
93
  else {
54
- const MULTICALL3_ADDRESS = '0xcA11bde05977b3631167028862bE2a173976CA11';
55
- const MULTICALL3_ABI = [
56
- 'function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) view returns (tuple(bool success, bytes returnData)[] returnData)'
57
- ];
58
- const multicall = new ethers.Contract(MULTICALL3_ADDRESS, MULTICALL3_ABI, provider);
94
+ // ERC20 余额:使用 Multicall3 批量获取
59
95
  const ERC20_ABI = ['function balanceOf(address) view returns (uint256)'];
60
96
  const iface = new ethers.Interface(ERC20_ABI);
61
97
  const calls = addresses.map(addr => ({
@@ -66,13 +102,19 @@ export async function batchGetBalances(provider, addresses, tokenAddress) {
66
102
  try {
67
103
  const results = await multicall.aggregate3(calls);
68
104
  return results.map((result) => {
69
- if (result.success) {
70
- return iface.decodeFunctionResult('balanceOf', result.returnData)[0];
105
+ if (result.success && result.returnData && result.returnData !== '0x') {
106
+ try {
107
+ return iface.decodeFunctionResult('balanceOf', result.returnData)[0];
108
+ }
109
+ catch {
110
+ return 0n;
111
+ }
71
112
  }
72
113
  return 0n;
73
114
  });
74
115
  }
75
116
  catch {
117
+ // ✅ 回退:并行调用(如果 Multicall3 失败)
76
118
  const fallbackCalls = addresses.map(addr => provider
77
119
  .call({ to: tokenAddress, data: iface.encodeFunctionData('balanceOf', [addr]) })
78
120
  .then(raw => iface.decodeFunctionResult('balanceOf', raw)[0])
@@ -2,22 +2,26 @@ import { FourPrivateBuySignParams, FourPrivateSellSignParams, FourPrivateTransac
2
2
  /**
3
3
  * 私有购买(单笔)(仅签名版本 - 不依赖 Merkle)
4
4
  * ✅ 精简版:只负责签名交易,不提交到 Merkle
5
+ * ✅ 优化:并行获取 gasPrice 和 nonce
5
6
  */
6
7
  export declare function fourPrivateBuyMerkle(params: FourPrivateBuySignParams): Promise<FourPrivateTransactionResult>;
7
8
  /**
8
9
  * 私有卖出(单笔)(仅签名版本 - 不依赖 Merkle)
9
10
  * ✅ 精简版:只负责签名交易,不提交到 Merkle
10
11
  * ✅ 自动检查授权,智能处理授权+卖出
12
+ * ✅ 优化:并行获取 gasPrice、allowance、nonce
11
13
  */
12
14
  export declare function fourPrivateSellMerkle(params: FourPrivateSellSignParams): Promise<FourPrivateTransactionResult>;
13
15
  /**
14
16
  * 批量私有购买(仅签名版本 - 不依赖 Merkle)
15
17
  * ✅ 精简版:只负责签名交易,不提交到 Merkle
18
+ * ✅ 优化:并行获取 gasPrice 和 nonces,批量构建交易
16
19
  */
17
20
  export declare function fourBatchPrivateBuyMerkle(params: FourBatchPrivateBuySignParams): Promise<FourBatchPrivateMerkleResult>;
18
21
  /**
19
22
  * 批量私有卖出(仅签名版本 - 不依赖 Merkle)
20
23
  * ✅ 精简版:只负责签名交易,不提交到 Merkle
21
24
  * ✅ 自动包含授权交易,无需前端单独调用
25
+ * ✅ 优化:并行获取所有查询数据,批量获取 nonces
22
26
  */
23
27
  export declare function fourBatchPrivateSellMerkle(params: FourBatchPrivateSellSignParams): Promise<FourBatchPrivateMerkleResult>;
@@ -1,5 +1,4 @@
1
1
  import { ethers, Wallet } from 'ethers';
2
- // import { MerkleClient } from '../../clients/merkle.js';
3
2
  import { NonceManager, getOptimizedGasPrice } from '../../utils/bundle-helpers.js';
4
3
  import { ADDRESSES } from '../../utils/constants.js';
5
4
  import { getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, calculateBatchProfit, getProfitRecipient } from './config.js';
@@ -29,6 +28,7 @@ function getGasLimit(config, defaultGas = DEFAULT_GAS_LIMIT) {
29
28
  /**
30
29
  * 私有购买(单笔)(仅签名版本 - 不依赖 Merkle)
31
30
  * ✅ 精简版:只负责签名交易,不提交到 Merkle
31
+ * ✅ 优化:并行获取 gasPrice 和 nonce
32
32
  */
33
33
  export async function fourPrivateBuyMerkle(params) {
34
34
  const { privateKey, tokenAddress, funds, to, config } = params;
@@ -39,41 +39,40 @@ export async function fourPrivateBuyMerkle(params) {
39
39
  });
40
40
  const wallet = new Wallet(privateKey, provider);
41
41
  const tmAddr = ADDRESSES.BSC.TokenManagerOriginal;
42
- const gasPrice = await getOptimizedGasPrice(provider, getGasPriceConfig(config));
43
42
  const txType = getTxType(config);
44
43
  const gasLimit = getGasLimit(config);
45
44
  const originalFundsWei = ethers.parseEther(funds);
46
- // ✅ 利润提取配置
45
+ // ✅ 利润提取配置(同步计算)
47
46
  const extractProfit = shouldExtractProfit(config);
48
47
  let profitWei = 0n;
49
48
  let actualFundsWei = originalFundsWei;
50
49
  if (extractProfit) {
51
50
  const { profit, remaining } = calculateProfit(originalFundsWei, config);
52
51
  profitWei = profit;
53
- actualFundsWei = remaining; // ✅ 扣除利润后的金额用于购买
52
+ actualFundsWei = remaining;
54
53
  }
55
- const minAmount = 0n;
56
- const signedTxs = [];
57
54
  const tm2 = new ethers.Contract(tmAddr, TM2_ABI, wallet);
58
- // ✅ 使用 TokenManager2 原始方法:buyTokenAMAP
59
- const unsigned = await tm2.buyTokenAMAP.populateTransaction(0n, tokenAddress, to ?? wallet.address, actualFundsWei, minAmount, { value: actualFundsWei } // ✅ 使用扣除利润后的金额
60
- );
61
- let currentNonce = await wallet.getNonce();
62
- const req = {
63
- ...unsigned,
64
- from: wallet.address,
65
- nonce: currentNonce,
66
- gasLimit,
67
- gasPrice,
68
- chainId: CHAIN_ID,
69
- type: txType,
70
- value: actualFundsWei // ✅ funds = msg.value(合约要求两者相等)
71
- };
72
- const signed = await wallet.signTransaction(req);
73
- signedTxs.push(signed);
74
- // ✅ 添加利润转账
55
+ // ✅ 优化:并行获取 gasPrice、nonce 和构建未签名交易
56
+ const [gasPrice, currentNonce, unsigned] = await Promise.all([
57
+ getOptimizedGasPrice(provider, getGasPriceConfig(config)),
58
+ wallet.getNonce(),
59
+ tm2.buyTokenAMAP.populateTransaction(0n, tokenAddress, to ?? wallet.address, actualFundsWei, 0n, { value: actualFundsWei })
60
+ ]);
61
+ // ✅ 并行签名主交易和利润交易
62
+ const signPromises = [
63
+ wallet.signTransaction({
64
+ ...unsigned,
65
+ from: wallet.address,
66
+ nonce: currentNonce,
67
+ gasLimit,
68
+ gasPrice,
69
+ chainId: CHAIN_ID,
70
+ type: txType,
71
+ value: actualFundsWei
72
+ })
73
+ ];
75
74
  if (extractProfit && profitWei > 0n) {
76
- const profitTx = await wallet.signTransaction({
75
+ signPromises.push(wallet.signTransaction({
77
76
  to: getProfitRecipient(),
78
77
  value: profitWei,
79
78
  nonce: currentNonce + 1,
@@ -81,11 +80,9 @@ export async function fourPrivateBuyMerkle(params) {
81
80
  gasLimit: 21000n,
82
81
  chainId: CHAIN_ID,
83
82
  type: txType
84
- });
85
- signedTxs.push(profitTx);
83
+ }));
86
84
  }
87
- // 直接返回签名交易(不提交到Merkle)
88
- // ✅ 简化返回:只返回签名交易
85
+ const signedTxs = await Promise.all(signPromises);
89
86
  return {
90
87
  signedTransactions: signedTxs
91
88
  };
@@ -94,6 +91,7 @@ export async function fourPrivateBuyMerkle(params) {
94
91
  * 私有卖出(单笔)(仅签名版本 - 不依赖 Merkle)
95
92
  * ✅ 精简版:只负责签名交易,不提交到 Merkle
96
93
  * ✅ 自动检查授权,智能处理授权+卖出
94
+ * ✅ 优化:并行获取 gasPrice、allowance、nonce
97
95
  */
98
96
  export async function fourPrivateSellMerkle(params) {
99
97
  const { privateKey, tokenAddress, amount, minFunds, config } = params;
@@ -104,64 +102,52 @@ export async function fourPrivateSellMerkle(params) {
104
102
  });
105
103
  const wallet = new Wallet(privateKey, provider);
106
104
  const tmAddr = ADDRESSES.BSC.TokenManagerOriginal;
107
- const gasPrice = await getOptimizedGasPrice(provider, getGasPriceConfig(config));
108
105
  const txType = getTxType(config);
109
106
  const sellGasLimit = getGasLimit(config);
110
107
  const amountWei = ethers.parseUnits(amount, 18);
111
108
  const minOut = minFunds ?? 0n;
112
- // ✅ Step 1: 检查授权状态
113
109
  const tokenContract = new ethers.Contract(tokenAddress, ERC20_ABI, provider);
114
- const currentAllowance = await tokenContract.allowance(wallet.address, tmAddr);
115
- // 使用 MaxUint256 的一半作为阈值,确保能处理超大供应量代币
110
+ const tm2 = new ethers.Contract(tmAddr, TM2_ABI, wallet);
111
+ // 优化:并行获取 gasPrice、allowance、nonce 和构建未签名交易
112
+ const [gasPrice, currentAllowance, sellNonce, sellUnsigned] = await Promise.all([
113
+ getOptimizedGasPrice(provider, getGasPriceConfig(config)),
114
+ tokenContract.allowance(wallet.address, tmAddr),
115
+ wallet.getNonce(),
116
+ tm2.sellToken.populateTransaction(0n, tokenAddress, amountWei, minOut)
117
+ ]);
118
+ // ✅ 检查授权状态
116
119
  const APPROVAL_THRESHOLD = ethers.MaxUint256 / 2n;
117
- // ✅ Step 2: 如果需要授权,抛出错误提示
118
- // ⚠️ SDK不再处理授权,需要前端先单独授权
119
120
  if (currentAllowance < APPROVAL_THRESHOLD) {
120
121
  throw new Error(`需要授权:钱包 ${wallet.address} 尚未授权。请先完成授权后再卖出。`);
121
122
  }
122
- else {
123
- }
124
- // ✅ Step 3: 卖出交易
125
- const nonceManager = new NonceManager(provider);
126
- const signedTxs = [];
127
- const tm2 = new ethers.Contract(tmAddr, TM2_ABI, wallet);
128
- const sellUnsigned = await tm2.sellToken.populateTransaction(0n, tokenAddress, amountWei, minOut);
129
- const sellNonce = await nonceManager.getNextNonce(wallet);
130
- // ✅ 卖出交易 value 必须为 0,不能发送原生代币
131
- const sellReq = {
132
- ...sellUnsigned,
133
- from: wallet.address,
134
- nonce: sellNonce,
135
- gasLimit: sellGasLimit,
136
- gasPrice,
137
- chainId: CHAIN_ID,
138
- type: txType,
139
- value: 0n // ✅ 卖出交易不发送原生代币
140
- };
141
- const signedSell = await wallet.signTransaction(sellReq);
142
- signedTxs.push(signedSell);
143
- // ✅ 基于 minFunds 计算利润
123
+ // ✅ 利润计算(同步)
144
124
  const extractProfit = shouldExtractProfit(config);
145
- if (extractProfit) {
146
- const { profit } = calculateProfit(minOut, config);
147
- if (profit > 0n) {
148
- const profitNonce = await nonceManager.getNextNonce(wallet);
149
- const profitTx = await wallet.signTransaction({
150
- to: getProfitRecipient(),
151
- value: profit,
152
- nonce: profitNonce,
153
- gasPrice,
154
- gasLimit: 21000n,
155
- chainId: CHAIN_ID,
156
- type: txType
157
- });
158
- signedTxs.push(profitTx);
159
- }
125
+ const { profit } = extractProfit ? calculateProfit(minOut, config) : { profit: 0n };
126
+ // 并行签名主交易和利润交易
127
+ const signPromises = [
128
+ wallet.signTransaction({
129
+ ...sellUnsigned,
130
+ from: wallet.address,
131
+ nonce: sellNonce,
132
+ gasLimit: sellGasLimit,
133
+ gasPrice,
134
+ chainId: CHAIN_ID,
135
+ type: txType,
136
+ value: 0n
137
+ })
138
+ ];
139
+ if (extractProfit && profit > 0n) {
140
+ signPromises.push(wallet.signTransaction({
141
+ to: getProfitRecipient(),
142
+ value: profit,
143
+ nonce: sellNonce + 1,
144
+ gasPrice,
145
+ gasLimit: 21000n,
146
+ chainId: CHAIN_ID,
147
+ type: txType
148
+ }));
160
149
  }
161
- // 清理临时 nonce 缓存
162
- nonceManager.clearTemp();
163
- // ✅ 直接返回签名交易(不提交到Merkle)
164
- // ✅ 简化返回:只返回签名交易
150
+ const signedTxs = await Promise.all(signPromises);
165
151
  return {
166
152
  signedTransactions: signedTxs
167
153
  };
@@ -169,6 +155,7 @@ export async function fourPrivateSellMerkle(params) {
169
155
  /**
170
156
  * 批量私有购买(仅签名版本 - 不依赖 Merkle)
171
157
  * ✅ 精简版:只负责签名交易,不提交到 Merkle
158
+ * ✅ 优化:并行获取 gasPrice 和 nonces,批量构建交易
172
159
  */
173
160
  export async function fourBatchPrivateBuyMerkle(params) {
174
161
  const { privateKeys, fundsList, tokenAddress, config } = params;
@@ -181,18 +168,15 @@ export async function fourBatchPrivateBuyMerkle(params) {
181
168
  name: 'BSC'
182
169
  });
183
170
  const tmAddr = ADDRESSES.BSC.TokenManagerOriginal;
184
- const gasPrice = await getOptimizedGasPrice(provider, getGasPriceConfig(config));
185
171
  const txType = getTxType(config);
186
172
  const finalGasLimit = getGasLimit(config);
187
- const signedTxs = [];
188
- const nonceManager = new NonceManager(provider);
189
173
  const wallets = privateKeys.map((k) => new Wallet(k, provider));
190
174
  const originalAmountsWei = fundsList.map((a) => ethers.parseEther(a));
191
- // ✅ 利润提取配置
175
+ // ✅ 利润提取配置(同步计算)
192
176
  const extractProfit = shouldExtractProfit(config);
193
177
  const { totalProfit, remainingAmounts } = calculateBatchProfit(originalAmountsWei, config);
194
- const actualAmountsWei = remainingAmounts; // 扣除利润后用于购买的金额
195
- // ✅ 找出投入金额最多的钱包(作为利润支付者)
178
+ const actualAmountsWei = remainingAmounts;
179
+ // ✅ 找出投入金额最多的钱包(作为利润支付者)- 同步计算
196
180
  let maxFundsIndex = 0;
197
181
  let maxFunds = originalAmountsWei[0];
198
182
  for (let i = 1; i < originalAmountsWei.length; i++) {
@@ -202,51 +186,69 @@ export async function fourBatchPrivateBuyMerkle(params) {
202
186
  }
203
187
  }
204
188
  const tm2Contracts = wallets.map((w) => new ethers.Contract(tmAddr, TM2_ABI, w));
205
- // 使用 TokenManager2 原始方法:buyTokenAMAP(使用扣除利润后的金额)
206
- const unsignedList = await Promise.all(tm2Contracts.map((c, i) => c.buyTokenAMAP.populateTransaction(0n, tokenAddress, wallets[i].address, actualAmountsWei[i], 0n, { value: actualAmountsWei[i] })));
207
- const gasLimits = new Array(wallets.length).fill(finalGasLimit);
208
- // Nonce 管理:如果有利润,支付者需要 2 个 nonce(买入 + 利润)
209
- const nonces = [];
210
- for (let i = 0; i < wallets.length; i++) {
211
- if (extractProfit && i === maxFundsIndex && totalProfit > 0n) {
212
- // 支付者需要 2 个 nonce
213
- const [nonce] = await nonceManager.getNextNonceBatch(wallets[i], 2);
214
- nonces.push(nonce);
215
- }
216
- else {
217
- // 其他钱包只需要 1 nonce
218
- const nonce = await nonceManager.getNextNonce(wallets[i]);
219
- nonces.push(nonce);
220
- }
221
- }
189
+ const nonceManager = new NonceManager(provider);
190
+ const needProfitTx = extractProfit && totalProfit > 0n;
191
+ // 优化:并行获取 gasPrice、nonces 和构建未签名交易
192
+ // 支付者需要 2 个 nonce,其他钱包各需要 1 个 nonce
193
+ const [gasPrice, unsignedList, noncesResult] = await Promise.all([
194
+ getOptimizedGasPrice(provider, getGasPriceConfig(config)),
195
+ Promise.all(tm2Contracts.map((c, i) => c.buyTokenAMAP.populateTransaction(0n, tokenAddress, wallets[i].address, actualAmountsWei[i], 0n, { value: actualAmountsWei[i] }))),
196
+ (async () => {
197
+ if (needProfitTx) {
198
+ // 支付者需要 2 个连续 nonce
199
+ const payerNonces = await nonceManager.getNextNonceBatch(wallets[maxFundsIndex], 2);
200
+ // 其他钱包各需要 1 个 nonce
201
+ const otherWallets = wallets.filter((_, i) => i !== maxFundsIndex);
202
+ const otherNonces = otherWallets.length > 0
203
+ ? await nonceManager.getNextNoncesForWallets(otherWallets)
204
+ : [];
205
+ // 组装最终的 nonces 数组(保持原顺序)
206
+ const nonces = [];
207
+ let otherIdx = 0;
208
+ for (let i = 0; i < wallets.length; i++) {
209
+ if (i === maxFundsIndex) {
210
+ nonces.push(payerNonces[0]);
211
+ }
212
+ else {
213
+ nonces.push(otherNonces[otherIdx++]);
214
+ }
215
+ }
216
+ return { nonces, profitNonce: payerNonces[1] };
217
+ }
218
+ else {
219
+ // 所有钱包各 1 个 nonce
220
+ const nonces = await nonceManager.getNextNoncesForWallets(wallets);
221
+ return { nonces, profitNonce: undefined };
222
+ }
223
+ })()
224
+ ]);
225
+ const { nonces, profitNonce } = noncesResult;
226
+ // ✅ 并行签名所有买入交易
222
227
  const signedList = await Promise.all(unsignedList.map((unsigned, i) => wallets[i].signTransaction({
223
228
  ...unsigned,
224
229
  from: wallets[i].address,
225
230
  nonce: nonces[i],
226
- gasLimit: gasLimits[i],
231
+ gasLimit: finalGasLimit,
227
232
  gasPrice,
228
233
  chainId: CHAIN_ID,
229
234
  type: txType,
230
- value: actualAmountsWei[i] // ✅ funds = msg.value(合约要求两者相等)
235
+ value: actualAmountsWei[i]
231
236
  })));
232
- signedTxs.push(...signedList);
237
+ const signedTxs = [...signedList];
233
238
  // ✅ 聚合利润:由投入金额最多的钱包支付所有利润(1笔交易)
234
- if (extractProfit && totalProfit > 0n) {
235
- const profitNonce = nonces[maxFundsIndex] + 1;
239
+ if (needProfitTx && profitNonce !== undefined) {
236
240
  const profitTx = await wallets[maxFundsIndex].signTransaction({
237
241
  to: getProfitRecipient(),
238
242
  value: totalProfit,
239
243
  nonce: profitNonce,
240
244
  gasPrice,
241
245
  gasLimit: 21000n,
242
- chainId: 56,
243
- type: getTxType(config)
246
+ chainId: CHAIN_ID,
247
+ type: txType
244
248
  });
245
249
  signedTxs.push(profitTx);
246
250
  }
247
- // ✅ 清理临时 nonce 缓存
248
251
  nonceManager.clearTemp();
249
- // ✅ 简化返回:只返回签名交易
250
252
  return {
251
253
  signedTransactions: signedTxs
252
254
  };
@@ -255,6 +257,7 @@ export async function fourBatchPrivateBuyMerkle(params) {
255
257
  * 批量私有卖出(仅签名版本 - 不依赖 Merkle)
256
258
  * ✅ 精简版:只负责签名交易,不提交到 Merkle
257
259
  * ✅ 自动包含授权交易,无需前端单独调用
260
+ * ✅ 优化:并行获取所有查询数据,批量获取 nonces
258
261
  */
259
262
  export async function fourBatchPrivateSellMerkle(params) {
260
263
  const { privateKeys, amounts, tokenAddress, config, minFundsEach } = params;
@@ -267,73 +270,64 @@ export async function fourBatchPrivateSellMerkle(params) {
267
270
  name: 'BSC'
268
271
  });
269
272
  const tmAddr = ADDRESSES.BSC.TokenManagerOriginal;
270
- const gasPrice = await getOptimizedGasPrice(provider, getGasPriceConfig(config));
271
273
  const txType = getTxType(config);
272
274
  const sellGasLimit = getGasLimit(config);
273
- const signedTxs = [];
274
- const nonceManager = new NonceManager(provider);
275
275
  const wallets = privateKeys.map((k) => new Wallet(k, provider));
276
276
  const amountsWei = amounts.map((a) => ethers.parseUnits(a, 18));
277
- // 自动获取每个钱包的预期收益(用于利润计算和滑点保护)
278
- let quotedOutputs;
279
- let minOuts;
280
- if (minFundsEach !== undefined) {
281
- // 用户提供了 minFundsEach,所有钱包使用相同的 minOut
282
- const minOutWei = typeof minFundsEach === 'string' ? ethers.parseEther(minFundsEach) : minFundsEach;
283
- minOuts = new Array(wallets.length).fill(minOutWei);
284
- quotedOutputs = minOuts.map(m => m * 100n / 95n);
285
- }
286
- else {
287
- // 自动调用 trySell 获取每个钱包的预期收益
288
- const rpcUrl = config.rpcUrl;
289
- quotedOutputs = await Promise.all(amountsWei.map(async (amount, i) => {
290
- try {
291
- const result = await trySell('BSC', rpcUrl, tokenAddress, amount);
292
- return result.funds;
293
- }
294
- catch (error) {
295
- return 0n;
296
- }
297
- }));
298
- // minOuts = 0,不设置滑点限制(大额交易更稳定)
299
- minOuts = quotedOutputs.map(() => 0n);
300
- }
301
- // ✅ Step 0: 检查代币余额
302
- const tokenContract = new ethers.Contract(tokenAddress, ERC20_ABI, provider);
303
- const balances = await Promise.all(wallets.map(w => tokenContract.balanceOf(w.address)));
277
+ const rpcUrl = config.rpcUrl;
278
+ // ✅ 优化:第一批并行获取 - gasPrice、quotedOutputs、balances、allowances、bnbBalances
279
+ const [gasPrice, quotedOutputs, balances, allowances, bnbBalances] = await Promise.all([
280
+ getOptimizedGasPrice(provider, getGasPriceConfig(config)),
281
+ // 获取预期收益
282
+ minFundsEach !== undefined
283
+ ? Promise.resolve((() => {
284
+ const minOutWei = typeof minFundsEach === 'string' ? ethers.parseEther(minFundsEach) : minFundsEach;
285
+ return new Array(wallets.length).fill(minOutWei * 100n / 95n);
286
+ })())
287
+ : Promise.all(amountsWei.map(async (amount) => {
288
+ try {
289
+ const result = await trySell('BSC', rpcUrl, tokenAddress, amount);
290
+ return result.funds;
291
+ }
292
+ catch {
293
+ return 0n;
294
+ }
295
+ })),
296
+ // 检查代币余额
297
+ (async () => {
298
+ const tokenContract = new ethers.Contract(tokenAddress, ERC20_ABI, provider);
299
+ return Promise.all(wallets.map(w => tokenContract.balanceOf(w.address)));
300
+ })(),
301
+ // 检查授权状态
302
+ batchCheckAllowances(provider, tokenAddress, wallets.map(w => w.address), tmAddr),
303
+ // 检查 BNB 余额
304
+ Promise.all(wallets.map(w => provider.getBalance(w.address)))
305
+ ]);
306
+ // 计算 minOuts
307
+ const minOuts = minFundsEach !== undefined
308
+ ? new Array(wallets.length).fill(typeof minFundsEach === 'string' ? ethers.parseEther(minFundsEach) : minFundsEach)
309
+ : quotedOutputs.map(() => 0n);
310
+ // ✅ 验证代币余额
304
311
  for (let i = 0; i < wallets.length; i++) {
305
312
  if (balances[i] < amountsWei[i]) {
306
- throw new Error(`钱包 ${i} 代币余额不足:` +
307
- `需要 ${ethers.formatUnits(amountsWei[i], 18)},` +
308
- `实际 ${ethers.formatUnits(balances[i], 18)}`);
309
- }
310
- }
311
- // ✅ Step 1: 检查授权状态
312
- const allowances = await batchCheckAllowances(provider, tokenAddress, wallets.map(w => w.address), tmAddr);
313
- const needApprovalIndexes = [];
314
- for (let i = 0; i < wallets.length; i++) {
315
- if (allowances[i] < amountsWei[i]) {
316
- needApprovalIndexes.push(i);
313
+ throw new Error(`钱包 ${i} 代币余额不足:需要 ${ethers.formatUnits(amountsWei[i], 18)},实际 ${ethers.formatUnits(balances[i], 18)}`);
317
314
  }
318
315
  }
316
+ // ✅ 验证授权状态
317
+ const needApprovalIndexes = wallets
318
+ .map((_, i) => i)
319
+ .filter(i => allowances[i] < amountsWei[i]);
319
320
  if (needApprovalIndexes.length > 0) {
320
- throw new Error(`${needApprovalIndexes.length} 个钱包需要授权。` +
321
- `请先调用 approveFourTokenManagerBatch({ amounts: ['max', ...] })`);
321
+ throw new Error(`${needApprovalIndexes.length} 个钱包需要授权。请先调用 approveFourTokenManagerBatch({ amounts: ['max', ...] })`);
322
322
  }
323
- // ✅ Step 2: 检查 BNB 余额(用于支付 gas)
324
- const bnbBalances = await Promise.all(wallets.map(w => provider.getBalance(w.address)));
323
+ // ✅ 验证 BNB 余额
325
324
  const estimatedGasCost = sellGasLimit * gasPrice;
326
325
  for (let i = 0; i < wallets.length; i++) {
327
326
  if (bnbBalances[i] < estimatedGasCost) {
328
- throw new Error(`钱包 ${i} BNB 不足:` +
329
- `需要 ${ethers.formatEther(estimatedGasCost)} BNB,` +
330
- `实际 ${ethers.formatEther(bnbBalances[i])} BNB`);
327
+ throw new Error(`钱包 ${i} BNB 不足:需要 ${ethers.formatEther(estimatedGasCost)} BNB,实际 ${ethers.formatEther(bnbBalances[i])} BNB`);
331
328
  }
332
329
  }
333
- // ✅ Step 3: 构建卖出交易
334
- const tm2Contracts = wallets.map((w) => new ethers.Contract(tmAddr, TM2_ABI, w));
335
- const sellUnsigned = await Promise.all(tm2Contracts.map((c, i) => c.sellToken.populateTransaction(0n, tokenAddress, amountsWei[i], minOuts[i])));
336
- // ✅ 计算总利润和找出收益最高的钱包
330
+ // ✅ 计算总利润和找出收益最高的钱包(同步计算)
337
331
  const extractProfit = shouldExtractProfit(config);
338
332
  let totalProfit = 0n;
339
333
  let maxRevenueIndex = 0;
@@ -350,37 +344,56 @@ export async function fourBatchPrivateSellMerkle(params) {
350
344
  }
351
345
  }
352
346
  }
353
- // Nonce 管理:如果有利润,支付者需要 2 nonce(卖出 + 利润)
354
- const sellNonces = [];
355
- for (let i = 0; i < wallets.length; i++) {
356
- if (extractProfit && i === maxRevenueIndex && totalProfit > 0n) {
357
- // 支付者需要 2 nonce
358
- const [nonce] = await nonceManager.getNextNonceBatch(wallets[i], 2);
359
- sellNonces.push(nonce);
360
- }
361
- else {
362
- // 其他钱包只需要 1 nonce
363
- const nonce = await nonceManager.getNextNonce(wallets[i]);
364
- sellNonces.push(nonce);
365
- }
366
- }
367
- // ✅ 签名所有卖出交易
368
- // 卖出交易 value 必须为 0,不能发送原生代币
369
- const sellGasLimits = new Array(wallets.length).fill(sellGasLimit);
347
+ const tm2Contracts = wallets.map((w) => new ethers.Contract(tmAddr, TM2_ABI, w));
348
+ const nonceManager = new NonceManager(provider);
349
+ const needProfitTx = extractProfit && totalProfit > 0n;
350
+ // 优化:第二批并行获取 - nonces 和构建未签名交易
351
+ const [sellUnsigned, noncesResult] = await Promise.all([
352
+ Promise.all(tm2Contracts.map((c, i) => c.sellToken.populateTransaction(0n, tokenAddress, amountsWei[i], minOuts[i]))),
353
+ (async () => {
354
+ if (needProfitTx) {
355
+ // 支付者需要 2 个连续 nonce
356
+ const payerNonces = await nonceManager.getNextNonceBatch(wallets[maxRevenueIndex], 2);
357
+ // 其他钱包各需要 1 nonce
358
+ const otherWallets = wallets.filter((_, i) => i !== maxRevenueIndex);
359
+ const otherNonces = otherWallets.length > 0
360
+ ? await nonceManager.getNextNoncesForWallets(otherWallets)
361
+ : [];
362
+ // 组装最终的 nonces 数组(保持原顺序)
363
+ const nonces = [];
364
+ let otherIdx = 0;
365
+ for (let i = 0; i < wallets.length; i++) {
366
+ if (i === maxRevenueIndex) {
367
+ nonces.push(payerNonces[0]);
368
+ }
369
+ else {
370
+ nonces.push(otherNonces[otherIdx++]);
371
+ }
372
+ }
373
+ return { nonces, profitNonce: payerNonces[1] };
374
+ }
375
+ else {
376
+ // 所有钱包各 1 个 nonce
377
+ const nonces = await nonceManager.getNextNoncesForWallets(wallets);
378
+ return { nonces, profitNonce: undefined };
379
+ }
380
+ })()
381
+ ]);
382
+ const { nonces, profitNonce } = noncesResult;
383
+ // ✅ 并行签名所有卖出交易
370
384
  const signedSells = await Promise.all(sellUnsigned.map((unsigned, i) => wallets[i].signTransaction({
371
385
  ...unsigned,
372
386
  from: wallets[i].address,
373
- nonce: sellNonces[i],
374
- gasLimit: sellGasLimits[i],
387
+ nonce: nonces[i],
388
+ gasLimit: sellGasLimit,
375
389
  gasPrice,
376
390
  chainId: CHAIN_ID,
377
391
  type: txType,
378
- value: 0n // ✅ 卖出交易不发送原生代币
392
+ value: 0n
379
393
  })));
380
- signedTxs.push(...signedSells);
394
+ const signedTxs = [...signedSells];
381
395
  // ✅ 聚合利润:由收益最高的钱包支付所有利润(1笔交易)
382
- if (extractProfit && totalProfit > 0n) {
383
- const profitNonce = sellNonces[maxRevenueIndex] + 1;
396
+ if (needProfitTx && profitNonce !== undefined) {
384
397
  const profitTx = await wallets[maxRevenueIndex].signTransaction({
385
398
  to: getProfitRecipient(),
386
399
  value: totalProfit,
@@ -393,7 +406,6 @@ export async function fourBatchPrivateSellMerkle(params) {
393
406
  signedTxs.push(profitTx);
394
407
  }
395
408
  nonceManager.clearTemp();
396
- // ✅ 简化返回:只返回签名交易
397
409
  return {
398
410
  signedTransactions: signedTxs
399
411
  };
@@ -224,9 +224,9 @@ export interface DirectSubmitResult {
224
224
  errorSummary?: string;
225
225
  }
226
226
  /**
227
- * 逐笔广播到 RPC(用于不支持 Bundle 的链,如 Monad)
227
+ * 并行广播到 RPC(用于不支持 Bundle 的链,如 Monad)
228
228
  *
229
- * 这个方法接收前端构建和签名好的交易,逐笔广播到 RPC 节点
229
+ * 优化:默认使用并行广播,速度更快
230
230
  *
231
231
  * @param signedTransactions 签名后的交易数组
232
232
  * @param config 直接广播配置
@@ -251,9 +251,9 @@ export async function submitMultipleBundlesToBlockRazorParallel(bundles, config)
251
251
  return await Promise.all(promises);
252
252
  }
253
253
  /**
254
- * 逐笔广播到 RPC(用于不支持 Bundle 的链,如 Monad)
254
+ * 并行广播到 RPC(用于不支持 Bundle 的链,如 Monad)
255
255
  *
256
- * 这个方法接收前端构建和签名好的交易,逐笔广播到 RPC 节点
256
+ * 优化:默认使用并行广播,速度更快
257
257
  *
258
258
  * @param signedTransactions 签名后的交易数组
259
259
  * @param config 直接广播配置
@@ -308,21 +308,10 @@ export async function submitDirectToRpc(signedTransactions, config) {
308
308
  chainId,
309
309
  name: chainName
310
310
  });
311
- const results = [];
312
- const txHashes = [];
313
- const errors = [];
314
- // 逐笔广播
315
- for (let i = 0; i < signedTransactions.length; i++) {
316
- const signedTx = signedTransactions[i];
311
+ // 并行广播所有交易
312
+ const broadcastPromises = signedTransactions.map(async (signedTx, i) => {
317
313
  try {
318
- // 广播交易
319
314
  const txResponse = await provider.broadcastTransaction(signedTx);
320
- results.push({
321
- index: i,
322
- success: true,
323
- txHash: txResponse.hash
324
- });
325
- txHashes.push(txResponse.hash);
326
315
  // 如果需要等待确认
327
316
  if (config.waitForConfirmation) {
328
317
  try {
@@ -335,18 +324,27 @@ export async function submitDirectToRpc(signedTransactions, config) {
335
324
  console.warn(`⚠️ [${chainName}] 等待交易确认超时: ${txResponse.hash}`);
336
325
  }
337
326
  }
327
+ return {
328
+ index: i,
329
+ success: true,
330
+ txHash: txResponse.hash
331
+ };
338
332
  }
339
333
  catch (error) {
340
334
  const errorMessage = error?.message || String(error);
341
- results.push({
335
+ console.error(`❌ [${chainName}] 交易 ${i + 1}/${totalTransactions} 广播失败:`, errorMessage);
336
+ return {
342
337
  index: i,
343
338
  success: false,
344
339
  error: errorMessage
345
- });
346
- errors.push(`交易 ${i + 1}: ${errorMessage}`);
347
- console.error(`❌ [${chainName}] 交易 ${i + 1}/${totalTransactions} 广播失败:`, errorMessage);
340
+ };
348
341
  }
349
- }
342
+ });
343
+ const results = await Promise.all(broadcastPromises);
344
+ // 按索引排序结果
345
+ results.sort((a, b) => a.index - b.index);
346
+ const txHashes = results.filter(r => r.success && r.txHash).map(r => r.txHash);
347
+ const errors = results.filter(r => !r.success).map(r => `交易 ${r.index + 1}: ${r.error}`);
350
348
  const successCount = txHashes.length;
351
349
  const failedCount = totalTransactions - successCount;
352
350
  return {
@@ -229,7 +229,7 @@ export async function batchBuyWithBundleMerkle(params) {
229
229
  resolveGasPrice(provider, config),
230
230
  populateBuyTransactionsWithQuote(buyers, FLAP_PORTAL_ADDRESSES[chain], tokenAddress, adjustedFundsList, inputToken, useNativeToken),
231
231
  presetNonces && presetNonces.length === buyers.length
232
- ? adjustNoncesForProfit(presetNonces, extractProfit, maxFundsIndex, nativeProfitAmount) // ✅ 调整 nonces 避免冲突
232
+ ? adjustNoncesForProfit(presetNonces) // ✅ 调整 nonces 避免冲突
233
233
  : allocateBuyerNonces(buyers, extractProfit, maxFundsIndex, nativeProfitAmount, nonceManager)
234
234
  ]);
235
235
  if (presetNonces) {
@@ -316,7 +316,7 @@ export async function batchSellWithBundleMerkle(params) {
316
316
  let profitNonce;
317
317
  if (presetNonces && presetNonces.length === wallets.length) {
318
318
  // ✅ 使用前端传入的 nonces,但需要调整避免利润交易冲突
319
- nonces = adjustNoncesForProfit(presetNonces, extractProfit, maxRevenueIndex, totalTokenProfit);
319
+ nonces = adjustNoncesForProfit(presetNonces);
320
320
  profitNonce = needProfitTx ? presetNonces[maxRevenueIndex] + 1 : undefined;
321
321
  }
322
322
  else if (needProfitTx) {
@@ -488,7 +488,7 @@ function buildGasLimitList(length, config) {
488
488
  * - 每个钱包使用自己的 nonce 发送买入交易
489
489
  * - 利润交易使用 maxIndex 钱包的 nonce + 1(在构建利润交易时处理)
490
490
  */
491
- function adjustNoncesForProfit(presetNonces, extractProfit, maxIndex, totalProfit) {
491
+ function adjustNoncesForProfit(presetNonces) {
492
492
  // ✅ 直接返回原始 nonces,不做任何调整
493
493
  // 不同钱包的 nonce 是独立的,不会冲突
494
494
  return presetNonces;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.3.80",
3
+ "version": "1.3.81",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",