@w3lib/evm-batch-call 0.1.0 → 0.3.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 (77) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/README.md +194 -12
  3. package/dist/aggregate.d.ts +5 -2
  4. package/dist/aggregate.d.ts.map +1 -1
  5. package/dist/aggregate.js.map +1 -1
  6. package/dist/call.d.ts +8 -2
  7. package/dist/call.d.ts.map +1 -1
  8. package/dist/call.js +25 -1
  9. package/dist/call.js.map +1 -1
  10. package/dist/chains.d.ts +13 -0
  11. package/dist/chains.d.ts.map +1 -0
  12. package/dist/chains.js +35 -0
  13. package/dist/chains.js.map +1 -0
  14. package/dist/detect.d.ts +23 -0
  15. package/dist/detect.d.ts.map +1 -0
  16. package/dist/detect.js +178 -0
  17. package/dist/detect.js.map +1 -0
  18. package/dist/erc20.d.ts +83 -7
  19. package/dist/erc20.d.ts.map +1 -1
  20. package/dist/erc20.js +36 -5
  21. package/dist/erc20.js.map +1 -1
  22. package/dist/fallback.d.ts +25 -0
  23. package/dist/fallback.d.ts.map +1 -1
  24. package/dist/fallback.js +123 -21
  25. package/dist/fallback.js.map +1 -1
  26. package/dist/index.d.ts +10 -3
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +9 -2
  29. package/dist/index.js.map +1 -1
  30. package/dist/nft.d.ts +71 -0
  31. package/dist/nft.d.ts.map +1 -0
  32. package/dist/nft.js +194 -0
  33. package/dist/nft.js.map +1 -0
  34. package/dist/owner.d.ts +136 -0
  35. package/dist/owner.d.ts.map +1 -0
  36. package/dist/owner.js +501 -0
  37. package/dist/owner.js.map +1 -0
  38. package/dist/provider.d.ts +112 -12
  39. package/dist/provider.d.ts.map +1 -1
  40. package/dist/provider.js +343 -48
  41. package/dist/provider.js.map +1 -1
  42. package/dist/scan.d.ts +59 -0
  43. package/dist/scan.d.ts.map +1 -0
  44. package/dist/scan.js +245 -0
  45. package/dist/scan.js.map +1 -0
  46. package/dist/shortcuts.d.ts +113 -0
  47. package/dist/shortcuts.d.ts.map +1 -0
  48. package/dist/shortcuts.js +193 -0
  49. package/dist/shortcuts.js.map +1 -0
  50. package/dist/source.d.ts +23 -1
  51. package/dist/source.d.ts.map +1 -1
  52. package/dist/source.js +110 -3
  53. package/dist/source.js.map +1 -1
  54. package/dist/tron.d.ts +6 -0
  55. package/dist/tron.d.ts.map +1 -1
  56. package/dist/tron.js +16 -1
  57. package/dist/tron.js.map +1 -1
  58. package/dist/util.d.ts +6 -0
  59. package/dist/util.d.ts.map +1 -0
  60. package/dist/util.js +20 -0
  61. package/dist/util.js.map +1 -0
  62. package/package.json +3 -2
  63. package/src/aggregate.ts +5 -2
  64. package/src/call.ts +32 -3
  65. package/src/chains.ts +46 -0
  66. package/src/detect.ts +193 -0
  67. package/src/erc20.ts +111 -9
  68. package/src/fallback.ts +127 -23
  69. package/src/index.ts +90 -4
  70. package/src/nft.ts +298 -0
  71. package/src/owner.ts +651 -0
  72. package/src/provider.ts +458 -54
  73. package/src/scan.ts +293 -0
  74. package/src/shortcuts.ts +278 -0
  75. package/src/source.ts +118 -3
  76. package/src/tron.ts +21 -2
  77. package/src/util.ts +20 -0
package/dist/source.js CHANGED
@@ -1,4 +1,5 @@
1
- import { BrowserProvider, FetchRequest, JsonRpcProvider } from 'ethers';
1
+ import { BrowserProvider, FetchRequest, JsonRpcProvider, makeError } from 'ethers';
2
+ import { canDetectChainId, detectChainId, detectChainIdCached } from './detect.js';
2
3
  import { FallbackRpc } from './fallback.js';
3
4
  import { DEFAULT_RPC_URLS, DEFAULT_TRON_HOSTS } from './rpcNodes.js';
4
5
  import { TRON_CHAIN_ID, TronProvider } from './tron.js';
@@ -22,9 +23,109 @@ export function resolveSource(chainId, source, options = {}) {
22
23
  }
23
24
  // 多节点时 Tron 节点不在单节点内重试 429,直接切到下一个节点
24
25
  const multiple = list.length > 1;
25
- const nodes = list.map((item) => toEthersLike(chainId, item, options, multiple));
26
+ const timeout = options.fallback?.timeout ?? 10_000;
27
+ const nodes = list.map((item) => {
28
+ const node = toEthersLike(chainId, item, options, multiple);
29
+ // 内置公共节点本来就是按 chainId 选出来的,不需要再校验
30
+ return source === undefined ? node : withChainCheck(chainId, item, node, timeout);
31
+ });
26
32
  return multiple ? new FallbackRpc(nodes, options.fallback) : nodes[0];
27
33
  }
34
+ /** 识别失败后多久内不再重试识别(期间请求照常发出,不做校验) */
35
+ const CHECK_RETRY_INTERVAL = 60_000;
36
+ /**
37
+ * 校验节点所在的链与 Provider 的 chainId 一致,避免把另一条链的数据当成这条链的返回:
38
+ * 比如 [钱包, 公共节点] 自动识别出钱包的链后,公共节点其实在另一条链上;或者配错了节点 URL。
39
+ *
40
+ * - 不一致时抛 NETWORK_ERROR(多节点时 FallbackRpc 会换下一个节点)
41
+ * - 通过已配置好的节点连接识别(带 Tron apiKey / 限流等),结果按来源缓存,每个节点只多一次请求
42
+ * - 识别与实际请求并行发出,不增加延迟;不一致时丢弃请求结果
43
+ * - 识别本身失败时不拦截(交给实际请求去报错),并在一段时间内不再重试,避免每次请求都多一次识别
44
+ */
45
+ export class ChainCheckedProvider {
46
+ inner;
47
+ chainId;
48
+ source;
49
+ timeout;
50
+ #checkFailedAt = 0;
51
+ constructor(inner, chainId, source, timeout) {
52
+ this.inner = inner;
53
+ this.chainId = chainId;
54
+ this.source = source;
55
+ this.timeout = timeout;
56
+ }
57
+ async #check() {
58
+ if (this.#checkFailedAt && Date.now() - this.#checkFailedAt < CHECK_RETRY_INTERVAL) {
59
+ return;
60
+ }
61
+ let actual;
62
+ try {
63
+ actual = await detectChainIdCached(this.source, () => detectViaNode(this.inner, this.source), this.timeout);
64
+ }
65
+ catch {
66
+ this.#checkFailedAt = Date.now();
67
+ return;
68
+ }
69
+ this.#checkFailedAt = 0;
70
+ if (actual !== this.chainId) {
71
+ throw makeError(`chainId mismatch: expected ${this.chainId}, but the node is on ${actual}`, 'NETWORK_ERROR', {
72
+ event: 'chainIdMismatch',
73
+ });
74
+ }
75
+ }
76
+ async #run(request) {
77
+ const [checked, result] = await Promise.allSettled([this.#check(), request()]);
78
+ if (checked.status === 'rejected') {
79
+ throw checked.reason;
80
+ }
81
+ if (result.status === 'rejected') {
82
+ throw result.reason;
83
+ }
84
+ return result.value;
85
+ }
86
+ call(tx) {
87
+ return this.#run(() => this.inner.call(tx));
88
+ }
89
+ getBalance(...args) {
90
+ return this.#run(() => this.inner.getBalance(...args));
91
+ }
92
+ getBlockNumber() {
93
+ const inner = this.inner;
94
+ if (!inner.getBlockNumber) {
95
+ return Promise.reject(new Error('getBlockNumber is not supported by this node'));
96
+ }
97
+ return this.#run(() => inner.getBlockNumber());
98
+ }
99
+ getLogs(filter) {
100
+ const inner = this.inner;
101
+ if (!inner.getLogs) {
102
+ return Promise.reject(new Error('getLogs is not supported by this node'));
103
+ }
104
+ return this.#run(() => inner.getLogs(filter));
105
+ }
106
+ async getChainId() {
107
+ return this.chainId;
108
+ }
109
+ }
110
+ /** 通过已创建的节点连接识别它实际所在的链 */
111
+ function detectViaNode(node, source) {
112
+ if (node instanceof TronProvider) {
113
+ return node.getChainId();
114
+ }
115
+ // JsonRpcProvider(staticNetwork)/ BrowserProvider('any' 网络)的 getNetwork 不反映节点实际的链,直接问节点
116
+ if (node instanceof JsonRpcProvider) {
117
+ return node.send('eth_chainId', []).then(Number);
118
+ }
119
+ return detectChainId(source, Number.POSITIVE_INFINITY);
120
+ }
121
+ function withChainCheck(chainId, source, node, timeout) {
122
+ if (!Number.isFinite(chainId) || !canDetectChainId(source) || pinnedWallets.has(node)) {
123
+ return node;
124
+ }
125
+ return new ChainCheckedProvider(node, chainId, source, timeout);
126
+ }
127
+ /** 由 EIP-1193 钱包创建、已固定在 chainId 上的 BrowserProvider(每次请求 ethers 都会校验链),不需要再包一层 */
128
+ const pinnedWallets = new WeakSet();
28
129
  function toEthersLike(chainId, source, options, multiple) {
29
130
  if (typeof source === 'string') {
30
131
  if (isTronChain(chainId)) {
@@ -49,7 +150,13 @@ function toEthersLike(chainId, source, options, multiple) {
49
150
  return TronProvider.fromTronWeb(source, options.tron);
50
151
  }
51
152
  if (typeof value.request === 'function') {
52
- return new BrowserProvider(source);
153
+ // 传入 chainId:钱包当前所在的链与之不符时请求报 NETWORK_ERROR(network changed),
154
+ // 而不是静默返回另一条链的数据;在多节点列表里会据此自动切到下一个节点
155
+ const wallet = new BrowserProvider(source, Number.isFinite(chainId) ? chainId : undefined);
156
+ if (Number.isFinite(chainId)) {
157
+ pinnedWallets.add(wallet);
158
+ }
159
+ return wallet;
53
160
  }
54
161
  throw new Error('Unsupported provider: expected an RPC URL, an ethers Provider, an EIP-1193 provider or a tronWeb instance');
55
162
  }
@@ -1 +1 @@
1
- {"version":3,"file":"source.js","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"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"}
package/dist/tron.d.ts CHANGED
@@ -13,8 +13,10 @@ export declare function toEvmAddress(address: string): string;
13
13
  export declare function toTronAddress(address: string): string;
14
14
  /** 只用到 tronWeb 的这几个字段,兼容 tronweb v5/v6 及钱包注入的实例 */
15
15
  export interface TronWebLike {
16
+ /** host 是当前连接的全节点地址,TronLink 切换网络时会变,用于区分 chainId 缓存 */
16
17
  fullNode: {
17
18
  request: (url: string, payload: Record<string, unknown>, method: string) => Promise<any>;
19
+ host?: string;
18
20
  };
19
21
  defaultAddress?: {
20
22
  base58?: string | false;
@@ -38,6 +40,8 @@ export interface TronProviderOptions {
38
40
  minInterval?: number;
39
41
  /** 遇到 HTTP 429 时的重试次数(指数退避,从 1s 开始)。默认 3 */
40
42
  retries?: number;
43
+ /** 单次 HTTP 请求超时(毫秒,仅对内置 fetch 生效,自定义 request 自行处理)。默认 10000;<= 0 不限制 */
44
+ timeout?: number;
41
45
  /** 不传 from 时使用的调用者地址;传函数则每次调用时取值(钱包切换账号后自动跟随) */
42
46
  defaultFrom?: string | (() => string | null | undefined);
43
47
  }
@@ -57,6 +61,8 @@ export declare class TronProvider implements EthersLikeProvider {
57
61
  */
58
62
  static fromTronWeb(tronWeb: TronWebLike, options?: Omit<TronProviderOptions, 'request' | 'fullHost'>): TronProvider;
59
63
  call(tx: TransactionRequest): Promise<string>;
64
+ /** chainId = 创世区块哈希的最后 4 字节(与 TronGrid /jsonrpc 的 eth_chainId 一致,主网 728126428) */
65
+ getChainId(): Promise<number>;
60
66
  getBalance(address: unknown, blockTag?: unknown): Promise<bigint>;
61
67
  }
62
68
  //# sourceMappingURL=tron.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tron.d.ts","sourceRoot":"","sources":["../src/tron.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,kBAAkB,EACxB,MAAM,QAAQ,CAAA;AAEf,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAExD,sDAAsD;AACtD,eAAO,MAAM,aAAa;;;;CAIhB,CAAA;AAIV,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAErD;AAED,+DAA+D;AAC/D,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAcpD;AAED,8CAA8C;AAC9C,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAWrD;AAMD,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE;QAAE,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;KAAE,CAAA;IACtG,cAAc,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;KAAE,CAAA;CAC7C;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;AAEvF,MAAM,WAAW,mBAAmB;IAClC,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;CACzD;AAcD;;;;;;GAMG;AACH,qBAAa,YAAa,YAAW,kBAAkB;;gBAUzC,OAAO,GAAE,mBAAwB;IAuB7C;;;OAGG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,GAAE,IAAI,CAAC,mBAAmB,EAAE,SAAS,GAAG,UAAU,CAAM,GAAG,YAAY;IAQjH,IAAI,CAAC,EAAE,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC;IAiD7C,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;CAmDxE"}
1
+ {"version":3,"file":"tron.d.ts","sourceRoot":"","sources":["../src/tron.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,kBAAkB,EACxB,MAAM,QAAQ,CAAA;AAEf,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAExD,sDAAsD;AACtD,eAAO,MAAM,aAAa;;;;CAIhB,CAAA;AAIV,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAErD;AAED,+DAA+D;AAC/D,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAcpD;AAED,8CAA8C;AAC9C,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAWrD;AAMD,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,wDAAwD;IACxD,QAAQ,EAAE;QAAE,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACrH,cAAc,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;KAAE,CAAA;CAC7C;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;AAEvF,MAAM,WAAW,mBAAmB;IAClC,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;CACzD;AAcD;;;;;;GAMG;AACH,qBAAa,YAAa,YAAW,kBAAkB;;gBAUzC,OAAO,GAAE,mBAAwB;IA6B7C;;;OAGG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,GAAE,IAAI,CAAC,mBAAmB,EAAE,SAAS,GAAG,UAAU,CAAM,GAAG,YAAY;IAQjH,IAAI,CAAC,EAAE,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC;IAiDnD,kFAAkF;IAC5E,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAS7B,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;CAmDxE"}
package/dist/tron.js CHANGED
@@ -80,8 +80,14 @@ export class TronProvider {
80
80
  if (options.apiKey) {
81
81
  headers['TRON-PRO-API-KEY'] = options.apiKey;
82
82
  }
83
+ const timeout = options.timeout ?? 10_000;
83
84
  this.#request = async (path, body) => {
84
- const res = await fetch(`${host}/${path}`, { method: 'POST', headers, body: JSON.stringify(body) });
85
+ const res = await fetch(`${host}/${path}`, {
86
+ method: 'POST',
87
+ headers,
88
+ body: JSON.stringify(body),
89
+ signal: timeout > 0 && Number.isFinite(timeout) ? AbortSignal.timeout(timeout) : undefined,
90
+ });
85
91
  if (!res.ok) {
86
92
  throw new HttpError(`Tron request ${path} failed: HTTP ${res.status}`, res.status);
87
93
  }
@@ -145,6 +151,15 @@ export class TronProvider {
145
151
  }
146
152
  return output;
147
153
  }
154
+ /** chainId = 创世区块哈希的最后 4 字节(与 TronGrid /jsonrpc 的 eth_chainId 一致,主网 728126428) */
155
+ async getChainId() {
156
+ const res = await this.#limit(() => this.#request('wallet/getblockbynum', { num: 0 }));
157
+ const blockId = String(res?.blockID ?? '');
158
+ if (!/^[0-9a-f]{64}$/i.test(blockId)) {
159
+ throw new Error('Unable to detect Tron chainId: unexpected genesis block response');
160
+ }
161
+ return Number.parseInt(blockId.slice(-8), 16);
162
+ }
148
163
  async getBalance(address, blockTag) {
149
164
  assertLatest(blockTag);
150
165
  const res = await this.#limit(() => this.#request('wallet/getaccount', { address: toTronHex(String(address)) }));
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;AA+BD,MAAM,SAAU,SAAQ,KAAK;IAGhB;IAFX,YACE,OAAe,EACN,MAAc;QAEvB,KAAK,CAAC,OAAO,CAAC,CAAA;QAFL,WAAM,GAAN,MAAM,CAAQ;IAGzB,CAAC;CACF;AAED,+CAA+C;AAC/C,MAAM,UAAU,GAAG,4CAA4C,CAAA;AAE/D;;;;;;GAMG;AACH,MAAM,OAAO,YAAY;IACd,QAAQ,CAAa;IACrB,YAAY,CAAQ;IACpB,YAAY,CAAQ;IACpB,QAAQ,CAAQ;IAChB,YAAY,CAAoC;IACzD,OAAO,GAAG,CAAC,CAAA;IACX,UAAU,GAAG,CAAC,CAAA;IACL,QAAQ,GAAsB,EAAE,CAAA;IAEzC,YAAY,UAA+B,EAAE;QAC3C,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC,CAAA;QACzD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC,CAAA;QACzD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC,CAAA;QACjD,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,WAAW,CAAA;QACvC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAA;QACjC,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,yBAAyB,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;YAChF,MAAM,OAAO,GAA2B,EAAE,cAAc,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAA;YAClG,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnB,OAAO,CAAC,kBAAkB,CAAC,GAAG,OAAO,CAAC,MAAM,CAAA;YAC9C,CAAC;YACD,IAAI,CAAC,QAAQ,GAAG,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;gBACnC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;gBACnG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;oBACZ,MAAM,IAAI,SAAS,CAAC,gBAAgB,IAAI,iBAAiB,GAAG,CAAC,MAAM,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;gBACpF,CAAC;gBACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAA;YACnB,CAAC,CAAA;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,WAAW,CAAC,OAAoB,EAAE,UAA6D,EAAE;QACtG,OAAO,IAAI,YAAY,CAAC;YACtB,GAAG,OAAO;YACV,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,MAAM,IAAI,SAAS,CAAC;YACvF,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC;SACtE,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAsB;QAC/B,YAAY,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAA;QACzB,MAAM,IAAI,GAA4B;YACpC,aAAa,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,EAAE;YAC5E,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;SACjD,CAAA;QACD,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;YACV,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QAClD,CAAC;QACD,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;YACb,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;QAC5C,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,gCAAgC,EAAE,IAAI,CAAC,CAAC,CAAA;QAC1F,MAAM,MAAM,GAAG,GAAG,EAAE,MAAM,IAAI,EAAE,CAAA;QAChC,MAAM,OAAO,GAAG,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAEvF,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAChB,2DAA2D;YAC3D,IAAI,MAAM,CAAC,IAAI,KAAK,yBAAyB,IAAI,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5E,OAAO,IAAI,CAAA;YACb,CAAC;YACD,+CAA+C;YAC/C,kFAAkF;YAClF,MAAM,SAAS,CAAC,qBAAqB,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,gBAAgB,EAAE;gBACnG,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,IAAI;gBACV,MAAM,EAAE,OAAO,IAAI,IAAI;gBACvB,WAAW,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE;gBAC7H,UAAU,EAAE,IAAI;gBAChB,MAAM,EAAE,IAAI;gBACZ,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,EAAE,EAAE;aAC9E,CAAC,CAAA;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,KAAK,GAAG,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAA;QACrD,IAAI,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,QAAQ,EAAE,CAAC;YACjD,MAAM,SAAS,CAAC,OAAO,IAAI,oBAAoB,EAAE,gBAAgB,EAAE;gBACjE,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,MAAM;gBACZ,MAAM,EAAE,IAAI;gBACZ,WAAW,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE;gBAC7H,UAAU,EAAE,IAAI;gBAChB,MAAM,EAAE,IAAI;aACb,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAAgB,EAAE,QAAkB;QACnD,YAAY,CAAC,QAAQ,CAAC,CAAA;QACtB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,mBAAmB,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QAChH,OAAO,MAAM,CAAC,GAAG,EAAE,OAAO,IAAI,CAAC,CAAC,CAAA;IAClC,CAAC;IAED,eAAe;QACb,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,YAAY,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAA;QAC9F,OAAO,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAA;IAC5C,CAAC;IAED,KAAK,CAAC,MAAM,CAAI,IAAsB;QACpC,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtC,+CAA+C;YAC/C,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;QACnE,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,EAAE,CAAA;QAChB,CAAC;QACD,IAAI,CAAC;YACH,KAAK,IAAI,OAAO,GAAG,CAAC,GAAI,OAAO,EAAE,EAAE,CAAC;gBAClC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAA;gBACtB,IAAI,CAAC;oBACH,OAAO,MAAM,IAAI,EAAE,CAAA;gBACrB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,IAAI,OAAO,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;wBACpD,MAAM,GAAG,CAAA;oBACX,CAAC;oBACD,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,OAAO,CAAC,CAAA;gBAClC,CAAC;YACH,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAA;YAClC,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,EAAE,CAAA;YACR,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,OAAO,EAAE,CAAA;YAChB,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,SAAS;QACb,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,OAAM;QACR,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,CAAA;QAC5C,IAAI,CAAC,UAAU,GAAG,KAAK,GAAG,IAAI,CAAC,YAAY,CAAA;QAC3C,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;YAChB,MAAM,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,CAAA;QAC1B,CAAC;IACH,CAAC;CACF;AAED,SAAS,YAAY,CAAC,QAAiB;IACrC,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnG,OAAM;IACR,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,wCAAwC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;AAC7E,CAAC;AAED,SAAS,aAAa,CAAC,GAAY;IACjC,yDAAyD;IACzD,MAAM,CAAC,GAAG,GAAiE,CAAA;IAC3E,OAAO,CAAC,EAAE,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,GAAG,CAAA;AACzD,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;AAC1D,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,KAAK,GAAG,EAAE,CAAC,CAAA;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,CAAA;IACZ,CAAC;AACH,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,6 @@
1
+ export declare class TimeoutError extends Error {
2
+ constructor(ms: number);
3
+ }
4
+ /** ms <= 0 或非有限值表示不限制 */
5
+ export declare function withTimeout<T>(promise: Promise<T>, ms: number): Promise<T>;
6
+ //# sourceMappingURL=util.d.ts.map
@@ -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
@@ -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.1.0",
3
+ "version": "0.3.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/aggregate.ts CHANGED
@@ -5,8 +5,11 @@ import { DEPLOYLESS_MULTICALL3_BYTECODE } from './deployless.js'
5
5
  import { isExecutionError } from './errors.js'
6
6
  import { MULTICALL3_ADDRESS, type Multicall } from './multicall.js'
7
7
 
8
- /** 只用到 ethers Provider 的这两个方法,JsonRpcProvider / BrowserProvider 都满足 */
9
- export type EthersLikeProvider = Pick<EthersProvider, 'call' | 'getBalance'>
8
+ /**
9
+ * 只用到 ethers Provider 的这几个方法:必需 call / getBalance;getLogs / getBlockNumber 可选(只有增量扫描 Transfer 事件时用到)。
10
+ * ethers 的 JsonRpcProvider / BrowserProvider 都满足
11
+ */
12
+ export type EthersLikeProvider = Pick<EthersProvider, 'call' | 'getBalance'> & Partial<Pick<EthersProvider, 'getLogs' | 'getBlockNumber'>>
10
13
 
11
14
  export type BlockTag = number | bigint | string
12
15
 
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
- /** 内部标记:原生币余额查询(见 Provider.getEthBalance) */
33
- kind?: 'ethBalance'
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
+ }