four-flap-meme-sdk 1.3.93 → 1.3.94

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.
Files changed (127) hide show
  1. package/dist/clients/blockrazor.js +1 -0
  2. package/dist/contracts/tm-bundle-merkle/config.d.ts +0 -5
  3. package/dist/contracts/tm-bundle-merkle/config.js +0 -10
  4. package/dist/contracts/tm-bundle-merkle/core.js +24 -92
  5. package/dist/contracts/tm-bundle-merkle/pancake-proxy.js +54 -103
  6. package/dist/contracts/tm-bundle-merkle/swap-buy-first.d.ts +1 -0
  7. package/dist/contracts/tm-bundle-merkle/swap-buy-first.js +6 -36
  8. package/dist/contracts/tm-bundle-merkle/swap.d.ts +3 -0
  9. package/dist/contracts/tm-bundle-merkle/swap.js +6 -59
  10. package/dist/flap/portal-bundle-merkle/config.d.ts +0 -8
  11. package/dist/flap/portal-bundle-merkle/config.js +0 -17
  12. package/dist/flap/portal-bundle-merkle/core.js +68 -120
  13. package/dist/flap/portal-bundle-merkle/pancake-proxy.js +78 -136
  14. package/dist/flap/portal-bundle-merkle/swap-buy-first.d.ts +2 -0
  15. package/dist/flap/portal-bundle-merkle/swap-buy-first.js +30 -49
  16. package/dist/flap/portal-bundle-merkle/swap.d.ts +2 -0
  17. package/dist/flap/portal-bundle-merkle/swap.js +47 -75
  18. package/dist/flap/portal-bundle-merkle/types.d.ts +0 -1
  19. package/dist/index.d.ts +2 -1
  20. package/dist/index.js +1 -0
  21. package/dist/pancake/bundle-buy-first.d.ts +1 -1
  22. package/dist/pancake/bundle-buy-first.js +17 -49
  23. package/dist/pancake/bundle-swap.d.ts +4 -1
  24. package/dist/pancake/bundle-swap.js +33 -98
  25. package/dist/sol/constants.d.ts +126 -0
  26. package/dist/sol/constants.js +145 -0
  27. package/dist/sol/dex/index.d.ts +8 -0
  28. package/dist/sol/dex/index.js +12 -0
  29. package/dist/sol/dex/meteora/client.d.ts +76 -0
  30. package/dist/sol/dex/meteora/client.js +219 -0
  31. package/dist/sol/dex/meteora/damm-v1-bundle.d.ts +61 -0
  32. package/dist/sol/dex/meteora/damm-v1-bundle.js +112 -0
  33. package/dist/sol/dex/meteora/damm-v1.d.ts +118 -0
  34. package/dist/sol/dex/meteora/damm-v1.js +315 -0
  35. package/dist/sol/dex/meteora/damm-v2-bundle.d.ts +82 -0
  36. package/dist/sol/dex/meteora/damm-v2-bundle.js +242 -0
  37. package/dist/sol/dex/meteora/damm-v2.d.ts +172 -0
  38. package/dist/sol/dex/meteora/damm-v2.js +632 -0
  39. package/dist/sol/dex/meteora/dbc-bundle.d.ts +123 -0
  40. package/dist/sol/dex/meteora/dbc-bundle.js +304 -0
  41. package/dist/sol/dex/meteora/dbc.d.ts +192 -0
  42. package/dist/sol/dex/meteora/dbc.js +619 -0
  43. package/dist/sol/dex/meteora/dlmm-bundle.d.ts +39 -0
  44. package/dist/sol/dex/meteora/dlmm-bundle.js +189 -0
  45. package/dist/sol/dex/meteora/dlmm.d.ts +157 -0
  46. package/dist/sol/dex/meteora/dlmm.js +671 -0
  47. package/dist/sol/dex/meteora/index.d.ts +25 -0
  48. package/dist/sol/dex/meteora/index.js +65 -0
  49. package/dist/sol/dex/meteora/types.d.ts +787 -0
  50. package/dist/sol/dex/meteora/types.js +110 -0
  51. package/dist/sol/dex/orca/index.d.ts +10 -0
  52. package/dist/sol/dex/orca/index.js +16 -0
  53. package/dist/sol/dex/orca/orca-bundle.d.ts +41 -0
  54. package/dist/sol/dex/orca/orca-bundle.js +173 -0
  55. package/dist/sol/dex/orca/orca.d.ts +65 -0
  56. package/dist/sol/dex/orca/orca.js +474 -0
  57. package/dist/sol/dex/orca/types.d.ts +263 -0
  58. package/dist/sol/dex/orca/types.js +38 -0
  59. package/dist/sol/dex/orca/wavebreak-bundle.d.ts +34 -0
  60. package/dist/sol/dex/orca/wavebreak-bundle.js +198 -0
  61. package/dist/sol/dex/orca/wavebreak-types.d.ts +227 -0
  62. package/dist/sol/dex/orca/wavebreak-types.js +23 -0
  63. package/dist/sol/dex/orca/wavebreak.d.ts +78 -0
  64. package/dist/sol/dex/orca/wavebreak.js +497 -0
  65. package/dist/sol/dex/pump/index.d.ts +9 -0
  66. package/dist/sol/dex/pump/index.js +14 -0
  67. package/dist/sol/dex/pump/pump-bundle.d.ts +92 -0
  68. package/dist/sol/dex/pump/pump-bundle.js +383 -0
  69. package/dist/sol/dex/pump/pump-swap-bundle.d.ts +103 -0
  70. package/dist/sol/dex/pump/pump-swap-bundle.js +380 -0
  71. package/dist/sol/dex/pump/pump-swap.d.ts +46 -0
  72. package/dist/sol/dex/pump/pump-swap.js +199 -0
  73. package/dist/sol/dex/pump/pump.d.ts +35 -0
  74. package/dist/sol/dex/pump/pump.js +352 -0
  75. package/dist/sol/dex/pump/types.d.ts +215 -0
  76. package/dist/sol/dex/pump/types.js +5 -0
  77. package/dist/sol/dex/raydium/index.d.ts +8 -0
  78. package/dist/sol/dex/raydium/index.js +12 -0
  79. package/dist/sol/dex/raydium/launchlab.d.ts +68 -0
  80. package/dist/sol/dex/raydium/launchlab.js +210 -0
  81. package/dist/sol/dex/raydium/raydium-bundle.d.ts +64 -0
  82. package/dist/sol/dex/raydium/raydium-bundle.js +324 -0
  83. package/dist/sol/dex/raydium/raydium.d.ts +40 -0
  84. package/dist/sol/dex/raydium/raydium.js +366 -0
  85. package/dist/sol/dex/raydium/types.d.ts +240 -0
  86. package/dist/sol/dex/raydium/types.js +5 -0
  87. package/dist/sol/index.d.ts +10 -0
  88. package/dist/sol/index.js +16 -0
  89. package/dist/sol/jito/bundle.d.ts +90 -0
  90. package/dist/sol/jito/bundle.js +263 -0
  91. package/dist/sol/jito/index.d.ts +7 -0
  92. package/dist/sol/jito/index.js +7 -0
  93. package/dist/sol/jito/tip.d.ts +51 -0
  94. package/dist/sol/jito/tip.js +83 -0
  95. package/dist/sol/jito/types.d.ts +100 -0
  96. package/dist/sol/jito/types.js +5 -0
  97. package/dist/sol/token/create-complete.d.ts +115 -0
  98. package/dist/sol/token/create-complete.js +235 -0
  99. package/dist/sol/token/create-token.d.ts +57 -0
  100. package/dist/sol/token/create-token.js +230 -0
  101. package/dist/sol/token/index.d.ts +9 -0
  102. package/dist/sol/token/index.js +14 -0
  103. package/dist/sol/token/metadata-upload.d.ts +86 -0
  104. package/dist/sol/token/metadata-upload.js +173 -0
  105. package/dist/sol/token/metadata.d.ts +92 -0
  106. package/dist/sol/token/metadata.js +274 -0
  107. package/dist/sol/token/types.d.ts +153 -0
  108. package/dist/sol/token/types.js +5 -0
  109. package/dist/sol/types.d.ts +176 -0
  110. package/dist/sol/types.js +7 -0
  111. package/dist/sol/utils/balance.d.ts +160 -0
  112. package/dist/sol/utils/balance.js +638 -0
  113. package/dist/sol/utils/connection.d.ts +78 -0
  114. package/dist/sol/utils/connection.js +168 -0
  115. package/dist/sol/utils/index.d.ts +9 -0
  116. package/dist/sol/utils/index.js +9 -0
  117. package/dist/sol/utils/lp-inspect.d.ts +129 -0
  118. package/dist/sol/utils/lp-inspect.js +900 -0
  119. package/dist/sol/utils/transfer.d.ts +125 -0
  120. package/dist/sol/utils/transfer.js +220 -0
  121. package/dist/sol/utils/wallet.d.ts +107 -0
  122. package/dist/sol/utils/wallet.js +210 -0
  123. package/dist/utils/erc20.d.ts +2 -108
  124. package/dist/utils/erc20.js +17 -65
  125. package/package.json +39 -4
  126. package/dist/flap/portal-bundle-merkle/encryption.d.ts +0 -16
  127. package/dist/flap/portal-bundle-merkle/encryption.js +0 -146
@@ -29,6 +29,7 @@ export interface FourBundleSwapSignParams {
29
29
  sellPercentage?: number;
30
30
  buyerPrivateKey: string;
31
31
  tokenAddress: string;
32
+ slippageTolerance?: number;
32
33
  config: FourSwapSignConfig;
33
34
  }
34
35
  export interface FourBundleSwapParams {
@@ -37,6 +38,7 @@ export interface FourBundleSwapParams {
37
38
  sellPercentage?: number;
38
39
  buyerPrivateKey: string;
39
40
  tokenAddress: string;
41
+ slippageTolerance?: number;
40
42
  config: FourSwapConfig;
41
43
  }
42
44
  /**
@@ -67,6 +69,7 @@ export interface FourBatchSwapSignParams {
67
69
  buyerPrivateKeys: string[];
68
70
  buyerRatios?: number[];
69
71
  tokenAddress: string;
72
+ slippageTolerance?: number;
70
73
  config: FourSwapSignConfig;
71
74
  }
72
75
  /**
@@ -8,14 +8,11 @@ import { calculateSellAmount } from '../../utils/swap-helpers.js';
8
8
  import { NonceManager, getOptimizedGasPrice, getGasLimit, getGasPriceConfig, getTxType } from '../../utils/bundle-helpers.js';
9
9
  import { ADDRESSES, PROFIT_CONFIG } from '../../utils/constants.js';
10
10
  import { TM_ABI, HELPER3_ABI, TM_ADDRESS } from './swap-internal.js';
11
- import { getBribeAmount } from './config.js';
12
- // ✅ BlockRazor Builder EOA 地址(用于贿赂)
13
- const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
14
11
  /**
15
12
  * Four内盘捆绑换手
16
13
  */
17
14
  export async function fourBundleSwapMerkle(params) {
18
- const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKey, tokenAddress, config } = params;
15
+ const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKey, tokenAddress, slippageTolerance = 0.5, config } = params;
19
16
  const chainIdNum = config.chainId ?? 56;
20
17
  const provider = new ethers.JsonRpcProvider(config.rpcUrl, {
21
18
  chainId: chainIdNum,
@@ -68,16 +65,11 @@ export async function fourBundleSwapMerkle(params) {
68
65
  const profitAmount = extractProfit && sellerWillGetBNB > 0n
69
66
  ? (sellerWillGetBNB * BigInt(profitRateBps)) / 10000n
70
67
  : 0n;
71
- // ✅ 获取贿赂金额
72
- const bribeAmount = getBribeAmount(config);
73
- const needBribeTx = bribeAmount > 0n;
74
68
  // ✅ 优化:第三批并行 - 构建交易、获取 nonces
75
69
  const tmSeller = new Contract(TM_ADDRESS, TM_ABI, seller);
76
70
  const tmBuyer = new Contract(TM_ADDRESS, TM_ABI, buyer);
77
71
  // 计算需要的 nonce 数量
78
72
  let sellerNonceCount = 1; // 卖出交易
79
- if (needBribeTx)
80
- sellerNonceCount++; // 贿赂交易
81
73
  if (needApproval)
82
74
  sellerNonceCount++; // 授权交易
83
75
  if (extractProfit)
@@ -104,28 +96,13 @@ export async function fourBundleSwapMerkle(params) {
104
96
  const { sellerNonces, buyerNonce } = noncesResult;
105
97
  // 分配 nonces
106
98
  let idx = 0;
107
- let bribeNonce;
108
99
  let approvalNonce;
109
- if (needBribeTx)
110
- bribeNonce = sellerNonces[idx++];
111
100
  if (needApproval)
112
101
  approvalNonce = sellerNonces[idx++];
113
102
  const sellerNonce = sellerNonces[idx++];
114
103
  const profitNonce = extractProfit ? sellerNonces[idx] : undefined;
115
104
  // ✅ 并行签名所有交易
116
105
  const signPromises = [];
117
- // ✅ 贿赂交易放在首位
118
- if (needBribeTx && bribeNonce !== undefined) {
119
- signPromises.push(seller.signTransaction({
120
- to: BLOCKRAZOR_BUILDER_EOA,
121
- value: bribeAmount,
122
- nonce: bribeNonce,
123
- gasPrice,
124
- gasLimit: 21000n,
125
- chainId: chainIdNum,
126
- type: txType
127
- }));
128
- }
129
106
  // 授权交易
130
107
  if (needApproval && approvalNonce !== undefined) {
131
108
  const approveInterface = new ethers.Interface(['function approve(address,uint256) returns (bool)']);
@@ -160,7 +137,7 @@ export async function fourBundleSwapMerkle(params) {
160
137
  type: txType,
161
138
  value: buyerFunds
162
139
  }));
163
- // ✅ 利润交易放在末尾
140
+ // 利润交易
164
141
  if (extractProfit && profitAmount > 0n && profitNonce !== undefined) {
165
142
  signPromises.push(seller.signTransaction({
166
143
  to: PROFIT_CONFIG.RECIPIENT,
@@ -175,20 +152,15 @@ export async function fourBundleSwapMerkle(params) {
175
152
  const signedTxs = await Promise.all(signPromises);
176
153
  // 解析签名结果
177
154
  let signIdx = 0;
178
- let bribeTx = null;
179
155
  let approvalTx = null;
180
- if (needBribeTx)
181
- bribeTx = signedTxs[signIdx++];
182
156
  if (needApproval)
183
157
  approvalTx = signedTxs[signIdx++];
184
158
  const signedSell = signedTxs[signIdx++];
185
159
  const signedBuy = signedTxs[signIdx++];
186
160
  const profitTx = extractProfit && profitAmount > 0n ? signedTxs[signIdx] : null;
187
161
  nonceManager.clearTemp();
188
- // ✅ 组装交易列表:贿赂 → 授权 → 卖出 → 买入 → 利润
162
+ // 组装交易列表
189
163
  const allTransactions = [];
190
- if (bribeTx)
191
- allTransactions.push(bribeTx);
192
164
  if (approvalTx)
193
165
  allTransactions.push(approvalTx);
194
166
  allTransactions.push(signedSell, signedBuy);
@@ -213,7 +185,7 @@ export async function fourBundleSwapMerkle(params) {
213
185
  * 限制:最多 24 个买方(服务器限制 25 笔交易,包含 1 笔利润交易)
214
186
  */
215
187
  export async function fourBatchSwapMerkle(params) {
216
- const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, tokenAddress, config } = params;
188
+ const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, tokenAddress, slippageTolerance = 0.5, config } = params;
217
189
  // ✅ 校验买方数量(最多 24 个)
218
190
  const MAX_BUYERS = 24;
219
191
  if (buyerPrivateKeys.length === 0) {
@@ -286,9 +258,6 @@ export async function fourBatchSwapMerkle(params) {
286
258
  const profitAmount = totalBuyerFunds > 0n
287
259
  ? (totalBuyerFunds * BigInt(profitRateBps)) / 10000n
288
260
  : 0n;
289
- // ✅ 获取贿赂金额
290
- const bribeAmount = getBribeAmount(config);
291
- const needBribeTx = bribeAmount > 0n;
292
261
  // ✅ 并行构建所有交易
293
262
  const tmSeller = new Contract(TM_ADDRESS, TM_ABI, seller);
294
263
  const [sellUnsigned, ...buyUnsignedList] = await Promise.all([
@@ -304,8 +273,6 @@ export async function fourBatchSwapMerkle(params) {
304
273
  // ✅ 计算 nonce
305
274
  // seller 需要的 nonce 数量
306
275
  let sellerNonceCount = 1; // 卖出交易
307
- if (needBribeTx)
308
- sellerNonceCount++; // 贿赂交易
309
276
  if (needApproval)
310
277
  sellerNonceCount++; // 授权交易
311
278
  sellerNonceCount++; // 利润交易
@@ -315,10 +282,7 @@ export async function fourBatchSwapMerkle(params) {
315
282
  // 分配 seller nonces
316
283
  const sellerNonces = Array.from({ length: sellerNonceCount }, (_, i) => initialNonces[0] + i);
317
284
  let idx = 0;
318
- let bribeNonce;
319
285
  let approvalNonce;
320
- if (needBribeTx)
321
- bribeNonce = sellerNonces[idx++];
322
286
  if (needApproval)
323
287
  approvalNonce = sellerNonces[idx++];
324
288
  const sellerNonce = sellerNonces[idx++];
@@ -327,18 +291,6 @@ export async function fourBatchSwapMerkle(params) {
327
291
  const buyerNonces = initialNonces.slice(1);
328
292
  // ✅ 并行签名所有交易
329
293
  const signPromises = [];
330
- // ✅ 贿赂交易放在首位
331
- if (needBribeTx && bribeNonce !== undefined) {
332
- signPromises.push(seller.signTransaction({
333
- to: BLOCKRAZOR_BUILDER_EOA,
334
- value: bribeAmount,
335
- nonce: bribeNonce,
336
- gasPrice,
337
- gasLimit: 21000n,
338
- chainId: chainIdNum,
339
- type: txType
340
- }));
341
- }
342
294
  // 授权交易
343
295
  if (needApproval && approvalNonce !== undefined) {
344
296
  const approveInterface = new ethers.Interface(['function approve(address,uint256) returns (bool)']);
@@ -377,7 +329,7 @@ export async function fourBatchSwapMerkle(params) {
377
329
  value: buyAmountsWei[i]
378
330
  }));
379
331
  });
380
- // ✅ 利润交易放在末尾
332
+ // 利润交易
381
333
  if (profitAmount > 0n) {
382
334
  signPromises.push(seller.signTransaction({
383
335
  to: PROFIT_CONFIG.RECIPIENT,
@@ -392,10 +344,7 @@ export async function fourBatchSwapMerkle(params) {
392
344
  const signedTxs = await Promise.all(signPromises);
393
345
  // 解析签名结果
394
346
  let signIdx = 0;
395
- let bribeTx = null;
396
347
  let approvalTx = null;
397
- if (needBribeTx)
398
- bribeTx = signedTxs[signIdx++];
399
348
  if (needApproval)
400
349
  approvalTx = signedTxs[signIdx++];
401
350
  const signedSell = signedTxs[signIdx++];
@@ -403,10 +352,8 @@ export async function fourBatchSwapMerkle(params) {
403
352
  signIdx += buyers.length;
404
353
  const profitTx = profitAmount > 0n ? signedTxs[signIdx] : null;
405
354
  nonceManager.clearTemp();
406
- // ✅ 按顺序组装交易数组:贿赂 → 授权 → 卖出 → 买入 → 利润
355
+ // ✅ 按顺序组装交易数组
407
356
  const signedTransactions = [];
408
- if (bribeTx)
409
- signedTransactions.push(bribeTx);
410
357
  if (approvalTx)
411
358
  signedTransactions.push(approvalTx);
412
359
  signedTransactions.push(signedSell);
@@ -1,6 +1,5 @@
1
1
  import type { FlapBundleMerkleConfig, FlapSignConfig, FlapChainForMerkleBundle } from './types.js';
2
2
  export type { FlapBundleMerkleConfig, FlapSignConfig, FlapChainForMerkleBundle };
3
- export declare const BLOCKRAZOR_BUILDER_EOA = "0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20";
4
3
  export type FlapAnyConfig = FlapBundleMerkleConfig | FlapSignConfig;
5
4
  export declare const CHAIN_ID_MAP: Record<FlapChainForMerkleBundle, number>;
6
5
  export declare const MERKLE_SUPPORTED_CHAIN_IDS: readonly [56, 1];
@@ -71,10 +70,3 @@ export declare function calculateBatchProfit(amounts: bigint[], config?: FlapAny
71
70
  totalProfit: bigint;
72
71
  remainingAmounts: bigint[];
73
72
  };
74
- /**
75
- * 获取 BlockRazor 贿赂金额(wei)
76
- * ✅ 用于提高 bundle 打包优先级
77
- * @param config 配置
78
- * @returns 贿赂金额(wei),如果未配置则返回 0n
79
- */
80
- export declare function getBribeAmount(config?: FlapAnyConfig): bigint;
@@ -1,8 +1,5 @@
1
1
  import { ethers } from 'ethers';
2
2
  import { PROFIT_CONFIG } from '../../utils/constants.js';
3
- // ✅ BlockRazor Builder EOA 地址(用于贿赂)
4
- // 参考文档: https://blockrazor.gitbook.io/blockrazor/bsc/block-builder/send-bundle
5
- export const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
6
3
  // ✅ Chain ID 映射
7
4
  // 注意:Merkle 捆绑服务目前只支持 BSC (56) 和 ETH (1)
8
5
  // 其他链仅用于非捆绑的签名交易
@@ -123,17 +120,3 @@ export function calculateBatchProfit(amounts, config) {
123
120
  }
124
121
  return { totalProfit, remainingAmounts };
125
122
  }
126
- /**
127
- * 获取 BlockRazor 贿赂金额(wei)
128
- * ✅ 用于提高 bundle 打包优先级
129
- * @param config 配置
130
- * @returns 贿赂金额(wei),如果未配置则返回 0n
131
- */
132
- export function getBribeAmount(config) {
133
- if (!config)
134
- return 0n;
135
- const bribeAmount = config.bribeAmount;
136
- if (!bribeAmount || bribeAmount <= 0)
137
- return 0n;
138
- return ethers.parseEther(String(bribeAmount));
139
- }
@@ -1,7 +1,7 @@
1
1
  import { ethers, Wallet, Contract, Interface } from 'ethers';
2
2
  import { NonceManager, getOptimizedGasPrice } from '../../utils/bundle-helpers.js';
3
3
  import { FLAP_PORTAL_ADDRESSES, FLAP_ORIGINAL_PORTAL_ADDRESSES } from '../constants.js';
4
- import { CHAIN_ID_MAP, PORTAL_ABI, getErrorMessage, getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, getProfitRecipient, getBribeAmount, BLOCKRAZOR_BUILDER_EOA } from './config.js';
4
+ import { CHAIN_ID_MAP, PORTAL_ABI, getErrorMessage, getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, getProfitRecipient } from './config.js';
5
5
  const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
6
6
  const MULTICALL3_ADDRESS = '0xcA11bde05977b3631167028862bE2a173976CA11';
7
7
  const MULTICALL3_ABI = [
@@ -153,25 +153,6 @@ export async function createTokenWithBundleBuyMerkle(params) {
153
153
  populateBuyTransactionsWithQuote(buyers, portalAddr, tokenAddress, adjustedFundsList, inputToken, useNativeToken),
154
154
  allocateBuyerNonces(buyers, extractProfit, maxFundsIndex, totalProfit, nonceManager)
155
155
  ]);
156
- // ✅ 贿赂交易放在首位(提高 BlockRazor 打包优先级)
157
- const bribeAmount = getBribeAmount(config);
158
- const bribeTxs = [];
159
- if (bribeAmount > 0n && maxFundsIndex >= 0 && buyers.length > 0) {
160
- // 贿赂交易使用 maxFundsIndex 钱包的第一个 nonce
161
- const bribeNonce = buyerNonces[maxFundsIndex];
162
- const bribeTx = await buyers[maxFundsIndex].signTransaction({
163
- to: BLOCKRAZOR_BUILDER_EOA,
164
- value: bribeAmount,
165
- nonce: bribeNonce,
166
- gasPrice,
167
- gasLimit: 21000n,
168
- chainId,
169
- type: getTxType(config)
170
- });
171
- bribeTxs.push(bribeTx);
172
- // 调整 maxFundsIndex 钱包的 nonce(买入交易 +1)
173
- buyerNonces[maxFundsIndex] = bribeNonce + 1;
174
- }
175
156
  const signedBuys = await signBuyTransactions({
176
157
  unsignedBuys,
177
158
  buyers,
@@ -183,25 +164,21 @@ export async function createTokenWithBundleBuyMerkle(params) {
183
164
  fundsList: adjustedFundsList, // ✅ 使用调整后的金额
184
165
  useNativeToken // ✅ 传递是否使用原生代币
185
166
  });
186
- // ✅ 利润交易放在末尾
187
- const profitTxs = [];
188
- if (extractProfit && totalProfit > 0n && maxFundsIndex >= 0) {
189
- const profitNonce = buyerNonces[maxFundsIndex] + 1;
190
- const profitTx = await buyers[maxFundsIndex].signTransaction({
191
- to: getProfitRecipient(),
192
- value: totalProfit,
193
- nonce: profitNonce,
194
- gasPrice,
195
- gasLimit: 23000n,
196
- chainId,
197
- type: getTxType(config)
198
- });
199
- profitTxs.push(profitTx);
200
- }
167
+ signedTxs.push(...signedBuys);
168
+ await appendProfitTransaction({
169
+ extractProfit,
170
+ totalProfit,
171
+ buyers,
172
+ maxIndex: maxFundsIndex,
173
+ nonces: buyerNonces,
174
+ gasPrice,
175
+ chainId,
176
+ config,
177
+ signedTxs
178
+ });
201
179
  nonceManager.clearTemp();
202
- // ✅ 组装顺序:贿赂 → 创建代币 → 买入 → 利润
203
180
  return {
204
- signedTransactions: [...bribeTxs, ...signedTxs, ...signedBuys, ...profitTxs],
181
+ signedTransactions: signedTxs,
205
182
  tokenAddress,
206
183
  metadata: buildProfitMetadata(extractProfit, totalBuyAmount, totalProfit, buyers.length)
207
184
  };
@@ -257,24 +234,6 @@ export async function batchBuyWithBundleMerkle(params) {
257
234
  ]);
258
235
  if (presetNonces) {
259
236
  }
260
- // ✅ 贿赂交易放在首位(提高 BlockRazor 打包优先级)
261
- const bribeAmount = getBribeAmount(config);
262
- const bribeTxs = [];
263
- if (bribeAmount > 0n && maxFundsIndex >= 0 && buyers.length > 0) {
264
- const bribeNonce = buyerNonces[maxFundsIndex];
265
- const bribeTx = await buyers[maxFundsIndex].signTransaction({
266
- to: BLOCKRAZOR_BUILDER_EOA,
267
- value: bribeAmount,
268
- nonce: bribeNonce,
269
- gasPrice,
270
- gasLimit: 21000n,
271
- chainId,
272
- type: getTxType(config)
273
- });
274
- bribeTxs.push(bribeTx);
275
- // 调整 maxFundsIndex 钱包的 nonce(买入交易 +1)
276
- buyerNonces[maxFundsIndex] = bribeNonce + 1;
277
- }
278
237
  const signedBuys = await signBuyTransactions({
279
238
  unsignedBuys,
280
239
  buyers,
@@ -286,25 +245,21 @@ export async function batchBuyWithBundleMerkle(params) {
286
245
  fundsList: adjustedFundsList, // ✅ 使用调整后的金额
287
246
  useNativeToken // ✅ USDT 购买时 value=0,BNB 购买时 value=金额
288
247
  });
289
- // ✅ 利润交易放在末尾
290
- const profitTxs = [];
291
- if (extractProfit && nativeProfitAmount > 0n && maxFundsIndex >= 0) {
292
- const profitNonce = buyerNonces[maxFundsIndex] + 1;
293
- const profitTx = await buyers[maxFundsIndex].signTransaction({
294
- to: getProfitRecipient(),
295
- value: nativeProfitAmount,
296
- nonce: profitNonce,
297
- gasPrice,
298
- gasLimit: 23000n,
299
- chainId,
300
- type: getTxType(config)
301
- });
302
- profitTxs.push(profitTx);
303
- }
248
+ signedTxs.push(...signedBuys);
249
+ await appendProfitTransaction({
250
+ extractProfit,
251
+ totalProfit: nativeProfitAmount, // 使用转换后的原生代币利润
252
+ buyers,
253
+ maxIndex: maxFundsIndex,
254
+ nonces: buyerNonces,
255
+ gasPrice,
256
+ chainId,
257
+ config,
258
+ signedTxs
259
+ });
304
260
  nonceManager.clearTemp();
305
- // ✅ 组装顺序:贿赂 → 买入 → 利润
306
261
  return {
307
- signedTransactions: [...bribeTxs, ...signedBuys, ...profitTxs],
262
+ signedTransactions: signedTxs,
308
263
  metadata: buildProfitMetadata(extractProfit, totalBuyAmount, nativeProfitAmount, buyers.length)
309
264
  };
310
265
  }
@@ -355,27 +310,18 @@ export async function batchSellWithBundleMerkle(params) {
355
310
  }
356
311
  }
357
312
  }
358
- // ✅ 修复:根据是否需要贿赂/利润交易,统一分配 nonces
359
- const bribeAmount = getBribeAmount(config);
360
- const needBribeTx = bribeAmount > 0n && maxRevenueIndex >= 0;
313
+ // ✅ 修复:根据是否需要利润交易,统一分配 nonces
361
314
  const needProfitTx = extractProfit && totalTokenProfit > 0n && maxRevenueIndex >= 0;
362
- // 计算 maxRevenueIndex 钱包需要的 nonce 数量:贿赂(可选) + 卖出 + 利润(可选)
363
- const maxRevenueNonceCount = 1 + (needBribeTx ? 1 : 0) + (needProfitTx ? 1 : 0);
364
315
  let nonces;
365
- let bribeNonce;
366
316
  let profitNonce;
367
317
  if (presetNonces && presetNonces.length === wallets.length) {
368
- // ✅ 使用前端传入的 nonces
369
- nonces = [...presetNonces];
370
- if (needBribeTx) {
371
- bribeNonce = nonces[maxRevenueIndex];
372
- nonces[maxRevenueIndex] = bribeNonce + 1; // 卖出交易 nonce +1
373
- }
374
- profitNonce = needProfitTx ? nonces[maxRevenueIndex] + 1 : undefined;
318
+ // ✅ 使用前端传入的 nonces,但需要调整避免利润交易冲突
319
+ nonces = adjustNoncesForProfit(presetNonces);
320
+ profitNonce = needProfitTx ? presetNonces[maxRevenueIndex] + 1 : undefined;
375
321
  }
376
- else if (maxRevenueNonceCount > 1 && maxRevenueIndex >= 0) {
377
- // maxRevenueIndex 钱包需要多个连续 nonce
378
- const maxRevenueNonces = await nonceManager.getNextNonceBatch(wallets[maxRevenueIndex], maxRevenueNonceCount);
322
+ else if (needProfitTx) {
323
+ // maxRevenueIndex 钱包需要 2 个连续 nonce(卖出 + 利润)
324
+ const maxRevenueNonces = await nonceManager.getNextNonceBatch(wallets[maxRevenueIndex], 2);
379
325
  // 其他钱包各需要 1 个 nonce
380
326
  const otherWallets = wallets.filter((_, i) => i !== maxRevenueIndex);
381
327
  const otherNonces = otherWallets.length > 0
@@ -384,24 +330,18 @@ export async function batchSellWithBundleMerkle(params) {
384
330
  // 组装最终的 nonces 数组(保持原顺序)
385
331
  nonces = [];
386
332
  let otherIdx = 0;
387
- let nonceIdx = 0;
388
- if (needBribeTx) {
389
- bribeNonce = maxRevenueNonces[nonceIdx++]; // 贿赂交易用第一个 nonce
390
- }
391
333
  for (let i = 0; i < wallets.length; i++) {
392
334
  if (i === maxRevenueIndex) {
393
- nonces.push(maxRevenueNonces[nonceIdx++]); // 卖出交易
335
+ nonces.push(maxRevenueNonces[0]); // 卖出交易用第一个 nonce
394
336
  }
395
337
  else {
396
338
  nonces.push(otherNonces[otherIdx++]);
397
339
  }
398
340
  }
399
- if (needProfitTx) {
400
- profitNonce = maxRevenueNonces[nonceIdx]; // 利润交易用最后一个 nonce
401
- }
341
+ profitNonce = maxRevenueNonces[1]; // 利润交易用第二个 nonce
402
342
  }
403
343
  else {
404
- // 不需要额外交易,所有钱包各 1 个 nonce
344
+ // 不需要利润交易,所有钱包各 1 个 nonce
405
345
  nonces = await nonceManager.getNextNoncesForWallets(wallets);
406
346
  }
407
347
  const minOuts = resolveMinOutputs(minOutputAmounts, wallets.length, quotedOutputs);
@@ -413,21 +353,7 @@ export async function batchSellWithBundleMerkle(params) {
413
353
  minOutputAmount: minOuts[i],
414
354
  permitData: '0x'
415
355
  })));
416
- // ✅ 贿赂交易放在首位
417
- const bribeTxs = [];
418
- if (needBribeTx && bribeNonce !== undefined) {
419
- const bribeTx = await wallets[maxRevenueIndex].signTransaction({
420
- to: BLOCKRAZOR_BUILDER_EOA,
421
- value: bribeAmount,
422
- nonce: bribeNonce,
423
- gasPrice,
424
- gasLimit: 21000n,
425
- chainId,
426
- type: getTxType(config)
427
- });
428
- bribeTxs.push(bribeTx);
429
- }
430
- // ✅ 签名所有卖出交易(并行)
356
+ // ✅ 签名所有交易(并行)
431
357
  // ✅ 卖出交易 value 必须为 0,不能发送原生代币
432
358
  const signedList = await Promise.all(unsignedList.map((unsigned, i) => wallets[i].signTransaction({
433
359
  ...unsigned,
@@ -439,13 +365,16 @@ export async function batchSellWithBundleMerkle(params) {
439
365
  type: getTxType(config),
440
366
  value: 0n // ✅ 卖出交易不发送原生代币
441
367
  })));
442
- // ✅ 利润交易放在末尾
443
- const profitTxs = [];
368
+ signedTxs.push(...signedList);
369
+ // 修复:使用预先分配的 profitNonce 添加利润交易
444
370
  if (needProfitTx && profitNonce !== undefined) {
445
371
  // ERC20 输出时:获取代币利润等值的原生代币(BNB)报价
446
372
  let nativeProfitAmount = totalTokenProfit;
447
373
  if (!useNativeOutput && outputToken) {
448
374
  nativeProfitAmount = await getTokenToNativeQuote(provider, outputToken, totalTokenProfit, chainId);
375
+ // 如果报价失败(返回 0),跳过利润提取
376
+ if (nativeProfitAmount === 0n) {
377
+ }
449
378
  }
450
379
  if (nativeProfitAmount > 0n) {
451
380
  const profitTx = await wallets[maxRevenueIndex].signTransaction({
@@ -457,13 +386,12 @@ export async function batchSellWithBundleMerkle(params) {
457
386
  chainId,
458
387
  type: getTxType(config)
459
388
  });
460
- profitTxs.push(profitTx);
389
+ signedTxs.push(profitTx);
461
390
  }
462
391
  }
463
392
  nonceManager.clearTemp();
464
- // ✅ 组装顺序:贿赂 → 卖出 → 利润
465
393
  return {
466
- signedTransactions: [...bribeTxs, ...signedList, ...profitTxs]
394
+ signedTransactions: signedTxs
467
395
  };
468
396
  }
469
397
  // ✅ Provider 缓存(复用连接,减少初始化开销)
@@ -607,6 +535,22 @@ async function signBuyTransactions({ unsignedBuys, buyers, nonces, gasLimits, ga
607
535
  value: useNativeToken ? fundsList[i] : 0n // ✅ 非原生代币时 value 为 0
608
536
  })));
609
537
  }
538
+ async function appendProfitTransaction({ extractProfit, totalProfit, buyers, maxIndex, nonces, gasPrice, chainId, config, signedTxs }) {
539
+ if (!extractProfit || totalProfit === 0n || buyers.length === 0 || maxIndex < 0) {
540
+ return;
541
+ }
542
+ const profitNonce = (nonces[maxIndex] ?? 0) + 1;
543
+ const profitTx = await buyers[maxIndex].signTransaction({
544
+ to: getProfitRecipient(),
545
+ value: totalProfit,
546
+ nonce: profitNonce,
547
+ gasPrice,
548
+ gasLimit: 23000n,
549
+ chainId,
550
+ type: getTxType(config)
551
+ });
552
+ signedTxs.push(profitTx);
553
+ }
610
554
  function buildProfitMetadata(extractProfit, totalBuyAmount, totalProfit, buyerCount) {
611
555
  if (!extractProfit) {
612
556
  return undefined;
@@ -684,8 +628,12 @@ async function quoteSellOutputsWithQuote(portal, tokenAddress, amountsWei, outpu
684
628
  }));
685
629
  }
686
630
  }
687
- function resolveMinOutputs(_provided, walletCount, _quotedOutputs) {
688
- // 已移除滑点保护:minOutput 固定为 0
631
+ function resolveMinOutputs(provided, walletCount, _quotedOutputs) {
632
+ if (provided && provided.length === walletCount) {
633
+ return provided.map(m => typeof m === 'string' ? ethers.parseEther(m) : BigInt(m));
634
+ }
635
+ // ✅ 默认 minOutput = 0,不设置滑点限制
636
+ // 原因:大额交易时 5% 滑点可能不够,导致交易失败
689
637
  return Array(walletCount).fill(0n);
690
638
  }
691
- // ✅ 贿赂交易和利润交易已内联到各函数中,确保正确的顺序:贿赂 主交易 利润
639
+ // ✅ appendSellProfitTransaction 已内联到 batchSellWithBundleMerkle 中,避免 nonce 竞争问题