Build with Client and Explorer

Connect a web app through WalletClient from @bsv/sdk, verify version/network without spending, and handle permissions across desktop and mobile.

Read as Markdown

Connect a browser application to Client 0.8.11 on desktop or Explorer 1.2.1 on mobile using the BRC-100 WalletClient API. This guide was checked October 26, 2026. Client 0.8.11 ships with SDK 3.2.1; the example below uses that published version as a reproducible baseline, not a claim that every wallet bundles the same SDK.

Make a connection without spending

In an existing TypeScript web project:

1npm install @bsv/sdk@3.2.1
Copied!

Add a button and a status element to your page:

1<button id="connect-wallet" type="button">Connect wallet</button>
2<p id="wallet-status" role="status" aria-live="polite"></p>
Copied!

Then run this code in your browser application's entry module:

1import { WalletClient } from '@bsv/sdk'
2
3const wallet = new WalletClient('auto')
4const button = document.querySelector<HTMLButtonElement>('#connect-wallet')!
5const status = document.querySelector<HTMLElement>('#wallet-status')!
6
7button.addEventListener('click', async () => {
8  button.disabled = true
9  status.textContent = 'Waiting for your wallet. Check its window or prompt.'
10  try {
11    await wallet.waitForAuthentication()
12    const [{ version }, { network }] = await Promise.all([
13      wallet.getVersion({}),
14      wallet.getNetwork({})
15    ])
16    status.textContent = `Connected: ${version} on ${network}`
17  } catch {
18    status.textContent = 'Connection did not complete. Open your wallet, check any prompt, then try again.'
19  } finally {
20    button.disabled = false
21  }
22})
Copied!

Expected result: the page reports the responding wallet version and network. No createAction, payment or private-key export is involved. Authentication still requires the user's wallet session; transport discovery is not user consent.

On desktop, serve the project on localhost with Client running and unlocked. On mobile, deploy the page to an HTTPS URL reachable from the phone and open it inside Explorer. localhost on the phone refers to the phone, not your development computer. Test production origins as well as development origins because permissions are scoped to the requesting app.

Request identity only when the feature needs it

After a user chooses a feature that needs their public identity:

1const { publicKey } = await wallet.getPublicKey({ identityKey: true })
Copied!

Explain why it is needed and handle rejection. A returned public key identifies a wallet/profile; it does not alone prove that a server request is authenticated. Use an appropriate challenge/proof or wallet-signed HTTP authentication for that purpose. Never ask for a seed, password, recovery key or raw private key.

Desktop and mobile connection paths

EnvironmentConnection path
Desktop browser with Client runningLocal wallet bridge discovered by the SDK
Website opened inside ExplorerWallet bridge in Explorer's WebView
Ordinary Safari/Chrome tab on the phoneDoes not automatically acquire Explorer's injected wallet
Backend/server processCannot assume access to a customer's browser wallet; design an explicit authenticated interaction

Client 0.8.11 reserves loopback ports 3301 (binary wallet wire), 3321 (JSON HTTP) and 2121 (HTTPS bridge). These are local connection details, not public wallet endpoints or ports to forward from a router. Use SDK discovery for normal app code. Another desktop BRC-100 wallet using those ports must be quit before launching Client.

The API is portable across compliant wallets; UX, transport and optional behavior still need testing. Do not hard-code an originator to impersonate another website, bypass permission checks or assume a wallet brand based solely on a successful connection.

Add one capability at a time

Continue with permissions, transactions, encryption, signatures and certificates.

For each feature, explain the requested capability before the prompt. Handle rejection, insufficient funds, wrong network, locked wallet, backgrounding and interrupted responses. Preserve a transaction reference or ID when one exists. Never automatically repeat a spend just because a timeout or delivery acknowledgement is missing. Reconcile the original operation first.

Before release, exercise a non-spending connection and identity flow in both Client and Explorer, then a separately approved low-value payment. Verify the recipient's acceptance and app outcome, not just the sender's HTTP success. Check denied/revoked permissions and account/profile changes as well.

Current references and older examples

For new integrations, replace old @babbage/metanet-client/MetanetDesktop tutorial patterns with the current @bsv/sdk interface. Do not silently change a production integration: map its actual methods, permission behavior and transaction handling, then verify both wallet paths.

Was this page helpful?