MCP EVM Signer

  • src
import { ethers } from 'ethers'; import fs from 'fs-extra'; import path from 'path'; import config from './config.js'; // Key storage interface interface KeyData { address: string; privateKey: string; encrypted: boolean; encryptedData: string | null; } /** * Encrypt a private key using password */ export async function encryptKey(privateKey: string, password: string): Promise<string> { const wallet = new ethers.Wallet(privateKey); return await wallet.encrypt(password); } /** * Decrypt an encrypted key using password */ export async function decryptKey(encryptedData: string, password: string): Promise<string> { const wallet = await ethers.Wallet.fromEncryptedJson(encryptedData, password); return wallet.privateKey; } /** * Save a wallet to storage */ export async function saveWallet(wallet: ethers.Wallet): Promise<void> { const address = wallet.address.toLowerCase(); const keyPath = path.join(config.keys.path, `${address}.json`); let keyData: KeyData; if (config.keys.encrypt) { const encryptedData = await wallet.encrypt(config.keys.password); keyData = { address, privateKey: '', // Don't store plaintext private key when encrypted encrypted: true, encryptedData, }; } else { keyData = { address, privateKey: wallet.privateKey, encrypted: false, encryptedData: null, }; } await fs.writeJson(keyPath, keyData, { spaces: 2 }); } /** * Get all wallet addresses from storage */ export async function getWalletAddresses(): Promise<string[]> { const files = await fs.readdir(config.keys.path); return files .filter(file => file.endsWith('.json')) .map(file => path.basename(file, '.json')); } /** * Load a wallet from storage */ export async function loadWallet(address: string): Promise<ethers.Wallet | null> { const normalizedAddress = address.toLowerCase(); const keyPath = path.join(config.keys.path, `${normalizedAddress}.json`); try { if (!await fs.pathExists(keyPath)) { return null; } const keyData: KeyData = await fs.readJson(keyPath); if (keyData.encrypted) { if (!keyData.encryptedData) { throw new Error(`Encrypted wallet missing encryptedData: ${address}`); } // Type assertion to make TypeScript happy return ethers.Wallet.fromEncryptedJson(keyData.encryptedData, config.keys.password) as Promise<ethers.Wallet>; } else { if (!keyData.privateKey) { throw new Error(`Wallet missing privateKey: ${address}`); } return new ethers.Wallet(keyData.privateKey); } } catch (error) { console.error(`Error loading wallet ${address}:`, error); return null; } } /** * Create a new random wallet */ export function createWallet(): ethers.Wallet { // Type assertion to ensure we get a Wallet type return ethers.Wallet.createRandom() as ethers.Wallet; } /** * Create a wallet from a private key */ export function importWallet(privateKey: string): ethers.Wallet { return new ethers.Wallet(privateKey); }