wallet_create
Create a new Ethereum wallet for Base Sepolia testnet. Generates private key and address, saving to local configuration file.
Instructions
Create a new local wallet (Base Sepolia testnet). Generates a private key and derives the Ethereum address. Saved to ~/.config/run402/wallet.json.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/tools/wallet-create.ts:16-79 (handler)The handleWalletCreate function is the main handler for the wallet_create tool. It checks if a wallet already exists, generates a new private key using secp256k1 ECDH, derives the Ethereum address via keccak256 hash, saves the wallet to disk with restricted permissions (0600), and returns a formatted response with the wallet address and path.
export async function handleWalletCreate( _args: Record<string, never>, ): Promise<{ content: Array<{ type: "text"; text: string }>; isError?: boolean }> { const walletPath = getWalletPath(); if (existsSync(walletPath)) { try { const existing = JSON.parse(readFileSync(walletPath, "utf-8")); return { content: [ { type: "text", text: `Wallet already exists at \`${walletPath}\`.\n\nAddress: \`${existing.address}\`\n\nUse \`wallet_status\` to check details.`, }, ], isError: true, }; } catch { // corrupt file — fall through and create a new one } } // Generate private key const privateKeyBytes = randomBytes(32); const privateKey = `0x${privateKeyBytes.toString("hex")}`; // Derive public key using secp256k1 const ecdh = createECDH("secp256k1"); ecdh.setPrivateKey(privateKeyBytes); const uncompressedPubKey = ecdh.getPublicKey(); // Remove the 04 prefix (uncompressed point marker) const pubKeyBody = uncompressedPubKey.subarray(1); // Ethereum address = last 20 bytes of keccak256(publicKey) const hash = keccak_256(pubKeyBody); const addressBytes = hash.slice(-20); const address = `0x${Buffer.from(addressBytes).toString("hex")}`; // Save wallet const wallet = { address, privateKey, created: new Date().toISOString(), funded: false, }; const dir = dirname(walletPath); mkdirSync(dir, { recursive: true }); writeFileSync(walletPath, JSON.stringify(wallet, null, 2), { mode: 0o600 }); chmodSync(walletPath, 0o600); const lines = [ `## Wallet Created`, ``, `| Field | Value |`, `|-------|-------|`, `| address | \`${address}\` |`, `| saved to | \`${walletPath}\` |`, ``, `Use \`request_faucet\` to fund it with testnet USDC, or send USDC on any supported chain.`, ]; return { content: [{ type: "text", text: lines.join("\n") }] }; } - src/tools/wallet-create.ts:14-14 (schema)The walletCreateSchema is an empty object {} indicating that the wallet_create tool takes no input parameters.
export const walletCreateSchema = {}; - src/index.ts:312-317 (registration)Registration of the wallet_create tool with the MCP server. The tool is named 'wallet_create', has a description about creating a new local wallet on Base Sepolia testnet, uses the walletCreateSchema, and wraps handleWalletCreate in an async arrow function.
server.tool( "wallet_create", "Create a new local wallet (Base Sepolia testnet). Generates a private key and derives the Ethereum address. Saved to ~/.config/run402/wallet.json.", walletCreateSchema, async (args) => handleWalletCreate(args), ); - src/index.ts:53-53 (registration)Import statement that brings in walletCreateSchema and handleWalletCreate from the wallet-create.ts module for registration.
import { walletCreateSchema, handleWalletCreate } from "./tools/wallet-create.js"; - src/config.ts:16-18 (helper)The getWalletPath helper function returns the file path where the wallet JSON file is stored (~/.config/run402/wallet.json by default). Used by handleWalletCreate to determine where to save the wallet.
export function getWalletPath(): string { return join(getConfigDir(), "wallet.json"); }