Skip to main content

Overview

The useWallet hook provides complete wallet management for Stacks blockchain authentication. It handles connecting/disconnecting wallets, managing user sessions, and formatting addresses for display. Source: src/hooks/useWallet.js

Import

import { useWallet } from './hooks/useWallet';

Hook Signature

function useWallet(): {
  connected: boolean,
  address: string | null,
  loading: boolean,
  shortAddress: (addr: string) => string,
  connectWallet: () => void,
  disconnectWallet: () => void,
}

Configuration

The hook uses the NetworkContext to determine whether to use mainnet or testnet addresses:
import { useNetwork } from '../context/NetworkContext';

const { network } = useNetwork(); // 'mainnet' or 'testnet'

Return Values

connected
boolean
Whether a wallet is currently connected. true if user is authenticated, false otherwise.
address
string | null
The user’s Stacks address for the active network. Returns the testnet address if network === 'testnet', otherwise returns mainnet address. null if not connected.
loading
boolean
true while authentication popup is active, false otherwise. Useful for disabling UI elements during connection.
shortAddress
function
Utility function to format addresses for display.Signature: (addr: string) => stringExample: "SP2H8...7SA5" (first 5 + last 4 characters)
connectWallet
function
Opens the Stacks wallet authentication popup. Handles the complete authentication flow including:
  • Launching wallet selector (Leather, Xverse, etc.)
  • Processing authentication callback
  • Extracting address for current network
  • Updating connection state
Signature: () => void
disconnectWallet
function
Signs out the current user, clears session data, and reloads the page to reset application state.Signature: () => void

Usage Example

import { useWallet } from './hooks/useWallet';

function WalletButton() {
  const { connected, address, loading, shortAddress, connectWallet, disconnectWallet } = useWallet();

  if (connected) {
    return (
      <div>
        <p>Connected: {shortAddress(address)}</p>
        <button onClick={disconnectWallet}>Disconnect</button>
      </div>
    );
  }

  return (
    <button onClick={connectWallet} disabled={loading}>
      {loading ? 'Connecting...' : 'Connect Wallet'}
    </button>
  );
}

Authentication Flow

The hook implements the standard Stacks authentication flow:
1

User clicks connect

Call connectWallet() to initiate authentication
2

Wallet popup appears

User selects their Stacks wallet (Leather, Xverse, etc.) and approves connection
3

Authentication callback

Hook receives user session data and extracts the appropriate address (mainnet or testnet)
4

State updates

connected becomes true, address is populated, and loading returns to false
5

Session persists

User remains connected across page reloads until they explicitly disconnect

Network Handling

The hook automatically selects the correct address based on your network configuration:
const getStxAddress = (userData) => {
  return network === 'testnet'
    ? userData?.profile?.stxAddress?.testnet
    : userData?.profile?.stxAddress?.mainnet;
};
Make sure your NetworkContext is properly configured in your app’s root component to ensure the correct network addresses are used.

App Configuration

The hook uses these app details for wallet authentication:
const appConfig = new AppConfig(['store_write', 'publish_data']);

appDetails: {
  name: 'Staxiq',
  icon: window.location.origin + '/favicon.ico',
}

Session Persistence

On component mount, the hook checks for existing sessions:
useEffect(() => {
  if (userSession.isUserSignedIn()) {
    const userData = userSession.loadUserData();
    const addr = getStxAddress(userData);
    if (addr) {
      setAddress(addr);
      setConnected(true);
    }
  }
}, []);
This ensures users remain connected across page reloads.

Best Practices

Loading States

Always check loading state to disable buttons and prevent double-clicks during authentication

Conditional Rendering

Use connected to show/hide wallet-dependent features and protect sensitive routes

Address Display

Always use shortAddress() for displaying addresses in UI to improve readability

Error Handling

The hook handles errors internally, but you can add try-catch in connectWallet if needed

Common Patterns

Conditional Feature Access

function AIAdvisor() {
  const { connected, address } = useWallet();
  
  if (!connected) {
    return <ConnectPrompt />;
  }
  
  return <AIStrategyGenerator address={address} />;
}

Multiple Hook Composition

function Portfolio() {
  const { connected, address } = useWallet();
  const { portfolio } = usePortfolio(address);
  const { strategy } = useAIAdvisor({ address, ...portfolio });
  
  return (
    <div>
      <WalletInfo address={address} />
      <PortfolioSummary data={portfolio} />
      <AIStrategy strategy={strategy} />
    </div>
  );
}

Build docs developers (and LLMs) love