four-flap-meme-sdk 1.3.93 → 1.3.94

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