web3-tools-mcp 1.6.0 → 2.0.1
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 +109 -0
- package/README.md +328 -234
- package/dist/anvil.d.ts +1 -1
- package/dist/anvil.d.ts.map +1 -1
- package/dist/anvil.js +11 -9
- package/dist/anvil.js.map +1 -1
- package/dist/chain-meta.d.ts.map +1 -1
- package/dist/chain-meta.js +7 -3
- package/dist/chain-meta.js.map +1 -1
- package/dist/chains.d.ts +960 -0
- package/dist/chains.d.ts.map +1 -0
- package/dist/chains.js +108 -0
- package/dist/chains.js.map +1 -0
- package/dist/client.d.ts +10 -1717
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +33 -218
- package/dist/client.js.map +1 -1
- package/dist/http-server.d.ts +6 -0
- package/dist/http-server.d.ts.map +1 -1
- package/dist/http-server.js +55 -40
- package/dist/http-server.js.map +1 -1
- package/dist/index.js +50 -29
- package/dist/index.js.map +1 -1
- package/dist/oauth.d.ts +31 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +227 -0
- package/dist/oauth.js.map +1 -0
- package/dist/preview.d.ts.map +1 -1
- package/dist/preview.js +2 -2
- package/dist/preview.js.map +1 -1
- package/dist/tools/advanced.d.ts +4 -4
- package/dist/tools/advanced.d.ts.map +1 -1
- package/dist/tools/advanced.js +228 -247
- package/dist/tools/advanced.js.map +1 -1
- package/dist/tools/balance.d.ts +1 -1
- package/dist/tools/balance.d.ts.map +1 -1
- package/dist/tools/balance.js +97 -103
- package/dist/tools/balance.js.map +1 -1
- package/dist/tools/contract-info.d.ts +3 -3
- package/dist/tools/contract-info.d.ts.map +1 -1
- package/dist/tools/contract-info.js +150 -161
- package/dist/tools/contract-info.js.map +1 -1
- package/dist/tools/contract.d.ts +4 -4
- package/dist/tools/contract.d.ts.map +1 -1
- package/dist/tools/contract.js +91 -110
- package/dist/tools/contract.js.map +1 -1
- package/dist/tools/ens.d.ts +6 -6
- package/dist/tools/ens.d.ts.map +1 -1
- package/dist/tools/ens.js +239 -297
- package/dist/tools/ens.js.map +1 -1
- package/dist/tools/gas.d.ts +4 -4
- package/dist/tools/gas.d.ts.map +1 -1
- package/dist/tools/gas.js +90 -138
- package/dist/tools/gas.js.map +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/logs.d.ts +1 -1
- package/dist/tools/logs.d.ts.map +1 -1
- package/dist/tools/logs.js +36 -37
- package/dist/tools/logs.js.map +1 -1
- package/dist/tools/signatures.d.ts.map +1 -1
- package/dist/tools/signatures.js +67 -89
- package/dist/tools/signatures.js.map +1 -1
- package/dist/tools/transactions.d.ts +35 -5
- package/dist/tools/transactions.d.ts.map +1 -1
- package/dist/tools/transactions.js +148 -74
- package/dist/tools/transactions.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +35 -98
- package/dist/utils.js.map +1 -1
- package/dist/wallet-client.d.ts +11 -1
- package/dist/wallet-client.d.ts.map +1 -1
- package/dist/wallet-client.js +27 -9
- package/dist/wallet-client.js.map +1 -1
- package/dist/walletconnect.d.ts +22 -1
- package/dist/walletconnect.d.ts.map +1 -1
- package/dist/walletconnect.js +106 -8
- package/dist/walletconnect.js.map +1 -1
- package/package.json +17 -9
- package/src/anvil.ts +15 -18
- package/src/chain-meta.ts +8 -4
- package/src/chains.ts +145 -0
- package/src/client.ts +39 -254
- package/src/http-server.ts +67 -44
- package/src/index.ts +77 -53
- package/src/oauth.ts +270 -0
- package/src/preview.ts +3 -12
- package/src/tools/advanced.ts +195 -213
- package/src/tools/balance.ts +103 -108
- package/src/tools/contract-info.ts +163 -184
- package/src/tools/contract.ts +123 -144
- package/src/tools/ens.ts +290 -345
- package/src/tools/gas.ts +122 -170
- package/src/tools/index.ts +2 -2
- package/src/tools/logs.ts +45 -43
- package/src/tools/signatures.ts +68 -86
- package/src/tools/transactions.ts +194 -87
- package/src/types.ts +1 -15
- package/src/utils.ts +52 -110
- package/src/wallet-client.ts +31 -9
- package/src/walletconnect.ts +124 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isAddress } from 'viem'
|
|
2
2
|
import { z } from 'zod'
|
|
3
|
+
import { getClientManager, SUPPORTED_CHAINS } from '../client.js'
|
|
3
4
|
import type { ChainName } from '../types.js'
|
|
4
|
-
import { CHAINS, getClientManager, SUPPORTED_CHAINS } from '../client.js'
|
|
5
5
|
import { createTool, formatResponse } from '../utils.js'
|
|
6
6
|
|
|
7
7
|
// Type for raw Etherscan contract info
|
|
@@ -44,11 +44,7 @@ function getCacheKey(chainId: number, address: string): string {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
// Shared helper to fetch contract info from Etherscan (with caching)
|
|
47
|
-
async function fetchContractInfo(
|
|
48
|
-
chainId: number,
|
|
49
|
-
address: string,
|
|
50
|
-
etherscanApiKey: string
|
|
51
|
-
): Promise<EtherscanContractInfo> {
|
|
47
|
+
async function fetchContractInfo(chainId: number, address: string, etherscanApiKey: string): Promise<EtherscanContractInfo> {
|
|
52
48
|
// Check cache first
|
|
53
49
|
const cacheKey = getCacheKey(chainId, address)
|
|
54
50
|
const cached = contractCache.get(cacheKey)
|
|
@@ -98,9 +94,7 @@ export default {
|
|
|
98
94
|
chain: z.enum(SUPPORTED_CHAINS).describe('The blockchain network to use'),
|
|
99
95
|
address: z.string().describe('The contract address to get ABI for'),
|
|
100
96
|
include: z
|
|
101
|
-
.array(
|
|
102
|
-
z.enum(['abi', 'implementationAbi', 'metadata', 'compilation', 'creation', 'stats'])
|
|
103
|
-
)
|
|
97
|
+
.array(z.enum(['abi', 'implementationAbi', 'metadata', 'compilation', 'creation', 'stats']))
|
|
104
98
|
.optional()
|
|
105
99
|
.describe(
|
|
106
100
|
'Optional: specify which data to include. Options: "abi" (contract ABI), "implementationAbi" (proxy implementation ABI), "metadata" (name, verification), "compilation" (compiler, optimization), "creation" (creator, tx), "stats" (function/event counts). Defaults to ["abi", "metadata"] for minimal context usage.'
|
|
@@ -124,8 +118,7 @@ export default {
|
|
|
124
118
|
const include = args.include || ['abi', 'metadata']
|
|
125
119
|
const includeSet = new Set(include)
|
|
126
120
|
|
|
127
|
-
const
|
|
128
|
-
const chainId = chains[args.chain as ChainName].chain.id
|
|
121
|
+
const chainId = getClientManager().getChainId(args.chain as ChainName)
|
|
129
122
|
|
|
130
123
|
// Use shared helper to fetch contract info
|
|
131
124
|
const contractInfo = await fetchContractInfo(chainId, args.address, config.etherscanApiKey)
|
|
@@ -153,7 +146,7 @@ export default {
|
|
|
153
146
|
chain: args.chain,
|
|
154
147
|
chainId,
|
|
155
148
|
address: args.address,
|
|
156
|
-
etherscanUrl:
|
|
149
|
+
etherscanUrl: clientManager.explorerUrl(args.chain as ChainName, `/address/${args.address}`)
|
|
157
150
|
}
|
|
158
151
|
|
|
159
152
|
// Add metadata if requested
|
|
@@ -292,201 +285,189 @@ export default {
|
|
|
292
285
|
const config = (clientManager as any).config
|
|
293
286
|
|
|
294
287
|
if (!config.etherscanApiKey) {
|
|
295
|
-
throw new Error(
|
|
296
|
-
'Etherscan API key is required. Use --etherscan-api-key or set ETHERSCAN_API_KEY environment variable.'
|
|
297
|
-
)
|
|
288
|
+
throw new Error('Etherscan API key is required. Use --etherscan-api-key or set ETHERSCAN_API_KEY environment variable.')
|
|
298
289
|
}
|
|
299
290
|
|
|
300
291
|
if (!isAddress(args.address)) {
|
|
301
292
|
throw new Error('Invalid contract address')
|
|
302
293
|
}
|
|
303
294
|
|
|
304
|
-
const
|
|
305
|
-
const chainId = chains[args.chain as ChainName].chain.id
|
|
295
|
+
const chainId = getClientManager().getChainId(args.chain as ChainName)
|
|
306
296
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
const contractInfo = await fetchContractInfo(chainId, args.address, config.etherscanApiKey)
|
|
297
|
+
// Fetch main contract source using shared helper
|
|
298
|
+
const contractInfo = await fetchContractInfo(chainId, args.address, config.etherscanApiKey)
|
|
310
299
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
300
|
+
if (!contractInfo) {
|
|
301
|
+
throw new Error('No contract information found')
|
|
302
|
+
}
|
|
314
303
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
if (!isVerified) {
|
|
319
|
-
return formatResponse({
|
|
320
|
-
success: false,
|
|
321
|
-
chain: args.chain,
|
|
322
|
-
chainId,
|
|
323
|
-
address: args.address,
|
|
324
|
-
isVerified: false,
|
|
325
|
-
message: 'Contract source code is not verified on Etherscan',
|
|
326
|
-
etherscanUrl: `https://${clientManager.getEtherscanDomain(args.chain as ChainName)}/address/${args.address}`
|
|
327
|
-
})
|
|
328
|
-
}
|
|
304
|
+
const isVerified = contractInfo.SourceCode !== ''
|
|
305
|
+
const isProxy = contractInfo.Proxy === '1'
|
|
329
306
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
307
|
+
if (!isVerified) {
|
|
308
|
+
return formatResponse({
|
|
309
|
+
success: false,
|
|
310
|
+
chain: args.chain,
|
|
311
|
+
chainId,
|
|
312
|
+
address: args.address,
|
|
313
|
+
isVerified: false,
|
|
314
|
+
message: 'Contract source code is not verified on Etherscan',
|
|
315
|
+
etherscanUrl: clientManager.explorerUrl(args.chain as ChainName, `/address/${args.address}`)
|
|
316
|
+
})
|
|
317
|
+
}
|
|
333
318
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
}
|
|
353
|
-
//
|
|
354
|
-
sourceFiles =
|
|
319
|
+
// Parse source code
|
|
320
|
+
let sourceFiles: Record<string, string> = {}
|
|
321
|
+
let sourceCodeString = contractInfo.SourceCode
|
|
322
|
+
|
|
323
|
+
// Handle multi-file sources (wrapped in {{ }} or [ ])
|
|
324
|
+
if (sourceCodeString.startsWith('{{') || sourceCodeString.startsWith('[')) {
|
|
325
|
+
try {
|
|
326
|
+
// Remove outer braces/brackets if present
|
|
327
|
+
if (sourceCodeString.startsWith('{{')) {
|
|
328
|
+
sourceCodeString = sourceCodeString.slice(1, -1)
|
|
329
|
+
}
|
|
330
|
+
const parsed = JSON.parse(sourceCodeString)
|
|
331
|
+
|
|
332
|
+
if (parsed.sources) {
|
|
333
|
+
// Standard JSON format
|
|
334
|
+
sourceFiles = Object.fromEntries(
|
|
335
|
+
Object.entries(parsed.sources).map(([path, data]: [string, any]) => [path, data.content || ''])
|
|
336
|
+
)
|
|
337
|
+
} else if (typeof parsed === 'object') {
|
|
338
|
+
// Simple object format
|
|
339
|
+
sourceFiles = parsed
|
|
355
340
|
}
|
|
356
|
-
}
|
|
357
|
-
//
|
|
358
|
-
sourceFiles = { [contractInfo.ContractName
|
|
341
|
+
} catch {
|
|
342
|
+
// If parsing fails, treat as single file
|
|
343
|
+
sourceFiles = { [`${contractInfo.ContractName}.sol`]: sourceCodeString }
|
|
359
344
|
}
|
|
345
|
+
} else {
|
|
346
|
+
// Single file source
|
|
347
|
+
sourceFiles = { [`${contractInfo.ContractName}.sol`]: sourceCodeString }
|
|
348
|
+
}
|
|
360
349
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
350
|
+
// Calculate file stats for summary mode
|
|
351
|
+
const fileStats = Object.entries(sourceFiles).map(([path, content]) => ({
|
|
352
|
+
path,
|
|
353
|
+
lines: (content as string).split('\n').length,
|
|
354
|
+
size: (content as string).length
|
|
355
|
+
}))
|
|
367
356
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
357
|
+
const result: Record<string, unknown> = {
|
|
358
|
+
success: true,
|
|
359
|
+
chain: args.chain,
|
|
360
|
+
chainId,
|
|
361
|
+
address: args.address,
|
|
362
|
+
isVerified: true,
|
|
363
|
+
isProxy,
|
|
364
|
+
contractName: contractInfo.ContractName,
|
|
365
|
+
compilerVersion: contractInfo.CompilerVersion,
|
|
366
|
+
optimizationUsed: contractInfo.OptimizationUsed === '1',
|
|
367
|
+
optimizationRuns: parseInt(contractInfo.Runs, 10) || 0,
|
|
368
|
+
evmVersion: contractInfo.EVMVersion,
|
|
369
|
+
licenseType: contractInfo.LicenseType,
|
|
370
|
+
constructorArguments: contractInfo.ConstructorArguments,
|
|
371
|
+
fileCount: Object.keys(sourceFiles).length,
|
|
372
|
+
totalLines: fileStats.reduce((sum, stat) => sum + stat.lines, 0),
|
|
373
|
+
etherscanUrl: clientManager.explorerUrl(args.chain as ChainName, `/address/${args.address}#code`)
|
|
374
|
+
}
|
|
386
375
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
if (
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
implSourceFiles = Object.fromEntries(
|
|
419
|
-
Object.entries(parsed.sources).map(([path, data]: [string, any]) => [path, data.content || ''])
|
|
420
|
-
)
|
|
421
|
-
} else if (typeof parsed === 'object') {
|
|
422
|
-
implSourceFiles = parsed
|
|
423
|
-
}
|
|
424
|
-
} catch {
|
|
425
|
-
implSourceFiles = { [implInfo.ContractName + '.sol']: implSourceCodeString }
|
|
376
|
+
// Add source based on includeSource parameter
|
|
377
|
+
if (args.includeSource === 'full') {
|
|
378
|
+
result.sourceFiles = sourceFiles
|
|
379
|
+
} else if (args.includeSource === 'summary') {
|
|
380
|
+
result.files = fileStats
|
|
381
|
+
}
|
|
382
|
+
// 'none' mode: no source files added
|
|
383
|
+
|
|
384
|
+
// If proxy and implementation requested, fetch implementation source
|
|
385
|
+
if (isProxy && args.includeImplementation && contractInfo.Implementation && isAddress(contractInfo.Implementation)) {
|
|
386
|
+
try {
|
|
387
|
+
const implInfo = await fetchContractInfo(chainId, contractInfo.Implementation, config.etherscanApiKey)
|
|
388
|
+
|
|
389
|
+
if (implInfo && implInfo.SourceCode !== '') {
|
|
390
|
+
// Parse implementation source code
|
|
391
|
+
let implSourceFiles: Record<string, string> = {}
|
|
392
|
+
let implSourceCodeString = implInfo.SourceCode
|
|
393
|
+
|
|
394
|
+
if (implSourceCodeString.startsWith('{{') || implSourceCodeString.startsWith('[')) {
|
|
395
|
+
try {
|
|
396
|
+
if (implSourceCodeString.startsWith('{{')) {
|
|
397
|
+
implSourceCodeString = implSourceCodeString.slice(1, -1)
|
|
398
|
+
}
|
|
399
|
+
const parsed = JSON.parse(implSourceCodeString)
|
|
400
|
+
|
|
401
|
+
if (parsed.sources) {
|
|
402
|
+
implSourceFiles = Object.fromEntries(
|
|
403
|
+
Object.entries(parsed.sources).map(([path, data]: [string, any]) => [path, data.content || ''])
|
|
404
|
+
)
|
|
405
|
+
} else if (typeof parsed === 'object') {
|
|
406
|
+
implSourceFiles = parsed
|
|
426
407
|
}
|
|
427
|
-
}
|
|
428
|
-
implSourceFiles = { [implInfo.ContractName
|
|
408
|
+
} catch {
|
|
409
|
+
implSourceFiles = { [`${implInfo.ContractName}.sol`]: implSourceCodeString }
|
|
429
410
|
}
|
|
411
|
+
} else {
|
|
412
|
+
implSourceFiles = { [`${implInfo.ContractName}.sol`]: implSourceCodeString }
|
|
413
|
+
}
|
|
430
414
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
415
|
+
// Calculate implementation file stats
|
|
416
|
+
const implFileStats = Object.entries(implSourceFiles).map(([path, content]) => ({
|
|
417
|
+
path,
|
|
418
|
+
lines: (content as string).split('\n').length,
|
|
419
|
+
size: (content as string).length
|
|
420
|
+
}))
|
|
421
|
+
|
|
422
|
+
const implResult: Record<string, unknown> = {
|
|
423
|
+
address: contractInfo.Implementation,
|
|
424
|
+
contractName: implInfo.ContractName,
|
|
425
|
+
compilerVersion: implInfo.CompilerVersion,
|
|
426
|
+
optimizationUsed: implInfo.OptimizationUsed === '1',
|
|
427
|
+
optimizationRuns: parseInt(implInfo.Runs, 10) || 0,
|
|
428
|
+
evmVersion: implInfo.EVMVersion,
|
|
429
|
+
licenseType: implInfo.LicenseType,
|
|
430
|
+
fileCount: Object.keys(implSourceFiles).length,
|
|
431
|
+
totalLines: implFileStats.reduce((sum, stat) => sum + stat.lines, 0),
|
|
432
|
+
etherscanUrl: clientManager.explorerUrl(args.chain as ChainName, `/address/${contractInfo.Implementation}#code`)
|
|
433
|
+
}
|
|
450
434
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
435
|
+
// Add implementation source based on includeSource parameter
|
|
436
|
+
if (args.includeSource === 'full') {
|
|
437
|
+
implResult.sourceFiles = implSourceFiles
|
|
438
|
+
} else if (args.includeSource === 'summary') {
|
|
439
|
+
implResult.files = implFileStats
|
|
440
|
+
}
|
|
457
441
|
|
|
458
|
-
|
|
442
|
+
result.implementation = implResult
|
|
459
443
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
}
|
|
444
|
+
// Update cache with implementation source (rawInfo already cached by fetchContractInfo)
|
|
445
|
+
if (contractInfo.Implementation) {
|
|
446
|
+
const implCacheKey = getCacheKey(chainId, contractInfo.Implementation)
|
|
447
|
+
const existingImpl = contractCache.get(implCacheKey)!
|
|
448
|
+
contractCache.set(implCacheKey, {
|
|
449
|
+
...existingImpl,
|
|
450
|
+
sourceFiles: implSourceFiles
|
|
451
|
+
})
|
|
469
452
|
}
|
|
470
|
-
} catch (error) {
|
|
471
|
-
// Implementation fetch failed, continue without it
|
|
472
|
-
result.implementationError = error instanceof Error ? error.message : 'Failed to fetch implementation source'
|
|
473
453
|
}
|
|
474
|
-
}
|
|
475
|
-
|
|
454
|
+
} catch (error) {
|
|
455
|
+
// Implementation fetch failed, continue without it
|
|
456
|
+
result.implementationError = error instanceof Error ? error.message : 'Failed to fetch implementation source'
|
|
476
457
|
}
|
|
458
|
+
} else if (isProxy && contractInfo.Implementation) {
|
|
459
|
+
result.implementationAddress = contractInfo.Implementation
|
|
460
|
+
}
|
|
477
461
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
462
|
+
// Update cache with main contract source (rawInfo already cached by fetchContractInfo)
|
|
463
|
+
const cacheKey = getCacheKey(chainId, args.address)
|
|
464
|
+
const existing = contractCache.get(cacheKey)!
|
|
465
|
+
contractCache.set(cacheKey, {
|
|
466
|
+
...existing,
|
|
467
|
+
sourceFiles
|
|
468
|
+
})
|
|
485
469
|
|
|
486
|
-
|
|
487
|
-
} catch (error) {
|
|
488
|
-
throw new Error(`Failed to fetch source code: ${error}`)
|
|
489
|
-
}
|
|
470
|
+
return formatResponse(result)
|
|
490
471
|
}
|
|
491
472
|
),
|
|
492
473
|
|
|
@@ -505,8 +486,7 @@ export default {
|
|
|
505
486
|
}),
|
|
506
487
|
async (args) => {
|
|
507
488
|
const clientManager = getClientManager()
|
|
508
|
-
const
|
|
509
|
-
const chainId = chains[args.chain as ChainName].chain.id
|
|
489
|
+
const chainId = clientManager.getChainId(args.chain as ChainName)
|
|
510
490
|
|
|
511
491
|
if (!isAddress(args.address)) {
|
|
512
492
|
throw new Error('Invalid contract address')
|
|
@@ -528,8 +508,7 @@ export default {
|
|
|
528
508
|
chain: args.chain,
|
|
529
509
|
chainId,
|
|
530
510
|
address: args.address,
|
|
531
|
-
message:
|
|
532
|
-
'Contract not in cache. Use get_contract_source_code with includeSource="full" first to cache the contract.'
|
|
511
|
+
message: 'Contract not in cache. Use get_contract_source_code with includeSource="full" first to cache the contract.'
|
|
533
512
|
})
|
|
534
513
|
}
|
|
535
514
|
|