Skip to main content
Version: 0.5.0

Architecture Overview

TezosX Wallet is a Chrome Manifest V3 extension composed of four runtime components, each living in a different execution boundary.

Component diagram

Components

Injected Provider — MAIN world

File: packages/wallet/src/injected/provider.ts

Runs in the same JavaScript context as the web page. Exposes window.ethereum as a minimal EIP-1193 provider. Has no access to chrome.* APIs — it communicates exclusively via window.postMessage.

Every call to provider.request() is assigned a unique requestId, forwarded to the content bridge, and resolved or rejected when the bridge replies.

Content Bridge — ISOLATED world

File: packages/wallet/src/content/bridge.ts

Runs in the extension's isolated world — it can see the page DOM but cannot access page globals. Bridges two channels:

  • Page → SW: receives TEZOSX_WALLET_REQUEST postMessages, forwards them via chrome.runtime.sendMessage
  • SW → Page: receives PROVIDER_EVENT push messages from the SW, relays them as TEZOSX_WALLET_EVENT postMessages

Service Worker

File: packages/wallet/src/background/service-worker.ts

The extension's backend. Holds all state that must persist across popup opens:

  • Keyring — in-memory unlocked identity (tz1, publicKey, secretKey)
  • RelayerProvider — EIP-1193 request handler; recreated on every unlock
  • ApprovalQueue — pending dApp requests awaiting user consent

Handles three message categories:

  • PopupRequest — from the popup UI (unlock, lock, create, send, etc.)
  • ApproveRequest — from approve.html (get/resolve pending request)
  • EthereumRequest — from the content bridge (dApp's provider.request() calls)

File: packages/wallet/src/ui/

A React + React Router app rendered in popup.html. Reads and mutates state exclusively via chrome.runtime.sendMessage to the service worker. Never touches the keyring or signer directly.

See User Flows for per-page documentation.

Data flow — dApp transaction request

See also