@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
package/dist/permit.js ADDED
@@ -0,0 +1,355 @@
1
+ /**
2
+ * 免 gas 授权(子路径 `@w3lib/evm-batch-call/permit`):EIP-2612 permit(含 DAI 风格)、Permit2(AllowanceTransfer 的 PermitSingle / PermitBatch、
3
+ * SignatureTransfer 的 permitTransferFrom)。构建 EIP-712 数据、用 ethers Signer 签名(私钥 / 浏览器钱包都行)、本地验证签名、生成上链的 calldata。
4
+ *
5
+ * 安全默认:金额精确(无限额度要显式 allowUnlimited)、有效期默认 30 分钟(超过 24 小时要显式 allowLongDeadline)、
6
+ * 签名前核对 owner = 签名者、chainId、verifyingContract(代币本身 / Permit2)、spender 不是零地址
7
+ */
8
+ import { Interface, MaxUint256, TypedDataEncoder, getAddress, hexlify, keccak256, randomBytes, toUtf8Bytes, verifyTypedData, Signature, ZeroAddress } from 'ethers';
9
+ /** Uniswap 的 Permit2(各 EVM 链上地址相同) */
10
+ export const PERMIT2_ADDRESS = '0x000000000022D473030F116dDEE9F6B43aC78BA3';
11
+ export const MAX_UINT160 = (1n << 160n) - 1n;
12
+ /** 默认的签名有效期(秒) */
13
+ export const DEFAULT_PERMIT_DEADLINE = 1800;
14
+ /** 有效期超过这个值(秒)要显式 allowLongDeadline */
15
+ export const MAX_PERMIT_DEADLINE = 86_400;
16
+ const now = () => Math.floor(Date.now() / 1000);
17
+ function resolveDeadline(options, label = 'deadline') {
18
+ const at = options.deadlineAt ?? now() + Math.floor(options.deadline ?? DEFAULT_PERMIT_DEADLINE);
19
+ if (!Number.isSafeInteger(at) || at <= now() + 10) {
20
+ throw new RangeError(`${label} must be at least 10 seconds in the future`);
21
+ }
22
+ if (at > now() + MAX_PERMIT_DEADLINE + 60 && !options.allowLongDeadline) {
23
+ throw new RangeError(`${label} is more than 24 hours away; pass allowLongDeadline: true if that is intended`);
24
+ }
25
+ return at;
26
+ }
27
+ function checkParty(owner, spender) {
28
+ const s = getAddress(spender);
29
+ if (s === ZeroAddress)
30
+ throw new Error('spender must not be the zero address');
31
+ return [getAddress(owner), s];
32
+ }
33
+ function checkAmount(amount, max, options, label = 'amount') {
34
+ if (amount <= 0n)
35
+ throw new RangeError(`${label} must be greater than 0 (a blank permit is never signed)`);
36
+ if (amount > max)
37
+ throw new RangeError(`${label} exceeds the maximum`);
38
+ if (amount === max && !options.allowUnlimited) {
39
+ throw new RangeError(`${label} is unlimited; pass allowUnlimited: true to sign an unlimited permit`);
40
+ }
41
+ }
42
+ // ---------------------------------------------------------------------------------------------
43
+ // EIP-2612 / DAI
44
+ // ---------------------------------------------------------------------------------------------
45
+ const DAI_TYPEHASH = keccak256(toUtf8Bytes('Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)'));
46
+ const PERMIT_TYPES = {
47
+ Permit: [
48
+ { name: 'owner', type: 'address' },
49
+ { name: 'spender', type: 'address' },
50
+ { name: 'value', type: 'uint256' },
51
+ { name: 'nonce', type: 'uint256' },
52
+ { name: 'deadline', type: 'uint256' },
53
+ ],
54
+ };
55
+ const DAI_TYPES = {
56
+ Permit: [
57
+ { name: 'holder', type: 'address' },
58
+ { name: 'spender', type: 'address' },
59
+ { name: 'nonce', type: 'uint256' },
60
+ { name: 'expiry', type: 'uint256' },
61
+ { name: 'allowed', type: 'bool' },
62
+ ],
63
+ };
64
+ const tokenInterface = new Interface([
65
+ 'function name() view returns (string)',
66
+ 'function version() view returns (string)',
67
+ 'function DOMAIN_SEPARATOR() view returns (bytes32)',
68
+ 'function nonces(address owner) view returns (uint256)',
69
+ 'function PERMIT_TYPEHASH() view returns (bytes32)',
70
+ 'function eip712Domain() view returns (bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions)',
71
+ 'function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)',
72
+ 'function permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s)',
73
+ ]);
74
+ /**
75
+ * 检测代币是否支持 permit:读 nonces / DOMAIN_SEPARATOR / name / version / eip712Domain(EIP-5267),
76
+ * 按链 ID 和代币地址重新算 domain,**和代币的 DOMAIN_SEPARATOR 逐位一致**才算支持(不一致说明 domain 参数猜错或代币的实现特殊,签了也会被拒)。
77
+ * 通过 PERMIT_TYPEHASH 区分 DAI 风格(Permit(holder, spender, nonce, expiry, allowed))
78
+ */
79
+ export async function detectPermit(provider, token) {
80
+ const address = getAddress(token);
81
+ const chainId = await provider.getChainId();
82
+ const c = provider.contract(address, tokenInterface);
83
+ const [name, version, separator, nonce, domain5267, typehash] = await provider.tryAll([
84
+ c.name(),
85
+ c.version(),
86
+ c.DOMAIN_SEPARATOR(),
87
+ c.nonces(ZeroAddress),
88
+ c.eip712Domain(),
89
+ c.PERMIT_TYPEHASH(),
90
+ ]);
91
+ if (separator === null || nonce === null) {
92
+ return { kind: null, reason: 'the token has no nonces() / DOMAIN_SEPARATOR(), so it does not support permit' };
93
+ }
94
+ const candidates = [];
95
+ if (domain5267) {
96
+ const d = domain5267;
97
+ candidates.push({ name: d.name, version: d.version, chainId: d.chainId, verifyingContract: d.verifyingContract });
98
+ }
99
+ if (name !== null) {
100
+ for (const v of [version, '1', '2']) {
101
+ if (v !== null)
102
+ candidates.push({ name: name, version: v, chainId, verifyingContract: address });
103
+ }
104
+ }
105
+ const match = candidates.find((d) => safeDomainHash(d) === separator.toLowerCase() && Number(d.chainId) === chainId && getAddress(d.verifyingContract) === address);
106
+ if (!match) {
107
+ return { kind: null, reason: 'the EIP-712 domain computed from name / version / chainId / address does not match the token DOMAIN_SEPARATOR (non-standard permit)' };
108
+ }
109
+ return { kind: typehash !== null && typehash.toLowerCase() === DAI_TYPEHASH ? 'dai' : 'eip2612', domain: match };
110
+ }
111
+ function safeDomainHash(d) {
112
+ try {
113
+ return TypedDataEncoder.hashDomain(d).toLowerCase();
114
+ }
115
+ catch {
116
+ return null;
117
+ }
118
+ }
119
+ /**
120
+ * 构建 EIP-2612 permit(代币不支持、domain 对不上时抛错):读 owner 当前的 nonce,默认有效期 30 分钟、精确额度。
121
+ * 返回要签的数据(`signPermit` 签名)
122
+ */
123
+ export async function buildPermit(provider, params, options = {}) {
124
+ const token = getAddress(params.token);
125
+ const [owner, spender] = checkParty(params.owner, params.spender);
126
+ const value = BigInt(params.value);
127
+ const support = await detectPermit(provider, token);
128
+ if (!support.kind || !support.domain) {
129
+ throw new Error(`${token} does not support permit: ${support.reason}`);
130
+ }
131
+ const chainId = await provider.getChainId();
132
+ const deadline = resolveDeadline(options);
133
+ const [nonce] = await provider.all([provider.contract(token, tokenInterface).nonces(owner)]);
134
+ if (support.kind === 'dai') {
135
+ if (!options.allowUnlimited) {
136
+ throw new RangeError('DAI-style permit can only approve an unlimited allowance; pass allowUnlimited: true or use a normal approve');
137
+ }
138
+ checkAmount(value, MaxUint256, { allowUnlimited: true });
139
+ const message = { holder: owner, spender, nonce: nonce, expiry: BigInt(deadline), allowed: true };
140
+ return { kind: 'dai', chainId, owner, spender, tokens: [token], amounts: [MaxUint256.toString()], deadline, nonces: [String(nonce)], typedData: { domain: support.domain, types: DAI_TYPES, primaryType: 'Permit', message } };
141
+ }
142
+ checkAmount(value, MaxUint256, options, 'value');
143
+ const message = { owner, spender, value, nonce: nonce, deadline: BigInt(deadline) };
144
+ return { kind: 'eip2612', chainId, owner, spender, tokens: [token], amounts: [value.toString()], deadline, nonces: [String(nonce)], typedData: { domain: support.domain, types: PERMIT_TYPES, primaryType: 'Permit', message } };
145
+ }
146
+ /** 代币上的 permit 调用 calldata(任何人都可以提交,不需要是 owner) */
147
+ export function permitCalldata(signed) {
148
+ const { permit, v, r, s } = signed;
149
+ const m = permit.typedData.message;
150
+ if (permit.kind === 'eip2612') {
151
+ return tokenInterface.encodeFunctionData('permit(address,address,uint256,uint256,uint8,bytes32,bytes32)', [m.owner, m.spender, m.value, m.deadline, v, r, s]);
152
+ }
153
+ if (permit.kind === 'dai') {
154
+ return tokenInterface.encodeFunctionData('permit(address,address,uint256,uint256,bool,uint8,bytes32,bytes32)', [m.holder, m.spender, m.nonce, m.expiry, m.allowed, v, r, s]);
155
+ }
156
+ throw new Error(`${permit.kind} is not a token permit; use permit2Calldata / permitTransferFromCalldata`);
157
+ }
158
+ // ---------------------------------------------------------------------------------------------
159
+ // Permit2
160
+ // ---------------------------------------------------------------------------------------------
161
+ const permit2Interface = new Interface([
162
+ 'function allowance(address owner, address token, address spender) view returns (uint160 amount, uint48 expiration, uint48 nonce)',
163
+ 'function permit(address owner, ((address token, uint160 amount, uint48 expiration, uint48 nonce) details, address spender, uint256 sigDeadline) permitSingle, bytes signature)',
164
+ 'function permit(address owner, ((address token, uint160 amount, uint48 expiration, uint48 nonce)[] details, address spender, uint256 sigDeadline) permitBatch, bytes signature)',
165
+ 'function permitTransferFrom(((address token, uint256 amount) permitted, uint256 nonce, uint256 deadline) permit, (address to, uint256 requestedAmount) transferDetails, address owner, bytes signature)',
166
+ ]);
167
+ const PERMIT_DETAILS = [
168
+ { name: 'token', type: 'address' },
169
+ { name: 'amount', type: 'uint160' },
170
+ { name: 'expiration', type: 'uint48' },
171
+ { name: 'nonce', type: 'uint48' },
172
+ ];
173
+ function permit2Domain(chainId) {
174
+ return { name: 'Permit2', chainId, verifyingContract: PERMIT2_ADDRESS };
175
+ }
176
+ /** 读 Permit2 里 owner 对 spender 的当前 nonce */
177
+ async function allowanceNonce(provider, owner, token, spender) {
178
+ const [a] = await provider.all([provider.contract(PERMIT2_ADDRESS, permit2Interface).allowance(owner, token, spender)]);
179
+ return BigInt(a.nonce);
180
+ }
181
+ /** 构建 Permit2 AllowanceTransfer 的 PermitSingle(owner 签名后任何人可调 permit2.permit,之后 spender 可通过 Permit2 转走额度内的代币) */
182
+ export async function buildPermit2Single(provider, params, options = {}) {
183
+ return buildPermit2Batch(provider, { owner: params.owner, spender: params.spender, items: [{ token: params.token, amount: params.amount }], expirationAt: params.expirationAt }, options, true);
184
+ }
185
+ /** 构建 Permit2 的 PermitBatch(多个代币一个签名);items 只有一个且 single 时为 PermitSingle */
186
+ export async function buildPermit2Batch(provider, params, options = {}, single = false) {
187
+ const [owner, spender] = checkParty(params.owner, params.spender);
188
+ if (!params.items.length)
189
+ throw new Error('items must not be empty');
190
+ if (new Set(params.items.map((i) => getAddress(i.token))).size !== params.items.length)
191
+ throw new Error('duplicate tokens in items');
192
+ const chainId = await provider.getChainId();
193
+ const deadline = resolveDeadline(options, 'sigDeadline');
194
+ const expiration = params.expirationAt ?? deadline;
195
+ if (expiration <= now() || expiration > now() + 2 ** 32)
196
+ throw new RangeError('expirationAt is out of range');
197
+ if (expiration > now() + MAX_PERMIT_DEADLINE + 60 && !options.allowLongDeadline) {
198
+ throw new RangeError('expirationAt is more than 24 hours away; pass allowLongDeadline: true if that is intended');
199
+ }
200
+ const tokens = params.items.map((i) => getAddress(i.token));
201
+ const amounts = params.items.map((i, k) => {
202
+ const amount = BigInt(i.amount);
203
+ checkAmount(amount, MAX_UINT160, options, `items[${k}].amount`);
204
+ return amount;
205
+ });
206
+ const nonces = await Promise.all(tokens.map((t) => allowanceNonce(provider, owner, t, spender)));
207
+ const details = tokens.map((token, k) => ({ token, amount: amounts[k], expiration, nonce: nonces[k] }));
208
+ const base = { chainId, owner, spender, tokens, amounts: amounts.map(String), deadline, expiration, nonces: nonces.map(String) };
209
+ if (single) {
210
+ return {
211
+ ...base,
212
+ kind: 'permit2-single',
213
+ typedData: {
214
+ domain: permit2Domain(chainId),
215
+ types: { PermitSingle: [{ name: 'details', type: 'PermitDetails' }, { name: 'spender', type: 'address' }, { name: 'sigDeadline', type: 'uint256' }], PermitDetails: PERMIT_DETAILS },
216
+ primaryType: 'PermitSingle',
217
+ message: { details: details[0], spender, sigDeadline: BigInt(deadline) },
218
+ },
219
+ };
220
+ }
221
+ return {
222
+ ...base,
223
+ kind: 'permit2-batch',
224
+ typedData: {
225
+ domain: permit2Domain(chainId),
226
+ types: { PermitBatch: [{ name: 'details', type: 'PermitDetails[]' }, { name: 'spender', type: 'address' }, { name: 'sigDeadline', type: 'uint256' }], PermitDetails: PERMIT_DETAILS },
227
+ primaryType: 'PermitBatch',
228
+ message: { details, spender, sigDeadline: BigInt(deadline) },
229
+ },
230
+ };
231
+ }
232
+ /** 构建 Permit2 SignatureTransfer 的 PermitTransferFrom:一次性签名,不留下链上额度(spender 合约在同一笔交易里 permitTransferFrom) */
233
+ export async function buildPermit2Transfer(provider, params, options = {}) {
234
+ const [owner, spender] = checkParty(params.owner, params.spender);
235
+ const token = getAddress(params.token);
236
+ const amount = BigInt(params.amount);
237
+ checkAmount(amount, MaxUint256, options);
238
+ const chainId = await provider.getChainId();
239
+ const deadline = resolveDeadline(options);
240
+ const nonce = params.nonce ?? BigInt(hexlify(randomBytes(7)));
241
+ return {
242
+ kind: 'permit2-transfer',
243
+ chainId,
244
+ owner,
245
+ spender,
246
+ tokens: [token],
247
+ amounts: [amount.toString()],
248
+ deadline,
249
+ nonces: [nonce.toString()],
250
+ typedData: {
251
+ domain: permit2Domain(chainId),
252
+ types: {
253
+ PermitTransferFrom: [{ name: 'permitted', type: 'TokenPermissions' }, { name: 'spender', type: 'address' }, { name: 'nonce', type: 'uint256' }, { name: 'deadline', type: 'uint256' }],
254
+ TokenPermissions: [{ name: 'token', type: 'address' }, { name: 'amount', type: 'uint256' }],
255
+ },
256
+ primaryType: 'PermitTransferFrom',
257
+ message: { permitted: { token, amount }, spender, nonce, deadline: BigInt(deadline) },
258
+ },
259
+ };
260
+ }
261
+ /** Permit2.permit(owner, permitSingle | permitBatch, signature) 的 calldata */
262
+ export function permit2Calldata(signed) {
263
+ const { permit, signature } = signed;
264
+ if (permit.kind !== 'permit2-single' && permit.kind !== 'permit2-batch')
265
+ throw new Error(`${permit.kind} is not an AllowanceTransfer permit`);
266
+ const m = permit.typedData.message;
267
+ const fn = permit.kind === 'permit2-single' ? 'permit(address,((address,uint160,uint48,uint48),address,uint256),bytes)' : 'permit(address,((address,uint160,uint48,uint48)[],address,uint256),bytes)';
268
+ return permit2Interface.encodeFunctionData(fn, [permit.owner, [permit.kind === 'permit2-single' ? tupleOf(m.details) : m.details.map(tupleOf), m.spender, m.sigDeadline], signature]);
269
+ }
270
+ const tupleOf = (d) => [d.token, d.amount, d.expiration, d.nonce];
271
+ /** Permit2.permitTransferFrom 的 calldata:把 owner 的代币转给 to(spender 合约调用) */
272
+ export function permitTransferFromCalldata(signed, to, requestedAmount) {
273
+ const { permit, signature } = signed;
274
+ if (permit.kind !== 'permit2-transfer')
275
+ throw new Error(`${permit.kind} is not a SignatureTransfer permit`);
276
+ const m = permit.typedData.message;
277
+ const amount = requestedAmount ?? m.permitted.amount;
278
+ if (amount > m.permitted.amount)
279
+ throw new RangeError('requestedAmount exceeds the permitted amount');
280
+ return permit2Interface.encodeFunctionData('permitTransferFrom', [[[m.permitted.token, m.permitted.amount], m.nonce, m.deadline], [getAddress(to), amount], permit.owner, signature]);
281
+ }
282
+ // ---------------------------------------------------------------------------------------------
283
+ // 签名 / 验证
284
+ // ---------------------------------------------------------------------------------------------
285
+ /** 签名前的核对:typedData 里的内容要和 permit 摘要一致(防止被替换)、链 / 合约地址正确、签名者就是 owner */
286
+ export function assertPermitSafe(permit, signerAddress, chainId) {
287
+ const { typedData: t } = permit;
288
+ const expectedContract = permit.kind === 'eip2612' || permit.kind === 'dai' ? permit.tokens[0] : PERMIT2_ADDRESS;
289
+ if (Number(t.domain.chainId) !== permit.chainId || (chainId !== undefined && chainId !== permit.chainId)) {
290
+ throw new Error(`The permit is for chain ${String(t.domain.chainId)}, expected ${chainId ?? permit.chainId}`);
291
+ }
292
+ if (getAddress(String(t.domain.verifyingContract)) !== getAddress(expectedContract)) {
293
+ throw new Error('The permit verifyingContract does not match the expected contract; refusing to sign');
294
+ }
295
+ if (signerAddress && getAddress(signerAddress) !== getAddress(permit.owner)) {
296
+ throw new Error('The signer is not the owner of the permit');
297
+ }
298
+ const m = t.message;
299
+ const same = (a, b) => String(a).toLowerCase() === String(b).toLowerCase();
300
+ const spender = m.spender;
301
+ if (!same(spender, permit.spender) || getAddress(permit.spender) === ZeroAddress)
302
+ throw new Error('The permit spender is inconsistent or the zero address; refusing to sign');
303
+ const ownerField = m.owner ?? m.holder;
304
+ if (permit.kind !== 'permit2-single' && permit.kind !== 'permit2-batch' && permit.kind !== 'permit2-transfer' && !same(ownerField, permit.owner)) {
305
+ throw new Error('The permit owner is inconsistent; refusing to sign');
306
+ }
307
+ const amounts = permit.kind === 'permit2-single' ? [m.details.amount] : permit.kind === 'permit2-batch' ? m.details.map((d) => d.amount) : permit.kind === 'permit2-transfer' ? [m.permitted.amount] : permit.kind === 'dai' ? [MaxUint256] : [m.value];
308
+ if (amounts.length !== permit.amounts.length || amounts.some((a, i) => !same(a, permit.amounts[i])) || amounts.some((a) => BigInt(a) === 0n)) {
309
+ throw new Error('The permit amounts are inconsistent or blank; refusing to sign');
310
+ }
311
+ // 代币、nonce、额度过期时间、DAI 的 allowed 也要和摘要一致:否则界面上显示的和钱包里实际签的不是同一个授权
312
+ const details = permit.kind === 'permit2-single' ? [m.details] : permit.kind === 'permit2-batch' ? m.details : permit.kind === 'permit2-transfer' ? [{ token: m.permitted.token }] : [];
313
+ if (details.length) {
314
+ if (details.length !== permit.tokens.length || details.some((d, i) => !same(d.token, permit.tokens[i])))
315
+ throw new Error('The permit tokens are inconsistent; refusing to sign');
316
+ if (permit.kind !== 'permit2-transfer' && details.some((d, i) => d.nonce !== undefined && permit.nonces[i] !== undefined && !same(d.nonce, permit.nonces[i])))
317
+ throw new Error('The permit nonce is inconsistent; refusing to sign');
318
+ if (permit.expiration !== undefined && details.some((d) => d.expiration !== undefined && !same(d.expiration, permit.expiration)))
319
+ throw new Error('The permit expiration is inconsistent; refusing to sign');
320
+ }
321
+ else if (permit.kind === 'dai' ? m.allowed !== true : permit.nonces[0] !== undefined && !same(m.nonce, permit.nonces[0])) {
322
+ throw new Error('The permit nonce or allowed flag is inconsistent; refusing to sign');
323
+ }
324
+ if (permit.kind === 'permit2-transfer' && permit.nonces[0] !== undefined && !same(m.nonce, permit.nonces[0]))
325
+ throw new Error('The permit nonce is inconsistent; refusing to sign');
326
+ const deadline = m.deadline ?? m.expiry ?? m.sigDeadline;
327
+ if (!same(deadline, permit.deadline) || permit.deadline <= now())
328
+ throw new Error('The permit deadline is inconsistent or already passed; refusing to sign');
329
+ }
330
+ /**
331
+ * 签名:signer 是 ethers Signer(Wallet、浏览器钱包的 JsonRpcSigner 等,用 signTypedData)或私钥以外的任何有 signTypedData 的对象。
332
+ * 签名前核对(assertPermitSafe),签完本地验证签名确实来自 owner
333
+ */
334
+ export async function signPermit(signer, permit, options = {}) {
335
+ if (typeof signer.signTypedData !== 'function')
336
+ throw new Error('The signer does not support signTypedData');
337
+ assertPermitSafe(permit, await signer.getAddress(), options.chainId);
338
+ const { domain, types, message } = permit.typedData;
339
+ const signature = await signer.signTypedData(domain, types, message);
340
+ if (!verifyPermitSignature(permit, signature)) {
341
+ throw new Error('The wallet returned a signature that does not recover to the permit owner');
342
+ }
343
+ const sig = Signature.from(signature);
344
+ return { permit, signature, v: sig.v, r: sig.r, s: sig.s };
345
+ }
346
+ /** 本地验证签名:恢复出的地址是不是 owner(EOA 签名;合约账户的 ERC-1271 签名无法本地验证,返回 false) */
347
+ export function verifyPermitSignature(permit, signature) {
348
+ try {
349
+ return verifyTypedData(permit.typedData.domain, permit.typedData.types, permit.typedData.message, signature).toLowerCase() === permit.owner.toLowerCase();
350
+ }
351
+ catch {
352
+ return false;
353
+ }
354
+ }
355
+ //# sourceMappingURL=permit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permit.js","sourceRoot":"","sources":["../src/permit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * 资产总值(子路径 `@w3lib/evm-batch-call/price`):已知代币的余额 × 价格,可选加上 LP 仓位的价值
3
+ */
4
+ import { type LpPosition, type LpPositionsOptions } from './lp.js';
5
+ import { type PriceSource } from './price.js';
6
+ import type { Provider } from './provider.js';
7
+ export interface PortfolioOptions {
8
+ /** 要计入的代币(含主币:NATIVE_TOKEN),余额用 multicall 一次读出 */
9
+ tokens: readonly string[];
10
+ /** 价格源,依次使用,默认 [defillamaPrices(), onchainPrices()] */
11
+ sources?: readonly PriceSource[];
12
+ /** 同时计入 LP 仓位(V2 LP 代币、V3 仓位 NFT;参数同 lpPositions,价格源用上面的 sources),默认不计入 */
13
+ lp?: boolean | Omit<LpPositionsOptions, 'prices'>;
14
+ /** 价值低于它的代币不列出(不影响合计);大于 0 时没有价格的代币也不列出(计入 unpriced),默认 0 */
15
+ minUsd?: number;
16
+ /** 某个价格源出错时调用 */
17
+ onPriceError?: (err: unknown) => void;
18
+ fetch?: typeof fetch;
19
+ /** 取消:余额、LP 的节点请求随之中止,查价格的步骤立即以 signal.reason 失败 */
20
+ signal?: AbortSignal;
21
+ }
22
+ export interface PortfolioToken {
23
+ token: string;
24
+ native: boolean;
25
+ symbol: string | null;
26
+ balance: string;
27
+ decimals: number;
28
+ formatted: string;
29
+ price: number | null;
30
+ /** 美元价值;没有价格时为 null */
31
+ value: number | null;
32
+ /** 给出价格的价格源 */
33
+ priceSource: string | null;
34
+ }
35
+ export interface Portfolio {
36
+ /** 合计(代币 + LP;没有价格的不计入) */
37
+ totalUsd: number;
38
+ tokensUsd: number;
39
+ lpUsd: number;
40
+ /** 有余额的代币,按价值从高到低 */
41
+ tokens: PortfolioToken[];
42
+ /** LP 仓位(开启 lp 时) */
43
+ lp: LpPosition[];
44
+ /** 有余额但没有价格的代币数(LP 仓位里缺价格的也算) */
45
+ unpriced: number;
46
+ }
47
+ /**
48
+ * 一个地址的资产总值:代币余额(只看传入的代币,EVM 不能只靠节点列出持仓)× 价格,可选加上 LP 仓位。
49
+ *
50
+ * ```ts
51
+ * const p = await portfolio(provider, user, { tokens: [NATIVE_TOKEN, USDT, USDC], lp: true })
52
+ * p.totalUsd // 1234.5
53
+ * ```
54
+ */
55
+ export declare function portfolio(provider: Provider, owner: string, options: PortfolioOptions): Promise<Portfolio>;
56
+ //# sourceMappingURL=portfolio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portfolio.d.ts","sourceRoot":"","sources":["../src/portfolio.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAe,KAAK,UAAU,EAAE,KAAK,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAC/E,OAAO,EAA8D,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AACzG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAG7C,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IACzB,uDAAuD;IACvD,OAAO,CAAC,EAAE,SAAS,WAAW,EAAE,CAAA;IAChC,2EAA2E;IAC3E,EAAE,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAA;IACjD,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,iBAAiB;IACjB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IACpB,oDAAoD;IACpD,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,uBAAuB;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,eAAe;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,qBAAqB;IACrB,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,qBAAqB;IACrB,EAAE,EAAE,UAAU,EAAE,CAAA;IAChB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC,CAsChH"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * 资产总值(子路径 `@w3lib/evm-batch-call/price`):已知代币的余额 × 价格,可选加上 LP 仓位的价值
3
+ */
4
+ import { lpPositions } from './lp.js';
5
+ import { combinePrices, defillamaPrices, onchainPrices, tokenPrices } from './price.js';
6
+ import { withSignal } from './util.js';
7
+ /**
8
+ * 一个地址的资产总值:代币余额(只看传入的代币,EVM 不能只靠节点列出持仓)× 价格,可选加上 LP 仓位。
9
+ *
10
+ * ```ts
11
+ * const p = await portfolio(provider, user, { tokens: [NATIVE_TOKEN, USDT, USDC], lp: true })
12
+ * p.totalUsd // 1234.5
13
+ * ```
14
+ */
15
+ export async function portfolio(provider, owner, options) {
16
+ const { tokens, sources = [defillamaPrices(), onchainPrices()], lp, minUsd = 0, onPriceError, fetch: fetchFn, signal } = options;
17
+ signal?.throwIfAborted();
18
+ const onError = onPriceError ? (_, err) => onPriceError(err) : undefined;
19
+ const sig = signal ? { signal } : {};
20
+ const [balances, positions] = await Promise.all([
21
+ tokens.length ? provider.balances(owner, tokens, { symbol: true, ...sig }) : Promise.resolve([]),
22
+ lp ? lpPositions(provider, owner, { ...(lp === true ? {} : lp), prices: combinePrices(sources, { onError }), ...(fetchFn ? { fetch: fetchFn } : {}), ...(onPriceError ? { onPriceError } : {}), ...sig }) : Promise.resolve([]),
23
+ ]);
24
+ const held = balances.filter((b) => b.success && BigInt(b.balance) > 0n);
25
+ const prices = held.length
26
+ ? await withSignal(signal, () => tokenPrices(provider, held.map((b) => b.token), { sources, ...(onError ? { onError } : {}), ...(fetchFn ? { fetch: fetchFn } : {}) }))
27
+ : [];
28
+ const list = held.map((b, i) => {
29
+ const p = prices[i];
30
+ const price = p?.price ?? null;
31
+ return {
32
+ token: b.token,
33
+ native: b.native,
34
+ symbol: b.symbol ?? null,
35
+ balance: b.balance,
36
+ decimals: b.decimals,
37
+ formatted: b.formatted,
38
+ price,
39
+ value: price === null ? null : Number(b.formatted) * price,
40
+ priceSource: p?.source ?? null,
41
+ };
42
+ });
43
+ const tokensUsd = list.reduce((sum, t) => sum + (t.value ?? 0), 0);
44
+ const lpUsd = positions.reduce((sum, p) => sum + (p.valueUsd ?? 0), 0);
45
+ return {
46
+ totalUsd: tokensUsd + lpUsd,
47
+ tokensUsd,
48
+ lpUsd,
49
+ tokens: list.filter((t) => (t.value ?? 0) >= minUsd || (minUsd === 0 && t.value === null)).sort((a, b) => (b.value ?? -1) - (a.value ?? -1)),
50
+ lp: positions,
51
+ unpriced: list.filter((t) => t.price === null).length + positions.filter((p) => p.valueUsd === null).length,
52
+ };
53
+ }
54
+ //# sourceMappingURL=portfolio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portfolio.js","sourceRoot":"","sources":["../src/portfolio.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ import { type LpProtocol } from './lp.js';
2
+ import type { Provider } from './provider.js';
3
+ export interface PriceSourceContext {
4
+ chainId: number;
5
+ /** 代币地址(不含主币) */
6
+ tokens: readonly string[];
7
+ /** 主币 symbol(需要主币价格时);不需要时为 null */
8
+ nativeSymbol: string | null;
9
+ fetch: typeof fetch;
10
+ /** 查询用的 Provider(链上价格源 onchainPrices 用它读池子) */
11
+ provider?: Provider;
12
+ }
13
+ export interface PriceSource {
14
+ readonly name: string;
15
+ /** 返回 去重键 → 美元价格:EVM 是小写 0x 地址;Tron 是 T 开头的 base58 地址(区分大小写);主币用键 'native'。没有价格的不返回 */
16
+ prices(ctx: PriceSourceContext): Promise<Map<string, number>>;
17
+ }
18
+ /** DefiLlama 的链标识:chainId → slug(2026-10 实测可用) */
19
+ export declare const DEFILLAMA_CHAINS: Readonly<Record<number, string>>;
20
+ export interface DefillamaPriceOptions {
21
+ /** 置信度下限(0~1),DefiLlama 给出的置信度低于它视为没有价格,默认 0.9 */
22
+ minConfidence?: number;
23
+ /** 历史价格:这个时间点(unix 秒或 Date)附近的价格;不传为当前价格 */
24
+ at?: number | Date;
25
+ }
26
+ /**
27
+ * DefiLlama 价格(免费、不需要 Key)。
28
+ * 注意:流动性很差的代币价格可能虚高,展示总资产时建议配合 minUsd 或自己的价格源。
29
+ *
30
+ * ```ts
31
+ * defillamaPrices() // 当前价格
32
+ * defillamaPrices({ at: new Date('2026-01-01') }) // 历史价格
33
+ * ```
34
+ */
35
+ export declare function defillamaPrices(options?: DefillamaPriceOptions): PriceSource;
36
+ /**
37
+ * 依次使用多个价格源:前面的源没给出价格的代币(和主币)交给下一个源。某个源出错时跳过它(错误交给 onError)。
38
+ *
39
+ * ```ts
40
+ * combinePrices([defillamaPrices(), onchainPrices()])
41
+ * ```
42
+ */
43
+ export declare function combinePrices(sources: readonly PriceSource[], options?: {
44
+ onError?: (source: PriceSource, err: unknown) => void;
45
+ }): PriceSource;
46
+ /** 价格结果里的键:EVM 小写 0x 地址;Tron 是 T 开头的 base58 地址;主币为 'native' */
47
+ export declare function priceKeyOf(chainId: number, token: string): string;
48
+ /** 按 1 美元计的稳定币(链上价格的计价锚点之一;另一个是包装主币) */
49
+ export declare const STABLECOINS: Readonly<Record<number, readonly string[]>>;
50
+ export interface OnchainPriceOptions {
51
+ /** 池子里计价币一侧的价值(美元)下限,低于它的池子不用(防止小池子的价格被操纵),默认 10000 */
52
+ minLiquidityUsd?: number;
53
+ /** 包装主币(计价锚点,主币的价格也按它),默认 LP_QUOTE_TOKENS 里这条链的第一个 */
54
+ wrappedNative?: string;
55
+ /** 按 1 美元计的稳定币,默认 STABLECOINS 里这条链的 */
56
+ stablecoins?: readonly string[];
57
+ /** 用哪些协议的池子,默认 LP_PROTOCOLS 里这条链的 V2 和 V3 */
58
+ protocols?: readonly LpProtocol[];
59
+ /** V3 池子的手续费档位,默认 [100, 500, 2500, 3000, 10000] */
60
+ fees?: readonly number[];
61
+ }
62
+ /**
63
+ * 链上价格:在 V2 / V3 池子里找代币对包装主币、稳定币的池子,用计价币一侧最深的池子的价格。
64
+ * 稳定币按 1 美元;包装主币(和主币)按它对稳定币最深的池子。读取全部用 multicall 合并。
65
+ * 适合 DefiLlama 没有收录的新币;价格是池子当前的价格,可能被单个区块内的交易影响,只用于展示
66
+ */
67
+ export declare function onchainPrices(options?: OnchainPriceOptions): PriceSource;
68
+ export interface TokenPricesOptions {
69
+ /** 价格源,依次使用(前面没有价格的交给后面的),默认 [defillamaPrices(), onchainPrices()] */
70
+ sources?: readonly PriceSource[];
71
+ /** 某个价格源出错时调用(继续用下一个源) */
72
+ onError?: (source: PriceSource, err: unknown) => void;
73
+ /** 自定义 fetch(代理等场景);默认全局 fetch */
74
+ fetch?: typeof fetch;
75
+ }
76
+ export interface TokenPrice {
77
+ /** 传入的代币地址(原样) */
78
+ token: string;
79
+ native: boolean;
80
+ /** 美元价格;所有价格源都没有时为 null */
81
+ price: number | null;
82
+ /** 给出价格的价格源(如 'defillama'、'onchain') */
83
+ source: string | null;
84
+ }
85
+ /**
86
+ * 查代币的美元价格(主币用 NATIVE_TOKEN 或零地址)。默认先查 DefiLlama,没有收录的再从链上池子算。
87
+ *
88
+ * ```ts
89
+ * await tokenPrices(provider, [NATIVE_TOKEN, USDT, newToken])
90
+ * // [{ token: '0xEeee…', native: true, price: 612.3, source: 'defillama' }, …, { token: newToken, price: 0.0012, source: 'onchain' }]
91
+ * await tokenPrices(provider, tokens, { sources: [defillamaPrices({ at: new Date('2026-01-01') })] }) // 历史价格
92
+ * ```
93
+ */
94
+ export declare function tokenPrices(provider: Provider, tokens: readonly string[], options?: TokenPricesOptions): Promise<TokenPrice[]>;
95
+ //# sourceMappingURL=price.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"price.d.ts","sourceRoot":"","sources":["../src/price.ts"],"names":[],"mappings":"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"}