@mcp-dockmaster/mcp-cryptowallet-evm 1.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.
- package/.eslintrc/index.js +12 -0
- package/LICENSE +21 -0
- package/README.md +179 -0
- package/build/handlers/utils.d.ts +29 -0
- package/build/handlers/utils.js +86 -0
- package/build/handlers/utils.js.map +1 -0
- package/build/handlers/wallet.d.ts +36 -0
- package/build/handlers/wallet.js +781 -0
- package/build/handlers/wallet.js.map +1 -0
- package/build/handlers/wallet.types.d.ts +14 -0
- package/build/handlers/wallet.types.js +2 -0
- package/build/handlers/wallet.types.js.map +1 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +32 -0
- package/build/index.js.map +1 -0
- package/build/tools.d.ts +1143 -0
- package/build/tools.js +571 -0
- package/build/tools.js.map +1 -0
- package/build/types.d.ts +20 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/jest.config.js +17 -0
- package/package.json +48 -0
- package/required-methods.md +53 -0
- package/src/handlers/utils.ts +97 -0
- package/src/handlers/wallet.ts +901 -0
- package/src/handlers/wallet.types.ts +16 -0
- package/src/index.ts +40 -0
- package/src/tools.ts +621 -0
- package/src/types.ts +21 -0
- package/tests/handlers/network.test.ts +73 -0
- package/tests/handlers/provider.test.ts +197 -0
- package/tests/handlers/wallet.test.ts +289 -0
- package/tsconfig.json +17 -0
@@ -0,0 +1,781 @@
|
|
1
|
+
import { ethers } from "ethers";
|
2
|
+
import { createSuccessResponse, createErrorResponse, getProvider, getWallet } from "./utils.js";
|
3
|
+
import { generateMnemonic, } from '@scure/bip39';
|
4
|
+
// Wallet Creation and Management
|
5
|
+
export const createWalletHandler = async (input) => {
|
6
|
+
try {
|
7
|
+
const options = {};
|
8
|
+
if (input.path) {
|
9
|
+
options.path = input.path;
|
10
|
+
}
|
11
|
+
if (input.locale) {
|
12
|
+
options.locale = input.locale;
|
13
|
+
}
|
14
|
+
const wallet = ethers.Wallet.createRandom(options);
|
15
|
+
let result = {
|
16
|
+
address: wallet.address,
|
17
|
+
mnemonic: wallet.mnemonic?.phrase,
|
18
|
+
privateKey: wallet.privateKey,
|
19
|
+
publicKey: wallet.publicKey
|
20
|
+
};
|
21
|
+
if (input.password) {
|
22
|
+
// If a password is provided, encrypt the wallet
|
23
|
+
const encryptedWallet = await wallet.encrypt(input.password);
|
24
|
+
result.encryptedWallet = encryptedWallet;
|
25
|
+
}
|
26
|
+
return createSuccessResponse(result, `Wallet created successfully:
|
27
|
+
Address: ${wallet.address}
|
28
|
+
Private Key: ${wallet.privateKey}
|
29
|
+
Public Key: ${wallet.publicKey}
|
30
|
+
Mnemonic: ${wallet.mnemonic?.phrase}
|
31
|
+
Encrypted Wallet: ${result.encryptedWallet ? "Yes" : "No"}
|
32
|
+
`);
|
33
|
+
}
|
34
|
+
catch (error) {
|
35
|
+
return createErrorResponse(`Failed to create wallet: ${error.message}`);
|
36
|
+
}
|
37
|
+
};
|
38
|
+
export const fromPrivateKeyHandler = async (input) => {
|
39
|
+
try {
|
40
|
+
if (!input.privateKey) {
|
41
|
+
return createErrorResponse("Private key is required");
|
42
|
+
}
|
43
|
+
const provider = input.provider ? getProvider(input.provider) : undefined;
|
44
|
+
const wallet = new ethers.Wallet(input.privateKey, provider);
|
45
|
+
return createSuccessResponse({
|
46
|
+
address: wallet.address,
|
47
|
+
privateKey: wallet.privateKey,
|
48
|
+
publicKey: wallet.publicKey
|
49
|
+
}, `Wallet created from private key successfully:
|
50
|
+
Address: ${wallet.address}
|
51
|
+
Private Key: ${wallet.privateKey}
|
52
|
+
Public Key: ${wallet.publicKey}
|
53
|
+
`);
|
54
|
+
}
|
55
|
+
catch (error) {
|
56
|
+
return createErrorResponse(`Failed to create wallet from private key: ${error.message}`);
|
57
|
+
}
|
58
|
+
};
|
59
|
+
export const createMnemonicPhraseHandler = async (input) => {
|
60
|
+
try {
|
61
|
+
const { wordlist } = await import(`@scure/bip39/wordlists/${input.locale || 'english'}`);
|
62
|
+
if (!wordlist) {
|
63
|
+
return createErrorResponse("Invalid locale");
|
64
|
+
}
|
65
|
+
// Convert length to entropy bits (12 words = 128 bits, 15 words = 160 bits, etc)
|
66
|
+
const entropyBits = ((input.length ?? 12) / 3) * 32;
|
67
|
+
const mnemonic = generateMnemonic(wordlist, entropyBits);
|
68
|
+
return createSuccessResponse({
|
69
|
+
mnemonic: mnemonic
|
70
|
+
}, `Mnemonic phrase created successfully:
|
71
|
+
Mnemonic: "${mnemonic}"
|
72
|
+
`);
|
73
|
+
}
|
74
|
+
catch (error) {
|
75
|
+
return createErrorResponse(`Failed to create mnemonic phrase: ${error.message}`);
|
76
|
+
}
|
77
|
+
};
|
78
|
+
export const fromMnemonicHandler = async (input) => {
|
79
|
+
try {
|
80
|
+
if (!input.mnemonic) {
|
81
|
+
return createErrorResponse("Mnemonic is required");
|
82
|
+
}
|
83
|
+
const options = {
|
84
|
+
path: input.path,
|
85
|
+
wordlist: (input.locale && ethers.wordlists[input.locale]) || ethers.wordlists.en
|
86
|
+
};
|
87
|
+
const provider = input.provider ? getProvider(input.provider) : undefined;
|
88
|
+
const wallet = ethers.Wallet.fromMnemonic(input.mnemonic, options.path, options.wordlist);
|
89
|
+
if (provider)
|
90
|
+
wallet.connect(provider);
|
91
|
+
return createSuccessResponse({
|
92
|
+
address: wallet.address,
|
93
|
+
mnemonic: wallet.mnemonic?.phrase,
|
94
|
+
privateKey: wallet.privateKey,
|
95
|
+
publicKey: wallet.publicKey
|
96
|
+
}, `Wallet created from mnemonic successfully:
|
97
|
+
Address: ${wallet.address}
|
98
|
+
Private Key: ${wallet.privateKey}
|
99
|
+
Public Key: ${wallet.publicKey}
|
100
|
+
`);
|
101
|
+
}
|
102
|
+
catch (error) {
|
103
|
+
return createErrorResponse(`Failed to create wallet from mnemonic: ${error.message}`);
|
104
|
+
}
|
105
|
+
};
|
106
|
+
export const fromEncryptedJsonHandler = async (input) => {
|
107
|
+
try {
|
108
|
+
if (!input.json) {
|
109
|
+
return createErrorResponse("Encrypted JSON is required");
|
110
|
+
}
|
111
|
+
if (!input.password) {
|
112
|
+
return createErrorResponse("Password is required");
|
113
|
+
}
|
114
|
+
const wallet = await ethers.Wallet.fromEncryptedJson(input.json, input.password);
|
115
|
+
const provider = input.provider ? getProvider(input.provider) : undefined;
|
116
|
+
if (provider) {
|
117
|
+
wallet.connect(provider);
|
118
|
+
}
|
119
|
+
return createSuccessResponse({
|
120
|
+
address: wallet.address,
|
121
|
+
privateKey: wallet.privateKey,
|
122
|
+
publicKey: wallet.publicKey
|
123
|
+
}, "Wallet created from encrypted JSON successfully");
|
124
|
+
}
|
125
|
+
catch (error) {
|
126
|
+
return createErrorResponse(`Failed to create wallet from encrypted JSON: ${error.message}`);
|
127
|
+
}
|
128
|
+
};
|
129
|
+
export const encryptWalletHandler = async (input) => {
|
130
|
+
try {
|
131
|
+
if (!input.wallet) {
|
132
|
+
return createErrorResponse("Wallet is required");
|
133
|
+
}
|
134
|
+
if (!input.password) {
|
135
|
+
return createErrorResponse("Password is required");
|
136
|
+
}
|
137
|
+
const wallet = await getWallet(input.wallet);
|
138
|
+
const encryptedWallet = await wallet.encrypt(input.password, input.options);
|
139
|
+
return createSuccessResponse({
|
140
|
+
encryptedWallet
|
141
|
+
}, "Wallet encrypted successfully");
|
142
|
+
}
|
143
|
+
catch (error) {
|
144
|
+
return createErrorResponse(`Failed to encrypt wallet: ${error.message}`);
|
145
|
+
}
|
146
|
+
};
|
147
|
+
// Wallet Properties
|
148
|
+
export const getAddressHandler = async (input) => {
|
149
|
+
try {
|
150
|
+
if (!input.wallet) {
|
151
|
+
return createErrorResponse("Wallet is required");
|
152
|
+
}
|
153
|
+
const wallet = await getWallet(input.wallet);
|
154
|
+
return createSuccessResponse({
|
155
|
+
address: wallet.address
|
156
|
+
}, "Wallet address retrieved successfully");
|
157
|
+
}
|
158
|
+
catch (error) {
|
159
|
+
return createErrorResponse(`Failed to get wallet address: ${error.message}`);
|
160
|
+
}
|
161
|
+
};
|
162
|
+
export const getPublicKeyHandler = async (input) => {
|
163
|
+
try {
|
164
|
+
if (!input.wallet) {
|
165
|
+
return createErrorResponse("Wallet is required");
|
166
|
+
}
|
167
|
+
const wallet = await getWallet(input.wallet);
|
168
|
+
return createSuccessResponse({
|
169
|
+
publicKey: wallet.publicKey
|
170
|
+
}, "Wallet public key retrieved successfully");
|
171
|
+
}
|
172
|
+
catch (error) {
|
173
|
+
return createErrorResponse(`Failed to get wallet public key: ${error.message}`);
|
174
|
+
}
|
175
|
+
};
|
176
|
+
export const getPrivateKeyHandler = async (input) => {
|
177
|
+
try {
|
178
|
+
if (!input.wallet) {
|
179
|
+
return createErrorResponse("Wallet is required");
|
180
|
+
}
|
181
|
+
const wallet = await getWallet(input.wallet, input.password);
|
182
|
+
return createSuccessResponse({
|
183
|
+
privateKey: wallet.privateKey
|
184
|
+
}, "WARNING: Never share your private key with anyone. Wallet private key retrieved successfully");
|
185
|
+
}
|
186
|
+
catch (error) {
|
187
|
+
return createErrorResponse(`Failed to get wallet private key: ${error.message}`);
|
188
|
+
}
|
189
|
+
};
|
190
|
+
// Blockchain Methods
|
191
|
+
export const getBalanceHandler = async (input) => {
|
192
|
+
try {
|
193
|
+
if (!input.wallet) {
|
194
|
+
return createErrorResponse("Wallet is required");
|
195
|
+
}
|
196
|
+
if (!input.provider) {
|
197
|
+
return createErrorResponse("Provider URL is required to get balance");
|
198
|
+
}
|
199
|
+
const wallet = await getWallet(input.wallet, input.password, input.provider);
|
200
|
+
const balance = await wallet.getBalance(input.blockTag ?? "latest");
|
201
|
+
return createSuccessResponse({
|
202
|
+
balance: balance.toString(),
|
203
|
+
balanceInEth: ethers.utils.formatEther(balance)
|
204
|
+
}, `Wallet balance retrieved successfully
|
205
|
+
Balance: ${balance.toString()}
|
206
|
+
Balance in ETH: ${ethers.utils.formatEther(balance)}
|
207
|
+
`);
|
208
|
+
}
|
209
|
+
catch (error) {
|
210
|
+
return createErrorResponse(`Failed to get wallet balance: ${error.message}`);
|
211
|
+
}
|
212
|
+
};
|
213
|
+
export const getChainIdHandler = async (input) => {
|
214
|
+
try {
|
215
|
+
if (!input.wallet) {
|
216
|
+
return createErrorResponse("Wallet is required");
|
217
|
+
}
|
218
|
+
const wallet = await getWallet(input.wallet, input.password, input.provider);
|
219
|
+
if (!wallet.provider) {
|
220
|
+
return createErrorResponse("Provider is required to get chain ID");
|
221
|
+
}
|
222
|
+
const chainId = await wallet.getChainId();
|
223
|
+
return createSuccessResponse({
|
224
|
+
chainId
|
225
|
+
}, `Chain ID retrieved successfully
|
226
|
+
Chain ID: ${chainId.toString()}
|
227
|
+
`);
|
228
|
+
}
|
229
|
+
catch (error) {
|
230
|
+
return createErrorResponse(`Failed to get chain ID: ${error.message}`);
|
231
|
+
}
|
232
|
+
};
|
233
|
+
export const getGasPriceHandler = async (input) => {
|
234
|
+
try {
|
235
|
+
if (!input.wallet) {
|
236
|
+
return createErrorResponse("Wallet is required");
|
237
|
+
}
|
238
|
+
const wallet = await getWallet(input.wallet, input.password, input.provider);
|
239
|
+
if (!wallet.provider) {
|
240
|
+
return createErrorResponse("Provider is required to get gas price");
|
241
|
+
}
|
242
|
+
const gasPrice = await wallet.getGasPrice();
|
243
|
+
return createSuccessResponse({
|
244
|
+
gasPrice: gasPrice.toString(),
|
245
|
+
gasPriceInGwei: ethers.utils.formatUnits(gasPrice, "gwei")
|
246
|
+
}, `Gas price retrieved successfully
|
247
|
+
Gas price: ${gasPrice.toString()}
|
248
|
+
Gas price in Gwei: ${ethers.utils.formatUnits(gasPrice, "gwei")}
|
249
|
+
`);
|
250
|
+
}
|
251
|
+
catch (error) {
|
252
|
+
return createErrorResponse(`Failed to get gas price: ${error.message}`);
|
253
|
+
}
|
254
|
+
};
|
255
|
+
export const getTransactionCountHandler = async (input) => {
|
256
|
+
try {
|
257
|
+
if (!input.wallet) {
|
258
|
+
return createErrorResponse("Wallet is required");
|
259
|
+
}
|
260
|
+
const wallet = await getWallet(input.wallet, input.password, input.provider);
|
261
|
+
if (!wallet.provider) {
|
262
|
+
return createErrorResponse("Provider is required to get transaction count");
|
263
|
+
}
|
264
|
+
const transactionCount = await wallet.getTransactionCount(input.blockTag);
|
265
|
+
return createSuccessResponse({
|
266
|
+
transactionCount
|
267
|
+
}, `Transaction count retrieved successfully
|
268
|
+
Transaction count: ${transactionCount.toString()}
|
269
|
+
`);
|
270
|
+
}
|
271
|
+
catch (error) {
|
272
|
+
return createErrorResponse(`Failed to get transaction count: ${error.message}`);
|
273
|
+
}
|
274
|
+
};
|
275
|
+
export const callHandler = async (input) => {
|
276
|
+
try {
|
277
|
+
if (!input.wallet) {
|
278
|
+
return createErrorResponse("Wallet is required");
|
279
|
+
}
|
280
|
+
if (!input.transaction) {
|
281
|
+
return createErrorResponse("Transaction is required");
|
282
|
+
}
|
283
|
+
const wallet = await getWallet(input.wallet, input.password, input.provider);
|
284
|
+
if (!wallet.provider) {
|
285
|
+
return createErrorResponse("Provider is required to call a contract");
|
286
|
+
}
|
287
|
+
const result = await wallet.call(input.transaction, input.blockTag);
|
288
|
+
return createSuccessResponse({
|
289
|
+
result
|
290
|
+
}, `Contract call executed successfully
|
291
|
+
Result: ${result}
|
292
|
+
`);
|
293
|
+
}
|
294
|
+
catch (error) {
|
295
|
+
return createErrorResponse(`Failed to call contract: ${error.message}`);
|
296
|
+
}
|
297
|
+
};
|
298
|
+
// Transaction Methods
|
299
|
+
export const sendTransactionHandler = async (input) => {
|
300
|
+
try {
|
301
|
+
if (!input.wallet) {
|
302
|
+
return createErrorResponse("Wallet is required");
|
303
|
+
}
|
304
|
+
if (!input.transaction) {
|
305
|
+
return createErrorResponse("Transaction is required");
|
306
|
+
}
|
307
|
+
const wallet = await getWallet(input.wallet, input.password, input.provider);
|
308
|
+
if (!wallet.provider) {
|
309
|
+
return createErrorResponse("Provider is required to send a transaction");
|
310
|
+
}
|
311
|
+
const tx = await wallet.sendTransaction(input.transaction);
|
312
|
+
return createSuccessResponse({
|
313
|
+
hash: tx.hash,
|
314
|
+
nonce: tx.nonce,
|
315
|
+
gasLimit: tx.gasLimit.toString(),
|
316
|
+
gasPrice: tx.gasPrice?.toString(),
|
317
|
+
data: tx.data,
|
318
|
+
value: tx.value.toString(),
|
319
|
+
chainId: tx.chainId,
|
320
|
+
from: tx.from,
|
321
|
+
to: tx.to,
|
322
|
+
type: tx.type
|
323
|
+
}, `Transaction sent successfully
|
324
|
+
Hash: ${tx.hash}
|
325
|
+
Nonce: ${tx.nonce.toString()}
|
326
|
+
Gas limit: ${tx.gasLimit.toString()}
|
327
|
+
Gas price: ${tx.gasPrice?.toString()}
|
328
|
+
Data: ${tx.data}
|
329
|
+
`);
|
330
|
+
}
|
331
|
+
catch (error) {
|
332
|
+
return createErrorResponse(`Failed to send transaction: ${error.message}`);
|
333
|
+
}
|
334
|
+
};
|
335
|
+
export const signTransactionHandler = async (input) => {
|
336
|
+
try {
|
337
|
+
if (!input.wallet) {
|
338
|
+
return createErrorResponse("Wallet is required");
|
339
|
+
}
|
340
|
+
if (!input.transaction) {
|
341
|
+
return createErrorResponse("Transaction is required");
|
342
|
+
}
|
343
|
+
const wallet = await getWallet(input.wallet, input.password, input.provider);
|
344
|
+
// For signing a transaction, we need to populate it first
|
345
|
+
const populatedTx = await wallet.populateTransaction(input.transaction);
|
346
|
+
const signedTx = await wallet.signTransaction(populatedTx);
|
347
|
+
return createSuccessResponse({
|
348
|
+
signedTransaction: signedTx
|
349
|
+
}, `Transaction signed successfully
|
350
|
+
Signed transaction: ${signedTx}
|
351
|
+
`);
|
352
|
+
}
|
353
|
+
catch (error) {
|
354
|
+
return createErrorResponse(`Failed to sign transaction: ${error.message}`);
|
355
|
+
}
|
356
|
+
};
|
357
|
+
export const populateTransactionHandler = async (input) => {
|
358
|
+
try {
|
359
|
+
if (!input.wallet) {
|
360
|
+
return createErrorResponse("Wallet is required");
|
361
|
+
}
|
362
|
+
if (!input.transaction) {
|
363
|
+
return createErrorResponse("Transaction is required");
|
364
|
+
}
|
365
|
+
const wallet = await getWallet(input.wallet, input.password, input.provider);
|
366
|
+
if (!wallet.provider) {
|
367
|
+
return createErrorResponse("Provider is required to populate a transaction");
|
368
|
+
}
|
369
|
+
const populatedTx = await wallet.populateTransaction(input.transaction);
|
370
|
+
return createSuccessResponse({
|
371
|
+
populatedTransaction: {
|
372
|
+
to: populatedTx.to,
|
373
|
+
from: populatedTx.from,
|
374
|
+
nonce: populatedTx.nonce,
|
375
|
+
gasLimit: populatedTx.gasLimit?.toString(),
|
376
|
+
gasPrice: populatedTx.gasPrice?.toString(),
|
377
|
+
data: populatedTx.data,
|
378
|
+
value: populatedTx.value?.toString(),
|
379
|
+
chainId: populatedTx.chainId,
|
380
|
+
type: populatedTx.type,
|
381
|
+
maxFeePerGas: populatedTx.maxFeePerGas?.toString(),
|
382
|
+
maxPriorityFeePerGas: populatedTx.maxPriorityFeePerGas?.toString()
|
383
|
+
}
|
384
|
+
}, `Transaction populated successfully
|
385
|
+
To: ${populatedTx.to}
|
386
|
+
From: ${populatedTx.from}
|
387
|
+
Nonce: ${populatedTx.nonce?.toString() ?? "Not specified"}
|
388
|
+
Gas limit: ${populatedTx.gasLimit?.toString() ?? "Not specified"}
|
389
|
+
Gas price: ${populatedTx.gasPrice?.toString() ?? "Not specified"}
|
390
|
+
`);
|
391
|
+
}
|
392
|
+
catch (error) {
|
393
|
+
return createErrorResponse(`Failed to populate transaction: ${error.message}`);
|
394
|
+
}
|
395
|
+
};
|
396
|
+
// Signing Methods
|
397
|
+
export const signMessageHandler = async (input) => {
|
398
|
+
try {
|
399
|
+
if (!input.wallet) {
|
400
|
+
return createErrorResponse("Wallet is required");
|
401
|
+
}
|
402
|
+
if (!input.message) {
|
403
|
+
return createErrorResponse("Message is required");
|
404
|
+
}
|
405
|
+
const wallet = await getWallet(input.wallet, input.password);
|
406
|
+
const signature = await wallet.signMessage(input.message);
|
407
|
+
return createSuccessResponse({
|
408
|
+
signature,
|
409
|
+
message: input.message
|
410
|
+
}, `Message signed successfully
|
411
|
+
Signature: ${signature}
|
412
|
+
Message: "${input.message}"
|
413
|
+
`);
|
414
|
+
}
|
415
|
+
catch (error) {
|
416
|
+
return createErrorResponse(`Failed to sign message: ${error.message}`);
|
417
|
+
}
|
418
|
+
};
|
419
|
+
export const signTypedDataHandler = async (input) => {
|
420
|
+
try {
|
421
|
+
if (!input.wallet) {
|
422
|
+
return createErrorResponse("Wallet is required");
|
423
|
+
}
|
424
|
+
if (!input.domain || !input.types || !input.value) {
|
425
|
+
return createErrorResponse("Domain, types, and value are required");
|
426
|
+
}
|
427
|
+
const wallet = await getWallet(input.wallet, input.password);
|
428
|
+
// Use ethers._signTypedData for EIP-712 signing
|
429
|
+
// @ts-ignore - _signTypedData is not in the type definitions but is available
|
430
|
+
const signature = await wallet._signTypedData(input.domain, input.types, input.value);
|
431
|
+
return createSuccessResponse({
|
432
|
+
signature,
|
433
|
+
domain: input.domain,
|
434
|
+
types: input.types,
|
435
|
+
value: input.value
|
436
|
+
}, `Typed data signed successfully
|
437
|
+
Signature: ${signature}
|
438
|
+
Domain: ${input.domain}
|
439
|
+
Types: ${input.types}
|
440
|
+
Value: ${input.value}
|
441
|
+
`);
|
442
|
+
}
|
443
|
+
catch (error) {
|
444
|
+
return createErrorResponse(`Failed to sign typed data: ${error.message}`);
|
445
|
+
}
|
446
|
+
};
|
447
|
+
export const verifyMessageHandler = async (input) => {
|
448
|
+
try {
|
449
|
+
if (!input.message || !input.signature || !input.address) {
|
450
|
+
return createErrorResponse("Message, signature, and address are required");
|
451
|
+
}
|
452
|
+
const recoveredAddress = ethers.utils.verifyMessage(input.message, input.signature);
|
453
|
+
const isValid = recoveredAddress.toLowerCase() === input.address.toLowerCase();
|
454
|
+
return createSuccessResponse({
|
455
|
+
isValid,
|
456
|
+
recoveredAddress
|
457
|
+
}, isValid ? `Signature verified successfully
|
458
|
+
Message: "${input.message}"
|
459
|
+
Signature: ${input.signature}
|
460
|
+
Address: ${input.address}
|
461
|
+
` : `Signature verification failed
|
462
|
+
Message: "${input.message}"
|
463
|
+
Signature: ${input.signature}
|
464
|
+
Address: ${input.address}
|
465
|
+
`);
|
466
|
+
}
|
467
|
+
catch (error) {
|
468
|
+
return createErrorResponse(`Failed to verify message: ${error.message}`);
|
469
|
+
}
|
470
|
+
};
|
471
|
+
export const verifyTypedDataHandler = async (input) => {
|
472
|
+
try {
|
473
|
+
if (!input.domain || !input.types || !input.value || !input.signature || !input.address) {
|
474
|
+
return createErrorResponse("Domain, types, value, signature, and address are required");
|
475
|
+
}
|
476
|
+
// Use ethers.utils.verifyTypedData for EIP-712 verification
|
477
|
+
const recoveredAddress = ethers.utils.verifyTypedData(input.domain, input.types, input.value, input.signature);
|
478
|
+
const isValid = recoveredAddress.toLowerCase() === input.address.toLowerCase();
|
479
|
+
return createSuccessResponse({
|
480
|
+
isValid,
|
481
|
+
recoveredAddress
|
482
|
+
}, isValid ? `Typed data signature is valid
|
483
|
+
Domain: ${input.domain}
|
484
|
+
Types: ${input.types}
|
485
|
+
Value: ${input.value}
|
486
|
+
Signature: ${input.signature}
|
487
|
+
Address: ${input.address}
|
488
|
+
` : "Typed data signature is invalid");
|
489
|
+
}
|
490
|
+
catch (error) {
|
491
|
+
return createErrorResponse(`Failed to verify typed data: ${error.message}`);
|
492
|
+
}
|
493
|
+
};
|
494
|
+
// Provider Methods
|
495
|
+
export const getBlockHandler = async (input) => {
|
496
|
+
try {
|
497
|
+
if (!input.provider) {
|
498
|
+
return createErrorResponse("Provider is required");
|
499
|
+
}
|
500
|
+
if (!input.blockHashOrBlockTag) {
|
501
|
+
return createErrorResponse("Block hash or block tag is required");
|
502
|
+
}
|
503
|
+
const provider = getProvider(input.provider);
|
504
|
+
// In ethers.js v5, getBlock can take includeTransactions as a second parameter
|
505
|
+
// but TypeScript definitions might not reflect this
|
506
|
+
const block = await provider.getBlock(input.blockHashOrBlockTag, input.includeTransactions);
|
507
|
+
return createSuccessResponse({
|
508
|
+
block
|
509
|
+
}, `Block retrieved successfully
|
510
|
+
Block hash: ${block.hash}
|
511
|
+
Block number: ${block.number?.toString() ?? "Not specified"}
|
512
|
+
Block timestamp: ${block.timestamp?.toString() ?? "Not specified"}
|
513
|
+
Block transactions: ${block.transactions?.length ?? "Not specified"}
|
514
|
+
`);
|
515
|
+
}
|
516
|
+
catch (error) {
|
517
|
+
return createErrorResponse(`Failed to get block: ${error.message}`);
|
518
|
+
}
|
519
|
+
};
|
520
|
+
export const getTransactionHandler = async (input) => {
|
521
|
+
try {
|
522
|
+
if (!input.provider) {
|
523
|
+
return createErrorResponse("Provider is required");
|
524
|
+
}
|
525
|
+
if (!input.transactionHash) {
|
526
|
+
return createErrorResponse("Transaction hash is required");
|
527
|
+
}
|
528
|
+
const provider = getProvider(input.provider);
|
529
|
+
const transaction = await provider.getTransaction(input.transactionHash);
|
530
|
+
return createSuccessResponse({
|
531
|
+
transaction
|
532
|
+
}, `Transaction retrieved successfully
|
533
|
+
Transaction hash: ${input.transactionHash}
|
534
|
+
Transaction: ${transaction}
|
535
|
+
`);
|
536
|
+
}
|
537
|
+
catch (error) {
|
538
|
+
return createErrorResponse(`Failed to get transaction: ${error.message}`);
|
539
|
+
}
|
540
|
+
};
|
541
|
+
export const getTransactionReceiptHandler = async (input) => {
|
542
|
+
try {
|
543
|
+
if (!input.provider) {
|
544
|
+
return createErrorResponse("Provider is required");
|
545
|
+
}
|
546
|
+
if (!input.transactionHash) {
|
547
|
+
return createErrorResponse("Transaction hash is required");
|
548
|
+
}
|
549
|
+
const provider = getProvider(input.provider);
|
550
|
+
const receipt = await provider.getTransactionReceipt(input.transactionHash);
|
551
|
+
return createSuccessResponse({
|
552
|
+
receipt
|
553
|
+
}, `Transaction receipt retrieved successfully
|
554
|
+
Transaction hash: ${input.transactionHash}
|
555
|
+
Transaction receipt: ${receipt}
|
556
|
+
`);
|
557
|
+
}
|
558
|
+
catch (error) {
|
559
|
+
return createErrorResponse(`Failed to get transaction receipt: ${error.message}`);
|
560
|
+
}
|
561
|
+
};
|
562
|
+
export const getCodeHandler = async (input) => {
|
563
|
+
try {
|
564
|
+
if (!input.provider) {
|
565
|
+
return createErrorResponse("Provider is required");
|
566
|
+
}
|
567
|
+
if (!input.address) {
|
568
|
+
return createErrorResponse("Address is required");
|
569
|
+
}
|
570
|
+
const provider = getProvider(input.provider);
|
571
|
+
const code = await provider.getCode(input.address, input.blockTag);
|
572
|
+
return createSuccessResponse({
|
573
|
+
code
|
574
|
+
}, `Code retrieved successfully
|
575
|
+
Address: ${input.address}
|
576
|
+
Code: ${code}
|
577
|
+
`);
|
578
|
+
}
|
579
|
+
catch (error) {
|
580
|
+
return createErrorResponse(`Failed to get code: ${error.message}`);
|
581
|
+
}
|
582
|
+
};
|
583
|
+
export const getStorageAtHandler = async (input) => {
|
584
|
+
try {
|
585
|
+
if (!input.provider) {
|
586
|
+
return createErrorResponse("Provider is required");
|
587
|
+
}
|
588
|
+
if (!input.address) {
|
589
|
+
return createErrorResponse("Address is required");
|
590
|
+
}
|
591
|
+
if (!input.position) {
|
592
|
+
return createErrorResponse("Position is required");
|
593
|
+
}
|
594
|
+
const provider = getProvider(input.provider);
|
595
|
+
const storage = await provider.getStorageAt(input.address, input.position, input.blockTag);
|
596
|
+
return createSuccessResponse({
|
597
|
+
storage
|
598
|
+
}, `Storage retrieved successfully
|
599
|
+
Address: ${input.address}
|
600
|
+
Position: ${input.position}
|
601
|
+
Storage: ${storage}
|
602
|
+
`);
|
603
|
+
}
|
604
|
+
catch (error) {
|
605
|
+
return createErrorResponse(`Failed to get storage: ${error.message}`);
|
606
|
+
}
|
607
|
+
};
|
608
|
+
export const estimateGasHandler = async (input) => {
|
609
|
+
try {
|
610
|
+
if (!input.provider) {
|
611
|
+
return createErrorResponse("Provider is required");
|
612
|
+
}
|
613
|
+
if (!input.transaction) {
|
614
|
+
return createErrorResponse("Transaction is required");
|
615
|
+
}
|
616
|
+
const provider = getProvider(input.provider);
|
617
|
+
const gasEstimate = await provider.estimateGas(input.transaction);
|
618
|
+
return createSuccessResponse({
|
619
|
+
gasEstimate: gasEstimate.toString()
|
620
|
+
}, `Gas estimate retrieved successfully
|
621
|
+
Gas estimate: ${gasEstimate.toString()}
|
622
|
+
`);
|
623
|
+
}
|
624
|
+
catch (error) {
|
625
|
+
return createErrorResponse(`Failed to estimate gas: ${error.message}`);
|
626
|
+
}
|
627
|
+
};
|
628
|
+
export const getLogsHandler = async (input) => {
|
629
|
+
try {
|
630
|
+
if (!input.provider) {
|
631
|
+
return createErrorResponse("Provider is required");
|
632
|
+
}
|
633
|
+
if (!input.filter) {
|
634
|
+
return createErrorResponse("Filter is required");
|
635
|
+
}
|
636
|
+
const provider = getProvider(input.provider);
|
637
|
+
const logs = await provider.getLogs(input.filter);
|
638
|
+
return createSuccessResponse({
|
639
|
+
logs
|
640
|
+
}, `Logs retrieved successfully
|
641
|
+
Logs: ${logs}
|
642
|
+
`);
|
643
|
+
}
|
644
|
+
catch (error) {
|
645
|
+
return createErrorResponse(`Failed to get logs: ${error.message}`);
|
646
|
+
}
|
647
|
+
};
|
648
|
+
export const getEnsResolverHandler = async (input) => {
|
649
|
+
try {
|
650
|
+
if (!input.provider) {
|
651
|
+
return createErrorResponse("Provider is required");
|
652
|
+
}
|
653
|
+
if (!input.name) {
|
654
|
+
return createErrorResponse("ENS name is required");
|
655
|
+
}
|
656
|
+
const provider = getProvider(input.provider);
|
657
|
+
// In ethers.js v5, getResolver might not be directly on the provider type
|
658
|
+
// but it's available in the implementation
|
659
|
+
const resolver = await provider.getResolver(input.name);
|
660
|
+
return createSuccessResponse({
|
661
|
+
resolver: resolver ? {
|
662
|
+
address: resolver.address,
|
663
|
+
name: resolver.name
|
664
|
+
} : null
|
665
|
+
}, resolver ? `ENS resolver retrieved successfully
|
666
|
+
Address: ${resolver.address}
|
667
|
+
Name: ${resolver.name}
|
668
|
+
` : "No resolver found for this ENS name");
|
669
|
+
}
|
670
|
+
catch (error) {
|
671
|
+
return createErrorResponse(`Failed to get ENS resolver: ${error.message}`);
|
672
|
+
}
|
673
|
+
};
|
674
|
+
export const lookupAddressHandler = async (input) => {
|
675
|
+
try {
|
676
|
+
if (!input.provider) {
|
677
|
+
return createErrorResponse("Provider is required");
|
678
|
+
}
|
679
|
+
if (!input.address) {
|
680
|
+
return createErrorResponse("Address is required");
|
681
|
+
}
|
682
|
+
const provider = getProvider(input.provider);
|
683
|
+
const name = await provider.lookupAddress(input.address);
|
684
|
+
return createSuccessResponse({
|
685
|
+
name
|
686
|
+
}, name ? `ENS name retrieved successfully
|
687
|
+
Name: ${name}
|
688
|
+
` : "No ENS name found for this address");
|
689
|
+
}
|
690
|
+
catch (error) {
|
691
|
+
return createErrorResponse(`Failed to lookup ENS name: ${error.message}`);
|
692
|
+
}
|
693
|
+
};
|
694
|
+
export const resolveNameHandler = async (input) => {
|
695
|
+
try {
|
696
|
+
if (!input.provider) {
|
697
|
+
return createErrorResponse("Provider is required");
|
698
|
+
}
|
699
|
+
if (!input.name) {
|
700
|
+
return createErrorResponse("ENS name is required");
|
701
|
+
}
|
702
|
+
const provider = getProvider(input.provider);
|
703
|
+
const address = await provider.resolveName(input.name);
|
704
|
+
return createSuccessResponse({
|
705
|
+
address
|
706
|
+
}, address ? `ENS name resolved successfully
|
707
|
+
Name: ${input.name}
|
708
|
+
Address: ${address}
|
709
|
+
` : "Could not resolve this ENS name");
|
710
|
+
}
|
711
|
+
catch (error) {
|
712
|
+
return createErrorResponse(`Failed to resolve ENS name: ${error.message}`);
|
713
|
+
}
|
714
|
+
};
|
715
|
+
// Network Methods
|
716
|
+
export const getNetworkHandler = async (input) => {
|
717
|
+
try {
|
718
|
+
if (!input.provider) {
|
719
|
+
return createErrorResponse("Provider is required");
|
720
|
+
}
|
721
|
+
const provider = getProvider(input.provider);
|
722
|
+
const network = await provider.getNetwork();
|
723
|
+
return createSuccessResponse({
|
724
|
+
network: {
|
725
|
+
name: network.name,
|
726
|
+
chainId: network.chainId,
|
727
|
+
ensAddress: network.ensAddress
|
728
|
+
}
|
729
|
+
}, `Network information retrieved successfully
|
730
|
+
Network name: ${network.name}
|
731
|
+
Chain ID: ${network.chainId}
|
732
|
+
ENS address: ${network.ensAddress}
|
733
|
+
`);
|
734
|
+
}
|
735
|
+
catch (error) {
|
736
|
+
return createErrorResponse(`Failed to get network information: ${error.message}`);
|
737
|
+
}
|
738
|
+
};
|
739
|
+
export const getBlockNumberHandler = async (input) => {
|
740
|
+
try {
|
741
|
+
if (!input.provider) {
|
742
|
+
return createErrorResponse("Provider is required");
|
743
|
+
}
|
744
|
+
const provider = getProvider(input.provider);
|
745
|
+
const blockNumber = await provider.getBlockNumber();
|
746
|
+
return createSuccessResponse({
|
747
|
+
blockNumber
|
748
|
+
}, `Block number retrieved successfully
|
749
|
+
Block number: ${blockNumber.toString()}
|
750
|
+
`);
|
751
|
+
}
|
752
|
+
catch (error) {
|
753
|
+
return createErrorResponse(`Failed to get block number: ${error.message}`);
|
754
|
+
}
|
755
|
+
};
|
756
|
+
export const getFeeDataHandler = async (input) => {
|
757
|
+
try {
|
758
|
+
if (!input.provider) {
|
759
|
+
return createErrorResponse("Provider is required");
|
760
|
+
}
|
761
|
+
const provider = getProvider(input.provider);
|
762
|
+
// getFeeData is available in ethers v5.5.0+
|
763
|
+
// @ts-ignore - getFeeData might not be in the type definitions depending on the version
|
764
|
+
const feeData = await provider.getFeeData();
|
765
|
+
return createSuccessResponse({
|
766
|
+
feeData: {
|
767
|
+
gasPrice: feeData.gasPrice?.toString(),
|
768
|
+
maxFeePerGas: feeData.maxFeePerGas?.toString(),
|
769
|
+
maxPriorityFeePerGas: feeData.maxPriorityFeePerGas?.toString()
|
770
|
+
}
|
771
|
+
}, `Fee data retrieved successfully
|
772
|
+
Gas price: ${feeData.gasPrice?.toString()}
|
773
|
+
Max fee per gas: ${feeData.maxFeePerGas?.toString()}
|
774
|
+
Max priority fee per gas: ${feeData.maxPriorityFeePerGas?.toString()}
|
775
|
+
`);
|
776
|
+
}
|
777
|
+
catch (error) {
|
778
|
+
return createErrorResponse(`Failed to get fee data: ${error.message}`);
|
779
|
+
}
|
780
|
+
};
|
781
|
+
//# sourceMappingURL=wallet.js.map
|