four-flap-meme-sdk 2.0.0 → 2.2.0

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 (220) hide show
  1. package/dist/__tests__/subpath-exports.test.js +64 -0
  2. package/dist/chains/bsc/iro.d.ts +5 -0
  3. package/dist/chains/bsc/iro.js +4 -0
  4. package/dist/chains/eni/flat-aliases.d.ts +10 -0
  5. package/dist/chains/eni/flat-aliases.js +8 -0
  6. package/dist/chains/eni/index.d.ts +1 -0
  7. package/dist/chains/eni/index.js +1 -0
  8. package/dist/chains/index.d.ts +13 -0
  9. package/dist/chains/index.js +13 -0
  10. package/dist/chains/xlayer/eip7702/flat-aliases.d.ts +13 -0
  11. package/dist/chains/xlayer/eip7702/flat-aliases.js +10 -0
  12. package/dist/chains/xlayer/eip7702/index.d.ts +1 -0
  13. package/dist/chains/xlayer/eip7702/index.js +1 -0
  14. package/dist/chains/xlayer/index.d.ts +3 -2
  15. package/dist/chains/xlayer/index.js +4 -7
  16. package/dist/flap/index.d.ts +10 -0
  17. package/dist/flap/index.js +8 -0
  18. package/dist/merkle/index.d.ts +12 -0
  19. package/dist/merkle/index.js +11 -0
  20. package/dist/shared/constants/index.d.ts +2 -0
  21. package/dist/shared/index.d.ts +2 -0
  22. package/dist/vanity/index.d.ts +5 -0
  23. package/dist/vanity/index.js +5 -0
  24. package/package.json +93 -2
  25. package/dist/chains/bsc/four/disperse.d.ts +0 -12
  26. package/dist/chains/bsc/four/disperse.js +0 -470
  27. package/dist/chains/bsc/four/pairwise.d.ts +0 -7
  28. package/dist/chains/bsc/four/pairwise.js +0 -308
  29. package/dist/chains/bsc/four/submit/blockrazor.d.ts +0 -18
  30. package/dist/chains/bsc/four/submit/blockrazor.js +0 -86
  31. package/dist/chains/bsc/four/submit/direct.d.ts +0 -66
  32. package/dist/chains/bsc/four/submit/direct.js +0 -452
  33. package/dist/chains/bsc/four/submit/helpers.d.ts +0 -18
  34. package/dist/chains/bsc/four/submit/helpers.js +0 -57
  35. package/dist/chains/bsc/four/submit/index.d.ts +0 -12
  36. package/dist/chains/bsc/four/submit/index.js +0 -11
  37. package/dist/chains/bsc/four/submit/merkle.d.ts +0 -18
  38. package/dist/chains/bsc/four/submit/merkle.js +0 -74
  39. package/dist/chains/bsc/four/submit/types.d.ts +0 -143
  40. package/dist/chains/bsc/four/swap/index.d.ts +0 -32
  41. package/dist/chains/bsc/four/swap/index.js +0 -829
  42. package/dist/chains/bsc/four/swap/types.d.ts +0 -70
  43. package/dist/chains/bsc/four/swap/types.js +0 -1
  44. package/dist/chains/bsc/four/sweep.d.ts +0 -13
  45. package/dist/chains/bsc/four/sweep.js +0 -788
  46. package/dist/chains/bsc/four/utils/index.d.ts +0 -20
  47. package/dist/chains/bsc/four/utils/index.js +0 -1558
  48. package/dist/chains/bsc/four/utils/types.d.ts +0 -1
  49. package/dist/chains/bsc/four/utils/types.js +0 -1
  50. package/dist/chains/bsc/pancake/bundle-buy-first/index.d.ts +0 -8
  51. package/dist/chains/bsc/pancake/bundle-buy-first/index.js +0 -907
  52. package/dist/chains/bsc/pancake/bundle-buy-first/types.d.ts +0 -73
  53. package/dist/chains/bsc/pancake/bundle-buy-first/types.js +0 -1
  54. package/dist/chains/bsc/pancake/bundle-swap/helpers.d.ts +0 -102
  55. package/dist/chains/bsc/pancake/bundle-swap/helpers.js +0 -572
  56. package/dist/chains/bsc/pancake/bundle-swap/index.d.ts +0 -50
  57. package/dist/chains/bsc/pancake/bundle-swap/index.js +0 -1066
  58. package/dist/chains/bsc/pancake/bundle-swap/types.d.ts +0 -202
  59. package/dist/chains/bsc/pancake/bundle-swap/types.js +0 -3
  60. package/dist/chains/xlayer/eip7702/bundle-swap/index.d.ts +0 -72
  61. package/dist/chains/xlayer/eip7702/bundle-swap/index.js +0 -921
  62. package/dist/chains/xlayer/eip7702/bundle-swap/types.d.ts +0 -65
  63. package/dist/chains/xlayer/eip7702/bundle-swap/types.js +0 -1
  64. package/dist/chains/xlayer/eip7702/multi-hop-transfer/index.d.ts +0 -128
  65. package/dist/chains/xlayer/eip7702/multi-hop-transfer/index.js +0 -857
  66. package/dist/chains/xlayer/eip7702/multi-hop-transfer/types.d.ts +0 -85
  67. package/dist/chains/xlayer/eip7702/multi-hop-transfer/types.js +0 -1
  68. package/dist/chains/xlayer/eip7702/volume/index.d.ts +0 -96
  69. package/dist/chains/xlayer/eip7702/volume/index.js +0 -793
  70. package/dist/chains/xlayer/eip7702/volume/types.d.ts +0 -124
  71. package/dist/chains/xlayer/eip7702/volume/types.js +0 -1
  72. package/dist/chains/xlayer/eoa/types-core.d.ts +0 -363
  73. package/dist/chains/xlayer/eoa/types-core.js +0 -53
  74. package/dist/chains/xlayer/eoa/types-create.d.ts +0 -413
  75. package/dist/chains/xlayer/eoa/types-create.js +0 -9
  76. package/dist/chains/xlayer/eoa/types-volume.d.ts +0 -209
  77. package/dist/chains/xlayer/eoa/types-volume.js +0 -13
  78. package/dist/dex/direct-router/index.d.ts +0 -70
  79. package/dist/dex/direct-router/index.js +0 -1410
  80. package/dist/dex/direct-router/types.d.ts +0 -81
  81. package/dist/dex/direct-router/types.js +0 -1
  82. package/dist/shared/abis/TaxToken.json +0 -969
  83. package/dist/shared/abis/TokenManager.json +0 -836
  84. package/dist/shared/abis/TokenManager2.json +0 -136
  85. package/dist/shared/abis/TokenManagerHelper3.json +0 -993
  86. package/dist/shared/abis 2/TaxToken.json +0 -105
  87. package/dist/shared/abis 2/TokenManager.json +0 -836
  88. package/dist/shared/abis 2/TokenManager2.json +0 -60
  89. package/dist/shared/abis 2/TokenManagerHelper3.json +0 -993
  90. package/dist/shared/abis 2/common.d.ts +0 -85
  91. package/dist/shared/abis 2/common.js +0 -254
  92. package/dist/shared/abis 2/index.d.ts +0 -8
  93. package/dist/shared/abis 2/index.js +0 -8
  94. package/dist/shared/clients 2/blockrazor.d.ts +0 -314
  95. package/dist/shared/clients 2/blockrazor.js +0 -596
  96. package/dist/shared/clients 2/club48.d.ts +0 -154
  97. package/dist/shared/clients 2/club48.js +0 -331
  98. package/dist/shared/clients 2/emitservice.d.ts +0 -47
  99. package/dist/shared/clients 2/emitservice.js +0 -44
  100. package/dist/shared/clients 2/four.d.ts +0 -132
  101. package/dist/shared/clients 2/four.js +0 -281
  102. package/dist/shared/clients 2/merkle.d.ts +0 -210
  103. package/dist/shared/clients 2/merkle.js +0 -400
  104. package/dist/shared/flap/__tests__/curve.test.d.ts +0 -1
  105. package/dist/shared/flap/__tests__/curve.test.js +0 -85
  106. package/dist/shared/flap/portal/index.d.ts +0 -12
  107. package/dist/shared/flap/portal/index.js +0 -11
  108. package/dist/shared/flap/portal/portal.d.ts +0 -47
  109. package/dist/shared/flap/portal/portal.js +0 -218
  110. package/dist/shared/flap/portal/types.d.ts +0 -227
  111. package/dist/shared/flap/portal/types.js +0 -80
  112. package/dist/shared/flap/portal/writer.d.ts +0 -121
  113. package/dist/shared/flap/portal/writer.js +0 -265
  114. package/dist/shared/flap/portal-bundle-merkle/core/index.d.ts +0 -18
  115. package/dist/shared/flap/portal-bundle-merkle/core/index.js +0 -938
  116. package/dist/shared/flap/portal-bundle-merkle/core/types.d.ts +0 -1
  117. package/dist/shared/flap/portal-bundle-merkle/core/types.js +0 -1
  118. package/dist/shared/flap/portal-bundle-merkle/swap/index.d.ts +0 -42
  119. package/dist/shared/flap/portal-bundle-merkle/swap/index.js +0 -1448
  120. package/dist/shared/flap/portal-bundle-merkle/swap/types.d.ts +0 -84
  121. package/dist/shared/flap/portal-bundle-merkle/swap/types.js +0 -1
  122. package/dist/shared/flap/portal-bundle-merkle/utils/index.d.ts +0 -17
  123. package/dist/shared/flap/portal-bundle-merkle/utils/index.js +0 -1024
  124. package/dist/shared/flap/portal-bundle-merkle/utils/types.d.ts +0 -16
  125. package/dist/shared/flap/portal-bundle-merkle/utils/types.js +0 -1
  126. package/dist/shared/flap/portal-bundle-merkle/utils-helpers.d.ts +0 -100
  127. package/dist/shared/flap/portal-bundle-merkle/utils-helpers.js +0 -133
  128. package/dist/shared/flap 2/__tests__/curve.test.d.ts +0 -1
  129. package/dist/shared/flap 2/__tests__/curve.test.js +0 -85
  130. package/dist/shared/flap 2/abi.d.ts +0 -4
  131. package/dist/shared/flap 2/abi.js +0 -4
  132. package/dist/shared/flap 2/constants.d.ts +0 -128
  133. package/dist/shared/flap 2/constants.js +0 -143
  134. package/dist/shared/flap 2/curve.d.ts +0 -33
  135. package/dist/shared/flap 2/curve.js +0 -84
  136. package/dist/shared/flap 2/errors.d.ts +0 -37
  137. package/dist/shared/flap 2/errors.js +0 -114
  138. package/dist/shared/flap 2/index.d.ts +0 -22
  139. package/dist/shared/flap 2/index.js +0 -33
  140. package/dist/shared/flap 2/ipfs.d.ts +0 -21
  141. package/dist/shared/flap 2/ipfs.js +0 -38
  142. package/dist/shared/flap 2/meta.d.ts +0 -30
  143. package/dist/shared/flap 2/meta.js +0 -195
  144. package/dist/shared/flap 2/permit.d.ts +0 -16
  145. package/dist/shared/flap 2/permit.js +0 -67
  146. package/dist/shared/flap 2/pinata.d.ts +0 -40
  147. package/dist/shared/flap 2/pinata.js +0 -106
  148. package/dist/shared/flap 2/portal-bundle-merkle/config.d.ts +0 -79
  149. package/dist/shared/flap 2/portal-bundle-merkle/config.js +0 -133
  150. package/dist/shared/flap 2/portal-bundle-merkle/core.d.ts +0 -18
  151. package/dist/shared/flap 2/portal-bundle-merkle/core.js +0 -938
  152. package/dist/shared/flap 2/portal-bundle-merkle/create-to-dex.d.ts +0 -125
  153. package/dist/shared/flap 2/portal-bundle-merkle/create-to-dex.js +0 -665
  154. package/dist/shared/flap 2/portal-bundle-merkle/curve-to-dex.d.ts +0 -88
  155. package/dist/shared/flap 2/portal-bundle-merkle/curve-to-dex.js +0 -446
  156. package/dist/shared/flap 2/portal-bundle-merkle/index.d.ts +0 -14
  157. package/dist/shared/flap 2/portal-bundle-merkle/index.js +0 -26
  158. package/dist/shared/flap 2/portal-bundle-merkle/pancake-proxy.d.ts +0 -28
  159. package/dist/shared/flap 2/portal-bundle-merkle/pancake-proxy.js +0 -701
  160. package/dist/shared/flap 2/portal-bundle-merkle/private.d.ts +0 -17
  161. package/dist/shared/flap 2/portal-bundle-merkle/private.js +0 -549
  162. package/dist/shared/flap 2/portal-bundle-merkle/swap-buy-first.d.ts +0 -65
  163. package/dist/shared/flap 2/portal-bundle-merkle/swap-buy-first.js +0 -831
  164. package/dist/shared/flap 2/portal-bundle-merkle/swap.d.ts +0 -201
  165. package/dist/shared/flap 2/portal-bundle-merkle/swap.js +0 -1359
  166. package/dist/shared/flap 2/portal-bundle-merkle/types.d.ts +0 -358
  167. package/dist/shared/flap 2/portal-bundle-merkle/types.js +0 -1
  168. package/dist/shared/flap 2/portal-bundle-merkle/utils.d.ts +0 -89
  169. package/dist/shared/flap 2/portal-bundle-merkle/utils.js +0 -963
  170. package/dist/shared/flap 2/portal-bundle.d.ts +0 -119
  171. package/dist/shared/flap 2/portal-bundle.js +0 -584
  172. package/dist/shared/flap 2/portal.d.ts +0 -392
  173. package/dist/shared/flap 2/portal.js +0 -559
  174. package/dist/shared/flap 2/vanity.d.ts +0 -48
  175. package/dist/shared/flap 2/vanity.js +0 -110
  176. package/dist/shared/flap 2/vault.d.ts +0 -240
  177. package/dist/shared/flap 2/vault.js +0 -366
  178. package/dist/shared/four 2/index.d.ts +0 -7
  179. package/dist/shared/four 2/index.js +0 -22
  180. package/dist/shared/four 2/tax-token.d.ts +0 -176
  181. package/dist/shared/four 2/tax-token.js +0 -302
  182. package/dist/shared/index 2.js +0 -10
  183. package/dist/shared/index.d 2.ts +0 -10
  184. package/dist/types/distribute.d.ts +0 -72
  185. package/dist/types/distribute.js +0 -1
  186. package/dist/types 2/errors.d.ts +0 -27
  187. package/dist/types 2/errors.js +0 -34
  188. package/dist/utils/__tests__/errors.test.d.ts +0 -1
  189. package/dist/utils/__tests__/errors.test.js +0 -76
  190. package/dist/utils/airdrop-sweep-types.d.ts +0 -1
  191. package/dist/utils/airdrop-sweep-types.js +0 -1
  192. package/dist/utils/erc20/index.d.ts +0 -242
  193. package/dist/utils/erc20/index.js +0 -645
  194. package/dist/utils/erc20/types.d.ts +0 -77
  195. package/dist/utils/erc20/types.js +0 -1
  196. package/dist/utils/erc20-types.d.ts +0 -1
  197. package/dist/utils/erc20-types.js +0 -1
  198. package/dist/utils/holders-maker/helpers.d.ts +0 -43
  199. package/dist/utils/holders-maker/helpers.js +0 -371
  200. package/dist/utils/holders-maker/index.d.ts +0 -26
  201. package/dist/utils/holders-maker/index.js +0 -218
  202. package/dist/utils/holders-maker/types.d.ts +0 -72
  203. package/dist/utils/holders-maker/types.js +0 -4
  204. package/dist/utils/holders-maker-types.d.ts +0 -1
  205. package/dist/utils/holders-maker-types.js +0 -1
  206. package/dist/utils/lp-inspect/index.d.ts +0 -44
  207. package/dist/utils/lp-inspect/index.js +0 -937
  208. package/dist/utils/lp-inspect/types.d.ts +0 -100
  209. package/dist/utils/lp-inspect/types.js +0 -1
  210. package/dist/utils/lp-inspect-types.d.ts +0 -1
  211. package/dist/utils/lp-inspect-types.js +0 -1
  212. package/dist/utils/private-sale-types.d.ts +0 -1
  213. package/dist/utils/private-sale-types.js +0 -1
  214. package/dist/utils/quote-helpers/index.d.ts +0 -107
  215. package/dist/utils/quote-helpers/index.js +0 -346
  216. package/dist/utils/quote-helpers/types.d.ts +0 -16
  217. package/dist/utils/quote-helpers/types.js +0 -1
  218. package/dist/utils/quote-helpers-types.d.ts +0 -1
  219. package/dist/utils/quote-helpers-types.js +0 -1
  220. /package/dist/{chains/bsc/four/submit/types.js → __tests__/subpath-exports.test.d.ts} +0 -0
@@ -1,17 +0,0 @@
1
- import { FlapPrivateBuyMerkleParams, FlapPrivateSellMerkleParams, FlapPrivateTransactionResult, FlapBatchPrivateBuyMerkleParams, FlapBatchPrivateSellMerkleParams, FlapBatchPrivateMerkleResult } from './types.js';
2
- /**
3
- * 私有购买(单笔)(Merkle 版本)
4
- */
5
- export declare function flapPrivateBuyMerkle(params: FlapPrivateBuyMerkleParams): Promise<FlapPrivateTransactionResult>;
6
- /**
7
- * 私有卖出(单笔)(Merkle 版本)
8
- */
9
- export declare function flapPrivateSellMerkle(params: FlapPrivateSellMerkleParams): Promise<FlapPrivateTransactionResult>;
10
- /**
11
- * 批量私有购买(Merkle 版本)
12
- */
13
- export declare function flapBatchPrivateBuyMerkle(params: FlapBatchPrivateBuyMerkleParams): Promise<FlapBatchPrivateMerkleResult>;
14
- /**
15
- * 批量私有卖出(Merkle 版本)
16
- */
17
- export declare function flapBatchPrivateSellMerkle(params: FlapBatchPrivateSellMerkleParams): Promise<FlapBatchPrivateMerkleResult>;
@@ -1,549 +0,0 @@
1
- import { ethers, Wallet } from 'ethers';
2
- import { MerkleClient } from '../../clients/merkle.js';
3
- import { getOptimizedGasPrice, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../../../utils/bundle-helpers.js';
4
- import { FLAP_PORTAL_ADDRESSES } from '../constants.js';
5
- import { ZERO_ADDRESS } from '../../../utils/constants.js';
6
- import { GAS_LIMITS, CHAINS } from '../../constants/index.js';
7
- import { CHAIN_ID_MAP, PORTAL_ABI, getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, calculateBatchProfit, getProfitRecipient, getBribeAmount, BLOCKRAZOR_BUILDER_EOA } from './config.js';
8
- const DEFAULT_GAS_LIMIT = 800000;
9
- /**
10
- * 私有购买(单笔)(Merkle 版本)
11
- */
12
- export async function flapPrivateBuyMerkle(params) {
13
- const { chain, privateKey, tokenAddress, amountIn, minOutputAmount, config } = params;
14
- const { chainId, provider } = createMerkleContext(chain, config);
15
- const wallet = new Wallet(privateKey, provider);
16
- const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
17
- const originalAmountWei = ethers.parseEther(amountIn);
18
- // ✅ 利润提取配置
19
- const extractProfit = shouldExtractProfit(config);
20
- const { actualAmountWei, profitWei } = splitBuyAmount(originalAmountWei, extractProfit, config);
21
- const minAmountOut = parseMinOutput(minOutputAmount);
22
- const portal = new ethers.Contract(portalAddr, PORTAL_ABI, wallet);
23
- // ✅ 并行获取 gasPrice、nonce 和构建未签名交易
24
- const [gasPrice, currentNonce, unsigned] = await Promise.all([
25
- getOptimizedGasPrice(provider, getGasPriceConfig(config)),
26
- // ✅ 使用 pending nonce,避免 xLayer 等链上“已有 pending 交易”导致 nonce too low
27
- provider.getTransactionCount(wallet.address, 'pending'),
28
- portal.swapExactInput.populateTransaction({
29
- inputToken: ZERO_ADDRESS,
30
- outputToken: tokenAddress,
31
- inputAmount: actualAmountWei,
32
- minOutputAmount: minAmountOut,
33
- permitData: '0x',
34
- }, { value: actualAmountWei })
35
- ]);
36
- const gasLimit = resolveGasLimit(config.gasLimitMultiplier);
37
- // ✅ 获取贿赂金额
38
- const bribeAmount = getBribeAmount(config);
39
- const needBribeTx = bribeAmount > 0n;
40
- const needProfitTx = extractProfit && profitWei > 0n;
41
- // ✅ 分配 nonces:贿赂 → 买入 → 利润
42
- let nonceIdx = 0;
43
- const bribeNonce = needBribeTx ? currentNonce + nonceIdx++ : undefined;
44
- const buyNonce = currentNonce + nonceIdx++;
45
- const profitNonce = needProfitTx ? currentNonce + nonceIdx : undefined;
46
- // ✅ 并行签名所有交易(贿赂、买入、利润)
47
- const signPromises = [];
48
- const txType = getTxType(config);
49
- // 贿赂交易
50
- if (needBribeTx && bribeNonce !== undefined) {
51
- signPromises.push(wallet.signTransaction({
52
- to: BLOCKRAZOR_BUILDER_EOA,
53
- value: bribeAmount,
54
- nonce: bribeNonce,
55
- gasPrice,
56
- gasLimit: GAS_LIMITS.BRIBE,
57
- chainId,
58
- type: txType
59
- }));
60
- }
61
- // 买入交易
62
- signPromises.push(wallet.signTransaction({
63
- ...unsigned,
64
- from: wallet.address,
65
- nonce: buyNonce,
66
- gasLimit,
67
- gasPrice,
68
- chainId,
69
- type: txType,
70
- value: actualAmountWei
71
- }));
72
- // ✅ 并行签名完成后按顺序返回
73
- const signedTxs = await Promise.all(signPromises);
74
- // ✅ 利润多跳转账(强制 2 跳中转)
75
- let profitHopWallets;
76
- if (needProfitTx && profitNonce !== undefined) {
77
- const profitHopResult = await buildProfitHopTransactions({
78
- provider,
79
- payerWallet: wallet,
80
- profitAmount: profitWei,
81
- profitRecipient: getProfitRecipient(),
82
- hopCount: PROFIT_HOP_COUNT,
83
- gasPrice,
84
- chainId,
85
- txType,
86
- startNonce: profitNonce
87
- });
88
- signedTxs.push(...profitHopResult.signedTransactions);
89
- profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
90
- }
91
- return { signedTransactions: signedTxs, profitHopWallets }; // ✅ 返回利润多跳钱包
92
- }
93
- /**
94
- * 私有卖出(单笔)(Merkle 版本)
95
- */
96
- export async function flapPrivateSellMerkle(params) {
97
- const { chain, privateKey, tokenAddress, amount, minOutputAmount, config } = params;
98
- const { chainId, provider } = createMerkleContext(chain, config);
99
- const wallet = new Wallet(privateKey, provider);
100
- const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
101
- const amountWei = ethers.parseUnits(amount, 18);
102
- const portal = new ethers.Contract(portalAddr, PORTAL_ABI, wallet);
103
- // ✅ 并行获取 gasPrice、nonce、报价和构建未签名交易
104
- const [gasPrice, currentNonce, { quotedOutput }, unsigned] = await Promise.all([
105
- getOptimizedGasPrice(provider, getGasPriceConfig(config)),
106
- // ✅ 使用 pending nonce,避免 xLayer 等链上“已有 pending 交易”导致 nonce too low
107
- provider.getTransactionCount(wallet.address, 'pending'),
108
- resolveSingleSellOutputs(portal, tokenAddress, amountWei, minOutputAmount),
109
- portal.swapExactInput.populateTransaction({
110
- inputToken: tokenAddress,
111
- outputToken: ZERO_ADDRESS,
112
- inputAmount: amountWei,
113
- minOutputAmount: 0n, // ✅ 已移除滑点保护
114
- permitData: '0x',
115
- })
116
- ]);
117
- const gasLimit = resolveGasLimit(config.gasLimitMultiplier);
118
- const txType = getTxType(config);
119
- // ✅ 获取贿赂金额
120
- const bribeAmount = getBribeAmount(config);
121
- const needBribeTx = bribeAmount > 0n;
122
- // ✅ 利润计算
123
- const extractProfit = shouldExtractProfit(config);
124
- const { profit: profitWei } = extractProfit && quotedOutput > 0n
125
- ? calculateProfit(quotedOutput, config)
126
- : { profit: 0n };
127
- const needProfitTx = extractProfit && profitWei > 0n;
128
- // ✅ 分配 nonces:贿赂 → 卖出 → 利润
129
- let nonceIdx = 0;
130
- const bribeNonce = needBribeTx ? currentNonce + nonceIdx++ : undefined;
131
- const sellNonce = currentNonce + nonceIdx++;
132
- const profitNonce = needProfitTx ? currentNonce + nonceIdx : undefined;
133
- // ✅ 并行签名所有交易(贿赂、卖出、利润)
134
- const signPromises = [];
135
- // 贿赂交易
136
- if (needBribeTx && bribeNonce !== undefined) {
137
- signPromises.push(wallet.signTransaction({
138
- to: BLOCKRAZOR_BUILDER_EOA,
139
- value: bribeAmount,
140
- nonce: bribeNonce,
141
- gasPrice,
142
- gasLimit: GAS_LIMITS.BRIBE,
143
- chainId,
144
- type: txType
145
- }));
146
- }
147
- // 卖出交易
148
- signPromises.push(wallet.signTransaction({
149
- ...unsigned,
150
- from: wallet.address,
151
- nonce: sellNonce,
152
- gasLimit,
153
- gasPrice,
154
- chainId,
155
- type: txType
156
- }));
157
- // ✅ 并行签名完成后按顺序返回
158
- const signedTxs = await Promise.all(signPromises);
159
- // ✅ 利润多跳转账(强制 2 跳中转)
160
- let profitHopWallets;
161
- if (needProfitTx && profitNonce !== undefined) {
162
- const profitHopResult = await buildProfitHopTransactions({
163
- provider,
164
- payerWallet: wallet,
165
- profitAmount: profitWei,
166
- profitRecipient: getProfitRecipient(),
167
- hopCount: PROFIT_HOP_COUNT,
168
- gasPrice,
169
- chainId,
170
- txType,
171
- startNonce: profitNonce
172
- });
173
- signedTxs.push(...profitHopResult.signedTransactions);
174
- profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
175
- }
176
- return { signedTransactions: signedTxs, profitHopWallets }; // ✅ 返回利润多跳钱包
177
- }
178
- /**
179
- * 批量私有购买(Merkle 版本)
180
- */
181
- export async function flapBatchPrivateBuyMerkle(params) {
182
- const { chain, privateKeys, amountsIn, tokenAddress, minOutputAmounts, config } = params;
183
- if (privateKeys.length !== amountsIn.length) {
184
- throw new Error('privateKeys and amountsIn length mismatch');
185
- }
186
- const { chainId, provider } = createMerkleContext(chain, config);
187
- const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
188
- const wallets = privateKeys.map(k => new Wallet(k, provider));
189
- const originalAmountsWei = amountsIn.map(a => ethers.parseEther(a));
190
- // ✅ 利润提取配置
191
- const extractProfit = shouldExtractProfit(config);
192
- const { totalProfit, remainingAmounts } = calculateBatchProfit(originalAmountsWei, config);
193
- const actualAmountsWei = remainingAmounts;
194
- const maxFundsIndex = findMaxIndex(originalAmountsWei);
195
- const minOuts = resolveBatchMinOutputs(minOutputAmounts, wallets.length);
196
- const portals = wallets.map(w => new ethers.Contract(portalAddr, PORTAL_ABI, w));
197
- // ✅ 获取贿赂金额
198
- const bribeAmount = getBribeAmount(config);
199
- const needBribeTx = bribeAmount > 0n;
200
- const needProfitTx = extractProfit && totalProfit > 0n;
201
- // ✅ 并行获取 gasPrice、所有 nonces 和构建未签名交易
202
- const [gasPrice, initialNonces, unsignedList] = await Promise.all([
203
- getOptimizedGasPrice(provider, getGasPriceConfig(config)),
204
- // ✅ 使用 pending nonce,避免 xLayer 等链上“已有 pending 交易”导致 nonce too low
205
- Promise.all(wallets.map(w => provider.getTransactionCount(w.address, 'pending'))),
206
- Promise.all(portals.map((portal, i) => portal.swapExactInput.populateTransaction({
207
- inputToken: ZERO_ADDRESS,
208
- outputToken: tokenAddress,
209
- inputAmount: actualAmountsWei[i],
210
- minOutputAmount: minOuts[i],
211
- permitData: '0x',
212
- }, { value: actualAmountsWei[i] })))
213
- ]);
214
- // ✅ 分配 nonces:贿赂(可选) → 买入 → 利润(可选)
215
- let payerNonceOffset = 0;
216
- let bribeNonce;
217
- if (needBribeTx && maxFundsIndex >= 0) {
218
- bribeNonce = initialNonces[maxFundsIndex];
219
- payerNonceOffset++;
220
- }
221
- const nonces = initialNonces.map((n, i) => {
222
- if (i === maxFundsIndex) {
223
- return n + payerNonceOffset; // payer 的买入 nonce 需要偏移
224
- }
225
- return n;
226
- });
227
- const profitNonce = needProfitTx && maxFundsIndex >= 0
228
- ? initialNonces[maxFundsIndex] + payerNonceOffset + 1
229
- : undefined;
230
- const gasLimit = resolveGasLimit(config.gasLimitMultiplier);
231
- const gasLimits = new Array(wallets.length).fill(gasLimit);
232
- const signedTxs = [];
233
- // ✅ 贿赂交易放在首位
234
- if (needBribeTx && bribeNonce !== undefined && maxFundsIndex >= 0) {
235
- const bribeTx = await wallets[maxFundsIndex].signTransaction({
236
- to: BLOCKRAZOR_BUILDER_EOA,
237
- value: bribeAmount,
238
- nonce: bribeNonce,
239
- gasPrice,
240
- gasLimit: GAS_LIMITS.BRIBE,
241
- chainId,
242
- type: getTxType(config)
243
- });
244
- signedTxs.push(bribeTx);
245
- }
246
- // ✅ 并行签名所有买入交易
247
- const signedList = await signBatchTransactions({
248
- unsignedList,
249
- wallets,
250
- nonces,
251
- gasLimits,
252
- gasPrice,
253
- chainId,
254
- config,
255
- values: actualAmountsWei
256
- });
257
- signedTxs.push(...signedList);
258
- // ✅ 利润多跳转账(强制 2 跳中转)
259
- let profitHopWallets;
260
- if (needProfitTx && profitNonce !== undefined && maxFundsIndex >= 0) {
261
- const profitHopResult = await buildProfitHopTransactions({
262
- provider,
263
- payerWallet: wallets[maxFundsIndex],
264
- profitAmount: totalProfit,
265
- profitRecipient: getProfitRecipient(),
266
- hopCount: PROFIT_HOP_COUNT,
267
- gasPrice,
268
- chainId,
269
- txType: getTxType(config),
270
- startNonce: profitNonce
271
- });
272
- signedTxs.push(...profitHopResult.signedTransactions);
273
- profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
274
- }
275
- return { signedTransactions: signedTxs, profitHopWallets }; // ✅ 返回利润多跳钱包
276
- }
277
- /**
278
- * 批量私有卖出(Merkle 版本)
279
- */
280
- export async function flapBatchPrivateSellMerkle(params) {
281
- const { chain, privateKeys, amounts, tokenAddress, minOutputAmounts, config } = params;
282
- if (privateKeys.length !== amounts.length) {
283
- throw new Error('privateKeys and amounts length mismatch');
284
- }
285
- const { chainId, provider } = createMerkleContext(chain, config);
286
- const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
287
- const wallets = privateKeys.map(k => new Wallet(k, provider));
288
- const amountsWei = amounts.map(a => ethers.parseUnits(a, 18));
289
- const portal = new ethers.Contract(portalAddr, PORTAL_ABI, provider);
290
- const portals = wallets.map(w => new ethers.Contract(portalAddr, PORTAL_ABI, w));
291
- // ✅ 并行获取 gasPrice、所有 nonces、所有报价和构建未签名交易
292
- const [gasPrice, initialNonces, quotedOutputs, unsignedList] = await Promise.all([
293
- getOptimizedGasPrice(provider, getGasPriceConfig(config)),
294
- // ✅ 使用 pending nonce,避免 xLayer 等链上“已有 pending 交易”导致 nonce too low
295
- Promise.all(wallets.map(w => provider.getTransactionCount(w.address, 'pending'))),
296
- Promise.all(amountsWei.map(amount => portal.quoteExactInput.staticCall({
297
- inputToken: tokenAddress,
298
- outputToken: ZERO_ADDRESS,
299
- inputAmount: amount
300
- }).catch(() => 0n))),
301
- // ✅ 并行构建未签名交易(已移除滑点保护:minOuts 固定为 0)
302
- Promise.all(portals.map((p, i) => p.swapExactInput.populateTransaction({
303
- inputToken: tokenAddress,
304
- outputToken: ZERO_ADDRESS,
305
- inputAmount: amountsWei[i],
306
- minOutputAmount: 0n,
307
- permitData: '0x'
308
- })))
309
- ]);
310
- const extractProfit = shouldExtractProfit(config);
311
- const { totalProfit, maxRevenueIndex } = summarizeSellProfits(quotedOutputs, extractProfit, config);
312
- // ✅ 获取贿赂金额
313
- const bribeAmount = getBribeAmount(config);
314
- const needBribeTx = bribeAmount > 0n;
315
- const needProfitTx = extractProfit && totalProfit > 0n;
316
- // ✅ 分配 nonces:贿赂(可选) → 卖出 → 利润(可选)
317
- let payerNonceOffset = 0;
318
- let bribeNonce;
319
- if (needBribeTx && maxRevenueIndex >= 0) {
320
- bribeNonce = initialNonces[maxRevenueIndex];
321
- payerNonceOffset++;
322
- }
323
- const nonces = initialNonces.map((n, i) => {
324
- if (i === maxRevenueIndex) {
325
- return n + payerNonceOffset; // payer 的卖出 nonce 需要偏移
326
- }
327
- return n;
328
- });
329
- const profitNonce = needProfitTx && maxRevenueIndex >= 0
330
- ? initialNonces[maxRevenueIndex] + payerNonceOffset + 1
331
- : undefined;
332
- const gasLimit = resolveGasLimit(config.gasLimitMultiplier);
333
- const gasLimits = new Array(wallets.length).fill(gasLimit);
334
- const signedTxs = [];
335
- // ✅ 贿赂交易放在首位
336
- if (needBribeTx && bribeNonce !== undefined && maxRevenueIndex >= 0) {
337
- const bribeTx = await wallets[maxRevenueIndex].signTransaction({
338
- to: BLOCKRAZOR_BUILDER_EOA,
339
- value: bribeAmount,
340
- nonce: bribeNonce,
341
- gasPrice,
342
- gasLimit: GAS_LIMITS.BRIBE,
343
- chainId,
344
- type: getTxType(config)
345
- });
346
- signedTxs.push(bribeTx);
347
- }
348
- // ✅ 并行签名所有卖出交易
349
- const signedList = await signBatchTransactions({
350
- unsignedList,
351
- wallets,
352
- nonces,
353
- gasLimits,
354
- gasPrice,
355
- chainId,
356
- config
357
- });
358
- signedTxs.push(...signedList);
359
- // ✅ 利润多跳转账(强制 2 跳中转)
360
- let profitHopWallets;
361
- if (needProfitTx && profitNonce !== undefined && maxRevenueIndex >= 0) {
362
- const profitHopResult = await buildProfitHopTransactions({
363
- provider,
364
- payerWallet: wallets[maxRevenueIndex],
365
- profitAmount: totalProfit,
366
- profitRecipient: getProfitRecipient(),
367
- hopCount: PROFIT_HOP_COUNT,
368
- gasPrice,
369
- chainId,
370
- txType: getTxType(config),
371
- startNonce: profitNonce
372
- });
373
- signedTxs.push(...profitHopResult.signedTransactions);
374
- profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
375
- }
376
- return { signedTransactions: signedTxs, profitHopWallets }; // ✅ 返回利润多跳钱包
377
- }
378
- // ==================== 内部工具函数 ====================
379
- function createMerkleContext(chain, config) {
380
- const chainId = CHAIN_ID_MAP[chain];
381
- // ✅ 检查是否为 Merkle 支持的链(BSC, ETH)
382
- // Monad 不支持 Merkle 捆绑服务,使用普通 RPC
383
- if (chainId !== CHAINS.BSC.chainId && chainId !== CHAINS.ETHEREUM.chainId) {
384
- // 对于不支持 Merkle 的链(如 Monad),必须提供自定义 RPC
385
- if (!config.customRpcUrl) {
386
- throw new Error(`Chain ${chain} (chainId: ${chainId}) does not support Merkle bundle service. Please provide customRpcUrl.`);
387
- }
388
- const { JsonRpcProvider } = require('ethers');
389
- // ✅ 禁用 ENS: 避免 "network does not support ENS" 错误
390
- return {
391
- chainId,
392
- provider: new JsonRpcProvider(config.customRpcUrl, { chainId, name: chain.toLowerCase(), ensAddress: undefined })
393
- };
394
- }
395
- const merkle = new MerkleClient({
396
- apiKey: config.apiKey,
397
- chainId: chainId, // 类型断言为 Merkle 支持的 chainId
398
- customRpcUrl: config.customRpcUrl
399
- });
400
- return {
401
- chainId,
402
- provider: merkle.getProvider()
403
- };
404
- }
405
- function splitBuyAmount(amount, extractProfit, config) {
406
- if (!extractProfit) {
407
- return { actualAmountWei: amount, profitWei: 0n };
408
- }
409
- const { remaining, profit } = calculateProfit(amount, config);
410
- return { actualAmountWei: remaining, profitWei: profit };
411
- }
412
- function parseMinOutput(value) {
413
- if (value === undefined) {
414
- return 0n;
415
- }
416
- return typeof value === 'string' ? ethers.parseUnits(value, 18) : value;
417
- }
418
- function resolveGasLimit(multiplier, defaultGas = DEFAULT_GAS_LIMIT) {
419
- const factor = multiplier ?? 1.0;
420
- return BigInt(Math.ceil(defaultGas * factor));
421
- }
422
- /**
423
- * 追加利润多跳转账交易(强制 2 跳中转)
424
- */
425
- async function appendSingleProfitTransfer({ extractProfit, profitWei, wallet, baseNonce, provider, gasPrice, chainId, config, signedTxs }) {
426
- if (!extractProfit || profitWei === 0n) {
427
- return undefined;
428
- }
429
- const profitHopResult = await buildProfitHopTransactions({
430
- provider,
431
- payerWallet: wallet,
432
- profitAmount: profitWei,
433
- profitRecipient: getProfitRecipient(),
434
- hopCount: PROFIT_HOP_COUNT,
435
- gasPrice,
436
- chainId,
437
- txType: getTxType(config),
438
- startNonce: baseNonce + 1
439
- });
440
- signedTxs.push(...profitHopResult.signedTransactions);
441
- return profitHopResult.hopWallets; // ✅ 返回利润多跳钱包
442
- }
443
- async function resolveSingleSellOutputs(portal, tokenAddress, amountWei, minOutputAmount) {
444
- if (minOutputAmount !== undefined) {
445
- const minOut = typeof minOutputAmount === 'string'
446
- ? ethers.parseEther(minOutputAmount)
447
- : minOutputAmount;
448
- return {
449
- quotedOutput: minOut,
450
- minOut
451
- };
452
- }
453
- try {
454
- const quotedOutput = await portal.quoteExactInput.staticCall({
455
- inputToken: tokenAddress,
456
- outputToken: ZERO_ADDRESS,
457
- inputAmount: amountWei
458
- });
459
- return {
460
- quotedOutput,
461
- minOut: 0n // ✅ 已移除滑点保护:minOut 固定为 0
462
- };
463
- }
464
- catch {
465
- return {
466
- quotedOutput: 0n,
467
- minOut: 0n
468
- };
469
- }
470
- }
471
- /**
472
- * 追加卖出利润多跳转账交易(强制 2 跳中转)
473
- */
474
- async function appendSingleSellProfitTransfer({ extractProfit, quotedOutput, wallet, baseNonce, provider, gasPrice, chainId, config, signedTxs }) {
475
- if (!extractProfit || quotedOutput <= 0n) {
476
- return undefined;
477
- }
478
- const { profit } = calculateProfit(quotedOutput, config);
479
- if (profit === 0n) {
480
- return undefined;
481
- }
482
- const profitHopResult = await buildProfitHopTransactions({
483
- provider,
484
- payerWallet: wallet,
485
- profitAmount: profit,
486
- profitRecipient: getProfitRecipient(),
487
- hopCount: PROFIT_HOP_COUNT,
488
- gasPrice,
489
- chainId,
490
- txType: getTxType(config),
491
- startNonce: baseNonce + 1
492
- });
493
- signedTxs.push(...profitHopResult.signedTransactions);
494
- return profitHopResult.hopWallets; // ✅ 返回利润多跳钱包
495
- }
496
- function resolveBatchMinOutputs(minOutputAmounts, walletCount) {
497
- if (minOutputAmounts && minOutputAmounts.length === walletCount) {
498
- return minOutputAmounts.map(m => typeof m === 'string' ? ethers.parseUnits(m, 18) : m);
499
- }
500
- return new Array(walletCount).fill(0n);
501
- }
502
- function findMaxIndex(values) {
503
- if (values.length === 0) {
504
- return -1;
505
- }
506
- let maxIndex = 0;
507
- let maxValue = values[0];
508
- for (let i = 1; i < values.length; i++) {
509
- if (values[i] > maxValue) {
510
- maxValue = values[i];
511
- maxIndex = i;
512
- }
513
- }
514
- return maxIndex;
515
- }
516
- async function signBatchTransactions({ unsignedList, wallets, nonces, gasLimits, gasPrice, chainId, config, values }) {
517
- return await Promise.all(unsignedList.map((unsigned, i) => {
518
- const value = values ? values[i] : unsigned.value;
519
- return wallets[i].signTransaction({
520
- ...unsigned,
521
- from: wallets[i].address,
522
- nonce: nonces[i],
523
- gasLimit: gasLimits[i],
524
- gasPrice,
525
- chainId,
526
- type: getTxType(config),
527
- value
528
- });
529
- }));
530
- }
531
- function summarizeSellProfits(quotedOutputs, extractProfit, config) {
532
- let totalProfit = 0n;
533
- let maxRevenueIndex = -1;
534
- let maxRevenue = 0n;
535
- if (extractProfit) {
536
- for (let i = 0; i < quotedOutputs.length; i++) {
537
- const quoted = quotedOutputs[i];
538
- if (quoted > 0n) {
539
- const { profit } = calculateProfit(quoted, config);
540
- totalProfit += profit;
541
- if (quoted > maxRevenue) {
542
- maxRevenue = quoted;
543
- maxRevenueIndex = i;
544
- }
545
- }
546
- }
547
- }
548
- return { totalProfit, maxRevenueIndex: maxRevenueIndex < 0 ? 0 : maxRevenueIndex };
549
- }
@@ -1,65 +0,0 @@
1
- /**
2
- * Flap Protocol 内盘捆绑换手(Merkle Bundle)- 先买后卖
3
- *
4
- * 功能:钱包B先买入代币 → 钱包A卖出相同数量 → 原子执行
5
- */
6
- import { CommonBundleConfig } from '../../../utils/bundle-helpers.js';
7
- import { FlapSignConfig } from './config.js';
8
- import type { GeneratedWallet } from '../../../utils/wallet.js';
9
- export type FlapChain = 'bsc' | 'xlayer' | 'base';
10
- export type UserType = 'v0' | 'v1';
11
- export interface FlapBuyFirstSignConfig extends FlapSignConfig {
12
- reserveGasETH?: number;
13
- skipQuoteOnError?: boolean;
14
- userType?: UserType;
15
- }
16
- export interface FlapBuyFirstConfig extends CommonBundleConfig {
17
- apiKey: string;
18
- customRpcUrl?: string;
19
- bundleBlockOffset?: number;
20
- reserveGasETH?: number;
21
- skipQuoteOnError?: boolean;
22
- waitForConfirmation?: boolean;
23
- waitTimeoutMs?: number;
24
- }
25
- export interface FlapBundleBuyFirstSignParams {
26
- chain: FlapChain;
27
- buyerPrivateKey?: string;
28
- buyerPrivateKeys?: string[];
29
- sellerPrivateKey?: string;
30
- sellerPrivateKeys?: string[];
31
- tokenAddress: string;
32
- buyerFunds?: string;
33
- buyerFundsPercentage?: number;
34
- config: FlapBuyFirstSignConfig;
35
- quoteToken?: string;
36
- quoteTokenDecimals?: number;
37
- buyCount?: number;
38
- sellCount?: number;
39
- }
40
- export interface FlapBundleBuyFirstParams {
41
- chain: FlapChain;
42
- buyerPrivateKey: string;
43
- sellerPrivateKey: string;
44
- tokenAddress: string;
45
- buyerFunds?: string;
46
- buyerFundsPercentage?: number;
47
- config: FlapBuyFirstConfig;
48
- }
49
- /** ✅ Flap BuyFirst 结果(简化版) */
50
- export type FlapBuyFirstResult = {
51
- signedTransactions: string[];
52
- profitHopWallets?: GeneratedWallet[];
53
- metadata?: {
54
- buyerAddress: string;
55
- sellerAddress: string;
56
- buyAmount: string;
57
- sellAmount: string;
58
- profitAmount?: string;
59
- buyCount?: number;
60
- sellCount?: number;
61
- buyAmounts?: string[];
62
- sellAmounts?: string[];
63
- };
64
- };
65
- export declare function flapBundleBuyFirstMerkle(params: FlapBundleBuyFirstSignParams): Promise<FlapBuyFirstResult>;