four-flap-meme-sdk 2.0.0 → 2.1.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 (205) hide show
  1. package/dist/__tests__/subpath-exports.test.js +34 -0
  2. package/dist/chains/index.d.ts +13 -0
  3. package/dist/chains/index.js +13 -0
  4. package/dist/chains/xlayer/eip7702/index.d.ts +2 -0
  5. package/dist/flap/index.d.ts +10 -0
  6. package/dist/flap/index.js +8 -0
  7. package/dist/shared/constants/index.d.ts +2 -0
  8. package/dist/shared/index.d.ts +2 -0
  9. package/package.json +66 -1
  10. package/dist/chains/bsc/four/disperse.d.ts +0 -12
  11. package/dist/chains/bsc/four/disperse.js +0 -470
  12. package/dist/chains/bsc/four/pairwise.d.ts +0 -7
  13. package/dist/chains/bsc/four/pairwise.js +0 -308
  14. package/dist/chains/bsc/four/submit/blockrazor.d.ts +0 -18
  15. package/dist/chains/bsc/four/submit/blockrazor.js +0 -86
  16. package/dist/chains/bsc/four/submit/direct.d.ts +0 -66
  17. package/dist/chains/bsc/four/submit/direct.js +0 -452
  18. package/dist/chains/bsc/four/submit/helpers.d.ts +0 -18
  19. package/dist/chains/bsc/four/submit/helpers.js +0 -57
  20. package/dist/chains/bsc/four/submit/index.d.ts +0 -12
  21. package/dist/chains/bsc/four/submit/index.js +0 -11
  22. package/dist/chains/bsc/four/submit/merkle.d.ts +0 -18
  23. package/dist/chains/bsc/four/submit/merkle.js +0 -74
  24. package/dist/chains/bsc/four/submit/types.d.ts +0 -143
  25. package/dist/chains/bsc/four/swap/index.d.ts +0 -32
  26. package/dist/chains/bsc/four/swap/index.js +0 -829
  27. package/dist/chains/bsc/four/swap/types.d.ts +0 -70
  28. package/dist/chains/bsc/four/swap/types.js +0 -1
  29. package/dist/chains/bsc/four/sweep.d.ts +0 -13
  30. package/dist/chains/bsc/four/sweep.js +0 -788
  31. package/dist/chains/bsc/four/utils/index.d.ts +0 -20
  32. package/dist/chains/bsc/four/utils/index.js +0 -1558
  33. package/dist/chains/bsc/four/utils/types.d.ts +0 -1
  34. package/dist/chains/bsc/four/utils/types.js +0 -1
  35. package/dist/chains/bsc/pancake/bundle-buy-first/index.d.ts +0 -8
  36. package/dist/chains/bsc/pancake/bundle-buy-first/index.js +0 -907
  37. package/dist/chains/bsc/pancake/bundle-buy-first/types.d.ts +0 -73
  38. package/dist/chains/bsc/pancake/bundle-buy-first/types.js +0 -1
  39. package/dist/chains/bsc/pancake/bundle-swap/helpers.d.ts +0 -102
  40. package/dist/chains/bsc/pancake/bundle-swap/helpers.js +0 -572
  41. package/dist/chains/bsc/pancake/bundle-swap/index.d.ts +0 -50
  42. package/dist/chains/bsc/pancake/bundle-swap/index.js +0 -1066
  43. package/dist/chains/bsc/pancake/bundle-swap/types.d.ts +0 -202
  44. package/dist/chains/bsc/pancake/bundle-swap/types.js +0 -3
  45. package/dist/chains/xlayer/eip7702/bundle-swap/index.d.ts +0 -72
  46. package/dist/chains/xlayer/eip7702/bundle-swap/index.js +0 -921
  47. package/dist/chains/xlayer/eip7702/bundle-swap/types.d.ts +0 -65
  48. package/dist/chains/xlayer/eip7702/bundle-swap/types.js +0 -1
  49. package/dist/chains/xlayer/eip7702/multi-hop-transfer/index.d.ts +0 -128
  50. package/dist/chains/xlayer/eip7702/multi-hop-transfer/index.js +0 -857
  51. package/dist/chains/xlayer/eip7702/multi-hop-transfer/types.d.ts +0 -85
  52. package/dist/chains/xlayer/eip7702/multi-hop-transfer/types.js +0 -1
  53. package/dist/chains/xlayer/eip7702/volume/index.d.ts +0 -96
  54. package/dist/chains/xlayer/eip7702/volume/index.js +0 -793
  55. package/dist/chains/xlayer/eip7702/volume/types.d.ts +0 -124
  56. package/dist/chains/xlayer/eip7702/volume/types.js +0 -1
  57. package/dist/chains/xlayer/eoa/types-core.d.ts +0 -363
  58. package/dist/chains/xlayer/eoa/types-core.js +0 -53
  59. package/dist/chains/xlayer/eoa/types-create.d.ts +0 -413
  60. package/dist/chains/xlayer/eoa/types-create.js +0 -9
  61. package/dist/chains/xlayer/eoa/types-volume.d.ts +0 -209
  62. package/dist/chains/xlayer/eoa/types-volume.js +0 -13
  63. package/dist/dex/direct-router/index.d.ts +0 -70
  64. package/dist/dex/direct-router/index.js +0 -1410
  65. package/dist/dex/direct-router/types.d.ts +0 -81
  66. package/dist/dex/direct-router/types.js +0 -1
  67. package/dist/shared/abis/TaxToken.json +0 -969
  68. package/dist/shared/abis/TokenManager.json +0 -836
  69. package/dist/shared/abis/TokenManager2.json +0 -136
  70. package/dist/shared/abis/TokenManagerHelper3.json +0 -993
  71. package/dist/shared/abis 2/TaxToken.json +0 -105
  72. package/dist/shared/abis 2/TokenManager.json +0 -836
  73. package/dist/shared/abis 2/TokenManager2.json +0 -60
  74. package/dist/shared/abis 2/TokenManagerHelper3.json +0 -993
  75. package/dist/shared/abis 2/common.d.ts +0 -85
  76. package/dist/shared/abis 2/common.js +0 -254
  77. package/dist/shared/abis 2/index.d.ts +0 -8
  78. package/dist/shared/abis 2/index.js +0 -8
  79. package/dist/shared/clients 2/blockrazor.d.ts +0 -314
  80. package/dist/shared/clients 2/blockrazor.js +0 -596
  81. package/dist/shared/clients 2/club48.d.ts +0 -154
  82. package/dist/shared/clients 2/club48.js +0 -331
  83. package/dist/shared/clients 2/emitservice.d.ts +0 -47
  84. package/dist/shared/clients 2/emitservice.js +0 -44
  85. package/dist/shared/clients 2/four.d.ts +0 -132
  86. package/dist/shared/clients 2/four.js +0 -281
  87. package/dist/shared/clients 2/merkle.d.ts +0 -210
  88. package/dist/shared/clients 2/merkle.js +0 -400
  89. package/dist/shared/flap/__tests__/curve.test.d.ts +0 -1
  90. package/dist/shared/flap/__tests__/curve.test.js +0 -85
  91. package/dist/shared/flap/portal/index.d.ts +0 -12
  92. package/dist/shared/flap/portal/index.js +0 -11
  93. package/dist/shared/flap/portal/portal.d.ts +0 -47
  94. package/dist/shared/flap/portal/portal.js +0 -218
  95. package/dist/shared/flap/portal/types.d.ts +0 -227
  96. package/dist/shared/flap/portal/types.js +0 -80
  97. package/dist/shared/flap/portal/writer.d.ts +0 -121
  98. package/dist/shared/flap/portal/writer.js +0 -265
  99. package/dist/shared/flap/portal-bundle-merkle/core/index.d.ts +0 -18
  100. package/dist/shared/flap/portal-bundle-merkle/core/index.js +0 -938
  101. package/dist/shared/flap/portal-bundle-merkle/core/types.d.ts +0 -1
  102. package/dist/shared/flap/portal-bundle-merkle/core/types.js +0 -1
  103. package/dist/shared/flap/portal-bundle-merkle/swap/index.d.ts +0 -42
  104. package/dist/shared/flap/portal-bundle-merkle/swap/index.js +0 -1448
  105. package/dist/shared/flap/portal-bundle-merkle/swap/types.d.ts +0 -84
  106. package/dist/shared/flap/portal-bundle-merkle/swap/types.js +0 -1
  107. package/dist/shared/flap/portal-bundle-merkle/utils/index.d.ts +0 -17
  108. package/dist/shared/flap/portal-bundle-merkle/utils/index.js +0 -1024
  109. package/dist/shared/flap/portal-bundle-merkle/utils/types.d.ts +0 -16
  110. package/dist/shared/flap/portal-bundle-merkle/utils/types.js +0 -1
  111. package/dist/shared/flap/portal-bundle-merkle/utils-helpers.d.ts +0 -100
  112. package/dist/shared/flap/portal-bundle-merkle/utils-helpers.js +0 -133
  113. package/dist/shared/flap 2/__tests__/curve.test.d.ts +0 -1
  114. package/dist/shared/flap 2/__tests__/curve.test.js +0 -85
  115. package/dist/shared/flap 2/abi.d.ts +0 -4
  116. package/dist/shared/flap 2/abi.js +0 -4
  117. package/dist/shared/flap 2/constants.d.ts +0 -128
  118. package/dist/shared/flap 2/constants.js +0 -143
  119. package/dist/shared/flap 2/curve.d.ts +0 -33
  120. package/dist/shared/flap 2/curve.js +0 -84
  121. package/dist/shared/flap 2/errors.d.ts +0 -37
  122. package/dist/shared/flap 2/errors.js +0 -114
  123. package/dist/shared/flap 2/index.d.ts +0 -22
  124. package/dist/shared/flap 2/index.js +0 -33
  125. package/dist/shared/flap 2/ipfs.d.ts +0 -21
  126. package/dist/shared/flap 2/ipfs.js +0 -38
  127. package/dist/shared/flap 2/meta.d.ts +0 -30
  128. package/dist/shared/flap 2/meta.js +0 -195
  129. package/dist/shared/flap 2/permit.d.ts +0 -16
  130. package/dist/shared/flap 2/permit.js +0 -67
  131. package/dist/shared/flap 2/pinata.d.ts +0 -40
  132. package/dist/shared/flap 2/pinata.js +0 -106
  133. package/dist/shared/flap 2/portal-bundle-merkle/config.d.ts +0 -79
  134. package/dist/shared/flap 2/portal-bundle-merkle/config.js +0 -133
  135. package/dist/shared/flap 2/portal-bundle-merkle/core.d.ts +0 -18
  136. package/dist/shared/flap 2/portal-bundle-merkle/core.js +0 -938
  137. package/dist/shared/flap 2/portal-bundle-merkle/create-to-dex.d.ts +0 -125
  138. package/dist/shared/flap 2/portal-bundle-merkle/create-to-dex.js +0 -665
  139. package/dist/shared/flap 2/portal-bundle-merkle/curve-to-dex.d.ts +0 -88
  140. package/dist/shared/flap 2/portal-bundle-merkle/curve-to-dex.js +0 -446
  141. package/dist/shared/flap 2/portal-bundle-merkle/index.d.ts +0 -14
  142. package/dist/shared/flap 2/portal-bundle-merkle/index.js +0 -26
  143. package/dist/shared/flap 2/portal-bundle-merkle/pancake-proxy.d.ts +0 -28
  144. package/dist/shared/flap 2/portal-bundle-merkle/pancake-proxy.js +0 -701
  145. package/dist/shared/flap 2/portal-bundle-merkle/private.d.ts +0 -17
  146. package/dist/shared/flap 2/portal-bundle-merkle/private.js +0 -549
  147. package/dist/shared/flap 2/portal-bundle-merkle/swap-buy-first.d.ts +0 -65
  148. package/dist/shared/flap 2/portal-bundle-merkle/swap-buy-first.js +0 -831
  149. package/dist/shared/flap 2/portal-bundle-merkle/swap.d.ts +0 -201
  150. package/dist/shared/flap 2/portal-bundle-merkle/swap.js +0 -1359
  151. package/dist/shared/flap 2/portal-bundle-merkle/types.d.ts +0 -358
  152. package/dist/shared/flap 2/portal-bundle-merkle/types.js +0 -1
  153. package/dist/shared/flap 2/portal-bundle-merkle/utils.d.ts +0 -89
  154. package/dist/shared/flap 2/portal-bundle-merkle/utils.js +0 -963
  155. package/dist/shared/flap 2/portal-bundle.d.ts +0 -119
  156. package/dist/shared/flap 2/portal-bundle.js +0 -584
  157. package/dist/shared/flap 2/portal.d.ts +0 -392
  158. package/dist/shared/flap 2/portal.js +0 -559
  159. package/dist/shared/flap 2/vanity.d.ts +0 -48
  160. package/dist/shared/flap 2/vanity.js +0 -110
  161. package/dist/shared/flap 2/vault.d.ts +0 -240
  162. package/dist/shared/flap 2/vault.js +0 -366
  163. package/dist/shared/four 2/index.d.ts +0 -7
  164. package/dist/shared/four 2/index.js +0 -22
  165. package/dist/shared/four 2/tax-token.d.ts +0 -176
  166. package/dist/shared/four 2/tax-token.js +0 -302
  167. package/dist/shared/index 2.js +0 -10
  168. package/dist/shared/index.d 2.ts +0 -10
  169. package/dist/types/distribute.d.ts +0 -72
  170. package/dist/types/distribute.js +0 -1
  171. package/dist/types 2/errors.d.ts +0 -27
  172. package/dist/types 2/errors.js +0 -34
  173. package/dist/utils/__tests__/errors.test.d.ts +0 -1
  174. package/dist/utils/__tests__/errors.test.js +0 -76
  175. package/dist/utils/airdrop-sweep-types.d.ts +0 -1
  176. package/dist/utils/airdrop-sweep-types.js +0 -1
  177. package/dist/utils/erc20/index.d.ts +0 -242
  178. package/dist/utils/erc20/index.js +0 -645
  179. package/dist/utils/erc20/types.d.ts +0 -77
  180. package/dist/utils/erc20/types.js +0 -1
  181. package/dist/utils/erc20-types.d.ts +0 -1
  182. package/dist/utils/erc20-types.js +0 -1
  183. package/dist/utils/holders-maker/helpers.d.ts +0 -43
  184. package/dist/utils/holders-maker/helpers.js +0 -371
  185. package/dist/utils/holders-maker/index.d.ts +0 -26
  186. package/dist/utils/holders-maker/index.js +0 -218
  187. package/dist/utils/holders-maker/types.d.ts +0 -72
  188. package/dist/utils/holders-maker/types.js +0 -4
  189. package/dist/utils/holders-maker-types.d.ts +0 -1
  190. package/dist/utils/holders-maker-types.js +0 -1
  191. package/dist/utils/lp-inspect/index.d.ts +0 -44
  192. package/dist/utils/lp-inspect/index.js +0 -937
  193. package/dist/utils/lp-inspect/types.d.ts +0 -100
  194. package/dist/utils/lp-inspect/types.js +0 -1
  195. package/dist/utils/lp-inspect-types.d.ts +0 -1
  196. package/dist/utils/lp-inspect-types.js +0 -1
  197. package/dist/utils/private-sale-types.d.ts +0 -1
  198. package/dist/utils/private-sale-types.js +0 -1
  199. package/dist/utils/quote-helpers/index.d.ts +0 -107
  200. package/dist/utils/quote-helpers/index.js +0 -346
  201. package/dist/utils/quote-helpers/types.d.ts +0 -16
  202. package/dist/utils/quote-helpers/types.js +0 -1
  203. package/dist/utils/quote-helpers-types.d.ts +0 -1
  204. package/dist/utils/quote-helpers-types.js +0 -1
  205. /package/dist/{chains/bsc/four/submit/types.js → __tests__/subpath-exports.test.d.ts} +0 -0
@@ -1,400 +0,0 @@
1
- /**
2
- * Merkle.io Bundle Service 客户端
3
- *
4
- * 提供基于 Merkle 的 MEV 保护和捆绑交易服务
5
- *
6
- * 官方文档: https://docs.merkle.io/
7
- *
8
- * 使用示例:
9
- * ```typescript
10
- * import { MerkleClient } from 'four-flap-meme-sdk';
11
- *
12
- * const merkle = new MerkleClient({
13
- * apiKey: 'pk_mbs_...',
14
- * chainId: 56
15
- * });
16
- *
17
- * const bundleHash = await merkle.sendBundle({
18
- * transactions: [tx1, tx2, tx3],
19
- * targetBlock: currentBlock + 2
20
- * });
21
- * ```
22
- */
23
- import { JsonRpcProvider, Transaction } from 'ethers';
24
- import { CHAINS } from '../constants/index.js';
25
- /**
26
- * Merkle 客户端
27
- */
28
- export class MerkleClient {
29
- constructor(config) {
30
- // ✅ 区块号缓存(减少 RPC 调用)
31
- // 注意:TTL 设为 1 秒,确保区块号尽可能新鲜,减少 "Missed inclusion" 风险
32
- this.blockNumberCache = null;
33
- this.chainId = config.chainId;
34
- this.chainName = config.chainId === CHAINS.BSC.chainId ? 'bsc' : 'ethereum';
35
- // ✅ 修复:移除弃用的 mempool.merkle.io RPC,使用公共 RPC 作为默认值
36
- // 优先使用用户自定义 RPC,否则使用官方公共 RPC
37
- const defaultRpc = config.chainId === CHAINS.BSC.chainId
38
- ? CHAINS.BSC.rpcUrls.backup // bsc-dataseed1
39
- : CHAINS.ETHEREUM.rpcUrls.default;
40
- const rpcUrl = config.customRpcUrl || defaultRpc;
41
- this.provider = new JsonRpcProvider(rpcUrl, {
42
- chainId: this.chainId,
43
- name: this.chainName,
44
- });
45
- }
46
- /**
47
- * 获取 Provider
48
- */
49
- getProvider() {
50
- return this.provider;
51
- }
52
- /**
53
- * 获取当前区块号(带缓存,减少 RPC 调用)
54
- * @param forceRefresh 是否强制刷新缓存
55
- */
56
- async getBlockNumber(forceRefresh = false) {
57
- const now = Date.now();
58
- // ✅ 检查缓存
59
- if (!forceRefresh && this.blockNumberCache) {
60
- const age = now - this.blockNumberCache.timestamp;
61
- if (age < MerkleClient.BLOCK_CACHE_TTL_MS) {
62
- // 缓存有效,直接返回(加 1 作为安全偏移)
63
- return this.blockNumberCache.value;
64
- }
65
- }
66
- // ✅ 缓存过期或强制刷新,查询 RPC
67
- const blockNumber = await this.provider.getBlockNumber();
68
- this.blockNumberCache = { value: blockNumber, timestamp: now };
69
- return blockNumber;
70
- }
71
- /**
72
- * 获取 Gas 价格信息
73
- */
74
- async getFeeData() {
75
- return await this.provider.getFeeData();
76
- }
77
- /**
78
- * 获取网络状态(用于 Bundle 参数优化)
79
- */
80
- async getNetworkStatus() {
81
- const [currentBlock, feeData] = await Promise.all([
82
- this.getBlockNumber(),
83
- this.getFeeData()
84
- ]);
85
- // 动态获取 gas price,并计算建议的最小值
86
- const baseGasPrice = feeData.gasPrice || feeData.maxFeePerGas || 3000000000n;
87
- // 建议至少提高 80% 以确保交易被打包
88
- const suggestedMinGasPrice = (baseGasPrice * 180n) / 100n;
89
- // BSC 平均 3 秒,Ethereum 平均 12 秒
90
- const avgBlockTime = this.chainId === CHAINS.BSC.chainId
91
- ? CHAINS.BSC.blockTime / 1000
92
- : CHAINS.ETHEREUM.blockTime / 1000;
93
- return {
94
- currentBlock,
95
- gasPrice: baseGasPrice,
96
- suggestedMinGasPrice,
97
- avgBlockTime
98
- };
99
- }
100
- /**
101
- * 发送捆绑交易(底层方法)
102
- *
103
- * @param params Bundle 参数
104
- * @returns Bundle Hash
105
- */
106
- async sendBundleRaw(params) {
107
- // 验证输入
108
- if (!params.txs || params.txs.length === 0) {
109
- throw new Error('Bundle transactions cannot be empty');
110
- }
111
- if (!params.blockNumber) {
112
- throw new Error('Target block number is required');
113
- }
114
- const bundleParams = {
115
- txs: params.txs,
116
- blockNumber: params.blockNumber,
117
- minTimestamp: params.minTimestamp || 0,
118
- maxTimestamp: params.maxTimestamp || 0,
119
- };
120
- try {
121
- const result = await this.provider.send('eth_sendBundle', [bundleParams]);
122
- // 规范化返回值
123
- if (typeof result === 'string') {
124
- return result;
125
- }
126
- // 如果是对象,尝试提取 bundleHash
127
- if (result && typeof result === 'object') {
128
- // Merkle 可能返回 { bundleHash: "0x..." }
129
- if ('bundleHash' in result) {
130
- return String(result.bundleHash);
131
- }
132
- // 或者直接是哈希
133
- if ('hash' in result) {
134
- return String(result.hash);
135
- }
136
- // 否则转为 JSON 字符串(但这不是理想情况)
137
- return JSON.stringify(result);
138
- }
139
- throw new Error('Invalid bundle result format');
140
- }
141
- catch (error) {
142
- // 增强错误信息
143
- const errorMsg = error.message || String(error);
144
- throw new Error(`Send bundle failed: ${errorMsg}`);
145
- }
146
- }
147
- /**
148
- * 发送捆绑交易(高级方法,带智能优化和重试)
149
- *
150
- * @param options 发送选项
151
- * @returns Bundle 结果
152
- */
153
- async sendBundle(options) {
154
- // 验证输入
155
- if (!options.transactions || options.transactions.length === 0) {
156
- throw new Error('Transactions array cannot be empty');
157
- }
158
- const minBlockOffset = options.minBlockOffset ?? 3; // 默认至少3个区块的窗口
159
- const autoRetry = options.autoRetry ?? false;
160
- const maxRetries = options.maxRetries ?? 2;
161
- let attempt = 0;
162
- let lastError = null;
163
- while (attempt <= (autoRetry ? maxRetries : 0)) {
164
- try {
165
- // 实时获取当前区块(每次尝试都重新获取)
166
- const currentBlock = await this.getBlockNumber();
167
- // 确定目标区块
168
- let targetBlock;
169
- if (options.targetBlock) {
170
- targetBlock = options.targetBlock;
171
- // 检查目标区块是否已经过期
172
- if (targetBlock <= currentBlock) {
173
- if (autoRetry && attempt < maxRetries) {
174
- attempt++;
175
- await new Promise(resolve => setTimeout(resolve, 300)); // 短暂延迟
176
- continue;
177
- }
178
- throw new Error(`Target block ${targetBlock} has already passed (current block: ${currentBlock})`);
179
- }
180
- }
181
- else {
182
- // 动态计算:确保至少有 minBlockOffset 个区块的窗口
183
- const requestedOffset = options.blockOffset ?? 3;
184
- const actualOffset = Math.max(requestedOffset, minBlockOffset);
185
- targetBlock = currentBlock + actualOffset;
186
- }
187
- // 转换为十六进制
188
- const targetBlockHex = '0x' + targetBlock.toString(16);
189
- // 发送 Bundle
190
- const bundleHash = await this.sendBundleRaw({
191
- txs: options.transactions,
192
- blockNumber: targetBlockHex,
193
- minTimestamp: options.minTimestamp,
194
- maxTimestamp: options.maxTimestamp,
195
- });
196
- // ✅ 优化:并行提取交易哈希(map 比 for 循环更高效)
197
- const txHashes = options.transactions.map(rawTx => {
198
- try {
199
- return Transaction.from(rawTx).hash || '';
200
- }
201
- catch {
202
- return '';
203
- }
204
- });
205
- return {
206
- bundleHash,
207
- txHashes,
208
- targetBlock,
209
- txCount: options.transactions.length,
210
- };
211
- }
212
- catch (error) {
213
- lastError = error;
214
- // 如果启用了重试且还有重试次数
215
- if (autoRetry && attempt < maxRetries) {
216
- attempt++;
217
- // 等待一个区块时间再重试
218
- const blockTime = this.chainId === CHAINS.BSC.chainId
219
- ? CHAINS.BSC.blockTime
220
- : CHAINS.ETHEREUM.blockTime;
221
- await new Promise(resolve => setTimeout(resolve, blockTime));
222
- continue;
223
- }
224
- // 没有重试或已达最大重试次数
225
- throw error;
226
- }
227
- }
228
- // 如果执行到这里,说明所有重试都失败了
229
- throw lastError || new Error('Bundle submission failed after all retries');
230
- }
231
- /**
232
- * 等待 Bundle 中的交易确认
233
- *
234
- * @param txHashes 交易哈希列表
235
- * @param confirmations 确认数(默认 1)
236
- * @param timeout 超时时间(毫秒,默认 120000)
237
- * @returns 交易结果列表
238
- */
239
- async waitForBundleConfirmation(txHashes, confirmations = 1, timeout = 120000) {
240
- const promises = txHashes.map(async (hash, index) => {
241
- try {
242
- const receipt = await this.provider.waitForTransaction(hash, confirmations, timeout);
243
- if (!receipt) {
244
- return {
245
- index,
246
- hash,
247
- success: false,
248
- error: 'Transaction not found',
249
- };
250
- }
251
- let gasCost;
252
- if (receipt.gasUsed && receipt.gasPrice) {
253
- // 使用 BigInt 避免精度丢失
254
- try {
255
- const costWei = receipt.gasUsed * receipt.gasPrice;
256
- // 转换为 ETH/BNB(保持精度)
257
- const costEth = Number(costWei) / 1e18;
258
- gasCost = costEth.toFixed(8); // 增加精度到 8 位小数
259
- }
260
- catch (error) {
261
- // 如果计算溢出,使用字符串处理
262
- const costWei = receipt.gasUsed * receipt.gasPrice;
263
- gasCost = (Number(costWei / 1000000000n) / 1e9).toFixed(8);
264
- }
265
- }
266
- return {
267
- index,
268
- hash,
269
- success: receipt.status === 1,
270
- blockNumber: receipt.blockNumber,
271
- gasUsed: receipt.gasUsed.toString(),
272
- effectiveGasPrice: receipt.gasPrice?.toString(),
273
- gasCost,
274
- };
275
- }
276
- catch (error) {
277
- return {
278
- index,
279
- hash,
280
- success: false,
281
- error: error.message,
282
- };
283
- }
284
- });
285
- return await Promise.all(promises);
286
- }
287
- /**
288
- * 准备并签名交易(辅助方法)
289
- *
290
- * @param wallet 钱包
291
- * @param transactions 交易列表
292
- * @param options 可选参数
293
- * @returns 已签名的交易数组
294
- */
295
- async signTransactions(wallet, transactions, options) {
296
- // 验证输入
297
- if (!transactions || transactions.length === 0) {
298
- throw new Error('Transactions array cannot be empty');
299
- }
300
- // 获取起始 Nonce(使用 pending 确保包含待处理交易)
301
- let nonce = options?.startNonce;
302
- if (nonce === undefined) {
303
- nonce = await this.provider.getTransactionCount(wallet.address, 'pending');
304
- }
305
- // 获取 Gas Price
306
- let gasPrice = options?.gasPrice;
307
- if (!gasPrice) {
308
- const feeData = await this.provider.getFeeData();
309
- // 动态获取基础 gas price,增加容错
310
- const baseGasPrice = feeData.gasPrice || feeData.maxFeePerGas || 3000000000n;
311
- const multiplier = options?.gasPriceMultiplier || 50;
312
- gasPrice = (baseGasPrice * BigInt(100 + multiplier)) / 100n;
313
- }
314
- // 签名所有交易(避免直接修改 nonce)
315
- const signedTxs = [];
316
- for (let i = 0; i < transactions.length; i++) {
317
- const currentNonce = nonce + i;
318
- const fullTx = {
319
- ...transactions[i],
320
- nonce: currentNonce,
321
- gasPrice,
322
- chainId: this.chainId,
323
- };
324
- const signedTx = await wallet.signTransaction(fullTx);
325
- signedTxs.push(signedTx);
326
- }
327
- return signedTxs;
328
- }
329
- /**
330
- * 检查交易是否已包含在区块中
331
- *
332
- * @param txHash 交易哈希
333
- * @returns 是否已包含
334
- */
335
- async isTransactionIncluded(txHash) {
336
- try {
337
- const receipt = await this.provider.getTransactionReceipt(txHash);
338
- return receipt !== null && receipt.blockNumber !== null;
339
- }
340
- catch {
341
- return false;
342
- }
343
- }
344
- /**
345
- * 等待达到目标区块
346
- *
347
- * @param targetBlock 目标区块号
348
- * @param maxAttempts 最大尝试次数(默认 10)
349
- * @param intervalMs 检查间隔(毫秒,默认 1000)
350
- * @returns 是否达到目标区块
351
- */
352
- async waitForBlock(targetBlock, maxAttempts = 10, intervalMs = 1000) {
353
- let attempts = 0;
354
- let lastError = null;
355
- while (attempts < maxAttempts) {
356
- try {
357
- const currentBlock = await this.getBlockNumber();
358
- // 已达到或超过目标区块
359
- if (currentBlock >= targetBlock) {
360
- return true;
361
- }
362
- // 检查是否已经错过目标区块(超过太多)
363
- // 修复:应该是 currentBlock > targetBlock,而不是 targetBlock + 5
364
- if (currentBlock > targetBlock) {
365
- // 已经错过目标区块
366
- return false;
367
- }
368
- }
369
- catch (error) {
370
- lastError = error;
371
- // 继续重试
372
- }
373
- // 等待下一次检查
374
- await new Promise(resolve => setTimeout(resolve, intervalMs));
375
- attempts++;
376
- }
377
- // 达到最大尝试次数
378
- if (lastError) {
379
- }
380
- return false;
381
- }
382
- /**
383
- * 获取当前 Provider 的统计信息(用于调试)
384
- */
385
- getProviderInfo() {
386
- return {
387
- chainId: this.chainId,
388
- chainName: this.chainName,
389
- // @ts-ignore - 访问私有属性用于调试
390
- rpcUrl: this.provider._getConnection?.().url || 'unknown',
391
- };
392
- }
393
- }
394
- MerkleClient.BLOCK_CACHE_TTL_MS = 1000; // 1秒缓存(BSC 约 3 秒出块,ETH 约 12 秒)
395
- /**
396
- * 创建 Merkle 客户端的便捷函数
397
- */
398
- export function createMerkleClient(apiKey, chainId = 56) {
399
- return new MerkleClient({ apiKey, chainId });
400
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,85 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { CDPV2 } from '../curve.js';
3
- describe('CDPV2', () => {
4
- describe('getCurve', () => {
5
- it('creates curve with default h and k when only r is provided', () => {
6
- const curve = CDPV2.getCurve(0.1);
7
- expect(curve.r).toBe(0.1);
8
- expect(curve.h).toBe(0);
9
- expect(curve.k).toBe(1e9 * 0.1);
10
- });
11
- it('creates curve with explicit h and k', () => {
12
- const curve = CDPV2.getCurve(0.1, 1000, 500000);
13
- expect(curve.r).toBe(0.1);
14
- expect(curve.h).toBe(1000);
15
- expect(curve.k).toBe(500000);
16
- });
17
- });
18
- describe('estimateSupply', () => {
19
- it('returns 0 for empty reserve', () => {
20
- const curve = CDPV2.getCurve(0.1);
21
- expect(curve.estimateSupply('0').toString()).toBe('0.0');
22
- });
23
- it('returns 0 for falsy reserve', () => {
24
- const curve = CDPV2.getCurve(0.1);
25
- expect(curve.estimateSupply('').toString()).toBe('0.0');
26
- });
27
- it('calculates supply correctly for given reserve', () => {
28
- const curve = CDPV2.getCurve(0.1);
29
- const supply = curve.estimateSupply('1000000');
30
- expect(supply.toUnsafeFloat()).toBeGreaterThan(0);
31
- expect(supply.toUnsafeFloat()).toBeLessThan(1_000_000_000);
32
- });
33
- });
34
- describe('estimateReserve', () => {
35
- it('returns 0 for empty amount', () => {
36
- const curve = CDPV2.getCurve(0.1);
37
- expect(curve.estimateReserve('0').toString()).toBe('0.0');
38
- });
39
- it('returns 0 for falsy amount', () => {
40
- const curve = CDPV2.getCurve(0.1);
41
- expect(curve.estimateReserve('').toString()).toBe('0.0');
42
- });
43
- it('calculates reserve inversely proportional to supply', () => {
44
- const curve = CDPV2.getCurve(0.1);
45
- const reserve = curve.estimateReserve('500000000');
46
- expect(reserve.toUnsafeFloat()).toBeGreaterThan(0);
47
- });
48
- it('supply and reserve are mutually consistent', () => {
49
- const curve = CDPV2.getCurve(0.1);
50
- const initialReserve = '1000000';
51
- const supply = curve.estimateSupply(initialReserve);
52
- const reserveBack = curve.estimateReserve(supply.toString());
53
- // Allow small rounding differences
54
- const diff = Math.abs(reserveBack.toUnsafeFloat() - 1_000_000);
55
- expect(diff).toBeLessThan(1);
56
- });
57
- });
58
- describe('price', () => {
59
- it('returns positive price for valid supply', () => {
60
- const curve = CDPV2.getCurve(0.1);
61
- const p = curve.price('500000000');
62
- expect(p.toUnsafeFloat()).toBeGreaterThan(0);
63
- });
64
- it('price increases as supply increases (bonding curve)', () => {
65
- const curve = CDPV2.getCurve(0.1);
66
- const priceLow = curve.price('100000000');
67
- const priceHigh = curve.price('500000000');
68
- expect(priceHigh.toUnsafeFloat()).toBeGreaterThan(priceLow.toUnsafeFloat());
69
- });
70
- });
71
- describe('fdv', () => {
72
- it('calculates FDV as price * 1B', () => {
73
- const curve = CDPV2.getCurve(0.1);
74
- const supply = '500000000';
75
- const p = curve.price(supply);
76
- const f = curve.fdv(supply);
77
- expect(f.toUnsafeFloat()).toBeCloseTo(p.toUnsafeFloat() * 1_000_000_000, -3);
78
- });
79
- });
80
- describe('defaultDexSupplyThreshold', () => {
81
- it('returns 800M', () => {
82
- expect(CDPV2.defaultDexSupplyThreshold().toString()).toBe('800000000.0');
83
- });
84
- });
85
- });
@@ -1,12 +0,0 @@
1
- /**
2
- * Flap Portal 模块
3
- *
4
- * 拆分自 portal.ts。包括:
5
- * - types.ts — 枚举、类型、工具函数
6
- * - portal.ts — FlapPortal(只读操作)
7
- * - writer.ts — FlapPortalWriter(读写操作)
8
- */
9
- export type { FlapChain, PortalConfig, TokenStateV2, TokenStateV3, TokenStateV4, TokenStateV5, TokenStateV7, QuoteExactInputParams, ExactInputParams, ExactInputV3Params, NewTokenV3Params, NewTokenV4Params, NewTokenV5Params, TaxDistributionConfig, TokenStatus, TokenVersion, DexThreshType, MigratorType, V3LPFeeProfile, DEXId, } from './types.js';
10
- export { FlapPortal } from './portal.js';
11
- export { FlapPortalWriter } from './writer.js';
12
- export { lpFeeProfileToV3Fee, validateTaxDistribution } from './types.js';
@@ -1,11 +0,0 @@
1
- /**
2
- * Flap Portal 模块
3
- *
4
- * 拆分自 portal.ts。包括:
5
- * - types.ts — 枚举、类型、工具函数
6
- * - portal.ts — FlapPortal(只读操作)
7
- * - writer.ts — FlapPortalWriter(读写操作)
8
- */
9
- export { FlapPortal } from './portal.js';
10
- export { FlapPortalWriter } from './writer.js';
11
- export { lpFeeProfileToV3Fee, validateTaxDistribution } from './types.js';
@@ -1,47 +0,0 @@
1
- import type { PortalConfig, TokenStateV2, TokenStateV3, TokenStateV4, TokenStateV5, TokenStateV7, QuoteExactInputParams } from './types.js';
2
- import { Contract } from 'ethers';
3
- export declare class FlapPortal {
4
- private rpcUrl;
5
- protected portal: string;
6
- protected contract: Contract;
7
- private buyFeeRate;
8
- private sellFeeRate;
9
- constructor(cfg: PortalConfig);
10
- getTokenV2(token: string): Promise<TokenStateV2>;
11
- getTokenV3(token: string): Promise<TokenStateV3>;
12
- getTokenV4(token: string): Promise<TokenStateV4>;
13
- getTokenV5(token: string): Promise<TokenStateV5>;
14
- /**
15
- * 获取代币状态 V7(包含毕业相关信息)
16
- * 注意:仅部分链支持 V7(如 XLayer v5.7+),不支持的链会 revert
17
- */
18
- getTokenV7(token: string): Promise<TokenStateV7>;
19
- /**
20
- * 计算距离毕业还需多少 OKB/ETH(含手续费)
21
- * @param state TokenStateV5 或 TokenStateV7
22
- * @returns 毕业相关信息
23
- */
24
- computeRemainingToGraduation(state: TokenStateV5 | TokenStateV7): {
25
- remainingOkb: string;
26
- graduationReserve: string;
27
- currentReserve: string;
28
- isGraduated: boolean;
29
- progressPercent: string;
30
- };
31
- computePriceAndProgress(state: TokenStateV5): {
32
- price: string;
33
- progress: string;
34
- };
35
- quoteBuy(state: TokenStateV5, inputEth: string): string;
36
- quoteSell(state: TokenStateV5, inputToken: string): string;
37
- previewBuy(token: string, ethAmount: bigint): Promise<bigint>;
38
- previewSell(token: string, tokenAmount: bigint): Promise<bigint>;
39
- quoteExactInput(params: QuoteExactInputParams): Promise<bigint>;
40
- getFeeRate(): Promise<{
41
- buyFeeRate: bigint;
42
- sellFeeRate: bigint;
43
- }>;
44
- nonce(): Promise<bigint>;
45
- version(): Promise<string>;
46
- getLocks(token: string): Promise<bigint[]>;
47
- }