@maximedogawa/chia-wallet-connect-react
v0.0.4
Published
WalletConnect plugin for Chia blockchain
Maintainers
Readme
Wallet Connect Plugin for Chia Network
A WalletConnect integration plugin for the Chia blockchain. This plugin provides a complete WalletConnect implementation that can be easily integrated into any Chia-based application.
Features
- WalletConnect v2 Support: Full integration with WalletConnect Sign Client
- Session Management: Connect, manage, and disconnect multiple wallet sessions
- QR Code Pairing: Display QR codes for easy wallet pairing
- Manual URI Copy: Copy pairing URIs manually for advanced users
- Address Management: Get and display wallet addresses
- Asset Management: Add CAT tokens to connected wallets
- Offer Generation: Generate offers for Chia transactions
- Dark Mode Support: Full dark/light mode support - all components automatically adapt to theme changes
Getting Started
Prerequisites
- Node.js 18+ or Bun 1.0+
- npm, yarn, pnpm, or bun
Installation
npm install
# or
yarn install
# or
pnpm install
# or
bun installBuild Package
Build the package for distribution (required before using in other projects):
npm run build
# or
yarn build
# or
pnpm build
# or
bun run buildThis will:
- Compile TypeScript to JavaScript
- Generate type definitions (.d.ts files)
- Copy styles to the dist directory
- Prepare the package for publishing or local use
Environment Variables
Create a .env.local file in the root directory with the following variables:
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=your_project_id
NEXT_PUBLIC_WALLET_CONNECT_RELAY_URL=wss://relay.walletconnect.com
NEXT_PUBLIC_CHIA_NETWORK=testnet
# WalletConnect Metadata (optional)
NEXT_PUBLIC_WALLET_CONNECT_METADATA_NAME=Wallet Connect
NEXT_PUBLIC_WALLET_CONNECT_METADATA_DESCRIPTION=Wallet Connect for Chia blockchain
NEXT_PUBLIC_WALLET_CONNECT_METADATA_URL=https://example.com
NEXT_PUBLIC_WALLET_CONNECT_METADATA_ICONS=https://example.com/logo.jpgDevelopment
Run the development server:
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun run devOpen http://localhost:3000 with your browser to see the result.
Build Demo
Build the demo application for production:
cd demo
npm run build
# or
yarn build
# or
pnpm build
# or
bun run buildStart Production Server
npm start
# or
yarn start
# or
pnpm start
# or
bun startAccessing Wallet Connection State
The package provides several ways to access and monitor the WalletConnect connection state in your application.
Using the useWalletConnectionState Hook (Recommended)
The easiest way to access connection state in your React components:
import { useWalletConnectionState } from '@maximedogawa/chia-wallet-connect-react';
function MyComponent() {
const {
isConnected,
connectedWallet,
address,
isWalletConnect,
walletConnectSession,
walletImage,
walletName,
cnsName,
} = useWalletConnectionState();
if (!isConnected) {
return <div>No wallet connected</div>;
}
return (
<div>
<p>Connected to: {connectedWallet}</p>
<p>Address: {address}</p>
{isWalletConnect && walletConnectSession && (
<p>Wallet: {walletConnectSession.peer.metadata.name}</p>
)}
</div>
);
}Hook Return Values:
isConnected: boolean- Whether any wallet is connectedconnectedWallet: string | null- The name of the connected wallet (e.g., "WalletConnect") or nulladdress: string | null- The wallet address or nullisWalletConnect: boolean- Whether WalletConnect is the connected walletwalletConnectSession: SessionTypes.Struct | null- The active WalletConnect session or nullwalletImage: string | null- The wallet image/icon URL or nullwalletName: string | null- The wallet name or nullcnsName: string | null- The CNS name (if available) or null
Using Redux Store Directly
You can also access the state directly from the Redux store:
import { store, useAppSelector } from '@maximedogawa/chia-wallet-connect-react';
import type { RootState } from '@maximedogawa/chia-wallet-connect-react';
function MyComponent() {
// Using useAppSelector hook
const connectedWallet = useAppSelector(
(state: RootState) => state.wallet.connectedWallet
);
const address = useAppSelector((state: RootState) => state.wallet.address);
const walletConnectSession = useAppSelector(
(state: RootState) => state.walletConnect.selectedSession
);
const walletConnectSessions = useAppSelector(
(state: RootState) => state.walletConnect.sessions
);
// Or access store directly (outside React components)
const state = store.getState();
const isConnected =
state.wallet.connectedWallet === "WalletConnect"
? Boolean(state.walletConnect.selectedSession)
: Boolean(state.wallet.connectedWallet);
return (
<div>
<p>Wallet: {connectedWallet}</p>
<p>Address: {address}</p>
</div>
);
}Redux State Structure:
state.wallet
connectedWallet: string | null- Connected wallet nameaddress: string | null- Wallet addressimage: string | null- Wallet image URLname: string | null- Wallet nameCNSName: string | null- CNS name
state.walletConnect
sessions: SessionTypes.Struct[]- All WalletConnect sessionsselectedSession: SessionTypes.Struct | null- Currently selected/active sessionselectedFingerprint: { [topic: string]: number }- Fingerprint for each sessionpairingUri: string | null- Current pairing URI (if pairing)
State Persistence
The connection state is automatically persisted to IndexedDB using redux-persist. This means:
- ✅ Connection state survives page refreshes
- ✅ State is automatically restored on app load
- ✅ No additional setup required
The following state is persisted:
walletslice (connectedWallet, address, image, name)walletConnectslice (sessions, selectedSession, selectedFingerprint)
Complete Example
import { useWalletConnectionState, ConnectButton } from '@maximedogawa/chia-wallet-connect-react';
function WalletStatus() {
const {
isConnected,
connectedWallet,
address,
isWalletConnect,
walletConnectSession,
walletImage,
} = useWalletConnectionState();
return (
<div>
<ConnectButton />
{isConnected && (
<div>
<h3>Wallet Status</h3>
<p>Connected: {connectedWallet}</p>
<p>Address: {address}</p>
{isWalletConnect && walletConnectSession && (
<div>
<p>Wallet: {walletConnectSession.peer.metadata.name}</p>
{walletImage && (
<img src={walletImage} alt="Wallet icon" />
)}
</div>
)}
</div>
)}
</div>
);
}Notes
- The
useWalletConnectionStatehook automatically updates when the connection state changes - For WalletConnect, both
connectedWallet === "WalletConnect"ANDselectedSessionmust be truthy for the connection to be considered active - The connection state is restored automatically after page refresh - no manual restoration needed
- Address may be
nullinitially if it hasn't been fetched yet, but the connection is still valid
Usage as a Package/Plugin
Installation
Install the package in your project:
npm install @maximedogawa/chia-wallet-connect-react
# or
yarn add @maximedogawa/chia-wallet-connect-react
# or
pnpm add @maximedogawa/chia-wallet-connect-react
# or
bun add @maximedogawa/chia-wallet-connect-reactSetup
1. Import Styles
Important: You must import the package styles in your app's main entry point:
// In your _app.tsx, layout.tsx, or main.tsx
import '@maximedogawa/chia-wallet-connect-react/styles';2. Configure Tailwind CSS (if using Tailwind)
Option A: Merge the package's Tailwind config (Recommended)
Import and merge the package's Tailwind configuration to ensure all styles and theme extensions are included:
// tailwind.config.js
const packageConfig = require('@maximedogawa/chia-wallet-connect-react/tailwind.config');
module.exports = {
...packageConfig,
content: [
'./src/**/*.{js,ts,jsx,tsx}',
'./pages/**/*.{js,ts,jsx,tsx}',
'./app/**/*.{js,ts,jsx,tsx}',
'./components/**/*.{js,ts,jsx,tsx}',
'./node_modules/@maximedogawa/chia-wallet-connect-react/dist/**/*.{js,ts,jsx,tsx}', // Important: Add this
],
// You can extend the theme further if needed
theme: {
...packageConfig.theme,
extend: {
...packageConfig.theme.extend,
// Your custom extensions
},
},
}Option B: Manual configuration
If you prefer not to merge the config, manually add the package to your Tailwind content paths and include the theme extensions:
// tailwind.config.js
module.exports = {
darkMode: 'class', // Required for dark mode support
content: [
'./src/**/*.{js,ts,jsx,tsx}',
'./pages/**/*.{js,ts,jsx,tsx}',
'./app/**/*.{js,ts,jsx,tsx}',
'./components/**/*.{js,ts,jsx,tsx}',
'./node_modules/@maximedogawa/chia-wallet-connect-react/dist/**/*.{js,ts,jsx,tsx}', // Important: Add this
],
theme: {
extend: {
colors: {
brandDark: '#526e78',
brandLight: '#EFF4F7',
},
keyframes: {
fadeIn: {
'0%': { opacity: 0 },
'100%': { opacity: 1 }
}
},
animation: {
fadeIn: 'fadeIn .3s ease-in-out',
},
},
},
plugins: [],
}Important Notes:
- The
contentarray must include the package's dist files so Tailwind can scan for class names - The
darkMode: 'class'setting is required for proper dark mode support - Make sure your PostCSS config includes Tailwind and Autoprefixer
3. Dark Mode Support
The package includes full dark mode support out of the box. Components automatically adapt to dark mode when the dark class is present on the <html> or <body> element.
Enable Dark Mode:
// Toggle dark mode by adding/removing the 'dark' class
// Option 1: Manual toggle
const toggleDarkMode = () => {
document.documentElement.classList.toggle('dark');
localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light');
};
// Option 2: React hook example
import { useEffect, useState } from 'react';
function useDarkMode() {
const [isDark, setIsDark] = useState(false);
useEffect(() => {
// Check localStorage or system preference
const stored = localStorage.getItem('theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const shouldBeDark = stored === 'dark' || (!stored && prefersDark);
setIsDark(shouldBeDark);
if (shouldBeDark) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
}, []);
const toggle = () => {
const newValue = !isDark;
setIsDark(newValue);
if (newValue) {
document.documentElement.classList.add('dark');
localStorage.setItem('theme', 'dark');
} else {
document.documentElement.classList.remove('dark');
localStorage.setItem('theme', 'light');
}
};
return [isDark, toggle] as const;
}All components automatically support dark mode:
ConnectButton- Adapts colors for dark/light themesConnectWalletModal- Full dark mode stylingModal- Dark background and text colorsWalletConnectQR- Dark mode compatible QR display- All other components - Fully theme-aware
4. Setup Redux Provider
Wrap your app with the Redux Provider:
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import { store, persistor } from '@maximedogawa/chia-wallet-connect-react';
function App() {
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
{/* Your app */}
</PersistGate>
</Provider>
);
}Basic Usage
Use the Connect Button
import { ConnectButton } from '@maximedogawa/chia-wallet-connect-react';
function MyComponent() {
return (
<div>
{/* Default usage */}
<ConnectButton />
{/* Custom text */}
<ConnectButton connectText="Connect Wallet" />
{/* Custom text and styling */}
<ConnectButton
connectText="My Custom Text"
className="custom-button-class"
/>
</div>
);
}ConnectButton Props:
connectText?: string- Text to display when wallet is not connected (default: "Manage Wallet")className?: string- Additional CSS classes to apply to the button
3. Use WalletManager Programmatically
import { WalletManager, useAppSelector } from '@maximedogawa/chia-wallet-connect-react';
function MyComponent() {
const walletManager = new WalletManager();
const connectedWallet = useAppSelector(state => state.wallet.connectedWallet);
const handleConnect = async () => {
await walletManager.connect('WalletConnect');
};
return (
<button onClick={handleConnect}>
{connectedWallet ? 'Connected' : 'Connect Wallet'}
</button>
);
}4. Access Wallet State
import { useAppSelector } from '@maximedogawa/chia-wallet-connect-react';
import type { RootState } from '@maximedogawa/chia-wallet-connect-react';
function WalletInfo() {
const address = useAppSelector((state: RootState) => state.wallet.address);
const connectedWallet = useAppSelector((state: RootState) => state.wallet.connectedWallet);
return (
<div>
<p>Wallet: {connectedWallet}</p>
<p>Address: {address}</p>
</div>
);
}Available Exports
Components
ConnectButton- Button component for connecting wallets (acceptsconnectTextandclassNameprops)ConnectButtonProps- TypeScript type for ConnectButton propsConnectWalletModal- Modal for wallet connection UIWalletConnectQR- QR code display componentWalletConnectSession- Session management componentAddAssetButton- Button to add assets to walletFingerprintListbox- Fingerprint selector component
Core Utilities
WalletManager- Main wallet management classWalletConnect- WalletConnect implementation class
Redux Store
store- Redux store instancepersistor- Redux persist instanceuseAppDispatch- Typed dispatch hookuseAppSelector- Typed selector hookRootState- TypeScript type for root stateAppDispatch- TypeScript type for dispatch
Redux Actions
setConnectedWallet- Set connected walletsetAddress- Set wallet addresssetCNSName- Set CNS nameconnectSession- Connect WalletConnect sessionsetPairingUri- Set pairing URIselectSession- Select active sessionsetSessions- Set all sessions- And more...
Environment Variables
Make sure to set these environment variables in your project:
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=your_project_id
NEXT_PUBLIC_WALLET_CONNECT_RELAY_URL=wss://relay.walletconnect.com
NEXT_PUBLIC_CHIA_NETWORK=testnetStyling
Import Styles
Import the package styles in your app's main entry point:
// In your _app.tsx, layout.tsx, or main.tsx
import '@maximedogawa/chia-wallet-connect-react/styles';Or if using CSS modules:
@import '@maximedogawa/chia-wallet-connect-react/styles';Troubleshooting Styling Issues
If styles are not appearing correctly:
- Verify CSS import: Make sure you've imported the styles in your main entry point
- Check Tailwind content paths: Ensure your
tailwind.config.jsincludes the package's dist files:content: [ // ... your paths './node_modules/@maximedogawa/chia-wallet-connect-react/dist/**/*.{js,ts,jsx,tsx}', ] - Verify PostCSS config: Ensure your
postcss.config.jsincludes Tailwind:module.exports = { plugins: { tailwindcss: {}, autoprefixer: {}, }, } - Rebuild Tailwind: After updating your config, restart your dev server and rebuild
- Check dark mode: If using dark mode, ensure
darkMode: 'class'is set in your Tailwind config and thedarkclass is on your<html>element - Merge package config: Use Option A in the setup section to automatically include all required theme extensions
Dark Mode Troubleshooting
If dark mode isn't working:
- Verify
darkclass: Check thatdocument.documentElement.classList.contains('dark')returnstruewhen dark mode should be active - Check Tailwind config: Ensure
darkMode: 'class'is set in your Tailwind config (included when merging package config) - Inspect components: Use browser dev tools to verify
dark:classes are being applied - Clear cache: Sometimes Tailwind needs a rebuild to recognize dark mode classes
Supported Wallets
- Sage Wallet
- Ozone Wallet
- Reference Wallet
- Any WalletConnect-compatible Chia wallet
License
See LICENSE file for details.
