A local RPC proxy that routes Ethereum transactions through your browser wallet instead of requiring private keys in .env files.
Deploying smart contracts requires signing transactions with a private key. Most developers use a separate "deployer" wallet with the key stored in a .env file, which:
- Is less secure than a browser wallet or hardware wallet
- Requires maintaining ETH balances across multiple chains
- Is tedious to set up and manage
browser-rpc is a local proxy server that intercepts transaction requests from your development tools (Foundry, Hardhat, viem scripts) and routes them through your browser wallet for signing.
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Foundry/HH │────▶│ browser-rpc │────▶│ Upstream RPC │
│ Script │◀────│ (localhost:8545)│◀────│ (Alchemy, etc) │
└─────────────────┘ └────────┬────────┘ └─────────────────┘
│
│ Opens browser for signing
▼
┌─────────────────┐ ┌─────────────────┐
│ Web UI │────▶│ Browser Wallet │
│ (localhost:8545)│◀────│ (MetaMask) │
└─────────────────┘ └─────────────────┘
npm install -g browser-rpcOr run directly with npx:
npx browser-rpc --rpc https://mainnet.base.org- Start the proxy server pointing to your target network:
browser-rpc --rpc https://mainnet.base.orgIf you're using Hardhat, you'll also need to specify the wallet address you'll use to sign transactions:
browser-rpc --rpc https://mainnet.base.org --from 0xYourWalletAddress-
Configure your script to use
http://localhost:8545as the RPC URL -
Run your script - when it sends a transaction, your browser will open for approval
import { createWalletClient, http } from 'viem'
import { base } from 'viem/chains'
const client = createWalletClient({
chain: base,
transport: http('http://localhost:8545', {
timeout: 60_000, // 1 minute to sign in the browser
}),
})
// This will open your browser for approval
const hash = await client.sendTransaction({
account: null,
to: '0x...',
value: parseEther('0.01'),
})forge script script/Deploy.s.sol \
--rpc-url http://localhost:8545 \
--broadcast \
--unlocked \
--sender 0xYourWalletAddressNote: The
--unlockedflag tells Foundry to sendeth_sendTransactionto the RPC instead of signing locally. The--senderflag specifies which public address you'll deploy from.
// hardhat.config.js
const config = {
networks: {
base: {
type: 'http',
chainType: 'op',
url: 'http://localhost:8545',
},
},
}Note: The
--fromflag is required for Hardhat. Hardhat callseth_accountsto get the signer address for nonce lookups and gas estimation. The address must match the wallet you'll use to sign in the browser.
| Flag | Default | Description |
|---|---|---|
--rpc, -r |
(required) | Upstream RPC URL for read calls |
--from, -f |
(none) | Wallet address (returned for eth_accounts) |
--port, -p |
8545 |
Port for the proxy server |
--no-open |
false |
Disable auto-opening the browser |
- Your script sends
eth_sendTransactionto the proxy - The proxy holds the connection open and opens a browser UI
- You connect your wallet and review the transaction
- Click "Execute" to sign and send via your wallet
- The transaction hash is returned to your script
Read-only calls (eth_call, eth_getBalance, etc.) pass through directly to the upstream RPC.
| Method | Behavior |
|---|---|
eth_sendTransaction |
Opens browser for signing |
eth_signTypedData_v4 |
Opens browser for signing |
eth_sign |
Opens browser for signing |
| Everything else | Passes through to upstream RPC |
The proxy automatically detects the chain from your upstream RPC and configures the UI accordingly. Any EVM-compatible chain is supported.
If your wallet is connected to the wrong chain, the UI will prompt you to switch.
# Clone the repo
git clone https://github.com/gskril/browser-rpc.git
cd browser-rpc
# Install dependencies
bun install
# Build everything
bun run build
# Start the dev server
bun run dev:server -- --rpc https://mainnet.base.orgMIT