Skip to content

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:

  1. connect() — calls initiateDappRelay(), creates a DappConnectionManager, sets uri/qrUri for QR display, and transitions to "connecting".
  2. Key exchange — persists the wallet's public key to session storage.
  3. walletready — transitions to "connected" and populates walletName/walletIcon.
  4. Auto-reconnect — on mount, checks session storage for a stored session with a walletPublicKey and automatically reconnects. During auto-reconnect, uri/qrUri remain null (no QR code to display — credentials are already known).
  5. disconnect() — sends a courtesy disconnect, cleans up the relay, and clears session storage.
  6. 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 on connect()
  • Wallet public key (walletPublicKey) — saved after key exchange
  • Wallet identity (walletName, walletIcon) — saved on walletready
  • Xpub paths (paths) — saved on walletready

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.