browser-rpc 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +152 -0
- package/dist/index.js +5 -6
- package/package.json +3 -2
package/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# browser-rpc
|
|
2
|
+
|
|
3
|
+
A local RPC proxy that routes Ethereum transactions through your browser wallet instead of requiring private keys in `.env` files.
|
|
4
|
+
|
|
5
|
+
## The Problem
|
|
6
|
+
|
|
7
|
+
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:
|
|
8
|
+
|
|
9
|
+
- Is less secure than a browser wallet or hardware wallet
|
|
10
|
+
- Requires maintaining ETH balances across multiple chains
|
|
11
|
+
- Is tedious to set up and manage
|
|
12
|
+
|
|
13
|
+
## The Solution
|
|
14
|
+
|
|
15
|
+
`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.
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
19
|
+
│ Foundry/HH │────▶│ browser-rpc │────▶│ Upstream RPC │
|
|
20
|
+
│ Script │◀────│ (localhost:8545)│◀────│ (Alchemy, etc) │
|
|
21
|
+
└─────────────────┘ └────────┬────────┘ └─────────────────┘
|
|
22
|
+
│
|
|
23
|
+
│ Opens browser for signing
|
|
24
|
+
▼
|
|
25
|
+
┌─────────────────┐ ┌─────────────────┐
|
|
26
|
+
│ Web UI │────▶│ Browser Wallet │
|
|
27
|
+
│ (localhost:8545)│◀────│ (MetaMask) │
|
|
28
|
+
└─────────────────┘ └─────────────────┘
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install -g browser-rpc
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Or run directly with npx:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npx browser-rpc --rpc https://mainnet.base.org
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Usage
|
|
44
|
+
|
|
45
|
+
1. Start the proxy server pointing to your target network:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
browser-rpc --rpc https://mainnet.base.org
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
2. Configure your tool to use `http://localhost:8545` as the RPC URL
|
|
52
|
+
|
|
53
|
+
3. Run your script - when it sends a transaction, your browser will open for approval
|
|
54
|
+
|
|
55
|
+
### With Foundry
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Start the proxy
|
|
59
|
+
browser-rpc --rpc https://mainnet.base.org
|
|
60
|
+
|
|
61
|
+
# In another terminal, run your script
|
|
62
|
+
forge script script/Deploy.s.sol --rpc-url http://localhost:8545 --broadcast
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### With Hardhat
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
// hardhat.config.js
|
|
69
|
+
module.exports = {
|
|
70
|
+
networks: {
|
|
71
|
+
browserRpc: {
|
|
72
|
+
url: 'http://localhost:8545',
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npx hardhat run scripts/deploy.js --network browserRpc
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### With viem
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { createWalletClient, http } from 'viem'
|
|
86
|
+
import { base } from 'viem/chains'
|
|
87
|
+
|
|
88
|
+
const client = createWalletClient({
|
|
89
|
+
chain: base,
|
|
90
|
+
transport: http('http://localhost:8545'),
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
// This will open your browser for approval
|
|
94
|
+
const hash = await client.sendTransaction({
|
|
95
|
+
to: '0x...',
|
|
96
|
+
value: parseEther('0.01'),
|
|
97
|
+
})
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## CLI Options
|
|
101
|
+
|
|
102
|
+
| Flag | Default | Description |
|
|
103
|
+
| -------------- | ---------- | -------------------------------- |
|
|
104
|
+
| `--rpc`, `-r` | (required) | Upstream RPC URL for read calls |
|
|
105
|
+
| `--port`, `-p` | `8545` | Port for the proxy server |
|
|
106
|
+
| `--no-open` | `false` | Disable auto-opening the browser |
|
|
107
|
+
|
|
108
|
+
## How It Works
|
|
109
|
+
|
|
110
|
+
1. Your script sends `eth_sendTransaction` to the proxy
|
|
111
|
+
2. The proxy holds the connection open and opens a browser UI
|
|
112
|
+
3. You connect your wallet and review the transaction
|
|
113
|
+
4. Click "Execute" to sign and send via your wallet
|
|
114
|
+
5. The transaction hash is returned to your script
|
|
115
|
+
|
|
116
|
+
Read-only calls (`eth_call`, `eth_getBalance`, etc.) pass through directly to the upstream RPC.
|
|
117
|
+
|
|
118
|
+
## Supported Methods
|
|
119
|
+
|
|
120
|
+
| Method | Behavior |
|
|
121
|
+
| ---------------------- | ------------------------------ |
|
|
122
|
+
| `eth_sendTransaction` | Opens browser for signing |
|
|
123
|
+
| `eth_signTypedData_v4` | Opens browser for signing |
|
|
124
|
+
| `eth_sign` | Opens browser for signing |
|
|
125
|
+
| Everything else | Passes through to upstream RPC |
|
|
126
|
+
|
|
127
|
+
## Chain Support
|
|
128
|
+
|
|
129
|
+
The proxy automatically detects the chain from your upstream RPC and configures the UI accordingly. Any EVM-compatible chain is supported.
|
|
130
|
+
|
|
131
|
+
If your wallet is connected to the wrong chain, the UI will prompt you to switch.
|
|
132
|
+
|
|
133
|
+
## Development
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Clone the repo
|
|
137
|
+
git clone https://github.com/gskril/browser-rpc.git
|
|
138
|
+
cd browser-rpc
|
|
139
|
+
|
|
140
|
+
# Install dependencies
|
|
141
|
+
bun install
|
|
142
|
+
|
|
143
|
+
# Build everything
|
|
144
|
+
bun run build
|
|
145
|
+
|
|
146
|
+
# Start the dev server
|
|
147
|
+
bun run dev:server -- --rpc https://mainnet.base.org
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
MIT
|
package/dist/index.js
CHANGED
|
@@ -3801,7 +3801,6 @@ function createPendingEntry(id, request) {
|
|
|
3801
3801
|
request,
|
|
3802
3802
|
resolve: resolvePromise
|
|
3803
3803
|
});
|
|
3804
|
-
console.log(`\uD83D\uDD10 Pending saved: id=${id} type=${request.type} jsonrpc=${request.jsonRpcId}`);
|
|
3805
3804
|
setTimeout(() => {
|
|
3806
3805
|
const entry = pending.get(id);
|
|
3807
3806
|
if (entry) {
|
|
@@ -3854,10 +3853,10 @@ api.post("/tx/:id/hash", async (c) => {
|
|
|
3854
3853
|
}
|
|
3855
3854
|
const request = getPendingRequest(id);
|
|
3856
3855
|
if (!request) {
|
|
3857
|
-
console.warn(`\
|
|
3856
|
+
console.warn(`\x1B[31m✗ Unknown request:\x1B[0m ${id}`);
|
|
3858
3857
|
return c.json({ error: "Request not found or expired" }, 404);
|
|
3859
3858
|
}
|
|
3860
|
-
console.log(`\
|
|
3859
|
+
console.log(`\x1B[32m✓ Submitted:\x1B[0m ${body.hash}`);
|
|
3861
3860
|
return c.json({ ok: true });
|
|
3862
3861
|
});
|
|
3863
3862
|
api.post("/complete/:id", async (c) => {
|
|
@@ -4093,7 +4092,7 @@ function createServer(config) {
|
|
|
4093
4092
|
const body = await c.req.json();
|
|
4094
4093
|
if (Array.isArray(body)) {
|
|
4095
4094
|
const methods = body.map((req) => req.method).join(", ");
|
|
4096
|
-
console.log(
|
|
4095
|
+
console.log(`\x1B[2m← [${methods}]\x1B[0m`);
|
|
4097
4096
|
const responses = await Promise.all(body.map((req) => handleRpcRequest(req, {
|
|
4098
4097
|
upstreamRpcUrl: config.upstreamRpcUrl,
|
|
4099
4098
|
uiBaseUrl: `http://localhost:${config.port}`,
|
|
@@ -4101,7 +4100,7 @@ function createServer(config) {
|
|
|
4101
4100
|
})));
|
|
4102
4101
|
return c.json(responses);
|
|
4103
4102
|
}
|
|
4104
|
-
console.log(
|
|
4103
|
+
console.log(`\x1B[2m← ${body.method}\x1B[0m`);
|
|
4105
4104
|
const response = await handleRpcRequest(body, {
|
|
4106
4105
|
upstreamRpcUrl: config.upstreamRpcUrl,
|
|
4107
4106
|
uiBaseUrl: `http://localhost:${config.port}`,
|
|
@@ -4160,7 +4159,7 @@ var server = createServer({
|
|
|
4160
4159
|
port,
|
|
4161
4160
|
onPendingRequest: (id, url) => {
|
|
4162
4161
|
console.log(`
|
|
4163
|
-
\
|
|
4162
|
+
\x1B[33m\u23F3 Awaiting approval:\x1B[0m ${url}`);
|
|
4164
4163
|
if (options.open) {
|
|
4165
4164
|
openBrowser(url);
|
|
4166
4165
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browser-rpc",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Local RPC proxy that routes Ethereum transactions through your browser wallet",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
|
-
"web-dist"
|
|
17
|
+
"web-dist",
|
|
18
|
+
"README.md"
|
|
18
19
|
],
|
|
19
20
|
"scripts": {
|
|
20
21
|
"dev": "bun run --watch src/index.ts",
|