web3-tools-mcp 1.6.0 → 2.0.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 (104) hide show
  1. package/CHANGELOG.md +95 -0
  2. package/README.md +328 -234
  3. package/dist/anvil.d.ts +1 -1
  4. package/dist/anvil.d.ts.map +1 -1
  5. package/dist/anvil.js +11 -9
  6. package/dist/anvil.js.map +1 -1
  7. package/dist/chain-meta.d.ts.map +1 -1
  8. package/dist/chain-meta.js +7 -3
  9. package/dist/chain-meta.js.map +1 -1
  10. package/dist/chains.d.ts +960 -0
  11. package/dist/chains.d.ts.map +1 -0
  12. package/dist/chains.js +108 -0
  13. package/dist/chains.js.map +1 -0
  14. package/dist/client.d.ts +10 -1717
  15. package/dist/client.d.ts.map +1 -1
  16. package/dist/client.js +33 -218
  17. package/dist/client.js.map +1 -1
  18. package/dist/http-server.d.ts +6 -0
  19. package/dist/http-server.d.ts.map +1 -1
  20. package/dist/http-server.js +55 -40
  21. package/dist/http-server.js.map +1 -1
  22. package/dist/index.js +50 -29
  23. package/dist/index.js.map +1 -1
  24. package/dist/oauth.d.ts +31 -0
  25. package/dist/oauth.d.ts.map +1 -0
  26. package/dist/oauth.js +227 -0
  27. package/dist/oauth.js.map +1 -0
  28. package/dist/preview.d.ts.map +1 -1
  29. package/dist/preview.js +2 -2
  30. package/dist/preview.js.map +1 -1
  31. package/dist/tools/advanced.d.ts +4 -4
  32. package/dist/tools/advanced.d.ts.map +1 -1
  33. package/dist/tools/advanced.js +228 -247
  34. package/dist/tools/advanced.js.map +1 -1
  35. package/dist/tools/balance.d.ts +1 -1
  36. package/dist/tools/balance.d.ts.map +1 -1
  37. package/dist/tools/balance.js +97 -103
  38. package/dist/tools/balance.js.map +1 -1
  39. package/dist/tools/contract-info.d.ts +3 -3
  40. package/dist/tools/contract-info.d.ts.map +1 -1
  41. package/dist/tools/contract-info.js +150 -161
  42. package/dist/tools/contract-info.js.map +1 -1
  43. package/dist/tools/contract.d.ts +4 -4
  44. package/dist/tools/contract.d.ts.map +1 -1
  45. package/dist/tools/contract.js +91 -110
  46. package/dist/tools/contract.js.map +1 -1
  47. package/dist/tools/ens.d.ts +6 -6
  48. package/dist/tools/ens.d.ts.map +1 -1
  49. package/dist/tools/ens.js +239 -297
  50. package/dist/tools/ens.js.map +1 -1
  51. package/dist/tools/gas.d.ts +4 -4
  52. package/dist/tools/gas.d.ts.map +1 -1
  53. package/dist/tools/gas.js +90 -138
  54. package/dist/tools/gas.js.map +1 -1
  55. package/dist/tools/index.d.ts +1 -1
  56. package/dist/tools/index.d.ts.map +1 -1
  57. package/dist/tools/logs.d.ts +1 -1
  58. package/dist/tools/logs.d.ts.map +1 -1
  59. package/dist/tools/logs.js +36 -37
  60. package/dist/tools/logs.js.map +1 -1
  61. package/dist/tools/signatures.d.ts.map +1 -1
  62. package/dist/tools/signatures.js +67 -89
  63. package/dist/tools/signatures.js.map +1 -1
  64. package/dist/tools/transactions.d.ts +35 -5
  65. package/dist/tools/transactions.d.ts.map +1 -1
  66. package/dist/tools/transactions.js +148 -74
  67. package/dist/tools/transactions.js.map +1 -1
  68. package/dist/types.d.ts +1 -1
  69. package/dist/types.d.ts.map +1 -1
  70. package/dist/utils.d.ts +1 -1
  71. package/dist/utils.d.ts.map +1 -1
  72. package/dist/utils.js +35 -98
  73. package/dist/utils.js.map +1 -1
  74. package/dist/wallet-client.d.ts +11 -1
  75. package/dist/wallet-client.d.ts.map +1 -1
  76. package/dist/wallet-client.js +27 -9
  77. package/dist/wallet-client.js.map +1 -1
  78. package/dist/walletconnect.d.ts +22 -1
  79. package/dist/walletconnect.d.ts.map +1 -1
  80. package/dist/walletconnect.js +101 -8
  81. package/dist/walletconnect.js.map +1 -1
  82. package/package.json +17 -9
  83. package/src/anvil.ts +15 -18
  84. package/src/chain-meta.ts +8 -4
  85. package/src/chains.ts +145 -0
  86. package/src/client.ts +39 -254
  87. package/src/http-server.ts +67 -44
  88. package/src/index.ts +77 -53
  89. package/src/oauth.ts +270 -0
  90. package/src/preview.ts +3 -12
  91. package/src/tools/advanced.ts +195 -213
  92. package/src/tools/balance.ts +103 -108
  93. package/src/tools/contract-info.ts +163 -184
  94. package/src/tools/contract.ts +123 -144
  95. package/src/tools/ens.ts +290 -345
  96. package/src/tools/gas.ts +122 -170
  97. package/src/tools/index.ts +2 -2
  98. package/src/tools/logs.ts +45 -43
  99. package/src/tools/signatures.ts +68 -86
  100. package/src/tools/transactions.ts +194 -87
  101. package/src/types.ts +1 -15
  102. package/src/utils.ts +52 -110
  103. package/src/wallet-client.ts +31 -9
  104. package/src/walletconnect.ts +119 -7
@@ -1,13 +1,9 @@
1
1
  import { type Address, decodeAbiParameters, isAddress, parseAbiParameters } from 'viem'
2
2
  import { z } from 'zod'
3
- import type { ChainName } from '../types.js'
3
+ import { isAnvilInstalled, simulateCallWithTrace, traceTransactionWithAnvil } from '../anvil.js'
4
4
  import { getClientManager, SUPPORTED_CHAINS } from '../client.js'
5
+ import type { ChainName } from '../types.js'
5
6
  import { createTool, formatResponse, summarizeTrace } from '../utils.js'
6
- import {
7
- isAnvilInstalled,
8
- traceTransactionWithAnvil,
9
- simulateCallWithTrace
10
- } from '../anvil.js'
11
7
 
12
8
  export default {
13
9
  get_storage_at: createTool(
@@ -17,9 +13,7 @@ export default {
17
13
  chain: z.enum(SUPPORTED_CHAINS).describe('The blockchain network to use'),
18
14
  address: z.string().describe('The contract address to inspect'),
19
15
  slot: z.string().describe('Storage slot (hex string, e.g., "0x0")'),
20
- abiType: z
21
- .string()
22
- .describe('ABI type for decoding (e.g., "uint256", "address", "bool", "bytes32")'),
16
+ abiType: z.string().describe('ABI type for decoding (e.g., "uint256", "address", "bool", "bytes32")'),
23
17
  blockNumber: z.string().optional().describe('Block number (optional, defaults to latest)')
24
18
  }),
25
19
  async (args) => {
@@ -31,90 +25,86 @@ export default {
31
25
  const client = clientManager.getClient(args.chain as ChainName)
32
26
  const blockTag = args.blockNumber ? BigInt(args.blockNumber) : 'latest'
33
27
 
34
- try {
35
- const storageValue = await client.getStorageAt({
36
- address: args.address as Address,
37
- slot: args.slot as `0x${string}`,
38
- blockNumber: blockTag === 'latest' ? undefined : blockTag
39
- })
28
+ const storageValue = await client.getStorageAt({
29
+ address: args.address as Address,
30
+ slot: args.slot as `0x${string}`,
31
+ blockNumber: blockTag === 'latest' ? undefined : blockTag
32
+ })
40
33
 
41
- if (!storageValue) {
42
- throw new Error('No storage value found')
43
- }
34
+ if (!storageValue) {
35
+ throw new Error('No storage value found')
36
+ }
44
37
 
45
- // Decode based on ABI type
46
- let decodedValue: unknown
47
- let formattedValue: string
38
+ // Decode based on ABI type
39
+ let decodedValue: unknown
40
+ let formattedValue: string
48
41
 
49
- try {
50
- switch (args.abiType.toLowerCase()) {
51
- case 'uint256':
52
- case 'uint': {
53
- decodedValue = BigInt(storageValue)
54
- formattedValue = (decodedValue as bigint).toString()
55
- break
56
- }
57
- case 'int256':
58
- case 'int': {
59
- // Handle two's complement for negative numbers
60
- const uint256Value = BigInt(storageValue)
61
- const maxUint256 = BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')
62
- decodedValue = uint256Value > maxUint256 / 2n ? uint256Value - maxUint256 - 1n : uint256Value
63
- formattedValue = (decodedValue as bigint).toString()
64
- break
65
- }
66
- case 'address': {
67
- decodedValue = `0x${storageValue.slice(-40)}`
68
- formattedValue = decodedValue as string
69
- break
70
- }
71
- case 'bool': {
72
- decodedValue = BigInt(storageValue) !== 0n
73
- formattedValue = String(decodedValue)
74
- break
75
- }
76
- case 'bytes32': {
77
- decodedValue = storageValue
78
- formattedValue = storageValue
79
- break
80
- }
81
- default: {
82
- // Try to decode as ABI parameters
83
- try {
84
- const parsedTypes = parseAbiParameters([args.abiType])
85
- if (parsedTypes.length > 0) {
86
- const decoded = decodeAbiParameters(parsedTypes, storageValue) as readonly unknown[]
87
- decodedValue = decoded.length > 0 ? decoded[0] : null
88
- formattedValue = decodedValue ? String(decodedValue) : 'No data'
89
- } else {
90
- decodedValue = null
91
- formattedValue = 'Invalid ABI type'
92
- }
93
- } catch {
42
+ try {
43
+ switch (args.abiType.toLowerCase()) {
44
+ case 'uint256':
45
+ case 'uint': {
46
+ decodedValue = BigInt(storageValue)
47
+ formattedValue = (decodedValue as bigint).toString()
48
+ break
49
+ }
50
+ case 'int256':
51
+ case 'int': {
52
+ // Handle two's complement for negative numbers
53
+ const uint256Value = BigInt(storageValue)
54
+ const maxUint256 = BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')
55
+ decodedValue = uint256Value > maxUint256 / 2n ? uint256Value - maxUint256 - 1n : uint256Value
56
+ formattedValue = (decodedValue as bigint).toString()
57
+ break
58
+ }
59
+ case 'address': {
60
+ decodedValue = `0x${storageValue.slice(-40)}`
61
+ formattedValue = decodedValue as string
62
+ break
63
+ }
64
+ case 'bool': {
65
+ decodedValue = BigInt(storageValue) !== 0n
66
+ formattedValue = String(decodedValue)
67
+ break
68
+ }
69
+ case 'bytes32': {
70
+ decodedValue = storageValue
71
+ formattedValue = storageValue
72
+ break
73
+ }
74
+ default: {
75
+ // Try to decode as ABI parameters
76
+ try {
77
+ const parsedTypes = parseAbiParameters([args.abiType])
78
+ if (parsedTypes.length > 0) {
79
+ const decoded = decodeAbiParameters(parsedTypes, storageValue) as readonly unknown[]
80
+ decodedValue = decoded.length > 0 ? decoded[0] : null
81
+ formattedValue = decodedValue ? String(decodedValue) : 'No data'
82
+ } else {
94
83
  decodedValue = null
95
- formattedValue = 'Failed to decode with custom ABI type'
84
+ formattedValue = 'Invalid ABI type'
96
85
  }
97
- break
86
+ } catch {
87
+ decodedValue = null
88
+ formattedValue = 'Failed to decode with custom ABI type'
98
89
  }
90
+ break
99
91
  }
100
- } catch {
101
- decodedValue = null
102
- formattedValue = 'Failed to decode'
103
92
  }
104
-
105
- return formatResponse({
106
- rawValue: storageValue,
107
- decodedValue,
108
- formattedValue,
109
- abiType: args.abiType,
110
- slot: args.slot,
111
- address: args.address,
112
- chain: args.chain,
113
- blockNumber: blockTag === 'latest' ? 'latest' : blockTag.toString()
114
- })
115
- } catch (error) {
116
- throw new Error(`Failed to get storage: ${error}`)
93
+ } catch {
94
+ decodedValue = null
95
+ formattedValue = 'Failed to decode'
117
96
  }
97
+
98
+ return formatResponse({
99
+ rawValue: storageValue,
100
+ decodedValue,
101
+ formattedValue,
102
+ abiType: args.abiType,
103
+ slot: args.slot,
104
+ address: args.address,
105
+ chain: args.chain,
106
+ blockNumber: blockTag === 'latest' ? 'latest' : blockTag.toString()
107
+ })
118
108
  }
119
109
  ),
120
110
 
@@ -130,28 +120,24 @@ export default {
130
120
  const client = clientManager.getClient(args.chain as ChainName)
131
121
  const blockTag = args.blockNumber ? BigInt(args.blockNumber) : 'latest'
132
122
 
133
- try {
134
- const block = await client.getBlock({
135
- blockNumber: blockTag === 'latest' ? undefined : blockTag,
136
- includeTransactions: false
137
- })
123
+ const block = await client.getBlock({
124
+ blockNumber: blockTag === 'latest' ? undefined : blockTag,
125
+ includeTransactions: false
126
+ })
138
127
 
139
- const timestamp = Number(block.timestamp)
140
- const date = new Date(timestamp * 1000)
128
+ const timestamp = Number(block.timestamp)
129
+ const date = new Date(timestamp * 1000)
141
130
 
142
- return formatResponse({
143
- blockNumber: block.number,
144
- timestamp: block.timestamp,
145
- timestampMs: timestamp * 1000,
146
- dateIso: date.toISOString(),
147
- dateReadable: date.toLocaleString(),
148
- hash: block.hash,
149
- parentHash: block.parentHash,
150
- chain: args.chain
151
- })
152
- } catch (error) {
153
- throw new Error(`Failed to get block time: ${error}`)
154
- }
131
+ return formatResponse({
132
+ blockNumber: block.number,
133
+ timestamp: block.timestamp,
134
+ timestampMs: timestamp * 1000,
135
+ dateIso: date.toISOString(),
136
+ dateReadable: date.toLocaleString(),
137
+ hash: block.hash,
138
+ parentHash: block.parentHash,
139
+ chain: args.chain
140
+ })
155
141
  }
156
142
  ),
157
143
 
@@ -164,9 +150,7 @@ export default {
164
150
  traceType: z
165
151
  .enum(['trace', 'vmTrace', 'stateDiff'])
166
152
  .optional()
167
- .describe(
168
- 'Trace type: "trace" (call tree, recommended), "vmTrace" (VM execution), "stateDiff" (state changes)'
169
- )
153
+ .describe('Trace type: "trace" (call tree, recommended), "vmTrace" (VM execution), "stateDiff" (state changes)')
170
154
  .default('trace'),
171
155
  useAnvil: z
172
156
  .boolean()
@@ -183,92 +167,96 @@ export default {
183
167
  const clientManager = getClientManager()
184
168
  const client = clientManager.getClient(args.chain as ChainName)
185
169
 
186
- try {
187
- // First get the transaction receipt to make sure it exists
188
- const transaction = await client.getTransaction({ hash: args.transactionHash as `0x${string}` })
189
- const receipt = await client.getTransactionReceipt({ hash: args.transactionHash as `0x${string}` })
170
+ // First get the transaction receipt to make sure it exists
171
+ const transaction = await client.getTransaction({ hash: args.transactionHash as `0x${string}` })
172
+ const receipt = await client.getTransactionReceipt({ hash: args.transactionHash as `0x${string}` })
190
173
 
191
- let traceResult: unknown = null
192
- let usedAnvil = false
174
+ let traceResult: unknown = null
175
+ let usedAnvil = false
193
176
 
194
- // Map trace type to tracer name
195
- const tracerMap: Record<string, 'callTracer' | 'prestateTracer' | 'stateDiffTracer'> = {
196
- trace: 'callTracer',
197
- vmTrace: 'prestateTracer',
198
- stateDiff: 'stateDiffTracer'
199
- }
200
- const tracer = tracerMap[args.traceType ?? 'trace'] ?? 'callTracer'
177
+ // Map trace type to tracer name
178
+ const tracerMap: Record<string, 'callTracer' | 'prestateTracer' | 'stateDiffTracer'> = {
179
+ trace: 'callTracer',
180
+ vmTrace: 'prestateTracer',
181
+ stateDiff: 'stateDiffTracer'
182
+ }
183
+ const tracer = tracerMap[args.traceType ?? 'trace'] ?? 'callTracer'
201
184
 
202
- // Try RPC tracing first (unless forceAnvil is true)
203
- if (!args.useAnvil) {
204
- try {
205
- traceResult = await client.request({
206
- method: 'debug_traceTransaction',
207
- params: [args.transactionHash, { tracer }]
208
- })
209
- } catch (rpcError) {
210
- // RPC tracing failed, will try Anvil fallback
211
- const errorMessage = (rpcError as Error).message
212
- if (
213
- errorMessage.includes('not supported') ||
214
- errorMessage.includes('not available') ||
215
- errorMessage.includes('method not found') ||
216
- errorMessage.includes('does not exist')
217
- ) {
218
- // This is an expected error for public RPCs, try Anvil
219
- traceResult = null
220
- } else {
221
- // Other error, store it but still try Anvil
222
- traceResult = { rpcError: errorMessage }
223
- }
185
+ // Try RPC tracing first (unless forceAnvil is true)
186
+ if (!args.useAnvil) {
187
+ try {
188
+ traceResult = await client.request({
189
+ method: 'debug_traceTransaction',
190
+ params: [args.transactionHash, { tracer }]
191
+ })
192
+ } catch (rpcError) {
193
+ // RPC tracing failed, will try Anvil fallback
194
+ const errorMessage = (rpcError as Error).message
195
+ if (
196
+ errorMessage.includes('not supported') ||
197
+ errorMessage.includes('not available') ||
198
+ errorMessage.includes('method not found') ||
199
+ errorMessage.includes('does not exist')
200
+ ) {
201
+ // This is an expected error for public RPCs, try Anvil
202
+ traceResult = null
203
+ } else {
204
+ // Other error, store it but still try Anvil
205
+ traceResult = { rpcError: errorMessage }
224
206
  }
225
207
  }
208
+ }
226
209
 
227
- // Fallback to Anvil if RPC tracing failed or was skipped
228
- if (traceResult === null || (traceResult && typeof traceResult === 'object' && 'rpcError' in traceResult) || args.useAnvil) {
229
- const anvilAvailable = await isAnvilInstalled()
230
- if (anvilAvailable) {
231
- usedAnvil = true // Mark as used before attempting (even if it fails)
232
- try {
233
- const forkUrl = clientManager.getRpcUrl(args.chain as ChainName)
234
- const blockNumber = transaction.blockNumber ?? 0n
210
+ // Fallback to Anvil if RPC tracing failed or was skipped
211
+ if (
212
+ traceResult === null ||
213
+ (traceResult && typeof traceResult === 'object' && 'rpcError' in traceResult) ||
214
+ args.useAnvil
215
+ ) {
216
+ const anvilAvailable = await isAnvilInstalled()
217
+ if (anvilAvailable) {
218
+ usedAnvil = true // Mark as used before attempting (even if it fails)
219
+ try {
220
+ const forkUrl = clientManager.getRpcUrl(args.chain as ChainName)
221
+ const blockNumber = transaction.blockNumber ?? 0n
235
222
 
236
- traceResult = await traceTransactionWithAnvil(
237
- forkUrl,
238
- args.transactionHash,
239
- blockNumber,
240
- tracer,
241
- args.chain
242
- )
243
- } catch (anvilError) {
244
- // Anvil tracing also failed
245
- traceResult = {
246
- error: `Anvil tracing failed: ${(anvilError as Error).message}`,
247
- rpcError: traceResult && typeof traceResult === 'object' && 'rpcError' in traceResult
223
+ traceResult = await traceTransactionWithAnvil(forkUrl, args.transactionHash, blockNumber, tracer, args.chain)
224
+ } catch (anvilError) {
225
+ // Anvil tracing also failed
226
+ traceResult = {
227
+ error: `Anvil tracing failed: ${(anvilError as Error).message}`,
228
+ rpcError:
229
+ traceResult && typeof traceResult === 'object' && 'rpcError' in traceResult
248
230
  ? (traceResult as { rpcError: string }).rpcError
249
231
  : 'RPC does not support debug_traceTransaction'
250
- }
251
232
  }
252
- } else if (!traceResult || (typeof traceResult === 'object' && 'rpcError' in traceResult)) {
253
- // Anvil not available and RPC failed
254
- traceResult = {
255
- error: 'Tracing not available. Install Foundry (anvil) for local tracing: https://book.getfoundry.sh/getting-started/installation',
256
- rpcError: traceResult && typeof traceResult === 'object' && 'rpcError' in traceResult
233
+ }
234
+ } else if (!traceResult || (typeof traceResult === 'object' && 'rpcError' in traceResult)) {
235
+ // Anvil not available and RPC failed
236
+ traceResult = {
237
+ error:
238
+ 'Tracing not available. Install Foundry (anvil) for local tracing: https://book.getfoundry.sh/getting-started/installation',
239
+ rpcError:
240
+ traceResult && typeof traceResult === 'object' && 'rpcError' in traceResult
257
241
  ? (traceResult as { rpcError: string }).rpcError
258
242
  : 'RPC does not support debug_traceTransaction'
259
- }
260
243
  }
261
244
  }
245
+ }
262
246
 
263
- // Apply summarization if requested - focused on finding reverts
264
- // Skip summarization only if traceResult is a plain error object (not a call trace with an error field)
265
- const isPlainError = traceResult && typeof traceResult === 'object' &&
266
- 'error' in traceResult && !('type' in traceResult) && !('calls' in traceResult)
267
- const traceSummary = args.summarize && traceResult && typeof traceResult === 'object' && !isPlainError
268
- ? summarizeTrace(traceResult)
269
- : null
247
+ // Apply summarization if requested - focused on finding reverts
248
+ // Skip summarization only if traceResult is a plain error object (not a call trace with an error field)
249
+ const isPlainError =
250
+ traceResult &&
251
+ typeof traceResult === 'object' &&
252
+ 'error' in traceResult &&
253
+ !('type' in traceResult) &&
254
+ !('calls' in traceResult)
255
+ const traceSummary =
256
+ args.summarize && traceResult && typeof traceResult === 'object' && !isPlainError ? summarizeTrace(traceResult) : null
270
257
 
271
- const result = args.summarize && traceSummary
258
+ const result =
259
+ args.summarize && traceSummary
272
260
  ? {
273
261
  chain: args.chain,
274
262
  transactionHash: args.transactionHash,
@@ -296,7 +284,7 @@ export default {
296
284
  status: receipt.status,
297
285
  gasUsed: receipt.gasUsed?.toString() || '0',
298
286
  effectiveGasPrice: receipt.effectiveGasPrice?.toString() || '0',
299
- logs: receipt.logs.map(log => ({
287
+ logs: receipt.logs.map((log) => ({
300
288
  address: log.address,
301
289
  topics: log.topics,
302
290
  data: log.data
@@ -305,10 +293,7 @@ export default {
305
293
  trace: traceResult
306
294
  }
307
295
 
308
- return formatResponse(result)
309
- } catch (error) {
310
- throw new Error(`Transaction trace failed: ${error}`)
311
- }
296
+ return formatResponse(result)
312
297
  }
313
298
  ),
314
299
 
@@ -327,10 +312,7 @@ export default {
327
312
  .array(z.union([z.string(), z.number(), z.boolean()]))
328
313
  .optional()
329
314
  .describe('Function arguments (when using functionAbi)'),
330
- from: z
331
- .string()
332
- .optional()
333
- .describe('Sender address (defaults to zero address)'),
315
+ from: z.string().optional().describe('Sender address (defaults to zero address)'),
334
316
  value: z.string().optional().describe('ETH value to send (in wei)'),
335
317
  blockNumber: z.string().optional().describe('Block number to fork from (defaults to latest)'),
336
318
  traceType: z
@@ -348,9 +330,7 @@ export default {
348
330
  // Check if Anvil is installed
349
331
  const anvilAvailable = await isAnvilInstalled()
350
332
  if (!anvilAvailable) {
351
- throw new Error(
352
- 'Anvil is not installed. Please install Foundry: https://book.getfoundry.sh/getting-started/installation'
353
- )
333
+ throw new Error('Anvil is not installed. Please install Foundry: https://book.getfoundry.sh/getting-started/installation')
354
334
  }
355
335
 
356
336
  const clientManager = getClientManager()
@@ -375,31 +355,36 @@ export default {
375
355
  }
376
356
  }
377
357
 
378
- try {
379
- const blockNumber = args.blockNumber ? BigInt(args.blockNumber) : undefined
380
- const value = args.value ? BigInt(args.value) : undefined
358
+ const blockNumber = args.blockNumber ? BigInt(args.blockNumber) : undefined
359
+ const value = args.value ? BigInt(args.value) : undefined
381
360
 
382
- const traceResult = await simulateCallWithTrace(
383
- forkUrl,
384
- {
385
- to: args.to,
386
- data: calldata,
387
- from: args.from,
388
- value
389
- },
390
- blockNumber,
391
- args.traceType
392
- )
361
+ const traceResult = await simulateCallWithTrace(
362
+ forkUrl,
363
+ {
364
+ to: args.to,
365
+ data: calldata,
366
+ from: args.from,
367
+ value
368
+ },
369
+ blockNumber,
370
+ args.traceType
371
+ )
393
372
 
394
- // Apply summarization if requested - focused on finding reverts
395
- // Skip summarization only if trace is a plain error object (not a call trace with an error field)
396
- const isPlainTraceError = traceResult.trace && typeof traceResult.trace === 'object' &&
397
- 'error' in traceResult.trace && !('type' in traceResult.trace) && !('calls' in traceResult.trace)
398
- const traceSummary = args.summarize && traceResult.trace && typeof traceResult.trace === 'object' && !isPlainTraceError
373
+ // Apply summarization if requested - focused on finding reverts
374
+ // Skip summarization only if trace is a plain error object (not a call trace with an error field)
375
+ const isPlainTraceError =
376
+ traceResult.trace &&
377
+ typeof traceResult.trace === 'object' &&
378
+ 'error' in traceResult.trace &&
379
+ !('type' in traceResult.trace) &&
380
+ !('calls' in traceResult.trace)
381
+ const traceSummary =
382
+ args.summarize && traceResult.trace && typeof traceResult.trace === 'object' && !isPlainTraceError
399
383
  ? summarizeTrace(traceResult.trace)
400
384
  : null
401
385
 
402
- const result = args.summarize && traceSummary
386
+ const result =
387
+ args.summarize && traceSummary
403
388
  ? {
404
389
  chain: args.chain,
405
390
  to: args.to,
@@ -422,10 +407,7 @@ export default {
422
407
  trace: traceResult.trace
423
408
  }
424
409
 
425
- return formatResponse(result)
426
- } catch (error) {
427
- throw new Error(`Debug call failed: ${(error as Error).message}`)
428
- }
410
+ return formatResponse(result)
429
411
  }
430
412
  )
431
413
  }