Skip to main content

Extension Architecture Diagram

SubWallet Extension follows a multi-layered architecture designed for browser extensions: Main Concept The extension is compiled from the packages/extension-koni folder and operates across three distinct execution contexts that communicate via Chrome’s message passing API.

Core Components

Background Environment

Background Script

The background environment is the heart of the extension, compiled from packages/extension-koni/src/background.ts
Responsibilities:
  • Handle messages from extension pages and Chrome tabs via Chrome API Message Passing
  • Manage all application state and persist to Chrome storage
  • Execute cronjobs for periodic tasks
  • Process all API calls and blockchain interactions
  • Coordinate data flow between different parts of the extension
Key Features:
  • Centralized state management through KoniState class
  • Message routing via KoniExtension and KoniTabs handlers
  • Scheduled tasks through KoniCron
  • Store persistence to Chrome local storage

Extension Pages

The frontend interface of SubWallet consists of two main views:

popup.html

Main extension page displayed when clicking the extension icon in the browser toolbar

portfolio.html

Advanced view for displaying complex data like dashboards and transaction history
UI Technology Stack:
  • React - Component-based UI framework
  • Redux Toolkit - State management with React hooks
  • Webpack - Module bundler for production builds

Inject Scripts

Scripts injected into Chrome tabs to enable dapp interactions:
  • Expose wallet functionality to web pages
  • Provide the window.injectedWeb3 interface
  • Enable MetaMask compatibility for EVM chains
  • Bridge communication between dapps and the background environment

Data Flow Architecture

1

Request Initiation

Extension pages or Chrome tabs send messages to the background environment
2

Background Processing

Background script processes requests, calls APIs, and updates state
3

State Persistence

Updated state is persisted to Chrome local storage
4

Response Delivery

Background sends response back to the requesting context
All data requests must be processed in the background environment. Extension pages and inject scripts use data from the background and should not call APIs directly.

Package Structure

The monorepo is organized into specialized packages:

Core Packages

Purpose: Foundation package for background functionalityContains:
  • Main features running in background
  • API calling infrastructure
  • Data persistence to Chrome storage
  • Inject script utilities
Purpose: Custom extension of extension-baseContains:
  • SubWallet-specific features
  • API definitions (packages/extension-koni-base/src/api)
  • Store implementations (packages/extension-koni-base/src/store)
  • Cronjob definitions (packages/extension-koni-base/src/cron)
  • Message handlers for KoniExtension and KoniTabs
Purpose: Main entry point for the extensionContains:
  • Injection logic
  • Background processing orchestration
  • Webpack configuration for builds
Purpose: User interface componentsContains:
  • React components
  • Redux stores
  • Hooks for global functions
  • Internationalization (i18n)
  • Messaging utilities (messaging.ts)
  • Assets and resources

Integration Packages

Convenience wrapper for dapps to integrate with the extension, simplifying data extraction for any application that wishes to use the injected objects.
Wrapper enabling extension developers to inject their extension for use by any dapp.
Chain definitions and metadata for supported blockchain networks, including bare definitions and stripped-down call-only metadata formats.
MetaMask compatibility layer for EVM chain support and web3 provider compatibility.
Mock data for testing purposes.

Message Passing System

SubWallet uses Chrome’s message passing API for communication between components.

Message Types

export interface KoniRequestSignatures {
  // One-time message from extension
  'pri(price.getPrice)': [RequestPrice, PriceJson]
  
  // Subscription message from extension
  'pri(price.getSubscription)': [RequestSubscribePrice, boolean, PriceJson]
}
Message Format:
  • Messages from extension pages start with pri prefix
  • Messages from Chrome tabs start with pub prefix
  • Each message type defines: type name, request type, response type, and optional subscription parameter

Communication Patterns

Extension or Chrome tab sends a request and listens for a single response. The listener is removed after receiving the response.
// Send request
sendMessage('pri(price.getPrice)', request)
  .then(response => {
    // Handle response
  });

State Management

Store System

Stores persist data to Chrome local storage and are defined in packages/extension-koni-base/src/store.
// Simple store with basic persistence
export default class MyStore extends BaseStore<DataType> {
  constructor() {
    super(EXTENSION_PREFIX ? `${EXTENSION_PREFIX}mystore` : null);
  }
}
Store Classes:
  • BaseStore - Basic persistence to Chrome local storage
  • SubscribableStore - Extends BaseStore with RxJS subjects for reactive updates

State Coordination

Stores are managed by the KoniState class:
export default class KoniState extends State {
  private readonly priceStore = new Price();
  private priceStoreReady = false;

  public setPrice(priceData: PriceJson, callback?: (priceData: PriceJson) => void): void {
    // Update price data
  }

  public getPrice(update: (value: PriceJson) => void): void {
    // Retrieve price data
  }

  public subscribePrice() {
    return this.priceStore.getSubject();
  }
}

Background Services

Cronjob System

Periodic tasks are defined in packages/extension-koni-base/src/cron and initialized through the KoniCron class. Use Cases:
  • Price updates
  • Balance refreshes
  • Network status checks
  • Transaction monitoring

UI Structure

The extension UI (packages/extension-koni-ui) is organized into:
  • assets - Images and resources
  • components - Reusable React components
  • hooks - Custom React hooks for global functions
  • i18n - Internationalization files
  • stores - Redux stores generated with Redux Toolkit
  • partials - Header and layout components
  • util - Utility methods
  • messaging.ts - Functions to send messages to background and handle responses

Security Considerations

  • All API calls must go through the background environment
  • Extension pages cannot make direct API calls
  • Inject scripts operate in isolated contexts
  • State is persisted securely to Chrome storage

Next Steps

Now that you understand the architecture, you can:

Setup Development Environment

Get started with local development

View Source Code

Explore the codebase on GitHub

Build docs developers (and LLMs) love