Skip to main content

Overview

useChipiWallet is a convenience hook that simplifies wallet management by combining multiple operations into one:
  • Wallet fetching (replaces useGetWallet)
  • Wallet creation (replaces useCreateWallet)
  • Balance checking (replaces useGetTokenBalance)
Use this hook when you want a streamlined API. Use the individual hooks (useGetWallet, useCreateWallet, useGetTokenBalance) when you need more granular control.

Quick Start

import { useChipiWallet } from "@chipi-stack/chipi-react";

function WalletComponent() {
  const { userId, getToken } = useYourAuthProvider(); // Clerk, Firebase, etc.
  
  const {
    wallet,
    hasWallet,
    balance,
    formattedBalance,
    createWallet,
    isCreating,
    isLoadingWallet,
  } = useChipiWallet({
    externalUserId: userId,
    getBearerToken: getToken,
  });

  if (isLoadingWallet) return <div>Loading...</div>;

  if (!hasWallet) {
    return (
      <button 
        onClick={() => createWallet({ encryptKey: "1234", chain: "STARKNET" })}
        disabled={isCreating}
      >
        {isCreating ? "Creating..." : "Create Wallet"}
      </button>
    );
  }

  return (
    <div>
      <p>Address: {wallet?.shortAddress}</p>
      <p>Balance: ${formattedBalance} USDC</p>
    </div>
  );
}

Configuration Options

interface UseChipiWalletConfig {
  // Required
  externalUserId: string | null | undefined;
  getBearerToken: () => Promise<string | null | undefined>;
  
  // Optional
  defaultToken?: ChainToken;  // Default: "USDC"
  enabled?: boolean;          // Default: true
}
OptionTypeDefaultDescription
externalUserIdstring | nullRequiredUser ID from your auth provider
getBearerToken() => Promise<string>RequiredFunction to get the auth token
defaultTokenChainToken"USDC"Token to fetch balance for
enabledbooleantrueWhether to fetch wallet on mount

Return Values

Wallet Data

PropertyTypeDescription
walletChipiWalletData | null | undefinedWallet data with computed properties
hasWalletbooleanWhether the user has a wallet
isLoadingWalletbooleanWallet fetch loading state
walletErrorError | nullAny error from fetching

Balance Data

PropertyTypeDescription
balanceGetTokenBalanceResponse | undefinedRaw balance data
formattedBalancestringFormatted balance (e.g., “1,234.56”)
isLoadingBalancebooleanBalance fetch loading state

Create Wallet

PropertyTypeDescription
createWallet(params) => Promise<CreateWalletResponse>Create a new wallet
isCreatingbooleanCreation loading state
createdWalletCreateWalletResponse | undefinedLast created wallet data

Actions

MethodDescription
refetchWallet()Refetch wallet data
refetchBalance()Refetch balance data
refetchAll()Refetch both wallet and balance

Computed Wallet Properties

The wallet object includes these computed properties:
interface ChipiWalletData extends GetWalletResponse {
  supportsSessionKeys: boolean;  // true for CHIPI wallets
  shortAddress: string;          // Truncated address for display
}

Example with Clerk Authentication

import { useState } from "react";
import { useAuth, SignInButton, SignedIn, SignedOut } from "@clerk/clerk-react";
import { useChipiWallet } from "@chipi-stack/chipi-react";

export function WalletDashboard() {
  const { userId, getToken } = useAuth();
  const [pin, setPin] = useState("");
  
  const {
    wallet,
    hasWallet,
    formattedBalance,
    createWallet,
    isCreating,
    isLoadingWallet,
    refetchAll,
  } = useChipiWallet({
    externalUserId: userId,
    getBearerToken: getToken,
  });

  const handleCreateWallet = async () => {
    if (!pin || pin.length < 4) {
      alert("Please enter a 4-digit PIN");
      return;
    }
    
    try {
      const result = await createWallet({ 
        encryptKey: pin,
        chain: "STARKNET",
        walletType: "CHIPI",
      });
      alert(`Wallet created! TX: ${result.txHash}`);
    } catch (err) {
      console.error(err);
      alert("Failed to create wallet");
    }
  };

  return (
    <div className="p-6 space-y-6">
      <SignedOut>
        <SignInButton mode="modal">
          <button className="btn">Sign In</button>
        </SignInButton>
      </SignedOut>
      
      <SignedIn>
        {isLoadingWallet ? (
          <p>Loading wallet...</p>
        ) : hasWallet ? (
          <div className="space-y-4">
            <p>Address: {wallet?.shortAddress}</p>
            <p className="text-2xl">${formattedBalance} USDC</p>
            <p>Sessions: {wallet?.supportsSessionKeys ? "✓" : "✗"}</p>
            <button onClick={() => refetchAll()}>Refresh</button>
          </div>
        ) : (
          <div className="space-y-4">
            <input
              type="password"
              placeholder="Enter 4-digit PIN"
              value={pin}
              onChange={(e) => setPin(e.target.value)}
              maxLength={4}
            />
            <button onClick={handleCreateWallet} disabled={isCreating}>
              {isCreating ? "Creating..." : "Create Wallet"}
            </button>
          </div>
        )}
      </SignedIn>
    </div>
  );
}

Wallet Types

TypeSession KeysDescription
CHIPI✅ YesOpenZeppelin account with SNIP-9 session key support
READY❌ NoArgent X compatible wallet
// Create a CHIPI wallet (supports session keys)
await createWallet({ 
  encryptKey: pin,
  chain: "STARKNET",
  walletType: "CHIPI" 
});

// Create a READY wallet (no session keys)
await createWallet({ 
  encryptKey: pin,
  chain: "STARKNET",
  walletType: "READY" 
});

Migration from Individual Hooks

Before

const { data: wallet, isLoading } = useGetWallet({
  params: { externalUserId: userId },
  getBearerToken: getToken,
  enabled: !!userId,
});

const { createWalletAsync } = useCreateWallet();

const { data: balance } = useGetTokenBalance({
  params: { walletPublicKey: wallet?.publicKey, ... },
  getBearerToken: getToken,
  enabled: !!wallet?.publicKey,
});

After

const {
  wallet,
  hasWallet,
  balance,
  formattedBalance,
  createWallet,
  isLoadingWallet,
} = useChipiWallet({
  externalUserId: userId,
  getBearerToken: getToken,
});
useChipiWallet automatically handles the dependency chain - it only fetches balance after the wallet is loaded.