Connect your site
bWalletX implements the open BRC-100 wallet interface. Your page talks straight to the user’s wallet: no API keys, no sign-up, nothing through our servers. Any BRC-100 wallet works the same way.
1. Add the script
Section titled “1. Add the script”<script src="https://bwalletx.com/connect.js"></script>Or from npm: @bwalletx/connect.
2. Add a button
Section titled “2. Add a button”<button id="connect">Connect with bWalletX</button><script> bWalletX.button('#connect', async ({ wallet, identityKey }) => { // wallet is a BRC-100 WalletInterface, the same API as window.CWI console.log('Connected', identityKey); });</script>If bWalletX isn’t installed, the button opens bwalletx.com/extension.
3. Use the wallet
Section titled “3. Use the wallet”const { wallet } = await bWalletX.connect();
// Sign in: prove who the user isconst { signature } = await wallet.createSignature({ data: [...new TextEncoder().encode(challenge)], protocolID: [0, 'my site login'], keyID: '1',});Sign people in (checked on your server)
Section titled “Sign people in (checked on your server)”A signature made in the browser proves nothing until your server checks it. @bwalletx/connect/server does the two steps: a one-time challenge, then a check of the wallet’s signature. No API key, no account with us, nothing through bwalletx.com.
pnpm add @bwalletx/connect @bsv/sdkThis runs both sides in one file. A throwaway key stands in for the user’s BRC-100 wallet:
import { PrivateKey, ProtoWallet, Utils } from '@bsv/sdk';import { createChallenge, verifySignIn, memoryStore } from '@bwalletx/connect/server';
const ORIGIN = 'https://example.com'; // your site, from config, never from the requestconst store = memoryStore(); // dev only: use redisStore or pgStore in production
// Browser: the wallet gives its identity key.const wallet = new ProtoWallet(PrivateKey.fromRandom());const { publicKey: identityKey } = await wallet.getPublicKey({ identityKey: true });
// Server, POST /challengeconst ch = await createChallenge({ origin: ORIGIN, identityKey, store });
// Browser: the wallet signs the challenge text.const { signature } = await wallet.createSignature({ data: Utils.toArray(ch.message, 'utf8'), protocolID: ch.protocolID, // [2, 'bwallet sign in'] keyID: ch.keyID, // the nonce counterparty: 'anyone',});
// Server, POST /verify: send the signature as the byte array createSignature returned (not hex).const proven = await verifySignIn({ origin: ORIGIN, store, identityKey, nonce: ch.nonce, signature });Output when we ran it (17 Oct 2026, @bwalletx/connect 0.5.0, @bsv/sdk 3.2.1):
Sign in to example.com with bWallet
This proves you hold this wallet. It does not spend anything.
Origin: https://example.comNonce: <nonce>Expires: <ISO time>
signed in as: the same identity key ✓second try with the same nonce: nullverifySignIn returns the identity key (66 lowercase hex characters) or null. Each nonce works once and expires after 2 minutes. If you get null every time, check that you pass the signature as an array of numbers, not a hex string.
For Next.js, @bwalletx/connect/next wraps this in four route handlers and a signed session cookie; React has BwalletXProvider and useBwalletX(). See the package README and the full protocol at bwalletx.com/connect.md.
Picking the right wallet
Section titled “Picking the right wallet”bWalletX also sets window.CWI, so sites that call it directly keep working. If the user has another wallet installed too, you can’t tell which one answers. bWalletX.connect() picks bWalletX by name (rdns com.bwalletx.extension) through BRC-100 wallet discovery. To let the user choose:
const wallets = await bWalletX.discover(); // [{ info: { name, icon, rdns, kind }, wallet }, …]Permissions
Section titled “Permissions”Every request is approved by the user on one sheet inside the wallet. Grants are per origin (https only, plus localhost).
More: bwalletx.com/developers, Sign in with bWalletX.
Standards
Section titled “Standards”- BRC-100: the wallet interface (
createAction,createSignature,getPublicKey…). - BRC-43: protocol IDs and key IDs used for signatures.
- BRC-29: paying an identity key directly.
Status
Section titled “Status”- ✓ connect.js and
@bwalletx/connect(0.5.0) - ✓ Wallet discovery by rdns
- ✓ window.CWI compatibility
- ✓ Server-checked sign-in (
createChallenge/verifySignIn), verified 17 Oct 2026