four-flap-meme-sdk 1.3.94 → 1.3.95

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 (130) 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/internal.d.ts +1 -1
  6. package/dist/contracts/tm-bundle-merkle/internal.js +4 -3
  7. package/dist/contracts/tm-bundle-merkle/pancake-proxy.js +103 -54
  8. package/dist/contracts/tm-bundle-merkle/swap-buy-first.d.ts +0 -1
  9. package/dist/contracts/tm-bundle-merkle/swap-buy-first.js +36 -6
  10. package/dist/contracts/tm-bundle-merkle/swap.d.ts +0 -3
  11. package/dist/contracts/tm-bundle-merkle/swap.js +59 -6
  12. package/dist/contracts/tm-bundle-merkle/utils.js +7 -7
  13. package/dist/flap/portal-bundle-merkle/config.d.ts +8 -0
  14. package/dist/flap/portal-bundle-merkle/config.js +17 -0
  15. package/dist/flap/portal-bundle-merkle/core.js +120 -68
  16. package/dist/flap/portal-bundle-merkle/encryption.d.ts +16 -0
  17. package/dist/flap/portal-bundle-merkle/encryption.js +146 -0
  18. package/dist/flap/portal-bundle-merkle/pancake-proxy.js +136 -78
  19. package/dist/flap/portal-bundle-merkle/swap-buy-first.d.ts +0 -2
  20. package/dist/flap/portal-bundle-merkle/swap-buy-first.js +49 -30
  21. package/dist/flap/portal-bundle-merkle/swap.d.ts +0 -2
  22. package/dist/flap/portal-bundle-merkle/swap.js +75 -47
  23. package/dist/flap/portal-bundle-merkle/types.d.ts +1 -0
  24. package/dist/index.d.ts +1 -2
  25. package/dist/index.js +0 -1
  26. package/dist/pancake/bundle-buy-first.d.ts +1 -1
  27. package/dist/pancake/bundle-buy-first.js +49 -17
  28. package/dist/pancake/bundle-swap.d.ts +1 -4
  29. package/dist/pancake/bundle-swap.js +98 -33
  30. package/dist/utils/erc20.d.ts +108 -2
  31. package/dist/utils/erc20.js +65 -17
  32. package/package.json +4 -39
  33. package/dist/sol/constants.d.ts +0 -126
  34. package/dist/sol/constants.js +0 -145
  35. package/dist/sol/dex/index.d.ts +0 -8
  36. package/dist/sol/dex/index.js +0 -12
  37. package/dist/sol/dex/meteora/client.d.ts +0 -76
  38. package/dist/sol/dex/meteora/client.js +0 -219
  39. package/dist/sol/dex/meteora/damm-v1-bundle.d.ts +0 -61
  40. package/dist/sol/dex/meteora/damm-v1-bundle.js +0 -112
  41. package/dist/sol/dex/meteora/damm-v1.d.ts +0 -118
  42. package/dist/sol/dex/meteora/damm-v1.js +0 -315
  43. package/dist/sol/dex/meteora/damm-v2-bundle.d.ts +0 -82
  44. package/dist/sol/dex/meteora/damm-v2-bundle.js +0 -242
  45. package/dist/sol/dex/meteora/damm-v2.d.ts +0 -172
  46. package/dist/sol/dex/meteora/damm-v2.js +0 -632
  47. package/dist/sol/dex/meteora/dbc-bundle.d.ts +0 -123
  48. package/dist/sol/dex/meteora/dbc-bundle.js +0 -304
  49. package/dist/sol/dex/meteora/dbc.d.ts +0 -192
  50. package/dist/sol/dex/meteora/dbc.js +0 -619
  51. package/dist/sol/dex/meteora/dlmm-bundle.d.ts +0 -39
  52. package/dist/sol/dex/meteora/dlmm-bundle.js +0 -189
  53. package/dist/sol/dex/meteora/dlmm.d.ts +0 -157
  54. package/dist/sol/dex/meteora/dlmm.js +0 -671
  55. package/dist/sol/dex/meteora/index.d.ts +0 -25
  56. package/dist/sol/dex/meteora/index.js +0 -65
  57. package/dist/sol/dex/meteora/types.d.ts +0 -787
  58. package/dist/sol/dex/meteora/types.js +0 -110
  59. package/dist/sol/dex/orca/index.d.ts +0 -10
  60. package/dist/sol/dex/orca/index.js +0 -16
  61. package/dist/sol/dex/orca/orca-bundle.d.ts +0 -41
  62. package/dist/sol/dex/orca/orca-bundle.js +0 -173
  63. package/dist/sol/dex/orca/orca.d.ts +0 -65
  64. package/dist/sol/dex/orca/orca.js +0 -474
  65. package/dist/sol/dex/orca/types.d.ts +0 -263
  66. package/dist/sol/dex/orca/types.js +0 -38
  67. package/dist/sol/dex/orca/wavebreak-bundle.d.ts +0 -34
  68. package/dist/sol/dex/orca/wavebreak-bundle.js +0 -198
  69. package/dist/sol/dex/orca/wavebreak-types.d.ts +0 -227
  70. package/dist/sol/dex/orca/wavebreak-types.js +0 -23
  71. package/dist/sol/dex/orca/wavebreak.d.ts +0 -78
  72. package/dist/sol/dex/orca/wavebreak.js +0 -497
  73. package/dist/sol/dex/pump/index.d.ts +0 -9
  74. package/dist/sol/dex/pump/index.js +0 -14
  75. package/dist/sol/dex/pump/pump-bundle.d.ts +0 -92
  76. package/dist/sol/dex/pump/pump-bundle.js +0 -383
  77. package/dist/sol/dex/pump/pump-swap-bundle.d.ts +0 -103
  78. package/dist/sol/dex/pump/pump-swap-bundle.js +0 -380
  79. package/dist/sol/dex/pump/pump-swap.d.ts +0 -46
  80. package/dist/sol/dex/pump/pump-swap.js +0 -199
  81. package/dist/sol/dex/pump/pump.d.ts +0 -35
  82. package/dist/sol/dex/pump/pump.js +0 -352
  83. package/dist/sol/dex/pump/types.d.ts +0 -215
  84. package/dist/sol/dex/pump/types.js +0 -5
  85. package/dist/sol/dex/raydium/index.d.ts +0 -8
  86. package/dist/sol/dex/raydium/index.js +0 -12
  87. package/dist/sol/dex/raydium/launchlab.d.ts +0 -68
  88. package/dist/sol/dex/raydium/launchlab.js +0 -210
  89. package/dist/sol/dex/raydium/raydium-bundle.d.ts +0 -64
  90. package/dist/sol/dex/raydium/raydium-bundle.js +0 -324
  91. package/dist/sol/dex/raydium/raydium.d.ts +0 -40
  92. package/dist/sol/dex/raydium/raydium.js +0 -366
  93. package/dist/sol/dex/raydium/types.d.ts +0 -240
  94. package/dist/sol/dex/raydium/types.js +0 -5
  95. package/dist/sol/index.d.ts +0 -10
  96. package/dist/sol/index.js +0 -16
  97. package/dist/sol/jito/bundle.d.ts +0 -90
  98. package/dist/sol/jito/bundle.js +0 -263
  99. package/dist/sol/jito/index.d.ts +0 -7
  100. package/dist/sol/jito/index.js +0 -7
  101. package/dist/sol/jito/tip.d.ts +0 -51
  102. package/dist/sol/jito/tip.js +0 -83
  103. package/dist/sol/jito/types.d.ts +0 -100
  104. package/dist/sol/jito/types.js +0 -5
  105. package/dist/sol/token/create-complete.d.ts +0 -115
  106. package/dist/sol/token/create-complete.js +0 -235
  107. package/dist/sol/token/create-token.d.ts +0 -57
  108. package/dist/sol/token/create-token.js +0 -230
  109. package/dist/sol/token/index.d.ts +0 -9
  110. package/dist/sol/token/index.js +0 -14
  111. package/dist/sol/token/metadata-upload.d.ts +0 -86
  112. package/dist/sol/token/metadata-upload.js +0 -173
  113. package/dist/sol/token/metadata.d.ts +0 -92
  114. package/dist/sol/token/metadata.js +0 -274
  115. package/dist/sol/token/types.d.ts +0 -153
  116. package/dist/sol/token/types.js +0 -5
  117. package/dist/sol/types.d.ts +0 -176
  118. package/dist/sol/types.js +0 -7
  119. package/dist/sol/utils/balance.d.ts +0 -160
  120. package/dist/sol/utils/balance.js +0 -638
  121. package/dist/sol/utils/connection.d.ts +0 -78
  122. package/dist/sol/utils/connection.js +0 -168
  123. package/dist/sol/utils/index.d.ts +0 -9
  124. package/dist/sol/utils/index.js +0 -9
  125. package/dist/sol/utils/lp-inspect.d.ts +0 -129
  126. package/dist/sol/utils/lp-inspect.js +0 -900
  127. package/dist/sol/utils/transfer.d.ts +0 -125
  128. package/dist/sol/utils/transfer.js +0 -220
  129. package/dist/sol/utils/wallet.d.ts +0 -107
  130. 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,
@@ -2,7 +2,7 @@ import { JsonRpcProvider } from 'ethers';
2
2
  import type { AmountLike } from './types.js';
3
3
  /**
4
4
  * 获取 ERC20 代币精度(带缓存)
5
- * ✅ 优化:避免每次调用都获取 network,使用 provider._network 或传入 chainId
5
+ * ✅ 优化:避免每次调用都获取 network,直接使用传入的 chainId
6
6
  */
7
7
  export declare function getErc20DecimalsMerkle(provider: JsonRpcProvider, token: string, chainId?: number): Promise<number>;
8
8
  export declare function generateHopWallets(recipientCount: number, hopCount: number | number[]): string[][] | null;
@@ -3,11 +3,12 @@ import { ethers, Wallet } from 'ethers';
3
3
  const decimalsCache = new Map();
4
4
  /**
5
5
  * 获取 ERC20 代币精度(带缓存)
6
- * ✅ 优化:避免每次调用都获取 network,使用 provider._network 或传入 chainId
6
+ * ✅ 优化:避免每次调用都获取 network,直接使用传入的 chainId
7
7
  */
8
8
  export async function getErc20DecimalsMerkle(provider, token, chainId) {
9
- // ✅ 优化:优先使用传入的 chainId,其次使用 provider 内部缓存的 network
10
- const resolvedChainId = chainId ?? (provider._network?.chainId ? Number(provider._network.chainId) : 56);
9
+ // ✅ 修复:不访问 provider._network(ethers v6 可能未准备好导致 NETWORK_ERROR)
10
+ // 直接使用传入的 chainId,如果没传则默认 56 (BSC)
11
+ const resolvedChainId = chainId ?? 56;
11
12
  const key = `${resolvedChainId}_${token.toLowerCase()}`;
12
13
  if (decimalsCache.has(key))
13
14
  return decimalsCache.get(key);
@@ -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;