Deriverse supports two data modes to help you explore the platform and analyze real trading activity. Understanding the difference is crucial for getting the most value from the analytics.
Overview
Deriverse operates in two distinct modes:
Mock Mode : Demo data for exploring features
Devnet Mode : Real blockchain data from your Solana wallet
Mock Mode
What is Mock Mode?
Mock mode generates realistic trading data using deterministic algorithms. This allows you to:
Explore Deriverse features without connecting a wallet
See what analytics look like with a full trading history
Test journaling and filtering capabilities
Understand the platform before committing to real data
How Mock Data is Generated
// Configuration
const TRADE_COUNT = 240 ;
const HISTORY_DAYS = 180 ;
const BASE_FEE_RATE = 0.0005 ; // 0.05%
const WIN_RATE = 0.60 ; // 60% win rate
const SEED = 123 ; // Fixed seed for deterministic generation
// Trading pairs with weighted distribution
const SYMBOLS = [
{ symbol: 'SOL-USDC' , weight: 25 , types: [ 'spot' , 'perp' ] },
{ symbol: 'BTC-USDC' , weight: 20 , types: [ 'spot' , 'perp' ] },
{ symbol: 'ETH-USDC' , weight: 15 , types: [ 'spot' , 'perp' ] },
{ symbol: 'JUP-USDC' , weight: 12 , types: [ 'spot' , 'perp' ] },
{ symbol: 'JTO-USDC' , weight: 10 , types: [ 'spot' , 'perp' ] },
{ symbol: 'BONK-USDC' , weight: 8 , types: [ 'spot' , 'perp' ] },
{ symbol: 'WIF-USDC' , weight: 6 , types: [ 'spot' , 'perp' ] },
{ symbol: 'RNDR-USDC' , weight: 4 , types: [ 'spot' , 'perp' ] },
];
// Leverage distribution for perpetuals (weighted)
const LEVERAGE_DISTRIBUTION = [
{ leverage: 1 , weight: 10 },
{ leverage: 2 , weight: 15 },
{ leverage: 3 , weight: 15 },
{ leverage: 5 , weight: 25 },
{ leverage: 8 , weight: 20 },
{ leverage: 10 , weight: 15 },
];
Mock Data Characteristics
Realistic Patterns:
240 trades over 180 days
60% win rate (slightly profitable trader)
Weighted token distribution (SOL most common)
Varied leverage usage (1x-10x for perps)
Realistic fee structure (maker/taker split)
Deterministic Generation:
class SeededRandom {
private seed : number ;
constructor ( seed : number ) {
this . seed = seed ;
}
next () : number {
this . seed = ( this . seed * 9301 + 49297 ) % 233280 ;
return this . seed / 233280 ;
}
nextInt ( min : number , max : number ) : number {
return Math . floor ( this . next () * ( max - min + 1 )) + min ;
}
}
The same seed (123) always generates identical trades. This ensures consistent behavior for demos and screenshots.
Mock Mode Limitations
Mock data is not real. Do not use it for:
Tax reporting
Performance verification
Portfolio tracking
External audits
Storage:
Journal annotations stored in browser localStorage
Cleared if you clear browser data
Not synced across devices
Data Freshness:
Fixed dataset, never updates
No real-time data
No actual blockchain transactions
When to Use Mock Mode
Use mock mode to:
Explore Deriverse features before connecting wallet
Test journaling workflows
Create screenshots or demos
Learn how filters and analytics work
Devnet Mode
What is Devnet Mode?
Devnet mode connects to the Solana Devnet blockchain and fetches your actual trading history from Deriverse DEX.
src/components/features/Home.tsx
useEffect (() => {
async function fetchRealTrades () {
if ( network === 'devnet' && analyzingWallet ) {
setLoading ( true );
setError ( null );
try {
const service = new SupabaseTradeService ();
const trades = await service . getTrades ( analyzingWallet );
setRealTrades ( trades );
setAnnotations ({});
if ( trades . length === 0 ) {
toast . info ( 'No trades found for this wallet on Devnet' );
}
} catch ( err ) {
console . error ( 'Failed to load trades:' , err );
setError ( 'Failed to load trades from database' );
toast . error ( 'Failed to load trades' );
} finally {
setLoading ( false );
}
}
}
fetchRealTrades ();
}, [ network , analyzingWallet ]);
How Devnet Fetching Works
Step 1: Connect Wallet
Connect any Solana wallet (Phantom, Solflare, Backpack) to provide your public address:
src/components/features/TradeHistory.tsx
const handleWalletConnect = async () => {
try {
openWalletModal ();
await connect ();
} catch ( err ) {
console . error ( '[Wallet] connect failed' , err );
}
};
Step 2: Fetch Transactions
Deriverse queries Helius RPC for all transactions from your wallet:
src/services/HeliusService.ts
export class HeliusService {
async fetchAllTransactions ( address : string ) : Promise <{ transactions : TransactionLog [] }> {
const response = await fetch (
`https://api.helius.xyz/v0/addresses/ ${ address } /transactions?api-key= ${ HELIUS_API_KEY } `
);
const data = await response . json ();
return {
transactions: data . map ( tx => ({
signature: tx . signature ,
time: tx . timestamp ,
type: this . parseType ( tx ),
status: tx . meta ?. err ? 'Failed' : 'Confirmed' ,
fee: tx . meta ?. fee || 0 ,
}))
};
}
}
Step 3: Parse Deriverse Trades
Filter transactions to find Deriverse DEX activity:
src/services/DeriverseTradeService.ts
export class DeriverseTradeService {
async fetchTradesForWallet ( connection : Connection , walletAddress : string ) : Promise < Trade []> {
const signatures = await connection . getSignaturesForAddress (
new PublicKey ( walletAddress ),
{ limit: 1000 }
);
const trades : Trade [] = [];
for ( const sig of signatures ) {
const tx = await connection . getParsedTransaction ( sig . signature );
// Parse instructions for Deriverse program ID
if ( this . isDeriverseTransaction ( tx )) {
const trade = this . parseTradeFromTransaction ( tx );
trades . push ( trade );
}
}
return trades . sort (( a , b ) => a . openedAt . getTime () - b . openedAt . getTime ());
}
}
Step 4: Save to Database
Parsed trades are saved to Supabase for fast future access:
src/services/SupabaseTradeService.ts
export class SupabaseTradeService {
async saveTrades ( walletAddress : string , trades : Trade []) {
const { data , error } = await supabase
. from ( 'trades' )
. upsert (
trades . map ( t => ({
wallet_address: walletAddress ,
trade_id: t . id ,
symbol: t . symbol ,
side: t . side ,
quantity: t . quantity ,
price: t . price ,
pnl: t . pnl ,
fee: t . fee ,
opened_at: t . openedAt . toISOString (),
closed_at: t . closedAt . toISOString (),
tx_signature: t . txSignature ,
leverage: t . leverage ,
is_win: t . isWin ,
})),
{ onConflict: 'tx_signature' }
);
return { saved: trades . length };
}
}
Caching & Sync Status
To save RPC credits and improve performance, Deriverse caches trades:
src/components/ui/SyncStatus.tsx
< SyncStatus
lastSyncedAt = { lastIngestionAt }
dataSource = { network === 'devnet' ? 'fresh' : 'mock' }
isLoading = { ingestionLoading }
error = { ingestionError }
context = "home"
hasWallet = { !! analyzingWallet }
/>
Cache Behavior:
First lookup: Fetches fresh data from blockchain
Subsequent lookups: Loads from Supabase cache
Force refresh: Click “Force Refresh” to bypass cache
Last synced time is displayed in the sync status badge. Green = recent, yellow = stale, red = error.
Devnet vs. Mainnet
Currently, Deriverse only supports Devnet :
interface HomeProps {
network ?: 'devnet' | 'mainnet' | 'mock' ;
analyzingWallet ?: string | null ;
onNavigateToLookup ?: () => void ;
}
export default function Home ({ network = 'mock' , analyzingWallet , onNavigateToLookup } : HomeProps = {}) {
// ...
}
Mainnet support is planned but not yet available. Devnet is for testing only—real funds should never be on Devnet.
When to Use Devnet Mode
Use devnet mode to:
Analyze your actual Deriverse trading activity
Test with real (but not valuable) transactions
Verify trade parsing accuracy
Save annotations to the cloud
Track progress across devices
Switching Between Modes
From Mock to Devnet
Click “Go to Wallet’s” in the Mock Data Banner
Navigate to Wallet Lookup
Connect your Solana wallet OR paste address manually
Click “Run Lookup”
Save trades to database
Click “View Analytics” to enter Devnet mode
src/components/ui/MockDataBanner.tsx
export const MockDataBanner = ({
onFetchTrades ,
message = "You are viewing sample data. To see your real trading analytics, fetch your trades from the blockchain."
} : MockDataBannerProps ) => {
return (
< div className = "mb- p-2 bg-white/5 rounded-none px-4 py-2 backdrop-blur-sm" >
< div className = "flex flex-col md:flex-row md:items-center md:justify-between gap-3" >
< div >
< h3 className = "text-sm font-semibold text-yellow-500 mb-1" >
Mock Data Mode Active
</ h3 >
< p className = "text-sm text-white/70" >
{ message }
</ p >
</ div >
{ onFetchTrades && (
< button
onClick = { onFetchTrades }
className = "px-4 py-2 bg-black/50 rounded-none border border-white/20 text-sm font-semibold text-white md:self-center md:ml-auto"
>
Go to Wallet's
</ button >
) }
</ div >
</ div >
);
};
From Devnet to Mock
Simply disconnect your wallet or navigate back to Home without a connected wallet. The platform automatically reverts to Mock mode.
Data Storage Comparison
Feature Mock Mode Devnet Mode Trade Data Generated locally Fetched from blockchain Storage Location Browser only Supabase cloud database Annotations localStorage Supabase (synced) Persistence Cleared with browser data Permanent (cloud) Sync Across Devices ❌ No ✅ Yes Data Source Deterministic seed Real transactions Transaction Verification ❌ Fake signatures ✅ Real Solscan links Performance Instant Requires RPC calls
Annotation Migration
When switching from Mock to Devnet for the first time, Deriverse offers to migrate your local annotations:
src/lib/annotationStorage.ts
export async function migrateToSupabase (
walletAddress : string ,
annotationService : SupabaseAnnotationService
) : Promise < number > {
const localAnnotations = loadAnnotations ();
let migratedCount = 0 ;
for ( const [ tradeId , annotation ] of Object . entries ( localAnnotations )) {
try {
await annotationService . saveAnnotation ({
tradeId ,
notes: annotation . note ,
tags: [],
lessonsLearned: '' ,
}, walletAddress );
migratedCount ++ ;
} catch ( err ) {
console . error ( `Failed to migrate annotation for ${ tradeId } :` , err );
}
}
return migratedCount ;
}
Migration happens automatically the first time you load Journal in Devnet mode. A success toast shows how many annotations were backed up.
Best Practices
Explore features and workflows without connecting a wallet. This helps you understand what Deriverse can do before fetching real data.
Devnet is free and safe. Test trade parsing, journaling, and analytics with small test trades before committing to mainnet (when available).
Force Refresh After New Trades
If you just executed trades on Devnet, click “Force Refresh” to bypass cache and fetch the latest data.
Even in Devnet mode, export your journal and trade history periodically for local backups.
Troubleshooting
No Trades Found
If Deriverse shows “No trades found” after fetching:
Confirm you’ve executed trades on Deriverse DEX (Devnet)
Check that you connected the correct wallet
Verify network is set to Devnet in your wallet
Try “Force Refresh” to re-fetch data
Cache Not Updating
If new trades don’t appear:
Check last sync time in the sync status badge
Click “Force Refresh” to bypass cache
Wait 10-15 seconds for blockchain indexing
Verify transactions on Solscan
Annotations Not Saving
If journal entries disappear:
Mock Mode: Check if you cleared browser data
Devnet Mode: Verify wallet is connected
Check browser console for error messages
Try disconnecting and reconnecting wallet
Next Steps
Analytics Dashboard Explore analytics with real or mock data
Trade Journaling Start building your 21-day journaling habit