System-wide native desktop wallet for macOS, Windows, and Linux that exposes a signing surface to any browser, CLI, or native app. Best-in-class hardware wallet integration (Ledger, Trezor, GridPlus Lattice1) and a browser extension that injects an EIP-1193 provider into web dApps.
- 01power users with hardware wallets
- 02CLI / Foundry / Hardhat workflows
- 03system-wide signing across browsers and apps
- 04Ledger / Trezor / GridPlus signing UX
- 05users who refuse browser-extension-only wallets
- pnpm add eth-provider
- pnpm add wagmi viem@2.x
Frame exposes an EIP-1193 provider both via its browser extension (injected as `window.ethereum` when no other wallet wins the namespace race, and announced via EIP-6963 with `info.rdns === 'sh.frame'`) and via its desktop IPC bridge using the `eth-provider` package: `import provider from 'eth-provider'; const eth = provider('frame'); const accounts = await eth.request({ method: 'eth_requestAccounts' }); const sig = await eth.request({ method: 'personal_sign', params: [msg, accounts[0]] });`. In wagmi v2 add an `injected({ target: { id: 'frame', name: 'Frame', provider: (w) => w?.frame ?? (w?.ethereum?.isFrame ? w.ethereum : undefined) } })` connector and rely on EIP-6963 multi-wallet discovery for users with MetaMask also installed. For Foundry/Hardhat scripts use `--frame` (or `eth-provider`) to route signing through the desktop app — the user approves every transaction in Frame's native UI.
- ⚑Provider detection collisions: when MetaMask and Frame are both installed, whichever loads last wins `window.ethereum` — always use EIP-6963 (`eip6963:announceProvider`) and pick the provider whose `info.rdns === 'sh.frame'` rather than reading `window.ethereum` directly.
- ⚑Frame is a native desktop app — there is no mobile build; mobile users see no wallet at all unless you fall back to WalletConnect or another connector. Branch on `navigator.userAgent` and hide Frame from mobile UIs.
- ⚑Hardware wallets (Ledger, Trezor, GridPlus) routed through Frame have stricter EIP-712 limits than software wallets — long structured data fields are truncated on Ledger; test typed-data signing on real devices, not just MetaMask.
- ⚑The desktop IPC bridge used by `eth-provider('frame')` requires the Frame app to be running; if it's closed, `eth.request` hangs indefinitely without throwing — wrap calls in a timeout (e.g. `Promise.race` with 5–10s) and surface a clear 'Open Frame' error.
- ⚑Frame's browser extension lifecycle is unusual: on extension reload (or browser update) the injected provider object is replaced, but EIP-1193 event subscriptions are NOT replayed — re-bind `accountsChanged` / `chainChanged` listeners on every provider re-detection.
- ⚑Account-abstraction / smart-contract wallets (ERC-4337, Safe) are not supported natively by Frame — it signs as an EOA only. Don't expose Frame in account-abstraction-only flows or signatures will fail ERC-1271 verification on the receiving side.