From 9b4f21676c344f0ef85905a62851a7d452554868 Mon Sep 17 00:00:00 2001 From: Dagur Valberg Johannsson Date: Tue, 17 Mar 2026 14:55:18 +0100 Subject: [PATCH] Add README --- CLAUDE.md | 1 + README.md | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 README.md diff --git a/CLAUDE.md b/CLAUDE.md index 3f84030..1b9f0e1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -65,6 +65,7 @@ Protocol and architecture documentation lives in `docs/`. Keep it up to date whe | `docs/wallet.md` | `WalletAdapter`, `WalletConnectionManager`, or connection lifecycle changes | | `docs/dapp.md` | `DappConnectionManager` API or session lifecycle changes | | `docs/pubkey-derivation.md` | xpub delivery, `DappPubkeyStateManager`, or gap-fill logic changes | +| `docs/xpub-sharing.md` | xpub sharing rationale, security model, or comparison with other protocols changes | | `docs/index.md` | New top-level docs files are added | ## Packages diff --git a/README.md b/README.md new file mode 100644 index 0000000..90ea010 --- /dev/null +++ b/README.md @@ -0,0 +1,192 @@ +# WizardConnect + +A dapp-to-wallet protocol built for Bitcoin Cash. + +WizardConnect lets a dapp scan a wallet's QR code and immediately start +deriving addresses, constructing transactions, and requesting signatures — +no seed phrases, no trusted servers, no round trips. + +## Why not WalletConnect? + +WalletConnect was built for Ethereum, where a wallet is a single address. BCH +wallets are HD wallets with thousands of addresses for privacy. Forcing an +Ethereum protocol onto BCH means: + +- **One address per session.** WalletConnect gives the dapp a single address. + That breaks the HD wallet model and destroys the privacy that multiple + addresses provide. +- **Unreliable on BCH.** BCH support in WalletConnect is a second-class + citizen — a bridge on top of an Ethereum-native protocol. Connections drop, + sessions fail to restore, and there's no community maintaining it for BCH. + +WizardConnect replaces all of this with a protocol designed from the ground up +for UTXO chains and HD wallets. + +## How it works + +``` +Wallet Relay Dapp + │ │ │ + │ ◄───── QR code scan ────── │ ◄──── shows QR (wiz://...) │ + │ │ │ + │ wallet_ready ──────────────►│──────────────────────────────►│ + │ (xpubs + key exchange) │ │ + │ │ derive addresses │ + │ │ locally from xpubs │ + │ │ (no more round trips)│ + │ │ │ + │ ◄──────────────────────────│◄──── sign_transaction_request │ + │ user approves on wallet │ │ + │ sign_transaction_response──►│──────────────────────────────►│ + │ │ broadcast │ +``` + +1. The dapp generates a `wiz://` URI and displays it as a QR code. +2. The wallet scans the QR, connects to the relay, and sends its xpubs. +3. The dapp derives all addresses locally — no further contact with the wallet + needed for address generation. +4. When the dapp needs a signature, it sends a request. The user approves on + the wallet. The signed transaction comes back. + +All communication is end-to-end encrypted via Nostr NIP-17 gift wrap. The +relay sees only ciphertext. + +## Key features + +**Full HD wallet support.** The wallet shares BIP32 xpubs for specific +derivation paths (receive, change, DeFi). The dapp derives unlimited +addresses locally. No more single-address sessions. + +**Zero round trips for addresses.** After the initial handshake, the dapp +never needs to ask the wallet for a public key. It derives them on demand from +the xpubs, in microseconds. + +**Decentralized transport.** Built on Nostr — an open protocol with hundreds +of public relays. No proprietary bridge server. Users can point to any relay +for additional privacy or self-host their own. + +**Reconnection-proof.** Both sides can disconnect and reconnect independently +(app switch, browser refresh, network drop) and converge back to a live +session without user action. + +**Extensible.** The protocol negotiates capabilities during the handshake. +`hdwalletv1` is the first protocol; future protocols (multisig, post-quantum, +token-aware) can be added without breaking existing connections. + +**Open source (LGPL-3.0).** Free to use in commercial and non-commercial +applications. Modifications to the library itself must be shared back. + +## Packages + +``` +npm install @wizardconnect/core # transport, protocol types, key exchange +npm install @wizardconnect/dapp # dapp-side session + address derivation +npm install @wizardconnect/wallet # wallet-side connection + signing +``` + +| Package | Description | +|---------|-------------| +| `@wizardconnect/core` | Relay client, NIP-17 encryption, URI encoding, protocol message types | +| `@wizardconnect/dapp` | `DappConnectionManager`, `DappPubkeyStateManager` — session management and on-demand pubkey derivation | +| `@wizardconnect/wallet` | `WalletConnectionManager`, `WalletAdapter` interface — multi-connection management and sign request dispatch | + +## Quick start: dapp + +```typescript +import { initiateDappRelay } from "@wizardconnect/core"; +import { DappConnectionManager } from "@wizardconnect/dapp"; + +const dapp = new DappConnectionManager("My Dapp", "https://example.com/icon.png"); + +const relay = initiateDappRelay( + (payload) => dapp.updateConnection(payload.client, payload.status), + { explicitRelayUrls: ["wss://relay.cauldron.quest:443"] }, +); + +// Display relay.uri as a QR code for the wallet to scan + +dapp.on("walletready", () => { + // Connected! Derive addresses locally: + const receivePubkey = dapp.getPubkey(0, 0n); // receive path, index 0 + const changePubkey = dapp.getPubkey(1, 0n); // change path, index 0 +}); +``` + +## Quick start: wallet + +```typescript +import { WalletConnectionManager } from "@wizardconnect/wallet"; + +const manager = new WalletConnectionManager(myWalletAdapter); + +// When the user scans a dapp's QR code: +const connectionId = manager.connect("wiz://?p=...&s=..."); + +// When a sign request arrives, show it to the user: +manager.on("pendingSignRequest", async ({ connectionId, request }) => { + const approved = await showApprovalUI(request); + if (approved) { + await manager.sendSignResponse(connectionId, request.sequence, signedTxHex); + } else { + await manager.sendSignError(connectionId, request.sequence, "User rejected"); + } +}); +``` + +See [wallet integration guide](docs/wallet.md) for `WalletAdapter` implementation details. + +## Privacy model + +WizardConnect shares xpubs at the **chain level**, not the account level. +A dapp receiving the receive xpub can derive receive addresses but cannot +derive change addresses or any other internal wallet activity. This is the +same level of key material used by watch-only wallets. + +For wallets that want stronger isolation, the protocol supports per-session +xpub rotation — the dapp sees only the xpub node, never the derivation path. + +See [xpub sharing: why it's safe](docs/xpub-sharing.md) for a full discussion. + +## Security + +- Private keys never leave the wallet. Signing happens on-device. +- All relay traffic is end-to-end encrypted (NIP-17 gift wrap). The relay + cannot read messages. +- Key exchange includes an 8-byte shared secret (embedded in the QR code) for + MITM prevention. +- No trusted intermediary. The relay is a dumb message broker — compromise it + and you get ciphertext. + +## Documentation + +| Topic | Link | +|-------|------| +| Protocol messages and handshake | [protocol.md](docs/protocol.md) | +| Connection URI and key exchange | [connection-uri.md](docs/connection-uri.md) | +| Relay transport and encryption | [transport.md](docs/transport.md) | +| Wallet integration guide | [wallet.md](docs/wallet.md) | +| Dapp integration guide | [dapp.md](docs/dapp.md) | +| xpub delivery and derivation | [pubkey-derivation.md](docs/pubkey-derivation.md) | +| xpub sharing: why it's safe | [xpub-sharing.md](docs/xpub-sharing.md) | + +## Building + +```bash +npm install +npm run build # builds all packages in dependency order +npm run test # unit tests (fast, no network) +``` + +Integration tests hit a live relay: + +```bash +cd packages/wallet && npm run test:integration +``` + +## License + +[LGPL-3.0-or-later](https://www.gnu.org/licenses/lgpl-3.0.html). Free for +commercial and non-commercial use. Modifications to the library must be +released under the same license. + +Built by [Riften Labs](https://riftenlabs.com).