Skip to main content

πŸ—οΈ Architecture Deep Dive

Explore the intricate details of SuperSafe Wallet's Professionally Standardized Service Worker architecture and understand how each component works together.

Executive Summary​

SuperSafe Wallet is a modern Ethereum-compatible browser extension wallet implementing a Professionally Standardized Service Worker architecture with Smart Native Connection for seamless multichain dApp integration. Built with React 18, ethers.js v6, and Chrome Extension Manifest V3.

Key Architectural Features​

  • βœ… Professionally Standardized Architecture: Service worker as single source of truth
  • βœ… Smart Native Connection: Real chainIds only, zero compatibility hacks
  • βœ… Multichain Support: 7 active networks (SuperSeed, Optimism, Ethereum, Base, BSC, Arbitrum, Shardeum)
  • βœ… Stream-Based Communication: Native Chrome long-lived connections
  • βœ… Unified Vault System: Military-grade AES-256-GCM encryption
  • βœ… Thin Client Pattern: Frontend as lightweight presentation layer
  • βœ… Enterprise Signing System: Robust request management and recovery
  • βœ… Bebop Integration: Native swap support with partner fees
  • βœ… Relay.link Integration: Cross-chain swaps across 85+ blockchains
  • βœ… WalletConnect V2: Full Reown WalletKit implementation
  • βœ… Framework Detection: Automatic dApp framework identification

System Metrics​

Total Project Files: 183 JavaScript/JSX files
Total Lines of Code: ~25,000 lines
Architecture Pattern: Professionally Standardized Service Worker
Security Level: Military-grade encryption
Supported Networks: 7 active networks
Response Time: <150ms average
Vault Encryption: AES-256-GCM + PBKDF2

System Architecture​

High-Level Architecture Diagram​

graph TB
subgraph "Chrome Browser Environment"
subgraph "Web Pages Context"
DAPP[🌐 dApp Websites]
PROVIDER[πŸ“‘ EIP-1193 Provider]
CONTENT[πŸ“œ Content Script]
end

subgraph "Extension Context"
POPUP[πŸ–₯️ Popup UI - React]
BACKGROUND[βš™οΈ Background Service Worker]
end

subgraph "Storage Layer"
VAULT[πŸ”’ Unified Vault]
SESSION[πŸ’Ύ Session Storage]
LOCAL[πŸ—„οΈ Local Storage]
end
end

subgraph "External Services"
SUPERSEED[🌟 SuperSeed RPC]
BEBOP[πŸ”„ Bebop Swap API]
RELAY[πŸŒ‰ Relay.link Cross-Chain]
WALLETCONNECT[πŸ”— WalletConnect/Reown]
APIS[πŸ“Š Price & Token APIs]
end

%% Communication Flow
DAPP --> PROVIDER
PROVIDER --> CONTENT
CONTENT -.Stream.-> BACKGROUND
POPUP -.Stream.-> BACKGROUND

BACKGROUND --> VAULT
BACKGROUND --> SESSION
BACKGROUND --> LOCAL

BACKGROUND --> SUPERSEED
BACKGROUND --> BEBOP
BACKGROUND --> RELAY
BACKGROUND --> WALLETCONNECT
BACKGROUND --> APIS

style DAPP fill:#e1f5fe
style POPUP fill:#f3e5f5
style BACKGROUND fill:#fff3e0
style VAULT fill:#ffebee

Component Interaction Model​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Frontend (Thin Client) β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ React UI β”‚ β”‚ Adapters β”‚ β”‚ Stream Manager β”‚ β”‚
β”‚ β”‚ Components β”‚β†’β†’β”‚ (Frontend) β”‚β†’β†’β”‚ (Long-lived ports) β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ Chrome Streams
↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Background Script (Single Source of Truth) β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Stream Handlers β”‚ β”‚
β”‚ β”‚ - Session - Provider - Swap - Send - Blockchain β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Core Controllers β”‚ β”‚
β”‚ β”‚ - BackgroundSessionController (3,979 lines) β”‚ β”‚
β”‚ β”‚ - BackgroundControllers (497 lines) β”‚ β”‚
β”‚ β”‚ β€’ TokenController β€’ NetworkController β”‚ β”‚
β”‚ β”‚ β€’ TransactionController β€’ NetworkSwitchService β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Enterprise Managers β”‚ β”‚
β”‚ β”‚ - SigningRequestManager - PopupManager β”‚ β”‚
β”‚ β”‚ - EIP1193EventsManager - AutoEscalationManager β”‚ β”‚
β”‚ β”‚ - StreamPersistenceManager β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Handler Layer β”‚ β”‚
β”‚ β”‚ - walletHandlers - contractHandlers β”‚ β”‚
β”‚ β”‚ - providerHandlers - AllowListManager β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ External Integrations β”‚ β”‚
β”‚ β”‚ - WalletConnect Manager - Bebop Integration β”‚ β”‚
β”‚ β”‚ - Relay.link Integration - Cross-chain swaps β”‚ β”‚
β”‚ β”‚ - Transaction History Service - Explorer Adapters β”‚ β”‚
β”‚ β”‚ - SuperSeed API Wrapper - Secure API Client β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Storage Layer β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Unified Vaultβ”‚ β”‚ Session β”‚ β”‚ Local β”‚ β”‚
β”‚ β”‚ (Encrypted) β”‚ β”‚ Storage β”‚ β”‚ Storage β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Core Design Principles​

1. Single Source of Truth​

All state lives in the background service worker.

  • Frontend components are purely presentational
  • No direct storage access from frontend
  • All mutations go through background controllers
  • State synchronization via Chrome streams

Benefits:

  • Eliminates race conditions
  • Prevents storage context isolation issues
  • Simplified state management
  • Single point of control for security

2. Thin Client Pattern​

Frontend is a lightweight presentation layer.

// ❌ WRONG: Frontend doing business logic
const wallet = await createWallet(privateKey);
await saveToStorage(wallet);

// βœ… CORRECT: Frontend delegates to background
const result = await FrontendSessionAdapter.createWallet(privateKey);

Frontend Responsibilities:

  • Render UI components
  • Handle user input
  • Display data from background
  • Route user actions to background

Background Responsibilities:

  • State management
  • Cryptographic operations
  • Storage access
  • Business logic
  • External API calls

3. Stream-Based Communication​

Native Chrome long-lived connections for efficiency.

// Frontend creates persistent connection
const port = chrome.runtime.connect({ name: 'session' });

// Background listens on named channels
backgroundStreamManager.onMessage('session', async (message, port) => {
// Handle message
return { success: true, data: result };
});

Stream Channels:

  • session - Session and wallet operations
  • provider - dApp provider requests (EIP-1193)
  • swap - Swap quote and execution
  • send - Token transfer operations
  • blockchain - Blockchain queries
  • api - External API calls

4. Zero Frontend Crypto​

All cryptographic operations isolated in background.

  • Private keys never leave background context
  • Vault encryption/decryption in background only
  • Signing operations in background only
  • Password handling in background only

Security Benefits:

  • Reduced attack surface
  • Memory isolation
  • Audit-friendly architecture
  • Simplified security model

5. Professionally Standardized Controllers​

Modular controller pattern for separation of concerns.

BackgroundControllers {
tokenController // ERC20 token management
networkController // Network switching & configuration
transactionController // Transaction history & management
networkSwitchService // Centralized network switching
}

Each controller:

  • Single responsibility
  • Independent initialization
  • Event-driven architecture
  • Stateless where possible

Component Architecture​

Background Script (3,220 lines)​

Location: src/background.js

Primary Responsibilities:

  • Service worker initialization and lifecycle
  • Stream handler registration
  • Manager orchestration
  • WalletConnect integration
  • Global state coordination

Key Components:

// Core Controllers
backgroundSessionController // Session & wallet management
backgroundControllers // Token, network, transaction controllers

// Enterprise Managers
signingRequestManager // Signing request lifecycle
popupManager // Popup window management
eip1193EventsManager // EIP-1193 event broadcasting
autoEscalationManager // Auto-approval for trusted dApps

// External Integrations
walletConnectManager // WalletConnect v2 / Reown
secureApiClient // Secure external API calls
bebopTokenService // Bebop token list management

BackgroundSessionController (3,979 lines)​

Location: src/background/BackgroundSessionController.js

Core Functionality:

  • Vault management (create, unlock, lock)
  • Wallet management (create, import, remove)
  • Session state management
  • Auto-lock functionality
  • Connected sites management
  • Network switching coordination

Session State:

{
isUnlocked: boolean,
password: string (memory only),
vaultData: Object (decrypted),
decryptedWallets: Map<address, privateKey>,
connectedSites: Map<origin, siteData>,
currentNetworkKey: string
}

BackgroundControllers (497 lines)​

Location: src/background/BackgroundControllers.js

Architecture:

class BackgroundControllers {
tokenController // ERC20 operations
networkController // Network management
transactionController // Transaction history
networkSwitchService // Unified switching

async initialize(networkKey, provider, getPrivateKeyFn)
async handleTokenMessage(message)
async handleNetworkMessage(message)
async handleTransactionMessage(message)
}

Frontend Application (1,569 lines)​

Location: src/App.jsx

Main React Component:

  • Screen routing logic
  • Modal management
  • Connection request handling
  • Transaction confirmation
  • Signing request UI
  • Network switch consent

State Management:

// Wallet state (from background)
const {
currentWallet,
wallets,
network,
isUnlocked,
supportsSwap
} = useWalletProvider();

Swap Architecture (v2.0.0 - Refactored Nov 2025)​

Design Philosophy: Unified panel architecture for provider-agnostic swap interface.

Structure:

Swap.jsx (~115 lines)              # Container/Orchestrator
β”œβ”€ SwapProviderSelector # Tab selector (Bebop | Relay)
β”œβ”€ SlippageControl # Shared slippage configuration
└─ Conditional Rendering:
β”œβ”€ BebopSwapPanel.jsx (~1,400 lines) # Bebop JAM protocol
└─ RelaySwapPanel.jsx (~1,288 lines) # Relay.link cross-chain

Key Benefits:

  1. βœ… Consistency: Both panels follow same architectural pattern
  2. βœ… Maintainability: Each panel is self-contained and independently testable
  3. βœ… Scalability: Easy to add new providers (Uniswap, 1inch, etc.)
  4. βœ… Separation of Concerns: Swap.jsx only handles routing, not implementation
  5. βœ… Reduced Complexity: From 2,206 lines monolith to 115-line orchestrator

BebopSwapPanel (~1,400 lines):

  • Gasless MEV-protected swaps via Bebop JAM protocol
  • Permit2 approvals (one-time per token)
  • Internal components: LoadingDots, PriceDeviationTooltip, SwapDetails
  • Uses SwapAdapter for all backend communication
  • NO ethers imports (architecture compliance)

RelaySwapPanel (~1,288 lines):

  • Cross-chain swaps via Relay.link
  • Network selection: Origin fixed (active network), Destination selectable
  • Internal components: UsdBalanceDisplay, formatTokenAmount
  • Uses RelayAdapter for all backend communication
  • Advanced features: Route visualization, gas estimation, bridge time

Stream Handlers​

Location: src/background/handlers/streams/

HandlerPurposeKey Operations
SessionStreamHandlerSession operationsunlock, createWallet, switchWallet
ProviderStreamHandlerdApp requestseth_requestAccounts, eth_sendTransaction
SwapStreamHandlerBebop swapsgetQuote, signOrder, checkStatus
SendStreamHandlerToken transfersestimateGas, sendTransaction
BlockchainStreamHandlerBlockchain queriesgetBalance, getTokens, getNFTs
ApiStreamHandlerExternal APIsprice feeds, token lists

Managers​

Location: src/background/managers/

ManagerPurposeKey Features
SigningRequestManagerSigning request lifecycleTimeout protection, request recovery
PopupManagerPopup window managementMutual exclusion, priority system
EIP1193EventsManagerEvent broadcastingaccountsChanged, chainChanged
AutoEscalationManagerAuto-approval systemTrusted dApp whitelist
WalletConnectManagerWalletConnect v2Session management, request handling

Services​

Location: src/background/services/

ServicePurposeImplementation
TokenMetadataServiceToken metadata lookupMulti-layer: Cache β†’ BebopTokenService β†’ RPC
BebopTokenServiceToken list managementLocal database, 2000+ tokens
NetworkSwitchServiceUnified network switchingBidirectional dApp-wallet sync

Transaction Decoder Architecture​

Overview​

SuperSafe Wallet implements a professional-grade transaction decoding system that transforms raw blockchain transactions into human-readable information. The system supports major DEX protocols (Uniswap V2/V3/V4, PancakeSwap Infinity, Velodrome, Aerodrome) across 7 EVM networks with a strict "no fallbacks" security policy.

Core Components​

TransactionDecoder - Main orchestrator (src/background/decoders/TransactionDecoder.js)

  • Routes transactions to specialized decoders based on function selector
  • Manages token metadata resolution
  • Enforces strict "no fallbacks" policy

UniversalRouterDecoder - Universal Router transactions (src/background/decoders/UniversalRouterDecoder.js)

  • Decodes Uniswap and Velodrome Universal Router transactions
  • Supports 11 command types (V2/V3/V4 swaps, wrap/unwrap, permit2)
  • Context-aware opcode interpretation (detects Uniswap vs PancakeSwap)

UniversalRouterDecoderPancake - PancakeSwap Infinity (src/background/decoders/UniversalRouterDecoderPancake.js)

  • Specialized decoder for PancakeSwap Infinity concentrated liquidity swaps
  • Heuristic-based decoding for complex CL structures
  • Handles both native (BNB) and ERC-20 inputs

TokenMetadataService - Token metadata management (src/background/services/TokenMetadataService.js)

  • Multi-layer lookup: Cache β†’ BebopTokenService β†’ On-Chain RPC
  • LRU cache with 1000 entry limit
  • Strict validation with no fallbacks
  • Request deduplication to prevent redundant RPC calls

Protocol Support​

ProtocolNetworksStatus
Uniswap V2/V3/V4ETH, OPT, BASEβœ… Full support
Universal RouterETH, OPT, BASE, BSCβœ… Full support
PancakeSwap InfinityBSCβœ… Heuristic decode
VelodromeOptimismβœ… Full support
AerodromeBaseβœ… Full support
ERC-20 OperationsAll networksβœ… Full support
Permit2All networksβœ… Single/batch

"No Fallbacks" Security Policy​

Core Principle: Never use default or guessed values for critical transaction parameters.

Examples:

// βœ… CORRECT
const metadata = await tokenMetadataService.getTokenMetadata(address, chainId, provider);
if (!metadata) {
throw new Error(`Cannot fetch metadata for token ${address}`);
}

// ❌ NEVER DO THIS
const decimals = metadata?.decimals || 18; // Dangerous!

Rationale:

  • Better to show error than incorrect amounts/tokens
  • Prevents user from signing wrong information
  • Eliminates network mismatch risks

Signing System Architecture​

Overview​

Unified signing system handling all signing request types (transactions, personal messages, typed data) with consistent request management, network validation, and security controls.

Core Components​

SigningRequestManager (src/background/managers/SigningRequestManager.js)

  • Centralized manager for all signing requests
  • Request lifecycle management (created β†’ pending β†’ completed/rejected/expired)
  • Timeout protection (5 minutes default)
  • Request recovery on popup crash

SigningModalAdapter (src/background/adapters/SigningModalAdapter.js)

  • Transforms raw RPC requests into user-friendly modal data
  • Handles personal_sign hex-to-UTF8 decoding
  • Parses eth_signTypedData_v4 structured data
  • Detects Permit2 approvals for enhanced UI

Supported Signing Methods​

MethodStatusPurpose
personal_signβœ… ActiveSIWE, message authentication
eth_signTypedData_v4βœ… ActivePermit2, structured data
eth_signTypedData_v3βœ… ActiveLegacy support
eth_sign❌ DisabledBlind signing risk

Snake_case Support: Both personal_sign and personalSign work (industry compatibility).

Request Lifecycle​

1. createRequest() β†’ Generate requestId, set timeout
2. buildModalRequestFromRpc() β†’ Transform to modal format
3. createSigningPopup() β†’ Show popup to user
4. User approves/rejects
5. handleResponse() β†’ Process response
6. Complete/reject/expire β†’ Cleanup

Security Validation​

Network Validation:

validateSigningNetwork(chainId, supportedNetworks, origin)
  • Prevents signing on unsupported networks
  • Clear error messages
  • Protects against replay attacks

eth_sign Disablement:

  • Permanently disabled for security
  • Returns error code 4200
  • Users must use personal_sign or eth_signTypedData_v4

dApp Connection Architecture​

PopupManager Mutual Exclusion​

Purpose: Ensures extension UI and popup windows never coexist (Professionally Standardized UX).

Implementation:

  • When popup opens β†’ Extension closes
  • When extension opens while popup active β†’ Extension closes, popup gains focus
  • Applies to ALL popup types

Popup Priority Order:

  1. Personal Sign
  2. Typed Data
  3. Transaction
  4. Network Switch
  5. Connection
  6. Unlock

Network Management​

Bidirectional Network Switching:

SuperSafe supports network switching initiated from both sides:

  1. Extension β†’ dApp: User changes network in wallet β†’ eth_chainChanged event propagated to all connected dApps
  2. dApp β†’ Wallet: dApp requests network switch via wallet_switchEthereumChain β†’ Popup shown to user

Network Validation:

validateSigningNetwork(chainId, supportedNetworks, origin)
  • Validates signing requests against dApp's supported networks
  • Prevents cross-network signing attacks
  • Shows clear error for unsupported networks

Stream Architecture​

Long-Lived Connections:

SuperSafe uses native Chrome message ports for bidirectional communication:

// Content Script β†’ Background
const port = chrome.runtime.connect({ name: 'provider-stream' });

// Background maintains open connections
providerStreams.set(origin, { port, metadata });

Stream Types:

  • Provider Stream - dApp RPC requests (eth_sendTransaction, personal_sign, etc.)
  • Session Stream - Extension UI communication
  • WalletConnect Stream - Mobile wallet protocol

Lifecycle Management:

  • Streams auto-reconnect on service worker restart
  • Pending requests recovered from memory
  • Disconnect cleanup removes stale connections

Service Worker Lifecycle​

Manifest V3 Architecture​

SuperSafe runs as Manifest V3 service worker with different lifecycle than traditional background pages.

Lifecycle States:

  • Installing β†’ Activated β†’ Running β†’ Idle (30s) β†’ Terminated (5min)
  • Wake-up events restart from Terminated to Running

Wakeup Mechanism​

Problem: Service workers terminate after inactivity, breaking long-lived connections.

Solution: Proactive keep-alive ping system.

Implementation:

// Keep service worker alive with periodic ping
setInterval(() => {
chrome.runtime.getPlatformInfo(() => {
// Ping prevents termination
});
}, 20000); // Every 20 seconds

Benefits:

  • Maintains stream connections
  • Prevents timeout-related disconnections
  • Ensures WalletConnect sessions stay alive
  • Preserves in-memory session state

Persistence Strategy​

  • Critical State β†’ Chrome Storage (encrypted vault, network selection)
  • Session State β†’ In-memory with auto-lock timeout
  • Transient State β†’ Streams with reconnection logic

Session Recovery​

Automatic Corruption Detection:

SuperSafe implements self-healing session restoration that automatically detects and cleans corrupted session data:

// checkPersistentSession() in BackgroundSessionController
const success = await this.restoreSessionWithLoginToken(loginToken, timeElapsed);

if (!success) {
// Auto-cleanup corrupted session data
await this.clearSessionState();
return false; // User sees login screen
}

Recovery Triggers:

  • Decryption failure (OperationError)
  • Invalid credentials (vault mismatch)
  • Restoration exceptions

Benefits:

  • βœ… Prevents error loops on every extension open
  • βœ… Self-healing without user intervention
  • βœ… Maintains vault integrity (only clears session state)

Data Flow Patterns​

Connection Request Flow​

sequenceDiagram
participant D as dApp
participant C as Content Script
participant BG as Background
participant P as Popup
participant U as User

D->>C: window.ethereum.request({method: 'eth_requestAccounts'})
C->>BG: Chrome message (ETH_REQUEST_ACCOUNTS)
BG->>BG: Check allowlist & existing connection

alt Not Connected
BG->>P: Open popup with connection request
P->>U: Display connection request screen
U->>P: Approve/Reject
P->>BG: User decision

alt Approved
BG->>BG: Store connection in connectedSites
BG->>C: Return [address]
C->>D: Resolve with accounts array
BG->>D: Emit 'accountsChanged' event
else Rejected
BG->>C: Return error (4001 User Rejected)
C->>D: Reject promise
end
else Already Connected
BG->>C: Return [address] immediately
C->>D: Resolve with accounts array
end

Transaction Signing Flow​

sequenceDiagram
participant D as dApp
participant BG as Background
participant SM as SigningRequestManager
participant PM as PopupManager
participant P as Popup
participant U as User

D->>BG: eth_sendTransaction
BG->>SM: Create signing request
SM->>SM: Generate requestId
SM->>PM: Request popup
PM->>P: Open signing popup
P->>BG: Request signing data
BG->>P: Return transaction details
P->>U: Display transaction confirmation
U->>P: Approve/Reject

alt Approved
P->>BG: User approved
BG->>BG: Sign transaction with private key
BG->>D: Return transaction hash
SM->>SM: Mark request complete
else Rejected
P->>BG: User rejected
BG->>D: Return error (4001)
SM->>SM: Mark request rejected
end

PM->>P: Close popup

Network Switch Flow​

sequenceDiagram
participant D as dApp
participant BG as Background
participant NS as NetworkSwitchService
participant SC as SessionController
participant P as Popup

D->>BG: wallet_switchEthereumChain
BG->>NS: switchNetwork(chainId, 'dapp_request')

alt Network Supported
NS->>P: Show consent modal
P->>User: Request permission

alt User Approves
User->>NS: Approve
NS->>SC: Update current network
SC->>SC: Persist network change
NS->>BG: Broadcast networkChanged event
BG->>D: Return success
else User Rejects
User->>NS: Reject
NS->>D: Return error (4001)
end
else Network Not Supported
NS->>D: Return error (4902)
end

Technology Stack​

Core Technologies​

TechnologyVersionPurpose
React18.2.0UI framework
ethers.js6.13.0Ethereum library
Vite6.3.6Build tool
TailwindCSS3.3.3Styling
Chrome ExtensionManifest V3Platform

Key Dependencies​

{
"@reown/walletkit": "^1.2.8",
"@reservoir0x/relay-sdk": "^2.4.0",
"@metamask/eth-sig-util": "^8.2.0",
"ethereum-cryptography": "^3.2.0",
"buffer": "^6.0.3",
"idb": "^7.1.1",
"axios": "^1.12.0"
}

Build Configuration​

Multiple Vite Configs:

  • vite.config.js - Frontend popup build
  • vite.config.worker.js - Background service worker
  • vite.config.content.js - Content script injection

Output Structure:

dist/
β”œβ”€β”€ index.html # Popup entry
β”œβ”€β”€ popup.js # Frontend bundle
β”œβ”€β”€ background.js # Service worker bundle
β”œβ”€β”€ content-script.js # Content script bundle
β”œβ”€β”€ provider.js # EIP-1193 provider
β”œβ”€β”€ manifest.json # Extension manifest
└── assets/ # Static resources

Directory Structure​

Backend Architecture​

src/background/
β”œβ”€β”€ BackgroundSessionController.js # Session management (3,979 lines)
β”œβ”€β”€ BackgroundControllers.js # Controller orchestration (497 lines)
β”‚
β”œβ”€β”€ handlers/ # Request handlers
β”‚ β”œβ”€β”€ streams/ # Stream-based handlers
β”‚ β”‚ β”œβ”€β”€ SessionStreamHandler.js # Session operations
β”‚ β”‚ β”œβ”€β”€ ProviderStreamHandler.js # dApp provider requests
β”‚ β”‚ β”œβ”€β”€ SwapStreamHandler.js # Bebop swap operations
β”‚ β”‚ β”œβ”€β”€ SendStreamHandler.js # Token transfers
β”‚ β”‚ β”œβ”€β”€ BlockchainStreamHandler.js # Blockchain queries
β”‚ β”‚ β”œβ”€β”€ ApiStreamHandler.js # External API calls
β”‚ β”‚ └── GenericStreamHandlers.js # Generic utilities
β”‚ β”œβ”€β”€ walletHandlers.js # Wallet operations
β”‚ β”œβ”€β”€ contractHandlers.js # Smart contract calls
β”‚ └── providerHandlers.js # Provider management
β”‚
β”œβ”€β”€ managers/ # Enterprise managers
β”‚ β”œβ”€β”€ SigningRequestManager.js # Signing lifecycle
β”‚ β”œβ”€β”€ PopupManager.js # Popup orchestration
β”‚ β”œβ”€β”€ EIP1193EventsManager.js # Event broadcasting
β”‚ β”œβ”€β”€ AutoEscalationManager.js # Auto-approval logic
β”‚ β”œβ”€β”€ StreamPersistenceManager.js # Stream persistence
β”‚ β”œβ”€β”€ SigningRequestRecovery.js # Request recovery
β”‚ └── SigningRequestDeduplicator.js # Duplicate prevention
β”‚
β”œβ”€β”€ services/ # External services
β”‚ β”œβ”€β”€ NetworkSwitchService.js # Unified network switching
β”‚ β”œβ”€β”€ SecureApiClient.js # Secure HTTP client
β”‚ └── SuperSeedApiWrapper.js # SuperSeed RPC wrapper
β”‚
β”œβ”€β”€ adapters/ # Adapters
β”‚ └── SigningModalAdapter.js # Modal communication
β”‚
β”œβ”€β”€ decoders/ # Data decoders
β”‚ └── TransactionDecoder.js # Transaction decoding
β”‚
β”œβ”€β”€ policy/ # Security policies
β”‚ └── AllowListManager.js # dApp allowlist
β”‚
β”œβ”€β”€ security/ # Security modules
β”‚ β”œβ”€β”€ SimpleRateLimiter.js # Rate limiting
β”‚ └── SimpleBlacklistManager.js # Blacklist management
β”‚
β”œβ”€β”€ config/ # Configuration
β”‚ β”œβ”€β”€ apiConfig.js # API endpoints
β”‚ β”œβ”€β”€ bebopPartnerConfig.js # Bebop partner settings
β”‚ └── walletConnectConfig.js # WalletConnect settings
β”‚
β”œβ”€β”€ strategy/ # Strategy patterns
β”‚ └── ConnectionStrategies.js # dApp connection strategies
β”‚
β”œβ”€β”€ api/ # API layer
β”‚ └── blockchainApi.js # Unified blockchain API
β”‚
└── utils/ # Utilities
└── feeConfig.js # Fee configuration

Frontend Architecture​

src/
β”œβ”€β”€ App.jsx # Main app component (1,569 lines)
β”œβ”€β”€ main.jsx # React entry point
β”‚
β”œβ”€β”€ components/ # UI components
β”‚ β”œβ”€β”€ Dashboard.jsx # Portfolio view
β”‚ β”œβ”€β”€ Swap.jsx # Swap container/orchestrator (~115 lines)
β”‚ β”œβ”€β”€ SwapProviderSelector.jsx # Bebop/Relay provider selector
β”‚ β”œβ”€β”€ Settings.jsx # Settings panel
β”‚ β”œβ”€β”€ Ecosystem.jsx # Ecosystem explorer
β”‚ β”‚
β”‚ β”œβ”€β”€ swap/ # Swap-specific components
β”‚ β”‚ β”œβ”€β”€ BebopSwapPanel.jsx # Bebop swap implementation (~1,400 lines)
β”‚ β”‚ β”œβ”€β”€ RelaySwapPanel.jsx # Relay swap implementation (~1,288 lines)
β”‚ β”‚ β”œβ”€β”€ CompactNetworkSelector.jsx # Compact network selector for cross-chain
β”‚ β”‚ β”œβ”€β”€ RouteVisualization.jsx # Visual swap route display
β”‚ β”‚ β”œβ”€β”€ BridgeTimeDisplay.jsx # Bridge time estimation
β”‚ β”‚ β”œβ”€β”€ GasEstimateDisplay.jsx # Gas cost estimation
β”‚ β”‚ └── LoadingDots.jsx # Loading animation
β”‚ β”‚
β”‚ β”œβ”€β”€ screens/ # Full-screen views
β”‚ β”‚ β”œβ”€β”€ ConnectionRequestScreen.jsx
β”‚ β”‚ β”œβ”€β”€ TransactionConfirmationScreen.jsx
β”‚ β”‚ β”œβ”€β”€ SigningConfirmationScreen.jsx
β”‚ β”‚ β”œβ”€β”€ TypedDataConfirmationScreen.jsx
β”‚ β”‚ β”œβ”€β”€ NetworkSwitchConfirmationScreen.jsx
β”‚ β”‚ └── TransactionSuccessScreen.jsx
β”‚ β”‚
β”‚ β”œβ”€β”€ modals/ # Modal dialogs
β”‚ β”‚ β”œβ”€β”€ UnlockWalletModal.jsx
β”‚ β”‚ β”œβ”€β”€ EditWalletModal.jsx
β”‚ β”‚ β”œβ”€β”€ NetworkConsentModal.jsx
β”‚ β”‚ β”œβ”€β”€ SignatureModal.jsx
β”‚ β”‚ β”œβ”€β”€ LoadingModal.jsx
β”‚ β”‚ └── StyledModal.jsx
β”‚ β”‚
β”‚ β”œβ”€β”€ settings/ # Settings sections
β”‚ β”‚ β”œβ”€β”€ SecuritySection.jsx
β”‚ β”‚ β”œβ”€β”€ WalletsSection.jsx
β”‚ β”‚ β”œβ”€β”€ NetworkSection.jsx
β”‚ β”‚ β”œβ”€β”€ TokensSection.jsx
β”‚ β”‚ β”œβ”€β”€ WalletConnectSection.jsx
β”‚ β”‚ └── AppInfoSection.jsx
β”‚ β”‚
β”‚ └── common/ # Reusable components
β”‚ β”œβ”€β”€ Dashboard/
β”‚ β”‚ β”œβ”€β”€ PortfolioBalanceSection.jsx
β”‚ β”‚ β”œβ”€β”€ TokensList.jsx
β”‚ β”‚ β”œβ”€β”€ NFTsSection.jsx
β”‚ β”‚ └── TokenCardDark.jsx
β”‚ β”œβ”€β”€ TokenImage.jsx
β”‚ β”œβ”€β”€ TokenLogo.jsx
β”‚ β”œβ”€β”€ NetworkIcon.jsx
β”‚ └── TokenPriceChart.jsx
β”‚
β”œβ”€β”€ contexts/ # React contexts
β”‚ β”œβ”€β”€ WalletProvider.jsx # Wallet state context
β”‚ └── BalancesProvider.jsx # Balances context
β”‚
β”œβ”€β”€ hooks/ # Custom hooks
β”‚ β”œβ”€β”€ useSessionWallet.js # Session management
β”‚ β”œβ”€β”€ useSwapLogic.js # Swap logic
β”‚ β”œβ”€β”€ useSwapQuote.js # Swap quote management
β”‚ β”œβ”€β”€ useTokenList.js # Token list management
β”‚ β”œβ”€β”€ usePortfolioData.js # Portfolio data aggregation
β”‚ β”œβ”€β”€ useUnifiedNetworkSwitch.js # Network switching
β”‚ β”œβ”€β”€ useNativeStreamConnection.js # Stream connection management
β”‚ β”œβ”€β”€ useAutoLock.js # Auto-lock functionality
β”‚ β”œβ”€β”€ useNotification.js # Notification system
β”‚ └── useApiProxy.js # API proxy utilities
β”‚
β”œβ”€β”€ utils/ # Frontend utilities
β”‚ β”œβ”€β”€ FrontendSessionAdapter.js # Session communication
β”‚ β”œβ”€β”€ FrontendControllerAdapter.js # Controller communication
β”‚ β”œβ”€β”€ SwapAdapter.js # Swap communication
β”‚ β”œβ”€β”€ SendAdapter.js # Send communication
β”‚ β”œβ”€β”€ NativeStreamManager.js # Stream management
β”‚ β”œβ”€β”€ provider.js # EIP-1193 provider
β”‚ β”œβ”€β”€ walletConnectManager.js # WalletConnect client
β”‚ β”œβ”€β”€ vaultManager.js # Vault operations
β”‚ β”œβ”€β”€ vaultStorage.js # Vault storage layer
β”‚ β”œβ”€β”€ crypto.js # Cryptography utilities
β”‚ β”œβ”€β”€ networks.js # Network configurations
β”‚ β”œβ”€β”€ ethereumUtils.js # Ethereum utilities
β”‚ β”œβ”€β”€ bebopTokenService.js # Bebop token list service
β”‚ β”œβ”€β”€ superseedApi.js # SuperSeed API client
β”‚ β”œβ”€β”€ apiProxy.js # API proxy layer
β”‚ β”œβ”€β”€ portfolioCalculator.js # Portfolio calculations
β”‚ β”œβ”€β”€ addressBook.js # Address book management
β”‚ β”œβ”€β”€ storage.js # Storage utilities
β”‚ β”œβ”€β”€ tokenConfig.js # Token configuration
β”‚ β”œβ”€β”€ swapConfig.js # Swap configuration
β”‚ β”œβ”€β”€ swapContracts.js # Swap contract addresses
β”‚ β”œβ”€β”€ curatedTokenLogos.js # Token logo mappings
β”‚ β”œβ”€β”€ feeConfigClient.js # Fee configuration client
β”‚ β”œβ”€β”€ dAppFrameworkDetector.js # dApp framework detection
β”‚ └── networkMismatchDetector.js # Network mismatch detection
β”‚
β”œβ”€β”€ controllers/ # Frontend controllers
β”‚ β”œβ”€β”€ TokenController.js # Token operations
β”‚ β”œβ”€β”€ NetworkController.js # Network management
β”‚ └── TransactionController.js # Transaction history
β”‚
└── services/ # Frontend services
└── NetworkSwitchService.js # Network switching service

Network Architecture​

Supported Networks​

Active Networks (7):

NetworkChain IDSwap SupportRelay SupportStatus
SuperSeed5330βœ… Bebop (JAM)βœ… Cross-chainβœ… Active
Optimism10βœ… Bebop (JAM+RFQ)βœ… Cross-chainβœ… Active
Ethereum1βœ… Bebop (JAM+RFQ)βœ… Cross-chainβœ… Active
Base8453βœ… Bebop (JAM+RFQ)βœ… Cross-chainβœ… Active
BNB Chain56βœ… Bebop (JAM+RFQ)βœ… Cross-chainβœ… Active
Arbitrum One42161βœ… Bebop (JAM+RFQ)βœ… Cross-chainβœ… Active
Shardeum8118❌ Not supported❌ Not supportedβœ… Active

Key Features:

  • Bebop Support: 6 networks support Bebop swaps (JAM and/or RFQ)
  • Relay.link Support: 6 networks support cross-chain swaps via Relay.link
  • Network Tokens: Each network has wrapped native token (WETH, WBNB, etc.)
  • Stable Tokens: USDC/USDT configured per network
  • Explorer APIs: Moralis (ETH, OPT, BASE, BSC, ARB), Blockscout (SuperSeed)

Network Switching Architecture​

graph LR
A[User/dApp Request] --> B{NetworkSwitchService}
B --> C[Validate Network]
C --> D{Requires Consent?}
D -->|Yes| E[Show Consent Modal]
D -->|No| F[Execute Switch]
E --> G{User Approves?}
G -->|Yes| F
G -->|No| H[Return Error]
F --> I[Update SessionController]
I --> J[Update Controllers]
J --> K[Broadcast Events]
K --> L[Update UI]
K --> M[Notify dApps]

Context-Aware Switching:

  • manual - User-initiated from UI
  • dapp_request - dApp-requested via wallet_switchEthereumChain
  • connection - During dApp connection
  • automatic - System-initiated

Pre-Switch Coordination System​

Purpose: Ensures all components are ready before network switch completes, preventing race conditions and state inconsistencies.

Architecture: Promise-based coordination replaces fragile timing-based delays with deterministic handler execution.

// Pre-switch handler registration
preSwitchCoordinator.registerHandler(
'portfolio-data-lock',
async (targetNetworkKey) => {
// Prepare for network switch
isNetworkSwitchingRef.current = true;
pendingNetworkSwitchRef.current = targetNetworkKey;
},
{ name: 'Portfolio Lock', timeout: 500 }
);

// Coordinated execution during switch
await preSwitchCoordinator.executeHandlers(targetNetworkKey, {
context: 'manual',
abortOnError: true // Abort switch on handler failure
});

Key Features:

  • Deterministic Execution: Waits for actual handler completion, not arbitrary delays
  • Abort-on-Failure: Network switch aborts if any handler fails/times out
  • Per-Handler Timeouts: Individual 2s timeout protection (configurable)
  • Global Timeout: 5s safety net prevents infinite hangs
  • Detailed Logging: Full visibility into handler execution and failures
  • Cleanup Support: Automatic unregistration on component unmount

Security Benefits:

  • Prevents showing one network while signing on another
  • Eliminates race conditions in portfolio data fetching
  • Ensures UI state consistency across network switches
  • No silent failures - all errors surfaced to user

Performance Metrics​

Response Times​

OperationTargetActualStatus
Session unlock<500ms~200msβœ… Excellent
dApp response<200ms<150msβœ… Excellent
Network switch<1s~300msβœ… Good
Swap quote<2s~800msβœ… Good
Transaction sign<100ms~50msβœ… Excellent

Optimization Strategies​

  1. Stream Persistence: Long-lived connections eliminate handshake overhead
  2. Pre-decrypted Keys: Private keys cached in memory during session
  3. Controller Caching: Network state and tokens cached in memory
  4. Lazy Loading: Components loaded on-demand
  5. Event-Driven: Zero polling, all updates via events

Bundle Sizes​

Frontend (popup.js): ~2.1 MB (includes React, ethers.js)
Background (background.js): ~1.8 MB (includes ethers.js, WalletConnect)
Content Script: ~150 KB (minimal injection)


Document Status: βœ… Current as of November 15, 2025
Code Version: v3.0.0+
Maintenance: Review quarterly or after major architecture changes