four-flap-meme-sdk 1.3.88 → 1.3.89

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 (122) hide show
  1. package/dist/clients/blockrazor.js +0 -1
  2. package/dist/contracts/tm-bundle-merkle/core.js +6 -3
  3. package/dist/contracts/tm-bundle-merkle/pancake-proxy.js +30 -38
  4. package/dist/contracts/tm-bundle-merkle/swap-buy-first.d.ts +0 -1
  5. package/dist/contracts/tm-bundle-merkle/swap-buy-first.js +4 -3
  6. package/dist/contracts/tm-bundle-merkle/swap.d.ts +0 -3
  7. package/dist/contracts/tm-bundle-merkle/swap.js +2 -2
  8. package/dist/flap/portal-bundle-merkle/core.js +2 -6
  9. package/dist/flap/portal-bundle-merkle/encryption.d.ts +16 -0
  10. package/dist/flap/portal-bundle-merkle/encryption.js +146 -0
  11. package/dist/flap/portal-bundle-merkle/pancake-proxy.js +55 -35
  12. package/dist/flap/portal-bundle-merkle/swap-buy-first.d.ts +0 -2
  13. package/dist/flap/portal-bundle-merkle/swap-buy-first.js +6 -11
  14. package/dist/flap/portal-bundle-merkle/swap.d.ts +0 -2
  15. package/dist/flap/portal-bundle-merkle/swap.js +10 -22
  16. package/dist/index.d.ts +1 -2
  17. package/dist/index.js +0 -1
  18. package/dist/pancake/bundle-buy-first.d.ts +0 -1
  19. package/dist/pancake/bundle-buy-first.js +4 -9
  20. package/dist/pancake/bundle-swap.d.ts +0 -4
  21. package/dist/pancake/bundle-swap.js +7 -14
  22. package/dist/utils/erc20.d.ts +108 -2
  23. package/dist/utils/erc20.js +65 -17
  24. package/package.json +4 -39
  25. package/dist/sol/constants.d.ts +0 -126
  26. package/dist/sol/constants.js +0 -145
  27. package/dist/sol/dex/index.d.ts +0 -8
  28. package/dist/sol/dex/index.js +0 -12
  29. package/dist/sol/dex/meteora/client.d.ts +0 -76
  30. package/dist/sol/dex/meteora/client.js +0 -219
  31. package/dist/sol/dex/meteora/damm-v1-bundle.d.ts +0 -61
  32. package/dist/sol/dex/meteora/damm-v1-bundle.js +0 -112
  33. package/dist/sol/dex/meteora/damm-v1.d.ts +0 -118
  34. package/dist/sol/dex/meteora/damm-v1.js +0 -315
  35. package/dist/sol/dex/meteora/damm-v2-bundle.d.ts +0 -82
  36. package/dist/sol/dex/meteora/damm-v2-bundle.js +0 -242
  37. package/dist/sol/dex/meteora/damm-v2.d.ts +0 -172
  38. package/dist/sol/dex/meteora/damm-v2.js +0 -632
  39. package/dist/sol/dex/meteora/dbc-bundle.d.ts +0 -123
  40. package/dist/sol/dex/meteora/dbc-bundle.js +0 -304
  41. package/dist/sol/dex/meteora/dbc.d.ts +0 -192
  42. package/dist/sol/dex/meteora/dbc.js +0 -619
  43. package/dist/sol/dex/meteora/dlmm-bundle.d.ts +0 -39
  44. package/dist/sol/dex/meteora/dlmm-bundle.js +0 -189
  45. package/dist/sol/dex/meteora/dlmm.d.ts +0 -146
  46. package/dist/sol/dex/meteora/dlmm.js +0 -593
  47. package/dist/sol/dex/meteora/index.d.ts +0 -25
  48. package/dist/sol/dex/meteora/index.js +0 -65
  49. package/dist/sol/dex/meteora/types.d.ts +0 -787
  50. package/dist/sol/dex/meteora/types.js +0 -110
  51. package/dist/sol/dex/orca/index.d.ts +0 -10
  52. package/dist/sol/dex/orca/index.js +0 -16
  53. package/dist/sol/dex/orca/orca-bundle.d.ts +0 -41
  54. package/dist/sol/dex/orca/orca-bundle.js +0 -173
  55. package/dist/sol/dex/orca/orca.d.ts +0 -65
  56. package/dist/sol/dex/orca/orca.js +0 -474
  57. package/dist/sol/dex/orca/types.d.ts +0 -263
  58. package/dist/sol/dex/orca/types.js +0 -38
  59. package/dist/sol/dex/orca/wavebreak-bundle.d.ts +0 -34
  60. package/dist/sol/dex/orca/wavebreak-bundle.js +0 -198
  61. package/dist/sol/dex/orca/wavebreak-types.d.ts +0 -227
  62. package/dist/sol/dex/orca/wavebreak-types.js +0 -23
  63. package/dist/sol/dex/orca/wavebreak.d.ts +0 -78
  64. package/dist/sol/dex/orca/wavebreak.js +0 -486
  65. package/dist/sol/dex/pump/index.d.ts +0 -9
  66. package/dist/sol/dex/pump/index.js +0 -14
  67. package/dist/sol/dex/pump/pump-bundle.d.ts +0 -92
  68. package/dist/sol/dex/pump/pump-bundle.js +0 -383
  69. package/dist/sol/dex/pump/pump-swap-bundle.d.ts +0 -103
  70. package/dist/sol/dex/pump/pump-swap-bundle.js +0 -380
  71. package/dist/sol/dex/pump/pump-swap.d.ts +0 -46
  72. package/dist/sol/dex/pump/pump-swap.js +0 -199
  73. package/dist/sol/dex/pump/pump.d.ts +0 -35
  74. package/dist/sol/dex/pump/pump.js +0 -352
  75. package/dist/sol/dex/pump/types.d.ts +0 -215
  76. package/dist/sol/dex/pump/types.js +0 -5
  77. package/dist/sol/dex/raydium/index.d.ts +0 -8
  78. package/dist/sol/dex/raydium/index.js +0 -12
  79. package/dist/sol/dex/raydium/launchlab.d.ts +0 -68
  80. package/dist/sol/dex/raydium/launchlab.js +0 -210
  81. package/dist/sol/dex/raydium/raydium-bundle.d.ts +0 -64
  82. package/dist/sol/dex/raydium/raydium-bundle.js +0 -324
  83. package/dist/sol/dex/raydium/raydium.d.ts +0 -40
  84. package/dist/sol/dex/raydium/raydium.js +0 -366
  85. package/dist/sol/dex/raydium/types.d.ts +0 -240
  86. package/dist/sol/dex/raydium/types.js +0 -5
  87. package/dist/sol/index.d.ts +0 -10
  88. package/dist/sol/index.js +0 -16
  89. package/dist/sol/jito/bundle.d.ts +0 -90
  90. package/dist/sol/jito/bundle.js +0 -263
  91. package/dist/sol/jito/index.d.ts +0 -7
  92. package/dist/sol/jito/index.js +0 -7
  93. package/dist/sol/jito/tip.d.ts +0 -51
  94. package/dist/sol/jito/tip.js +0 -83
  95. package/dist/sol/jito/types.d.ts +0 -100
  96. package/dist/sol/jito/types.js +0 -5
  97. package/dist/sol/token/create-complete.d.ts +0 -115
  98. package/dist/sol/token/create-complete.js +0 -235
  99. package/dist/sol/token/create-token.d.ts +0 -57
  100. package/dist/sol/token/create-token.js +0 -230
  101. package/dist/sol/token/index.d.ts +0 -9
  102. package/dist/sol/token/index.js +0 -14
  103. package/dist/sol/token/metadata-upload.d.ts +0 -86
  104. package/dist/sol/token/metadata-upload.js +0 -173
  105. package/dist/sol/token/metadata.d.ts +0 -92
  106. package/dist/sol/token/metadata.js +0 -274
  107. package/dist/sol/token/types.d.ts +0 -153
  108. package/dist/sol/token/types.js +0 -5
  109. package/dist/sol/types.d.ts +0 -176
  110. package/dist/sol/types.js +0 -7
  111. package/dist/sol/utils/balance.d.ts +0 -160
  112. package/dist/sol/utils/balance.js +0 -638
  113. package/dist/sol/utils/connection.d.ts +0 -78
  114. package/dist/sol/utils/connection.js +0 -168
  115. package/dist/sol/utils/index.d.ts +0 -9
  116. package/dist/sol/utils/index.js +0 -9
  117. package/dist/sol/utils/lp-inspect.d.ts +0 -129
  118. package/dist/sol/utils/lp-inspect.js +0 -521
  119. package/dist/sol/utils/transfer.d.ts +0 -125
  120. package/dist/sol/utils/transfer.js +0 -220
  121. package/dist/sol/utils/wallet.d.ts +0 -107
  122. package/dist/sol/utils/wallet.js +0 -210
@@ -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,
@@ -301,32 +299,28 @@ async function buildApprovalTransaction({ tokenAddress, seller, provider, decima
301
299
  type: txType
302
300
  });
303
301
  }
304
- async function quoteSellOutput({ portalAddress, tokenAddress, sellAmountWei, provider, slippageBps, skipQuoteOnError, outputToken = ZERO_ADDRESS // ✅ 默认使用原生代币
302
+ async function quoteSellOutput({ portalAddress, tokenAddress, sellAmountWei, provider, skipQuoteOnError, outputToken = ZERO_ADDRESS // ✅ 默认使用原生代币
305
303
  }) {
306
304
  const portal = new Contract(portalAddress, PORTAL_ABI, provider);
307
- const safeSlippage = Math.max(0, Math.min(5000, slippageBps ?? 100));
308
305
  try {
309
306
  const quotedNative = await portal.quoteExactInput.staticCall({
310
307
  inputToken: tokenAddress,
311
308
  outputToken, // ✅ 使用动态输出代币
312
309
  inputAmount: sellAmountWei
313
310
  });
314
- const keep = BigInt(10000 - safeSlippage);
315
- const minOutNative = (quotedNative * keep) / 10000n;
316
- return { quotedNative, minOutNative };
311
+ // 已移除滑点保护:minOutNative 固定为 0
312
+ return { quotedNative, minOutNative: 0n };
317
313
  }
318
314
  catch (err) {
319
315
  if (skipQuoteOnError ?? true) {
320
- console.warn(`⚠️ 报价失败,使用 minOut = 0: ${err}`);
321
316
  return { quotedNative: 0n, minOutNative: 0n };
322
317
  }
323
318
  throw new Error(`卖出报价失败: ${err}`);
324
319
  }
325
320
  }
326
321
  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 }) {
322
+ async function calculateBuyerNeed({ buyer, quotedNative, reserveGasEth, nativeToken, useNativeToken = true, quoteToken, quoteTokenDecimals = 18, provider }) {
328
323
  const reserveGas = ethers.parseEther((reserveGasEth || 0.0005).toString());
329
- const safeSlippage = Math.max(0, Math.min(5000, slippageBps ?? 100));
330
324
  // ✅ 根据是否使用原生代币获取不同的余额
331
325
  let buyerBalance;
332
326
  if (useNativeToken) {
@@ -337,11 +331,8 @@ async function calculateBuyerNeed({ buyer, quotedNative, reserveGasEth, slippage
337
331
  const erc20 = new Contract(quoteToken, ERC20_BALANCE_OF_ABI, provider || buyer.provider);
338
332
  buyerBalance = await erc20.balanceOf(buyer.address);
339
333
  }
340
- let estimatedBuyerNeed = 0n;
341
- if (quotedNative > 0n) {
342
- const increase = BigInt(10000 + safeSlippage);
343
- estimatedBuyerNeed = (quotedNative * increase) / 10000n;
344
- }
334
+ // 已移除滑点保护:直接使用报价金额
335
+ const estimatedBuyerNeed = quotedNative;
345
336
  // ✅ 原生代币需要预留 Gas,ERC20 不需要
346
337
  const buyerNeedTotal = useNativeToken
347
338
  ? estimatedBuyerNeed + reserveGas
@@ -483,7 +474,7 @@ export async function flapBatchSwapMerkle(params) {
483
474
  ]);
484
475
  const { amount: sellAmountWei, decimals } = sellAmountResult;
485
476
  const priorityFee = gasPrice / 10n === 0n ? 1n : gasPrice / 10n;
486
- // ✅ 并行获取:授权、报价
477
+ // ✅ 并行获取:授权、报价(已移除滑点保护)
487
478
  const [approvalTx, quote] = await Promise.all([
488
479
  config.skipApprovalCheck
489
480
  ? Promise.resolve(null)
@@ -501,15 +492,12 @@ export async function flapBatchSwapMerkle(params) {
501
492
  tokenAddress,
502
493
  sellAmountWei,
503
494
  provider: chainContext.provider,
504
- slippageBps: config.slippageBps,
505
495
  skipQuoteOnError: config.skipQuoteOnError,
506
496
  outputToken
507
497
  })
508
498
  ]);
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;
499
+ // ✅ 计算每个买方的买入金额(按比例分配,已移除滑点保护)
500
+ const totalBuyAmount = quote.quotedNative;
513
501
  let buyAmountsWei;
514
502
  if (params.buyerRatios && params.buyerRatios.length === buyers.length) {
515
503
  // 按比例分配
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,7 +13,6 @@ 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;
19
18
  }
@@ -98,8 +98,7 @@ export async function pancakeBundleBuyFirstMerkle(params) {
98
98
  const buyerNeed = calculateBuyerNeed({
99
99
  quotedNative,
100
100
  buyerBalance: buyerFundsInfo.buyerBalance,
101
- reserveGas: buyerFundsInfo.reserveGas,
102
- slippageBps: config.slippageBps
101
+ reserveGas: buyerFundsInfo.reserveGas
103
102
  });
104
103
  const finalGasLimit = getGasLimit(config);
105
104
  const gasPrice = await getGasPrice(context.provider, config);
@@ -303,13 +302,9 @@ async function quoteSellerNative({ provider, tokenAddress, sellAmountToken }) {
303
302
  return 0n;
304
303
  }
305
304
  }
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
- }
305
+ function calculateBuyerNeed({ quotedNative, buyerBalance, reserveGas }) {
306
+ // 已移除滑点保护:直接使用报价金额
307
+ const estimatedBuyerNeed = quotedNative;
313
308
  const buyerNeedTotal = estimatedBuyerNeed + reserveGas;
314
309
  if (buyerBalance < buyerNeedTotal) {
315
310
  throw new Error(`买方余额不足:\n - 需要: ${ethers.formatEther(buyerNeedTotal)} BNB\n - 实际: ${ethers.formatEther(buyerBalance)} BNB`);
@@ -8,7 +8,6 @@ export interface PancakeSwapSignConfig {
8
8
  txType?: 0 | 2;
9
9
  chainId?: number;
10
10
  reserveGasBNB?: number;
11
- slippageTolerance?: number;
12
11
  skipApprovalCheck?: boolean;
13
12
  }
14
13
  export type SwapRouteType = 'v2' | 'v3-single' | 'v3-multi';
@@ -46,7 +45,6 @@ export interface PancakeBundleSwapSignParams {
46
45
  buyerPrivateKey: string;
47
46
  tokenAddress: string;
48
47
  routeParams: RouteParams;
49
- slippageTolerance?: number;
50
48
  config: PancakeSwapSignConfig;
51
49
  quoteToken?: string;
52
50
  quoteTokenDecimals?: number;
@@ -58,7 +56,6 @@ export interface PancakeBundleSwapParams {
58
56
  buyerPrivateKey: string;
59
57
  tokenAddress: string;
60
58
  routeParams: RouteParams;
61
- slippageTolerance?: number;
62
59
  config: PancakeSwapConfig;
63
60
  }
64
61
  /** ✅ Pancake Swap 结果(简化版) */
@@ -90,7 +87,6 @@ export interface PancakeBatchSwapSignParams {
90
87
  buyerRatios?: number[];
91
88
  tokenAddress: string;
92
89
  routeParams: RouteParams;
93
- slippageTolerance?: number;
94
90
  config: PancakeSwapSignConfig;
95
91
  quoteToken?: string;
96
92
  quoteTokenDecimals?: number;
@@ -99,9 +99,10 @@ async function buildSwapTransactions({ routeParams, sellAmountWei, buyAmountBNB,
99
99
  );
100
100
  return { sellUnsigned, buyUnsigned };
101
101
  }
102
- async function calculateBuyerBudget({ buyer, quotedBNBOut, reserveGasBNB, slippageTolerance, useNativeToken = true, quoteToken, quoteTokenDecimals = 18, provider }) {
102
+ async function calculateBuyerBudget({ buyer, quotedBNBOut, reserveGasBNB, useNativeToken = true, quoteToken, quoteTokenDecimals = 18, provider }) {
103
103
  const reserveGas = ethers.parseEther((reserveGasBNB ?? 0.0005).toString());
104
- const buyAmountBNB = applySlippage(quotedBNBOut, slippageTolerance);
104
+ // 已移除滑点保护:直接使用报价金额
105
+ const buyAmountBNB = quotedBNBOut;
105
106
  // ✅ 根据是否使用原生代币获取不同的余额
106
107
  let buyerBalance;
107
108
  if (useNativeToken) {
@@ -128,13 +129,6 @@ async function calculateBuyerBudget({ buyer, quotedBNBOut, reserveGasBNB, slippa
128
129
  return { buyerBalance, reserveGas, requiredBalance, buyAmountBNB, useNativeToken };
129
130
  }
130
131
  }
131
- function applySlippage(amount, tolerancePercent = 0.5) {
132
- if (amount === 0n) {
133
- return 0n;
134
- }
135
- const bps = BigInt(Math.round(Math.max(0, tolerancePercent) * 100));
136
- return (amount * (10000n + bps)) / 10000n;
137
- }
138
132
  async function planNonces({ seller, buyer, sameAddress, approvalExists, profitNeeded, nonceManager }) {
139
133
  if (sameAddress) {
140
134
  const txCount = countTruthy([approvalExists, true, true, profitNeeded]);
@@ -285,7 +279,7 @@ const ERC20_BALANCE_OF_ABI = ['function balanceOf(address) view returns (uint256
285
279
  * ✅ 支持 quoteToken:传入 USDT 等地址时,卖出得到该代币,买入使用该代币
286
280
  */
287
281
  export async function pancakeBundleSwapMerkle(params) {
288
- const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKey, tokenAddress, routeParams, slippageTolerance = 0.5, config, quoteToken, quoteTokenDecimals = 18 } = params;
282
+ const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKey, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18 } = params;
289
283
  // ✅ 判断是否使用原生代币(BNB)或 ERC20 代币(如 USDT)
290
284
  const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
291
285
  const context = createPancakeContext(config);
@@ -319,7 +313,6 @@ export async function pancakeBundleSwapMerkle(params) {
319
313
  buyer,
320
314
  quotedBNBOut: quoteResult.estimatedBNBOut,
321
315
  reserveGasBNB: config.reserveGasBNB,
322
- slippageTolerance,
323
316
  useNativeToken,
324
317
  quoteToken,
325
318
  quoteTokenDecimals,
@@ -412,7 +405,7 @@ export async function pancakeBundleSwapMerkle(params) {
412
405
  * 交易顺序:[授权(可选)] → [卖出] → [买入1, 买入2, ..., 买入N] → [利润]
413
406
  */
414
407
  export async function pancakeBatchSwapMerkle(params) {
415
- const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerAmounts, tokenAddress, routeParams, slippageTolerance = 0.5, config, quoteToken, quoteTokenDecimals = 18 } = params;
408
+ const { sellerPrivateKey, sellAmount, sellPercentage, buyerPrivateKeys, buyerAmounts, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18 } = params;
416
409
  // ✅ 校验买方数量(最多 24 个)
417
410
  const MAX_BUYERS = 24;
418
411
  if (buyerPrivateKeys.length === 0) {
@@ -451,9 +444,9 @@ export async function pancakeBatchSwapMerkle(params) {
451
444
  provider: context.provider
452
445
  });
453
446
  const estimatedBNBOut = quoteResult.estimatedBNBOut;
454
- // ✅ 计算每个买方的买入金额
447
+ // ✅ 计算每个买方的买入金额(已移除滑点保护:直接使用报价金额)
455
448
  let buyAmountsWei;
456
- const totalBuyAmount = applySlippage(estimatedBNBOut, slippageTolerance);
449
+ const totalBuyAmount = estimatedBNBOut;
457
450
  if (buyerAmounts && buyerAmounts.length === buyers.length) {
458
451
  // 方式1:使用指定的买入金额(USDT)
459
452
  buyAmountsWei = buyerAmounts.map(amt => useNativeToken
@@ -167,6 +167,14 @@ export type ApproveTokenBatchParams = {
167
167
  privateKeys: string[];
168
168
  tokenAddress: string;
169
169
  amounts: (bigint | 'max')[];
170
+ /** 是否只签名不提交(默认 false,直接发送交易) */
171
+ signOnly?: boolean;
172
+ /** Gas Price(可选,单位 Gwei,signOnly=true 时生效) */
173
+ gasPriceGwei?: number;
174
+ /** Gas Limit(可选,默认 100000,signOnly=true 时生效) */
175
+ gasLimit?: number;
176
+ /** 链ID(可选,默认56=BSC,signOnly=true 时生效) */
177
+ chainId?: number;
170
178
  };
171
179
  export type ApproveTokenBatchRawParams = {
172
180
  rpcUrl: string;
@@ -174,7 +182,16 @@ export type ApproveTokenBatchRawParams = {
174
182
  tokenAddress: string;
175
183
  spenderAddress: string;
176
184
  amounts: (bigint | 'max')[];
185
+ /** 是否只签名不提交(默认 false,直接发送交易) */
186
+ signOnly?: boolean;
187
+ /** Gas Price(可选,单位 Gwei,signOnly=true 时生效) */
188
+ gasPriceGwei?: number;
189
+ /** Gas Limit(可选,默认 100000,signOnly=true 时生效) */
190
+ gasLimit?: number;
191
+ /** 链ID(可选,默认56=BSC,signOnly=true 时生效) */
192
+ chainId?: number;
177
193
  };
194
+ /** signOnly=false 时的返回结果(直接发送交易) */
178
195
  export type ApproveTokenBatchResult = {
179
196
  success: boolean;
180
197
  approvedCount: number;
@@ -187,18 +204,107 @@ export type ApproveTokenBatchResult = {
187
204
  error?: string;
188
205
  }>;
189
206
  };
207
+ /** signOnly=true 时的返回结果(仅签名) */
208
+ export type ApproveTokenBatchSignResult = {
209
+ /** 需要授权的签名交易数组(已过滤掉已授权的钱包) */
210
+ signedTransactions: string[];
211
+ /** 详细结果 */
212
+ results: Array<{
213
+ owner: string;
214
+ /** 是否已授权(无需发送交易) */
215
+ alreadyApproved: boolean;
216
+ currentAllowance: bigint;
217
+ requiredAllowance: bigint;
218
+ /** 签名交易(仅当 alreadyApproved=false 时有值) */
219
+ signedTx?: string;
220
+ }>;
221
+ /** 需要授权的钱包数量 */
222
+ needApproveCount: number;
223
+ /** 已授权的钱包数量 */
224
+ alreadyApprovedCount: number;
225
+ };
190
226
  /**
191
227
  * ✅ 智能路由:批量授权 ERC20 代币(自动选择 spender,自动检查,只在不足时才发送交易)
192
228
  *
193
229
  * @param params - 批量授权参数
230
+ * @param params.signOnly - 是否只签名不提交(默认 false)
231
+ * - false: 直接发送交易并等待确认,返回 ApproveTokenBatchResult
232
+ * - true: 只签名不提交,返回 ApproveTokenBatchSignResult,前端可通过 submitBundleToBlockRazor 提交
194
233
  * @returns 批量授权结果
234
+ *
235
+ * @example
236
+ * ```typescript
237
+ * // 模式1:直接发送交易(默认)
238
+ * const result = await approveTokenBatch({
239
+ * chain: 'BSC',
240
+ * platform: 'four',
241
+ * rpcUrl: 'https://bsc-dataseed.binance.org',
242
+ * privateKeys: [key1, key2],
243
+ * tokenAddress: '0x...',
244
+ * amounts: ['max', 'max']
245
+ * });
246
+ *
247
+ * // 模式2:只签名,前端提交
248
+ * const signResult = await approveTokenBatch({
249
+ * chain: 'BSC',
250
+ * platform: 'four',
251
+ * rpcUrl: 'https://bsc-dataseed.binance.org',
252
+ * privateKeys: [key1, key2],
253
+ * tokenAddress: '0x...',
254
+ * amounts: ['max', 'max'],
255
+ * signOnly: true
256
+ * });
257
+ * // 提交到 BlockRazor
258
+ * if (signResult.signedTransactions.length > 0) {
259
+ * await submitBundleToBlockRazor(signResult.signedTransactions, { blockOffset: 10 });
260
+ * }
261
+ * ```
195
262
  */
196
- export declare function approveTokenBatch(params: ApproveTokenBatchParams): Promise<ApproveTokenBatchResult>;
263
+ export declare function approveTokenBatch(params: ApproveTokenBatchParams & {
264
+ signOnly: true;
265
+ }): Promise<ApproveTokenBatchSignResult>;
266
+ export declare function approveTokenBatch(params: ApproveTokenBatchParams & {
267
+ signOnly?: false;
268
+ }): Promise<ApproveTokenBatchResult>;
197
269
  /**
198
270
  * ✅ 底层方法:批量授权 ERC20 代币(手动指定 spender)
199
271
  * 适用于任意 spender 地址(Flap、Four、PancakeSwap V2/V3 等)
200
272
  *
201
273
  * @param params - 批量授权参数
274
+ * @param params.signOnly - 是否只签名不提交(默认 false)
275
+ * - false: 直接发送交易并等待确认,返回 ApproveTokenBatchResult
276
+ * - true: 只签名不提交,返回 ApproveTokenBatchSignResult,前端可通过 submitBundleToBlockRazor 提交
202
277
  * @returns 批量授权结果
278
+ *
279
+ * @example
280
+ * ```typescript
281
+ * // 模式1:直接发送交易(默认)
282
+ * const result = await approveTokenBatchRaw({
283
+ * rpcUrl: 'https://bsc-dataseed.binance.org',
284
+ * privateKeys: [key1, key2],
285
+ * tokenAddress: '0x...',
286
+ * spenderAddress: '0x...',
287
+ * amounts: ['max', 'max']
288
+ * });
289
+ *
290
+ * // 模式2:只签名,前端提交
291
+ * const signResult = await approveTokenBatchRaw({
292
+ * rpcUrl: 'https://bsc-dataseed.binance.org',
293
+ * privateKeys: [key1, key2],
294
+ * tokenAddress: '0x...',
295
+ * spenderAddress: '0x...',
296
+ * amounts: ['max', 'max'],
297
+ * signOnly: true
298
+ * });
299
+ * // 提交到 BlockRazor
300
+ * if (signResult.signedTransactions.length > 0) {
301
+ * await submitBundleToBlockRazor(signResult.signedTransactions, { blockOffset: 10 });
302
+ * }
303
+ * ```
203
304
  */
204
- export declare function approveTokenBatchRaw(params: ApproveTokenBatchRawParams): Promise<ApproveTokenBatchResult>;
305
+ export declare function approveTokenBatchRaw(params: ApproveTokenBatchRawParams & {
306
+ signOnly: true;
307
+ }): Promise<ApproveTokenBatchSignResult>;
308
+ export declare function approveTokenBatchRaw(params: ApproveTokenBatchRawParams & {
309
+ signOnly?: false;
310
+ }): Promise<ApproveTokenBatchResult>;
@@ -1,4 +1,4 @@
1
- import { Contract, Wallet, JsonRpcProvider } from 'ethers';
1
+ import { Contract, Wallet, JsonRpcProvider, Interface, parseUnits } from 'ethers';
2
2
  import { ADDRESSES } from './constants.js';
3
3
  const ERC20_ABI = [
4
4
  { "constant": false, "inputs": [{ "name": "spender", "type": "address" }, { "name": "value", "type": "uint256" }], "name": "approve", "outputs": [{ "name": "", "type": "bool" }], "type": "function" },
@@ -482,26 +482,13 @@ export async function checkAllowanceBatchRaw(rpcUrl, tokenAddress, ownerAddresse
482
482
  await validateContractAddress(provider, normalizedSpender, 'Spender');
483
483
  return batchCheckAllowances(provider, normalizedToken, normalizedOwners, normalizedSpender);
484
484
  }
485
- /**
486
- * ✅ 智能路由:批量授权 ERC20 代币(自动选择 spender,自动检查,只在不足时才发送交易)
487
- *
488
- * @param params - 批量授权参数
489
- * @returns 批量授权结果
490
- */
491
485
  export async function approveTokenBatch(params) {
492
- const { chain, platform, rpcUrl, privateKeys, tokenAddress, amounts } = params;
486
+ const { chain, platform, rpcUrl, privateKeys, tokenAddress, amounts, signOnly, gasPriceGwei, gasLimit, chainId } = params;
493
487
  const spenderAddress = resolveSpenderAddress(chain, platform);
494
- return approveTokenBatchRaw({ rpcUrl, privateKeys, tokenAddress, spenderAddress, amounts });
488
+ return approveTokenBatchRaw({ rpcUrl, privateKeys, tokenAddress, spenderAddress, amounts, signOnly, gasPriceGwei, gasLimit, chainId });
495
489
  }
496
- /**
497
- * ✅ 底层方法:批量授权 ERC20 代币(手动指定 spender)
498
- * 适用于任意 spender 地址(Flap、Four、PancakeSwap V2/V3 等)
499
- *
500
- * @param params - 批量授权参数
501
- * @returns 批量授权结果
502
- */
503
490
  export async function approveTokenBatchRaw(params) {
504
- const { rpcUrl, privateKeys, tokenAddress, spenderAddress, amounts } = params;
491
+ const { rpcUrl, privateKeys, tokenAddress, spenderAddress, amounts, signOnly, gasPriceGwei, gasLimit, chainId = 56 } = params;
505
492
  if (privateKeys.length === 0 || amounts.length !== privateKeys.length) {
506
493
  throw new Error('❌ 私钥数量和授权数量必须匹配');
507
494
  }
@@ -518,6 +505,67 @@ export async function approveTokenBatchRaw(params) {
518
505
  const requiredAmounts = amounts.map(amount => amount === 'max'
519
506
  ? BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')
520
507
  : amount);
508
+ // ==================== signOnly=true:只签名不提交 ====================
509
+ if (signOnly) {
510
+ // ✅ 并行获取:当前授权额度 + nonces + gasPrice
511
+ const [currentAllowances, nonces, fetchedGasPrice] = await Promise.all([
512
+ batchCheckAllowances(provider, normalizedToken, ownerAddresses, normalizedSpender),
513
+ Promise.all(wallets.map(w => provider.getTransactionCount(w.address, 'latest'))),
514
+ gasPriceGwei ? Promise.resolve(parseUnits(gasPriceGwei.toString(), 'gwei')) : provider.getFeeData().then(fee => fee.gasPrice || parseUnits('3', 'gwei'))
515
+ ]);
516
+ const finalGasPrice = fetchedGasPrice;
517
+ const finalGasLimit = BigInt(gasLimit || 100000);
518
+ // ✅ ERC20 approve 函数的 ABI 编码
519
+ const erc20Interface = new Interface(ERC20_ABI);
520
+ // ✅ 并行签名所有需要授权的交易
521
+ const signPromises = wallets.map(async (wallet, i) => {
522
+ const ownerAddress = ownerAddresses[i];
523
+ const currentAllowance = currentAllowances[i];
524
+ const requiredAmount = requiredAmounts[i];
525
+ // 如果已经授权足够,跳过
526
+ if (currentAllowance >= requiredAmount) {
527
+ return {
528
+ owner: ownerAddress,
529
+ alreadyApproved: true,
530
+ currentAllowance,
531
+ requiredAllowance: requiredAmount,
532
+ signedTx: undefined
533
+ };
534
+ }
535
+ // 构建并签名交易
536
+ const txData = erc20Interface.encodeFunctionData('approve', [normalizedSpender, requiredAmount]);
537
+ const signedTx = await wallet.signTransaction({
538
+ to: normalizedToken,
539
+ data: txData,
540
+ nonce: nonces[i],
541
+ gasLimit: finalGasLimit,
542
+ gasPrice: finalGasPrice,
543
+ chainId,
544
+ type: 0 // Legacy 交易
545
+ });
546
+ return {
547
+ owner: ownerAddress,
548
+ alreadyApproved: false,
549
+ currentAllowance,
550
+ requiredAllowance: requiredAmount,
551
+ signedTx
552
+ };
553
+ });
554
+ const results = await Promise.all(signPromises);
555
+ // ✅ 提取所有签名交易(过滤掉已授权的)
556
+ const signedTransactions = results
557
+ .filter(r => !r.alreadyApproved && r.signedTx)
558
+ .map(r => r.signedTx);
559
+ const alreadyApprovedCount = results.filter(r => r.alreadyApproved).length;
560
+ const needApproveCount = results.filter(r => !r.alreadyApproved).length;
561
+ return {
562
+ signedTransactions,
563
+ results,
564
+ needApproveCount,
565
+ alreadyApprovedCount
566
+ };
567
+ }
568
+ // ==================== signOnly=false(默认):直接发送交易 ====================
521
569
  // ✅ 优化:并行检查所有钱包的授权额度
522
570
  const currentAllowances = await batchCheckAllowances(provider, normalizedToken, ownerAddresses, normalizedSpender);
523
571
  // ✅ 优化:并行发送所有需要授权的交易
package/package.json CHANGED
@@ -1,24 +1,10 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.3.88",
4
- "description": "SDK for Flap bonding curve, four.meme TokenManager, and Solana DEX",
3
+ "version": "1.3.89",
4
+ "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./dist/index.d.ts",
11
- "import": "./dist/index.js"
12
- },
13
- "./sol": {
14
- "types": "./dist/sol/index.d.ts",
15
- "import": "./dist/sol/index.js"
16
- },
17
- "./sol/*": {
18
- "types": "./dist/sol/*.d.ts",
19
- "import": "./dist/sol/*.js"
20
- }
21
- },
22
8
  "files": [
23
9
  "dist",
24
10
  "src/abis/*.json"
@@ -43,32 +29,11 @@
43
29
  "node": ">=18"
44
30
  },
45
31
  "dependencies": {
46
- "@metaplex-foundation/mpl-token-metadata": "^3.4.0",
47
- "@metaplex-foundation/umi": "^1.4.1",
48
- "@metaplex-foundation/umi-bundle-defaults": "^1.4.1",
49
- "@metaplex-foundation/umi-web3js-adapters": "^1.4.1",
50
- "@meteora-ag/cp-amm-sdk": "^1.2.6",
51
- "@meteora-ag/dlmm": "^1.9.0",
52
- "@meteora-ag/dynamic-amm-sdk": "^1.4.1",
53
- "@meteora-ag/dynamic-bonding-curve-sdk": "^1.4.9",
54
- "@orca-so/common-sdk": "^0.7.0",
55
- "@orca-so/whirlpools-sdk": "^0.17.0",
56
- "@pump-fun/pump-sdk": "^1.23.0",
57
- "@pump-fun/pump-swap-sdk": "^1.11.0",
58
- "@raydium-io/raydium-sdk-v2": "^0.2.30-alpha",
59
- "@solana/spl-token": "^0.4.14",
60
- "@solana/web3.js": "^1.98.4",
61
32
  "axios": "^1.12.2",
62
33
  "ethers": "^6.11.0",
63
- "pinata": "^1.10.1",
64
- "tweetnacl": "^1.0.3"
65
- },
66
- "optionalDependencies": {
67
- "@orca-so/wavebreak": "^1.1.7"
34
+ "pinata": "^1.10.1"
68
35
  },
69
36
  "devDependencies": {
70
- "@types/bn.js": "^5.2.0",
71
- "@types/bs58": "^4.0.4",
72
37
  "typescript": "^5.6.3"
73
38
  }
74
- }
39
+ }