name: browser-wallet description: Inject a realistic wallet provider (MetaMask/Phantom) into any browser page for seamless web3 dApp testing. Use when testing dApps, automating web3 interactions, or developing dApps without browser extension setup. Supports EVM (Ethereum, Polygon, BSC) and Solana chains.
Web3 Browser Wallet
Inject a test wallet into any browser page via agent-browser. No extension installs, no manual setup — dApps see a real MetaMask/Phantom wallet.
Prerequisites
which agent-browser || npm install -g agent-browser
Browser Automation — agent-browser Basics
This skill builds on agent-browser, a full browser automation CLI. Run agent-browser --help for all commands.
Core workflow:
agent-browser open <url>— Navigate to a page (add--headedfor visible browser)agent-browser snapshot -i— Get the page's interactive elements with refs (@e1,@e2, …)agent-browser click @e1/agent-browser fill @e2 "text"— Interact using refs- Re-snapshot after any page change to get updated refs
Bundle Path
The inject.bundle.js file is in the same directory as this skill file. Set the BUNDLE variable once per session using the path for your tool:
| Tool | Path |
|---|---|
| Cursor | ~/.cursor/skills/browser-wallet/inject.bundle.js |
| Claude Code | ~/.claude/skills/browser-wallet/inject.bundle.js |
| OpenCode | ~/.config/opencode/skills/browser-wallet/inject.bundle.js |
Quick Start — EVM
Step 1: Open dApp — use --headed for production dApps (Cloudflare blocks headless browsers). Omit for localhost.
agent-browser open https://app.uniswap.org --headed
Step 2: Inject wallet — single chained command that sets config, injects bundle, reloads, and re-injects so the dApp discovers the wallet on init:
agent-browser eval "window.__WEB3_WALLET_CONFIG__ = { generate: true, providers: ['evm'], evm: { chainId: 1, rpcUrl: 'https://eth.llamarpc.com' }, confirmMode: 'auto', logLevel: 'info' };" && cat $BUNDLE | agent-browser eval --stdin && agent-browser reload && agent-browser wait 1000 && agent-browser eval "window.__WEB3_WALLET_CONFIG__ = { generate: true, providers: ['evm'], evm: { chainId: 1, rpcUrl: 'https://eth.llamarpc.com' }, confirmMode: 'auto', logLevel: 'info' };" && cat $BUNDLE | agent-browser eval --stdin
Step 3: Verify — confirm the wallet initialized and show the user their wallet details:
agent-browser eval "JSON.stringify(window.__injectedWallet)"
Once you receive a valid JSON result (not undefined), parse it and tell the user:
- Address — the EVM address (
addressfield) or Solana public key (publicKeyfield) - Chain — current chain ID (
chainId) or Solana cluster (cluster) - Mnemonic — the seed phrase (
mnemonic) so they can import/recover the wallet later
Example output you should present:
Wallet injected successfully!
- Address:
0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18- Chain ID: 1 (Ethereum Mainnet)
- Mnemonic:
word1 word2 ... word12
If the result is undefined or null, the injection failed — re-run Step 2.
Step 4: Connect wallet in the dApp
agent-browser wait 2000 && agent-browser snapshot -i
Find the "Connect Wallet" button ref (e.g. @e9) and click it. A wallet selection modal appears — use screenshot to see it visually, then click the injected wallet:
agent-browser click @e9 && agent-browser wait 1000 && agent-browser screenshot
The injected wallet usually appears as "Injected Test Wallet" or "Browser Wallet" with a "Detected" badge. To click it:
# Try data-testid first (Uniswap, many dApps), then fall back to text matching
agent-browser eval "document.querySelector('[data-testid=\"wallet-option-injected\"]')?.click() || [...document.querySelectorAll('button,[role=button],div[class*=wallet],div[class*=option]')].find(el => /injected|browser.wallet|detected/i.test(el.textContent))?.click()"
If that doesn't work, use agent-browser find text "Injected" click or agent-browser find text "MetaMask" click.
Quick Start — Solana
agent-browser open https://raydium.io/swap --headed
agent-browser eval "window.__WEB3_WALLET_CONFIG__ = { generate: true, providers: ['solana'], solana: { cluster: 'devnet' }, confirmMode: 'auto', logLevel: 'info' };" && cat $BUNDLE | agent-browser eval --stdin && agent-browser reload && agent-browser wait 1000 && agent-browser eval "window.__WEB3_WALLET_CONFIG__ = { generate: true, providers: ['solana'], solana: { cluster: 'devnet' }, confirmMode: 'auto', logLevel: 'info' };" && cat $BUNDLE | agent-browser eval --stdin
Then find and click the "Connect Wallet" → "Phantom" option using the same snapshot/click approach.
Configuration Reference
Set window.__WEB3_WALLET_CONFIG__ before injecting. Pick one key source:
| Option | Example | Purpose |
|---|---|---|
generate |
true |
Fresh random wallet (recommended) |
privateKey |
"0xabc..." |
Import existing key |
mnemonic |
"word1 word2 ..." |
Import from seed phrase |
hdPath |
"m/44'/60'/0'/0/0" |
Custom derivation path |
Chain and provider options:
| Option | Values |
|---|---|
providers |
['evm'], ['solana'], ['evm','solana'] |
evm.chainId |
Chain ID number (e.g. 1, 137, 56) |
evm.rpcUrl |
RPC endpoint URL |
evm.chains |
Extra chains: { 137: { rpcUrl: "...", name: "Polygon" } } |
solana.cluster |
"mainnet-beta" | "devnet" | "localnet" | custom URL |
confirmMode |
"auto" (approve all) | "log" (approve + log) | "reject" (reject all) |
logLevel |
"silent" | "info" | "debug" |
What Gets Injected
EVM (window.ethereum): MetaMask-compatible EIP-1193 provider. isMetaMask: true. Supports eth_requestAccounts, personal_sign, eth_signTypedData_v4, eth_sendTransaction, wallet_switchEthereumChain, chain events, EIP-6963 discovery, and legacy enable()/send()/sendAsync().
Solana (window.solana): Phantom-compatible provider. isPhantom: true. Supports connect, disconnect, signTransaction, signAllTransactions, signMessage, signAndSendTransaction.
Info (window.__injectedWallet): address, publicKey, chainId, cluster, mnemonic.
Operational Tips
- Always
--headedfor production dApps — Cloudflare/anti-bot blocks headless. Only skip for localhost. - Wait before snapshots — After
openorreload, useagent-browser wait 2000beforesnapshot. - Re-inject after navigation — If the page navigates to a new URL, re-run the config + inject chain.
- Use
screenshotwhensnapshotis unclear — Wallet modals and overlays are often invisible in accessibility snapshots. - Use
evalto click stubborn elements — Wallet modal buttons often lack accessible roles. UsequerySelectorviaevalto click them. - Verify connection — After connecting,
agent-browser eval "window.ethereum.selectedAddress"confirms the active address.
Security
NEVER use real private keys with mainnet funds. Prefer generate: true. Use testnets or local nodes (Hardhat, Anvil, Solana localnet) for transaction testing.
References
- examples.md — Detailed workflow examples
- troubleshooting.md — Common issues and fixes