Mobile
MWA Deep Dive

MWA Deep Dive

Konten ini sedang diterjemahkan dan akan tersedia di sini ketika siap.

The MWA Architecture

MWA Deep Dive

Browser extension wallets work because your dApp and wallet share the same execution context: the browser. Phantom's extension can inject itself into every page, intercept wallet requests, and respond directly. Simple, elegant, fragile.

Mobile breaks this model completely. Your React Native app runs in its own sandbox. The wallet app runs in another. No shared memory. No injected scripts. No common window object. The operating system enforces strict isolation between applications.

Mobile Wallet Adapter is the protocol that bridges this gap.

MWA defines how two completely isolated applications, your dApp and a wallet, can establish a secure channel, negotiate authorization, and exchange signed transactions.

Three-Layer Architecture

The MWA protocol operates across three distinct layers:

Transport Layer: How bytes move between apps. On Android, this means WebSockets over localhost. The dApp opens a WebSocket client; the wallet runs a WebSocket server. For remote connections (dApp on laptop, wallet on phone), a reflector server mediates.

Session Layer: How the apps establish trust. Before any wallet operations happen, the dApp and wallet perform a cryptographic handshake. They exchange public keys, verify identities, and derive a shared encryption key. Every subsequent message is encrypted.

RPC Layer: What operations the wallet exposes. Once a secure session exists, the dApp sends JSON-RPC requests (authorize, sign_and_send_transactions, sign_messages) and receives responses. This is the layer most developers interact with.

text
+-----------------------------------------------------+
|                   RPC Layer                         |
|  authorize, sign_and_send_transactions, etc.        |
+-----------------------------------------------------+
|                 Session Layer                       |
|  ECDH key exchange, AES-GCM encryption              |
+-----------------------------------------------------+
|                Transport Layer                      |
|  WebSocket (local or via reflector)                 |
+-----------------------------------------------------+

Endpoints and Roles

The spec defines two roles:

dApp Endpoint: Your application. It initiates connections, sends requests, and processes responses. In the Transport layer, it acts as the WebSocket client (for local connections) or connects to a reflector. The dApp endpoint is always the initiator.

Wallet Endpoint: The wallet app (Phantom, Solflare, etc.). It accepts connections, presents authorization UI to users, signs transactions, and returns results. In the Transport layer, it acts as the WebSocket server (locally) or connects to the same reflector. The wallet endpoint is always the responder.

text
+-----------------+                      +-----------------+
|  dApp Endpoint  |                      | Wallet Endpoint |
|   (your app)    |<-------------------->|   (Phantom)     |
|                 |    MWA Protocol      |                 |
|   - initiator   |                      |   - responder   |
|   - WS client   |                      |   - WS server   |
+-----------------+                      +-----------------+

The Association Token

Every MWA session begins with an association token. This is a base64url-encoded P-256 elliptic curve public key generated by the dApp.

text
solana-wallet:/v1/associate/local?association=<TOKEN>&port=<PORT>

The association token serves two purposes:

  1. Authentication: The dApp proves it generated the token by signing messages with the corresponding private key during session establishment.

  2. Key Agreement Salt: The token's public key is used as a salt in the HKDF function that derives the session encryption key.

Why generate a fresh keypair for every connection? Because MWA sessions are ephemeral. When your app calls transact(), it creates a brand-new association keypair, opens a wallet session, performs operations, and closes the session. The keypair is discarded. The next transact() call generates a new one.

This means:

  • Sessions don't persist across app restarts

  • Each transact() is independent

  • There's no long-lived credential to steal

Why Encryption Matters

You might wonder: if both apps run on the same device, communicating over localhost, why encrypt?

Three reasons:

Privacy from other apps: On a rooted device or one with malware, other processes could potentially sniff localhost traffic. Encryption ensures transaction details remain confidential.

Integrity protection: Encryption (specifically authenticated encryption with AES-GCM) ensures messages can't be tampered with in transit. A modified transaction would fail authentication.

Protocol uniformity: The same encryption scheme works for both local and remote connections. Remote connections route through a reflector server, a third party that explicitly should not see plaintext. By encrypting always, the protocol doesn't need special cases.

The Reflector's Role

For remote connections, where the dApp runs on a laptop and the wallet on a phone, direct communication isn't possible. MWA uses a reflector server as an intermediary.

The reflector is intentionally simple and untrusted:

  1. The dApp connects to wss://<reflector>/reflect and receives a unique ID

  2. This ID is encoded into a QR code that the wallet scans

  3. The wallet connects to wss://<reflector>/reflect?id=<ID>

  4. The reflector begins forwarding messages between them

  5. All forwarded messages are encrypted; the reflector sees only ciphertext

text
+----------+      +------------+      +----------+
|   dApp   |----->|  Reflector |<-----|  Wallet  |
| (laptop) |      |  (server)  |      | (phone)  |
+----------+      +------------+      +----------+
                        |
                  Can't read
                  message content

The reflector enforces timeouts (30 seconds for half-open connections, 90 seconds for established sessions) and limits message size to 4KB. It's a dumb pipe by design.

Session Lifecycle

Understanding the session lifecycle helps debug issues:

1. Association

The dApp generates an association keypair and constructs a solana-wallet: URI. On Android, opening this URI launches the wallet app via an Intent.

2. Transport Establishment

The wallet starts a WebSocket server on the specified port. The dApp connects and begins the handshake.

3. Session Establishment

The apps exchange HELLO_REQ and HELLO_RSP messages containing ECDH public keys. They derive a shared AES key. The session is now encrypted.

4. Authorization

The dApp sends an authorize JSON-RPC request. The wallet shows UI asking the user to approve. If approved, the wallet returns accounts and an auth_token.

5. Privileged Operations

With authorization, the dApp can request signing (sign_and_send_transactions, sign_messages).

6. Session Close

When the dApp's transact() callback completes, the WebSocket closes. All session keys are discarded.

What Makes MWA Different

Comparing MWA to other wallet connection protocols:

AspectBrowser ExtensionsWalletConnectMWA
Execution ContextShared (injected)SeparateSeparate
TransportDirect memoryRemote relayLocal WS or relay
Session DurationLong-livedLong-livedEphemeral
EncryptionOptionalYesYes
Identity VerificationDomain-basedNone standardDigital Asset Links

The ephemeral session model is MWA's most distinctive feature. Other protocols maintain persistent connections. MWA reconnects for each operation batch. This simplifies state management but means authorization must be efficient (hence the auth_token for silent reauthorization).

Why This Course Exists

Most dApp developers only need Course 1: practical integration patterns. But some scenarios demand deeper understanding:

  • Debugging: When sessions fail mysteriously, knowing the handshake helps isolate the problem

  • Wallet Development: Building a wallet requires implementing the server side

  • Security Audits: Reviewing MWA implementations requires protocol knowledge

  • Custom Transports: Adding Bluetooth or other transports means understanding the abstraction layers

This course takes you through the spec layer by layer. By the end, you'll be able to read the official specification fluently and trace issues from user-facing symptoms to protocol-level causes.

We start in the next lesson with the transport layer: how bytes actually move between apps.

Daftar Isi
Lihat Sumber
Blueshift © 2026Commit: 1b8118f