Open-source wallet infrastructure

Like WalletConnect, but without WalletConnect.

WalletConnect built the standard for mobile wallet connectivity. Then came the dashboards, the API keys, the monthly bills, and the single point of failure. WalletCast gives you the same seamless experience — built on open protocols, without asking anyone's permission.

WalletCast QR connection on mobile

Zero Onboarding

Forget creating developer accounts or waiting for approvals. Install the SDK, generate a QR, and you're connected. Zero friction.

100% Free, No Limits

No payment tiers, no per-user fees, no credit cards. Public and open infrastructure, the way it should have always been.

Truly Decentralized

You don't depend on our servers. WalletCast uses P2P and Nostr routing. If we disappear tomorrow, your dApp keeps working perfectly.

Drop-in Replacement

Compatible with standard provider interfaces (EIP-1193). Switching from your current solution takes a couple lines of code.

1

Generate keypair

Dapp creates an ephemeral keypair and renders a QR code with wallet-specific deep links.

2

Scan QR code

User scans the QR — their wallet opens the connector page in its in-app browser.

3

Bridge RPC calls

The connector detects window.ethereum and bridges all RPC calls over encrypted Nostr messages.

4

Connected

Dapp receives signed transactions and wallet events in real-time. No relay signup. No tracking.

WalletCast connection flow — choose wallet, scan QR, connected
1Choose wallet 2Scan QR code 3Connected
MetaMask
Trust Wallet
Coinbase Wallet
Phantom
OKX Wallet
import { WalletCast } from '@walletcast/sdk'; const { provider, accounts } = await WalletCast.connect(); // That's it. Chain and accounts detected from the wallet.

Ready to build?

npm install @walletcast/sdk
Documentation

Everything you need to integrate WalletCast into your dapp.

Quickstart

1. Install

npm install @walletcast/sdk

2. Connect

import { WalletCast } from '@walletcast/sdk'; const { provider, accounts, type, chainId, disconnect } = await WalletCast.connect(); // type is 'injected' (used window.ethereum) or 'walletcast' (QR deep link) console.log(`Connected via ${type} on chain ${chainId}:`, accounts);

WalletCast.connect() automatically restores saved sessions, detects injected wallets, and shows a QR modal if no injected wallet is found.

3. Use the provider

const balance = await provider.request({ method: 'eth_getBalance', params: [accounts[0], 'latest'] });

API Reference

WalletCast.connect(options?)

High-level API that handles everything: session restore, injected wallet detection, and QR modal.

Options
OptionTypeDefaultDescription
rpcUrlstringPublic RPC for read methods
chainIdnumberDetected from wallet if omitted
connectorUrlstring'https://walletcast.net/'Connector page URL
nostrRelaysstring[]defaultsNostr relay URLs
preferInjectedbooleantrueCheck injected wallet first
theme'dark' | 'light' | 'system''dark'QR modal theme
walletIdWalletIdSkip picker, show specific wallet QR
Returns ConnectResult
FieldTypeDescription
providerEIP1193ProviderUse for all RPC calls
type'injected' | 'walletcast'Connection method used
accountsstring[]Connected wallet accounts
chainIdstringHex chain ID (e.g. "0x1")
disconnect() => Promise<void>Disconnect and clear session

WalletCast.createDeepLinkProvider(config)

Lower-level API for custom UI. Generates deep links but doesn't show any modal.

import { WalletCast, toSVGDataURL } from '@walletcast/sdk'; const { provider, links, approval } = WalletCast.createDeepLinkProvider({ connectorUrl: 'https://walletcast.net/', }); const qrSvg = toSVGDataURL(links.metamask.universal, { moduleSize: 6 }); const accounts = await approval;

WalletCast.detectInjectedWallet()

Check for an injected EIP-1193 provider without triggering connection.

const injected = await WalletCast.detectInjectedWallet(); if (injected) { /* use injected wallet */ }

Framework Examples

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') });
import { createWalletClient, custom } from 'viem'; import { mainnet } from 'viem/chains'; import { WalletCast } from '@walletcast/sdk'; const { provider } = await WalletCast.connect(); const client = createWalletClient({ chain: mainnet, transport: custom(provider), });
import { useState, useCallback } from 'react'; import { WalletCast } 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, accounts: result?.accounts ?? [], isConnected: !!result, connect, disconnect }; }

Events

provider.on('connect', ({ chainId }) => { /* ... */ }); provider.on('disconnect', () => { /* ... */ }); provider.on('accountsChanged', (accounts) => { /* ... */ }); provider.on('chainChanged', (chainId) => { /* ... */ });

Supported Wallets

IDWalletDeep LinkUniversal Link
metamaskMetaMaskmetamask://dapp/...metamask.app.link/dapp/...
trustTrust Wallettrust://open_url?...link.trustwallet.com/...
coinbaseCoinbase Walletcbwallet://dapp?...go.cb-w.com/dapp?...
phantomPhantomphantom://browse/...phantom.app/ul/browse/...
okxOKX Walletokx://wallet/dapp/...

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 the connector sends a disconnect message.

Why WalletCast?

Connecting a mobile wallet to a desktop dapp should not require a centralized relay service, an API key, or trust in any third party. WalletCast replaces the entire WalletConnect infrastructure with encrypted Nostr messages — an open protocol anyone can relay.

Architecture

[Dapp] [Wallet] | | |— generates ephemeral keypair | |— creates QR with deep link ----------------> | | |— opens connector page | |— detects window.ethereum | |— derives shared key (ECDH) | | | <------ encrypted Nostr messages ------> | | | |— eth_sendTransaction -------------------> | | <---- signed result ---------------------- | All messages are end-to-end encrypted. Relays see only opaque ciphertext.

WalletCast vs WalletConnect

FeatureWalletConnectWalletCast
Centralized relayRequiredNone
Project ID / signupRequiredNone
Message privacyRelay can observeE2E encrypted
Self-hostable relayComplexAny Nostr relay
Connector size~200KB+ SDK~55KB single file
ProtocolProprietaryNostr (open)
Vendor lock-inYesNone

Self-Hosting

The connector is a single self-contained HTML file (~55KB). Deploy it anywhere and pass your URL:

npm install @walletcast/deep-link # Build connector.html — deploy to any static host WalletCast.connect({ connectorUrl: 'https://your-domain.com/connector.html' });

WalletCast

Secure wallet bridge

Initializing...

Liquidity & Settlement

Hot Wallet

No hot wallet configured

Stake Liquidity

Your Stakes

No active stakes

Auto-Settlement

Auto-Settle
Min Profit 0.001 ETH

Statistics

Settled
0
Earnings
0 ETH
Gas Spent
0 ETH
Pending
0

Settlement Log

Powered by WalletCast