diff --git a/bun.lock b/bun.lock
index c67ae89..a1475ad 100644
--- a/bun.lock
+++ b/bun.lock
@@ -41,6 +41,7 @@
"@radix-ui/react-tooltip": "^1.2.8",
"@tailwindcss/vite": "^4.1.18",
"@tanstack/react-query": "^5.90.20",
+ "boring-avatars": "^2.0.4",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
@@ -719,6 +720,8 @@
"blakejs": ["blakejs@1.2.1", "", {}, "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ=="],
+ "boring-avatars": ["boring-avatars@2.0.4", "", { "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-xhZO/w/6aFmRfkaWohcl2NfyIy87gK5SBbys8kctZeTGF1Apjpv/10pfUuv+YEfVPkESU/h2Y6tt/Dwp+bIZPw=="],
+
"bottleneck": ["bottleneck@2.19.5", "", {}, "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="],
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
diff --git a/package.json b/package.json
index a29fa9c..52258db 100644
--- a/package.json
+++ b/package.json
@@ -52,6 +52,7 @@
"@radix-ui/react-tooltip": "^1.2.8",
"@tailwindcss/vite": "^4.1.18",
"@tanstack/react-query": "^5.90.20",
+ "boring-avatars": "^2.0.4",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
diff --git a/src/components/account-avatar.tsx b/src/components/account-avatar.tsx
new file mode 100644
index 0000000..bb370cd
--- /dev/null
+++ b/src/components/account-avatar.tsx
@@ -0,0 +1,58 @@
+import BoringAvatar from 'boring-avatars'
+import { EyeIcon } from 'lucide-react'
+import { cn } from '@/lib/utils'
+
+const ACCOUNT_AVATAR_COLORS = [
+ '#1ADEF5',
+ '#03C1DB',
+ '#61F0FE',
+ '#0C131B',
+ '#152A38',
+ '#47CD89',
+ '#FABC3C',
+]
+
+const SIZE_STYLES = {
+ xs: { className: 'h-6 w-6', pixelSize: 24 },
+ sm: { className: 'h-8 w-8', pixelSize: 32 },
+ md: { className: 'h-10 w-10', pixelSize: 40 },
+ lg: { className: 'h-12 w-12', pixelSize: 48 },
+} as const
+
+type AccountAvatarProps = {
+ identity: string
+ name?: string
+ watchOnly?: boolean
+ size?: keyof typeof SIZE_STYLES
+ className?: string
+}
+
+const AccountAvatar = ({
+ identity,
+ name,
+ watchOnly = false,
+ size = 'md',
+ className,
+}: AccountAvatarProps) => {
+ const { className: sizeClassName, pixelSize } = SIZE_STYLES[size]
+ const avatarName = name?.trim() ? `${name}-${identity}` : identity
+
+ return (
+
+
+ {watchOnly && (
+
+
+
+ )}
+
+ )
+}
+
+export default AccountAvatar
diff --git a/src/components/app-header.tsx b/src/components/app-header.tsx
index 5467289..2c1ba69 100644
--- a/src/components/app-header.tsx
+++ b/src/components/app-header.tsx
@@ -1,12 +1,5 @@
-import {
- CopyIcon,
- EyeIcon,
- XIcon,
- PanelRightOpenIcon,
- PlusIcon,
- UsersIcon,
- WalletIcon,
-} from 'lucide-react'
+import { CopyIcon, EyeIcon, XIcon, PanelRightOpenIcon, PlusIcon, UsersIcon } from 'lucide-react'
+import AccountAvatar from '@/components/account-avatar'
import { Button } from '@/components/ui/button'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { truncateString } from '@/lib/utils'
@@ -59,6 +52,10 @@ const AppHeader = ({
Array<{ name: string; identity: string; watchOnly?: boolean }>
>([])
const [isMenuOpen, setIsMenuOpen] = useState(false)
+ const activeAccount = useMemo(
+ () => accounts.find((account) => account.identity === identity),
+ [accounts, identity],
+ )
const refreshAccounts = useCallback(() => {
const nextAccountName =
@@ -160,9 +157,12 @@ const AppHeader = ({
className="flex min-w-0 items-center gap-3 text-left"
aria-label={t('home.accounts.selectLabel')}
>
-
-
-
+
{accountName}
@@ -212,10 +212,17 @@ const AppHeader = ({
key={account.identity}
type="button"
onClick={() => handleSelectAccount(account)}
- className={`flex w-full items-center rounded-md px-2 py-2 text-left text-sm transition hover:bg-muted/30 ${
+ className={`flex w-full items-center gap-3 rounded-md px-2 py-2 text-left text-sm transition hover:bg-muted/30 ${
account.identity === identity ? 'bg-muted/20' : ''
}`}
>
+
diff --git a/src/components/dapp/dapp-approval-drawer.tsx b/src/components/dapp/dapp-approval-drawer.tsx
index 0931c89..89a61a9 100644
--- a/src/components/dapp/dapp-approval-drawer.tsx
+++ b/src/components/dapp/dapp-approval-drawer.tsx
@@ -2,6 +2,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useLocation } from 'react-router-dom'
import { ChevronDownIcon, ChevronUpIcon, GlobeIcon, Link2OffIcon, LinkIcon } from 'lucide-react'
+import AccountAvatar from '@/components/account-avatar'
import { Button } from '@/components/ui/button'
import {
Drawer,
@@ -282,12 +283,21 @@ const DappApprovalDrawer = () => {
{t('dapp.approval.sharedAccount')}
-
- {connectSummary.accountName || t('dapp.approval.sharedAccountFallback')}
-
-
- {truncateString(connectSummary.accountIdentity)}
-
+
+
+
+
+ {connectSummary.accountName || t('dapp.approval.sharedAccountFallback')}
+
+
+ {truncateString(connectSummary.accountIdentity)}
+
+
+
)}
{current.method === 'signMessage' && (
@@ -371,15 +381,25 @@ const DappApprovalDrawer = () => {
)}
{isWatchOnlySigningRequest && accountSummary && (
-
- {t('dapp.approval.watchOnlyTitle')}
-
-
- {t('dapp.approval.watchOnlyDescription', {
- accountName:
- accountSummary.accountName || t('dapp.approval.sharedAccountFallback'),
- })}
-
+
+
+
+
+ {t('dapp.approval.watchOnlyTitle')}
+
+
+ {t('dapp.approval.watchOnlyDescription', {
+ accountName:
+ accountSummary.accountName || t('dapp.approval.sharedAccountFallback'),
+ })}
+
+
+
)}
{requiresPassphrase && !isWatchOnlySigningRequest && (
diff --git a/src/components/pages/manage-accounts/account-list-item.tsx b/src/components/pages/manage-accounts/account-list-item.tsx
index 763a269..e4afdd1 100644
--- a/src/components/pages/manage-accounts/account-list-item.tsx
+++ b/src/components/pages/manage-accounts/account-list-item.tsx
@@ -8,6 +8,7 @@ import {
TrashIcon,
} from 'lucide-react'
import { useTranslation } from 'react-i18next'
+import AccountAvatar from '@/components/account-avatar'
import { Button } from '@/components/ui/button'
import {
DropdownMenu,
@@ -76,6 +77,12 @@ const AccountListItem = ({
} ${isDragging ? 'opacity-60' : ''}`}
>