From e47cd35a349a5d9e2ecb9a5a0e2203922acb97e7 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Wed, 11 Mar 2026 14:23:00 -0700 Subject: [PATCH] feat(identity): add My Wallets panel to avatar dropdown Adds a wallet modal accessible from the identity dropdown showing: - rIdentity wallet card with username, DID, and passkey badge - Browser wallet discovery via EIP-6963 (MetaMask, Rainbow, etc.) - Connect flow with eth_requestAccounts - Quick link to open the full rWallet module Co-Authored-By: Claude Opus 4.6 --- shared/components/rstack-identity.ts | 216 ++++++++++++++++++++++++++- 1 file changed, 215 insertions(+), 1 deletion(-) diff --git a/shared/components/rstack-identity.ts b/shared/components/rstack-identity.ts index 1da3f8e..3015ddc 100644 --- a/shared/components/rstack-identity.ts +++ b/shared/components/rstack-identity.ts @@ -6,7 +6,7 @@ * Refactored from lib/rspace-header.ts into a standalone web component. */ -import { rspaceNavUrl, getCurrentModule } from "../url-helpers"; +import { rspaceNavUrl, getCurrentModule, getCurrentSpace } from "../url-helpers"; import { resetDocBridge, isEncryptedBackupEnabled, setEncryptedBackupEnabled } from "../local-first/encryptid-bridge"; const SESSION_KEY = "encryptid_session"; @@ -28,6 +28,32 @@ interface SessionState { }; } +// ── EIP-6963 browser wallet discovery ── + +interface _EIP6963Provider { + info: { uuid: string; name: string; icon: string; rdns: string }; + provider: { request: (args: { method: string; params?: unknown[] }) => Promise }; +} + +class _WalletDiscovery { + providers: _EIP6963Provider[] = []; + #cb: (() => void) | null = null; + + start(onChange: () => void) { + this.#cb = onChange; + window.addEventListener("eip6963:announceProvider", ((e: CustomEvent) => { + const detail = e.detail as _EIP6963Provider; + if (!this.providers.some((p) => p.info.uuid === detail.info.uuid)) { + this.providers.push(detail); + this.#cb?.(); + } + }) as EventListener); + window.dispatchEvent(new Event("eip6963:requestProvider")); + } + + stop() { this.#cb = null; } +} + // ── Cross-subdomain cookie helpers ── function _isRspace(): boolean { @@ -353,6 +379,7 @@ export class RStackIdentity extends HTMLElement { +