four-flap-meme-sdk 1.3.94 → 1.3.98

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 (132) 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/dex/direct-router.d.ts +2 -0
  14. package/dist/dex/direct-router.js +150 -49
  15. package/dist/flap/portal-bundle-merkle/config.d.ts +8 -0
  16. package/dist/flap/portal-bundle-merkle/config.js +17 -0
  17. package/dist/flap/portal-bundle-merkle/core.js +120 -68
  18. package/dist/flap/portal-bundle-merkle/encryption.d.ts +16 -0
  19. package/dist/flap/portal-bundle-merkle/encryption.js +146 -0
  20. package/dist/flap/portal-bundle-merkle/pancake-proxy.js +136 -78
  21. package/dist/flap/portal-bundle-merkle/swap-buy-first.d.ts +0 -2
  22. package/dist/flap/portal-bundle-merkle/swap-buy-first.js +49 -30
  23. package/dist/flap/portal-bundle-merkle/swap.d.ts +0 -2
  24. package/dist/flap/portal-bundle-merkle/swap.js +75 -47
  25. package/dist/flap/portal-bundle-merkle/types.d.ts +1 -0
  26. package/dist/index.d.ts +1 -2
  27. package/dist/index.js +0 -1
  28. package/dist/pancake/bundle-buy-first.d.ts +1 -1
  29. package/dist/pancake/bundle-buy-first.js +49 -17
  30. package/dist/pancake/bundle-swap.d.ts +1 -4
  31. package/dist/pancake/bundle-swap.js +98 -33
  32. package/dist/utils/erc20.d.ts +108 -2
  33. package/dist/utils/erc20.js +65 -17
  34. package/package.json +4 -39
  35. package/dist/sol/constants.d.ts +0 -126
  36. package/dist/sol/constants.js +0 -145
  37. package/dist/sol/dex/index.d.ts +0 -8
  38. package/dist/sol/dex/index.js +0 -12
  39. package/dist/sol/dex/meteora/client.d.ts +0 -76
  40. package/dist/sol/dex/meteora/client.js +0 -219
  41. package/dist/sol/dex/meteora/damm-v1-bundle.d.ts +0 -61
  42. package/dist/sol/dex/meteora/damm-v1-bundle.js +0 -112
  43. package/dist/sol/dex/meteora/damm-v1.d.ts +0 -118
  44. package/dist/sol/dex/meteora/damm-v1.js +0 -315
  45. package/dist/sol/dex/meteora/damm-v2-bundle.d.ts +0 -82
  46. package/dist/sol/dex/meteora/damm-v2-bundle.js +0 -242
  47. package/dist/sol/dex/meteora/damm-v2.d.ts +0 -172
  48. package/dist/sol/dex/meteora/damm-v2.js +0 -632
  49. package/dist/sol/dex/meteora/dbc-bundle.d.ts +0 -123
  50. package/dist/sol/dex/meteora/dbc-bundle.js +0 -304
  51. package/dist/sol/dex/meteora/dbc.d.ts +0 -192
  52. package/dist/sol/dex/meteora/dbc.js +0 -619
  53. package/dist/sol/dex/meteora/dlmm-bundle.d.ts +0 -39
  54. package/dist/sol/dex/meteora/dlmm-bundle.js +0 -189
  55. package/dist/sol/dex/meteora/dlmm.d.ts +0 -157
  56. package/dist/sol/dex/meteora/dlmm.js +0 -671
  57. package/dist/sol/dex/meteora/index.d.ts +0 -25
  58. package/dist/sol/dex/meteora/index.js +0 -65
  59. package/dist/sol/dex/meteora/types.d.ts +0 -787
  60. package/dist/sol/dex/meteora/types.js +0 -110
  61. package/dist/sol/dex/orca/index.d.ts +0 -10
  62. package/dist/sol/dex/orca/index.js +0 -16
  63. package/dist/sol/dex/orca/orca-bundle.d.ts +0 -41
  64. package/dist/sol/dex/orca/orca-bundle.js +0 -173
  65. package/dist/sol/dex/orca/orca.d.ts +0 -65
  66. package/dist/sol/dex/orca/orca.js +0 -474
  67. package/dist/sol/dex/orca/types.d.ts +0 -263
  68. package/dist/sol/dex/orca/types.js +0 -38
  69. package/dist/sol/dex/orca/wavebreak-bundle.d.ts +0 -34
  70. package/dist/sol/dex/orca/wavebreak-bundle.js +0 -198
  71. package/dist/sol/dex/orca/wavebreak-types.d.ts +0 -227
  72. package/dist/sol/dex/orca/wavebreak-types.js +0 -23
  73. package/dist/sol/dex/orca/wavebreak.d.ts +0 -78
  74. package/dist/sol/dex/orca/wavebreak.js +0 -497
  75. package/dist/sol/dex/pump/index.d.ts +0 -9
  76. package/dist/sol/dex/pump/index.js +0 -14
  77. package/dist/sol/dex/pump/pump-bundle.d.ts +0 -92
  78. package/dist/sol/dex/pump/pump-bundle.js +0 -383
  79. package/dist/sol/dex/pump/pump-swap-bundle.d.ts +0 -103
  80. package/dist/sol/dex/pump/pump-swap-bundle.js +0 -380
  81. package/dist/sol/dex/pump/pump-swap.d.ts +0 -46
  82. package/dist/sol/dex/pump/pump-swap.js +0 -199
  83. package/dist/sol/dex/pump/pump.d.ts +0 -35
  84. package/dist/sol/dex/pump/pump.js +0 -352
  85. package/dist/sol/dex/pump/types.d.ts +0 -215
  86. package/dist/sol/dex/pump/types.js +0 -5
  87. package/dist/sol/dex/raydium/index.d.ts +0 -8
  88. package/dist/sol/dex/raydium/index.js +0 -12
  89. package/dist/sol/dex/raydium/launchlab.d.ts +0 -68
  90. package/dist/sol/dex/raydium/launchlab.js +0 -210
  91. package/dist/sol/dex/raydium/raydium-bundle.d.ts +0 -64
  92. package/dist/sol/dex/raydium/raydium-bundle.js +0 -324
  93. package/dist/sol/dex/raydium/raydium.d.ts +0 -40
  94. package/dist/sol/dex/raydium/raydium.js +0 -366
  95. package/dist/sol/dex/raydium/types.d.ts +0 -240
  96. package/dist/sol/dex/raydium/types.js +0 -5
  97. package/dist/sol/index.d.ts +0 -10
  98. package/dist/sol/index.js +0 -16
  99. package/dist/sol/jito/bundle.d.ts +0 -90
  100. package/dist/sol/jito/bundle.js +0 -263
  101. package/dist/sol/jito/index.d.ts +0 -7
  102. package/dist/sol/jito/index.js +0 -7
  103. package/dist/sol/jito/tip.d.ts +0 -51
  104. package/dist/sol/jito/tip.js +0 -83
  105. package/dist/sol/jito/types.d.ts +0 -100
  106. package/dist/sol/jito/types.js +0 -5
  107. package/dist/sol/token/create-complete.d.ts +0 -115
  108. package/dist/sol/token/create-complete.js +0 -235
  109. package/dist/sol/token/create-token.d.ts +0 -57
  110. package/dist/sol/token/create-token.js +0 -230
  111. package/dist/sol/token/index.d.ts +0 -9
  112. package/dist/sol/token/index.js +0 -14
  113. package/dist/sol/token/metadata-upload.d.ts +0 -86
  114. package/dist/sol/token/metadata-upload.js +0 -173
  115. package/dist/sol/token/metadata.d.ts +0 -92
  116. package/dist/sol/token/metadata.js +0 -274
  117. package/dist/sol/token/types.d.ts +0 -153
  118. package/dist/sol/token/types.js +0 -5
  119. package/dist/sol/types.d.ts +0 -176
  120. package/dist/sol/types.js +0 -7
  121. package/dist/sol/utils/balance.d.ts +0 -160
  122. package/dist/sol/utils/balance.js +0 -638
  123. package/dist/sol/utils/connection.d.ts +0 -78
  124. package/dist/sol/utils/connection.js +0 -168
  125. package/dist/sol/utils/index.d.ts +0 -9
  126. package/dist/sol/utils/index.js +0 -9
  127. package/dist/sol/utils/lp-inspect.d.ts +0 -129
  128. package/dist/sol/utils/lp-inspect.js +0 -900
  129. package/dist/sol/utils/transfer.d.ts +0 -125
  130. package/dist/sol/utils/transfer.js +0 -220
  131. package/dist/sol/utils/wallet.d.ts +0 -107
  132. package/dist/sol/utils/wallet.js +0 -210
@@ -8,7 +8,7 @@ import { calculateSellAmount } from '../../utils/swap-helpers.js';
8
8
  import { NonceManager, getOptimizedGasPrice } from '../../utils/bundle-helpers.js';
9
9
  import { FLAP_PORTAL_ADDRESSES } from '../constants.js';
10
10
  import { PROFIT_CONFIG } from '../../utils/constants.js';
11
- import { getGasPriceConfig, getTxType, getProfitRecipient } from './config.js';
11
+ import { getGasPriceConfig, getTxType, getProfitRecipient, getBribeAmount, BLOCKRAZOR_BUILDER_EOA } from './config.js';
12
12
  /**
13
13
  * 获取 Gas Limit(支持 FlapAnyConfig)
14
14
  */
@@ -116,7 +116,7 @@ export async function flapBundleSwapMerkle(params) {
116
116
  ]);
117
117
  const { amount: sellAmountWei, decimals } = sellAmountResult;
118
118
  const priorityFee = gasPrice / 10n === 0n ? 1n : gasPrice / 10n;
119
- // ✅ 优化:第二批并行 - approval、quote
119
+ // ✅ 优化:第二批并行 - approval、quote(已移除滑点保护)
120
120
  const [approvalTx, quote] = await Promise.all([
121
121
  config.skipApprovalCheck
122
122
  ? Promise.resolve(null)
@@ -134,7 +134,6 @@ export async function flapBundleSwapMerkle(params) {
134
134
  tokenAddress,
135
135
  sellAmountWei,
136
136
  provider: chainContext.provider,
137
- slippageBps: config.slippageBps,
138
137
  skipQuoteOnError: config.skipQuoteOnError,
139
138
  outputToken // ✅ 传递输出代币
140
139
  })
@@ -144,7 +143,6 @@ export async function flapBundleSwapMerkle(params) {
144
143
  buyer,
145
144
  quotedNative: quote.quotedNative,
146
145
  reserveGasEth: config.reserveGasETH,
147
- slippageBps: config.slippageBps,
148
146
  nativeToken: chainContext.nativeToken,
149
147
  useNativeToken,
150
148
  quoteToken,
@@ -159,6 +157,9 @@ export async function flapBundleSwapMerkle(params) {
159
157
  // 将代币利润转换为等值 BNB
160
158
  nativeProfitAmount = await getTokenToNativeQuote(chainContext.provider, quoteToken, tokenProfitAmount, chainContext.chainId);
161
159
  }
160
+ // ✅ 获取贿赂金额
161
+ const bribeAmount = getBribeAmount(config);
162
+ const needBribeTx = bribeAmount > 0n;
162
163
  // ✅ 优化:第四批并行 - 构建交易、获取 nonces、验证余额
163
164
  const portalSeller = new Contract(chainContext.portalAddress, PORTAL_ABI, seller);
164
165
  const portalBuyer = new Contract(chainContext.portalAddress, PORTAL_ABI, buyer);
@@ -183,6 +184,7 @@ export async function flapBundleSwapMerkle(params) {
183
184
  buyer,
184
185
  approvalExists: !!approvalTx,
185
186
  extractProfit: nativeProfitAmount > 0n,
187
+ needBribeTx, // ✅ 新增:是否需要贿赂交易
186
188
  nonceManager
187
189
  }),
188
190
  validateBalances({
@@ -218,23 +220,38 @@ export async function flapBundleSwapMerkle(params) {
218
220
  txType,
219
221
  value: useNativeToken ? buyerNeed.maxBuyerValue : 0n // ✅ ERC20 购买时 value=0
220
222
  });
221
- // ✅ 优化:并行签名所有交易(包括利润交易)
222
- const signPromises = [
223
- seller.signTransaction(sellTx),
224
- buyer.signTransaction(buyTx),
225
- buildProfitTransaction({
226
- seller,
227
- profitAmount: nativeProfitAmount, // ✅ 使用转换后的原生代币利润
228
- profitNonce: noncePlan.profitNonce,
223
+ // ✅ 贿赂交易放在首位
224
+ let bribeTx = null;
225
+ if (needBribeTx && noncePlan.bribeNonce !== undefined) {
226
+ bribeTx = await seller.signTransaction({
227
+ to: BLOCKRAZOR_BUILDER_EOA,
228
+ value: bribeAmount,
229
+ nonce: noncePlan.bribeNonce,
229
230
  gasPrice,
231
+ gasLimit: 21000n,
230
232
  chainId: chainContext.chainId,
231
- txType
232
- })
233
- ];
234
- const [signedSell, signedBuy, profitTx] = await Promise.all(signPromises);
233
+ type: txType
234
+ });
235
+ }
236
+ // 并行签名卖出和买入交易
237
+ const [signedSell, signedBuy] = await Promise.all([
238
+ seller.signTransaction(sellTx),
239
+ buyer.signTransaction(buyTx)
240
+ ]);
241
+ // ✅ 利润交易放在末尾
242
+ const profitTx = await buildProfitTransaction({
243
+ seller,
244
+ profitAmount: nativeProfitAmount, // ✅ 使用转换后的原生代币利润
245
+ profitNonce: noncePlan.profitNonce,
246
+ gasPrice,
247
+ chainId: chainContext.chainId,
248
+ txType
249
+ });
235
250
  nonceManager.clearTemp();
236
- // 组装交易列表
251
+ // ✅ 组装顺序:贿赂 → 授权 → 卖出 → 买入 → 利润
237
252
  const allTransactions = [];
253
+ if (bribeTx)
254
+ allTransactions.push(bribeTx);
238
255
  if (approvalTx)
239
256
  allTransactions.push(approvalTx);
240
257
  allTransactions.push(signedSell, signedBuy);
@@ -301,32 +318,28 @@ async function buildApprovalTransaction({ tokenAddress, seller, provider, decima
301
318
  type: txType
302
319
  });
303
320
  }
304
- async function quoteSellOutput({ portalAddress, tokenAddress, sellAmountWei, provider, slippageBps, skipQuoteOnError, outputToken = ZERO_ADDRESS // ✅ 默认使用原生代币
321
+ async function quoteSellOutput({ portalAddress, tokenAddress, sellAmountWei, provider, skipQuoteOnError, outputToken = ZERO_ADDRESS // ✅ 默认使用原生代币
305
322
  }) {
306
323
  const portal = new Contract(portalAddress, PORTAL_ABI, provider);
307
- const safeSlippage = Math.max(0, Math.min(5000, slippageBps ?? 100));
308
324
  try {
309
325
  const quotedNative = await portal.quoteExactInput.staticCall({
310
326
  inputToken: tokenAddress,
311
327
  outputToken, // ✅ 使用动态输出代币
312
328
  inputAmount: sellAmountWei
313
329
  });
314
- const keep = BigInt(10000 - safeSlippage);
315
- const minOutNative = (quotedNative * keep) / 10000n;
316
- return { quotedNative, minOutNative };
330
+ // 已移除滑点保护:minOutNative 固定为 0
331
+ return { quotedNative, minOutNative: 0n };
317
332
  }
318
333
  catch (err) {
319
334
  if (skipQuoteOnError ?? true) {
320
- console.warn(`⚠️ 报价失败,使用 minOut = 0: ${err}`);
321
335
  return { quotedNative: 0n, minOutNative: 0n };
322
336
  }
323
337
  throw new Error(`卖出报价失败: ${err}`);
324
338
  }
325
339
  }
326
340
  const ERC20_BALANCE_OF_ABI = ['function balanceOf(address) view returns (uint256)'];
327
- async function calculateBuyerNeed({ buyer, quotedNative, reserveGasEth, slippageBps, nativeToken, useNativeToken = true, quoteToken, quoteTokenDecimals = 18, provider }) {
341
+ async function calculateBuyerNeed({ buyer, quotedNative, reserveGasEth, nativeToken, useNativeToken = true, quoteToken, quoteTokenDecimals = 18, provider }) {
328
342
  const reserveGas = ethers.parseEther((reserveGasEth || 0.0005).toString());
329
- const safeSlippage = Math.max(0, Math.min(5000, slippageBps ?? 100));
330
343
  // ✅ 根据是否使用原生代币获取不同的余额
331
344
  let buyerBalance;
332
345
  if (useNativeToken) {
@@ -337,11 +350,8 @@ async function calculateBuyerNeed({ buyer, quotedNative, reserveGasEth, slippage
337
350
  const erc20 = new Contract(quoteToken, ERC20_BALANCE_OF_ABI, provider || buyer.provider);
338
351
  buyerBalance = await erc20.balanceOf(buyer.address);
339
352
  }
340
- let estimatedBuyerNeed = 0n;
341
- if (quotedNative > 0n) {
342
- const increase = BigInt(10000 + safeSlippage);
343
- estimatedBuyerNeed = (quotedNative * increase) / 10000n;
344
- }
353
+ // 已移除滑点保护:直接使用报价金额
354
+ const estimatedBuyerNeed = quotedNative;
345
355
  // ✅ 原生代币需要预留 Gas,ERC20 不需要
346
356
  const buyerNeedTotal = useNativeToken
347
357
  ? estimatedBuyerNeed + reserveGas
@@ -385,23 +395,25 @@ async function validateBalances({ buyerNeed, buyerAddress, portalGasCost, provid
385
395
  }
386
396
  /**
387
397
  * ✅ 优化:使用批量 nonce 获取(JSON-RPC 批量请求)
398
+ * 交易顺序:贿赂 → 授权 → 卖出 → 买入 → 利润
388
399
  */
389
- async function planNonces({ seller, buyer, approvalExists, extractProfit, nonceManager }) {
390
- if (approvalExists || extractProfit) {
391
- // 卖方需要多个 nonce:使用 getNextNonceBatch
392
- const sellerTxCount = countTruthy([approvalExists, true, extractProfit]);
400
+ async function planNonces({ seller, buyer, approvalExists, extractProfit, needBribeTx, nonceManager }) {
401
+ if (needBribeTx || approvalExists || extractProfit) {
402
+ // 卖方需要多个 nonce:贿赂(可选) + 授权(可选) + 卖出 + 利润(可选)
403
+ const sellerTxCount = countTruthy([needBribeTx, approvalExists, true, extractProfit]);
393
404
  // ✅ 优化:并行获取 seller 和 buyer 的 nonce
394
405
  const [sellerNonces, buyerNonces] = await Promise.all([
395
406
  nonceManager.getNextNonceBatch(seller, sellerTxCount),
396
407
  nonceManager.getNextNoncesForWallets([buyer])
397
408
  ]);
398
409
  let idx = 0;
410
+ const bribeNonce = needBribeTx ? sellerNonces[idx++] : undefined;
399
411
  if (approvalExists)
400
412
  idx++;
401
413
  const sellerNonce = sellerNonces[idx++];
402
414
  const profitNonce = extractProfit ? sellerNonces[idx] : undefined;
403
415
  const buyerNonce = buyerNonces[0];
404
- return { sellerNonce, buyerNonce, profitNonce };
416
+ return { sellerNonce, buyerNonce, bribeNonce, profitNonce };
405
417
  }
406
418
  // ✅ 优化:使用 getNextNoncesForWallets 批量获取(单次网络往返)
407
419
  const nonces = await nonceManager.getNextNoncesForWallets([seller, buyer]);
@@ -483,7 +495,7 @@ export async function flapBatchSwapMerkle(params) {
483
495
  ]);
484
496
  const { amount: sellAmountWei, decimals } = sellAmountResult;
485
497
  const priorityFee = gasPrice / 10n === 0n ? 1n : gasPrice / 10n;
486
- // ✅ 并行获取:授权、报价
498
+ // ✅ 并行获取:授权、报价(已移除滑点保护)
487
499
  const [approvalTx, quote] = await Promise.all([
488
500
  config.skipApprovalCheck
489
501
  ? Promise.resolve(null)
@@ -501,15 +513,12 @@ export async function flapBatchSwapMerkle(params) {
501
513
  tokenAddress,
502
514
  sellAmountWei,
503
515
  provider: chainContext.provider,
504
- slippageBps: config.slippageBps,
505
516
  skipQuoteOnError: config.skipQuoteOnError,
506
517
  outputToken
507
518
  })
508
519
  ]);
509
- // ✅ 计算每个买方的买入金额(按比例分配)
510
- const safeSlippage = Math.max(0, Math.min(5000, config.slippageBps ?? 100));
511
- const increase = BigInt(10000 + safeSlippage);
512
- const totalBuyAmount = (quote.quotedNative * increase) / 10000n;
520
+ // ✅ 计算每个买方的买入金额(按比例分配,已移除滑点保护)
521
+ const totalBuyAmount = quote.quotedNative;
513
522
  let buyAmountsWei;
514
523
  if (params.buyerRatios && params.buyerRatios.length === buyers.length) {
515
524
  // 按比例分配
@@ -575,12 +584,29 @@ export async function flapBatchSwapMerkle(params) {
575
584
  // ✅ 并行获取所有 nonce
576
585
  const sellNonce = await nonceManager.getNextNonce(seller);
577
586
  const buyerNonces = await Promise.all(buyers.map(buyer => nonceManager.getNextNonce(buyer)));
578
- // 利润交易 nonce(从第一个买方发送)
587
+ // 贿赂交易和利润交易都由卖方发送(保持一致)
588
+ const bribeAmount = getBribeAmount(config);
589
+ let bribeTx = null;
590
+ let bribeNonceOffset = 0;
591
+ if (bribeAmount > 0n) {
592
+ const bribeNonce = sellNonce; // 使用卖方的第一个 nonce
593
+ bribeTx = await seller.signTransaction({
594
+ to: BLOCKRAZOR_BUILDER_EOA,
595
+ value: bribeAmount,
596
+ nonce: bribeNonce,
597
+ gasPrice,
598
+ gasLimit: 21000n,
599
+ chainId: chainContext.chainId,
600
+ type: txType
601
+ });
602
+ bribeNonceOffset = 1; // 卖出交易的 nonce 需要 +1
603
+ }
604
+ // 利润交易放在末尾(由卖方发送,与贿赂交易同一钱包)
579
605
  let profitTx = null;
580
606
  if (nativeProfitAmount > 0n) {
581
- const profitPayer = buyers[0];
582
- const profitNonce = await nonceManager.getNextNonce(profitPayer);
583
- profitTx = await profitPayer.signTransaction({
607
+ // 利润交易 nonce = 卖出 nonce + 1
608
+ const profitNonce = sellNonce + bribeNonceOffset + 1;
609
+ profitTx = await seller.signTransaction({
584
610
  to: getProfitRecipient(),
585
611
  value: nativeProfitAmount,
586
612
  nonce: profitNonce,
@@ -594,7 +620,7 @@ export async function flapBatchSwapMerkle(params) {
594
620
  // ✅ 并行签名所有交易
595
621
  const sellTx = buildTransactionRequest(sellUnsigned, {
596
622
  from: seller.address,
597
- nonce: sellNonce,
623
+ nonce: sellNonce + bribeNonceOffset, // ✅ 考虑贿赂交易的 nonce 偏移
598
624
  gasLimit: finalGasLimit,
599
625
  gasPrice,
600
626
  priorityFee,
@@ -618,8 +644,10 @@ export async function flapBatchSwapMerkle(params) {
618
644
  return buyer.signTransaction(buyTx);
619
645
  })
620
646
  ]);
621
- // ✅ 按顺序组装交易数组
647
+ // ✅ 按顺序组装交易数组:贿赂 → 授权 → 卖出 → 买入 → 利润
622
648
  const signedTransactions = [];
649
+ if (bribeTx)
650
+ signedTransactions.push(bribeTx);
623
651
  if (approvalTx)
624
652
  signedTransactions.push(approvalTx);
625
653
  signedTransactions.push(signedSell);
@@ -7,6 +7,7 @@ export type FlapSignConfig = {
7
7
  minGasPriceGwei?: number;
8
8
  nonces?: number[];
9
9
  gasPrice?: bigint;
10
+ bribeAmount?: number;
10
11
  };
11
12
  export type FlapBundleMerkleConfig = {
12
13
  apiKey: string;
package/dist/index.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  export * as Abis from './abis/index.js';
2
- export * as Sol from './sol/index.js';
3
2
  export { ADDRESSES, CHAIN } from './utils/constants.js';
4
3
  export { isExclusiveOnChain, isExclusiveOffChain } from './utils/mpcExclusive.js';
5
- export { ensureSellApprovalV1, checkSellApprovalV1, ensureSellApprovalV2, checkSellApprovalV2, ensureSellApproval, checkSellApproval, ensureFlapSellApproval, checkFlapSellApproval, ensureFlapSellApprovalBatch, checkFlapSellApprovalBatch, checkAllowance, approveToken, checkAllowanceBatch, approveTokenBatch, checkAllowanceRaw, approveTokenRaw, checkAllowanceBatchRaw, approveTokenBatchRaw, type EnsureAllowanceBatchItemResult, type ApproveTokenBatchParams, type ApproveTokenBatchRawParams, type ApproveTokenBatchResult } from './utils/erc20.js';
4
+ export { ensureSellApprovalV1, checkSellApprovalV1, ensureSellApprovalV2, checkSellApprovalV2, ensureSellApproval, checkSellApproval, ensureFlapSellApproval, checkFlapSellApproval, ensureFlapSellApprovalBatch, checkFlapSellApprovalBatch, checkAllowance, approveToken, checkAllowanceBatch, approveTokenBatch, checkAllowanceRaw, approveTokenRaw, checkAllowanceBatchRaw, approveTokenBatchRaw, type EnsureAllowanceBatchItemResult, type ApproveTokenBatchParams, type ApproveTokenBatchRawParams, type ApproveTokenBatchResult, type ApproveTokenBatchSignResult } from './utils/erc20.js';
6
5
  export { parseFourError, type FourErrorCode } from './utils/errors.js';
7
6
  export { getTokenManagerV1, getTokenManagerV2, getTokenManagerHelper3, getTokenManagerV1Writer, getTokenManagerV2Writer, getTokenManagerHelper3Writer, getTokenManagerAddress, type ChainName } from './utils/contract-factory.js';
8
7
  export { FourClient, buildLoginMessage, type FourConfig, type GenerateNonceReq, type LoginReq, type CreateTokenReq, type CreateTokenResp } from './clients/four.js';
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  export * as Abis from './abis/index.js';
2
- export * as Sol from './sol/index.js';
3
2
  export { ADDRESSES, CHAIN } from './utils/constants.js';
4
3
  export { isExclusiveOnChain, isExclusiveOffChain } from './utils/mpcExclusive.js';
5
4
  export {
@@ -13,9 +13,9 @@ export interface PancakeBuyFirstSignConfig {
13
13
  txType?: 0 | 2;
14
14
  chainId?: number;
15
15
  reserveGasBNB?: number;
16
- slippageBps?: number;
17
16
  skipQuoteOnError?: boolean;
18
17
  skipApprovalCheck?: boolean;
18
+ bribeAmount?: number;
19
19
  }
20
20
  export type SwapRouteType = 'v2' | 'v3-single' | 'v3-multi';
21
21
  export interface V2RouteParams {
@@ -6,6 +6,9 @@
6
6
  import { ethers, Contract, Wallet } from 'ethers';
7
7
  import { NonceManager } from '../utils/bundle-helpers.js';
8
8
  import { ADDRESSES, PROFIT_CONFIG } from '../utils/constants.js';
9
+ // ✅ BlockRazor Builder EOA 地址(用于贿赂)
10
+ // 参考文档: https://blockrazor.gitbook.io/blockrazor/bsc/block-builder/send-bundle
11
+ const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
9
12
  function getGasLimit(config, defaultGas = 800000) {
10
13
  if (config.gasLimit !== undefined) {
11
14
  return typeof config.gasLimit === 'bigint' ? config.gasLimit : BigInt(config.gasLimit);
@@ -98,8 +101,7 @@ export async function pancakeBundleBuyFirstMerkle(params) {
98
101
  const buyerNeed = calculateBuyerNeed({
99
102
  quotedNative,
100
103
  buyerBalance: buyerFundsInfo.buyerBalance,
101
- reserveGas: buyerFundsInfo.reserveGas,
102
- slippageBps: config.slippageBps
104
+ reserveGas: buyerFundsInfo.reserveGas
103
105
  });
104
106
  const finalGasLimit = getGasLimit(config);
105
107
  const gasPrice = await getGasPrice(context.provider, config);
@@ -125,14 +127,33 @@ export async function pancakeBundleBuyFirstMerkle(params) {
125
127
  });
126
128
  const profitBase = estimatedProfitFromSell > 0n ? estimatedProfitFromSell : (buyerFundsInfo.buyerFundsWei * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
127
129
  const profitAmount = profitBase;
130
+ // ✅ 获取贿赂金额
131
+ const bribeAmount = config.bribeAmount && config.bribeAmount > 0
132
+ ? ethers.parseEther(String(config.bribeAmount))
133
+ : 0n;
134
+ const needBribeTx = bribeAmount > 0n;
128
135
  const noncePlan = await planNonces({
129
136
  buyer,
130
137
  seller,
131
138
  sameAddress,
132
139
  approvalExists: !!approvalTx,
133
140
  extractProfit: profitAmount > 0n,
141
+ needBribeTx, // ✅ 新增
134
142
  nonceManager
135
143
  });
144
+ // ✅ 贿赂交易放在首位(由卖方发送,与利润交易同一钱包)
145
+ let bribeTx = null;
146
+ if (needBribeTx && noncePlan.bribeNonce !== undefined) {
147
+ bribeTx = await seller.signTransaction({
148
+ to: BLOCKRAZOR_BUILDER_EOA,
149
+ value: bribeAmount,
150
+ nonce: noncePlan.bribeNonce,
151
+ gasPrice,
152
+ gasLimit: 21000n,
153
+ chainId: context.chainId,
154
+ type: txType
155
+ });
156
+ }
136
157
  const signedBuy = await buyer.signTransaction({
137
158
  ...swapUnsigned.buyUnsigned,
138
159
  from: buyer.address,
@@ -151,6 +172,7 @@ export async function pancakeBundleBuyFirstMerkle(params) {
151
172
  chainId: context.chainId,
152
173
  type: txType
153
174
  });
175
+ // ✅ 利润交易放在末尾
154
176
  const profitTx = await buildProfitTransaction({
155
177
  seller,
156
178
  profitAmount,
@@ -172,7 +194,10 @@ export async function pancakeBundleBuyFirstMerkle(params) {
172
194
  provider: context.provider,
173
195
  buyerAddress: buyer.address
174
196
  });
197
+ // ✅ 组装顺序:贿赂 → 授权 → 买入 → 卖出 → 利润
175
198
  const allTransactions = [];
199
+ if (bribeTx)
200
+ allTransactions.push(bribeTx);
176
201
  if (approvalTx)
177
202
  allTransactions.push(approvalTx);
178
203
  allTransactions.push(signedBuy, signedSell);
@@ -303,13 +328,9 @@ async function quoteSellerNative({ provider, tokenAddress, sellAmountToken }) {
303
328
  return 0n;
304
329
  }
305
330
  }
306
- function calculateBuyerNeed({ quotedNative, buyerBalance, reserveGas, slippageBps }) {
307
- let estimatedBuyerNeed = 0n;
308
- if (quotedNative > 0n) {
309
- const safeSlippage = Math.max(0, Math.min(5000, slippageBps ?? 100));
310
- const increase = BigInt(10000 + safeSlippage);
311
- estimatedBuyerNeed = (quotedNative * increase) / 10000n;
312
- }
331
+ function calculateBuyerNeed({ quotedNative, buyerBalance, reserveGas }) {
332
+ // 已移除滑点保护:直接使用报价金额
333
+ const estimatedBuyerNeed = quotedNative;
313
334
  const buyerNeedTotal = estimatedBuyerNeed + reserveGas;
314
335
  if (buyerBalance < buyerNeedTotal) {
315
336
  throw new Error(`买方余额不足:\n - 需要: ${ethers.formatEther(buyerNeedTotal)} BNB\n - 实际: ${ethers.formatEther(buyerBalance)} BNB`);
@@ -381,28 +402,39 @@ async function estimateProfitAmount({ provider, tokenAddress, sellAmountToken })
381
402
  return 0n;
382
403
  }
383
404
  }
384
- async function planNonces({ buyer, seller, sameAddress, approvalExists, extractProfit, nonceManager }) {
405
+ /**
406
+ * ✅ 规划 nonce
407
+ * 交易顺序:贿赂 → 授权 → 买入 → 卖出 → 利润
408
+ */
409
+ async function planNonces({ buyer, seller, sameAddress, approvalExists, extractProfit, needBribeTx, nonceManager }) {
385
410
  if (sameAddress) {
386
- const txCount = countTruthy([approvalExists, true, true, extractProfit]);
411
+ // 同一地址:贿赂(可选) + 授权(可选) + 买入 + 卖出 + 利润(可选)
412
+ const txCount = countTruthy([needBribeTx, approvalExists, true, true, extractProfit]);
387
413
  const nonces = await nonceManager.getNextNonceBatch(buyer, txCount);
388
414
  let idx = 0;
415
+ const bribeNonce = needBribeTx ? nonces[idx++] : undefined;
389
416
  if (approvalExists)
390
417
  idx++;
391
418
  const buyerNonce = nonces[idx++];
392
419
  const sellerNonce = nonces[idx++];
393
420
  const profitNonce = extractProfit ? nonces[idx] : undefined;
394
- return { buyerNonce, sellerNonce, profitNonce };
421
+ return { buyerNonce, sellerNonce, bribeNonce, profitNonce };
395
422
  }
396
- if (approvalExists || extractProfit) {
397
- const sellerTxCount = countTruthy([approvalExists, true, extractProfit]);
398
- const sellerNonces = await nonceManager.getNextNonceBatch(seller, sellerTxCount);
423
+ if (needBribeTx || approvalExists || extractProfit) {
424
+ // 卖方需要多个 nonce:贿赂(可选) + 授权(可选) + 卖出 + 利润(可选)
425
+ const sellerTxCount = countTruthy([needBribeTx, approvalExists, true, extractProfit]);
426
+ // ✅ 并行获取 seller 和 buyer 的 nonce
427
+ const [sellerNonces, buyerNonce] = await Promise.all([
428
+ nonceManager.getNextNonceBatch(seller, sellerTxCount),
429
+ nonceManager.getNextNonce(buyer)
430
+ ]);
399
431
  let idx = 0;
432
+ const bribeNonce = needBribeTx ? sellerNonces[idx++] : undefined;
400
433
  if (approvalExists)
401
434
  idx++;
402
435
  const sellerNonce = sellerNonces[idx++];
403
436
  const profitNonce = extractProfit ? sellerNonces[idx] : undefined;
404
- const buyerNonce = await nonceManager.getNextNonce(buyer);
405
- return { buyerNonce, sellerNonce, profitNonce };
437
+ return { buyerNonce, sellerNonce, bribeNonce, profitNonce };
406
438
  }
407
439
  const [buyerNonce, sellerNonce] = await Promise.all([
408
440
  nonceManager.getNextNonce(buyer),
@@ -8,8 +8,8 @@ export interface PancakeSwapSignConfig {
8
8
  txType?: 0 | 2;
9
9
  chainId?: number;
10
10
  reserveGasBNB?: number;
11
- slippageTolerance?: number;
12
11
  skipApprovalCheck?: boolean;
12
+ bribeAmount?: number;
13
13
  }
14
14
  export type SwapRouteType = 'v2' | 'v3-single' | 'v3-multi';
15
15
  export interface PancakeSwapConfig extends CommonBundleConfig {
@@ -46,7 +46,6 @@ export interface PancakeBundleSwapSignParams {
46
46
  buyerPrivateKey: string;
47
47
  tokenAddress: string;
48
48
  routeParams: RouteParams;
49
- slippageTolerance?: number;
50
49
  config: PancakeSwapSignConfig;
51
50
  quoteToken?: string;
52
51
  quoteTokenDecimals?: number;
@@ -58,7 +57,6 @@ export interface PancakeBundleSwapParams {
58
57
  buyerPrivateKey: string;
59
58
  tokenAddress: string;
60
59
  routeParams: RouteParams;
61
- slippageTolerance?: number;
62
60
  config: PancakeSwapConfig;
63
61
  }
64
62
  /** ✅ Pancake Swap 结果(简化版) */
@@ -90,7 +88,6 @@ export interface PancakeBatchSwapSignParams {
90
88
  buyerRatios?: number[];
91
89
  tokenAddress: string;
92
90
  routeParams: RouteParams;
93
- slippageTolerance?: number;
94
91
  config: PancakeSwapSignConfig;
95
92
  quoteToken?: string;
96
93
  quoteTokenDecimals?: number;