-
Notifications
You must be signed in to change notification settings - Fork 15
Description
Overview
Session-based transaction history that records every send and swap initiated by the user from vault import onward. No blockchain scanning - we log what the user does, not what happened externally.
Figma: Transaction History - Overview
Scope
- All sends (native + token) on all supported chains
- All swaps (1inch, KyberSwap, LiFi, THORChain, MayaChain) on all supported chains
- Per-vault history with tab filtering (Overview/Swaps/Send) + basic filters (chain, token, date range)
- Pending status tracking (poll on app open)
- Reuse dynamic complete screen for detail/status view
Out of scope (v1): Blockchain scanning, incoming transactions (receives), token approvals, cross-vault aggregate view, export, backend sync.
Core Concept
"Session" = lifecycle from vault import (or creation) to now. The app acts as a local ledger of user-initiated actions.
- Recorded: Every tx the user broadcasts through the app
- NOT recorded: Txs before vault import, incoming txs, txs from other devices
- Trade-off: Reinstalling/importing on new device starts fresh history (no server dependency)
Data Model
Common fields:
| Field | Type | Description |
|---|---|---|
id |
UUID | Local unique identifier |
vaultId |
String | Vault that initiated the tx |
type |
Enum | send or swap |
status |
Enum | broadcasted, pending, confirmed, failed |
chain |
String | Source chain |
timestamp |
ISO 8601 | When broadcast |
txHash |
String | On-chain transaction hash |
explorerUrl |
String | Block explorer link |
fiatValue |
String? | USD value at broadcast time |
Send-specific: fromAddress, toAddress, amount, token, tokenLogo, feeEstimate, memo
Swap-specific: fromToken, fromAmount, fromChain, fromTokenLogo, toToken, toAmount, toChain, toTokenLogo, provider, route
Status metadata: confirmedAt, failureReason, lastCheckedAt
Storage (iOS)
- Engine: SwiftData (preferred) or Core Data
- Location: App's persistent container (not caches directory - must survive cache clearing)
- Retention: Unlimited, no auto-pruning
- Migration: Standard lightweight migration for future schema changes
- Schema: Single entity for transaction records, partitioned by
vaultId
Recording Flow
- User confirms send/swap
- Transaction signed + broadcast
- Write tx record to local storage with
status = broadcasted - Dynamic complete screen shows (existing)
- Complete screen polls + updates status (existing)
- On status change (confirmed/failed): update local record
Integration point: Write immediately after successful broadcast, before showing the complete screen. Complete screen's status callback updates the history record.
Status Tracking
State machine: broadcasted -> pending -> confirmed / failed
During complete screen: Existing dynamic complete screen resolves status. On resolution, update history record.
After leaving complete screen (pending txs): Refresh on app open only.
- On
scenePhase == .active: query pending records, fire status checks - On history screen
onAppear: same - Pull-to-refresh: same
- Reuse existing chain status check providers from dynamic tx status feature
- Concurrent checks (one async task per pending tx, reasonable concurrency limit)
- No background polling. No push notifications. No polling when offline.
UI Implementation
History List Screen
- Scrollable list using SwiftUI lazy loading
- Tab bar:
Overview|Swaps|Sendas custom segmented control matching Figma (underline active indicator) - Transaction cards as custom views matching Figma card designs
- Date section headers ("Today [date]", "Yesterday [date]", etc.)
- Pull-to-refresh triggers pending tx status check
Card Views (follow Figma exactly)
In-Progress Card (swap):
- Elevated visual treatment (border/shadow)
- Green "Swap" badge pill, "In progress... [elapsed]" with progress bar
- Token icons, amounts, "min. payout" label, route pill
Resolved Card (send or swap):
- Type badge pill (blue Send, green Swap)
- Status: "Successful" (green) or "Error" (red)
- Token icon + fiat value + token amount
- Address pill "to [truncated address]"
Detail View
Tapping a card navigates to the existing dynamic complete screen, passing tx data:
confirmed/failed: Static resolved statebroadcasted/pending: Active state, resumes polling
Filtering
- Primary: Tab bar (Overview / Swaps / Send)
- Secondary: Chain, token, date range filters
Empty State
"No transactions yet. Your sends and swaps will appear here."
Key Considerations
- Offline: History readable offline. Status refresh only when network available.
- VoiceOver: Accessibility labels on all card elements
- Dynamic Type: Respect text sizing preferences
- Dark theme: Match Figma dark theme
- Performance: Lazy loading for 1000+ records
- Thread safety: SwiftData writes on correct context/thread
Deliverables
- Transaction history data model (SwiftData entity)
- Transaction recording service (write on broadcast, update on status change)
- History list screen (tabs, cards, date grouping, filters, pull-to-refresh)
- Detail view integration (navigate to dynamic complete screen with tx data)
- Pending status refresh on app foreground / history screen appear