diff --git a/README.md b/README.md
index 70a8d52..9b26132 100644
--- a/README.md
+++ b/README.md
@@ -34,13 +34,13 @@ Rivet is still the best dev tool that works well in the development flow of use
## Download
-- **Chromium (Chrome, Brave, Arc, etc)** [TBD]
+- **Chromium (Chrome, Brave, Arc, etc)** [[Download]](https://chromewebstore.google.com/detail/emajibkjkkilgdahffjhapcljjhhdpeb?utm_source=item-share-cb)
- **Firefox**: coming soon
- **Safari**: coming soon
### Nightly Release
-DW: DevWallet is currently in active development. If you would like to try out the latest features, you can download the latest nightly build below:
+DevWallet is currently in active development. If you would like to try out the latest features, you can download the latest nightly build below:
- **Chromium (Chrome, Brave, Arc, etc)**: [Download](https://github.com/D01-DayOne/dev-wallet/releases/latest)
@@ -147,11 +147,19 @@ bun run dev
This will run a script that will build the Web Extension, start a dev server for the Test Dapp, and automatically open Chrome with a fresh profile and the extension installed.
-## Known Issues
+## Multi-Wallet Support
-DW: DevWallet uses the `window.ethereum` interface, which means it has some known conflicts with other wallets which also rely on `window.ethereum`. Once Dapps start to integrate [EIP-6963](https://eips.ethereum.org/EIPS/eip-6963) to handle multiple injected wallets, this should not be a problem anymore.
+DW: DevWallet supports both legacy `window.ethereum` injection and modern [EIP-6963](https://eips.ethereum.org/EIPS/eip-6963) multi-wallet discovery.
-For best results it is recommended to run DW: DevWallet in its own Chrome profile, without any other conflicting browser wallets installed.
+**EIP-6963 Support:**
+- DevWallet announces itself via EIP-6963, allowing dapps to discover it alongside other wallets
+- If another wallet (MetaMask, Coinbase, etc.) is already installed, DevWallet will NOT overwrite `window.ethereum` to avoid conflicts
+- Dapps that support EIP-6963 can present users with a wallet selector to choose between DevWallet and other installed wallets
+- The test dapp (`bun run dapp`) demonstrates EIP-6963 wallet discovery
+
+**Legacy Dapp Compatibility:**
+- If no other wallet is present, DevWallet will inject itself as `window.ethereum` for compatibility with older dapps
+- For testing legacy dapps, run DevWallet in its own Chrome profile without other wallets installed
Helpful note: A fresh Chrome profile gets instantiated when running the dev script: `bun run dev`.
diff --git a/src/components/Container.tsx b/src/components/Container.tsx
index 2c19d1a..bf520b1 100644
--- a/src/components/Container.tsx
+++ b/src/components/Container.tsx
@@ -1,15 +1,6 @@
import type { ReactNode } from 'react'
import { useNavigate } from 'react-router'
-import {
- Box,
- Button,
- Inline,
- Inset,
- Row,
- Rows,
- Separator,
- Text,
-} from '~/design-system'
+import { Box, Button, Inset, Row, Rows, Separator, Text } from '~/design-system'
import type { RowProps } from '~/design-system/components/Rows'
export function Container({
@@ -48,19 +39,17 @@ export function Container({
display="flex"
paddingHorizontal="8px"
width="full"
- style={{ minHeight: '44px' }}
+ style={{ minHeight: '44px', gap: '12px' }}
>
-
+
{typeof header === 'string' ? (
{header}
) : (
header
)}
- {dismissable && (
+
+ {dismissable && (
+
- )}
-
+
+ )}
diff --git a/src/components/Header.tsx b/src/components/Header.tsx
index 1910ece..ef6afd4 100644
--- a/src/components/Header.tsx
+++ b/src/components/Header.tsx
@@ -1,4 +1,11 @@
-import { type ReactNode, useLayoutEffect, useMemo, useState } from 'react'
+import {
+ type ReactNode,
+ useEffect,
+ useLayoutEffect,
+ useMemo,
+ useRef,
+ useState,
+} from 'react'
import { Link } from 'react-router-dom'
import { type Hex, formatGwei } from 'viem'
@@ -133,7 +140,33 @@ function Account() {
const [key, setKey] = useState(0)
useLayoutEffect(() => {
requestAnimationFrame(() => setKey((key) => key + 1))
- }, [])
+ }, [account?.address])
+
+ // Flash animation when account changes
+ const [isFlashing, setIsFlashing] = useState(false)
+ const [transitionDuration, setTransitionDuration] = useState('200ms')
+ const prevAccountRef = useRef(account?.address)
+
+ useEffect(() => {
+ if (
+ account?.address &&
+ account.address !== prevAccountRef.current &&
+ prevAccountRef.current !== undefined
+ ) {
+ // Fast switch to flash color (50ms)
+ setTransitionDuration('50ms')
+ setIsFlashing(true)
+
+ // Then slowly fade back (200ms)
+ const fadeTimer = setTimeout(() => {
+ setTransitionDuration('200ms')
+ setIsFlashing(false)
+ }, 50)
+
+ return () => clearTimeout(fadeTimer)
+ }
+ prevAccountRef.current = account?.address
+ }, [account?.address])
if (!account) return null
return (
@@ -145,7 +178,13 @@ function Account() {
}}
display="flex"
height="full"
- style={{ cursor: 'default' }}
+ style={{
+ cursor: 'default',
+ transition: `background-color ${transitionDuration} ease-out`,
+ ...(isFlashing && {
+ backgroundColor: 'var(--flash-color)',
+ }),
+ }}
>
{account && (
diff --git a/src/components/tabs/TabsList.tsx b/src/components/tabs/TabsList.tsx
index da3873c..2371aaf 100644
--- a/src/components/tabs/TabsList.tsx
+++ b/src/components/tabs/TabsList.tsx
@@ -1,6 +1,6 @@
import * as Tabs_ from '@radix-ui/react-tabs'
-import { Bleed, Box, Inline, Separator, Text } from '~/design-system'
+import { Bleed, Box, Column, Columns, Separator, Text } from '~/design-system'
import * as styles from './TabsList.css'
@@ -16,27 +16,29 @@ export function TabsList({ items, onSelect }: TabsListProps) {
<>