Seeker Connect for web dapps
Seeker Connect links a web page open in the browser on the device to a Solana Mobile certified device's own wallet — Seeker is the first such device. It is a dapp-only SDK built on top of the official Mobile Wallet Adapter libraries: a UX/DX layer, not a protocol reimplementation. Where generic MWA centers on a "pick a wallet" chooser, Seeker Connect launches the device wallet directly through the MWA spec's Endpoint-specific URI (Android App Link) mechanism, carries the session over a Nostr relay, and ships Seeker-branded progress and error UI — all exposed to the app as an ordinary Wallet Standard wallet named "Seeker Connect".
Targets: Web is available today. React Native and Android (Kotlin) are planned. Until
they ship, wallet connection inside an Expo or React Native app uses the
solana-mobile-wallet skill instead.
The mental model — read this before writing code
- There is no long-lived connection. Every wallet interaction (connect, sign message, sign transaction) opens its own short-lived MWA session, runs one request, and tears down. Each interaction launches the wallet app and shows a branded progress overlay — the one exception is a silent connect, which only reads the cache and never opens a session. This is by design — do not build reconnect loops or keep-alive logic around it.
- "Connected" means "holds a cached authorization." The first
connect()stores a wallet-issuedauthTokenplus accounts and capabilities (localStorage by default). Later operations replay that token silently — no repeated consent prompt. - Disconnect only forgets the token locally. It deliberately never calls the wallet's
deauthorize, because that would launch the wallet app just to disconnect. - It only completes on the device. On desktop, connect fails with
association-failed— typically within seconds, when nothing answers the wallet launch; the association timeout only applies to a wallet that launches but never connects. Register the wallet unconditionally; it simply won't get past association elsewhere. - The SDK ships no default relay. Use Solana Mobile's,
relay.solanamobile.com: it is free, including in production. Using it requires agreeing to Solana Mobile's terms, so tell the developer to accept them — Step 2.
Step 1: install
New project: the react-kit-shadcn template from the Solana Mobile CLI ships with
Seeker Connect already wired up on Solana Mobile's relay. The next steps create prints tell
the developer to accept the relay terms on the quickstart page:
Existing app: install the Wallet Standard entry point plus the Wallet Standard helpers the snippets below import from:
Use 0.1.2 or later. Earlier releases sit on Mobile Wallet Adapter 2.x, which can leave a
wallet call pending forever when the session drops; 0.1.2 moves to MWA 3.0, which rejects
it with session-closed instead.
The Wallet Standard package pulls in the other Seeker Connect packages (core, ui, web)
as dependencies. They are not re-exported, though — so also install any of them the app
imports from directly (@solana-mobile/seeker-connect-ui for the optional button below,
@solana-mobile/seeker-connect-web for the imperative path in the references); strict
package managers like pnpm refuse imports of undeclared transitive dependencies.
Step 2: set the relay
Seeker Connect carries MWA's extended remote communication protocol over a Nostr relay,
named by relayDomain. Payloads are end-to-end encrypted between dapp and wallet; the relay
carries ciphertext only.
Use relay.solanamobile.com. Solana Mobile runs it for Seeker Connect, and it is free to
use, including in production. Pass the bare host; the SDK adds the wss:// scheme itself.
Tell the developer to accept the relay terms. Using Solana Mobile's relay requires agreeing to Solana Mobile's terms. Whenever you wire it in, say so, and point the developer at the quickstart page where they accept them: https://docs.solanamobile.com/solana-mobile-stack/seeker-connect-quickstart
Step 3: register once at startup
Call registerSeekerConnect before the UI renders, so wallet discovery sees it from the
first render. It must run in the browser — the snippet below reads window, so under SSR
(Next.js and similar) put the call in a client-only module or guard it with
typeof window !== 'undefined'; in a plain client-rendered app, module scope of the entry
file is fine:
Configuration:
registerSeekerConnect also accepts seekerLink, authorizationCache, and presenter
overrides — see references/imperative-api.md [blocked].
Step 4: use it like any other wallet
After registration, "Seeker Connect" appears in the Wallet Standard registry, so
wallet-adapter, ConnectorKit, @solana/react-hooks, or a raw @wallet-standard/app listing
all pick it up with no further wiring. Existing connect buttons and signing code keep
working.
Features exposed: standard:connect, standard:disconnect, standard:events,
solana:signMessage, solana:signIn, and — depending on the wallet's reported capabilities
after the first connect — solana:signTransaction and/or solana:signAndSendTransaction.
Working with the wallet directly:
Restore the session on page load with a silent connect — it reads the cache and never launches the wallet, resolving with zero accounts when there is nothing cached:
Feature-detect the signing routes. Until the first connect, both transaction features
are assumed; after it they are re-derived from the wallet's actual capabilities, announced
via a standard:events change event. Check before calling:
chain is part of the Wallet Standard input, but this wallet ignores it — the network is the
one passed to registerSeekerConnect, replayed from the cached authorization on every call.
Nothing cross-checks the two, so a per-call solana:devnet against a mainnet registration
submits on mainnet without complaint. Pass seeker.chains[0] so the two can never disagree,
and change networks at registration.
Transactions cross the feature boundary as raw serialized bytes (Uint8Array), legacy and
v0 both supported — serialize with whichever client library the app already uses. Sign-in
follows the SIWS spec via solana:signIn; domain defaults to window.location.host.
When sign-in authenticates a user, the server is the authority, not the client: issue a
single-use, short-lived nonce server-side, and verify the returned message and signature —
including the expected domain and validity window — on the server before creating a
session. The seeker-genesis-token skill walks through that server flow step by step.
Handle errors by code
Wallet outcomes reject with a SeekerConnectError carrying a code:
Three failures are plain Errors instead, and they are misuse rather than wallet outcomes:
signAndSendTransaction on a wallet that reported no support for it, any signing call before a
successful connect, and a sign-in the wallet answered without a result.
That distinction decides who shows the error. The branded dialog fires for SeekerConnectError
and nothing else — every code above except cancelled, which is a normal outcome and stays
silent. The three plain Errors never reach the presenter, so if the app shows nothing they
fail invisibly. Branch on the type first, then on .code:
Optional: the branded connect button
@solana-mobile/seeker-connect-ui ships a <seeker-connect-button> custom element in
Shadow DOM (no host CSS needed). The SDK defines its elements on first use; call
defineSeekerConnectElements() at startup to define them eagerly:
Attributes: disabled, theme="light" | "dark" (names the host page's theme), and
variant="connect" (default) or variant="sign-in" for the label. Wire click to the
connect or sign-in call yourself — the button is presentation only.
Reference material
- references/imperative-api.md [blocked] — the non-Wallet-Standard
path via
createNostrSeekerLink().transact, and theseekerLink/authorizationCache/presenteroverrides - references/troubleshooting.md [blocked] — association failures, desktop testing, capability-derived features, cache behavior
Related skills
seeker-domains— display.skrnames instead of raw addressesseeker-genesis-token— verify Seeker device ownership after connectingsolana-mobile— the CLI, templates, and toolchain behindsolana-mobile createsolana-mobile-wallet— wallet connection in React Native apps (Mobile Wallet Adapter directly)
Links
- MWA web docs: https://docs.solanamobile.com/get-started/web/installation
- Seeker Connect docs: https://docs.solanamobile.com/solana-mobile-stack/seeker-connect
- Seeker Connect quickstart (relay terms live here): https://docs.solanamobile.com/solana-mobile-stack/seeker-connect-quickstart
- Seeker Connect repository: https://github.com/solana-mobile/seeker-connect


