@w3lib/evm-batch-call 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/README.md +103 -12
- package/dist/call.d.ts +8 -2
- package/dist/call.d.ts.map +1 -1
- package/dist/call.js +25 -1
- package/dist/call.js.map +1 -1
- package/dist/chains.d.ts +13 -0
- package/dist/chains.d.ts.map +1 -0
- package/dist/chains.js +35 -0
- package/dist/chains.js.map +1 -0
- package/dist/detect.d.ts +23 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +178 -0
- package/dist/detect.js.map +1 -0
- package/dist/erc20.d.ts +83 -7
- package/dist/erc20.d.ts.map +1 -1
- package/dist/erc20.js +36 -5
- package/dist/erc20.js.map +1 -1
- package/dist/fallback.d.ts +2 -0
- package/dist/fallback.d.ts.map +1 -1
- package/dist/fallback.js +6 -18
- package/dist/fallback.js.map +1 -1
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/nft.d.ts +71 -0
- package/dist/nft.d.ts.map +1 -0
- package/dist/nft.js +194 -0
- package/dist/nft.js.map +1 -0
- package/dist/provider.d.ts +93 -12
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +306 -48
- package/dist/provider.js.map +1 -1
- package/dist/shortcuts.d.ts +95 -0
- package/dist/shortcuts.d.ts.map +1 -0
- package/dist/shortcuts.js +175 -0
- package/dist/shortcuts.js.map +1 -0
- package/dist/source.d.ts +21 -1
- package/dist/source.d.ts.map +1 -1
- package/dist/source.js +96 -3
- package/dist/source.js.map +1 -1
- package/dist/tron.d.ts +6 -0
- package/dist/tron.d.ts.map +1 -1
- package/dist/tron.js +16 -1
- package/dist/tron.js.map +1 -1
- package/dist/util.d.ts +6 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +20 -0
- package/dist/util.js.map +1 -0
- package/package.json +3 -2
- package/src/call.ts +32 -3
- package/src/chains.ts +46 -0
- package/src/detect.ts +193 -0
- package/src/erc20.ts +111 -9
- package/src/fallback.ts +7 -20
- package/src/index.ts +55 -4
- package/src/nft.ts +298 -0
- package/src/provider.ts +416 -54
- package/src/shortcuts.ts +256 -0
- package/src/source.ts +102 -3
- package/src/tron.ts +21 -2
- package/src/util.ts +20 -0
package/dist/tron.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tron.js","sourceRoot":"","sources":["../src/tron.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,SAAS,EACT,MAAM,EACN,OAAO,EACP,YAAY,GAEb,MAAM,QAAQ,CAAA;AAIf,sDAAsD;AACtD,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,UAAU;IAClB,IAAI,EAAE,UAAU;CACR,CAAA;AAEV,MAAM,eAAe,GAAG,6BAA6B,CAAA;AAErD,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AACjE,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,IAAI,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACxC,OAAO,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;QAChC,CAAC;QACD,OAAO,OAAO,CAAA;IAChB,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;IAC1D,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAClC,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC9D,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,KAAK,CAAC,yBAAyB,OAAO,EAAE,CAAC,CAAA;IACrD,CAAC;IACD,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AAClC,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,OAAO,OAAO,CAAA;IAChB,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAA;IAC9E,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAA;IAChD,CAAC;IACD,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,GAAG,EAAE,CAAC,CAAA;IACtC,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC9D,OAAO,YAAY,CAAC,IAAI,UAAU,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;AAChE,CAAC;AAED,SAAS,SAAS,CAAC,OAAe;IAChC,OAAO,KAAK,YAAY,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAA;AAC5D,CAAC;
|
|
1
|
+
{"version":3,"file":"tron.js","sourceRoot":"","sources":["../src/tron.ts"],"names":[],"mappings":"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"}
|
package/dist/util.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,qBAAa,YAAa,SAAQ,KAAK;gBACzB,EAAE,EAAE,MAAM;CAIvB;AAED,yBAAyB;AACzB,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAW1E"}
|
package/dist/util.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export class TimeoutError extends Error {
|
|
2
|
+
constructor(ms) {
|
|
3
|
+
super(`RPC request timed out after ${ms}ms`);
|
|
4
|
+
this.name = 'TimeoutError';
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
/** ms <= 0 或非有限值表示不限制 */
|
|
8
|
+
export function withTimeout(promise, ms) {
|
|
9
|
+
if (!Number.isFinite(ms) || ms <= 0) {
|
|
10
|
+
return promise;
|
|
11
|
+
}
|
|
12
|
+
let timer;
|
|
13
|
+
return Promise.race([
|
|
14
|
+
promise,
|
|
15
|
+
new Promise((_, reject) => {
|
|
16
|
+
timer = setTimeout(() => reject(new TimeoutError(ms)), ms);
|
|
17
|
+
}),
|
|
18
|
+
]).finally(() => clearTimeout(timer));
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=util.js.map
|
package/dist/util.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrC,YAAY,EAAU;QACpB,KAAK,CAAC,+BAA+B,EAAE,IAAI,CAAC,CAAA;QAC5C,IAAI,CAAC,IAAI,GAAG,cAAc,CAAA;IAC5B,CAAC;CACF;AAED,yBAAyB;AACzB,MAAM,UAAU,WAAW,CAAI,OAAmB,EAAE,EAAU;IAC5D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QACpC,OAAO,OAAO,CAAA;IAChB,CAAC;IACD,IAAI,KAAoC,CAAA;IACxC,OAAO,OAAO,CAAC,IAAI,CAAC;QAClB,OAAO;QACP,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;YAC/B,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QAC5D,CAAC,CAAC;KACH,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAA;AACvC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@w3lib/evm-batch-call",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Batched EVM/Tron contract reads via Multicall3 with deployless fallback, native balances, RPC failover, auto-batching and staticCall simulation. ethcall compatible.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ethers",
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"src",
|
|
28
28
|
"contracts",
|
|
29
29
|
"README.md",
|
|
30
|
-
"LICENSE"
|
|
30
|
+
"LICENSE",
|
|
31
|
+
"CHANGELOG.md"
|
|
31
32
|
],
|
|
32
33
|
"sideEffects": false,
|
|
33
34
|
"engines": {
|
package/src/call.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FunctionFragment, Interface, getAddress, toBeHex, zeroPadValue, type JsonFragmentType, type ParamType, type Result } from 'ethers'
|
|
1
|
+
import { FunctionFragment, Interface, Utf8ErrorFuncs, getAddress, toBeHex, toUtf8String, zeroPadValue, type JsonFragmentType, type ParamType, type Result } from 'ethers'
|
|
2
2
|
|
|
3
3
|
import { isTronAddress, toEvmAddress } from './tron.js'
|
|
4
4
|
|
|
@@ -29,8 +29,12 @@ export interface Call<T = any> {
|
|
|
29
29
|
value?: bigint | string | number
|
|
30
30
|
gasLimit?: bigint | string | number
|
|
31
31
|
}
|
|
32
|
-
/**
|
|
33
|
-
|
|
32
|
+
/**
|
|
33
|
+
* 内部标记:
|
|
34
|
+
* - ethBalance:原生币余额查询(见 Provider.getEthBalance)
|
|
35
|
+
* - stringOrBytes32:string 返回值,解码失败时按 bytes32 解析(MKR 等老代币的 symbol / name)
|
|
36
|
+
*/
|
|
37
|
+
kind?: 'ethBalance' | 'stringOrBytes32'
|
|
34
38
|
/** 仅用于类型推断 */
|
|
35
39
|
readonly __result?: T
|
|
36
40
|
}
|
|
@@ -133,12 +137,37 @@ function normalizeValue(type: ParamType, value: unknown): unknown {
|
|
|
133
137
|
|
|
134
138
|
/** 单返回值直接返回该值,多返回值返回 ethers Result(可按下标或名字取) */
|
|
135
139
|
export function decodeCall<T>(call: Call, returnData: string): T {
|
|
140
|
+
if (call.kind === 'stringOrBytes32') {
|
|
141
|
+
return decodeStringOrBytes32(call, returnData) as T
|
|
142
|
+
}
|
|
136
143
|
const iface = getInterface(call)
|
|
137
144
|
const fragment = iface.fragments[0] as FunctionFragment
|
|
138
145
|
const result: Result = iface.decodeFunctionResult(fragment, returnData)
|
|
139
146
|
return (call.outputs.length === 1 ? result[0] : result) as T
|
|
140
147
|
}
|
|
141
148
|
|
|
149
|
+
/** 标记 string 返回值的调用:解码失败时按 bytes32 解析(MKR 等老代币的 symbol / name) */
|
|
150
|
+
export function asStringOrBytes32<T>(call: Call<T>): Call<T> {
|
|
151
|
+
call.kind = 'stringOrBytes32'
|
|
152
|
+
return call
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function decodeStringOrBytes32(call: Call, returnData: string): string {
|
|
156
|
+
try {
|
|
157
|
+
const iface = getInterface(call)
|
|
158
|
+
return iface.decodeFunctionResult(iface.fragments[0] as FunctionFragment, returnData)[0] as string
|
|
159
|
+
} catch (err) {
|
|
160
|
+
// bytes32:恰好 32 字节,按 UTF-8 解析并去掉末尾的 \0
|
|
161
|
+
if (/^0x[0-9a-fA-F]{64}$/.test(returnData)) {
|
|
162
|
+
const text = toUtf8String(returnData, Utf8ErrorFuncs.ignore).replace(/\0+$/, '')
|
|
163
|
+
if (text) {
|
|
164
|
+
return text
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
throw err
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
142
171
|
export function encodeUint256(value: bigint): string {
|
|
143
172
|
return zeroPadValue(toBeHex(value), 32)
|
|
144
173
|
}
|
package/src/chains.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 内置链的主币信息(balances() / tokens() 里主币的 name / symbol / 精度)。
|
|
3
|
+
* 来源:https://chainid.network/chains.json 的 nativeCurrency;999 在该表里与 Wanchain 测试网撞号,
|
|
4
|
+
* 这里按 HyperEVM 手动填写;Tron 手动填写。表里没有的链可通过 nativeSymbol / nativeDecimals 配置。
|
|
5
|
+
*/
|
|
6
|
+
export interface NativeCurrency {
|
|
7
|
+
name: string
|
|
8
|
+
symbol: string
|
|
9
|
+
decimals: number
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const NATIVE_CURRENCIES: Readonly<Record<number, NativeCurrency>> = {
|
|
13
|
+
1: { name: 'Ether', symbol: 'ETH', decimals: 18 }, // Ethereum Mainnet
|
|
14
|
+
10: { name: 'Ether', symbol: 'ETH', decimals: 18 }, // OP Mainnet
|
|
15
|
+
56: { name: 'BNB Chain Native Token', symbol: 'BNB', decimals: 18 }, // BNB Smart Chain Mainnet
|
|
16
|
+
130: { name: 'Ether', symbol: 'ETH', decimals: 18 }, // Unichain
|
|
17
|
+
137: { name: 'POL', symbol: 'POL', decimals: 18 }, // Polygon Mainnet
|
|
18
|
+
143: { name: 'Monad', symbol: 'MON', decimals: 18 }, // Monad
|
|
19
|
+
173: { name: 'EGAS', symbol: 'EGAS', decimals: 18 }, // ENI Mainnet
|
|
20
|
+
196: { name: 'X Layer Global Utility Token', symbol: 'OKB', decimals: 18 }, // X Layer Mainnet
|
|
21
|
+
204: { name: 'BNB Chain Native Token', symbol: 'BNB', decimals: 18 }, // opBNB Mainnet
|
|
22
|
+
324: { name: 'Ether', symbol: 'ETH', decimals: 18 }, // zkSync Mainnet
|
|
23
|
+
988: { name: 'USDT0', symbol: 'USDT0', decimals: 18 }, // Stable Mainnet
|
|
24
|
+
999: { name: 'HYPE', symbol: 'HYPE', decimals: 18 }, // HyperEVM
|
|
25
|
+
1116: { name: 'Core Blockchain Native Token', symbol: 'CORE', decimals: 18 }, // Core Blockchain Mainnet
|
|
26
|
+
2818: { name: 'Ether', symbol: 'ETH', decimals: 18 }, // Morph
|
|
27
|
+
4663: { name: 'Ether', symbol: 'ETH', decimals: 18 }, // Robinhood Chain
|
|
28
|
+
5000: { name: 'Mantle', symbol: 'MNT', decimals: 18 }, // Mantle
|
|
29
|
+
8453: { name: 'Ether', symbol: 'ETH', decimals: 18 }, // Base
|
|
30
|
+
9745: { name: 'Plasma', symbol: 'XPL', decimals: 18 }, // Plasma Mainnet
|
|
31
|
+
34443: { name: 'Ether', symbol: 'ETH', decimals: 18 }, // Mode
|
|
32
|
+
42161: { name: 'Ether', symbol: 'ETH', decimals: 18 }, // Arbitrum One
|
|
33
|
+
43114: { name: 'Avalanche', symbol: 'AVAX', decimals: 18 }, // Avalanche C-Chain
|
|
34
|
+
57073: { name: 'Ether', symbol: 'ETH', decimals: 18 }, // Ink
|
|
35
|
+
59144: { name: 'Linea Ether', symbol: 'ETH', decimals: 18 }, // Linea
|
|
36
|
+
80094: { name: 'BERA Token', symbol: 'BERA', decimals: 18 }, // Berachain
|
|
37
|
+
81457: { name: 'Ether', symbol: 'ETH', decimals: 18 }, // Blast
|
|
38
|
+
534352: { name: 'Ether', symbol: 'ETH', decimals: 18 }, // Scroll
|
|
39
|
+
6666665: { name: 'SAFE(AnWang)', symbol: 'SAFE', decimals: 18 }, // Safe(AnWang) Mainnet
|
|
40
|
+
20260131: { name: 'MetaAssets', symbol: 'MA', decimals: 18 }, // Meta Assets Chain
|
|
41
|
+
728126428: { name: 'TRON', symbol: 'TRX', decimals: 6 }, // Tron
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function getNativeCurrency(chainId: number): NativeCurrency | undefined {
|
|
45
|
+
return NATIVE_CURRENCIES[chainId]
|
|
46
|
+
}
|
package/src/detect.ts
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { BrowserProvider, FetchRequest } from 'ethers'
|
|
2
|
+
|
|
3
|
+
import type { EthersLikeProvider } from './aggregate.js'
|
|
4
|
+
import type { ProviderSource } from './source.js'
|
|
5
|
+
import { TronProvider, type TronWebLike } from './tron.js'
|
|
6
|
+
import { withTimeout } from './util.js'
|
|
7
|
+
|
|
8
|
+
type Eip1193Like = { request: (args: { method: string }) => Promise<unknown>; on?: (event: string, listener: () => void) => unknown }
|
|
9
|
+
|
|
10
|
+
// 识别结果缓存,避免每次都请求。缓存的是 Promise:同时发起的识别共用一个请求;失败(含超时)时删除,下次重试。
|
|
11
|
+
// 只缓存“链不会悄悄变”或“变了能感知到”的来源:
|
|
12
|
+
// - URL:同一个地址的链不会变,按 URL 缓存
|
|
13
|
+
// - tronWeb:TronLink 切网络时换的是 fullNode.host,按 host 缓存
|
|
14
|
+
// - EIP-1193 钱包:有 on() 的监听 chainChanged,切链时清掉;没有 on() 的不缓存(无法感知切链)
|
|
15
|
+
// - ethers BrowserProvider:底下是钱包,可能切链,不缓存(getNetwork 只问本地钱包,开销很小)
|
|
16
|
+
// - 其他 ethers Provider / TronProvider 等对象:按对象缓存
|
|
17
|
+
const keyedCache = new Map<string, Promise<number>>()
|
|
18
|
+
let objectCache = new WeakMap<object, Promise<number>>()
|
|
19
|
+
const watched = new WeakSet<object>()
|
|
20
|
+
|
|
21
|
+
type CacheSlot = { kind: 'key'; key: string } | { kind: 'object'; key: object } | null
|
|
22
|
+
|
|
23
|
+
function cacheSlot(source: ProviderSource): CacheSlot {
|
|
24
|
+
if (typeof source === 'string') {
|
|
25
|
+
return { kind: 'key', key: `url:${source}` }
|
|
26
|
+
}
|
|
27
|
+
const value = source as Partial<EthersLikeProvider & Eip1193Like & TronWebLike> & { fullNode?: { host?: unknown } }
|
|
28
|
+
if (source instanceof BrowserProvider) {
|
|
29
|
+
return null
|
|
30
|
+
}
|
|
31
|
+
if (typeof value.call === 'function') {
|
|
32
|
+
return { kind: 'object', key: source }
|
|
33
|
+
}
|
|
34
|
+
if (value.fullNode && typeof value.fullNode.request === 'function') {
|
|
35
|
+
return typeof value.fullNode.host === 'string' ? { kind: 'key', key: `tronweb:${value.fullNode.host}` } : null
|
|
36
|
+
}
|
|
37
|
+
if (typeof value.request === 'function') {
|
|
38
|
+
return watchChainChanged(source as Eip1193Like) ? { kind: 'object', key: source } : null
|
|
39
|
+
}
|
|
40
|
+
return null
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 按来源缓存地执行一次识别(与 detectChainId 共用缓存)。
|
|
45
|
+
* 链校验用它通过已配置好的节点连接识别(带 apiKey / 限流等),而不是重新创建连接。
|
|
46
|
+
*/
|
|
47
|
+
export function detectChainIdCached(source: ProviderSource, detect: () => Promise<number>, timeout = 10_000): Promise<number> {
|
|
48
|
+
return cached(source, () => withTimeout(detect(), timeout))
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function cached(source: ProviderSource, detect: () => Promise<number>): Promise<number> {
|
|
52
|
+
const slot = cacheSlot(source)
|
|
53
|
+
if (!slot) {
|
|
54
|
+
return detect()
|
|
55
|
+
}
|
|
56
|
+
const hit = slot.kind === 'key' ? keyedCache.get(slot.key) : objectCache.get(slot.key)
|
|
57
|
+
if (hit) {
|
|
58
|
+
return hit
|
|
59
|
+
}
|
|
60
|
+
const promise = detect()
|
|
61
|
+
if (slot.kind === 'key') {
|
|
62
|
+
keyedCache.set(slot.key, promise)
|
|
63
|
+
} else {
|
|
64
|
+
objectCache.set(slot.key, promise)
|
|
65
|
+
}
|
|
66
|
+
promise.catch(() => {
|
|
67
|
+
if (slot.kind === 'key') {
|
|
68
|
+
if (keyedCache.get(slot.key) === promise) keyedCache.delete(slot.key)
|
|
69
|
+
} else if (objectCache.get(slot.key) === promise) {
|
|
70
|
+
objectCache.delete(slot.key)
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
return promise
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** EIP-1193 钱包切链时会触发 chainChanged,清掉该钱包的缓存。返回是否成功监听 */
|
|
77
|
+
function watchChainChanged(wallet: Eip1193Like): boolean {
|
|
78
|
+
if (watched.has(wallet)) {
|
|
79
|
+
return true
|
|
80
|
+
}
|
|
81
|
+
if (typeof wallet.on !== 'function') {
|
|
82
|
+
return false
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
const result = wallet.on('chainChanged', () => objectCache.delete(wallet))
|
|
86
|
+
// 个别实现的 on() 返回 Promise
|
|
87
|
+
;(result as Promise<unknown> | undefined)?.catch?.(() => {})
|
|
88
|
+
watched.add(wallet)
|
|
89
|
+
return true
|
|
90
|
+
} catch {
|
|
91
|
+
return false
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** 清空 chainId 识别缓存 */
|
|
96
|
+
export function clearChainIdCache(): void {
|
|
97
|
+
keyedCache.clear()
|
|
98
|
+
objectCache = new WeakMap()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* 从节点识别 chainId(不传 chainId 时使用),结果会缓存。数组按顺序探测,第一个成功的为准:
|
|
103
|
+
* - RPC URL:先按 EVM 节点发 eth_chainId,失败再按 Tron 全节点读创世区块
|
|
104
|
+
* - 浏览器插件钱包(EIP-1193):eth_chainId;tronWeb:Tron 创世区块
|
|
105
|
+
* - ethers Provider:getNetwork();TronProvider / FallbackRpc:getChainId()
|
|
106
|
+
*
|
|
107
|
+
* @param timeout 单个节点的超时(毫秒);URL 的 EVM / Tron 两次尝试各自计时
|
|
108
|
+
*/
|
|
109
|
+
export async function detectChainId(source: ProviderSource | readonly ProviderSource[], timeout = 10_000): Promise<number> {
|
|
110
|
+
const list: readonly ProviderSource[] = Array.isArray(source) ? source : [source as ProviderSource]
|
|
111
|
+
let lastError: unknown = new Error('Provider list is empty')
|
|
112
|
+
for (const item of list) {
|
|
113
|
+
try {
|
|
114
|
+
// 超时包在缓存里面:挂住的识别超时后会从缓存删除,不会让后续调用一直等
|
|
115
|
+
return await cached(item, () => (typeof item === 'string' ? detectUrl(item, timeout) : withTimeout(detectOne(item), timeout)))
|
|
116
|
+
} catch (err) {
|
|
117
|
+
lastError = err
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
throw lastError
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** 能否从这个来源识别 chainId(不能的来源跳过链校验,见 source.ts) */
|
|
124
|
+
export function canDetectChainId(source: ProviderSource): boolean {
|
|
125
|
+
if (typeof source === 'string') {
|
|
126
|
+
return true
|
|
127
|
+
}
|
|
128
|
+
const value = source as { getChainId?: unknown; getNetwork?: unknown; request?: unknown; call?: unknown; fullNode?: { request?: unknown } }
|
|
129
|
+
if (typeof value.call === 'function') {
|
|
130
|
+
return typeof value.getChainId === 'function' || typeof value.getNetwork === 'function'
|
|
131
|
+
}
|
|
132
|
+
return typeof value.fullNode?.request === 'function' || typeof value.request === 'function'
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** 已创建的连接对象上识别 chainId */
|
|
136
|
+
export async function detectChainIdOf(node: EthersLikeProvider): Promise<number> {
|
|
137
|
+
const value = node as {
|
|
138
|
+
getChainId?: () => Promise<number>
|
|
139
|
+
send?: (method: string, params: unknown[]) => Promise<unknown>
|
|
140
|
+
getNetwork?: () => Promise<{ chainId: bigint }>
|
|
141
|
+
}
|
|
142
|
+
if (typeof value.getChainId === 'function') {
|
|
143
|
+
return Number(await value.getChainId())
|
|
144
|
+
}
|
|
145
|
+
// ethers JsonRpcProvider / BrowserProvider:直接问节点。getNetwork 在 staticNetwork 或 'any' 网络下
|
|
146
|
+
// 返回的是配置 / 首次识别的值,节点(钱包)切链后不会变
|
|
147
|
+
if (typeof value.send === 'function') {
|
|
148
|
+
return Number(await value.send('eth_chainId', []))
|
|
149
|
+
}
|
|
150
|
+
if (typeof value.getNetwork === 'function') {
|
|
151
|
+
return Number((await value.getNetwork()).chainId)
|
|
152
|
+
}
|
|
153
|
+
throw new Error('Unable to detect chainId from this provider, please pass chainId explicitly')
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async function detectOne(source: Exclude<ProviderSource, string>): Promise<number> {
|
|
157
|
+
const value = source as Partial<EthersLikeProvider & Eip1193Like & TronWebLike>
|
|
158
|
+
if (typeof value.call === 'function') {
|
|
159
|
+
return detectChainIdOf(source as EthersLikeProvider)
|
|
160
|
+
}
|
|
161
|
+
if (value.fullNode && typeof value.fullNode.request === 'function') {
|
|
162
|
+
return TronProvider.fromTronWeb(source as TronWebLike).getChainId()
|
|
163
|
+
}
|
|
164
|
+
if (typeof value.request === 'function') {
|
|
165
|
+
return Number(await value.request({ method: 'eth_chainId' }))
|
|
166
|
+
}
|
|
167
|
+
throw new Error('Unsupported provider: expected an RPC URL, an ethers Provider, an EIP-1193 provider or a tronWeb instance')
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async function detectUrl(url: string, timeout: number): Promise<number> {
|
|
171
|
+
try {
|
|
172
|
+
const request = new FetchRequest(url)
|
|
173
|
+
if (timeout > 0 && Number.isFinite(timeout)) {
|
|
174
|
+
request.timeout = timeout
|
|
175
|
+
}
|
|
176
|
+
request.setHeader('content-type', 'application/json')
|
|
177
|
+
request.body = JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'eth_chainId', params: [] })
|
|
178
|
+
const response = await request.send()
|
|
179
|
+
response.assertOk()
|
|
180
|
+
const json = response.bodyJson as { result?: string; error?: { message?: string } }
|
|
181
|
+
if (!json?.result) {
|
|
182
|
+
throw new Error(`eth_chainId failed: ${json?.error?.message ?? 'empty result'}`)
|
|
183
|
+
}
|
|
184
|
+
return Number(json.result)
|
|
185
|
+
} catch (evmError) {
|
|
186
|
+
// 不是 EVM 节点:按 Tron 全节点 HTTP API 再试一次(单独计时)
|
|
187
|
+
try {
|
|
188
|
+
return await new TronProvider({ fullHost: url, retries: 0, timeout }).getChainId()
|
|
189
|
+
} catch {
|
|
190
|
+
throw evmError
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
package/src/erc20.ts
CHANGED
|
@@ -28,16 +28,118 @@ export interface Erc20Contract extends Contract {
|
|
|
28
28
|
transferFrom: Method<[from: string, to: string, amount: bigint | string | number], boolean>
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
/** allowances() / getAllowances() 的单项结果 */
|
|
32
|
+
export interface TokenAllowance {
|
|
33
|
+
token: string
|
|
34
|
+
spender: string
|
|
35
|
+
/** 主币不需要授权,视为无限额度 */
|
|
36
|
+
native: boolean
|
|
37
|
+
/** 授权额度(最小单位的十进制字符串) */
|
|
38
|
+
allowance: string
|
|
39
|
+
decimals: number
|
|
40
|
+
/** 按 decimals 换算后的额度 */
|
|
41
|
+
formatted: string
|
|
42
|
+
/** 额度 ≥ uint96 最大值时为 true(覆盖 MaxUint256,以及 UNI / COMP 等把额度截断为 uint96 的代币) */
|
|
43
|
+
unlimited: boolean
|
|
44
|
+
success: boolean
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** unlimited 的判定阈值:uint96 最大值 */
|
|
48
|
+
export const UNLIMITED_ALLOWANCE_THRESHOLD = 2n ** 96n - 1n
|
|
49
|
+
|
|
50
|
+
const MAX_UINT256 = 2n ** 256n - 1n
|
|
51
|
+
|
|
52
|
+
export { MAX_UINT256 }
|
|
53
|
+
|
|
54
|
+
/** tokens() / getTokens() 可选的字段 */
|
|
55
|
+
export type TokenField = 'name' | 'symbol' | 'decimals' | 'totalSupply'
|
|
56
|
+
|
|
57
|
+
/** 不指定 fields 时返回的字段 */
|
|
58
|
+
export const DEFAULT_TOKEN_FIELDS = ['name', 'symbol', 'decimals'] as const satisfies readonly TokenField[]
|
|
59
|
+
|
|
60
|
+
export type DefaultTokenField = (typeof DEFAULT_TOKEN_FIELDS)[number]
|
|
61
|
+
|
|
62
|
+
interface TokenFieldTypes {
|
|
35
63
|
name: string | null
|
|
64
|
+
symbol: string | null
|
|
65
|
+
decimals: number | null
|
|
66
|
+
/** 最小单位的十进制字符串 */
|
|
67
|
+
totalSupply: string | null
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* tokens() / getTokens() 的单项结果,只包含请求的字段(读取失败的字段为 null)。
|
|
72
|
+
* 请求 totalSupply 时额外带 totalSupplyFormatted(按 decimals 换算)。
|
|
73
|
+
*/
|
|
74
|
+
export type TokenDetails<F extends TokenField = DefaultTokenField> = {
|
|
75
|
+
address: string
|
|
76
|
+
/** 是否是主币占位地址(信息来自内置链信息表 / nativeSymbol 等配置) */
|
|
77
|
+
native: boolean
|
|
78
|
+
/** 请求的字段都读到时为 true(主币没有 totalSupply,不计入) */
|
|
79
|
+
success: boolean
|
|
80
|
+
} & { [K in F]: TokenFieldTypes[K] } & ('totalSupply' extends F ? { totalSupplyFormatted: string | null } : unknown)
|
|
81
|
+
|
|
82
|
+
/** 主币占位地址(多数聚合器、钱包的约定),传给 balances() 时按主币处理 */
|
|
83
|
+
export const NATIVE_TOKEN = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'
|
|
84
|
+
|
|
85
|
+
/** balances() 默认视为主币的地址:0xeeee…eeee 和零地址 */
|
|
86
|
+
export const DEFAULT_NATIVE_TOKENS: readonly string[] = [NATIVE_TOKEN, '0x0000000000000000000000000000000000000000']
|
|
87
|
+
|
|
88
|
+
/** balances() 的代币参数:地址,或带已知 decimals 的对象(跳过 decimals 查询) */
|
|
89
|
+
export type BalanceToken = string | { address: string; decimals?: number }
|
|
90
|
+
|
|
91
|
+
export interface TokenBalance {
|
|
92
|
+
/** 传入的代币地址(原样) */
|
|
93
|
+
token: string
|
|
94
|
+
/** 是否按主币查询 */
|
|
95
|
+
native: boolean
|
|
96
|
+
/** 原始余额(最小单位)的十进制字符串,如 "1234500000";需要计算时用 BigInt(balance) */
|
|
97
|
+
balance: string
|
|
36
98
|
decimals: number
|
|
99
|
+
/** 按 decimals 换算后的十进制字符串,如 "1234.5";整数不带小数点 */
|
|
100
|
+
formatted: string
|
|
101
|
+
/** 仅在 symbol: true 时返回;读取失败或主币 symbol 未知时为 null */
|
|
102
|
+
symbol?: string | null
|
|
103
|
+
/** 余额和 decimals 都查到时为 true;失败时 balance、formatted 都为 "0" */
|
|
104
|
+
success: boolean
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* 按精度格式化:formatAmount(1234500000n, 6) === '1234.5',formatAmount(10n ** 18n, 18) === '1'。
|
|
109
|
+
* 不做四舍五入,保留全部有效小数位。
|
|
110
|
+
*/
|
|
111
|
+
export function formatAmount(value: bigint, decimals: number): string {
|
|
112
|
+
const negative = value < 0n
|
|
113
|
+
const digits = (negative ? -value : value).toString().padStart(decimals + 1, '0')
|
|
114
|
+
const whole = digits.slice(0, digits.length - decimals)
|
|
115
|
+
const fraction = digits.slice(digits.length - decimals).replace(/0+$/, '')
|
|
116
|
+
return `${negative ? '-' : ''}${whole}${fraction ? `.${fraction}` : ''}`
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// decimals / symbol / name 不会变,按 chainId + 地址缓存,轮询余额时只需要查 balanceOf
|
|
120
|
+
interface TokenMeta {
|
|
121
|
+
decimals?: number
|
|
122
|
+
symbol?: string
|
|
123
|
+
name?: string
|
|
124
|
+
/** NFT 集合标准(nftCollections 识别后缓存);null 表示确认不是 ERC721 / ERC1155 */
|
|
125
|
+
standard?: 'ERC721' | 'ERC1155' | null
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const tokenMetaCache = new Map<string, TokenMeta>()
|
|
129
|
+
|
|
130
|
+
export function getCachedTokenMeta(chainId: number, token: string): TokenMeta {
|
|
131
|
+
return tokenMetaCache.get(`${chainId}:${token.toLowerCase()}`) ?? {}
|
|
37
132
|
}
|
|
38
133
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
134
|
+
export function setCachedTokenMeta(chainId: number, token: string, meta: TokenMeta): void {
|
|
135
|
+
if (Object.keys(meta).length === 0) {
|
|
136
|
+
return // 没有新数据(如查询失败)时不写入空条目
|
|
137
|
+
}
|
|
138
|
+
const key = `${chainId}:${token.toLowerCase()}`
|
|
139
|
+
tokenMetaCache.set(key, { ...tokenMetaCache.get(key), ...meta })
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** 测试用:清空 decimals / symbol 缓存 */
|
|
143
|
+
export function resetDecimalsCache(): void {
|
|
144
|
+
tokenMetaCache.clear()
|
|
145
|
+
}
|
package/src/fallback.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { isError, type TransactionRequest } from 'ethers'
|
|
2
2
|
|
|
3
3
|
import type { EthersLikeProvider } from './aggregate.js'
|
|
4
|
+
import { detectChainIdOf } from './detect.js'
|
|
4
5
|
import { isExecutionError } from './errors.js'
|
|
6
|
+
import { withTimeout } from './util.js'
|
|
5
7
|
|
|
6
8
|
export interface FallbackOptions {
|
|
7
9
|
/** 单个节点单次请求超时(毫秒),超时视为该节点故障并换下一个。默认 10000;<= 0 表示不限制 */
|
|
@@ -45,6 +47,11 @@ export class FallbackRpc implements EthersLikeProvider {
|
|
|
45
47
|
return this.#run((node) => node.getBalance(address, blockTag))
|
|
46
48
|
}
|
|
47
49
|
|
|
50
|
+
/** 按节点顺序探测 chainId(节点需实现 getChainId,见 detect.ts) */
|
|
51
|
+
getChainId(): Promise<number> {
|
|
52
|
+
return this.#run((node) => detectChainIdOf(node))
|
|
53
|
+
}
|
|
54
|
+
|
|
48
55
|
async #run<T>(fn: (node: EthersLikeProvider) => Promise<T>): Promise<T> {
|
|
49
56
|
let lastError: unknown
|
|
50
57
|
for (const index of this.#order()) {
|
|
@@ -83,23 +90,3 @@ function isDeterministic(err: unknown): boolean {
|
|
|
83
90
|
isError(err, 'NUMERIC_FAULT')
|
|
84
91
|
)
|
|
85
92
|
}
|
|
86
|
-
|
|
87
|
-
class TimeoutError extends Error {
|
|
88
|
-
constructor(ms: number) {
|
|
89
|
-
super(`RPC request timed out after ${ms}ms`)
|
|
90
|
-
this.name = 'TimeoutError'
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {
|
|
95
|
-
if (!Number.isFinite(ms) || ms <= 0) {
|
|
96
|
-
return promise
|
|
97
|
-
}
|
|
98
|
-
let timer: ReturnType<typeof setTimeout>
|
|
99
|
-
return Promise.race([
|
|
100
|
-
promise,
|
|
101
|
-
new Promise<never>((_, reject) => {
|
|
102
|
-
timer = setTimeout(() => reject(new TimeoutError(ms)), ms)
|
|
103
|
-
}),
|
|
104
|
-
]).finally(() => clearTimeout(timer))
|
|
105
|
-
}
|
package/src/index.ts
CHANGED
|
@@ -1,15 +1,66 @@
|
|
|
1
1
|
export { Contract, bindCall, type BoundMethod, type ContractAbi, type ContractRunner } from './contract.js'
|
|
2
|
-
export {
|
|
2
|
+
export {
|
|
3
|
+
getAllowances,
|
|
4
|
+
getBalances,
|
|
5
|
+
getErc1155Balances,
|
|
6
|
+
getNftBalances,
|
|
7
|
+
getNftCollections,
|
|
8
|
+
getNftOwners,
|
|
9
|
+
getNftTokenUris,
|
|
10
|
+
getTokens,
|
|
11
|
+
type GetBalancesOptions,
|
|
12
|
+
type GetNftCollectionsOptions,
|
|
13
|
+
type GetNftTokenUrisOptions,
|
|
14
|
+
type GetTokensOptions,
|
|
15
|
+
type ShortcutOptions,
|
|
16
|
+
type ShortcutProviderOptions,
|
|
17
|
+
} from './shortcuts.js'
|
|
18
|
+
export {
|
|
19
|
+
DEFAULT_NFT_COLLECTION_FIELDS,
|
|
20
|
+
ERC1155_ABI,
|
|
21
|
+
ERC721_ABI,
|
|
22
|
+
type DefaultNftCollectionField,
|
|
23
|
+
type Erc1155Balance,
|
|
24
|
+
type NftBalance,
|
|
25
|
+
type NftCollection,
|
|
26
|
+
type NftCollectionField,
|
|
27
|
+
type NftCollectionsOptions,
|
|
28
|
+
type NftItem,
|
|
29
|
+
type NftOwner,
|
|
30
|
+
type NftStandard,
|
|
31
|
+
type NftTokenUri,
|
|
32
|
+
type NftTokenUriOptions,
|
|
33
|
+
} from './nft.js'
|
|
34
|
+
export { NATIVE_CURRENCIES, getNativeCurrency, type NativeCurrency } from './chains.js'
|
|
35
|
+
export { clearChainIdCache, detectChainId } from './detect.js'
|
|
36
|
+
export {
|
|
37
|
+
DEFAULT_NATIVE_TOKENS,
|
|
38
|
+
ERC20_ABI,
|
|
39
|
+
NATIVE_TOKEN,
|
|
40
|
+
formatAmount,
|
|
41
|
+
type BalanceToken,
|
|
42
|
+
type Erc20Contract,
|
|
43
|
+
type TokenBalance,
|
|
44
|
+
type TokenAllowance,
|
|
45
|
+
MAX_UINT256,
|
|
46
|
+
UNLIMITED_ALLOWANCE_THRESHOLD,
|
|
47
|
+
DEFAULT_TOKEN_FIELDS,
|
|
48
|
+
type DefaultTokenField,
|
|
49
|
+
type TokenDetails,
|
|
50
|
+
type TokenField,
|
|
51
|
+
} from './erc20.js'
|
|
3
52
|
export {
|
|
4
53
|
Provider,
|
|
5
|
-
type
|
|
54
|
+
type BalancesOptions,
|
|
6
55
|
type CallInput,
|
|
7
56
|
type CallResults,
|
|
57
|
+
type ProviderConfig,
|
|
8
58
|
type ProviderSource,
|
|
9
|
-
type TryCallResults,
|
|
10
59
|
type StaticCallItem,
|
|
11
60
|
type StaticCallOverrides,
|
|
12
61
|
type StaticCallResult,
|
|
62
|
+
type TokensOptions,
|
|
63
|
+
type TryCallResults,
|
|
13
64
|
} from './provider.js'
|
|
14
65
|
export {
|
|
15
66
|
TRON_CHAIN_ID,
|
|
@@ -23,7 +74,7 @@ export {
|
|
|
23
74
|
} from './tron.js'
|
|
24
75
|
export { CallFailedError, decodeRevertReason, isExecutionError } from './errors.js'
|
|
25
76
|
export { FallbackRpc, type FallbackOptions } from './fallback.js'
|
|
26
|
-
export { getDefaultRpcUrls, isTronChain, type SourceOptions } from './source.js'
|
|
77
|
+
export { ChainCheckedProvider, getDefaultRpcUrls, isTronChain, type SourceOptions } from './source.js'
|
|
27
78
|
export { DEFAULT_RPC_URLS, DEFAULT_TRON_HOSTS } from './rpcNodes.js'
|
|
28
79
|
export { MULTICALL3_ADDRESS, getMulticall3, type Multicall } from './multicall.js'
|
|
29
80
|
export type { BlockTag, CallOverrides, EthersLikeProvider } from './aggregate.js'
|