Skip to main content

useTransactions Hook

The useTransactions hook provides transaction history access.

Basic Usage

import { useTransactions } from '@testinprod-io/privacy-boost-react';

function TransactionList() {
  const { transactions, loading, fetchHistory } = useTransactions();

  useEffect(() => {
    fetchHistory();
  }, []);

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

  return (
    <ul>
      {transactions.map((tx) => (
        <li key={tx.txHash}>
          {tx.type}: {tx.amount.toString()}
        </li>
      ))}
    </ul>
  );
}

Return Value

interface UseTransactionsResult {
  // Reactive data
  transactions: Transaction[];
  loading: boolean;

  // Actions
  fetchHistory(params?: TransactionHistoryParams): Promise<void>;
}

Transaction Type

interface Transaction {
  txHash: Hex;
  type: TransactionType;        // 'deposit' | 'withdraw' | 'transfer'
  direction: TransactionDirection;  // 'incoming' | 'outgoing'
  status: TransactionStatus;    // 'pending' | 'completed' | 'failed'
  tokenAddress: Hex;
  amount: bigint;
  createdAt: number;
  updatedAt: number;
  to?: Hex;
  from?: Hex;
  error?: string;
}

Fetching History

Basic Fetch

const { fetchHistory } = useTransactions();

useEffect(() => {
  fetchHistory();
}, []);

With Filters

// Only deposits
await fetchHistory({ type: 'deposit' });

// Only for specific token
await fetchHistory({ tokenAddress: '0x...usdc' });

// Limited results
await fetchHistory({ limit: 10 });

Filter Parameters

interface TransactionHistoryParams {
  type?: 'deposit' | 'withdraw' | 'transfer';
  tokenAddress?: string;
  limit?: number;
}

Complete Example

import { useState, useEffect } from 'react';
import { useTransactions } from '@testinprod-io/privacy-boost-react';

function TransactionHistory() {
  const { transactions, loading, fetchHistory } = useTransactions();
  const [filter, setFilter] = useState<string>('all');

  useEffect(() => {
    if (filter === 'all') {
      fetchHistory({ limit: 50 });
    } else {
      fetchHistory({ type: filter as any, limit: 50 });
    }
  }, [filter, fetchHistory]);

  const formatAmount = (amount: bigint, decimals = 18) => {
    return (Number(amount) / 10 ** decimals).toFixed(4);
  };

  const formatDate = (timestamp: number) => {
    return new Date(timestamp).toLocaleDateString();
  };

  return (
    <div>
      {/* Filter Tabs */}
      <div className="tabs">
        {['all', 'deposit', 'withdraw', 'transfer'].map((type) => (
          <button
            key={type}
            onClick={() => setFilter(type)}
            className={filter === type ? 'active' : ''}
          >
            {type.charAt(0).toUpperCase() + type.slice(1)}
          </button>
        ))}
      </div>

      {/* Loading State */}
      {loading && <div>Loading transactions...</div>}

      {/* Transaction List */}
      {!loading && transactions.length === 0 && (
        <p>No transactions found</p>
      )}

      <table>
        <thead>
          <tr>
            <th>Type</th>
            <th>Amount</th>
            <th>Status</th>
            <th>Date</th>
          </tr>
        </thead>
        <tbody>
          {transactions.map((tx) => (
            <tr key={tx.txHash}>
              <td>
                <span className={`type-${tx.type}`}>
                  {tx.type}
                </span>
                {tx.direction === 'incoming' && ' (received)'}
              </td>
              <td>{formatAmount(tx.amount)}</td>
              <td>
                <span className={`status-${tx.status}`}>
                  {tx.status}
                </span>
              </td>
              <td>{formatDate(tx.createdAt)}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

Transaction Details Modal

function TransactionDetail({ tx }: { tx: Transaction }) {
  return (
    <div className="tx-detail">
      <h3>{tx.type.toUpperCase()}</h3>

      <div className="row">
        <label>Status</label>
        <span className={`status-${tx.status}`}>{tx.status}</span>
      </div>

      <div className="row">
        <label>Amount</label>
        <span>{tx.amount.toString()}</span>
      </div>

      <div className="row">
        <label>Transaction Hash</label>
        <a
          href={`https://etherscan.io/tx/${tx.txHash}`}
          target="_blank"
          rel="noopener noreferrer"
        >
          {tx.txHash.slice(0, 20)}...
        </a>
      </div>

      {tx.to && (
        <div className="row">
          <label>To</label>
          <span>{tx.to.slice(0, 20)}...</span>
        </div>
      )}

      <div className="row">
        <label>Date</label>
        <span>{new Date(tx.createdAt).toLocaleString()}</span>
      </div>

      {tx.error && (
        <div className="error">
          Error: {tx.error}
        </div>
      )}
    </div>
  );
}

Refresh Transactions

function RefreshableHistory() {
  const { transactions, loading, fetchHistory } = useTransactions();
  const [lastRefresh, setLastRefresh] = useState<Date | null>(null);

  const handleRefresh = async () => {
    await fetchHistory();
    setLastRefresh(new Date());
  };

  return (
    <div>
      <div className="header">
        <h3>Transaction History</h3>
        <button onClick={handleRefresh} disabled={loading}>
          {loading ? 'Refreshing...' : 'Refresh'}
        </button>
      </div>

      {lastRefresh && (
        <small>Last refreshed: {lastRefresh.toLocaleTimeString()}</small>
      )}

      {/* Transaction list */}
    </div>
  );
}

Next Steps