Skip to main content
Glama

Neo N3 MCP Server

by r3e-network
wallet-service.ts6.01 kB
/** * Wallet Service for Neo N3 MCP * * This module provides wallet management functionality for the Neo N3 MCP server. */ import * as neonJs from '@cityofzion/neon-js'; import * as fs from 'fs'; import * as path from 'path'; import * as crypto from 'crypto'; export class WalletService { private walletsDir: string; constructor(walletsDir: string = './wallets') { this.walletsDir = walletsDir; this.ensureWalletsDirExists(); } /** * Ensure the wallets directory exists */ private ensureWalletsDirExists() { if (!fs.existsSync(this.walletsDir)) { fs.mkdirSync(this.walletsDir, { recursive: true }); } } /** * Create a new wallet * @param password Password to encrypt the wallet * @returns Wallet information */ async createWallet(password: string): Promise<any> { try { // Create a new account const account = new neonJs.wallet.Account(); // Encrypt the private key const encryptedPrivateKey = this.encryptPrivateKey(account.privateKey, password); // Create wallet info const walletInfo = { address: account.address, publicKey: account.publicKey, encryptedPrivateKey, createdAt: new Date().toISOString() }; // Save the wallet this.saveWallet(account.address, walletInfo); return walletInfo; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; throw new Error(`Failed to create wallet: ${errorMessage}`); } } /** * Get wallet information * @param address Wallet address * @returns Wallet information */ async getWallet(address: string): Promise<any> { try { const walletPath = path.join(this.walletsDir, `${address}.json`); if (!fs.existsSync(walletPath)) { throw new Error(`Wallet not found: ${address}`); } const walletData = fs.readFileSync(walletPath, 'utf-8'); return JSON.parse(walletData); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; throw new Error(`Failed to get wallet: ${errorMessage}`); } } /** * Import a wallet from private key or WIF * @param key Private key or WIF * @param password Password to encrypt the wallet * @returns Wallet information */ async importWallet(key: string, password: string = 'password'): Promise<any> { try { // Create an account from the key const account = new neonJs.wallet.Account(key); // Encrypt the private key const encryptedPrivateKey = this.encryptPrivateKey(account.privateKey, password); // Create wallet info const walletInfo = { address: account.address, publicKey: account.publicKey, encryptedPrivateKey, createdAt: new Date().toISOString() }; // Save the wallet this.saveWallet(account.address, walletInfo); return walletInfo; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; throw new Error(`Failed to import wallet: ${errorMessage}`); } } /** * Encrypt a private key * @param privateKey Private key to encrypt * @param password Password to use for encryption * @returns Encrypted private key */ private encryptPrivateKey(privateKey: string, password: string): string { try { // Generate a random salt const salt = crypto.randomBytes(16); // Derive a key from the password const key = crypto.pbkdf2Sync(password, salt, 100000, 32, 'sha256'); // Generate a random IV const iv = crypto.randomBytes(16); // Create a cipher const cipher = crypto.createCipheriv('aes-256-cbc', key, iv); // Encrypt the private key let encrypted = cipher.update(privateKey, 'utf-8', 'hex'); encrypted += cipher.final('hex'); // Return the encrypted private key with salt and IV return `${salt.toString('hex')}:${iv.toString('hex')}:${encrypted}`; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; throw new Error(`Failed to encrypt private key: ${errorMessage}`); } } /** * Decrypt a private key * @param encryptedPrivateKey Encrypted private key * @param password Password to use for decryption * @returns Decrypted private key */ private decryptPrivateKey(encryptedPrivateKey: string, password: string): string { try { // Split the encrypted private key into salt, IV, and encrypted data const [saltHex, ivHex, encrypted] = encryptedPrivateKey.split(':'); // Convert salt and IV from hex to Buffer const salt = Buffer.from(saltHex, 'hex'); const iv = Buffer.from(ivHex, 'hex'); // Derive a key from the password const key = crypto.pbkdf2Sync(password, salt, 100000, 32, 'sha256'); // Create a decipher const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv); // Decrypt the private key let decrypted = decipher.update(encrypted, 'hex', 'utf-8'); decrypted += decipher.final('utf-8'); return decrypted; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; throw new Error(`Failed to decrypt private key: ${errorMessage}`); } } /** * Save a wallet to disk * @param address Wallet address * @param walletInfo Wallet information */ private saveWallet(address: string, walletInfo: any) { try { const walletPath = path.join(this.walletsDir, `${address}.json`); fs.writeFileSync(walletPath, JSON.stringify(walletInfo, null, 2)); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; throw new Error(`Failed to save wallet: ${errorMessage}`); } } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/r3e-network/neo-n3-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server