Disclaimer: Bear in mind this is still a project in early development. It still needs further testing and polishing. Feedback and contributions are welcome!
A 100% local web interface for managing multisignature wallets inspired by SafeWallet and EternalSafeWallet. No worrying about the SafeAPI being compromised... Run an instance yourself!
v0.2.0 - Now with IPFS deployment support and enhanced UI!
- Safe Account Dashboard: View Safe details, owners, threshold, nonce, and balance with enhanced UI organization.
- Transaction Workflow: Create, import, export, and execute Safe transactions with improved collaboration tools.
- WalletConnect Integration: Sign messages and transactions from dApps via WalletConnect v2.
- IPFS Deployment: Automated deployment to IPFS via Pinata when creating GitHub releases.
- SafeWallet Data Import/Export: Backup and restore address book, visited accounts, and undeployed safes.
- Calldata Decoding: Decode transaction calldata directly in the UI for better transparency.
- Collaboration Tools: Easy sharing of transactions, signatures, and links with organized dropdown menus.
- Wallet Connection: MetaMask and RainbowKit integration with multiple wallet support.
- Client-Side State: All wallet and Safe logic is handled client-side using wagmi, RainbowKit, and Safe Protocol Kit.
- Hash-Based Routing: Uses React Router with hash-based routing for static IPFS deployment compatibility.
- Node.js v18+
- pnpm
- Anvil (for E2E tests)
-
Install pnpm.
-
Clone the repository and install dependencies:
git clone https://github.com/cyfrin/localsafe.eth
cd localsafe.eth
pnpm install- Create a
.envfile in the root (take.env.exampleas a reference):
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_walletconnect_project_id- Start the development server:
pnpm dev- Open your browser and navigate to
http://localhost:3000.
Note: The testing infrastructure is currently in need of refactoring from Synpress. The existing tests may require updates to work with the latest changes.
To run the app with a production build locally and run the optimized version:
pnpm run localsafeLocalSafe can be automatically deployed to IPFS via Pinata when you create a GitHub release or push a version tag. See DEPLOYMENT.md for complete setup instructions.
Quick Deploy:
# Create and push a version tag
git tag v0.2.0
git push origin v0.2.0
# Or create a GitHub Release via the UIThe deployment workflow will:
- Build the static site (
pnpm run build) - Deploy to IPFS via Pinata
- Output the IPFS CID and gateway URLs in the GitHub Actions logs
Access your deployment:
- Pinata Gateway:
https://gateway.pinata.cloud/ipfs/<CID> - IPFS Gateway:
https://ipfs.io/ipfs/<CID> - Cloudflare IPFS Gateway:
https://cloudflare-ipfs.com/ipfs/<CID>
To ensure deterministic E2E tests, we use Anvil’s state management:
- After setting up contracts and accounts, run:
This creates a snapshot of the chain state in
anvil --dump-state ./anvil-safe-state.json
anvil-safe-state.json. - For all test runs, start Anvil with:
This restores the chain to the known state for reproducible tests.
anvil --load-state ./anvil-safe-state.json --block-time 1
- The test runner script and package.json use this approach:
"anvil": "anvil --load-state ./anvil-safe-state.json --block-time 1", "test:e2e": "bash tests/scripts/start-anvil-and-test.sh"
- Client-Side Architecture: All wallet and Safe logic is handled client-side for maximum privacy and flexibility.
- Hash-Based Routing: Uses React Router with hash-based routing (
HashRouter) to ensure compatibility with static IPFS deployments where server-side routing is not available. - Modular Structure: The project structure is modular, with reusable components and hooks for maintainability.
- WalletConnect Integration: WalletConnect v2 is integrated for dApp connections and signing requests. Session data is persisted in localStorage.
- Process Cleanup: Sometimes
next-serverandanvilprocesses may remain running in the background. Usepnpm run test:cleanto kill them. - Local Contract Deployment: For deploying Safe contracts locally, see the instructions below.
To run your own local Safe contracts for development, follow these steps:
- Clone the Repository
git clone https://github.com/safe-global/safe-smart-account.git cd safe-smart-account - Checkout the Correct Version
git checkout tags/v1.4.1-3
- Install Dependencies and Build
npm install npm run build
- Start a Local Anvil Node
anvil
- Create a
.envFileMNEMONIC="test test test test test test test test test test test junk" NODE_URL="http://127.0.0.1:8545"
- Deploy Contracts
npx hardhat --network custom deploy
- Update Contract Addresses
- After deployment, copy the contract addresses from the output and update them in your project’s
localContractNetworks.tsfile.
- After deployment, copy the contract addresses from the output and update them in your project’s
Note: Currently, contract addresses are manually maintained in
localContractNetworks.ts. In the future, we may automate this process or use environment variables for better flexibility.
-
Refactor E2E testing infrastructure from Synpress to support latest features.
-
Improve devcontainer setup for E2E tests; currently, UI mode has limitations.
-
Ensure smooth DX when switching between local and devcontainer environments and wild processes cleaning (next-server, anvil).
-
Adapt for different SafeWallet contract versions (currently optimized for 1.4.1-3).
-
Automate
versionvalue inDEFAULT_SAFE_WALLET_DATAconstant (app/utils/constants.tshardcoded to3.0.0now). -
Add ENS name resolution for addresses in the UI.
-
Implement transaction history and filtering.
-
Extract out the EIP-712 data to it's own component for reusability.
-
Run linter
- SafeSDK: Protocol Kit
- wagmi
- RainbowKit
- WalletConnect
- React Router
- Synpress
- Playwright
- Foundry
- Pinata
- IPFS
- Tailwind CSS
- DaisyUI
Special thanks to all contributors!