Skip to main content

Overview

The Transactions API provides access to a user’s complete transaction history across all chains. It supports pagination for efficient data loading and returns detailed information about swaps, transfers, and their execution status.

API Methods

getTransactionHistory

Retrieve paginated transaction history for a user.
transactionsApi.getTransactionHistory(
  params: TransactionHistoryParams
): Promise<TransactionHistoryResponse>

Parameters

params
TransactionHistoryParams
required
Pagination and filter parameters

Returns

TransactionHistoryResponse
object
Paginated list of transactions with continuation token

Example

import { transactionsApi } from '@/lib/api/transactions';
import type { TransactionHistoryParams } from '@/lib/types/transaction';

const params: TransactionHistoryParams = {
  user: '0x1234567890abcdef1234567890abcdef12345678',
  limit: 20
};

const response = await transactionsApi.getTransactionHistory(params);

console.log('Loaded transactions:', response.transactions.length);
console.log('Has more:', !!response.continuation);

// Display transactions
response.transactions.forEach(tx => {
  console.log(`${tx.type}: ${tx.originToken.aggregatedAssetId} -> ${tx.destinationToken?.aggregatedAssetId}`);
  console.log(`Status: ${tx.status}`);
  console.log(`Time: ${tx.timestamp}`);
});

Pagination Pattern

The API uses cursor-based pagination with continuation tokens:
1

Initial Request

Make first request with just user and limit parameters
const response = await transactionsApi.getTransactionHistory({
  user: accountAddress,
  limit: 20
});
2

Check for More

Check if continuation token exists in response
if (response.continuation) {
  // More pages available
}
3

Load Next Page

Pass continuation token to get next page
const nextPage = await transactionsApi.getTransactionHistory({
  user: accountAddress,
  limit: 20,
  continuation: response.continuation
});
4

Repeat

Continue until continuation is undefined

Real-World Implementation

Here’s how the transaction history is used in the actual application:
const fetchTransactionHistory = useCallback(async (params: TransactionHistoryParams) => {
  if (!params.user) return;

  setLoading(true);
  setError(null);

  try {
    const data = await transactionsApi.getTransactionHistory(params);

    if (params.continuation) {
      // Append to existing transactions for pagination
      setTransactions(prev => [...prev, ...data.transactions]);
    } else {
      // Replace transactions for initial load or refresh
      setTransactions(data.transactions);
    }

    setContinuation(data.continuation);
    setHasMore(!!data.continuation);
  } catch (err) {
    setError(err instanceof Error ? err.message : 'Failed to fetch transaction history');
  } finally {
    setLoading(false);
  }
}, []);

Transaction Types

SWAP

Token swap transaction between different assets
  • Has both originToken and destinationToken
  • May involve multiple chains
  • Includes price/rate information

TRANSFER

Token transfer to another account
  • Has recipientAccountId
  • Only originToken is relevant
  • May be cross-chain

Transaction Status Flow

  • PENDING: Transaction submitted, waiting for blockchain confirmation
  • IN_PROGRESS: Being processed across chains (OneBalance only)
  • COMPLETED: Successfully completed on all chains
  • FAILED: Transaction failed on one or more chains
  • REFUNDED: Failed transaction with funds returned to user

Filtering and Display

const completedTxs = transactions.filter(tx => tx.status === 'COMPLETED');
const pendingTxs = transactions.filter(tx => 
  tx.status === 'PENDING' || tx.status === 'IN_PROGRESS'
);

Display Transaction Details

import { formatUnits } from 'viem';

function formatTransaction(tx: Transaction) {
  const fromAmount = formatUnits(
    BigInt(tx.originToken.amount),
    // Get decimals from asset metadata
    18
  );
  
  const timestamp = new Date(tx.timestamp).toLocaleString();
  
  return {
    id: tx.quoteId,
    type: tx.type,
    from: `${fromAmount} ${tx.originToken.aggregatedAssetId}`,
    to: tx.destinationToken 
      ? `${formatUnits(BigInt(tx.destinationToken.amount), 18)} ${tx.destinationToken.aggregatedAssetId}`
      : 'N/A',
    status: tx.status,
    time: timestamp,
    explorerUrl: tx.originChainOperations[0]?.explorerUrl
  };
}

Error Handling

try {
  const response = await transactionsApi.getTransactionHistory(params);
  return response;
} catch (error) {
  if (error instanceof Error) {
    console.error('Failed to fetch transaction history:', error.message);
    
    // Handle specific errors
    if (error.message.includes('invalid address')) {
      // Show address validation error
    } else if (error.message.includes('rate limit')) {
      // Back off and retry
    }
  }
  
  throw error;
}

Best Practices

Reasonable Page Size

Use 10-50 transactions per page for optimal performance and UX

Cache Results

Cache transaction data to avoid unnecessary API calls on navigation

Show Loading States

Display loading indicators during pagination for better UX

Handle Empty States

Show helpful messages when users have no transaction history

Build docs developers (and LLMs) love