web3-tools-mcp 1.1.0 → 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.
- package/README.md +28 -4
- package/dist/package.json +5 -2
- package/dist/src/tools/ens.d.ts +119 -0
- package/dist/src/tools/ens.d.ts.map +1 -0
- package/dist/src/tools/ens.js +425 -0
- package/dist/src/tools/ens.js.map +1 -0
- package/dist/src/tools/index.d.ts.map +1 -1
- package/dist/src/tools/index.js +3 -1
- package/dist/src/tools/index.js.map +1 -1
- package/dist/test/tools/ens.test.d.ts +2 -0
- package/dist/test/tools/ens.test.d.ts.map +1 -0
- package/dist/test/tools/ens.test.js +236 -0
- package/dist/test/tools/ens.test.js.map +1 -0
- package/package.json +5 -2
- package/src/tools/ens.ts +493 -0
- package/src/tools/index.ts +3 -1
- package/dist/client.d.ts +0 -1653
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -142
- package/dist/client.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -88
- package/dist/index.js.map +0 -1
- package/dist/test/mcp-client.test.d.ts +0 -2
- package/dist/test/mcp-client.test.d.ts.map +0 -1
- package/dist/test/mcp-client.test.js +0 -376
- package/dist/test/mcp-client.test.js.map +0 -1
- package/dist/tools/advanced.d.ts +0 -75
- package/dist/tools/advanced.d.ts.map +0 -1
- package/dist/tools/advanced.js +0 -234
- package/dist/tools/advanced.js.map +0 -1
- package/dist/tools/balance.d.ts +0 -55
- package/dist/tools/balance.d.ts.map +0 -1
- package/dist/tools/balance.js +0 -146
- package/dist/tools/balance.js.map +0 -1
- package/dist/tools/batch.d.ts +0 -122
- package/dist/tools/batch.d.ts.map +0 -1
- package/dist/tools/batch.js +0 -243
- package/dist/tools/batch.js.map +0 -1
- package/dist/tools/contract-info.d.ts +0 -79
- package/dist/tools/contract-info.d.ts.map +0 -1
- package/dist/tools/contract-info.js +0 -450
- package/dist/tools/contract-info.js.map +0 -1
- package/dist/tools/contract.d.ts +0 -79
- package/dist/tools/contract.d.ts.map +0 -1
- package/dist/tools/contract.js +0 -140
- package/dist/tools/contract.js.map +0 -1
- package/dist/tools/index.d.ts +0 -3
- package/dist/tools/index.d.ts.map +0 -1
- package/dist/tools/index.js +0 -27
- package/dist/tools/index.js.map +0 -1
- package/dist/tools/logs.d.ts +0 -39
- package/dist/tools/logs.d.ts.map +0 -1
- package/dist/tools/logs.js +0 -231
- package/dist/tools/logs.js.map +0 -1
- package/dist/tools/signatures.d.ts +0 -83
- package/dist/tools/signatures.d.ts.map +0 -1
- package/dist/tools/signatures.js +0 -93
- package/dist/tools/signatures.js.map +0 -1
- package/dist/types.d.ts +0 -22
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/utils.d.ts +0 -22
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js +0 -183
- package/dist/utils.js.map +0 -1
package/src/tools/ens.ts
ADDED
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
import { type Address, isAddress, namehash } from "viem";
|
|
2
|
+
import { normalize } from "viem/ens";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import type { ChainName } from "../types.js";
|
|
5
|
+
import { getClientManager, SUPPORTED_CHAINS } from "../client.js";
|
|
6
|
+
import { createTool, formatResponse } from "../utils.js";
|
|
7
|
+
|
|
8
|
+
// Base ENS Contract Addresses
|
|
9
|
+
const BASE_ENS_CONTRACTS = {
|
|
10
|
+
registry: "0xb94704422c2a1e396835a571837aa5ae53285a95" as Address,
|
|
11
|
+
reverseRegistrar: "0x79ea96012eea67a83431f1701b3dff7e37f9e282" as Address,
|
|
12
|
+
l2Resolver: "0xC6d566A56A1aFf6508b41f6c90ff131615583BCD" as Address,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// Helper function for Base ENS reverse resolution
|
|
16
|
+
async function reverseResolveBase(address: Address): Promise<string | null> {
|
|
17
|
+
const clientManager = getClientManager();
|
|
18
|
+
const client = clientManager.getClient("base");
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
// Get the reverse node from ReverseRegistrar
|
|
22
|
+
const reverseNode = await client.readContract({
|
|
23
|
+
address: BASE_ENS_CONTRACTS.reverseRegistrar,
|
|
24
|
+
abi: [
|
|
25
|
+
{
|
|
26
|
+
name: "node",
|
|
27
|
+
type: "function",
|
|
28
|
+
stateMutability: "pure",
|
|
29
|
+
inputs: [{ name: "addr", type: "address" }],
|
|
30
|
+
outputs: [{ name: "", type: "bytes32" }],
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
functionName: "node",
|
|
34
|
+
args: [address],
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Query the L2Resolver for the name
|
|
38
|
+
const name = await client.readContract({
|
|
39
|
+
address: BASE_ENS_CONTRACTS.l2Resolver,
|
|
40
|
+
abi: [
|
|
41
|
+
{
|
|
42
|
+
name: "name",
|
|
43
|
+
type: "function",
|
|
44
|
+
stateMutability: "view",
|
|
45
|
+
inputs: [{ name: "node", type: "bytes32" }],
|
|
46
|
+
outputs: [{ name: "", type: "string" }],
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
functionName: "name",
|
|
50
|
+
args: [reverseNode as `0x${string}`],
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
return name || null;
|
|
54
|
+
} catch (error) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Helper function for Base ENS forward resolution
|
|
60
|
+
async function resolveNameBase(name: string): Promise<Address | null> {
|
|
61
|
+
const clientManager = getClientManager();
|
|
62
|
+
const client = clientManager.getClient("base");
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
const node = namehash(name);
|
|
66
|
+
|
|
67
|
+
// Get resolver from registry
|
|
68
|
+
const resolver = await client.readContract({
|
|
69
|
+
address: BASE_ENS_CONTRACTS.registry,
|
|
70
|
+
abi: [
|
|
71
|
+
{
|
|
72
|
+
name: "resolver",
|
|
73
|
+
type: "function",
|
|
74
|
+
stateMutability: "view",
|
|
75
|
+
inputs: [{ name: "node", type: "bytes32" }],
|
|
76
|
+
outputs: [{ name: "", type: "address" }],
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
functionName: "resolver",
|
|
80
|
+
args: [node],
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
if (!resolver || resolver === "0x0000000000000000000000000000000000000000") {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Get address from resolver
|
|
88
|
+
const address = await client.readContract({
|
|
89
|
+
address: resolver as Address,
|
|
90
|
+
abi: [
|
|
91
|
+
{
|
|
92
|
+
name: "addr",
|
|
93
|
+
type: "function",
|
|
94
|
+
stateMutability: "view",
|
|
95
|
+
inputs: [{ name: "node", type: "bytes32" }],
|
|
96
|
+
outputs: [{ name: "", type: "address" }],
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
functionName: "addr",
|
|
100
|
+
args: [node],
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
return address as Address | null;
|
|
104
|
+
} catch (error) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Helper function for Base ENS text records
|
|
110
|
+
async function getTextRecordBase(name: string, key: string): Promise<string | null> {
|
|
111
|
+
const clientManager = getClientManager();
|
|
112
|
+
const client = clientManager.getClient("base");
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
const node = namehash(name);
|
|
116
|
+
|
|
117
|
+
// Get resolver from registry
|
|
118
|
+
const resolver = await client.readContract({
|
|
119
|
+
address: BASE_ENS_CONTRACTS.registry,
|
|
120
|
+
abi: [
|
|
121
|
+
{
|
|
122
|
+
name: "resolver",
|
|
123
|
+
type: "function",
|
|
124
|
+
stateMutability: "view",
|
|
125
|
+
inputs: [{ name: "node", type: "bytes32" }],
|
|
126
|
+
outputs: [{ name: "", type: "address" }],
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
functionName: "resolver",
|
|
130
|
+
args: [node],
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
if (!resolver || resolver === "0x0000000000000000000000000000000000000000") {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Get text record from resolver
|
|
138
|
+
const textRecord = await client.readContract({
|
|
139
|
+
address: resolver as Address,
|
|
140
|
+
abi: [
|
|
141
|
+
{
|
|
142
|
+
name: "text",
|
|
143
|
+
type: "function",
|
|
144
|
+
stateMutability: "view",
|
|
145
|
+
inputs: [
|
|
146
|
+
{ name: "node", type: "bytes32" },
|
|
147
|
+
{ name: "key", type: "string" },
|
|
148
|
+
],
|
|
149
|
+
outputs: [{ name: "", type: "string" }],
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
functionName: "text",
|
|
153
|
+
args: [node, key],
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
return textRecord || null;
|
|
157
|
+
} catch (error) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const EnsResolveSchema = z.object({
|
|
163
|
+
chain: z
|
|
164
|
+
.enum(SUPPORTED_CHAINS)
|
|
165
|
+
.default("mainnet")
|
|
166
|
+
.describe("Blockchain network (defaults to mainnet, as ENS is primarily on Ethereum)"),
|
|
167
|
+
name: z
|
|
168
|
+
.string()
|
|
169
|
+
.describe("ENS name to resolve to an address (e.g., 'vitalik.eth', 'example.eth')"),
|
|
170
|
+
universalResolver: z
|
|
171
|
+
.boolean()
|
|
172
|
+
.optional()
|
|
173
|
+
.describe("Use universal resolver for cross-chain resolution (defaults to true)"),
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
const EnsReverseResolveSchema = z.object({
|
|
177
|
+
chain: z
|
|
178
|
+
.enum(SUPPORTED_CHAINS)
|
|
179
|
+
.default("mainnet")
|
|
180
|
+
.describe("Blockchain network (defaults to mainnet)"),
|
|
181
|
+
address: z.string().describe("Ethereum address to resolve to an ENS name"),
|
|
182
|
+
universalResolver: z
|
|
183
|
+
.boolean()
|
|
184
|
+
.optional()
|
|
185
|
+
.describe("Use universal resolver for cross-chain resolution (defaults to true)"),
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const EnsTextRecordSchema = z.object({
|
|
189
|
+
chain: z
|
|
190
|
+
.enum(SUPPORTED_CHAINS)
|
|
191
|
+
.default("mainnet")
|
|
192
|
+
.describe("Blockchain network (defaults to mainnet)"),
|
|
193
|
+
name: z.string().describe("ENS name to query text records from"),
|
|
194
|
+
key: z
|
|
195
|
+
.string()
|
|
196
|
+
.describe(
|
|
197
|
+
"Text record key (e.g., 'avatar', 'description', 'email', 'url', 'com.twitter', 'com.github')"
|
|
198
|
+
),
|
|
199
|
+
universalResolver: z
|
|
200
|
+
.boolean()
|
|
201
|
+
.optional()
|
|
202
|
+
.describe("Use universal resolver for cross-chain resolution (defaults to true)"),
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
const EnsBatchResolveSchema = z.object({
|
|
206
|
+
chain: z
|
|
207
|
+
.enum(SUPPORTED_CHAINS)
|
|
208
|
+
.default("mainnet")
|
|
209
|
+
.describe("Blockchain network (defaults to mainnet)"),
|
|
210
|
+
names: z
|
|
211
|
+
.array(z.string())
|
|
212
|
+
.describe("Array of ENS names to resolve to addresses in a single batch"),
|
|
213
|
+
universalResolver: z
|
|
214
|
+
.boolean()
|
|
215
|
+
.optional()
|
|
216
|
+
.describe("Use universal resolver for cross-chain resolution (defaults to true)"),
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
export default {
|
|
220
|
+
resolve_ens_name: createTool(
|
|
221
|
+
"Resolve ENS Name to Address",
|
|
222
|
+
"Resolve an ENS name to its Ethereum address. ENS names are human-readable identifiers (like vitalik.eth) that resolve to Ethereum addresses.",
|
|
223
|
+
EnsResolveSchema,
|
|
224
|
+
async (args) => {
|
|
225
|
+
try {
|
|
226
|
+
// Normalize the ENS name
|
|
227
|
+
const normalizedName = normalize(args.name);
|
|
228
|
+
|
|
229
|
+
let address: Address | null = null;
|
|
230
|
+
|
|
231
|
+
// Use Base-specific logic for Base chain
|
|
232
|
+
if (args.chain === "base") {
|
|
233
|
+
address = await resolveNameBase(normalizedName);
|
|
234
|
+
} else {
|
|
235
|
+
// Use viem's built-in ENS resolution for other chains
|
|
236
|
+
const clientManager = getClientManager();
|
|
237
|
+
const client = clientManager.getClient(args.chain as ChainName);
|
|
238
|
+
|
|
239
|
+
address = await client.getEnsAddress({
|
|
240
|
+
name: normalizedName,
|
|
241
|
+
universalResolverAddress: args.universalResolver !== false ? undefined : undefined,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (!address) {
|
|
246
|
+
return formatResponse({
|
|
247
|
+
success: false,
|
|
248
|
+
name: args.name,
|
|
249
|
+
normalizedName,
|
|
250
|
+
address: null,
|
|
251
|
+
chain: args.chain,
|
|
252
|
+
message: "ENS name does not resolve to an address",
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return formatResponse({
|
|
257
|
+
success: true,
|
|
258
|
+
name: args.name,
|
|
259
|
+
normalizedName,
|
|
260
|
+
address,
|
|
261
|
+
chain: args.chain,
|
|
262
|
+
});
|
|
263
|
+
} catch (error) {
|
|
264
|
+
throw new Error(`Failed to resolve ENS name: ${error}`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
),
|
|
268
|
+
|
|
269
|
+
reverse_resolve_ens: createTool(
|
|
270
|
+
"Reverse Resolve Address to ENS Name",
|
|
271
|
+
"Reverse resolve an Ethereum address to its primary ENS name. Returns the ENS name if the address has set a reverse record.",
|
|
272
|
+
EnsReverseResolveSchema,
|
|
273
|
+
async (args) => {
|
|
274
|
+
if (!isAddress(args.address)) {
|
|
275
|
+
throw new Error(`Invalid Ethereum address: ${args.address}`);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
try {
|
|
279
|
+
let ensName: string | null = null;
|
|
280
|
+
|
|
281
|
+
// Use Base-specific logic for Base chain
|
|
282
|
+
if (args.chain === "base") {
|
|
283
|
+
ensName = await reverseResolveBase(args.address as Address);
|
|
284
|
+
} else {
|
|
285
|
+
// Use viem's built-in ENS resolution for other chains
|
|
286
|
+
const clientManager = getClientManager();
|
|
287
|
+
const client = clientManager.getClient(args.chain as ChainName);
|
|
288
|
+
|
|
289
|
+
ensName = await client.getEnsName({
|
|
290
|
+
address: args.address as Address,
|
|
291
|
+
universalResolverAddress: args.universalResolver !== false ? undefined : undefined,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (!ensName) {
|
|
296
|
+
return formatResponse({
|
|
297
|
+
success: false,
|
|
298
|
+
address: args.address,
|
|
299
|
+
name: null,
|
|
300
|
+
chain: args.chain,
|
|
301
|
+
message: "Address does not have a primary ENS name set",
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return formatResponse({
|
|
306
|
+
success: true,
|
|
307
|
+
address: args.address,
|
|
308
|
+
name: ensName,
|
|
309
|
+
chain: args.chain,
|
|
310
|
+
});
|
|
311
|
+
} catch (error) {
|
|
312
|
+
throw new Error(`Failed to reverse resolve address: ${error}`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
),
|
|
316
|
+
|
|
317
|
+
get_ens_text_record: createTool(
|
|
318
|
+
"Get ENS Text Record",
|
|
319
|
+
"Retrieve a text record from an ENS name. Common keys include 'avatar', 'description', 'email', 'url', 'com.twitter', 'com.github'.",
|
|
320
|
+
EnsTextRecordSchema,
|
|
321
|
+
async (args) => {
|
|
322
|
+
try {
|
|
323
|
+
// Normalize the ENS name
|
|
324
|
+
const normalizedName = normalize(args.name);
|
|
325
|
+
|
|
326
|
+
let textRecord: string | null = null;
|
|
327
|
+
|
|
328
|
+
// Use Base-specific logic for Base chain
|
|
329
|
+
if (args.chain === "base") {
|
|
330
|
+
textRecord = await getTextRecordBase(normalizedName, args.key);
|
|
331
|
+
} else {
|
|
332
|
+
// Use viem's built-in ENS resolution for other chains
|
|
333
|
+
const clientManager = getClientManager();
|
|
334
|
+
const client = clientManager.getClient(args.chain as ChainName);
|
|
335
|
+
|
|
336
|
+
textRecord = await client.getEnsText({
|
|
337
|
+
name: normalizedName,
|
|
338
|
+
key: args.key,
|
|
339
|
+
universalResolverAddress: args.universalResolver !== false ? undefined : undefined,
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (!textRecord) {
|
|
344
|
+
return formatResponse({
|
|
345
|
+
success: false,
|
|
346
|
+
name: args.name,
|
|
347
|
+
normalizedName,
|
|
348
|
+
key: args.key,
|
|
349
|
+
value: null,
|
|
350
|
+
chain: args.chain,
|
|
351
|
+
message: `Text record '${args.key}' not found for ${args.name}`,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return formatResponse({
|
|
356
|
+
success: true,
|
|
357
|
+
name: args.name,
|
|
358
|
+
normalizedName,
|
|
359
|
+
key: args.key,
|
|
360
|
+
value: textRecord,
|
|
361
|
+
chain: args.chain,
|
|
362
|
+
});
|
|
363
|
+
} catch (error) {
|
|
364
|
+
throw new Error(`Failed to get ENS text record: ${error}`);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
),
|
|
368
|
+
|
|
369
|
+
get_ens_avatar: createTool(
|
|
370
|
+
"Get ENS Avatar",
|
|
371
|
+
"Get the avatar URI for an ENS name. Returns the avatar URL if set.",
|
|
372
|
+
z.object({
|
|
373
|
+
chain: z
|
|
374
|
+
.enum(SUPPORTED_CHAINS)
|
|
375
|
+
.default("mainnet")
|
|
376
|
+
.describe("Blockchain network (defaults to mainnet)"),
|
|
377
|
+
name: z.string().describe("ENS name to get avatar from"),
|
|
378
|
+
universalResolver: z
|
|
379
|
+
.boolean()
|
|
380
|
+
.optional()
|
|
381
|
+
.describe("Use universal resolver for cross-chain resolution (defaults to true)"),
|
|
382
|
+
}),
|
|
383
|
+
async (args) => {
|
|
384
|
+
try {
|
|
385
|
+
// Normalize the ENS name
|
|
386
|
+
const normalizedName = normalize(args.name);
|
|
387
|
+
|
|
388
|
+
let avatar: string | null = null;
|
|
389
|
+
|
|
390
|
+
// Use Base-specific logic for Base chain
|
|
391
|
+
if (args.chain === "base") {
|
|
392
|
+
avatar = await getTextRecordBase(normalizedName, "avatar");
|
|
393
|
+
} else {
|
|
394
|
+
// Use viem's built-in ENS resolution for other chains
|
|
395
|
+
const clientManager = getClientManager();
|
|
396
|
+
const client = clientManager.getClient(args.chain as ChainName);
|
|
397
|
+
|
|
398
|
+
avatar = await client.getEnsAvatar({
|
|
399
|
+
name: normalizedName,
|
|
400
|
+
universalResolverAddress: args.universalResolver !== false ? undefined : undefined,
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (!avatar) {
|
|
405
|
+
return formatResponse({
|
|
406
|
+
success: false,
|
|
407
|
+
name: args.name,
|
|
408
|
+
normalizedName,
|
|
409
|
+
avatar: null,
|
|
410
|
+
chain: args.chain,
|
|
411
|
+
message: `No avatar set for ${args.name}`,
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
return formatResponse({
|
|
416
|
+
success: true,
|
|
417
|
+
name: args.name,
|
|
418
|
+
normalizedName,
|
|
419
|
+
avatar,
|
|
420
|
+
chain: args.chain,
|
|
421
|
+
});
|
|
422
|
+
} catch (error) {
|
|
423
|
+
throw new Error(`Failed to get ENS avatar: ${error}`);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
),
|
|
427
|
+
|
|
428
|
+
batch_resolve_ens_names: createTool(
|
|
429
|
+
"Batch Resolve ENS Names",
|
|
430
|
+
"Resolve multiple ENS names to addresses in a single batch for efficiency.",
|
|
431
|
+
EnsBatchResolveSchema,
|
|
432
|
+
async (args) => {
|
|
433
|
+
try {
|
|
434
|
+
// Resolve all ENS names in parallel
|
|
435
|
+
const results = await Promise.allSettled(
|
|
436
|
+
args.names.map(async (name) => {
|
|
437
|
+
const normalizedName = normalize(name);
|
|
438
|
+
let address: Address | null = null;
|
|
439
|
+
|
|
440
|
+
// Use Base-specific logic for Base chain
|
|
441
|
+
if (args.chain === "base") {
|
|
442
|
+
address = await resolveNameBase(normalizedName);
|
|
443
|
+
} else {
|
|
444
|
+
// Use viem's built-in ENS resolution for other chains
|
|
445
|
+
const clientManager = getClientManager();
|
|
446
|
+
const client = clientManager.getClient(args.chain as ChainName);
|
|
447
|
+
|
|
448
|
+
address = await client.getEnsAddress({
|
|
449
|
+
name: normalizedName,
|
|
450
|
+
universalResolverAddress: args.universalResolver !== false ? undefined : undefined,
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
return {
|
|
455
|
+
name,
|
|
456
|
+
normalizedName,
|
|
457
|
+
address,
|
|
458
|
+
success: !!address,
|
|
459
|
+
};
|
|
460
|
+
})
|
|
461
|
+
);
|
|
462
|
+
|
|
463
|
+
// Process results
|
|
464
|
+
const resolved = results.map((result, index) => {
|
|
465
|
+
if (result.status === "fulfilled") {
|
|
466
|
+
return result.value;
|
|
467
|
+
}
|
|
468
|
+
return {
|
|
469
|
+
name: args.names[index],
|
|
470
|
+
normalizedName: args.names[index],
|
|
471
|
+
address: null,
|
|
472
|
+
success: false,
|
|
473
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
474
|
+
};
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
const successCount = resolved.filter((r) => r.success).length;
|
|
478
|
+
const failCount = resolved.filter((r) => !r.success).length;
|
|
479
|
+
|
|
480
|
+
return formatResponse({
|
|
481
|
+
success: true,
|
|
482
|
+
chain: args.chain,
|
|
483
|
+
totalNames: args.names.length,
|
|
484
|
+
successfulResolves: successCount,
|
|
485
|
+
failedResolves: failCount,
|
|
486
|
+
results: resolved,
|
|
487
|
+
});
|
|
488
|
+
} catch (error) {
|
|
489
|
+
throw new Error(`Failed to batch resolve ENS names: ${error}`);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
),
|
|
493
|
+
};
|
package/src/tools/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import advancedTools from './advanced.js'
|
|
|
5
5
|
import balanceTools from './balance.js'
|
|
6
6
|
import contractTools from './contract.js'
|
|
7
7
|
import contractInfoTools from './contract-info.js'
|
|
8
|
+
import ensTools from './ens.js'
|
|
8
9
|
import logTools from './logs.js'
|
|
9
10
|
import signatureTools from './signatures.js'
|
|
10
11
|
|
|
@@ -14,7 +15,8 @@ const allToolDefinitions = {
|
|
|
14
15
|
...contractInfoTools,
|
|
15
16
|
...balanceTools,
|
|
16
17
|
...logTools,
|
|
17
|
-
...advancedTools
|
|
18
|
+
...advancedTools,
|
|
19
|
+
...ensTools
|
|
18
20
|
} as const
|
|
19
21
|
|
|
20
22
|
// Register all tools with the MCP server
|