@w3lib/evm-batch-call 0.6.0 → 0.8.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 (248) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +367 -3
  3. package/contracts/TokenProbe.sol +103 -0
  4. package/dist/aggregate.d.ts.map +1 -1
  5. package/dist/aggregate.js +114 -3
  6. package/dist/aggregate.js.map +1 -1
  7. package/dist/approvals.d.ts +169 -0
  8. package/dist/approvals.d.ts.map +1 -0
  9. package/dist/approvals.js +310 -0
  10. package/dist/approvals.js.map +1 -0
  11. package/dist/chains.d.ts.map +1 -1
  12. package/dist/chains.js +4 -0
  13. package/dist/chains.js.map +1 -1
  14. package/dist/dividends.d.ts +135 -0
  15. package/dist/dividends.d.ts.map +1 -0
  16. package/dist/dividends.js +253 -0
  17. package/dist/dividends.js.map +1 -0
  18. package/dist/fees.d.ts +97 -0
  19. package/dist/fees.d.ts.map +1 -0
  20. package/dist/fees.js +115 -0
  21. package/dist/fees.js.map +1 -0
  22. package/dist/history.d.ts +154 -0
  23. package/dist/history.d.ts.map +1 -0
  24. package/dist/history.js +247 -0
  25. package/dist/history.js.map +1 -0
  26. package/dist/historySources.d.ts +32 -0
  27. package/dist/historySources.d.ts.map +1 -0
  28. package/dist/historySources.js +319 -0
  29. package/dist/historySources.js.map +1 -0
  30. package/dist/http.d.ts +10 -0
  31. package/dist/http.d.ts.map +1 -0
  32. package/dist/http.js +30 -0
  33. package/dist/http.js.map +1 -0
  34. package/dist/liquidity/v3.d.ts +2 -0
  35. package/dist/liquidity/v3.d.ts.map +1 -1
  36. package/dist/liquidity/v3.js +1 -1
  37. package/dist/liquidity/v3.js.map +1 -1
  38. package/dist/liquidity/v4.d.ts +21 -0
  39. package/dist/liquidity/v4.d.ts.map +1 -1
  40. package/dist/liquidity/v4.js +4 -3
  41. package/dist/liquidity/v4.js.map +1 -1
  42. package/dist/lp.d.ts +10 -1
  43. package/dist/lp.d.ts.map +1 -1
  44. package/dist/lp.js +19 -2
  45. package/dist/lp.js.map +1 -1
  46. package/dist/lpV4.d.ts +4 -0
  47. package/dist/lpV4.d.ts.map +1 -1
  48. package/dist/lpV4.js +27 -3
  49. package/dist/lpV4.js.map +1 -1
  50. package/dist/multicall.d.ts.map +1 -1
  51. package/dist/multicall.js +3 -0
  52. package/dist/multicall.js.map +1 -1
  53. package/dist/names.d.ts +55 -0
  54. package/dist/names.d.ts.map +1 -0
  55. package/dist/names.js +93 -0
  56. package/dist/names.js.map +1 -0
  57. package/dist/owner.d.ts +4 -26
  58. package/dist/owner.d.ts.map +1 -1
  59. package/dist/owner.js +7 -112
  60. package/dist/owner.js.map +1 -1
  61. package/dist/permit.d.ts +137 -0
  62. package/dist/permit.d.ts.map +1 -0
  63. package/dist/permit.js +355 -0
  64. package/dist/permit.js.map +1 -0
  65. package/dist/portfolio.d.ts +56 -0
  66. package/dist/portfolio.d.ts.map +1 -0
  67. package/dist/portfolio.js +54 -0
  68. package/dist/portfolio.js.map +1 -0
  69. package/dist/price.d.ts +95 -0
  70. package/dist/price.d.ts.map +1 -0
  71. package/dist/price.js +329 -0
  72. package/dist/price.js.map +1 -0
  73. package/dist/rewards/farms.d.ts +26 -0
  74. package/dist/rewards/farms.d.ts.map +1 -0
  75. package/dist/rewards/farms.js +210 -0
  76. package/dist/rewards/farms.js.map +1 -0
  77. package/dist/rewards/index.d.ts +42 -0
  78. package/dist/rewards/index.d.ts.map +1 -0
  79. package/dist/rewards/index.js +382 -0
  80. package/dist/rewards/index.js.map +1 -0
  81. package/dist/rewards/types.d.ts +170 -0
  82. package/dist/rewards/types.d.ts.map +1 -0
  83. package/dist/rewards/types.js +2 -0
  84. package/dist/rewards/types.js.map +1 -0
  85. package/dist/risk.d.ts +42 -0
  86. package/dist/risk.d.ts.map +1 -0
  87. package/dist/risk.js +134 -0
  88. package/dist/risk.js.map +1 -0
  89. package/dist/rpcNodes.d.ts.map +1 -1
  90. package/dist/rpcNodes.js +18 -0
  91. package/dist/rpcNodes.js.map +1 -1
  92. package/dist/simulate.d.ts +186 -0
  93. package/dist/simulate.d.ts.map +1 -0
  94. package/dist/simulate.js +559 -0
  95. package/dist/simulate.js.map +1 -0
  96. package/dist/simulateDecode.d.ts +33 -0
  97. package/dist/simulateDecode.d.ts.map +1 -0
  98. package/dist/simulateDecode.js +321 -0
  99. package/dist/simulateDecode.js.map +1 -0
  100. package/dist/smartAccount/account.d.ts +31 -0
  101. package/dist/smartAccount/account.d.ts.map +1 -0
  102. package/dist/smartAccount/account.js +33 -0
  103. package/dist/smartAccount/account.js.map +1 -0
  104. package/dist/smartAccount/clients.d.ts +77 -0
  105. package/dist/smartAccount/clients.d.ts.map +1 -0
  106. package/dist/smartAccount/clients.js +122 -0
  107. package/dist/smartAccount/clients.js.map +1 -0
  108. package/dist/smartAccount/eip5792.d.ts +77 -0
  109. package/dist/smartAccount/eip5792.d.ts.map +1 -0
  110. package/dist/smartAccount/eip5792.js +152 -0
  111. package/dist/smartAccount/eip5792.js.map +1 -0
  112. package/dist/smartAccount/send.d.ts +40 -0
  113. package/dist/smartAccount/send.d.ts.map +1 -0
  114. package/dist/smartAccount/send.js +271 -0
  115. package/dist/smartAccount/send.js.map +1 -0
  116. package/dist/smartAccount/userOp.d.ts +91 -0
  117. package/dist/smartAccount/userOp.d.ts.map +1 -0
  118. package/dist/smartAccount/userOp.js +124 -0
  119. package/dist/smartAccount/userOp.js.map +1 -0
  120. package/dist/subpaths/approvals.d.ts +26 -0
  121. package/dist/subpaths/approvals.d.ts.map +1 -0
  122. package/dist/subpaths/approvals.js +27 -0
  123. package/dist/subpaths/approvals.js.map +1 -0
  124. package/dist/subpaths/dividends.d.ts +28 -0
  125. package/dist/subpaths/dividends.d.ts.map +1 -0
  126. package/dist/subpaths/dividends.js +29 -0
  127. package/dist/subpaths/dividends.js.map +1 -0
  128. package/dist/subpaths/fees.d.ts +23 -0
  129. package/dist/subpaths/fees.d.ts.map +1 -0
  130. package/dist/subpaths/fees.js +25 -0
  131. package/dist/subpaths/fees.js.map +1 -0
  132. package/dist/subpaths/history.d.ts +22 -0
  133. package/dist/subpaths/history.d.ts.map +1 -0
  134. package/dist/subpaths/history.js +23 -0
  135. package/dist/subpaths/history.js.map +1 -0
  136. package/dist/subpaths/names.d.ts +35 -0
  137. package/dist/subpaths/names.d.ts.map +1 -0
  138. package/dist/subpaths/names.js +39 -0
  139. package/dist/subpaths/names.js.map +1 -0
  140. package/dist/subpaths/permit.d.ts +14 -0
  141. package/dist/subpaths/permit.d.ts.map +1 -0
  142. package/dist/subpaths/permit.js +14 -0
  143. package/dist/subpaths/permit.js.map +1 -0
  144. package/dist/subpaths/price.d.ts +38 -0
  145. package/dist/subpaths/price.d.ts.map +1 -0
  146. package/dist/subpaths/price.js +40 -0
  147. package/dist/subpaths/price.js.map +1 -0
  148. package/dist/subpaths/rewards.d.ts +27 -0
  149. package/dist/subpaths/rewards.d.ts.map +1 -0
  150. package/dist/subpaths/rewards.js +25 -0
  151. package/dist/subpaths/rewards.js.map +1 -0
  152. package/dist/subpaths/risk.d.ts +19 -0
  153. package/dist/subpaths/risk.d.ts.map +1 -0
  154. package/dist/subpaths/risk.js +20 -0
  155. package/dist/subpaths/risk.js.map +1 -0
  156. package/dist/subpaths/simulate.d.ts +25 -0
  157. package/dist/subpaths/simulate.d.ts.map +1 -0
  158. package/dist/subpaths/simulate.js +28 -0
  159. package/dist/subpaths/simulate.js.map +1 -0
  160. package/dist/subpaths/smart-account.d.ts +24 -0
  161. package/dist/subpaths/smart-account.d.ts.map +1 -0
  162. package/dist/subpaths/smart-account.js +24 -0
  163. package/dist/subpaths/smart-account.js.map +1 -0
  164. package/dist/subpaths/swap.d.ts +19 -0
  165. package/dist/subpaths/swap.d.ts.map +1 -0
  166. package/dist/subpaths/swap.js +20 -0
  167. package/dist/subpaths/swap.js.map +1 -0
  168. package/dist/swap.d.ts +168 -0
  169. package/dist/swap.d.ts.map +1 -0
  170. package/dist/swap.js +387 -0
  171. package/dist/swap.js.map +1 -0
  172. package/dist/tokenProbe.d.ts +3 -0
  173. package/dist/tokenProbe.d.ts.map +1 -0
  174. package/dist/tokenProbe.js +4 -0
  175. package/dist/tokenProbe.js.map +1 -0
  176. package/dist/write/batch.d.ts +34 -2
  177. package/dist/write/batch.d.ts.map +1 -1
  178. package/dist/write/batch.js +22 -3
  179. package/dist/write/batch.js.map +1 -1
  180. package/dist/write/collect.d.ts +9 -0
  181. package/dist/write/collect.d.ts.map +1 -1
  182. package/dist/write/collect.js +41 -1
  183. package/dist/write/collect.js.map +1 -1
  184. package/dist/write/send.d.ts +4 -0
  185. package/dist/write/send.d.ts.map +1 -1
  186. package/dist/write/send.js.map +1 -1
  187. package/dist/write/signer.d.ts +5 -1
  188. package/dist/write/signer.d.ts.map +1 -1
  189. package/dist/write/signer.js.map +1 -1
  190. package/dist/write/transfer.d.ts +5 -3
  191. package/dist/write/transfer.d.ts.map +1 -1
  192. package/dist/write/transfer.js +12 -6
  193. package/dist/write/transfer.js.map +1 -1
  194. package/dist/write/tron.d.ts +25 -0
  195. package/dist/write/tron.d.ts.map +1 -1
  196. package/dist/write/tron.js +26 -0
  197. package/dist/write/tron.js.map +1 -1
  198. package/package.json +73 -16
  199. package/src/aggregate.ts +110 -3
  200. package/src/approvals.ts +462 -0
  201. package/src/chains.ts +4 -0
  202. package/src/dividends.ts +360 -0
  203. package/src/fees.ts +201 -0
  204. package/src/history.ts +367 -0
  205. package/src/historySources.ts +360 -0
  206. package/src/http.ts +34 -0
  207. package/src/liquidity/v3.ts +1 -1
  208. package/src/liquidity/v4.ts +4 -3
  209. package/src/lp.ts +21 -2
  210. package/src/lpV4.ts +32 -2
  211. package/src/multicall.ts +3 -0
  212. package/src/names.ts +141 -0
  213. package/src/owner.ts +7 -138
  214. package/src/permit.ts +457 -0
  215. package/src/portfolio.ts +98 -0
  216. package/src/price.ts +415 -0
  217. package/src/rewards/farms.ts +229 -0
  218. package/src/rewards/index.ts +431 -0
  219. package/src/rewards/types.ts +179 -0
  220. package/src/risk.ts +166 -0
  221. package/src/rpcNodes.ts +18 -0
  222. package/src/simulate.ts +727 -0
  223. package/src/simulateDecode.ts +352 -0
  224. package/src/smartAccount/account.ts +63 -0
  225. package/src/smartAccount/clients.ts +180 -0
  226. package/src/smartAccount/eip5792.ts +187 -0
  227. package/src/smartAccount/send.ts +341 -0
  228. package/src/smartAccount/userOp.ts +180 -0
  229. package/src/subpaths/approvals.ts +48 -0
  230. package/src/subpaths/dividends.ts +47 -0
  231. package/src/subpaths/fees.ts +43 -0
  232. package/src/subpaths/history.ts +41 -0
  233. package/src/subpaths/names.ts +43 -0
  234. package/src/subpaths/permit.ts +39 -0
  235. package/src/subpaths/price.ts +60 -0
  236. package/src/subpaths/rewards.ts +46 -0
  237. package/src/subpaths/risk.ts +23 -0
  238. package/src/subpaths/simulate.ts +51 -0
  239. package/src/subpaths/smart-account.ts +40 -0
  240. package/src/subpaths/swap.ts +36 -0
  241. package/src/swap.ts +534 -0
  242. package/src/tokenProbe.ts +5 -0
  243. package/src/write/batch.ts +44 -5
  244. package/src/write/collect.ts +60 -1
  245. package/src/write/send.ts +4 -0
  246. package/src/write/signer.ts +5 -1
  247. package/src/write/transfer.ts +17 -10
  248. package/src/write/tron.ts +43 -0
@@ -0,0 +1,253 @@
1
+ /**
2
+ * Flap(flap.sh,BNB Chain 发币平台)的分红:持有带分红的 Flap 税收代币(FlapTaxToken)的地址按持仓比例分到税收,
3
+ * 分红放在每个代币自己的 Dividend 合约里,持有人(或任何人替持有人)调用 withdrawDividendsFor 领取。
4
+ *
5
+ * 核实过的合约(BSC 主网,2026-10 在主网分叉上实测):
6
+ * - 代币:`dividendContract()` 返回它的 Dividend 合约(Tax Token V3 总是部署;V2 只在 dividendBps > 0 时部署)
7
+ * - Dividend 合约(EIP-1167 克隆,实现 0xd67447C2…5905,Sourcify / BscScan 上未验证源码,函数靠官方文档 + 链上调用核对):
8
+ * `dividendToken()`、`weth()`、`minimumShareBalance()`、`withdrawableDividends(address)`、`withdrawnDividends(address)`、
9
+ * `withdrawDividendsFor(address)`(任何人可调,款项直接到持有人)
10
+ * - 官方 TaxTokenHelper(0x53841c73…8346)的 `getDividendInfo(token, user) → (claimed, pending)` 与上面两个函数结果一致(测试里交叉核对)
11
+ *
12
+ * 只有一种合约形态,所以只有一个适配器(flap);识别不了的代币(没有 dividendContract() 或 Dividend 合约缺函数)放进 unsupported,
13
+ * 不猜函数。
14
+ */
15
+ import { Interface, getAddress } from 'ethers';
16
+ import { NATIVE_TOKEN, formatUnits } from './erc20.js';
17
+ import { runLogScan } from './scan.js';
18
+ import { isTronChain } from './tron.js';
19
+ /** 支持的链:目前只有 BSC(Flap 在 Base、X Layer 等链上也有部署,但没有核实过,不开放) */
20
+ export const FLAP_DIVIDEND_CHAINS = {
21
+ 56: {
22
+ portal: '0xe2cE6ab80874Fa9Fa2aAE65D277Dd6B8e65C9De0',
23
+ taxTokenHelper: '0x53841c73217735F37BC1775538b03b23feFD8346',
24
+ swapRegistry: '0x644A8f560138418bAD4EdEFC7c17878a3c2fBEB6',
25
+ },
26
+ };
27
+ /** Flap 代币地址的靓号后缀(Portal 创建时用):税收代币是 7777,普通代币是 8888(实测也有 8888 的代币带分红合约);发现持仓时只收这类地址 */
28
+ export const FLAP_TOKEN_SUFFIXES = ['7777', '8888'];
29
+ const TOKEN_ABI = [
30
+ 'function dividendContract() view returns (address)',
31
+ 'function balanceOf(address) view returns (uint256)',
32
+ 'function symbol() view returns (string)',
33
+ 'function decimals() view returns (uint8)',
34
+ ];
35
+ const DIVIDEND_ABI = [
36
+ 'function dividendToken() view returns (address)',
37
+ 'function weth() view returns (address)',
38
+ 'function minimumShareBalance() view returns (uint256)',
39
+ 'function withdrawableDividends(address) view returns (uint256)',
40
+ 'function withdrawnDividends(address) view returns (uint256)',
41
+ ];
42
+ const ERC20_META_ABI = ['function symbol() view returns (string)', 'function decimals() view returns (uint8)'];
43
+ const claimInterface = new Interface(['function withdrawDividendsFor(address user)']);
44
+ const ZERO = '0x0000000000000000000000000000000000000000';
45
+ const TRANSFER_TOPIC = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
46
+ /** 一次最多检查的代币数(防止传入或发现的列表无限大) */
47
+ const MAX_TOKENS = 200;
48
+ function assertChain(chainId) {
49
+ if (isTronChain(chainId) || !FLAP_DIVIDEND_CHAINS[chainId]) {
50
+ throw new Error(`Flap dividends are only supported on BNB Chain (56), got chain ${chainId}`);
51
+ }
52
+ }
53
+ /** 发现持有人收到过的 Flap 税收代币(只发现,不核对有没有分红:把 tokens 交给 dividends) */
54
+ export async function scanDividendTokens(provider, owner, options = {}) {
55
+ assertChain(await provider.getChainId());
56
+ const ownerTopic = `0x${getAddress(owner).slice(2).toLowerCase().padStart(64, '0')}`;
57
+ const lookback = Math.max(0, Math.floor(options.lookbackBlocks ?? 5000));
58
+ const suffixes = (options.suffixes ?? FLAP_TOKEN_SUFFIXES).map((x) => x.toLowerCase());
59
+ const progress = await runLogScan({
60
+ provider,
61
+ saved: options.progress,
62
+ initialCursor: (target) => (options.fromBlock !== undefined ? options.fromBlock - 1 : target - lookback),
63
+ filter: { topics: [TRANSFER_TOPIC, null, ownerTopic] },
64
+ // 只收 ERC20 的 Transfer(3 个 topic)里靓号后缀的合约
65
+ collect: (log) => (log.topics.length === 3 && suffixes.some((s) => log.address.toLowerCase().endsWith(s)) ? log.address.toLowerCase() : null),
66
+ maxRange: Math.max(1, Math.floor(options.blockRange ?? 1000)),
67
+ maxRequests: Math.max(1, Math.floor(options.maxRequests ?? 10)),
68
+ timeBudget: options.timeBudget ?? 10_000,
69
+ confirmations: 0,
70
+ ...(options.signal ? { signal: options.signal } : {}),
71
+ });
72
+ return { tokens: (progress?.items ?? []).map((a) => getAddress(a)), cursor: progress?.cursor ?? -1, progress };
73
+ }
74
+ /**
75
+ * 查持有人在 Flap 代币上的分红:余额、可领取数量、已领取数量、分红资产和美元价值。
76
+ * 代币来自 tokens 和 discover(扫描收到过的 Transfer),每个代币都在链上核对(dividendContract() + Dividend 合约的函数),
77
+ * 核对不过的放进 unsupported。不发送交易
78
+ */
79
+ export async function dividends(provider, owner, options = {}) {
80
+ const chainId = await provider.getChainId();
81
+ assertChain(chainId);
82
+ const holder = getAddress(owner);
83
+ let scan;
84
+ const found = new Map();
85
+ const explicit = new Set();
86
+ for (const t of options.tokens ?? []) {
87
+ found.set(getAddress(t).toLowerCase(), getAddress(t));
88
+ explicit.add(getAddress(t).toLowerCase());
89
+ }
90
+ if (options.discover) {
91
+ const r = await scanDividendTokens(provider, holder, options.discover === true ? {} : options.discover);
92
+ scan = { cursor: r.cursor, progress: r.progress, tokens: r.tokens };
93
+ for (const t of r.tokens)
94
+ found.set(t.toLowerCase(), t);
95
+ }
96
+ const tokens = [...found.values()];
97
+ if (tokens.length > MAX_TOKENS)
98
+ throw new Error(`Too many tokens (${tokens.length}), at most ${MAX_TOKENS} per call`);
99
+ const result = { items: [], unsupported: [], ...(scan ? { scan } : {}) };
100
+ if (!tokens.length)
101
+ return result;
102
+ // 第一步:代币本身(余额、精度、Dividend 合约地址)
103
+ const stage1 = await provider.tryAll(tokens.flatMap((t) => [provider.contract(t, TOKEN_ABI).dividendContract(), provider.contract(t, TOKEN_ABI).balanceOf(holder), provider.contract(t, TOKEN_ABI).symbol(), provider.contract(t, TOKEN_ABI).decimals()]));
104
+ const valid = [];
105
+ tokens.forEach((token, i) => {
106
+ const [dividend, balance, symbol, decimals] = stage1.slice(i * 4, i * 4 + 4);
107
+ if (dividend === null || dividend === ZERO) {
108
+ // 发现来的代币大多不是分红代币(普通 8888 代币等),只报告用户明确传入的
109
+ if (explicit.has(token.toLowerCase()))
110
+ result.unsupported.push({ token, reason: dividend === null ? 'no dividendContract() (not a Flap tax token V2/V3)' : 'token has no dividend contract' });
111
+ }
112
+ else if (balance === null || decimals === null) {
113
+ result.unsupported.push({ token, reason: 'not an ERC20 token' });
114
+ }
115
+ else {
116
+ valid.push({ token, dividend, balance, symbol: typeof symbol === 'string' ? symbol : null, decimals: Number(decimals) });
117
+ }
118
+ });
119
+ // 第二步:Dividend 合约(分红代币、可领取、已领取、最低持仓)
120
+ const stage2 = valid.length
121
+ ? await provider.tryAll(valid.flatMap((v) => {
122
+ const d = provider.contract(v.dividend, DIVIDEND_ABI);
123
+ return [d.dividendToken(), d.weth(), d.withdrawableDividends(holder), d.withdrawnDividends(holder), d.minimumShareBalance()];
124
+ }))
125
+ : [];
126
+ const rows = [];
127
+ valid.forEach((v, i) => {
128
+ const [dividendToken, weth, claimable, claimed, min] = stage2.slice(i * 5, i * 5 + 5);
129
+ if (dividendToken === null || claimable === null || claimed === null || min === null) {
130
+ result.unsupported.push({ token: v.token, reason: 'dividend contract does not expose the expected functions (unknown generation)' });
131
+ }
132
+ else {
133
+ rows.push({ v, dividendToken, weth, claimable, claimed, min });
134
+ }
135
+ });
136
+ // 第三步:分红资产的 symbol / decimals(WBNB 作为 BNB 领取:按主币处理)
137
+ const isNative = (r) => r.dividendToken === ZERO || (r.weth !== null && r.dividendToken.toLowerCase() === r.weth.toLowerCase());
138
+ const assetTokens = [...new Set(rows.filter((r) => !isNative(r)).map((r) => r.dividendToken))];
139
+ const meta = new Map();
140
+ if (assetTokens.length) {
141
+ const res = await provider.tryAll(assetTokens.flatMap((a) => [provider.contract(a, ERC20_META_ABI).symbol(), provider.contract(a, ERC20_META_ABI).decimals()]));
142
+ assetTokens.forEach((a, i) => meta.set(a, { symbol: typeof res[i * 2] === 'string' ? res[i * 2] : null, decimals: res[i * 2 + 1] === null ? 18 : Number(res[i * 2 + 1]), known: res[i * 2 + 1] !== null }));
143
+ }
144
+ const nativeMeta = { symbol: 'BNB', decimals: 18, known: true };
145
+ const items = rows.map((r) => {
146
+ const native = isNative(r);
147
+ const m = native ? nativeMeta : (meta.get(r.dividendToken) ?? { symbol: null, decimals: 18, known: false });
148
+ return {
149
+ owner: holder,
150
+ token: r.v.token,
151
+ symbol: r.v.symbol,
152
+ decimals: r.v.decimals,
153
+ balance: r.v.balance.toString(),
154
+ dividendContract: getAddress(r.v.dividend),
155
+ dividendToken: getAddress(r.dividendToken),
156
+ asset: native ? 'native' : getAddress(r.dividendToken),
157
+ assetSymbol: m.symbol,
158
+ assetDecimals: m.decimals,
159
+ ...(m.known ? {} : { decimalsUnknown: true }),
160
+ claimable: r.claimable.toString(),
161
+ claimableFormatted: formatUnits(r.claimable, m.decimals),
162
+ claimed: r.claimed.toString(),
163
+ claimedFormatted: formatUnits(r.claimed, m.decimals),
164
+ usd: null,
165
+ minimumShareBalance: r.min.toString(),
166
+ accruing: r.v.balance >= r.min && r.v.balance > 0n,
167
+ adapter: 'flap',
168
+ };
169
+ });
170
+ const shown = options.includeZero ? items : items.filter((i) => BigInt(i.claimable) > 0n);
171
+ if (options.prices !== false && shown.length) {
172
+ try {
173
+ const { tokenPrices } = await import('./price.js');
174
+ const assets = [...new Set(shown.map((i) => (i.asset === 'native' ? NATIVE_TOKEN : i.asset)))];
175
+ const prices = await tokenPrices(provider, assets, { ...(typeof options.prices === 'object' ? { sources: [options.prices] } : {}), ...(options.fetch ? { fetch: options.fetch } : {}) });
176
+ const byAsset = new Map(prices.map((p) => [p.token.toLowerCase(), p.price]));
177
+ for (const i of shown) {
178
+ if (i.decimalsUnknown)
179
+ continue; // 精度未知,换算不出可信的美元价值
180
+ const price = byAsset.get((i.asset === 'native' ? NATIVE_TOKEN : i.asset).toLowerCase());
181
+ i.usd = price === null || price === undefined ? null : Number(i.claimableFormatted) * price;
182
+ }
183
+ }
184
+ catch (err) {
185
+ result.priceError = err instanceof Error ? err.message : String(err);
186
+ }
187
+ }
188
+ result.items = shown;
189
+ return result;
190
+ }
191
+ /**
192
+ * 领取分红要发的交易(不签名):每个代币一笔 `withdrawDividendsFor(owner)`,发给它的 Dividend 合约,款项直接到 owner。
193
+ * 只包含 claimable > 0 的项。只校验 owner / dividendContract 是合法地址,不连链:items 来自调用方,
194
+ * 要确认 dividendContract 确实是代币自己的 Dividend 合约,用 claimDividends(发送前会在链上核对)
195
+ */
196
+ export function buildClaimDividends(items) {
197
+ return items
198
+ .filter((item) => BigInt(item.claimable) > 0n)
199
+ .map((item) => {
200
+ if (item.adapter !== 'flap')
201
+ throw new Error(`Unsupported dividend adapter for ${item.token}`);
202
+ let to;
203
+ let owner;
204
+ try {
205
+ to = getAddress(item.dividendContract);
206
+ owner = getAddress(item.owner);
207
+ }
208
+ catch {
209
+ throw new Error(`Invalid dividendContract / owner address for ${item.token}`);
210
+ }
211
+ return { to, data: claimInterface.encodeFunctionData('withdrawDividendsFor', [owner]), value: '0', item };
212
+ });
213
+ }
214
+ /**
215
+ * 领取分红:构建(同 buildClaimDividends)后用 from 签名发送,钱包和选项同 batchCall
216
+ * (mode: '7702' / '4337' / '5792' 时合成一笔原子交易)。任何人都可以替持有人领取,款项直接到 item.owner,所以 from 不必是持有人(如代付 gas)。
217
+ *
218
+ * ```ts
219
+ * const { items } = await getDividends(user, { chainId: 56, discover: true })
220
+ * await claimDividends(provider, key, items, { mode: '7702' })
221
+ * ```
222
+ */
223
+ export async function claimDividends(provider, from, items, options = {}) {
224
+ assertChain(await provider.getChainId());
225
+ const { simulate: preCheck = true, ...sendOptions } = options;
226
+ const txs = buildClaimDividends(items);
227
+ if (!txs.length)
228
+ return [];
229
+ const skipped = new Map();
230
+ // 核对 items 里的 dividendContract 确实是代币自己的 Dividend 合约(items 来自调用方,不能直接信)
231
+ const onChain = await provider.tryAll(txs.map((tx) => provider.contract(tx.item.token, TOKEN_ABI).dividendContract()));
232
+ onChain.forEach((d, i) => {
233
+ if (d === null || txs[i].to.toLowerCase() !== d.toLowerCase()) {
234
+ skipped.set(i, `dividendContract mismatch: ${txs[i].to} is not the dividend contract of ${txs[i].item.token}`);
235
+ }
236
+ });
237
+ if (preCheck) {
238
+ const { simulate } = await import('./simulate.js');
239
+ const sims = await Promise.all(txs.map((tx, i) => skipped.has(i) ? Promise.resolve({ success: true }) : simulate(provider, { to: tx.to, data: tx.data, from: tx.item.owner }, { usd: false, risk: false }).catch((err) => ({ success: false, error: err instanceof Error ? err.message : String(err) }))));
240
+ sims.forEach((s, i) => !s.success && skipped.set(i, s.error ?? 'simulation failed'));
241
+ }
242
+ const send = txs.map((tx, i) => ({ tx, i })).filter(({ i }) => !skipped.has(i));
243
+ const { batchCall } = await import('./write/batch.js');
244
+ const sent = send.length ? await batchCall(provider, send.map(({ tx }) => ({ from, to: tx.to, data: tx.data })), { continueOnError: true, ...sendOptions }) : [];
245
+ const sentBy = new Map(send.map(({ i }, k) => [i, sent[k]]));
246
+ return txs.map((tx, i) => {
247
+ const r = sentBy.get(i);
248
+ if (r)
249
+ return { ...r, index: i, item: tx.item };
250
+ return { index: i, from: tx.item.owner, to: tx.to, status: 'skipped', hash: null, nonce: null, gasLimit: null, gasUsed: null, fee: null, blockNumber: null, error: skipped.get(i) ?? null, item: tx.item };
251
+ });
252
+ }
253
+ //# sourceMappingURL=dividends.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dividends.js","sourceRoot":"","sources":["../src/dividends.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAE9C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAEtD,OAAO,EAAE,UAAU,EAAwB,MAAM,WAAW,CAAA;AAE5D,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAKvC,4DAA4D;AAC5D,MAAM,CAAC,MAAM,oBAAoB,GAA+F;IAC9H,EAAE,EAAE;QACF,MAAM,EAAE,4CAA4C;QACpD,cAAc,EAAE,4CAA4C;QAC5D,YAAY,EAAE,4CAA4C;KAC3D;CACF,CAAA;AAED,wFAAwF;AACxF,MAAM,CAAC,MAAM,mBAAmB,GAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAEtE,MAAM,SAAS,GAAG;IAChB,oDAAoD;IACpD,oDAAoD;IACpD,yCAAyC;IACzC,0CAA0C;CAC3C,CAAA;AACD,MAAM,YAAY,GAAG;IACnB,iDAAiD;IACjD,wCAAwC;IACxC,uDAAuD;IACvD,gEAAgE;IAChE,6DAA6D;CAC9D,CAAA;AACD,MAAM,cAAc,GAAG,CAAC,yCAAyC,EAAE,0CAA0C,CAAC,CAAA;AAC9G,MAAM,cAAc,GAAG,IAAI,SAAS,CAAC,CAAC,6CAA6C,CAAC,CAAC,CAAA;AACrF,MAAM,IAAI,GAAG,4CAA4C,CAAA;AACzD,MAAM,cAAc,GAAG,oEAAoE,CAAA;AAE3F,gCAAgC;AAChC,MAAM,UAAU,GAAG,GAAG,CAAA;AAkFtB,SAAS,WAAW,CAAC,OAAe;IAClC,IAAI,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,kEAAkE,OAAO,EAAE,CAAC,CAAA;IAC9F,CAAC;AACH,CAAC;AAED,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,QAAkB,EAAE,KAAa,EAAE,UAA+B,EAAE;IAC3G,WAAW,CAAC,MAAM,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;IACxC,MAAM,UAAU,GAAG,KAAK,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAA;IACpF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,cAAc,IAAI,IAAI,CAAC,CAAC,CAAA;IACxE,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,mBAAmB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAA;IACtF,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC;QAChC,QAAQ;QACR,KAAK,EAAE,OAAO,CAAC,QAAQ;QACvB,aAAa,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,QAAQ,CAAC;QACxG,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,cAAc,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE;QACtD,yCAAyC;QACzC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7I,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC;QAC7D,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;QAC/D,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,MAAM;QACxC,aAAa,EAAE,CAAC;QAChB,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtD,CAAC,CAAA;IACF,OAAO,EAAE,MAAM,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAA;AAChH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAkB,EAAE,KAAa,EAAE,UAA4B,EAAE;IAC/F,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,CAAA;IAC3C,WAAW,CAAC,OAAO,CAAC,CAAA;IACpB,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;IAEhC,IAAI,IAA6B,CAAA;IACjC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAA;IACvC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAA;IAClC,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QACrC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;QACrD,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAA;IAC3C,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,CAAC,GAAG,MAAM,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QACvG,IAAI,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAA;QACnE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAA;IACzD,CAAC;IACD,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAA;IAClC,IAAI,MAAM,CAAC,MAAM,GAAG,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,MAAM,CAAC,MAAM,cAAc,UAAU,WAAW,CAAC,CAAA;IACrH,MAAM,MAAM,GAAoB,EAAE,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;IACzF,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,OAAO,MAAM,CAAA;IAEjC,gCAAgC;IAChC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,gBAAgB,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAA;IAC1P,MAAM,KAAK,GAAyG,EAAE,CAAA;IACtH,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QAC1B,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAiE,CAAA;QAC5I,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC3C,yCAAyC;YACzC,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;gBAAE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,oDAAoD,CAAC,CAAC,CAAC,gCAAgC,EAAE,CAAC,CAAA;QAChM,CAAC;aAAM,IAAI,OAAO,KAAK,IAAI,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC,CAAA;QAClE,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;QAC1H,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,qCAAqC;IACrC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM;QACzB,CAAC,CAAC,MAAM,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACxC,MAAM,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAA;YACrD,OAAO,CAAC,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAA;QAC9H,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,EAAE,CAAA;IACN,MAAM,IAAI,GAAsI,EAAE,CAAA;IAClJ,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACrB,MAAM,CAAC,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAgF,CAAA;QACpK,IAAI,aAAa,KAAK,IAAI,IAAI,SAAS,KAAK,IAAI,IAAI,OAAO,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACrF,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,+EAA+E,EAAE,CAAC,CAAA;QACtI,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAA;QAChE,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,oDAAoD;IACpD,MAAM,QAAQ,GAAG,CAAC,CAAwB,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,aAAa,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAA;IACtJ,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAA;IAC9F,MAAM,IAAI,GAAG,IAAI,GAAG,EAAuE,CAAA;IAC3F,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,MAAM,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAA;QAC/J,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAY,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAA;IACzN,CAAC;IACD,MAAM,UAAU,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;IAE/D,MAAM,KAAK,GAAmB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC3C,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;QAC1B,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAA;QAC3G,OAAO;YACL,KAAK,EAAE,MAAM;YACb,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK;YAChB,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM;YAClB,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ;YACtB,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE;YAC/B,gBAAgB,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC1C,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC;YAC1C,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC;YACtD,WAAW,EAAE,CAAC,CAAC,MAAM;YACrB,aAAa,EAAE,CAAC,CAAC,QAAQ;YACzB,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;YAC7C,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,QAAQ,EAAE;YACjC,kBAAkB,EAAE,WAAW,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC;YACxD,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE;YAC7B,gBAAgB,EAAE,WAAW,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC;YACpD,GAAG,EAAE,IAAI;YACT,mBAAmB,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE;YACrC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,EAAE;YAClD,OAAO,EAAE,MAAM;SAChB,CAAA;IACH,CAAC,CAAC,CAAA;IACF,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAA;IAEzF,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAC7C,IAAI,CAAC;YACH,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAA;YAClD,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;YAC9F,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;YACxL,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;YAC5E,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;gBACtB,IAAI,CAAC,CAAC,eAAe;oBAAE,SAAQ,CAAC,mBAAmB;gBACnD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,CAAA;gBACxF,CAAC,CAAC,GAAG,GAAG,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAG,KAAK,CAAA;YAC7F,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,UAAU,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACtE,CAAC;IACH,CAAC;IACD,MAAM,CAAC,KAAK,GAAG,KAAK,CAAA;IACpB,OAAO,MAAM,CAAA;AACf,CAAC;AAaD;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAA8B;IAChE,OAAO,KAAK;SACT,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;SAC7C,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,IAAI,IAAI,CAAC,OAAO,KAAK,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;QAC9F,IAAI,EAAU,CAAA;QACd,IAAI,KAAa,CAAA;QACjB,IAAI,CAAC;YACH,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;YACtC,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,gDAAgD,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;QAC/E,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,cAAc,CAAC,kBAAkB,CAAC,sBAAsB,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,GAAY,EAAE,IAAI,EAAE,CAAA;IACpH,CAAC,CAAC,CAAA;AACN,CAAC;AAWD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAkB,EAAE,IAAiB,EAAE,KAA8B,EAAE,UAAiC,EAAE;IAC7I,WAAW,CAAC,MAAM,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;IACxC,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,EAAE,GAAG,WAAW,EAAE,GAAG,OAAO,CAAA;IAC7D,MAAM,GAAG,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAA;IACtC,IAAI,CAAC,GAAG,CAAC,MAAM;QAAE,OAAO,EAAE,CAAA;IAC1B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAA;IACzC,uEAAuE;IACvE,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAS,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAA;IAC9H,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACvB,IAAI,CAAC,KAAK,IAAI,IAAK,GAAG,CAAC,CAAC,CAAqB,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YACnF,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,8BAA+B,GAAG,CAAC,CAAC,CAAqB,CAAC,EAAE,oCAAqC,GAAG,CAAC,CAAC,CAAqB,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;QAC1J,CAAC;IACH,CAAC,CAAC,CAAA;IACF,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAA;QAClD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAiD,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QAClW,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,mBAAmB,CAAC,CAAC,CAAA;IACtF,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;IAC/E,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAA;IACtD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAChK,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAgB,CAAC,CAAC,CAAC,CAAA;IAC3E,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE;QACvB,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QACvB,IAAI,CAAC;YAAE,OAAO,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAA;QAC/C,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAA;IAC5M,CAAC,CAAC,CAAA;AACJ,CAAC"}
package/dist/fees.d.ts ADDED
@@ -0,0 +1,97 @@
1
+ /**
2
+ * 手续费估算(子路径 `@w3lib/evm-batch-call/fees`):EIP-1559 的 baseFee 和三档优先费(按最近区块的 eth_feeHistory),
3
+ * 一笔交易的手续费(含 OP Stack / Scroll 的 L1 数据费);Tron 按能量 / 带宽和账户剩余的资源算要烧的 TRX
4
+ */
5
+ import type { BigNumberish } from 'ethers';
6
+ import type { Provider } from './provider.js';
7
+ export type FeeLevel = 'slow' | 'normal' | 'fast';
8
+ /** 一档费用(wei 的十进制字符串):EIP-1559 链是 maxFeePerGas / maxPriorityFeePerGas,legacy 链是 gasPrice */
9
+ export type FeeLevelEstimate = {
10
+ maxFeePerGas: string;
11
+ maxPriorityFeePerGas: string;
12
+ } | {
13
+ gasPrice: string;
14
+ };
15
+ export interface FeeEstimate {
16
+ type: 'eip1559' | 'legacy';
17
+ /** 下一个区块的 baseFee(wei);legacy 链为 null */
18
+ baseFee: string | null;
19
+ slow: FeeLevelEstimate;
20
+ normal: FeeLevelEstimate;
21
+ fast: FeeLevelEstimate;
22
+ }
23
+ export interface EstimateFeesOptions {
24
+ /** 看最近多少个区块,默认 20 */
25
+ blocks?: number;
26
+ /** 三档优先费取各区块交易优先费的百分位,默认 [10, 50, 90] */
27
+ percentiles?: readonly [number, number, number];
28
+ /** maxFeePerGas = baseFee × baseFeeMultiplier + 优先费,默认 2(baseFee 连涨几个区块也够) */
29
+ baseFeeMultiplier?: number;
30
+ }
31
+ /**
32
+ * 当前的手续费建议(EVM 链):baseFee 取下一个区块的,三档优先费是最近区块里交易优先费的百分位的中位数;
33
+ * 节点不支持 eth_feeHistory 或链上没有 baseFee 时按 eth_gasPrice(三档为 1、1、1.2 倍)。Tron 用 estimateCost
34
+ *
35
+ * ```ts
36
+ * const fees = await estimateFees(provider)
37
+ * // { type: 'eip1559', baseFee: '1200000000', slow: { maxFeePerGas, maxPriorityFeePerGas }, normal: {…}, fast: {…} }
38
+ * ```
39
+ */
40
+ export declare function estimateFees(provider: Provider, options?: EstimateFeesOptions): Promise<FeeEstimate>;
41
+ export interface CostCall {
42
+ /** 发送者(预估 gas、Tron 上按它剩余的资源算) */
43
+ from: string;
44
+ to: string;
45
+ data?: string;
46
+ value?: BigNumberish;
47
+ }
48
+ export interface EvmCostEstimate {
49
+ type: 'evm';
50
+ gasLimit: string;
51
+ /** 这一档的每 gas 价格:EIP-1559 是 baseFee + 优先费(预计实际付的),legacy 是 gasPrice */
52
+ gasPrice: string;
53
+ /** gasLimit × gasPrice(wei) */
54
+ fee: string;
55
+ /** 最多付多少:gasLimit × maxFeePerGas(legacy 同 fee) */
56
+ maxFee: string;
57
+ /** OP Stack / Scroll 的 L1 数据费(wei,含 25% 余量),其他链为 0 */
58
+ l1Fee: string;
59
+ /** fee + l1Fee(wei)和按主币精度换算的值 */
60
+ total: string;
61
+ totalFormatted: string;
62
+ symbol: string | null;
63
+ }
64
+ export interface TronCost {
65
+ type: 'tron';
66
+ energy: number;
67
+ bandwidth: number;
68
+ /** 剩余能量 / 带宽不够时要烧的 TRX(sun) */
69
+ energyBurn: string;
70
+ bandwidthBurn: string;
71
+ /** 转 TRX 给没激活的地址(激活费算在 bandwidthBurn 里) */
72
+ activates: boolean;
73
+ energyPrice: string;
74
+ bandwidthPrice: string;
75
+ /** energyBurn + bandwidthBurn(sun)和按 TRX 换算的值 */
76
+ total: string;
77
+ totalFormatted: string;
78
+ symbol: 'TRX';
79
+ }
80
+ export type CostEstimate = EvmCostEstimate | TronCost;
81
+ export interface EstimateCostOptions extends EstimateFeesOptions {
82
+ /** 用哪一档,默认 'normal' */
83
+ level?: FeeLevel;
84
+ /** 已经查好的费用建议(多笔交易共用,不再查一次) */
85
+ fees?: FeeEstimate;
86
+ }
87
+ /**
88
+ * 估算一笔交易的手续费:EVM 预估 gas × 这一档的价格(+ L1 数据费);Tron 模拟能量,按发送者剩余的资源算要烧的 TRX。
89
+ * 预估 gas 会执行一遍交易,revert 时抛出
90
+ *
91
+ * ```ts
92
+ * await estimateCost(provider, { from: user, to: USDT, data }) // { type: 'evm', gasLimit, fee, total, totalFormatted: '0.00042', symbol: 'BNB', … }
93
+ * await estimateCost(tronProvider, { from, to: USDT, data }) // { type: 'tron', energy: 64285, energyBurn: '6750000', totalFormatted: '7.0', … }
94
+ * ```
95
+ */
96
+ export declare function estimateCost(provider: Provider, call: CostCall, options?: EstimateCostOptions): Promise<CostEstimate>;
97
+ //# sourceMappingURL=fees.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fees.d.ts","sourceRoot":"","sources":["../src/fees.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAI1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAG7C,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEjD,2FAA2F;AAC3F,MAAM,MAAM,gBAAgB,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,oBAAoB,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAA;AAE5G,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAA;IAC1B,yCAAyC;IACzC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,IAAI,EAAE,gBAAgB,CAAA;IACtB,MAAM,EAAE,gBAAgB,CAAA;IACxB,IAAI,EAAE,gBAAgB,CAAA;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,qBAAqB;IACrB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,yCAAyC;IACzC,WAAW,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/C,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAwBD;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,WAAW,CAAC,CA6B9G;AAED,MAAM,WAAW,QAAQ;IACvB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,YAAY,CAAA;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,KAAK,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAA;IAChB,+BAA+B;IAC/B,GAAG,EAAE,MAAM,CAAA;IACX,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAA;IACd,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAA;IACb,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,cAAc,EAAE,MAAM,CAAA;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,MAAM,CAAA;IACrB,2CAA2C;IAC3C,SAAS,EAAE,OAAO,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAA;IACb,cAAc,EAAE,MAAM,CAAA;IACtB,MAAM,EAAE,KAAK,CAAA;CACd;AAED,MAAM,MAAM,YAAY,GAAG,eAAe,GAAG,QAAQ,CAAA;AAErD,MAAM,WAAW,mBAAoB,SAAQ,mBAAmB;IAC9D,uBAAuB;IACvB,KAAK,CAAC,EAAE,QAAQ,CAAA;IAChB,8BAA8B;IAC9B,IAAI,CAAC,EAAE,WAAW,CAAA;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,YAAY,CAAC,CA4C/H"}
package/dist/fees.js ADDED
@@ -0,0 +1,115 @@
1
+ import { getNativeCurrency } from './chains.js';
2
+ import { formatUnits } from './erc20.js';
3
+ import { isTronChain } from './tron.js';
4
+ async function send(provider, method, params) {
5
+ const { runOnNodes } = await import('./write/rpc.js');
6
+ return runOnNodes(provider.rpc, method, async (node) => {
7
+ if (typeof node.send !== 'function')
8
+ throw new Error(`${method} is not supported by this node; pass an RPC URL or an ethers Provider`);
9
+ return (await node.send(method, params));
10
+ });
11
+ }
12
+ const median = (values) => {
13
+ if (!values.length)
14
+ return 0n;
15
+ const sorted = [...values].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
16
+ return sorted[Math.floor(sorted.length / 2)];
17
+ };
18
+ /**
19
+ * 当前的手续费建议(EVM 链):baseFee 取下一个区块的,三档优先费是最近区块里交易优先费的百分位的中位数;
20
+ * 节点不支持 eth_feeHistory 或链上没有 baseFee 时按 eth_gasPrice(三档为 1、1、1.2 倍)。Tron 用 estimateCost
21
+ *
22
+ * ```ts
23
+ * const fees = await estimateFees(provider)
24
+ * // { type: 'eip1559', baseFee: '1200000000', slow: { maxFeePerGas, maxPriorityFeePerGas }, normal: {…}, fast: {…} }
25
+ * ```
26
+ */
27
+ export async function estimateFees(provider, options = {}) {
28
+ if (isTronChain(await provider.getChainId()))
29
+ throw new Error('estimateFees is for EVM chains; use estimateCost on Tron');
30
+ const blocks = Math.max(1, Math.min(1024, Math.floor(options.blocks ?? 20)));
31
+ const percentiles = options.percentiles ?? [10, 50, 90];
32
+ if (!percentiles.every((p, i) => p >= 0 && p <= 100 && (i === 0 || p >= percentiles[i - 1])))
33
+ throw new RangeError('percentiles must be ascending numbers in [0, 100]');
34
+ const multiplier = options.baseFeeMultiplier ?? 2;
35
+ let history = null;
36
+ try {
37
+ history = await send(provider, 'eth_feeHistory', [`0x${blocks.toString(16)}`, 'latest', [...percentiles]]);
38
+ }
39
+ catch (err) {
40
+ // 只有节点 / 链不支持 feeHistory 时才按 gasPrice;网络等其他错误照常抛出(不要在 EIP-1559 链上悄悄退回 legacy)
41
+ if (!/not (supported|available|found)|unsupported|does not exist|unknown method|-32601|method.*not/i.test(err instanceof Error ? err.message : String(err)))
42
+ throw err;
43
+ history = null;
44
+ }
45
+ const baseFees = history?.baseFeePerGas ?? [];
46
+ const next = baseFees.length ? BigInt(baseFees[baseFees.length - 1]) : 0n;
47
+ if (!history || !baseFees.length || next === 0n) {
48
+ const gasPrice = BigInt(await send(provider, 'eth_gasPrice', []));
49
+ const level = (n, d) => ({ gasPrice: ((gasPrice * n) / d).toString() });
50
+ return { type: 'legacy', baseFee: null, slow: level(1n, 1n), normal: level(1n, 1n), fast: level(6n, 5n) };
51
+ }
52
+ const rewards = history.reward ?? [];
53
+ // 每档:各区块这个百分位的优先费取中位数(空区块的 0 不算)
54
+ const tip = (k) => median(rewards.map((r) => BigInt(r[k] ?? '0')).filter((v) => v > 0n));
55
+ const base = (next * BigInt(Math.round(multiplier * 1000))) / 1000n;
56
+ const level = (priority) => ({ maxFeePerGas: (base + priority).toString(), maxPriorityFeePerGas: priority.toString() });
57
+ const [slow, normal, fast] = [tip(0), tip(1), tip(2)];
58
+ // 优先费不递减(区块很空时三档可能相同)
59
+ return { type: 'eip1559', baseFee: next.toString(), slow: level(slow), normal: level(normal > slow ? normal : slow), fast: level(fast > normal ? fast : normal > slow ? normal : slow) };
60
+ }
61
+ /**
62
+ * 估算一笔交易的手续费:EVM 预估 gas × 这一档的价格(+ L1 数据费);Tron 模拟能量,按发送者剩余的资源算要烧的 TRX。
63
+ * 预估 gas 会执行一遍交易,revert 时抛出
64
+ *
65
+ * ```ts
66
+ * await estimateCost(provider, { from: user, to: USDT, data }) // { type: 'evm', gasLimit, fee, total, totalFormatted: '0.00042', symbol: 'BNB', … }
67
+ * await estimateCost(tronProvider, { from, to: USDT, data }) // { type: 'tron', energy: 64285, energyBurn: '6750000', totalFormatted: '7.0', … }
68
+ * ```
69
+ */
70
+ export async function estimateCost(provider, call, options = {}) {
71
+ const chainId = await provider.getChainId();
72
+ const value = BigInt(call.value ?? 0);
73
+ if (isTronChain(chainId)) {
74
+ const { tronEstimateCost } = await import('./write/tron.js');
75
+ const c = await tronEstimateCost(provider, { from: call.from, to: call.to, ...(call.data ? { data: call.data } : {}), value });
76
+ const total = c.energyBurn + c.bandwidthBurn;
77
+ return {
78
+ type: 'tron',
79
+ energy: c.energy,
80
+ bandwidth: c.bandwidth,
81
+ energyBurn: c.energyBurn.toString(),
82
+ bandwidthBurn: c.bandwidthBurn.toString(),
83
+ activates: c.activates,
84
+ energyPrice: c.energyPrice.toString(),
85
+ bandwidthPrice: c.bandwidthPrice.toString(),
86
+ total: total.toString(),
87
+ totalFormatted: formatUnits(total, 6),
88
+ symbol: 'TRX',
89
+ };
90
+ }
91
+ const { WriteRpc, l1Fee } = await import('./write/rpc.js');
92
+ const rpc = await WriteRpc.from(provider);
93
+ const tx = { from: call.from, to: call.to, data: call.data ?? '0x', value };
94
+ const [gasLimit, fees] = await Promise.all([rpc.estimateGas(tx), options.fees ? Promise.resolve(options.fees) : estimateFees(provider, options)]);
95
+ const level = fees[options.level ?? 'normal'];
96
+ const perGas = 'gasPrice' in level ? BigInt(level.gasPrice) : BigInt(fees.baseFee ?? '0') + BigInt(level.maxPriorityFeePerGas);
97
+ const maxPerGas = 'gasPrice' in level ? perGas : BigInt(level.maxFeePerGas);
98
+ const feeFields = 'gasPrice' in level ? { type: 0, gasPrice: perGas } : { type: 2, maxFeePerGas: maxPerGas, maxPriorityFeePerGas: BigInt(level.maxPriorityFeePerGas) };
99
+ const l1 = await l1Fee(rpc, { ...tx, from: undefined, gasLimit, ...feeFields });
100
+ const fee = gasLimit * perGas;
101
+ const total = fee + l1;
102
+ const native = getNativeCurrency(chainId);
103
+ return {
104
+ type: 'evm',
105
+ gasLimit: gasLimit.toString(),
106
+ gasPrice: perGas.toString(),
107
+ fee: fee.toString(),
108
+ maxFee: (gasLimit * maxPerGas).toString(),
109
+ l1Fee: l1.toString(),
110
+ total: total.toString(),
111
+ totalFormatted: formatUnits(total, native?.decimals ?? 18),
112
+ symbol: native?.symbol ?? null,
113
+ };
114
+ }
115
+ //# sourceMappingURL=fees.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fees.js","sourceRoot":"","sources":["../src/fees.ts"],"names":[],"mappings":"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"}