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
@@ -151,7 +151,6 @@ export class BlockRazorClient {
151
151
  const gasPrice = tx.gasPrice || 0n;
152
152
  const minGasPrice = ethers.parseUnits(String(MIN_GAS_PRICE_GWEI), 'gwei');
153
153
  if (gasPrice < minGasPrice) {
154
- console.warn(`⚠️ 交易 Gas Price (${ethers.formatUnits(gasPrice, 'gwei')} Gwei) 低于最低要求 (${MIN_GAS_PRICE_GWEI} Gwei)`);
155
154
  }
156
155
  }
157
156
  catch {
@@ -64,3 +64,8 @@ export declare function calculateBatchProfit(amounts: bigint[], config?: FourAny
64
64
  totalProfit: bigint;
65
65
  remainingAmounts: bigint[];
66
66
  };
67
+ /**
68
+ * 获取贿赂金额(Wei)
69
+ * ✅ 从配置中读取贿赂金额,转换为 Wei
70
+ */
71
+ export declare function getBribeAmount(config?: FourAnyConfig): bigint;
@@ -103,3 +103,13 @@ export function calculateBatchProfit(amounts, config) {
103
103
  }
104
104
  return { totalProfit, remainingAmounts };
105
105
  }
106
+ /**
107
+ * 获取贿赂金额(Wei)
108
+ * ✅ 从配置中读取贿赂金额,转换为 Wei
109
+ */
110
+ export function getBribeAmount(config) {
111
+ if (!config || !config.bribeAmount || config.bribeAmount <= 0) {
112
+ return 0n;
113
+ }
114
+ return ethers.parseEther(String(config.bribeAmount));
115
+ }
@@ -2,7 +2,9 @@ import { ethers, Wallet, Contract, Interface } from 'ethers';
2
2
  import { NonceManager, getOptimizedGasPrice } from '../../utils/bundle-helpers.js';
3
3
  import { ADDRESSES } from '../../utils/constants.js';
4
4
  import { FourClient, buildLoginMessage } from '../../clients/four.js';
5
- import { getErrorMessage, getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, getProfitRecipient } from './config.js';
5
+ import { getErrorMessage, getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, getProfitRecipient, getBribeAmount } from './config.js';
6
+ // ✅ BlockRazor Builder EOA 地址(用于贿赂)
7
+ const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
6
8
  import { batchCheckAllowances } from '../../utils/erc20.js';
7
9
  import { trySell } from '../tm.js';
8
10
  import Helper3Abi from '../../abis/TokenManagerHelper3.json' with { type: 'json' };
@@ -87,7 +89,6 @@ export async function createTokenWithBundleBuyMerkle(params) {
87
89
  const txType = getTxType(config);
88
90
  const signedTxs = [];
89
91
  const tmCreateAddr = ADDRESSES.BSC.TokenManagerOriginal;
90
- const tmBuyAddr = ADDRESSES.BSC.TokenManagerOriginal;
91
92
  // ✅ 单笔交易: 和 Four.meme 官网一样
92
93
  // 计算利润
93
94
  const extractProfit = shouldExtractProfit(config);
@@ -103,6 +104,9 @@ export async function createTokenWithBundleBuyMerkle(params) {
103
104
  actualBuyFunds = originalBuyAmount;
104
105
  profitAmount = 0n;
105
106
  }
107
+ // ✅ 获取贿赂金额
108
+ const bribeAmount = getBribeAmount(config);
109
+ const needBribeTx = bribeAmount > 0n;
106
110
  const b0AmountWei = ethers.parseEther(params.b0Amount ?? '0');
107
111
  const preSaleWei = tokenInfo.preSale ? ethers.parseEther(tokenInfo.preSale) : 0n;
108
112
  // ✅ 关键: value = 创建费用 + b0Amount + preSale + 买入金额
@@ -111,6 +115,21 @@ export async function createTokenWithBundleBuyMerkle(params) {
111
115
  const tmCreate = new ethers.Contract(tmCreateAddr, TM2_ABI, devWallet);
112
116
  const createTxUnsigned = await tmCreate.createToken.populateTransaction(createResp.createArg, createResp.signature, { value: valueWei } // ✅ 包含买入金额
113
117
  );
118
+ // ✅ 贿赂交易放在首位(由 devWallet 发送)
119
+ let bribeNonce;
120
+ if (needBribeTx) {
121
+ bribeNonce = await nonceManager.getNextNonce(devWallet);
122
+ const bribeTx = await devWallet.signTransaction({
123
+ to: BLOCKRAZOR_BUILDER_EOA,
124
+ value: bribeAmount,
125
+ nonce: bribeNonce,
126
+ gasPrice,
127
+ gasLimit: 21000n,
128
+ chainId,
129
+ type: txType
130
+ });
131
+ signedTxs.push(bribeTx);
132
+ }
114
133
  const createTxRequest = {
115
134
  ...createTxUnsigned,
116
135
  from: devWallet.address,
@@ -122,7 +141,7 @@ export async function createTokenWithBundleBuyMerkle(params) {
122
141
  value: valueWei
123
142
  };
124
143
  signedTxs.push(await devWallet.signTransaction(createTxRequest));
125
- // ✅ 添加利润转账交易
144
+ // ✅ 添加利润转账交易(放在末尾)
126
145
  if (extractProfit && profitAmount > 0n) {
127
146
  const profitNonce = await nonceManager.getNextNonce(devWallet);
128
147
  const profitTx = await devWallet.signTransaction({
@@ -257,6 +276,27 @@ async function executeBuyFlow(options) {
257
276
  const extractProfit = shouldExtractProfit(config);
258
277
  const analysis = analyzeBuyFunds(buyAmounts, config, extractProfit);
259
278
  const finalGasLimit = getGasLimit(config);
279
+ // ✅ 获取贿赂金额
280
+ const bribeAmount = getBribeAmount(config);
281
+ const needBribeTx = bribeAmount > 0n;
282
+ const payer = profitMode.type === 'aggregated' ? (profitMode.payer ?? wallets[0]) : wallets[0];
283
+ // ✅ 贿赂交易放在首位
284
+ const signedTxs = [];
285
+ let bribeNonceOffset = 0;
286
+ if (needBribeTx) {
287
+ const bribeNonce = await nonceManager.getNextNonce(payer);
288
+ const bribeTx = await payer.signTransaction({
289
+ to: BLOCKRAZOR_BUILDER_EOA,
290
+ value: bribeAmount,
291
+ nonce: bribeNonce,
292
+ gasPrice,
293
+ gasLimit: 21000n,
294
+ chainId,
295
+ type: txType
296
+ });
297
+ signedTxs.push(bribeTx);
298
+ bribeNonceOffset = 1; // payer 的买入交易 nonce 需要偏移
299
+ }
260
300
  // ✅ 优化:并行执行 populateBuyTransactions 和批量获取 nonces(JSON-RPC 批量请求)
261
301
  const [unsignedBuys, nonces] = await Promise.all([
262
302
  populateBuyTransactions({
@@ -267,27 +307,24 @@ async function executeBuyFlow(options) {
267
307
  }),
268
308
  nonceManager.getNextNoncesForWallets(wallets) // ✅ 批量获取 nonce
269
309
  ]);
270
- // ✅ 如果需要利润转账,预先获取 payer 的下一个 nonce
271
- let profitNonce;
272
- if (extractProfit && analysis.totalProfit > 0n && profitMode.type === 'aggregated') {
273
- const payer = profitMode.payer ?? wallets[0];
274
- profitNonce = await nonceManager.getNextNonce(payer);
275
- }
310
+ // ✅ 调整 payer nonce(如果有贿赂交易,需要偏移)
311
+ const payerIndex = wallets.findIndex(w => w.address.toLowerCase() === payer.address.toLowerCase());
312
+ const adjustedNonces = nonces.map((n, i) => i === payerIndex ? n + bribeNonceOffset : n);
276
313
  // ✅ 并行签名所有买入交易
277
314
  const signedBuys = await Promise.all(unsignedBuys.map((unsigned, index) => wallets[index].signTransaction({
278
315
  ...unsigned,
279
316
  from: wallets[index].address,
280
- nonce: nonces[index],
317
+ nonce: adjustedNonces[index],
281
318
  gasLimit: finalGasLimit,
282
319
  gasPrice,
283
320
  chainId,
284
321
  type: txType,
285
322
  value: analysis.fundsList[index]
286
323
  })));
287
- const signedTxs = [...signedBuys];
288
- // ✅ 添加利润转账交易(使用预先获取的 nonce)
289
- if (extractProfit && profitNonce !== undefined && profitMode.type === 'aggregated') {
290
- const payer = profitMode.payer ?? wallets[0];
324
+ signedTxs.push(...signedBuys);
325
+ // ✅ 添加利润转账交易(放在末尾,由 payer 发送)
326
+ if (extractProfit && analysis.totalProfit > 0n && profitMode.type === 'aggregated') {
327
+ const profitNonce = await nonceManager.getNextNonce(payer);
291
328
  const profitTx = await payer.signTransaction({
292
329
  to: getProfitRecipient(),
293
330
  value: analysis.totalProfit,
@@ -307,6 +344,9 @@ async function executeSellFlow(options) {
307
344
  const amountsWei = sellAmounts.map((amount) => ethers.parseUnits(amount, 18));
308
345
  const finalGasLimit = getGasLimit(config);
309
346
  const extractProfit = shouldExtractProfit(config);
347
+ // ✅ 获取贿赂金额
348
+ const bribeAmount = getBribeAmount(config);
349
+ const needBribeTx = bribeAmount > 0n;
310
350
  // ✅ 优化:并行执行 resolveSellOutputs、ensureSellerBalances、ensureSellAllowances 和批量获取 nonces
311
351
  const [sellOutputs, , , nonces] = await Promise.all([
312
352
  resolveSellOutputs({
@@ -326,6 +366,29 @@ async function executeSellFlow(options) {
326
366
  }),
327
367
  nonceManager.getNextNoncesForWallets(wallets) // ✅ 批量获取 nonce(JSON-RPC 批量请求)
328
368
  ]);
369
+ // ✅ 找出收益最多的钱包作为 payer(贿赂和利润都由它发送)
370
+ const { totalProfit, payer } = summarizeSellProfits(sellOutputs.quotedOutputs, wallets, config);
371
+ const payerWallet = payer ?? wallets[0];
372
+ const payerIndex = wallets.findIndex(w => w.address.toLowerCase() === payerWallet.address.toLowerCase());
373
+ // ✅ 贿赂交易放在首位
374
+ const signedTxs = [];
375
+ let bribeNonceOffset = 0;
376
+ if (needBribeTx) {
377
+ const bribeNonce = nonces[payerIndex];
378
+ const bribeTx = await payerWallet.signTransaction({
379
+ to: BLOCKRAZOR_BUILDER_EOA,
380
+ value: bribeAmount,
381
+ nonce: bribeNonce,
382
+ gasPrice,
383
+ gasLimit: 21000n,
384
+ chainId,
385
+ type: txType
386
+ });
387
+ signedTxs.push(bribeTx);
388
+ bribeNonceOffset = 1;
389
+ }
390
+ // ✅ 调整 payer 的 nonce(如果有贿赂交易,需要偏移)
391
+ const adjustedNonces = nonces.map((n, i) => i === payerIndex ? n + bribeNonceOffset : n);
329
392
  // ✅ 构建未签名交易
330
393
  const unsignedSells = await populateSellTransactions({
331
394
  sellers: wallets,
@@ -338,23 +401,24 @@ async function executeSellFlow(options) {
338
401
  const signedSells = await Promise.all(unsignedSells.map((unsigned, index) => wallets[index].signTransaction({
339
402
  ...unsigned,
340
403
  from: wallets[index].address,
341
- nonce: nonces[index],
404
+ nonce: adjustedNonces[index],
342
405
  gasLimit: finalGasLimit,
343
406
  gasPrice,
344
407
  chainId,
345
408
  type: txType
346
409
  })));
347
- const signedTxs = [...signedSells];
348
- const { totalProfit, payer } = summarizeSellProfits(sellOutputs.quotedOutputs, wallets, config);
410
+ signedTxs.push(...signedSells);
411
+ // 利润交易放在末尾
349
412
  await appendAggregatedProfitTransfer({
350
413
  extractProfit,
351
414
  totalProfit,
352
- payer,
415
+ payer: payerWallet,
353
416
  nonceManager,
354
417
  gasPrice,
355
418
  chainId,
356
419
  txType,
357
- signedTxs
420
+ signedTxs,
421
+ baseNonce: adjustedNonces[payerIndex] + 1 // ✅ 传入基础 nonce
358
422
  });
359
423
  return { signedTxs };
360
424
  }
@@ -412,7 +476,8 @@ async function resolveSellOutputs(params) {
412
476
  try {
413
477
  const result = await trySell('BSC', rpcUrl, tokenAddress, amountsWei[0]);
414
478
  const quotedOutputs = [result.funds];
415
- const minOuts = quotedOutputs.map((quote) => (quote * 95n) / 100n);
479
+ // ✅ 已移除滑点保护:minOuts 固定为 0
480
+ const minOuts = [0n];
416
481
  return { minOuts, quotedOutputs };
417
482
  }
418
483
  catch {
@@ -445,7 +510,8 @@ async function resolveSellOutputs(params) {
445
510
  }
446
511
  return 0n;
447
512
  });
448
- const minOuts = quotedOutputs.map((quote) => (quote * 95n) / 100n);
513
+ // ✅ 已移除滑点保护:minOuts 固定为 0
514
+ const minOuts = quotedOutputs.map(() => 0n);
449
515
  return { minOuts, quotedOutputs };
450
516
  }
451
517
  catch {
@@ -459,7 +525,8 @@ async function resolveSellOutputs(params) {
459
525
  return 0n;
460
526
  }
461
527
  }));
462
- const minOuts = quotedOutputs.map((quote) => (quote * 95n) / 100n);
528
+ // ✅ 已移除滑点保护:minOuts 固定为 0
529
+ const minOuts = quotedOutputs.map(() => 0n);
463
530
  return { minOuts, quotedOutputs };
464
531
  }
465
532
  }
@@ -509,11 +576,12 @@ function summarizeSellProfits(quotedOutputs, sellers, config) {
509
576
  return { totalProfit, payer };
510
577
  }
511
578
  async function appendAggregatedProfitTransfer(params) {
512
- const { extractProfit, totalProfit, payer, nonceManager, gasPrice, chainId, txType, signedTxs } = params;
579
+ const { extractProfit, totalProfit, payer, nonceManager, gasPrice, chainId, txType, signedTxs, baseNonce } = params;
513
580
  if (!extractProfit || totalProfit <= 0n || !payer) {
514
581
  return;
515
582
  }
516
- const profitNonce = await nonceManager.getNextNonce(payer);
583
+ // 如果提供了 baseNonce,直接使用;否则从 nonceManager 获取
584
+ const profitNonce = baseNonce ?? await nonceManager.getNextNonce(payer);
517
585
  const profitTx = await payer.signTransaction({
518
586
  to: getProfitRecipient(),
519
587
  value: totalProfit,
@@ -1,8 +1,10 @@
1
1
  import { ethers, Wallet, JsonRpcProvider, Contract, Interface } from 'ethers';
2
2
  import { NonceManager, getOptimizedGasPrice } from '../../utils/bundle-helpers.js';
3
3
  import { ADDRESSES } from '../../utils/constants.js';
4
- import { getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, calculateBatchProfit, getProfitRecipient } from './config.js';
4
+ import { getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, calculateBatchProfit, getProfitRecipient, getBribeAmount } from './config.js';
5
5
  import { batchCheckAllowances } from '../../utils/erc20.js';
6
+ // ✅ BlockRazor Builder EOA 地址(用于贿赂)
7
+ const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
6
8
  const MULTICALL3_ADDRESS = '0xcA11bde05977b3631167028862bE2a173976CA11';
7
9
  const MULTICALL3_ABI = [
8
10
  'function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) external payable returns (tuple(bool success, bytes returnData)[])'
@@ -303,15 +305,22 @@ export async function fourPancakeProxyBatchBuyMerkle(params) {
303
305
  const actualAmountsWei = remainingAmounts; // 扣除利润后用于购买的金额
304
306
  const finalGasLimit = getGasLimit(config);
305
307
  const nonceManager = new NonceManager(provider);
308
+ // ✅ 获取贿赂金额
309
+ const bribeAmount = getBribeAmount(config);
310
+ const needBribeTx = bribeAmount > 0n;
306
311
  // ✅ 优化:并行获取 gasPrice 和 tokenDecimals
307
312
  const [gasPrice, tokenDecimals] = await Promise.all([
308
313
  getOptimizedGasPrice(provider, getGasPriceConfig(config)),
309
314
  getTokenDecimals(tokenAddress, provider)
310
315
  ]);
311
316
  // ✅ 修复:先计算需要的 nonce 数量,再统一获取
312
- // buyers[0] 可能需要 2 个 nonce(买入 + 利润转账)
317
+ // buyers[0] 可能需要 3 个 nonce(贿赂 + 买入 + 利润转账)
313
318
  const needProfitTx = extractProfit && totalProfit > 0n;
314
- const buyer0NeedCount = needProfitTx ? 2 : 1;
319
+ let buyer0NeedCount = 1; // 买入交易
320
+ if (needBribeTx)
321
+ buyer0NeedCount++; // 贿赂交易
322
+ if (needProfitTx)
323
+ buyer0NeedCount++; // 利润交易
315
324
  // 获取 buyers[0] 的连续 nonces
316
325
  const buyer0Nonces = await nonceManager.getNextNonceBatch(buyers[0], buyer0NeedCount);
317
326
  // 获取其他 buyers 的 nonces(如果有)
@@ -319,9 +328,13 @@ export async function fourPancakeProxyBatchBuyMerkle(params) {
319
328
  if (buyers.length > 1) {
320
329
  otherNonces = await nonceManager.getNextNoncesForWallets(buyers.slice(1));
321
330
  }
331
+ // 分配 nonces
332
+ let buyer0NonceIdx = 0;
333
+ const bribeNonce = needBribeTx ? buyer0Nonces[buyer0NonceIdx++] : undefined;
334
+ const buyer0BuyNonce = buyer0Nonces[buyer0NonceIdx++];
335
+ const profitNonce = needProfitTx ? buyer0Nonces[buyer0NonceIdx] : undefined;
322
336
  // 组装最终的 nonces 数组
323
- const nonces = [buyer0Nonces[0], ...otherNonces];
324
- const profitNonce = needProfitTx ? buyer0Nonces[1] : undefined;
337
+ const nonces = [buyer0BuyNonce, ...otherNonces];
325
338
  // 计算 minOutputAmounts
326
339
  let minOuts;
327
340
  if (params.minOutputAmounts && params.minOutputAmounts.length === buyers.length) {
@@ -356,8 +369,22 @@ export async function fourPancakeProxyBatchBuyMerkle(params) {
356
369
  else {
357
370
  throw new Error(`Unsupported routeType: ${routeType}`);
358
371
  }
372
+ // ✅ 贿赂交易放在首位
373
+ const signedTxs = [];
374
+ if (needBribeTx && bribeNonce !== undefined) {
375
+ const bribeTx = await buyers[0].signTransaction({
376
+ to: BLOCKRAZOR_BUILDER_EOA,
377
+ value: bribeAmount,
378
+ nonce: bribeNonce,
379
+ gasPrice,
380
+ gasLimit: 21000n,
381
+ chainId: 56,
382
+ type: txType
383
+ });
384
+ signedTxs.push(bribeTx);
385
+ }
359
386
  // ✅ 并行签名所有买入交易
360
- const signedTxs = await Promise.all(unsignedBuys.map((unsigned, i) => buyers[i].signTransaction({
387
+ const signedBuys = await Promise.all(unsignedBuys.map((unsigned, i) => buyers[i].signTransaction({
361
388
  ...unsigned,
362
389
  from: buyers[i].address,
363
390
  nonce: nonces[i],
@@ -367,7 +394,8 @@ export async function fourPancakeProxyBatchBuyMerkle(params) {
367
394
  type: txType,
368
395
  value: unsigned.value // ✅ 显式保留 value(BNB 金额 + 手续费)
369
396
  })));
370
- // ✅ 添加利润转账(使用预先获取的 nonce)
397
+ signedTxs.push(...signedBuys);
398
+ // ✅ 添加利润转账(放在末尾,使用预先获取的 nonce)
371
399
  if (extractProfit && totalProfit > 0n && profitNonce !== undefined) {
372
400
  const profitTx = await buyers[0].signTransaction({
373
401
  to: getProfitRecipient(),
@@ -409,6 +437,9 @@ export async function fourPancakeProxyBatchSellMerkle(params) {
409
437
  const finalGasLimit = getGasLimit(config);
410
438
  const nonceManager = new NonceManager(provider);
411
439
  const extractProfit = shouldExtractProfit(config);
440
+ // ✅ 获取贿赂金额
441
+ const bribeAmount = getBribeAmount(config);
442
+ const needBribeTx = bribeAmount > 0n;
412
443
  // ✅ 优化:并行获取 gasPrice、tokenDecimals 和 allowances
413
444
  const [gasPrice, tokenDecimals, allowances] = await Promise.all([
414
445
  getOptimizedGasPrice(provider, getGasPriceConfig(config)),
@@ -429,48 +460,40 @@ export async function fourPancakeProxyBatchSellMerkle(params) {
429
460
  if (needApprovalIndexes.length > 0) {
430
461
  throw new Error(`需要授权: ${needApprovalIndexes.length} 个钱包尚未授权。请先完成授权后再卖出。`);
431
462
  }
432
- // ✅ 自动获取报价或使用用户提供的 minOutputAmounts
433
- let minOuts;
463
+ // ✅ 获取报价(用于计算利润),已移除滑点保护
434
464
  let quotedOutputs;
435
- if (params.minOutputAmounts && params.minOutputAmounts.length === sellers.length) {
436
- // 用户提供了 minOutputAmounts,跳过报价查询
437
- minOuts = params.minOutputAmounts.map(m => typeof m === 'string' ? ethers.parseEther(m) : m);
438
- quotedOutputs = minOuts.map(m => m * 100n / 95n); // 反推预期收益
465
+ // 使用 Multicall3 批量获取报价(仅 V2 路由支持)
466
+ if (routeType === 'v2' && params.v2Path && params.v2Path.length >= 2) {
467
+ quotedOutputs = await batchGetV2Quotes(provider, amountsWei, params.v2Path);
468
+ }
469
+ else if (routeType === 'v3-single') {
470
+ // V3 单跳:并行调用(V3 Quoter 是 non-view 函数,不支持 Multicall3)
471
+ quotedOutputs = await Promise.all(amountsWei.map(async (amount) => {
472
+ try {
473
+ const quoter = new Contract(PANCAKE_V3_QUOTER_ADDRESS, PANCAKE_V3_QUOTER_ABI, provider);
474
+ const result = await quoter.quoteExactInputSingle.staticCall({
475
+ tokenIn: tokenAddress,
476
+ tokenOut: params.v3TokenOut,
477
+ amountIn: amount,
478
+ fee: params.v3Fee,
479
+ sqrtPriceLimitX96: 0
480
+ });
481
+ return result[0];
482
+ }
483
+ catch {
484
+ return 0n;
485
+ }
486
+ }));
487
+ }
488
+ else if (routeType === 'v3-multi' && params.v2Path && params.v2Path.length >= 2) {
489
+ // V3 多跳:使用 V2 备选路由
490
+ quotedOutputs = await batchGetV2Quotes(provider, amountsWei, params.v2Path);
439
491
  }
440
492
  else {
441
- // 使用 Multicall3 批量获取报价(仅 V2 路由支持)
442
- if (routeType === 'v2' && params.v2Path && params.v2Path.length >= 2) {
443
- quotedOutputs = await batchGetV2Quotes(provider, amountsWei, params.v2Path);
444
- }
445
- else if (routeType === 'v3-single') {
446
- // V3 单跳:并行调用(V3 Quoter 是 non-view 函数,不支持 Multicall3)
447
- quotedOutputs = await Promise.all(amountsWei.map(async (amount) => {
448
- try {
449
- const quoter = new Contract(PANCAKE_V3_QUOTER_ADDRESS, PANCAKE_V3_QUOTER_ABI, provider);
450
- const result = await quoter.quoteExactInputSingle.staticCall({
451
- tokenIn: tokenAddress,
452
- tokenOut: params.v3TokenOut,
453
- amountIn: amount,
454
- fee: params.v3Fee,
455
- sqrtPriceLimitX96: 0
456
- });
457
- return result[0];
458
- }
459
- catch {
460
- return 0n;
461
- }
462
- }));
463
- }
464
- else if (routeType === 'v3-multi' && params.v2Path && params.v2Path.length >= 2) {
465
- // V3 多跳:使用 V2 备选路由
466
- quotedOutputs = await batchGetV2Quotes(provider, amountsWei, params.v2Path);
467
- }
468
- else {
469
- quotedOutputs = new Array(amountsWei.length).fill(0n);
470
- }
471
- // ✅ minOuts = 0,不设置滑点限制(大额交易更稳定)
472
- minOuts = quotedOutputs.map(() => 0n);
493
+ quotedOutputs = new Array(amountsWei.length).fill(0n);
473
494
  }
495
+ // ✅ 已移除滑点保护:minOuts 固定为 0
496
+ const minOuts = new Array(sellers.length).fill(0n);
474
497
  // ✅ 计算利润并找出收益最多的钱包
475
498
  let totalProfit = 0n;
476
499
  let maxRevenueIndex = 0;
@@ -489,32 +512,43 @@ export async function fourPancakeProxyBatchSellMerkle(params) {
489
512
  }
490
513
  // ✅ 修复:先计算需要的 nonce 数量,再统一获取
491
514
  const needProfitTx = extractProfit && totalProfit > 0n && maxRevenue > 0n;
492
- // 分配 nonces:收益最多的钱包可能需要 2 个 nonce(卖出 + 利润转账)
515
+ // 分配 nonces:收益最多的钱包可能需要 3 个 nonce(贿赂 + 卖出 + 利润转账)
493
516
  let nonces;
517
+ let bribeNonce;
494
518
  let profitNonce;
495
- if (needProfitTx) {
496
- // 收益最多的钱包需要 2 个连续 nonce
497
- const maxRevenueNonces = await nonceManager.getNextNonceBatch(sellers[maxRevenueIndex], 2);
519
+ if (needBribeTx || needProfitTx) {
520
+ // 计算收益最多的钱包需要的 nonce 数量
521
+ let maxRevenueNonceCount = 1; // 卖出交易
522
+ if (needBribeTx)
523
+ maxRevenueNonceCount++; // 贿赂交易
524
+ if (needProfitTx)
525
+ maxRevenueNonceCount++; // 利润交易
526
+ // 收益最多的钱包需要连续 nonce
527
+ const maxRevenueNonces = await nonceManager.getNextNonceBatch(sellers[maxRevenueIndex], maxRevenueNonceCount);
498
528
  // 其他钱包各需要 1 个 nonce
499
529
  const otherSellers = sellers.filter((_, i) => i !== maxRevenueIndex);
500
530
  const otherNonces = otherSellers.length > 0
501
531
  ? await nonceManager.getNextNoncesForWallets(otherSellers)
502
532
  : [];
533
+ // 分配收益最多钱包的 nonces
534
+ let maxRevenueNonceIdx = 0;
535
+ bribeNonce = needBribeTx ? maxRevenueNonces[maxRevenueNonceIdx++] : undefined;
536
+ const maxRevenueSellNonce = maxRevenueNonces[maxRevenueNonceIdx++];
537
+ profitNonce = needProfitTx ? maxRevenueNonces[maxRevenueNonceIdx] : undefined;
503
538
  // 组装最终的 nonces 数组(保持原顺序)
504
539
  nonces = [];
505
540
  let otherIdx = 0;
506
541
  for (let i = 0; i < sellers.length; i++) {
507
542
  if (i === maxRevenueIndex) {
508
- nonces.push(maxRevenueNonces[0]); // 卖出交易用第一个 nonce
543
+ nonces.push(maxRevenueSellNonce); // 卖出交易 nonce
509
544
  }
510
545
  else {
511
546
  nonces.push(otherNonces[otherIdx++]);
512
547
  }
513
548
  }
514
- profitNonce = maxRevenueNonces[1]; // 利润交易用第二个 nonce
515
549
  }
516
550
  else {
517
- // 不需要利润交易,所有钱包各 1 个 nonce
551
+ // 不需要贿赂和利润交易,所有钱包各 1 个 nonce
518
552
  nonces = await nonceManager.getNextNoncesForWallets(sellers);
519
553
  }
520
554
  // 卖出不需要发送 BNB,只需要 flatFee
@@ -543,8 +577,22 @@ export async function fourPancakeProxyBatchSellMerkle(params) {
543
577
  else {
544
578
  throw new Error(`Unsupported routeType: ${routeType}`);
545
579
  }
580
+ // ✅ 贿赂交易放在首位
581
+ const signedTxs = [];
582
+ if (needBribeTx && bribeNonce !== undefined) {
583
+ const bribeTx = await sellers[maxRevenueIndex].signTransaction({
584
+ to: BLOCKRAZOR_BUILDER_EOA,
585
+ value: bribeAmount,
586
+ nonce: bribeNonce,
587
+ gasPrice,
588
+ gasLimit: 21000n,
589
+ chainId: 56,
590
+ type: txType
591
+ });
592
+ signedTxs.push(bribeTx);
593
+ }
546
594
  // ✅ 并行签名所有卖出交易
547
- const signedTxs = await Promise.all(unsignedSells.map((unsigned, i) => sellers[i].signTransaction({
595
+ const signedSells = await Promise.all(unsignedSells.map((unsigned, i) => sellers[i].signTransaction({
548
596
  ...unsigned,
549
597
  from: sellers[i].address,
550
598
  nonce: nonces[i],
@@ -554,7 +602,8 @@ export async function fourPancakeProxyBatchSellMerkle(params) {
554
602
  type: txType,
555
603
  value: unsigned.value // ✅ 显式保留 value(手续费)
556
604
  })));
557
- // ✅ 添加利润转账(使用预先获取的 nonce)
605
+ signedTxs.push(...signedSells);
606
+ // ✅ 添加利润转账(放在末尾,使用预先获取的 nonce)
558
607
  if (extractProfit && totalProfit > 0n && profitNonce !== undefined) {
559
608
  const profitTx = await sellers[maxRevenueIndex].signTransaction({
560
609
  to: getProfitRecipient(),
@@ -7,7 +7,6 @@ import { CommonBundleConfig } from '../../utils/bundle-helpers.js';
7
7
  import { FourSignConfig } from './types.js';
8
8
  export interface FourBuyFirstSignConfig extends FourSignConfig {
9
9
  reserveGasBNB?: number;
10
- slippageBps?: number;
11
10
  }
12
11
  export interface FourBuyFirstConfig extends CommonBundleConfig {
13
12
  apiKey: string;
@@ -7,8 +7,10 @@ import { ethers, Contract, Wallet } from 'ethers';
7
7
  import { NonceManager, getOptimizedGasPrice } from '../../utils/bundle-helpers.js';
8
8
  import { ADDRESSES } from '../../utils/constants.js';
9
9
  import { TM_ABI, HELPER3_ABI, TM_ADDRESS } from './swap-internal.js';
10
- import { getTxType, getGasPriceConfig, getProfitRecipient, getProfitRateBps } from './config.js';
10
+ import { getTxType, getGasPriceConfig, getProfitRecipient, getProfitRateBps, getBribeAmount } from './config.js';
11
11
  import { trySell } from '../tm.js';
12
+ // ✅ BlockRazor Builder EOA 地址(用于贿赂)
13
+ const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
12
14
  /**
13
15
  * 获取 Gas Limit(支持 FourAnyConfig)
14
16
  */
@@ -82,14 +84,19 @@ export async function fourBundleBuyFirstMerkle(params) {
82
84
  // ✅ 优化:第三批并行 - trySell、构建交易、获取 nonces
83
85
  const tmBuyer = new Contract(TM_ADDRESS, TM_ABI, buyer);
84
86
  const tmSeller = new Contract(TM_ADDRESS, TM_ABI, seller);
85
- const slippageBps = config.slippageBps ?? 100;
86
- const minBuyAmount = (estimatedTokenAmount * BigInt(10000 - slippageBps)) / 10000n;
87
+ // 已移除滑点保护:minBuyAmount 固定为 0
88
+ const minBuyAmount = 0n;
87
89
  // 预先规划 nonces
88
90
  const extractProfit = true;
89
91
  const profitRateBps = getProfitRateBps();
92
+ // ✅ 获取贿赂金额
93
+ const bribeAmount = getBribeAmount(config);
94
+ const needBribeTx = bribeAmount > 0n;
90
95
  // 计算需要的 nonce 数量
91
96
  let buyerNonceCount = 1; // 买入交易
92
97
  let sellerNonceCount = 1; // 卖出交易
98
+ if (needBribeTx)
99
+ sellerNonceCount++; // 贿赂交易(由卖方发送)
93
100
  if (needApproval)
94
101
  sellerNonceCount++; // 授权交易
95
102
  if (extractProfit)
@@ -121,7 +128,8 @@ export async function fourBundleBuyFirstMerkle(params) {
121
128
  ]);
122
129
  const { buyerNonces, sellerNonces } = noncesResult;
123
130
  const estimatedSellFunds = sellResult.funds;
124
- const minSellFunds = (estimatedSellFunds * BigInt(10000 - slippageBps)) / 10000n;
131
+ // ✅ 已移除滑点保护:minSellFunds 固定为 0
132
+ const minSellFunds = 0n;
125
133
  const profitAmount = extractProfit ? (estimatedSellFunds * BigInt(profitRateBps)) / 10000n : 0n;
126
134
  // 更新卖出交易的 minSellFunds
127
135
  sellUnsigned.data = tmSeller.interface.encodeFunctionData('sellToken', [
@@ -130,10 +138,13 @@ export async function fourBundleBuyFirstMerkle(params) {
130
138
  // 分配 nonces
131
139
  let buyerNonce;
132
140
  let sellerNonce;
141
+ let bribeNonce;
133
142
  let approvalNonce;
134
143
  let profitNonce;
135
144
  if (sameAddress) {
136
145
  let idx = 0;
146
+ if (needBribeTx)
147
+ bribeNonce = sellerNonces[idx++];
137
148
  if (needApproval)
138
149
  approvalNonce = sellerNonces[idx++];
139
150
  buyerNonce = sellerNonces[idx++];
@@ -144,6 +155,8 @@ export async function fourBundleBuyFirstMerkle(params) {
144
155
  else {
145
156
  buyerNonce = buyerNonces[0];
146
157
  let idx = 0;
158
+ if (needBribeTx)
159
+ bribeNonce = sellerNonces[idx++];
147
160
  if (needApproval)
148
161
  approvalNonce = sellerNonces[idx++];
149
162
  sellerNonce = sellerNonces[idx++];
@@ -152,6 +165,19 @@ export async function fourBundleBuyFirstMerkle(params) {
152
165
  }
153
166
  // ✅ 并行签名所有交易
154
167
  const signPromises = [];
168
+ // ✅ 贿赂交易放在首位
169
+ let bribeTx = null;
170
+ if (needBribeTx && bribeNonce !== undefined) {
171
+ signPromises.push(seller.signTransaction({
172
+ to: BLOCKRAZOR_BUILDER_EOA,
173
+ value: bribeAmount,
174
+ nonce: bribeNonce,
175
+ gasPrice,
176
+ gasLimit: 21000n,
177
+ chainId: chainIdNum,
178
+ type: txType
179
+ }));
180
+ }
155
181
  // 授权交易
156
182
  let approvalTx = null;
157
183
  if (needApproval && approvalNonce !== undefined) {
@@ -190,7 +216,7 @@ export async function fourBundleBuyFirstMerkle(params) {
190
216
  type: txType,
191
217
  value: 0n // ✅ 卖出交易不发送原生代币
192
218
  }));
193
- // 利润交易
219
+ // ✅ 利润交易放在末尾
194
220
  let profitTx = null;
195
221
  if (extractProfit && profitAmount > 0n && profitNonce !== undefined) {
196
222
  signPromises.push(seller.signTransaction({
@@ -206,6 +232,8 @@ export async function fourBundleBuyFirstMerkle(params) {
206
232
  const signedTxs = await Promise.all(signPromises);
207
233
  // 解析签名结果
208
234
  let idx = 0;
235
+ if (needBribeTx)
236
+ bribeTx = signedTxs[idx++];
209
237
  if (needApproval)
210
238
  approvalTx = signedTxs[idx++];
211
239
  const signedBuy = signedTxs[idx++];
@@ -213,8 +241,10 @@ export async function fourBundleBuyFirstMerkle(params) {
213
241
  if (extractProfit && profitAmount > 0n)
214
242
  profitTx = signedTxs[idx];
215
243
  nonceManager.clearTemp();
216
- // 组装交易列表
244
+ // ✅ 组装交易列表:贿赂 → 授权 → 买入 → 卖出 → 利润
217
245
  const allTransactions = [];
246
+ if (bribeTx)
247
+ allTransactions.push(bribeTx);
218
248
  if (approvalTx)
219
249
  allTransactions.push(approvalTx);
220
250
  allTransactions.push(signedBuy, signedSell);