All files / src/features/wallet/hooks use-wallet.ts

100% Statements 41/41
70.58% Branches 12/17
100% Functions 10/10
100% Lines 41/41

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134                      4x   17x   17x     9x 9x 7x 7x 7x     2x     2x 2x             17x   17x                       4x 16x   16x   16x   3x 3x   3x 3x     1x     1x                 1x     2x 2x 2x   3x         1x                 4x 10x 10x 10x   10x                     1x       2x 2x       2x 2x         1x 1x        
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useWalletStore } from '@/store/wallet-store';
import { walletApi, type WithdrawRequest } from '../services/wallet.service';
import { walletUtils } from '../utils/wallet-utils';
import { currencyFormatter } from '@/lib/currency-formatter';
import { WALLET_QUERY_KEYS, WALLET_ERROR_MESSAGES } from '@/constants/wallet';
 
/**
 * Hook to fetch and manage wallet data
 * Handles loading states and error management through Zustand store
 */
export const useWallet = () => {
  const { setWalletData, setWalletError, walletData, walletError } =
    useWalletStore();
 
  const query = useQuery({
    queryKey: WALLET_QUERY_KEYS.BALANCE(),
    queryFn: async () => {
      try {
        const data = await walletApi.getWalletData();
        setWalletData(data);
        setWalletError(null);
        return data;
      } catch (error) {
        const errorMessage =
          error instanceof Error
            ? error.message
            : WALLET_ERROR_MESSAGES.LOAD_FAILURE;
        setWalletError(errorMessage);
        throw error;
      }
    },
    enabled: true,
  });
 
  // Use only React Query's isLoading state for better test compatibility
  const isLoading = query.isLoading;
 
  return {
    data: walletData || query.data || null,
    isLoading,
    error: walletError || (query.error?.message ?? null),
    refetch: query.refetch,
  };
};
 
/**
 * Hook to handle fund withdrawal operations
 * Includes optimistic updates and transaction history management
 */
export const useWithdrawFunds = () => {
  const queryClient = useQueryClient();
  const { setWithdrawing, setWithdrawError, updateBalance, addTransaction } =
    useWalletStore();
 
  return useMutation({
    mutationFn: async (data: WithdrawRequest) => {
      setWithdrawing(true);
      setWithdrawError(null);
 
      try {
        await walletApi.withdrawFunds(data);
 
        // Update local balance optimistically
        updateBalance(data.amount, 'subtract');
 
        // Add transaction to history
        addTransaction({
          id: walletUtils.generateTransactionId('withdrawal'),
          amount: data.amount,
          type: 'withdrawal',
          status: 'completed',
          date: new Date().toISOString(),
          description: `Withdrawal to ${data.destination}`,
        });
 
        return data;
      } catch (error) {
        const errorMessage =
          error instanceof Error ? error.message : 'Withdrawal failed';
        setWithdrawError(errorMessage);
        throw error;
      } finally {
        setWithdrawing(false);
      }
    },
    onSuccess: () => {
      // Invalidate and refetch wallet data to ensure consistency
      queryClient.invalidateQueries({ queryKey: WALLET_QUERY_KEYS.BALANCE() });
    },
  });
};
 
/**
 * Combined hook providing all wallet operations and utilities
 * This is the main hook components should use for wallet functionality
 */
export const useWalletOperations = () => {
  const walletQuery = useWallet();
  const withdrawMutation = useWithdrawFunds();
  const { isWithdrawing, withdrawError } = useWalletStore();
 
  return {
    // Wallet data
    ...walletQuery,
 
    // Withdraw operations
    withdraw: withdrawMutation.mutate,
    isWithdrawing,
    withdrawError,
 
    // Helper methods using utilities
    formatCurrency: (amount: string, currency = 'USD') =>
      currencyFormatter.format(amount, currency),
 
    // Validation using utilities
    canWithdraw: (amount: string) => {
      const currentBalance = walletQuery.data?.balance || '0';
      return walletUtils.canWithdraw(amount, currentBalance);
    },
 
    validateWithdrawal: (amount: string) => {
      const currentBalance = walletQuery.data?.balance || '0';
      return walletUtils.validateWithdrawalAmount(amount, currentBalance);
    },
 
    // Wallet health status
    getWalletHealth: () => {
      const currentBalance = walletQuery.data?.balance || '0';
      return walletUtils.getWalletHealth(currentBalance);
    },
  };
};