Private Ethereum Assistant is a local-first Next.js chat app for interacting with EVM chains in natural language.
It can:
- read balances, transactions, and ENS data on the selected network
- prepare and send normal wallet transactions from a configured EOA (Externally Owned Account — a standard Ethereum wallet controlled by a private key)
- inspect and propose Safe (multisig) transactions
- run Railgun privacy test flows on Arbitrum
Install the following before starting:
| Tool | What it does | Install |
|---|---|---|
| Bun | JavaScript runtime and package manager | curl -fsSL https://bun.sh/install | bash |
| Ollama | Local LLM server (Normal mode only) | Download from ollama.com or brew install ollama |
| dotenvx | Encrypted env loader for OpenRouter config (Developer mode only) | brew install dotenvx/brew/dotenvx |
The project runs on macOS, Linux, and Windows. Secret storage adapts to each platform automatically (macOS Keychain, libsecret/Secret Service on Linux, Windows Credential Manager). On Linux, the automatic browser-open step is skipped — open http://localhost:3000 manually.
Note: Linux and Windows secret backends have not been fully tested across all distributions and versions. If you run into issues on your machine, contributions and bug reports are very welcome — see the open issues for Linux (#58) and Windows (#59).
Install dependencies first (one-time):
bun install --frozen-lockfileThen choose one of the two modes below.
Normal mode runs the LLM locally via Ollama. No external API keys are needed.
- Start the app:
bun run local-
The launcher will automatically:
- start Ollama if it is not already running
- pull the default model (
llama3.2:3b) if not already downloaded - build the macOS Keychain helper if needed on macOS
- start the Next.js dev server on
http://localhost:3000 - open the browser
-
Complete the onboarding wizard in the browser:
- Provider: select
Local - Base URL:
http://localhost:11434/v1(pre-filled for Ollama) - Model:
llama3.2:3b - Keys: paste your EOA private key (the hex private key of the Ethereum wallet you want the assistant to use)
- Provider: select
You can change any of these later in the settings panel.
Developer mode uses OpenRouter (a cloud LLM gateway) instead of a local model. It loads developer-only secrets from the repo file .env.tianjin via dotenvx, including APP_MODE, OPEN_ROUTER_KEY, EOA_PRIVATE_KEY, and any optional Safe credentials present there. You need the dotenvx decryption key (ask a team member if you don't have it).
- Start the app:
dotenvx run -f .env.tianjin -- bun run dev -- --developer-mode-
Open
http://localhost:3000in your browser. -
Start using the app. Developer-mode wallet and Safe secrets come from
.env.tianjin; standard mode secrets are stored in the local platform credential backend.
The app uses a UI onboarding wizard for runtime settings. Secrets are saved server-side.
Stored in browser local storage (non-sensitive preferences):
- selected LLM provider and model names
- local model base URL
- selected RPC endpoint and chain ID
- Safe address, Safe RPC, and chain ID
- wallet approval thresholds
- Railgun RPC, POI (Proof of Innocence) nodes, explorer URL, mnemonic, and timing settings
Stored in the OS secret store (macOS Keychain · Linux libsecret/encrypted file · Windows Credential Manager):
EOA_PRIVATE_KEY— the Ethereum wallet private keySAFE_SIGNER_PRIVATE_KEY— the Safe multisig signer key (optional)SAFE_API_KEY— Safe Transaction Service API key (optional)
On macOS this uses the native Keychain helper. On Linux the app prefers Secret Service via secret-tool and falls back to an encrypted file when PEA_SECRET_STORE_PASSPHRASE is set and no Secret Service provider is available. You can override the fallback file path with PEA_SECRET_STORE_FILE.
Security notes:
- Secrets never enter browser storage
- Use dedicated low-value wallets for local testing
- "Delete all" in settings clears browser preferences only, not OS secret store entries
The app supports two interchangeable backends. You can switch between them at any time in settings.
Cloud-based inference via OpenRouter. Use this when you want the practical default backend (Developer mode).
- Base URL:
https://openrouter.ai/api/v1 - Auth: uses the developer/test key from
.env.tianjin - Recommended model:
qwen/qwen3.5-27b - Prompts and tool outputs leave your machine for inference
- Ollama is not required
Fully offline inference via Ollama, LM Studio, or any OpenAI-compatible local server.
- The launcher (
bun run local) manages Ollama automatically when using the defaultlocalhost:11434endpoint - If you use a different local server, make sure it is running before starting the app
- Enter your server's base URL and model name in onboarding or settings
- No repo env editing is needed to switch between Local and OpenRouter
Safe is a smart-contract wallet requiring multiple signatures to execute transactions.
- Safe config is independent from the selected read/send network
- The app can inspect a configured Safe without a signer key
- Proposing transactions requires a Safe owner key;
SAFE_API_KEYis only needed for automatic signing/submission to the Safe Transaction Service - Leaving the Safe signer key blank keeps the flow manual (you confirm in the Safe UI)
Railgun enables private transfers on EVM chains using zero-knowledge proofs.
- Railgun settings are edited in the same settings UI
- The default Railgun network is Arbitrum
- Leaving the Railgun mnemonic blank derives one from your configured EOA key (for testing only)
- Shielding (depositing into Railgun) is a public on-chain transaction; subsequent Railgun-to-Railgun transfers are private
Unit tests cover schema and serialization logic:
bun testBrowser E2E tests use the onboarding flow with OpenRouter (requires .env.tianjin):
dotenvx run -f .env.tianjin -- bun test:e2e:browserStore any required developer-mode wallet or Safe credentials in .env.tianjin before running the suite.
The browser suite verifies:
- first-run onboarding
- OpenRouter-backed chat success
- provider switching between OpenRouter and Local
- persistence across reload
- edit flow
- delete-all flow
Tool-level E2E tests:
dotenvx run -f .env.tianjin -- bun test:e2e:toolsThese tests also read developer-mode wallet and Safe credentials from .env.tianjin.
Model benchmark reports compare tool-routing accuracy and response quality across OpenRouter cloud models and local models.
- OpenRouter Cloud Model Benchmark — qwen3-32b, deepseek-r1-distill-qwen-32b, gemma-3-27b-it across EOA, Safe, and Railgun modes (11 prompts per model)
- MacBook Air Local Model Benchmark — small local models via Ollama on M1 hardware (4 EOA prompts per model)
dotenvx run -f .env.tianjin -- bun run benchmarkOverride the model list with BENCHMARK_MODELS:
BENCHMARK_MODELS="qwen/qwen3-32b,google/gemma-3-27b-it" dotenvx run -f .env.tianjin -- bun run benchmarkThe script starts the dev server, sends 11 prompts per model, and writes OpenRouter_Benchmark.md to the project root.
OpenRouter requests fail:
- confirm you started the app with
dotenvx run -f .env.tianjin - confirm
.env.tianjincontains a validOPEN_ROUTER_KEY - if startup says "Missing local dependencies", run
bun install --frozen-lockfile
Local requests fail:
- confirm your local model server is running (
ollama serveor equivalent) - confirm the Local base URL matches the API root exposed by your server
- confirm the model name matches an available model (
ollama listto check)
Onboarding keeps reappearing:
- check whether your browser profile blocks local storage
- open DevTools > Application > Local Storage and confirm it is writable for the app origin