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-expo";

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 <Text>Loading...</Text>;

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

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

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 } from "@clerk/clerk-expo";
import { useChipiWallet } from "@chipi-stack/chipi-expo";
import { View, Text, TextInput, TouchableOpacity, ActivityIndicator } from "react-native";

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

  if (isLoadingWallet) {
    return <ActivityIndicator size="large" />;
  }

  if (!hasWallet) {
    return (
      <View style={{ padding: 20, gap: 16 }}>
        <TextInput
          secureTextEntry
          placeholder="Enter 4-digit PIN"
          value={pin}
          onChangeText={setPin}
          maxLength={4}
          keyboardType="numeric"
          style={{ borderWidth: 1, padding: 12, borderRadius: 8 }}
        />
        <TouchableOpacity 
          onPress={handleCreateWallet}
          disabled={isCreating}
          style={{ backgroundColor: '#007AFF', padding: 16, borderRadius: 8 }}
        >
          <Text style={{ color: 'white', textAlign: 'center' }}>
            {isCreating ? "Creating..." : "Create Wallet"}
          </Text>
        </TouchableOpacity>
      </View>
    );
  }

  return (
    <View style={{ padding: 20, gap: 16 }}>
      <Text>Address: {wallet?.shortAddress}</Text>
      <Text style={{ fontSize: 24, fontWeight: 'bold' }}>
        ${formattedBalance} USDC
      </Text>
      <Text>Sessions: {wallet?.supportsSessionKeys ? "✓ Supported" : "✗ Not Supported"}</Text>
      <TouchableOpacity onPress={() => refetchAll()}>
        <Text>Refresh</Text>
      </TouchableOpacity>
    </View>
  );
}

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.