web3-tools-mcp 1.0.1 → 1.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.
Files changed (93) hide show
  1. package/README.md +46 -230
  2. package/dist/package.json +63 -0
  3. package/dist/src/client.d.ts +1653 -0
  4. package/dist/src/client.d.ts.map +1 -0
  5. package/dist/src/client.js +142 -0
  6. package/dist/src/client.js.map +1 -0
  7. package/dist/src/index.d.ts +3 -0
  8. package/dist/src/index.d.ts.map +1 -0
  9. package/dist/src/index.js +88 -0
  10. package/dist/src/index.js.map +1 -0
  11. package/dist/src/tools/advanced.d.ts +75 -0
  12. package/dist/src/tools/advanced.d.ts.map +1 -0
  13. package/dist/src/tools/advanced.js +234 -0
  14. package/dist/src/tools/advanced.js.map +1 -0
  15. package/dist/src/tools/balance.d.ts +55 -0
  16. package/dist/src/tools/balance.d.ts.map +1 -0
  17. package/dist/src/tools/balance.js +146 -0
  18. package/dist/src/tools/balance.js.map +1 -0
  19. package/dist/src/tools/contract-info.d.ts +79 -0
  20. package/dist/src/tools/contract-info.d.ts.map +1 -0
  21. package/dist/src/tools/contract-info.js +450 -0
  22. package/dist/src/tools/contract-info.js.map +1 -0
  23. package/dist/src/tools/contract.d.ts +79 -0
  24. package/dist/src/tools/contract.d.ts.map +1 -0
  25. package/dist/src/tools/contract.js +140 -0
  26. package/dist/src/tools/contract.js.map +1 -0
  27. package/dist/src/tools/ens.d.ts +119 -0
  28. package/dist/src/tools/ens.d.ts.map +1 -0
  29. package/dist/src/tools/ens.js +425 -0
  30. package/dist/src/tools/ens.js.map +1 -0
  31. package/dist/src/tools/index.d.ts +3 -0
  32. package/dist/src/tools/index.d.ts.map +1 -0
  33. package/dist/src/tools/index.js +29 -0
  34. package/dist/src/tools/index.js.map +1 -0
  35. package/dist/src/tools/logs.d.ts +39 -0
  36. package/dist/src/tools/logs.d.ts.map +1 -0
  37. package/dist/src/tools/logs.js +231 -0
  38. package/dist/src/tools/logs.js.map +1 -0
  39. package/dist/src/tools/signatures.d.ts +83 -0
  40. package/dist/src/tools/signatures.d.ts.map +1 -0
  41. package/dist/src/tools/signatures.js +93 -0
  42. package/dist/src/tools/signatures.js.map +1 -0
  43. package/dist/src/types.d.ts +22 -0
  44. package/dist/src/types.d.ts.map +1 -0
  45. package/dist/src/types.js +2 -0
  46. package/dist/src/types.js.map +1 -0
  47. package/dist/src/utils.d.ts +22 -0
  48. package/dist/src/utils.d.ts.map +1 -0
  49. package/dist/src/utils.js +183 -0
  50. package/dist/src/utils.js.map +1 -0
  51. package/dist/test/tools/advanced.test.d.ts +2 -0
  52. package/dist/test/tools/advanced.test.d.ts.map +1 -0
  53. package/dist/test/tools/advanced.test.js +235 -0
  54. package/dist/test/tools/advanced.test.js.map +1 -0
  55. package/dist/test/tools/balance.test.d.ts +2 -0
  56. package/dist/test/tools/balance.test.d.ts.map +1 -0
  57. package/dist/test/tools/balance.test.js +167 -0
  58. package/dist/test/tools/balance.test.js.map +1 -0
  59. package/dist/test/tools/contract-info.test.d.ts +2 -0
  60. package/dist/test/tools/contract-info.test.d.ts.map +1 -0
  61. package/dist/test/tools/contract-info.test.js +286 -0
  62. package/dist/test/tools/contract-info.test.js.map +1 -0
  63. package/dist/test/tools/contract.test.d.ts +2 -0
  64. package/dist/test/tools/contract.test.d.ts.map +1 -0
  65. package/dist/test/tools/contract.test.js +234 -0
  66. package/dist/test/tools/contract.test.js.map +1 -0
  67. package/dist/test/tools/ens.test.d.ts +2 -0
  68. package/dist/test/tools/ens.test.d.ts.map +1 -0
  69. package/dist/test/tools/ens.test.js +236 -0
  70. package/dist/test/tools/ens.test.js.map +1 -0
  71. package/dist/test/tools/logs.test.d.ts +2 -0
  72. package/dist/test/tools/logs.test.d.ts.map +1 -0
  73. package/dist/test/tools/logs.test.js +196 -0
  74. package/dist/test/tools/logs.test.js.map +1 -0
  75. package/dist/test/tools/signatures.test.d.ts +2 -0
  76. package/dist/test/tools/signatures.test.d.ts.map +1 -0
  77. package/dist/test/tools/signatures.test.js +112 -0
  78. package/dist/test/tools/signatures.test.js.map +1 -0
  79. package/package.json +37 -22
  80. package/src/client.ts +160 -0
  81. package/src/index.ts +96 -0
  82. package/src/tools/advanced.ts +262 -0
  83. package/src/tools/balance.ts +176 -0
  84. package/src/tools/contract-info.ts +582 -0
  85. package/src/tools/contract.ts +180 -0
  86. package/src/tools/ens.ts +493 -0
  87. package/src/tools/index.ts +37 -0
  88. package/src/tools/logs.ts +291 -0
  89. package/src/tools/signatures.ts +126 -0
  90. package/src/types.ts +29 -0
  91. package/src/utils.ts +222 -0
  92. package/dist/hypersync-client.darwin-arm64-7fegfwn5.node +0 -0
  93. package/dist/index.js +0 -28282
@@ -0,0 +1,176 @@
1
+ import { type Address, formatEther, formatUnits, isAddress } from 'viem'
2
+ import { z } from 'zod'
3
+ import type { ChainName } from '../types.js'
4
+ import { getClientManager, SUPPORTED_CHAINS } from '../client.js'
5
+ import { createTool, formatResponse } from '../utils.js'
6
+
7
+ const BalanceQuerySchema = z.object({
8
+ chain: z.enum(SUPPORTED_CHAINS).describe('The blockchain network to use'),
9
+ address: z.string().describe('The address to check balance for'),
10
+ tokenAddress: z
11
+ .string()
12
+ .optional()
13
+ .describe('Token contract address (optional, if not provided returns native token balance)'),
14
+ blockNumber: z.string().optional().describe('Block number to query (optional, defaults to latest)'),
15
+ label: z.string().optional().describe('Optional label for batch results')
16
+ })
17
+
18
+ export default {
19
+ get_balance: createTool(
20
+ 'Get Token Balances',
21
+ 'Retrieve native and ERC20 token balances for multiple addresses. BATCH OPTIMIZED - use for portfolio tracking, wallet monitoring.',
22
+ z.object({
23
+ queries: z.array(BalanceQuerySchema).describe('Array of balance queries. Omit tokenAddress for native balance, include for ERC20.')
24
+ }),
25
+ async (args) => {
26
+ // Group by chain and blockNumber for efficient processing
27
+ const groupedQueries = new Map<string, typeof args.queries>()
28
+ for (const item of args.queries) {
29
+ const key = `${item.chain}:${item.blockNumber || 'latest'}`
30
+ if (!groupedQueries.has(key)) {
31
+ groupedQueries.set(key, [])
32
+ }
33
+ groupedQueries.get(key)!.push(item)
34
+ }
35
+
36
+ const allResults: Array<{
37
+ index: number
38
+ label?: string
39
+ address: string
40
+ tokenAddress?: string
41
+ chain: string
42
+ blockNumber: string
43
+ success: boolean
44
+ balance?: unknown
45
+ balanceFormatted?: string
46
+ decimals?: number
47
+ error?: string
48
+ }> = []
49
+
50
+ try {
51
+ // Process each group
52
+ for (const [key, queries] of groupedQueries) {
53
+ const [chain, blockNum] = key.split(':')
54
+ const clientManager = getClientManager()
55
+ const client = clientManager.getClient(chain as ChainName)
56
+ const blockTag = blockNum === 'latest' ? 'latest' : BigInt(blockNum)
57
+
58
+ // Process all queries in this group
59
+ const results = await Promise.allSettled(
60
+ queries.map(async (query) => {
61
+ if (!isAddress(query.address)) {
62
+ throw new Error(`Invalid address format: ${query.address}`)
63
+ }
64
+
65
+ const originalIndex = args.queries.indexOf(query)
66
+
67
+ // Native token balance
68
+ if (!query.tokenAddress) {
69
+ const balance = await client.getBalance({
70
+ address: query.address as Address,
71
+ blockNumber: blockTag === 'latest' ? undefined : blockTag
72
+ })
73
+
74
+ return {
75
+ index: originalIndex,
76
+ label: query.label,
77
+ address: query.address,
78
+ chain: query.chain,
79
+ blockNumber: query.blockNumber || 'latest',
80
+ success: true,
81
+ balance,
82
+ balanceFormatted: formatEther(balance)
83
+ }
84
+ }
85
+
86
+ // ERC20 token balance
87
+ if (!isAddress(query.tokenAddress)) {
88
+ throw new Error(`Invalid token address format: ${query.tokenAddress}`)
89
+ }
90
+
91
+ const balance = await client.readContract({
92
+ address: query.tokenAddress as Address,
93
+ abi: [
94
+ {
95
+ name: 'balanceOf',
96
+ type: 'function',
97
+ stateMutability: 'view',
98
+ inputs: [{ name: 'account', type: 'address' }],
99
+ outputs: [{ name: '', type: 'uint256' }]
100
+ }
101
+ ],
102
+ functionName: 'balanceOf',
103
+ args: [query.address as Address],
104
+ blockNumber: blockTag === 'latest' ? undefined : blockTag
105
+ })
106
+
107
+ // Try to get decimals
108
+ let decimals = 18
109
+ try {
110
+ decimals = (await client.readContract({
111
+ address: query.tokenAddress as Address,
112
+ abi: [
113
+ {
114
+ name: 'decimals',
115
+ type: 'function',
116
+ stateMutability: 'view',
117
+ inputs: [],
118
+ outputs: [{ name: '', type: 'uint8' }]
119
+ }
120
+ ],
121
+ functionName: 'decimals',
122
+ blockNumber: blockTag === 'latest' ? undefined : blockTag
123
+ })) as number
124
+ } catch {
125
+ // Use default decimals if call fails
126
+ }
127
+
128
+ return {
129
+ index: originalIndex,
130
+ label: query.label,
131
+ address: query.address,
132
+ tokenAddress: query.tokenAddress,
133
+ chain: query.chain,
134
+ blockNumber: query.blockNumber || 'latest',
135
+ success: true,
136
+ balance,
137
+ balanceFormatted: formatUnits(balance as bigint, decimals),
138
+ decimals
139
+ }
140
+ })
141
+ )
142
+
143
+ // Process results
144
+ results.forEach((result, idx) => {
145
+ if (result.status === 'fulfilled') {
146
+ allResults[result.value.index] = result.value
147
+ } else {
148
+ const query = queries[idx]!
149
+ const originalIndex = args.queries.indexOf(query)
150
+ allResults[originalIndex] = {
151
+ index: originalIndex,
152
+ label: query.label,
153
+ address: query.address,
154
+ tokenAddress: query.tokenAddress,
155
+ chain: query.chain,
156
+ blockNumber: query.blockNumber || 'latest',
157
+ success: false,
158
+ error: result.reason instanceof Error ? result.reason.message : String(result.reason)
159
+ }
160
+ }
161
+ })
162
+ }
163
+
164
+ return formatResponse({
165
+ success: true,
166
+ totalQueries: args.queries.length,
167
+ successfulQueries: allResults.filter((r) => r.success).length,
168
+ failedQueries: allResults.filter((r) => !r.success).length,
169
+ results: allResults
170
+ })
171
+ } catch (error) {
172
+ throw new Error(`Balance query failed: ${error}`)
173
+ }
174
+ }
175
+ )
176
+ }