# WalletCast — Integration Guide Use this guide to integrate `@walletcast/sdk` into any web dapp for decentralized wallet connection. ## Installation ```bash npm install @walletcast/sdk ``` ## API Reference ### `WalletCast.connect(options)` — Recommended High-level API that handles everything: session restore, injected wallet detection, and QR modal. ```typescript import { WalletCast } from '@walletcast/sdk'; const { provider, accounts, type, chainId, disconnect } = await WalletCast.connect({ // All options are optional — chain is detected from the wallet rpcUrl: 'https://eth.llamarpc.com', // Optional — public RPC for read methods (if omitted, all requests go through wallet) connectorUrl: 'https://walletcast.net/', // Optional (default) nostrRelays: ['wss://relay.damus.io'], // Optional — defaults provided preferInjected: true, // Check injected wallets first (default) theme: 'dark', // QR modal theme (default) }); // type is 'injected' | 'walletcast' console.log(`Connected via ${type}:`, accounts); ``` **Returns `ConnectResult`:** - `provider` — EIP-1193 compatible provider - `type` — `'injected'` if an injected wallet was used, `'walletcast'` if QR/deep link was used - `accounts` — Connected wallet accounts - `chainId` — Hex chain ID (e.g. `"0x1"`) - `disconnect` — `() => Promise` — call to disconnect and clear session **Behavior:** 1. Tries to restore a saved session (silent reconnect via ping/pong, 5s timeout) 2. If `preferInjected` is true, checks for `window.ethereum` + EIP-6963 3. If no injected wallet found, shows a Shadow DOM QR modal with wallet picker ### `WalletCast.createDeepLinkProvider(config)` — Lower-level For custom UI — generates deep links but doesn't show any modal. You render your own QR. ```typescript import { WalletCast, WALLET_REGISTRY, toSVGDataURL } from '@walletcast/sdk'; const { provider, links, connectorUrl, pubkey, keypair, relays, approval } = WalletCast.createDeepLinkProvider({ connectorUrl: 'https://walletcast.net/', }); ``` **Returns `DeepLinkResult`:** - `provider` — EIP-1193 compatible provider - `links` — `Record` — deep link URLs for each wallet - `connectorUrl` — Full connector URL: `https://walletcast.net/c/{pubkey_b64url}/{relay1}/{relay2}/...` - `pubkey` — Dapp's ephemeral public key (hex) - `keypair` — Dapp's full keypair (for manual session persistence) - `relays` — Nostr relay URLs used - `approval` — `Promise` — resolves with accounts when wallet connects ### `WalletCast.detectInjectedWallet()` Check for an injected EIP-1193 provider without triggering connection. ```typescript const injected = await WalletCast.detectInjectedWallet(); if (injected) { // Use injected wallet directly } ``` ### Utility Exports ```typescript import { generateKeyPair, // Returns KeyPair { privateKey, publicKey, publicKeyHex } toSVGDataURL, // Render QR code as SVG data URL WALLET_REGISTRY, // Wallet metadata map SessionManager, // Manual session persistence QRModal, // Use the modal directly } from '@walletcast/sdk'; ``` ## Common Patterns ### Simplest integration ```typescript import { WalletCast } from '@walletcast/sdk'; const { provider, disconnect } = await WalletCast.connect(); // Done! provider is ready to use — chain detected from wallet. ``` ### With ethers.js v6 ```typescript import { BrowserProvider } from 'ethers'; import { WalletCast } from '@walletcast/sdk'; const { provider } = await WalletCast.connect(); const signer = await new BrowserProvider(provider).getSigner(); const tx = await signer.sendTransaction({ to: '0x...', value: parseEther('0.01') }); ``` ### With viem ```typescript import { createWalletClient, custom } from 'viem'; import { WalletCast } from '@walletcast/sdk'; const { provider } = await WalletCast.connect(); const client = createWalletClient({ transport: custom(provider), }); ``` ### With React ```typescript import { useState, useCallback } from 'react'; import { WalletCast } from '@walletcast/sdk'; import type { EIP1193Provider, ConnectResult } from '@walletcast/sdk'; function useWalletCast() { const [result, setResult] = useState(null); const connect = useCallback(async () => { const res = await WalletCast.connect(); setResult(res); res.provider.on('disconnect', () => setResult(null)); return res; }, []); const disconnect = useCallback(async () => { await result?.disconnect(); setResult(null); }, [result]); return { provider: result?.provider ?? null, accounts: result?.accounts ?? [], type: result?.type ?? null, isConnected: !!result, connect, disconnect, }; } ``` ### Custom QR UI (skip built-in modal) ```typescript import { WalletCast, toSVGDataURL, WALLET_REGISTRY } from '@walletcast/sdk'; import type { WalletId } from '@walletcast/sdk'; const { provider, links, approval } = WalletCast.createDeepLinkProvider({ connectorUrl: 'https://walletcast.net/', }); // Render your own QR const walletId: WalletId = 'metamask'; const qrSvg = toSVGDataURL(links[walletId].universal, { moduleSize: 6, foreground: '#6366f1', background: '#141414', }); document.querySelector('#qr').src = qrSvg; const accounts = await approval; ``` ## Supported Wallets | ID | Wallet | Deep Link | Universal Link | |----|--------|-----------|----------------| | `metamask` | MetaMask | `metamask://dapp/...` | `https://metamask.app.link/dapp/...` | | `trust` | Trust Wallet | `trust://open_url?...` | `https://link.trustwallet.com/open_url?...` | | `coinbase` | Coinbase Wallet | `cbwallet://dapp?...` | `https://go.cb-w.com/dapp?...` | | `phantom` | Phantom | `phantom://browse/...` | `https://phantom.app/ul/browse/...` | | `okx` | OKX Wallet | `okx://wallet/dapp/url?...` | — | ## EIP-1193 Events ```typescript provider.on('connect', ({ chainId }) => { ... }); provider.on('disconnect', () => { ... }); provider.on('accountsChanged', (accounts: string[]) => { ... }); provider.on('chainChanged', (chainId: string) => { ... }); ``` ## Session Persistence Sessions are automatically managed by `WalletCast.connect()`: - Saved to `localStorage` with 24-hour TTL - Restored silently on page reload via ping/pong - Cleared on `disconnect()` or when connector sends disconnect message - Works on both dapp and connector sides ## Self-Hosting the Connector The connector page is a self-contained HTML file (~55KB). To self-host: ```bash npm install @walletcast/deep-link cd node_modules/@walletcast/deep-link pnpm build:connector ``` Output: `dist/connector.html`. Deploy to any static hosting and pass your URL as `connectorUrl`. ## Source - GitHub: [github.com/nicholasgasior/walletcast](https://github.com/nicholasgasior/walletcast) - npm: [@walletcast/sdk](https://www.npmjs.com/package/@walletcast/sdk)