The Trade History view provides a comprehensive table of all your executed trades with powerful filtering and analysis tools.
Overview
Trade History is accessible from:
Home Analytics : Scrollable table below analytics cards
Wallet Lookup : After fetching trades from blockchain
Table Features
Columns Displayed
export interface Trade {
id : string ;
symbol : string ; // e.g., "SOL-PERP", "BTC-USDC"
quoteCurrency : string ; // "USDC"
side : 'buy' | 'sell' | 'long' | 'short' ;
orderType : OrderType ; // 'limit' | 'market' | 'stop_limit' | 'stop_market'
quantity : number ; // Position size
price : number ; // Execution price
notional : number ; // Total value (price × quantity)
pnl : number ; // Profit/Loss in USDC
fee : number ; // Total fees paid
feeCurrency : string ; // "USDC"
openedAt : Date ; // Trade entry time
closedAt : Date ; // Trade exit time
durationSeconds : number ; // How long the position was held
isWin : boolean ; // True if pnl > 0
txSignature : string ; // Solana transaction signature
// Fee breakdown
feeBreakdown ?: FeeComposition [];
isMaker ?: boolean ; // Maker vs. Taker order
// Leverage fields (for perpetuals)
leverage ?: number ; // 1x, 2x, 3x, 5x, 8x, 10x
liquidationPrice ?: number ; // Liquidation threshold
marginUsed ?: number ; // Collateral used
}
Visible columns:
Time (formatted timestamp)
Symbol (token pair)
Side (Buy/Sell/Long/Short with color coding)
Order Type (Limit, Market, Stop)
Price
Quantity
Notional Value
PnL (color-coded: green for profit, red for loss)
Fees
Duration
Leverage (perps only)
Transaction Signature (clickable link to Solscan)
Color Coding
src/components/features/DeriverseTradesTable.tsx
// PnL Color Coding
< td className = { `px-6 py-4 whitespace-nowrap text-sm font-semibold ${
trade . pnl >= 0 ? 'text-green-400' : 'text-red-400'
} ` } >
{ trade . pnl >= 0 ? '+' : '' } $ { trade . pnl . toFixed ( 2 ) }
</ td >
// Side Color Coding
< td className = "px-6 py-4 whitespace-nowrap" >
< span className = { `px-3 py-1.5 rounded-none text-xs font-semibold ${
trade . side === 'long' || trade . side === 'buy'
? 'bg-green-500/20 text-green-300 border border-green-500/30'
: 'bg-red-500/20 text-red-300 border border-red-500/30'
} ` } >
{ trade . side . toUpperCase () }
</ span >
</ td >
Date Filtering
Filter trades by time period using the top bar:
export type FilterType = 'All' | 'Yesterday' | 'Today' | 'This Week' | 'This Month' | 'This Year' ;
export function filterTradesByDate ( trades : Trade [], filter : FilterType ) : Trade [] {
const now = new Date ();
switch ( filter ) {
case 'Today' :
return trades . filter ( t => isToday ( t . closedAt ));
case 'Yesterday' :
return trades . filter ( t => isYesterday ( t . closedAt ));
case 'This Week' :
// Last 7 days (rolling)
const sevenDaysAgo = startOfDay ( subDays ( now , 7 ));
return trades . filter ( t => t . closedAt >= sevenDaysAgo );
case 'This Month' :
// Last 30 days (rolling)
const thirtyDaysAgo = startOfDay ( subDays ( now , 30 ));
return trades . filter ( t => t . closedAt >= thirtyDaysAgo );
case 'This Year' :
// Last 365 days (rolling)
const yearAgo = startOfDay ( subDays ( now , 365 ));
return trades . filter ( t => t . closedAt >= yearAgo );
case 'All' :
default :
return trades ;
}
}
Available filters:
Today : Trades executed today
Yesterday : Trades from previous day
This Week : Last 7 days (rolling window)
This Month : Last 30 days (rolling window)
This Year : Last 365 days (rolling window)
All : Complete trade history
Time filters use rolling windows, not calendar periods. “This Week” means the last 7 days from today.
Custom Date Range
src/components/features/Home.tsx
const handleApplyFilters = () => {
setAppliedDateRange ( draftDateRange );
setAppliedSelectedPairs ( draftSelectedPairs );
setActiveFilter ( undefined ); // No filter active when date range is applied
};
// Filter trades based on active filter
const filteredTrades = useMemo (() => {
let trades ;
if ( activeFilter && activeFilter !== 'All' ) {
// Use quick filter, ignore date range completely
trades = filterTradesByDate ( displayTrades , activeFilter );
} else {
// Use date range if applied, otherwise show all trades
trades = displayTrades ;
if ( appliedDateRange ?. from ) {
const from = startOfDay ( appliedDateRange . from );
trades = trades . filter (( t ) => t . closedAt >= from );
}
if ( appliedDateRange ?. to ) {
const to = endOfDay ( appliedDateRange . to );
trades = trades . filter (( t ) => t . closedAt <= to );
}
}
if ( appliedSelectedPairs . length > 0 ) {
trades = trades . filter (( t ) => appliedSelectedPairs . includes ( t . symbol ));
}
return trades ;
}, [ activeFilter , appliedDateRange , appliedSelectedPairs , displayTrades ]);
Use the calendar picker to select a custom start and end date. Click Apply to filter.
Custom date ranges override quick filters. To return to quick filters, clear the date range.
Trading Pair Selection
Filter by specific tokens:
src/components/features/Home.tsx
const availablePairs = useMemo (() => {
const symbols = new Set < string >();
for ( const t of displayTrades ) symbols . add ( t . symbol );
return Array . from ( symbols ). sort (( a , b ) => a . localeCompare ( b ));
}, [ displayTrades ]);
< TopBar
activeFilter = { activeFilter }
onFilterChange = { handleFilterChange }
dateRange = { draftDateRange }
onDateRangeChange = { setDraftDateRange }
availablePairs = { availablePairs }
selectedPairs = { draftSelectedPairs }
onSelectedPairsChange = { setDraftSelectedPairs }
onApply = { handleApplyFilters }
/>
How it works:
Deriverse scans all trades and extracts unique symbols
Symbols are sorted alphabetically
Select multiple pairs to compare performance
Click Apply to filter the table
Available pairs (based on src/lib/mockData.ts:17):
SOL-USDC / SOL-PERP
BTC-USDC / BTC-PERP
ETH-USDC / ETH-PERP
JUP-USDC / JUP-PERP
JTO-USDC / JTO-PERP
BONK-USDC / BONK-PERP
WIF-USDC / WIF-PERP
RNDR-USDC / RNDR-PERP
Search Functionality
Quickly find specific trades by:
Transaction signature
Symbol/pair name
Date/time
Search is currently in development. For now, use the browser’s built-in find (Ctrl+F / Cmd+F) to search within the visible table.
Export Capabilities
Export filtered trade data to CSV:
function exportTradesToCSV ( trades : Trade []) {
const headers = [
'Date' ,
'Symbol' ,
'Side' ,
'Order Type' ,
'Quantity' ,
'Price' ,
'Notional' ,
'PnL' ,
'Fees' ,
'Duration (sec)' ,
'Leverage' ,
'Tx Signature'
];
const rows = trades . map ( t => [
format ( t . closedAt , 'yyyy-MM-dd HH:mm:ss' ),
t . symbol ,
t . side ,
t . orderType ,
t . quantity ,
t . price ,
t . notional ,
t . pnl ,
t . fee ,
t . durationSeconds ,
t . leverage || 'N/A' ,
t . txSignature
]);
const csv = [ headers , ... rows ]
. map ( row => row . join ( ',' ))
. join ( ' \n ' );
const blob = new Blob ([ csv ], { type: 'text/csv' });
const url = URL . createObjectURL ( blob );
const a = document . createElement ( 'a' );
a . href = url ;
a . download = `deriverse-trades- ${ format ( new Date (), 'yyyy-MM-dd' ) } .csv` ;
a . click ();
}
Export includes:
All visible columns
Respects active filters (date, pairs, etc.)
Formatted timestamps
Transaction signatures for verification
Export trades after filtering to create focused datasets for external analysis in Excel or Google Sheets.
Transaction Verification
Every trade includes a clickable transaction signature:
< a
href = { `https://solscan.io/tx/ ${ trade . txSignature } ?cluster=devnet` }
target = "_blank"
rel = "noopener noreferrer"
className = "text-blue-400 hover:text-blue-300 transition-colors font-mono group-hover:underline"
>
{ trade . txSignature . slice ( 0 , 8 ) } ... { trade . txSignature . slice ( - 8 ) }
</ a >
Click the signature to:
View on-chain transaction details on Solscan
Verify trade execution
Inspect instruction logs
Confirm fees and token transfers
All trades are verifiable on the Solana blockchain. Deriverse never invents or modifies trade data.
Trade Card View (Mobile)
On smaller screens, trades display as cards instead of a table:
src/components/features/TradeCard.tsx
< div className = "glass-morphism border border-white/10 overflow-hidden hover:border-white/20 transition-all" >
< div className = "p-4 space-y-3" >
< div className = "flex items-center justify-between" >
< div className = "flex items-center gap-2" >
< span className = "text-white font-mono text-sm" > { trade . symbol } </ span >
< span className = { `px-2 py-0.5 text-[10px] font-bold ${
trade . side === 'long' || trade . side === 'buy'
? 'bg-green-500/20 text-green-400'
: 'bg-red-500/20 text-red-400'
} ` } >
{ trade . side . toUpperCase () }
</ span >
</ div >
< span className = "text-white/40 text-xs" >
{ format ( trade . closedAt , 'MMM dd, HH:mm' ) }
</ span >
</ div >
< div className = "flex justify-between items-baseline" >
< span className = "text-white/60 text-xs" > PnL </ span >
< span className = { `text-lg font-bold ${
trade . pnl >= 0 ? 'text-green-400' : 'text-red-400'
} ` } >
{ trade . pnl >= 0 ? '+' : '' } $ { trade . pnl . toFixed ( 2 ) }
</ span >
</ div >
</ div >
</ div >
Trade cards are optimized for touch interfaces and display the most important info at a glance.
For large trade histories, Deriverse uses:
const ITEMS_PER_PAGE = 50 ;
const startIndex = ( currentPage - 1 ) * ITEMS_PER_PAGE ;
const endIndex = startIndex + ITEMS_PER_PAGE ;
const paginatedTrades = filteredTrades . slice ( startIndex , endIndex );
Virtualization (planned)
For 1000+ trades, virtual scrolling will render only visible rows.
Memoization
const filteredTrades = useMemo (() => {
let trades = displayTrades ;
if ( activeFilter ) {
trades = filterTradesByDate ( trades , activeFilter );
}
if ( appliedSelectedPairs . length > 0 ) {
trades = trades . filter ( t => appliedSelectedPairs . includes ( t . symbol ));
}
return trades ;
}, [ activeFilter , appliedSelectedPairs , displayTrades ]);
Expensive filtering operations are cached and only recalculate when dependencies change.
Next Steps
Analytics Dashboard See aggregated metrics from your trade history
Data Modes Learn about mock data vs. real blockchain data