A comprehensive transaction detail screen that displays full information about individual transactions with proper handling of edge cases.
Screen: app/transaction/[id].tsx
Feature Module: src/features/transactions/
Tests: __tests__/transactionDetail.test.tsx
- β Amount with direction (+/-)
- β Transaction status (Successful/Pending/Failed)
- β Sender and recipient addresses
- β Transaction hash
- β Memo (when present)
- β Timestamp
- β Asset type
- β Copy to clipboard (hash, addresses, memo)
- β Open in Stellar Explorer
- β Contact name resolution
- β Visual copy feedback
- β Missing data gracefully handled
- β Transaction not found state
- β Clipboard failure alerts
- β Explorer unavailability handling
// From transaction list
import { useRouter } from 'expo-router';
const router = useRouter();
router.push(`/transaction/${transactionId}`);import {
getTransactionStatus,
formatTransactionAmount,
getTransactionHash
} from '@/features/transactions';
const status = getTransactionStatus(transaction);
const amount = formatTransactionAmount(transaction, userPublicKey);
const hash = getTransactionHash(transaction);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
id- Transaction identifieramount- Transaction amount (fallback: 'N/A')from- Sender address (conditionally shown)to- Recipient address (conditionally shown)
hashortransaction_hash- Transaction hashcreated_atorcreatedAtortimestamp- Datememo- Memo textmemo_type- Memo type (text, id, hash, return)transaction_successful- Success booleanis_pending- Pending booleanasset- Asset code (default: 'XLM')
{
transaction_successful: true,
is_pending: false
}- Green checkmark icon
- "Successful" label
{
is_pending: true
}- Yellow clock icon
- "Pending" label
{
transaction_successful: false
}- Red X icon
- "Failed" label
# Run all tests
npm test
# Run transaction detail tests only
npm test transactionDetail.test.tsx
# Run with coverage
npm test -- --coverageconst 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,
};// app/(tabs)/history.tsx
<TransactionListItem
transaction={tx}
currentPublicKey={publicKey}
onPress={(tx) => router.push(`/transaction/${tx.id}`)}
/>import { useAppStore } from '@/store/appStore';
import { resolveAddressLabel } from '@/utils/contacts';
const contacts = useAppStore((state) => state.contacts);
const label = resolveAddressLabel(address, contacts);import { getExplorerTxUrl } from '@/services/stellar';
const explorerUrl = getExplorerTxUrl(transactionHash);
if (explorerUrl) {
await Linking.openURL(explorerUrl);
}import { getTransactionStatus } from '@/features/transactions';
const status = getTransactionStatus(transaction);
// Returns: 'successful' | 'pending' | 'failed'import { isSentTransaction } from '@/features/transactions';
const isSent = isSentTransaction(transaction, userPublicKey);
// Returns: true if user sent this transactionimport { validateTransactionData } from '@/features/transactions';
const { isValid, missingFields } = validateTransactionData(transaction);
// Returns validation result with missing field listSolution: Ensure transaction exists in wallet store and ID is correct
Solution: Check network configuration and hash availability
Solution: Verify expo-clipboard permissions and installation
Solution: Check date field format (should be ISO 8601)
- Always handle missing data - Use optional chaining and fallbacks
- Validate before display - Check data exists before rendering
- Provide user feedback - Show loading, error, and success states
- Use helper functions - Don't duplicate transaction logic
- Test edge cases - Missing fields, empty strings, null values
- 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