diff --git a/surfsense_browser_extension/sidepanel/mock/mockData.ts b/surfsense_browser_extension/sidepanel/mock/mockData.ts index 6cf4735d2..30be13668 100644 --- a/surfsense_browser_extension/sidepanel/mock/mockData.ts +++ b/surfsense_browser_extension/sidepanel/mock/mockData.ts @@ -7,6 +7,7 @@ import type { TokenData } from "../context/PageContextProvider"; import type { WatchlistToken, WatchlistAlert } from "../crypto/WatchlistPanel"; import type { SafetyFactor } from "../crypto/SafetyScoreDisplay"; import type { AlertConfig } from "../crypto/AlertConfigModal"; +import type { WhaleTransaction } from "../whale/WhaleActivityFeed"; // ============================================ // MOCK TOKEN DATA (DexScreener) @@ -196,6 +197,111 @@ export const MOCK_WATCHLIST_ALERTS: WatchlistAlert[] = [ }, ]; +// ============================================ +// MOCK WHALE TRANSACTIONS +// ============================================ + +export const MOCK_WHALE_TRANSACTIONS: WhaleTransaction[] = [ + { + id: "whale-1", + tokenSymbol: "BULLA", + tokenName: "Bulla Token", + chain: "solana", + type: "buy", + amountUSD: 100000, + amountTokens: "8.1B", + walletAddress: "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", + txHash: "5Kn8WqXZKqYqKqYqKqYqKqYqKqYqKqYqKqYqKqYqKqYq", + timestamp: new Date(Date.now() - 1000 * 60 * 2), // 2 mins ago + isSmartMoney: true, + isInWatchlist: true, + }, + { + id: "whale-2", + tokenSymbol: "BONK", + tokenName: "Bonk", + chain: "solana", + type: "sell", + amountUSD: 50000, + amountTokens: "2.3B", + walletAddress: "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263", + txHash: "3Hn7WpXZKpYpKpYpKpYpKpYpKpYpKpYpKpYpKpYpKpYp", + timestamp: new Date(Date.now() - 1000 * 60 * 5), // 5 mins ago + isSmartMoney: false, + isInWatchlist: true, + }, + { + id: "whale-3", + tokenSymbol: "PEPE", + tokenName: "Pepe", + chain: "ethereum", + type: "buy", + amountUSD: 250000, + amountTokens: "23B", + walletAddress: "0x6982508145454Ce325dDbE47a25d4ec3d2311933", + txHash: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + timestamp: new Date(Date.now() - 1000 * 60 * 10), // 10 mins ago + isSmartMoney: true, + isInWatchlist: true, + }, + { + id: "whale-4", + tokenSymbol: "WIF", + tokenName: "dogwifhat", + chain: "solana", + type: "buy", + amountUSD: 75000, + amountTokens: "30.6K", + walletAddress: "EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm", + txHash: "4Jm6VoXYJoXoJoXoJoXoJoXoJoXoJoXoJoXoJoXoJoXo", + timestamp: new Date(Date.now() - 1000 * 60 * 15), // 15 mins ago + isSmartMoney: false, + isInWatchlist: true, + }, + { + id: "whale-5", + tokenSymbol: "DEGEN", + tokenName: "Degen", + chain: "base", + type: "sell", + amountUSD: 35000, + amountTokens: "2.2M", + walletAddress: "0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed", + txHash: "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", + timestamp: new Date(Date.now() - 1000 * 60 * 20), // 20 mins ago + isSmartMoney: false, + isInWatchlist: true, + }, + { + id: "whale-6", + tokenSymbol: "SOL", + tokenName: "Solana", + chain: "solana", + type: "buy", + amountUSD: 500000, + amountTokens: "5K", + walletAddress: "So11111111111111111111111111111111111111112", + txHash: "6Lp7XqYZLqZqLqZqLqZqLqZqLqZqLqZqLqZqLqZqLqZq", + timestamp: new Date(Date.now() - 1000 * 60 * 30), // 30 mins ago + isSmartMoney: true, + isInWatchlist: false, + }, + { + id: "whale-7", + tokenSymbol: "MATIC", + tokenName: "Polygon", + chain: "ethereum", + type: "buy", + amountUSD: 150000, + amountTokens: "200K", + walletAddress: "0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0", + txHash: "0xfedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321", + timestamp: new Date(Date.now() - 1000 * 60 * 45), // 45 mins ago + isSmartMoney: false, + isInWatchlist: false, + }, +]; + // ============================================ // MOCK ALERT CONFIGS // ============================================ diff --git a/surfsense_browser_extension/sidepanel/whale/WhaleActivityFeed.tsx b/surfsense_browser_extension/sidepanel/whale/WhaleActivityFeed.tsx new file mode 100644 index 000000000..bed325508 --- /dev/null +++ b/surfsense_browser_extension/sidepanel/whale/WhaleActivityFeed.tsx @@ -0,0 +1,267 @@ +import { useState } from "react"; +import { cn } from "~/lib/utils"; +import { + TrendingUp, + TrendingDown, + ExternalLink, + Filter, + Star, + Clock, + DollarSign, + Wallet, +} from "lucide-react"; +import { Button } from "@/routes/ui/button"; +import { ChainIcon } from "../components/shared/ChainIcon"; + +export interface WhaleTransaction { + /** Transaction ID */ + id: string; + /** Token symbol */ + tokenSymbol: string; + /** Token name */ + tokenName?: string; + /** Blockchain chain */ + chain: string; + /** Transaction type */ + type: "buy" | "sell"; + /** Amount in USD */ + amountUSD: number; + /** Amount in tokens */ + amountTokens: string; + /** Wallet address */ + walletAddress: string; + /** Transaction hash */ + txHash: string; + /** When the transaction occurred */ + timestamp: Date; + /** Whether this is a smart money wallet */ + isSmartMoney?: boolean; + /** Whether this token is in user's watchlist */ + isInWatchlist?: boolean; +} + +export interface WhaleActivityFeedProps { + /** List of whale transactions */ + transactions: WhaleTransaction[]; + /** Callback when transaction is clicked */ + onTransactionClick?: (tx: WhaleTransaction) => void; + /** Callback when "Track Wallet" is clicked */ + onTrackWallet?: (walletAddress: string) => void; + /** Callback when "View on Explorer" is clicked */ + onViewExplorer?: (txHash: string, chain: string) => void; + /** Additional class names */ + className?: string; +} + +/** + * WhaleActivityFeed - Display whale transactions (large buys/sells >$10K) + * + * Features: + * - Real-time feed of large transactions + * - Filter by watchlist tokens or all tokens + * - Smart money wallet indicators + * - Quick links to block explorer + * - Track wallet functionality + */ +export function WhaleActivityFeed({ + transactions, + onTransactionClick, + onTrackWallet, + onViewExplorer, + className, +}: WhaleActivityFeedProps) { + const [filter, setFilter] = useState<"all" | "watchlist" | "smart_money">("all"); + + // Filter transactions based on selected filter + const filteredTransactions = transactions.filter((tx) => { + if (filter === "watchlist") return tx.isInWatchlist; + if (filter === "smart_money") return tx.isSmartMoney; + return true; + }); + + const formatTimeAgo = (date: Date) => { + const seconds = Math.floor((new Date().getTime() - date.getTime()) / 1000); + if (seconds < 60) return `${seconds}s ago`; + const minutes = Math.floor(seconds / 60); + if (minutes < 60) return `${minutes}m ago`; + const hours = Math.floor(minutes / 60); + if (hours < 24) return `${hours}h ago`; + return `${Math.floor(hours / 24)}d ago`; + }; + + const formatAmount = (amount: number) => { + if (amount >= 1000000) return `$${(amount / 1000000).toFixed(2)}M`; + if (amount >= 1000) return `$${(amount / 1000).toFixed(1)}K`; + return `$${amount.toFixed(0)}`; + }; + + const shortenAddress = (address: string) => { + return `${address.slice(0, 6)}...${address.slice(-4)}`; + }; + + return ( +
+ {/* Header */} +
+
+
🐋
+
+

Whale Activity

+

+ {filteredTransactions.length} transactions +

+
+
+
+ + {/* Filter tabs */} +
+ + + +
+ + {/* Transaction feed */} +
+ {filteredTransactions.length === 0 ? ( +
+
🐋
+

+ No whale activity detected yet +

+

+ Large transactions (>$10K) will appear here +

+
+ ) : ( +
+ {filteredTransactions.map((tx) => ( +
onTransactionClick?.(tx)} + > + {/* Time and smart money badge */} +
+
+ + {formatTimeAgo(tx.timestamp)} +
+ {tx.isSmartMoney && ( +
+ ⚠️ Smart Money +
+ )} +
+ + {/* Transaction type and amount */} +
+ {tx.type === "buy" ? ( +
+ + BUY +
+ ) : ( +
+ + SELL +
+ )} + + {formatAmount(tx.amountUSD)} + + + {tx.tokenSymbol} + + +
+ + {/* Token amount */} +
+ Amount: {tx.amountTokens} tokens +
+ + {/* Wallet address */} +
+ + + {shortenAddress(tx.walletAddress)} + + +
+ + {/* Action buttons */} +
+ + {!tx.isSmartMoney && ( + + )} +
+
+ ))} +
+ )} +
+ + {/* Footer info */} +
+
+ Monitoring transactions >$10K + Updates every 1 min +
+
+
+ ); +}