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,584 +0,0 @@
1
- import { ethers, Wallet, JsonRpcProvider } from 'ethers';
2
- import { Club48Client, sendBatchPrivateTransactions, BUILDER_CONTROL_EOA } from '../clients/club48.js';
3
- import { FLAP_PORTAL_ADDRESSES, FLAP_ORIGINAL_PORTAL_ADDRESSES } from './constants.js';
4
- import { GAS_LIMITS } from '../constants/index.js';
5
- // Portal ABI (简化版,仅包含需要的方法)
6
- const PORTAL_ABI = [
7
- 'function newToken(string name, string symbol, string meta) external payable returns (address)',
8
- 'function newTokenV2((string name,string symbol,string meta,uint8 dexThresh,bytes32 salt,uint16 taxRate,uint8 migratorType,address quoteToken,uint256 quoteAmt,address beneficiary,bytes permitData)) external payable returns (address)',
9
- 'function swapExactInputBuy((address inputToken,address outputToken,uint256 inputAmount,uint256 minOutputAmount,bytes permitData)) external payable returns (uint256)',
10
- 'function swapExactInputSell((address inputToken,address outputToken,uint256 inputAmount,uint256 minOutputAmount,bytes permitData)) external returns (uint256)',
11
- 'function quoteExactInput((address inputToken,address outputToken,uint256 inputAmount)) external returns (uint256)'
12
- ];
13
- /**
14
- * Flap Protocol Bundle 交易方法
15
- * 使用 48.club Bundle 服务实现原子化交易
16
- */
17
- // 错误信息国际化
18
- const ERRORS = {
19
- NO_PRIVATE_KEY: {
20
- en: 'At least 1 private key (creator) is required',
21
- zh: '至少需要 1 个私钥(创建者)'
22
- },
23
- AMOUNT_MISMATCH: {
24
- en: (buyCount, buyerCount) => `Buy amount count (${buyCount}) must equal buyer count (${buyerCount})`,
25
- zh: (buyCount, buyerCount) => `购买金额数量(${buyCount})必须等于买家数量(${buyerCount})`
26
- },
27
- KEY_AMOUNT_MISMATCH: {
28
- en: 'Private key count and amount count must match',
29
- zh: '私钥和购买金额数量必须一致'
30
- },
31
- SELL_KEY_AMOUNT_MISMATCH: {
32
- en: 'Private key count and sell amount count must match',
33
- zh: '私钥和卖出数量必须一致'
34
- }
35
- };
36
- // 获取错误信息(根据环境语言)
37
- function getErrorMessage(key, ...args) {
38
- const lang = (process.env.LANG || process.env.LANGUAGE || 'en').toLowerCase().includes('zh') ? 'zh' : 'en';
39
- const message = ERRORS[key][lang];
40
- return typeof message === 'function' ? message(...args) : message;
41
- }
42
- // ========================================
43
- // 辅助函数:估算 gas 并应用配置
44
- // ========================================
45
- /**
46
- * 估算 gas 并应用用户配置的倍数
47
- */
48
- async function estimateGasWithMultiplier(provider, txRequest, multiplier) {
49
- const estimated = await provider.estimateGas(txRequest);
50
- const mult = multiplier ?? 1.2; // 默认 20% 安全余量
51
- return BigInt(Math.ceil(Number(estimated) * mult));
52
- }
53
- /**
54
- * 获取交易类型(用户可配置)
55
- */
56
- function getTxType(config) {
57
- return config.txType ?? 0; // 默认 Legacy (type 0),适用于 48.club/BSC
58
- }
59
- /**
60
- * 构建完整的交易请求(包含 gas 估算和交易类型)
61
- */
62
- async function buildTxRequest(provider, unsigned, from, nonce, gasPrice, config, value) {
63
- const gasLimit = await estimateGasWithMultiplier(provider, { ...unsigned, from, value }, config.gasLimitMultiplier);
64
- return {
65
- ...unsigned,
66
- from,
67
- nonce,
68
- gasLimit,
69
- gasPrice,
70
- chainId: 56,
71
- type: getTxType(config)
72
- };
73
- }
74
- /**
75
- * Flap Protocol: 创建代币 + 捆绑购买
76
- */
77
- export async function createTokenWithBundleBuy(params) {
78
- const { chain, privateKeys, buyAmounts, tokenInfo, quoteToken, tokenAddress, config } = params;
79
- // 默认使用 BNB (0地址)
80
- const quoteTokenAddress = quoteToken || '0x0000000000000000000000000000000000000000';
81
- if (privateKeys.length === 0) {
82
- throw new Error(getErrorMessage('NO_PRIVATE_KEY'));
83
- }
84
- if (buyAmounts.length !== privateKeys.length - 1) {
85
- throw new Error(getErrorMessage('AMOUNT_MISMATCH', buyAmounts.length, privateKeys.length - 1));
86
- }
87
- const provider = new JsonRpcProvider(config.rpcUrl);
88
- const devWallet = new Wallet(privateKeys[0], provider);
89
- const club48 = new Club48Client({
90
- endpoint: config.club48Endpoint,
91
- explorerEndpoint: config.club48ExplorerEndpoint
92
- });
93
- const blockOffset = config.bundleBlockOffset ?? 100;
94
- // 1. 构建交易(为重复地址分配顺序 nonce)
95
- const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
96
- const originalPortalAddr = FLAP_ORIGINAL_PORTAL_ADDRESSES[chain];
97
- const gasPrice = await club48.getMinGasPrice();
98
- const signedTxs = [];
99
- const nextNonceMap = new Map();
100
- const getNextNonce = async (w) => {
101
- const key = w.address.toLowerCase();
102
- const cached = nextNonceMap.get(key);
103
- if (cached !== undefined) {
104
- const n = cached;
105
- nextNonceMap.set(key, cached + 1);
106
- return n;
107
- }
108
- const onchain = await w.getNonce();
109
- nextNonceMap.set(key, onchain + 1);
110
- return onchain;
111
- };
112
- // 1.1 创建交易(改为在原始 Portal 上执行 V2 创建,支持 salt/vanity)
113
- const portal = new ethers.Contract(originalPortalAddr, PORTAL_ABI, devWallet);
114
- const createTxUnsigned = await portal.newTokenV2.populateTransaction({
115
- name: tokenInfo.name,
116
- symbol: tokenInfo.symbol,
117
- meta: tokenInfo.meta,
118
- dexThresh: (params.dexThresh ?? 1) & 0xff,
119
- salt: params.salt ?? '0x' + '00'.repeat(32),
120
- taxRate: (params.taxRate ?? 0) & 0xffff,
121
- migratorType: (params.migratorType ?? 0) & 0xff,
122
- quoteToken: params.quoteToken || '0x0000000000000000000000000000000000000000',
123
- quoteAmt: 0n,
124
- beneficiary: new Wallet(privateKeys[0]).address,
125
- permitData: '0x'
126
- });
127
- // 估算 gas 并应用用户配置的安全余量
128
- const createGasLimit = await estimateGasWithMultiplier(provider, { ...createTxUnsigned, from: devWallet.address }, config.gasLimitMultiplier);
129
- const createTxRequest = {
130
- ...createTxUnsigned,
131
- from: devWallet.address,
132
- nonce: await getNextNonce(devWallet),
133
- gasLimit: createGasLimit,
134
- gasPrice: gasPrice,
135
- chainId: 56, // BSC
136
- type: getTxType(config) // 用户可配置:0=Legacy(默认),2=EIP-1559
137
- };
138
- const signedCreateTx = await devWallet.signTransaction(createTxRequest);
139
- signedTxs.push(signedCreateTx);
140
- // 可选:添加 tipTx 提升排序
141
- if (config.tipAmountWei && config.tipAmountWei > 0n) {
142
- const tipTx = await devWallet.signTransaction({
143
- to: BUILDER_CONTROL_EOA,
144
- value: config.tipAmountWei,
145
- gasPrice,
146
- gasLimit: GAS_LIMITS.BRIBE,
147
- chainId: 56,
148
- type: 0, // Legacy transaction
149
- nonce: await getNextNonce(devWallet)
150
- });
151
- signedTxs.push(tipTx);
152
- }
153
- // 1.2 购买交易
154
- const buyTxs = [];
155
- for (let i = 0; i < buyAmounts.length; i++) {
156
- const buyerWallet = new Wallet(privateKeys[i + 1], provider);
157
- const amountIn = ethers.parseEther(buyAmounts[i]);
158
- // 滑点保护(默认 1%)
159
- const slippageBps = Math.max(0, Math.min(5000, params.config.slippageBps ?? 100));
160
- let minAmountOut = 0n;
161
- try {
162
- const quote = new ethers.Contract(portalAddr, PORTAL_ABI, buyerWallet);
163
- const exactOut = await quote.quoteExactInput.staticCall({
164
- inputToken: '0x0000000000000000000000000000000000000000',
165
- outputToken: tokenAddress,
166
- inputAmount: amountIn
167
- });
168
- const keep = BigInt(10000 - slippageBps);
169
- minAmountOut = (exactOut * keep) / 10000n;
170
- }
171
- catch { }
172
- const buyPortal = new ethers.Contract(portalAddr, PORTAL_ABI, buyerWallet);
173
- const buyTxUnsigned = await buyPortal.swapExactInputBuy.populateTransaction({
174
- inputToken: '0x0000000000000000000000000000000000000000',
175
- outputToken: tokenAddress,
176
- inputAmount: 0n,
177
- minOutputAmount: minAmountOut,
178
- permitData: '0x',
179
- }, { value: amountIn });
180
- // 估算 gas 并应用用户配置的安全余量;若因代币尚未创建(同一 bundle 内先创建后购买)导致预估回滚,则使用保守兜底值
181
- let buyGasLimit;
182
- try {
183
- buyGasLimit = await estimateGasWithMultiplier(provider, { ...buyTxUnsigned, from: buyerWallet.address, value: amountIn }, config.gasLimitMultiplier);
184
- }
185
- catch {
186
- // 兜底:在 BSC 上对 swapExactInputBuy 使用相对保守的 gas 上限
187
- buyGasLimit = 600000n;
188
- }
189
- const buyTxRequest = {
190
- ...buyTxUnsigned,
191
- from: buyerWallet.address,
192
- nonce: await getNextNonce(buyerWallet),
193
- gasLimit: buyGasLimit,
194
- gasPrice: gasPrice,
195
- chainId: 56, // BSC
196
- type: getTxType(config) // 用户可配置
197
- };
198
- const signedBuyTx = await buyerWallet.signTransaction(buyTxRequest);
199
- signedTxs.push(signedBuyTx);
200
- buyTxs.push(signedBuyTx);
201
- }
202
- // 2. 提交 Bundle
203
- const bundleUuid = await club48.sendBundle({
204
- txs: signedTxs,
205
- maxBlockNumber: (await provider.getBlockNumber()) + blockOffset,
206
- noMerge: config.noMerge
207
- }, {
208
- spMode: params.config.spMode ?? 'timestampPersonalSign',
209
- spPrivateKey: params.config.spPrivateKey || privateKeys[0],
210
- spVMode: params.config.spVMode
211
- });
212
- // 3. 等待完成
213
- const status = await club48.waitForBundle(bundleUuid, params.config.waitTimeoutMs ?? 60000);
214
- return {
215
- bundleUuid,
216
- tokenAddress,
217
- status,
218
- createTx: signedCreateTx,
219
- buyTxs
220
- };
221
- }
222
- /**
223
- * Flap Protocol: 批量购买
224
- */
225
- export async function batchBuyWithBundle(params) {
226
- const { chain, privateKeys, buyAmounts, tokenAddress, config } = params;
227
- if (privateKeys.length === 0 || buyAmounts.length !== privateKeys.length) {
228
- throw new Error(getErrorMessage('KEY_AMOUNT_MISMATCH'));
229
- }
230
- const provider = new JsonRpcProvider(config.rpcUrl);
231
- const club48 = new Club48Client({
232
- endpoint: config.club48Endpoint,
233
- explorerEndpoint: config.club48ExplorerEndpoint
234
- });
235
- const blockOffset = config.bundleBlockOffset ?? 100;
236
- const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
237
- const gasPrice = await club48.getMinGasPrice();
238
- const signedTxs = [];
239
- const nextNonceMap = new Map();
240
- const getNextNonce = async (w) => {
241
- const key = w.address.toLowerCase();
242
- const cached = nextNonceMap.get(key);
243
- if (cached !== undefined) {
244
- const n = cached;
245
- nextNonceMap.set(key, cached + 1);
246
- return n;
247
- }
248
- const onchain = await w.getNonce();
249
- nextNonceMap.set(key, onchain + 1);
250
- return onchain;
251
- };
252
- // 可选:添加 tipTx 提升排序(在第一位)
253
- if (config.tipAmountWei && config.tipAmountWei > 0n) {
254
- const tipWallet = new Wallet(privateKeys[0], provider);
255
- const tipTx = await tipWallet.signTransaction({
256
- to: BUILDER_CONTROL_EOA,
257
- value: config.tipAmountWei,
258
- gasPrice,
259
- gasLimit: GAS_LIMITS.BRIBE,
260
- chainId: 56,
261
- type: 0, // Legacy transaction
262
- nonce: await getNextNonce(tipWallet)
263
- });
264
- signedTxs.unshift(tipTx);
265
- }
266
- for (let i = 0; i < privateKeys.length; i++) {
267
- const buyerWallet = new Wallet(privateKeys[i], provider);
268
- const amountIn = ethers.parseEther(buyAmounts[i]);
269
- // 滑点保护(默认 1%)
270
- const slippageBps = Math.max(0, Math.min(5000, params.config.slippageBps ?? 100));
271
- let minAmountOut = 0n; // 兼容非关键失败
272
- try {
273
- const quote = new ethers.Contract(portalAddr, PORTAL_ABI, buyerWallet);
274
- const exactOut = await quote.quoteExactInput.staticCall({
275
- inputToken: '0x0000000000000000000000000000000000000000',
276
- outputToken: tokenAddress,
277
- inputAmount: amountIn
278
- });
279
- const keep = BigInt(10000 - slippageBps);
280
- minAmountOut = (exactOut * keep) / 10000n;
281
- }
282
- catch { }
283
- const portal = new ethers.Contract(portalAddr, PORTAL_ABI, buyerWallet);
284
- const buyTxUnsigned = await portal.swapExactInputBuy.populateTransaction({
285
- inputToken: '0x0000000000000000000000000000000000000000',
286
- outputToken: tokenAddress,
287
- inputAmount: 0n,
288
- minOutputAmount: minAmountOut,
289
- permitData: '0x',
290
- }, { value: amountIn });
291
- // 估算 gas 并添加 20% 安全余量
292
- const estimatedGas = await provider.estimateGas({
293
- ...buyTxUnsigned,
294
- from: buyerWallet.address,
295
- value: amountIn
296
- });
297
- const gasLimit = (estimatedGas * 120n) / 100n;
298
- const buyTxRequest = {
299
- ...buyTxUnsigned,
300
- from: buyerWallet.address,
301
- nonce: await getNextNonce(buyerWallet),
302
- gasLimit: gasLimit,
303
- gasPrice: gasPrice,
304
- chainId: 56, // BSC
305
- type: 0 // Legacy transaction
306
- };
307
- const signedBuyTx = await buyerWallet.signTransaction(buyTxRequest);
308
- signedTxs.push(signedBuyTx);
309
- }
310
- const bundleUuid = await club48.sendBundle({
311
- txs: signedTxs,
312
- maxBlockNumber: (await provider.getBlockNumber()) + blockOffset,
313
- noMerge: config.noMerge
314
- }, {
315
- spMode: params.config.spMode ?? 'timestampPersonalSign',
316
- spPrivateKey: params.config.spPrivateKey || privateKeys[0],
317
- spVMode: params.config.spVMode
318
- });
319
- const status = await club48.waitForBundle(bundleUuid);
320
- return { bundleUuid, status, buyTxs: signedTxs };
321
- }
322
- /**
323
- * Flap Protocol: 批量卖出
324
- */
325
- export async function batchSellWithBundle(params) {
326
- const { chain, privateKeys, sellAmounts, tokenAddress, config } = params;
327
- if (privateKeys.length === 0 || sellAmounts.length !== privateKeys.length) {
328
- throw new Error(getErrorMessage('SELL_KEY_AMOUNT_MISMATCH'));
329
- }
330
- const provider = new JsonRpcProvider(config.rpcUrl);
331
- const club48 = new Club48Client({
332
- endpoint: config.club48Endpoint,
333
- explorerEndpoint: config.club48ExplorerEndpoint
334
- });
335
- const blockOffset = config.bundleBlockOffset ?? 100;
336
- const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
337
- const gasPrice = await club48.getMinGasPrice();
338
- const signedTxs = [];
339
- const nextNonceMap = new Map();
340
- const getNextNonce = async (w) => {
341
- const key = w.address.toLowerCase();
342
- const cached = nextNonceMap.get(key);
343
- if (cached !== undefined) {
344
- const n = cached;
345
- nextNonceMap.set(key, cached + 1);
346
- return n;
347
- }
348
- const onchain = await w.getNonce();
349
- nextNonceMap.set(key, onchain + 1);
350
- return onchain;
351
- };
352
- // 可选 tipTx
353
- if (config.tipAmountWei && config.tipAmountWei > 0n) {
354
- const tipWallet = new Wallet(privateKeys[0], provider);
355
- const tipTx = await tipWallet.signTransaction({
356
- to: BUILDER_CONTROL_EOA,
357
- value: config.tipAmountWei,
358
- gasPrice,
359
- gasLimit: GAS_LIMITS.BRIBE,
360
- chainId: 56,
361
- type: 0, // Legacy transaction
362
- nonce: await getNextNonce(tipWallet)
363
- });
364
- signedTxs.unshift(tipTx);
365
- }
366
- for (let i = 0; i < privateKeys.length; i++) {
367
- const sellerWallet = new Wallet(privateKeys[i], provider);
368
- const amountIn = ethers.parseUnits(sellAmounts[i], 18);
369
- const minAmountOut = 0n; // TODO: 调用 quoteExactInput
370
- const portal = new ethers.Contract(portalAddr, PORTAL_ABI, sellerWallet);
371
- const sellTxUnsigned = await portal.swapExactInputSell.populateTransaction({
372
- inputToken: tokenAddress,
373
- outputToken: '0x0000000000000000000000000000000000000000',
374
- inputAmount: amountIn,
375
- minOutputAmount: minAmountOut,
376
- permitData: '0x',
377
- });
378
- // 估算 gas 并添加 20% 安全余量
379
- const estimatedGas = await provider.estimateGas({
380
- ...sellTxUnsigned,
381
- from: sellerWallet.address
382
- });
383
- const gasLimit = (estimatedGas * 120n) / 100n;
384
- const sellTxRequest = {
385
- ...sellTxUnsigned,
386
- from: sellerWallet.address,
387
- nonce: await getNextNonce(sellerWallet),
388
- gasLimit: gasLimit,
389
- gasPrice: gasPrice,
390
- chainId: 56, // BSC
391
- type: 0 // Legacy transaction
392
- };
393
- const signedSellTx = await sellerWallet.signTransaction(sellTxRequest);
394
- signedTxs.push(signedSellTx);
395
- }
396
- const bundleUuid = await club48.sendBundle({
397
- txs: signedTxs,
398
- maxBlockNumber: (await provider.getBlockNumber()) + blockOffset,
399
- noMerge: config.noMerge
400
- }, {
401
- spMode: params.config.spMode ?? 'timestampPersonalSign',
402
- spPrivateKey: params.config.spPrivateKey || privateKeys[0],
403
- spVMode: params.config.spVMode
404
- });
405
- const status = await club48.waitForBundle(bundleUuid);
406
- return { bundleUuid, status, sellTxs: signedTxs };
407
- }
408
- export async function flapPrivateBuy(params) {
409
- const { chain, privateKey, tokenAddress, amountIn, to, config, spPrivateKey } = params;
410
- const provider = new JsonRpcProvider(config.rpcUrl);
411
- const wallet = new Wallet(privateKey, provider);
412
- const club48 = new Club48Client({ endpoint: config.club48Endpoint, explorerEndpoint: config.club48ExplorerEndpoint });
413
- const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
414
- const gasPrice = await club48.getMinGasPrice();
415
- const amountWei = ethers.parseEther(amountIn);
416
- const minAmountOut = 0n; // 不加滑点
417
- const portal = new ethers.Contract(portalAddr, PORTAL_ABI, wallet);
418
- const unsigned = await portal.swapExactInputBuy.populateTransaction({
419
- inputToken: '0x0000000000000000000000000000000000000000',
420
- outputToken: tokenAddress,
421
- inputAmount: 0n,
422
- minOutputAmount: minAmountOut,
423
- permitData: '0x',
424
- }, { value: amountWei });
425
- // 估算 gas 并添加 20% 安全余量
426
- const estimatedGas = await provider.estimateGas({
427
- ...unsigned,
428
- from: wallet.address,
429
- value: amountWei
430
- });
431
- const gasLimit = (estimatedGas * 120n) / 100n;
432
- const req = {
433
- ...unsigned,
434
- from: wallet.address,
435
- nonce: await wallet.getNonce(),
436
- gasLimit: gasLimit,
437
- gasPrice,
438
- chainId: 56,
439
- type: 0 // Legacy transaction
440
- };
441
- const signed = await wallet.signTransaction(req);
442
- if (spPrivateKey)
443
- return await club48.sendPrivateTransactionWith48SP(signed, spPrivateKey);
444
- return await club48.sendPrivateTransaction(signed);
445
- }
446
- export async function flapPrivateSell(params) {
447
- const { chain, privateKey, tokenAddress, amount, minEth, config, spPrivateKey } = params;
448
- const provider = new JsonRpcProvider(config.rpcUrl);
449
- const wallet = new Wallet(privateKey, provider);
450
- const club48 = new Club48Client({ endpoint: config.club48Endpoint, explorerEndpoint: config.club48ExplorerEndpoint });
451
- const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
452
- const gasPrice = await club48.getMinGasPrice();
453
- const amountWei = ethers.parseUnits(amount, 18);
454
- const minOut = minEth ?? 0n;
455
- const portal = new ethers.Contract(portalAddr, PORTAL_ABI, wallet);
456
- const unsigned = await portal.swapExactInputSell.populateTransaction({
457
- inputToken: tokenAddress,
458
- outputToken: '0x0000000000000000000000000000000000000000',
459
- inputAmount: amountWei,
460
- minOutputAmount: minOut,
461
- permitData: '0x',
462
- });
463
- // 估算 gas 并添加 20% 安全余量
464
- const estimatedGas = await provider.estimateGas({
465
- ...unsigned,
466
- from: wallet.address
467
- });
468
- const gasLimit = (estimatedGas * 120n) / 100n;
469
- const req = {
470
- ...unsigned,
471
- from: wallet.address,
472
- nonce: await wallet.getNonce(),
473
- gasLimit: gasLimit,
474
- gasPrice,
475
- chainId: 56,
476
- type: 0 // Legacy transaction
477
- };
478
- const signed = await wallet.signTransaction(req);
479
- if (spPrivateKey)
480
- return await club48.sendPrivateTransactionWith48SP(signed, spPrivateKey);
481
- return await club48.sendPrivateTransaction(signed);
482
- }
483
- export async function flapBatchPrivateBuy(params) {
484
- const { chain, privateKeys, amountsIn, tokenAddress, config, spPrivateKey } = params;
485
- if (privateKeys.length !== amountsIn.length)
486
- throw new Error('privateKeys and amountsIn length mismatch');
487
- const provider = new JsonRpcProvider(config.rpcUrl);
488
- const club48 = new Club48Client({ endpoint: config.club48Endpoint, explorerEndpoint: config.club48ExplorerEndpoint });
489
- const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
490
- const gasPrice = await club48.getMinGasPrice();
491
- const signedTxs = [];
492
- const nextNonceMap = new Map();
493
- const getNextNonce = async (w) => {
494
- const key = w.address.toLowerCase();
495
- const cached = nextNonceMap.get(key);
496
- if (cached !== undefined) {
497
- const n = cached;
498
- nextNonceMap.set(key, cached + 1);
499
- return n;
500
- }
501
- const onchain = await w.getNonce();
502
- nextNonceMap.set(key, onchain + 1);
503
- return onchain;
504
- };
505
- for (let i = 0; i < privateKeys.length; i++) {
506
- const w = new Wallet(privateKeys[i], provider);
507
- const amountWei = ethers.parseEther(amountsIn[i]);
508
- const portal = new ethers.Contract(portalAddr, PORTAL_ABI, w);
509
- const unsigned = await portal.swapExactInputBuy.populateTransaction({
510
- inputToken: '0x0000000000000000000000000000000000000000',
511
- outputToken: tokenAddress,
512
- inputAmount: 0n,
513
- minOutputAmount: 0n,
514
- permitData: '0x',
515
- }, { value: amountWei });
516
- // 估算 gas 并添加 20% 安全余量
517
- const estimatedGas = await provider.estimateGas({ ...unsigned, from: w.address, value: amountWei });
518
- const gasLimit = (estimatedGas * 120n) / 100n;
519
- const req = { ...unsigned, from: w.address, nonce: await getNextNonce(w), gasLimit, gasPrice, chainId: 56, type: 0 };
520
- signedTxs.push(await w.signTransaction(req));
521
- }
522
- return await sendBatchPrivateTransactions(signedTxs, spPrivateKey, config.club48Endpoint || 'https://puissant-bsc.48.club');
523
- }
524
- export async function flapBatchPrivateSell(params) {
525
- const { chain, privateKeys, amounts, tokenAddress, config, spPrivateKey, minEthEach } = params;
526
- if (privateKeys.length !== amounts.length)
527
- throw new Error('privateKeys and amounts length mismatch');
528
- const provider = new JsonRpcProvider(config.rpcUrl);
529
- const club48 = new Club48Client({ endpoint: config.club48Endpoint, explorerEndpoint: config.club48ExplorerEndpoint });
530
- const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
531
- const gasPrice = await club48.getMinGasPrice();
532
- const minOut = minEthEach ?? 0n;
533
- const signedTxs = [];
534
- const nextNonceMap = new Map();
535
- const getNextNonce = async (w) => {
536
- const key = w.address.toLowerCase();
537
- const cached = nextNonceMap.get(key);
538
- if (cached !== undefined) {
539
- const n = cached;
540
- nextNonceMap.set(key, cached + 1);
541
- return n;
542
- }
543
- const onchain = await w.getNonce();
544
- nextNonceMap.set(key, onchain + 1);
545
- return onchain;
546
- };
547
- for (let i = 0; i < privateKeys.length; i++) {
548
- const w = new Wallet(privateKeys[i], provider);
549
- const amountWei = ethers.parseUnits(amounts[i], 18);
550
- const portal = new ethers.Contract(portalAddr, PORTAL_ABI, w);
551
- const unsigned = await portal.swapExactInputSell.populateTransaction({
552
- inputToken: tokenAddress,
553
- outputToken: '0x0000000000000000000000000000000000000000',
554
- inputAmount: amountWei,
555
- minOutputAmount: minOut,
556
- permitData: '0x',
557
- });
558
- // 估算 gas 并添加 20% 安全余量
559
- const estimatedGas = await provider.estimateGas({ ...unsigned, from: w.address });
560
- const gasLimit = (estimatedGas * 120n) / 100n;
561
- const req = { ...unsigned, from: w.address, nonce: await getNextNonce(w), gasLimit, gasPrice, chainId: 56, type: 0 };
562
- signedTxs.push(await w.signTransaction(req));
563
- }
564
- // 使用 bundle 通道提交(统一与捆绑买保持一致)
565
- const blockOffset = config.bundleBlockOffset ?? 100;
566
- const bundleUuid = await club48.sendBundle({
567
- txs: signedTxs,
568
- maxBlockNumber: (await provider.getBlockNumber()) + blockOffset,
569
- noMerge: config.noMerge
570
- }, {
571
- // 若传入 sp 配置,则用于生成 48SP 签名提升打包优先级(与批量买一致)
572
- spMode: params.config.spMode ?? 'timestampPersonalSign',
573
- spPrivateKey: params.config.spPrivateKey || 'https://puissant-bsc.48.club',
574
- spVMode: params.config.spVMode
575
- });
576
- try {
577
- const status = await club48.waitForBundle(bundleUuid);
578
- return { submitted: true, bundleUuid, status, sellTxs: signedTxs };
579
- }
580
- catch {
581
- // 超时或查询失败:为避免误报,返回已提交与原始交易,状态暂缺
582
- return { submitted: true, bundleUuid, sellTxs: signedTxs };
583
- }
584
- }