four-flap-meme-sdk 1.3.92 → 1.3.93

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