React integration
@wizardconnect/react provides React components and hooks for dapp developers who want to add
WizardConnect wallet connectivity without writing relay boilerplate.
Quick start
import { useWizardConnect, WizardConnectQRDialog } from "@wizardconnect/react";
function App() {
const wc = useWizardConnect({ dappName: "My Dapp" });
return (
<>
<button onClick={wc.connect} disabled={wc.state !== "idle"}>
Connect Wallet
</button>
{wc.uri && wc.qrUri && (
<WizardConnectQRDialog
show={wc.state === "connecting"}
onClose={() => wc.disconnect()}
uri={wc.uri}
qrUri={wc.qrUri}
/>
)}
{wc.state === "connected" && (
<p>Connected to {wc.walletName}</p>
)}
</>
);
}
useWizardConnect
The useWizardConnect hook manages the full relay lifecycle:
connect()— callsinitiateDappRelay(), creates aDappConnectionManager, setsuri/qrUrifor QR display, and transitions to"connecting".- Key exchange — persists the wallet's public key to session storage.
walletready— transitions to"connected"and populateswalletName/walletIcon.- Auto-reconnect — on mount, checks session storage for a stored session with a
walletPublicKeyand automatically reconnects. During auto-reconnect,uri/qrUriremainnull(no QR code to display — credentials are already known). disconnect()— sends a courtesy disconnect, cleans up the relay, and clears session storage.- Remote disconnect — when the wallet sends a disconnect, the hook transitions to
"disconnected", clears the session, and tears down the relay.
Return value
interface UseWizardConnectResult {
state: "idle" | "connecting" | "connected" | "disconnected";
manager: DappConnectionManager | null;
uri: string | null;
qrUri: string | null;
walletName: string | null;
walletIcon: string | null;
connect: () => boolean;
disconnect: () => Promise<void>;
error: string | null;
}
Using the manager
Once state === "connected", the manager is a live DappConnectionManager from
@wizardconnect/dapp. Use it to derive addresses and request signatures:
// Derive a receive address pubkey
const pubkey = wc.manager.getPubkey(0, 0n);
// Send a sign request (auto-fills action, sequence, time)
const response = await wc.manager.signTransaction({
transaction: { transaction: txHex, sourceOutputs, broadcast: true },
inputPaths: [[0, "receive", 0]],
});
See the dapp integration docs for cancellation via
AbortSignal and the low-level sendSignRequest API.
For most dapps, you'll wrap the manager in an app-specific wallet adapter (like
RelayWalletDapp in the Cauldron and Moria codebases).
WizardConnectQRDialog
A framework-independent modal dialog for displaying the connection QR code. Uses inline styles (no Tailwind or CSS framework dependency) with a dark theme by default.
Customization
Colors, text, and logos are all customizable via props:
<WizardConnectQRDialog
show={true}
onClose={handleClose}
uri={connection.uri}
qrUri={connection.qrUri}
title="My Protocol"
subtitle="Scan to pair your wallet"
logoUrl="/my-logo.png"
theme={{
dialogBackground: "#0f172a",
headerBackground: "#0f172a",
borderColor: "#334155",
}}
onCopy={(uri) => {
navigator.clipboard.writeText(uri);
showToast("Copied!");
}}
/>
The onCopy callback replaces the default navigator.clipboard.writeText behavior, which is
useful when the dapp has its own toast/notification system.
AlphanumericQRCode
A standalone canvas-based QR code component. Uses QR Alphanumeric mode with error correction level H (30% recovery), which allows a center logo overlay without breaking the code.
<AlphanumericQRCode
value="WIZ://..."
size={280}
foreground="#1e2a4a"
background="#ffffff"
logoUrl="/logo.png"
/>
Session persistence
By default, useWizardConnect persists session data to localStorage under the
wizardconnect-session key. The stored session includes:
- Relay credentials (
privateKey,secret) — saved onconnect() - Wallet public key (
walletPublicKey) — saved after key exchange - Wallet identity (
walletName,walletIcon) — saved onwalletready - Xpub paths (
paths) — saved onwalletready
On page refresh, the hook auto-reconnects if a stored session with walletPublicKey exists.
Xpub paths and wallet name are restored immediately so getPubkey() works and the UI can
display the wallet name before the wallet app responds. During auto-reconnect, uri and
qrUri remain null — the QR dialog should not be shown. The typical pattern is:
{wc.uri && wc.qrUri && (
<WizardConnectQRDialog
show={wc.state === "connecting"}
onClose={() => wc.disconnect()}
uri={wc.uri}
qrUri={wc.qrUri}
/>
)}
This naturally hides the dialog during auto-reconnect since wc.uri is null.
If the wallet sends a disconnect, the hook clears the session automatically and transitions
to "disconnected". Dapps should listen for this state change to update their UI (e.g.
clear the wallet from their store).
Customization
useWizardConnect({
sessionKey: "my-app-session", // custom storage key (default: "wizardconnect-session")
persistSession: false, // disable persistence entirely
storage: myCustomStorage, // custom SessionStorage backend (default: localStorage)
});
The storage option accepts any object with getItem, setItem, and removeItem methods
(the standard Web Storage API). This is useful for React Native or server-side rendering
where localStorage is not available.
On disconnect, the stored session is cleared.