A mobile-first BSV wallet that runs in any modern browser. Biometric-gated, PWA-installable, BRC-100-native.
Live at wallet.sendbsv.com.
| npm | sendbsv-wallet · engine bsv-wallet-toolbox-rs — early access (0.x) |
| Repo | https://github.com/BSVanon/SendBSV-Wallet |
| License | Open BSV License |
Open wallet.sendbsv.com on your phone, enroll a passkey, and you've got a BSV wallet. Send, receive, sweep to cold storage, request payments, claim a paymail handle, manage profiles and certificates, watch your inbox for incoming requests, view your collectibles.
Face ID / Touch ID / Windows Hello / fingerprint / FIDO2 security key — pick one. The wallet engine signs in-browser using passkey-derived keys; nothing leaves the device. The public BSV overlay network carries your wallet identity to every other device you sign in on with the same passkey.
Install it as a PWA for one-tap launch (Add to Home Screen on iOS, Install on desktop Chrome). No app store, no signup form, no servers asking who you are.
The same engine ships as an npm package so any app can plug into it. Five integration surfaces:
- React import — drop
Dashboard,SendSheet,ReceiveSheet, or any of the layer-2 modules into your React app. - Embed button — one
<script>tag and a<sendbsv-pay>custom element. Accept BSV from any HTML page. - Iframe widget — same trust model as the embed button, for hosts with strict CSPs.
- Connect SDK — Promise-based JS API for non-React DApps.
- M2M Fetch — BRC-121 (Simple 402 Payments)
fetch-shaped wrapper for agents, scripts, and browser tabs that pay protected APIs.
pnpm install
pnpm devOpens a dev playground at http://localhost:5173 with three views:
- WASM (live) — the production setup flow driving
bsv-wallet-toolbox-rs. - Dashboard (stub) — every layer-2 component mounted against a stub wallet with seeded data, for fast UI iteration.
- Legacy v0 — earlier component versions, kept for visual reference.
The wiring lives in examples/dev/main.tsx.
pnpm add sendbsv-wallet bsv-wallet-toolbox-rs @bsv/sdk react react-domSendBSV is two npm packages that combine into one wallet: sendbsv-wallet (the TypeScript UI + layer-2 logic) and bsv-wallet-toolbox-rs (the Rust → WASM signing engine it runs on). Both are early access (0.x — the API may change before 1.0); bsv-wallet-toolbox-rs is the peer that actually signs, alongside @bsv/sdk / react / react-dom.
import { Dashboard, SetupFlowWasm } from "sendbsv-wallet";
import "sendbsv-wallet/styles.css";
function App() {
const [wallet, setWallet] = React.useState(null);
if (!wallet) {
return (
<SetupFlowWasm
adminOriginator="your.app.example"
postBeef={async (beef, txids) => { /* wire to ARC */ }}
onComplete={setWallet}
/>
);
}
return <Dashboard wallet={wallet} />;
}SetupFlowWasm handles enrollment (passkey + WebAuthn-PRF → identity → UMP token publish) and unlock (PRF challenge → local SQLite or overlay lookup → wallet ready). It self-detects returning users, so subsequent visits skip onboarding.
When you're wrapping the wallet for third-party DApps, use useSignDrawer + wrap(rawWallet, adminOriginator). Every signed BRC-100 verb routes through a user-approval BottomSheet whenever the originator is external; the wallet's own UI surfaces bypass it.
The full surface area lives in src/index.ts. Common imports:
import {
Dashboard,
SetupFlowWasm,
SendSheet,
ReceiveSheet,
InboxScreen,
Holdings,
ActivityLog,
HotColdSweeper,
TipJar,
Collectibles,
useSignDrawer,
wrap
} from "sendbsv-wallet";<sendbsv-pay
to="alice@sendbsv.com"
amount="1000"
label="Tip 1000 sats"
></sendbsv-pay>
<script src="https://wallet.sendbsv.com/embed.js"></script>Or programmatically:
const result = await window.SendBSV.pay({
to: "alice@sendbsv.com",
amount: 1000,
description: "Premium unlock"
});
// result.status === "success" | "declined" | "error"Events on the custom element: sendbsv-success ({ txid, amount }), sendbsv-declined ({ reason: "user_cancelled" | "popup_blocked" }), sendbsv-error ({ message }).
The runtime weighs about 4 KB minified, 2 KB gzipped. Tapping the button opens wallet.sendbsv.com in a popup; the user confirms with their biometric; the result returns via postMessage with origin, source, and envelope version verified. Examples in examples/embed-host/.
<iframe
src="https://wallet.sendbsv.com/embed/tip?to=alice@sendbsv.com&amount=1000"
style="border:none; width:240px; height:80px;"
></iframe>Same popup-signing flow as the embed button. Drop-in for sites that can't add a <script> tag. See examples/widget-host/.
import { SendBSVConnect } from "sendbsv-wallet/connect";
const wallet = new SendBSVConnect();
const result = await wallet.requestPayment({
to: "alice@sendbsv.com",
amount: 1000,
description: "tip for the article"
});Promise-based. Never rejects — every failure path returns as data on result.status.
BRC-121 wrapper around fetch, built on canonical @bsv/402-pay:
import { createM2MFetch } from "sendbsv-wallet";
const m2mFetch = createM2MFetch({
wallet,
maxSpendPerCall: 5000,
maxSpendPerSession: 50_000
});
const data = await m2mFetch("https://api.example.com/premium-endpoint")
.then(r => r.json());For interactive contexts that want user approval on each spend, pair it with useSignDrawer().createM2MApprover().
- Engine —
bsv-wallet-toolbox-rs, the canonical Rust port of@bsv/wallet-toolbox, compiled to WASM. Runs in a DedicatedWorker;sqlite-wasminstalls its sahpool VFS for persistence. All 28 BRC-100 methods exposed viaWasmWalletAdapter. - Keys — WebAuthn-PRF derives the wallet root key from a passkey. Apple and Google passkey sync handles cross-device portability for default users; advanced users get a recovery key they can pair to a new-device passkey directly.
- Identity — UMP token published to the public BSV overlay network. Same passkey on a fresh device finds the same wallet.
- L2 storage —
storage.sendbsv.com(Cloudflare Workers + D1 + R2) holds an encrypted SQLite snapshot for cold-start recovery.hydrateOnEmptyruns once on returning-user-with-empty-local-storage. - Messaging — BRC-125 PeerPay routes through
messagebox.babbage.systems, currently fronted bymsgbox.sendbsv.comfor browser CORS.
pnpm install # install deps
pnpm dev # dev playground at http://localhost:5173
pnpm test # vitest unit suite (~2,600 tests)
pnpm tsc --noEmit # type check
pnpm app:build # production app build → dist-app/
pnpm test:e2e # Playwright headless e2eNode 24+ (see .nvmrc). The unit suite uses fake-indexeddb for headless persistence; Playwright runs against the real dist-app/ bundle.
Issues and pull requests welcome at https://github.com/BSVanon/SendBSV-Wallet/issues.
For security issues that should not be public, DM @SendBSV on X rather than filing a public issue.