Skip to content

Latest commit

Β 

History

History
254 lines (200 loc) Β· 6.12 KB

File metadata and controls

254 lines (200 loc) Β· 6.12 KB

Transaction Detail Screen - Quick Start Guide

🎯 What Was Implemented

A comprehensive transaction detail screen that displays full information about individual transactions with proper handling of edge cases.

πŸ“ Location

Screen: app/transaction/[id].tsx
Feature Module: src/features/transactions/
Tests: __tests__/transactionDetail.test.tsx

✨ Key Features

1. Transaction Information Display

  • βœ… Amount with direction (+/-)
  • βœ… Transaction status (Successful/Pending/Failed)
  • βœ… Sender and recipient addresses
  • βœ… Transaction hash
  • βœ… Memo (when present)
  • βœ… Timestamp
  • βœ… Asset type

2. Interactive Features

  • βœ… Copy to clipboard (hash, addresses, memo)
  • βœ… Open in Stellar Explorer
  • βœ… Contact name resolution
  • βœ… Visual copy feedback

3. Error Handling

  • βœ… Missing data gracefully handled
  • βœ… Transaction not found state
  • βœ… Clipboard failure alerts
  • βœ… Explorer unavailability handling

πŸš€ How to Use

Navigate to Detail Screen

// From transaction list
import { useRouter } from 'expo-router';

const router = useRouter();
router.push(`/transaction/${transactionId}`);

Access Transaction Helpers

import { 
  getTransactionStatus, 
  formatTransactionAmount,
  getTransactionHash 
} from '@/features/transactions';

const status = getTransactionStatus(transaction);
const amount = formatTransactionAmount(transaction, userPublicKey);
const hash = getTransactionHash(transaction);

🧩 Component Structure

TransactionDetailScreen
β”œβ”€β”€ Hero Section
β”‚   β”œβ”€β”€ Direction Icon
β”‚   β”œβ”€β”€ Amount Display
β”‚   β”œβ”€β”€ Date
β”‚   └── Status Badge
β”œβ”€β”€ Details Card
β”‚   β”œβ”€β”€ Type Row
β”‚   β”œβ”€β”€ Status Row
β”‚   β”œβ”€β”€ Memo Row (conditional)
β”‚   β”œβ”€β”€ Hash Row
β”‚   β”œβ”€β”€ Sender Row
β”‚   └── Recipient Row
└── Explorer Section (conditional)
    └── Explorer Button or Unavailable Message

πŸ“Š Data Fields Handled

Required Fields

  • id - Transaction identifier
  • amount - Transaction amount (fallback: 'N/A')
  • from - Sender address (conditionally shown)
  • to - Recipient address (conditionally shown)

Optional Fields

  • hash or transaction_hash - Transaction hash
  • created_at or createdAt or timestamp - Date
  • memo - Memo text
  • memo_type - Memo type (text, id, hash, return)
  • transaction_successful - Success boolean
  • is_pending - Pending boolean
  • asset - Asset code (default: 'XLM')

🎨 Status States

Successful βœ“

{
  transaction_successful: true,
  is_pending: false
}
  • Green checkmark icon
  • "Successful" label

Pending ⏱

{
  is_pending: true
}
  • Yellow clock icon
  • "Pending" label

Failed βœ—

{
  transaction_successful: false
}
  • Red X icon
  • "Failed" label

πŸ§ͺ Running Tests

# Run all tests
npm test

# Run transaction detail tests only
npm test transactionDetail.test.tsx

# Run with coverage
npm test -- --coverage

πŸ“ Example Transaction Data

const exampleTransaction = {
  id: 'tx123',
  from: 'GABCD...XYZ',
  to: 'GXYZ...ABC',
  amount: '100.0000000',
  asset: 'XLM',
  created_at: '2024-01-15T10:30:00Z',
  hash: 'abc123...def456',
  memo: 'Payment for services',
  memo_type: 'text',
  transaction_successful: true,
  is_pending: false,
};

πŸ”— Integration Points

From History Screen

// app/(tabs)/history.tsx
<TransactionListItem
  transaction={tx}
  currentPublicKey={publicKey}
  onPress={(tx) => router.push(`/transaction/${tx.id}`)}
/>

With Contact Store

import { useAppStore } from '@/store/appStore';
import { resolveAddressLabel } from '@/utils/contacts';

const contacts = useAppStore((state) => state.contacts);
const label = resolveAddressLabel(address, contacts);

With Explorer

import { getExplorerTxUrl } from '@/services/stellar';

const explorerUrl = getExplorerTxUrl(transactionHash);
if (explorerUrl) {
  await Linking.openURL(explorerUrl);
}

πŸ›  Helper Functions

Status Detection

import { getTransactionStatus } from '@/features/transactions';

const status = getTransactionStatus(transaction);
// Returns: 'successful' | 'pending' | 'failed'

Direction Check

import { isSentTransaction } from '@/features/transactions';

const isSent = isSentTransaction(transaction, userPublicKey);
// Returns: true if user sent this transaction

Data Validation

import { validateTransactionData } from '@/features/transactions';

const { isValid, missingFields } = validateTransactionData(transaction);
// Returns validation result with missing field list

πŸ› Common Issues & Solutions

Issue: Transaction not found

Solution: Ensure transaction exists in wallet store and ID is correct

Issue: Explorer link not working

Solution: Check network configuration and hash availability

Issue: Copy not working

Solution: Verify expo-clipboard permissions and installation

Issue: Date showing "Unknown date"

Solution: Check date field format (should be ISO 8601)

πŸ“š Related Documentation

πŸŽ“ Best Practices

  1. Always handle missing data - Use optional chaining and fallbacks
  2. Validate before display - Check data exists before rendering
  3. Provide user feedback - Show loading, error, and success states
  4. Use helper functions - Don't duplicate transaction logic
  5. Test edge cases - Missing fields, empty strings, null values

πŸ’‘ Quick Tips

  • Use getTransactionHash() instead of direct field access
  • Use formatTransactionDate() for consistent date formatting
  • Use validateTransactionData() before critical operations
  • Check explorer URL availability before showing link
  • Always provide copy feedback to users

Need Help? Check the full documentation in src/features/transactions/README.md