@w3lib/evm-batch-call 0.3.0 → 0.4.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 (103) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +98 -35
  3. package/contracts/DeploylessMulticall3.sol +5 -0
  4. package/dist/aggregate.d.ts +20 -1
  5. package/dist/aggregate.d.ts.map +1 -1
  6. package/dist/aggregate.js +143 -5
  7. package/dist/aggregate.js.map +1 -1
  8. package/dist/batcher.d.ts +6 -1
  9. package/dist/batcher.d.ts.map +1 -1
  10. package/dist/batcher.js +59 -9
  11. package/dist/batcher.js.map +1 -1
  12. package/dist/call.d.ts +27 -2
  13. package/dist/call.d.ts.map +1 -1
  14. package/dist/call.js +22 -0
  15. package/dist/call.js.map +1 -1
  16. package/dist/chains.d.ts +7 -0
  17. package/dist/chains.d.ts.map +1 -1
  18. package/dist/chains.js +11 -0
  19. package/dist/chains.js.map +1 -1
  20. package/dist/deployless.d.ts +1 -1
  21. package/dist/deployless.d.ts.map +1 -1
  22. package/dist/deployless.js +1 -1
  23. package/dist/deployless.js.map +1 -1
  24. package/dist/erc20.d.ts +70 -4
  25. package/dist/erc20.d.ts.map +1 -1
  26. package/dist/erc20.js +121 -5
  27. package/dist/erc20.js.map +1 -1
  28. package/dist/events.d.ts +25 -0
  29. package/dist/events.d.ts.map +1 -0
  30. package/dist/events.js +25 -0
  31. package/dist/events.js.map +1 -0
  32. package/dist/fallback.d.ts +31 -3
  33. package/dist/fallback.d.ts.map +1 -1
  34. package/dist/fallback.js +165 -27
  35. package/dist/fallback.js.map +1 -1
  36. package/dist/index.d.ts +9 -10
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +6 -7
  39. package/dist/index.js.map +1 -1
  40. package/dist/multicall.d.ts.map +1 -1
  41. package/dist/multicall.js +33 -2
  42. package/dist/multicall.js.map +1 -1
  43. package/dist/nft.d.ts +5 -0
  44. package/dist/nft.d.ts.map +1 -1
  45. package/dist/nft.js +5 -0
  46. package/dist/nft.js.map +1 -1
  47. package/dist/owner.d.ts +9 -0
  48. package/dist/owner.d.ts.map +1 -1
  49. package/dist/owner.js +11 -2
  50. package/dist/owner.js.map +1 -1
  51. package/dist/provider.d.ts +55 -29
  52. package/dist/provider.d.ts.map +1 -1
  53. package/dist/provider.js +140 -111
  54. package/dist/provider.js.map +1 -1
  55. package/dist/shortcuts.d.ts +34 -53
  56. package/dist/shortcuts.d.ts.map +1 -1
  57. package/dist/shortcuts.js +41 -91
  58. package/dist/shortcuts.js.map +1 -1
  59. package/dist/source.d.ts +4 -2
  60. package/dist/source.d.ts.map +1 -1
  61. package/dist/source.js +35 -6
  62. package/dist/source.js.map +1 -1
  63. package/dist/subpaths/nft.d.ts +46 -0
  64. package/dist/subpaths/nft.d.ts.map +1 -0
  65. package/dist/subpaths/nft.js +55 -0
  66. package/dist/subpaths/nft.js.map +1 -0
  67. package/dist/subpaths/owner.d.ts +33 -0
  68. package/dist/subpaths/owner.d.ts.map +1 -0
  69. package/dist/subpaths/owner.js +34 -0
  70. package/dist/subpaths/owner.js.map +1 -0
  71. package/dist/tron.d.ts +2 -0
  72. package/dist/tron.d.ts.map +1 -1
  73. package/dist/tron.js +5 -0
  74. package/dist/tron.js.map +1 -1
  75. package/dist/util.d.ts +5 -0
  76. package/dist/util.d.ts.map +1 -1
  77. package/dist/util.js +23 -0
  78. package/dist/util.js.map +1 -1
  79. package/dist/watch.d.ts +25 -0
  80. package/dist/watch.d.ts.map +1 -0
  81. package/dist/watch.js +105 -0
  82. package/dist/watch.js.map +1 -0
  83. package/package.json +19 -10
  84. package/src/aggregate.ts +172 -7
  85. package/src/batcher.ts +69 -9
  86. package/src/call.ts +42 -2
  87. package/src/chains.ts +15 -0
  88. package/src/deployless.ts +1 -1
  89. package/src/erc20.ts +171 -8
  90. package/src/events.ts +42 -0
  91. package/src/fallback.ts +193 -26
  92. package/src/index.ts +19 -61
  93. package/src/multicall.ts +34 -2
  94. package/src/nft.ts +5 -0
  95. package/src/owner.ts +11 -2
  96. package/src/provider.ts +225 -124
  97. package/src/shortcuts.ts +76 -110
  98. package/src/source.ts +35 -8
  99. package/src/subpaths/nft.ts +107 -0
  100. package/src/subpaths/owner.ts +69 -0
  101. package/src/tron.ts +7 -0
  102. package/src/util.ts +27 -0
  103. package/src/watch.ts +149 -0
package/src/index.ts CHANGED
@@ -1,80 +1,33 @@
1
1
  export { Contract, bindCall, type BoundMethod, type ContractAbi, type ContractRunner } from './contract.js'
2
- export {
3
- getTransferScanState,
4
- keyValueScanStorage,
5
- memoryScanStorage,
6
- transferScan,
7
- type TransferScanOptions,
8
- type TransferScanState,
9
- type TransferScanStorage,
10
- } from './scan.js'
11
2
  export { GetLogsError } from './fallback.js'
12
- export {
13
- ALCHEMY_NETWORKS,
14
- COINGECKO_PLATFORMS,
15
- DEFILLAMA_CHAINS,
16
- alchemy,
17
- clearTokenListCache,
18
- coingeckoTokenList,
19
- combine,
20
- defaultTokenSource,
21
- defillamaPrices,
22
- firstAvailable,
23
- metamaskTokenList,
24
- nodereal,
25
- staticTokens,
26
- tokenList,
27
- type DiscoveredToken,
28
- type OwnedToken,
29
- type OwnerTokensOptions,
30
- type PriceSource,
31
- type PriceSourceContext,
32
- type TokenSource,
33
- type TokenSourceContext,
34
- } from './owner.js'
35
3
  export {
36
4
  getAllowances,
37
5
  getBalances,
38
- getErc1155Balances,
39
- getNftBalances,
40
- getNftCollections,
41
- getNftOwners,
42
- getNftTokenUris,
43
- getOwnerTokens,
6
+ getMultiBalances,
44
7
  getTokens,
8
+ type GetAllowancesOptions,
45
9
  type GetBalancesOptions,
46
- type GetNftCollectionsOptions,
47
- type GetNftTokenUrisOptions,
48
- type GetOwnerTokensOptions,
49
10
  type GetTokensOptions,
50
11
  type ShortcutOptions,
51
12
  type ShortcutProviderOptions,
52
13
  } from './shortcuts.js'
53
- export {
54
- DEFAULT_NFT_COLLECTION_FIELDS,
55
- ERC1155_ABI,
56
- ERC721_ABI,
57
- type DefaultNftCollectionField,
58
- type Erc1155Balance,
59
- type NftBalance,
60
- type NftCollection,
61
- type NftCollectionField,
62
- type NftCollectionsOptions,
63
- type NftItem,
64
- type NftOwner,
65
- type NftStandard,
66
- type NftTokenUri,
67
- type NftTokenUriOptions,
68
- } from './nft.js'
69
- export { NATIVE_CURRENCIES, getNativeCurrency, type NativeCurrency } from './chains.js'
14
+ export { NATIVE_BALANCE_MODES, NATIVE_CURRENCIES, getNativeBalanceMode, getNativeCurrency, type NativeCurrency } from './chains.js'
70
15
  export { clearChainIdCache, detectChainId } from './detect.js'
71
16
  export {
72
17
  DEFAULT_NATIVE_TOKENS,
73
18
  ERC20_ABI,
74
19
  NATIVE_TOKEN,
20
+ exportTokenMetaCache,
75
21
  formatAmount,
22
+ formatUnits,
23
+ importTokenMetaCache,
24
+ persistTokenMetaCache,
25
+ type TokenMetaSnapshot,
26
+ type TokenMetaStore,
76
27
  type BalanceToken,
77
28
  type Erc20Contract,
29
+ type RawTokenAllowance,
30
+ type RawTokenBalance,
78
31
  type TokenBalance,
79
32
  type TokenAllowance,
80
33
  MAX_UINT256,
@@ -86,7 +39,10 @@ export {
86
39
  } from './erc20.js'
87
40
  export {
88
41
  Provider,
42
+ type AllowancesOptions,
89
43
  type BalancesOptions,
44
+ type BalancesQuery,
45
+ type BlockOptions,
90
46
  type CallInput,
91
47
  type CallResults,
92
48
  type ProviderConfig,
@@ -108,10 +64,12 @@ export {
108
64
  type TronWebLike,
109
65
  } from './tron.js'
110
66
  export { CallFailedError, decodeRevertReason, isExecutionError } from './errors.js'
111
- export { FallbackRpc, type FallbackOptions } from './fallback.js'
67
+ export { AllNodesFailedError, FallbackRpc, type FallbackNodeInfo, type FallbackOptions } from './fallback.js'
68
+ export { onRequest, type RequestEvent, type RequestListener } from './events.js'
69
+ export { watchBalances, type WatchBalancesOptions } from './watch.js'
112
70
  export { ChainCheckedProvider, getDefaultRpcUrls, isTronChain, type SourceOptions } from './source.js'
113
71
  export { DEFAULT_RPC_URLS, DEFAULT_TRON_HOSTS } from './rpcNodes.js'
114
72
  export { MULTICALL3_ADDRESS, getMulticall3, type Multicall } from './multicall.js'
115
- export type { BlockTag, CallOverrides, EthersLikeProvider } from './aggregate.js'
73
+ export type { BlockTag, CallOverrides, EthersLikeProvider, NativeBalanceMode } from './aggregate.js'
116
74
  export type { BatchOptions } from './batcher.js'
117
- export type { BoundCall, Call, FailableCall, Params, RawResult } from './call.js'
75
+ export type { BoundCall, Call, FailableCall, FailureReason, Params, RawResult, Settled } from './call.js'
package/src/multicall.ts CHANGED
@@ -47,12 +47,44 @@ const MULTICALL3: Record<number, Multicall> = {
47
47
  43114: { address: CANONICAL, block: 11907934 },
48
48
  80001: { address: CANONICAL, block: 25444704 },
49
49
  421611: { address: CANONICAL, block: 10228837 },
50
- 5000: { address: '0xd77b59d4cb13bea71f3cc093e401720867355d6e', block: 18877383 },
50
+ // Mantle:标准地址上的合约字节码与其他链不同,但 aggregate3 / getBlockNumber / getEthBalance 行为一致(2026-10 实测);
51
+ // ethcall 表里的 0xd77b…5d6e 调 aggregate3 会 revert
52
+ 5000: { address: CANONICAL, block: 304717 },
51
53
  1666600000: { address: CANONICAL, block: 24185753 },
52
54
  73927: { address: '0x138A85647768815078DF1dD85C6121e611381A0b', block: 14080843 },
53
55
  // Tron 主网 TEazPvZwDjDtFeJupyo7QunvnrnUjPH8ED(链上合约名 Multicall3,2026-10 实测)
54
56
  728126428: { address: '0x32a4f47a74a6810bd0bf861cabab99656a75de9e', block: 0 },
55
- 81457: { address: '0x23928c6f823e0d78eadc9d2f69ace652ff3cdcb1', block: 368182 },
57
+ // Blast:ethcall 表里的 0x2392…cdcb1 调 aggregate3 会 revert,标准地址可用(2026-10 实测)
58
+ 81457: { address: CANONICAL, block: 88189 },
59
+
60
+ // ---- 2026-10 实测补充:标准地址上 aggregate3 可用、区块号与节点一致 ----
61
+ // 部署区块查到的按实际填写;节点不提供历史状态(或忽略区块参数)查不到的,保守地填核实时的区块:
62
+ // 更早的历史查询走 deployless,最新状态照常用合约
63
+ 25: { address: CANONICAL, block: 98990812 }, // Cronos,部署区块未查到
64
+ 106: { address: CANONICAL, block: 70377223 }, // Velas,部署区块未查到
65
+ 130: { address: CANONICAL, block: 60854543 }, // Unichain,部署区块未查到
66
+ 143: { address: CANONICAL, block: 9248132 }, // Monad
67
+ 204: { address: CANONICAL, block: 193943883 }, // opBNB,部署区块未查到
68
+ 288: { address: CANONICAL, block: 40299030 }, // Boba,部署区块未查到
69
+ 321: { address: CANONICAL, block: 56352410 }, // KCC,部署区块未查到
70
+ 592: { address: CANONICAL, block: 761794 }, // Astar
71
+ 988: { address: CANONICAL, block: 42479473 }, // Stable,部署区块未查到
72
+ 999: { address: CANONICAL, block: 48135400 }, // HyperEVM,部署区块未查到
73
+ 1116: { address: CANONICAL, block: 6988931 }, // Core
74
+ 2818: { address: CANONICAL, block: 3654913 }, // Morph
75
+ 4663: { address: CANONICAL, block: 84683398 }, // Robinhood Chain,部署区块未查到
76
+ 4689: { address: CANONICAL, block: 53225909 }, // IoTeX,部署区块未查到
77
+ 9745: { address: CANONICAL, block: 0 }, // Plasma,创世预置
78
+ 34443: { address: CANONICAL, block: 2465882 }, // Mode
79
+ 57073: { address: CANONICAL, block: 58104502 }, // Ink,部署区块未查到
80
+ 59144: { address: CANONICAL, block: 42 }, // Linea
81
+ 80094: { address: CANONICAL, block: 0 }, // Berachain,创世预置
82
+ 534352: { address: CANONICAL, block: 14 }, // Scroll
83
+ 86233268: { address: CANONICAL, block: 10854614 }, // Winchain,部署区块未查到
84
+ // 以下两条链不支持 deployless(合约创建式 eth_call 返回空 / 格式不对),只能用 Multicall3;
85
+ // 早于部署区块的历史查询会失败
86
+ 42262: { address: CANONICAL, block: 22380155 }, // Oasis Emerald,部署区块未查到
87
+ 1313161554: { address: CANONICAL, block: 62907816 }, // Aurora
56
88
  }
57
89
 
58
90
  export function getMulticall3(chainId: number): Multicall | null {
package/src/nft.ts CHANGED
@@ -118,6 +118,7 @@ function expandUri(uri: string, tokenId: bigint, gateway?: string): string {
118
118
  return expanded
119
119
  }
120
120
 
121
+ /** 批量查 ERC721 持有人(ownerOf),可混合多个集合:`await nftOwners(multi, [{ contract: BAYC, tokenId: 1 }])` */
121
122
  export async function nftOwners(provider: Provider, items: readonly NftItem[], overrides?: CallOverrides): Promise<NftOwner[]> {
122
123
  // Tron 上返回 T 开头的地址,方便与 tronWeb.defaultAddress.base58 等直接比较
123
124
  const tron = isTronChain(await provider.getChainId())
@@ -132,6 +133,7 @@ export async function nftOwners(provider: Provider, items: readonly NftItem[], o
132
133
  })
133
134
  }
134
135
 
136
+ /** 批量查 ERC721 持有数量(balanceOf):`await nftBalances(multi, user, [BAYC, MAYC])` */
135
137
  export async function nftBalances(
136
138
  provider: Provider,
137
139
  owner: string,
@@ -146,6 +148,7 @@ export async function nftBalances(
146
148
  })
147
149
  }
148
150
 
151
+ /** 批量查 ERC1155 余额:`await erc1155Balances(multi, user, [{ contract, tokenId: 1 }])` */
149
152
  export async function erc1155Balances(
150
153
  provider: Provider,
151
154
  owner: string,
@@ -169,6 +172,7 @@ export async function erc1155Balances(
169
172
  })
170
173
  }
171
174
 
175
+ /** 批量查 NFT 元数据地址:兼容 ERC721 tokenURI 与 ERC1155 uri({id} 按规范替换),可转换 ipfs:// */
172
176
  export async function nftTokenUris(provider: Provider, items: readonly NftItem[], options: NftTokenUriOptions = {}): Promise<NftTokenUri[]> {
173
177
  const { ipfsGateway, ...overrides } = options
174
178
  const chainId = await provider.getChainId()
@@ -227,6 +231,7 @@ export async function nftTokenUris(provider: Provider, items: readonly NftItem[]
227
231
  })
228
232
  }
229
233
 
234
+ /** 批量查 NFT 集合信息(标准 / name / symbol / totalSupply),字段可选 */
230
235
  export async function nftCollections<F extends NftCollectionField = DefaultNftCollectionField>(
231
236
  provider: Provider,
232
237
  collections: readonly string[],
package/src/owner.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { CallOverrides } from './aggregate.js'
2
- import { NATIVE_TOKEN, formatAmount, type BalanceToken } from './erc20.js'
2
+ import { NATIVE_TOKEN, formatUnits, type BalanceToken } from './erc20.js'
3
3
  import type { Provider } from './provider.js'
4
4
  import { transferScan, type TransferScanOptions } from './scan.js'
5
5
  import { isTronAddress } from './tron.js'
@@ -555,6 +555,15 @@ export interface OwnedToken {
555
555
  source: string
556
556
  }
557
557
 
558
+ /**
559
+ * 列出持有人拥有的代币(资产列表):从代币来源拿候选代币,再用 multicall 在链上核对余额。
560
+ * 默认来源是公开代币列表,**只能发现列表里的代币**,局限性见 README「资产列表」一节。
561
+ *
562
+ * @deprecated 不推荐使用:EVM 链上无法只靠节点可靠地列出地址持有的全部代币,这个方法只是尽力而为——
563
+ * 默认来源只能发现公开列表里的代币,依赖第三方免费服务(可能限流、改格式或停止服务),要查几千个代币的余额、耗时数秒,
564
+ * 价格也不一定可信;传 `alchemy` / `nodereal` 来源能查全,但同样受第三方服务的额度和可用性约束。
565
+ * 已知要查哪些代币时请用 `getBalances`;需要可靠的完整持仓请直接接入索引服务的接口或自己的索引。局限性详见 README「资产列表」。
566
+ */
558
567
  export async function ownerTokens(provider: Provider, owner: string, options: OwnerTokensOptions = {}): Promise<OwnedToken[]> {
559
568
  const { source: baseSource = defaultTokenSource(), prices, minUsd, includeNative = true, fetch: fetchOption, scanTransfers, ...overrides } = options
560
569
  const source = scanTransfers ? combine(baseSource, transferScan(scanTransfers === true ? {} : scanTransfers)) : baseSource
@@ -606,7 +615,7 @@ export async function ownerTokens(provider: Provider, owner: string, options: Ow
606
615
  return []
607
616
  }
608
617
  const decimals = chain.decimals
609
- const formatted = decimals === balance.decimals ? balance.formatted : formatAmount(BigInt(balance.balance), decimals)
618
+ const formatted = decimals === balance.decimals ? balance.formatted : formatUnits(BigInt(balance.balance), decimals)
610
619
  const price = priceMap.get(addressKey(meta.address))
611
620
  return [
612
621
  {