feat: add new widgets for holder analysis, live token data, price, market overview, and trending tokens

- Implemented HolderAnalysisWidget to display holder distribution and concentration risk.
- Created LiveTokenDataWidget for real-time market data including price changes and transaction activity.
- Added LiveTokenPriceWidget to show current token price and changes over various timeframes.
- Developed MarketOverviewWidget to provide a summary of market statistics and token prices.
- Introduced TrendingTokensWidget to showcase trending tokens with price changes and volume.
- Added TradingSuggestionToolUI for AI-powered trading suggestions with detailed entry, targets, and stop-loss information.
- Enhanced settings components for better user configuration options in the SurfSense Browser Extension.
This commit is contained in:
API Test Bot 2026-02-04 13:11:39 +07:00
parent 2bf40ab5ce
commit 8bc092e40e
23 changed files with 2173 additions and 111 deletions

View file

@ -7,6 +7,122 @@ chrome.sidePanel
.setPanelBehavior({ openPanelOnActionClick: true })
.catch((error) => console.error("Failed to set side panel behavior:", error));
// ============================================
// Context Menu Setup (Epic 4.3)
// ============================================
// Create context menus on extension install
chrome.runtime.onInstalled.addListener(() => {
// Parent menu for SurfSense
chrome.contextMenus.create({
id: "surfsense-parent",
title: "🧠 SurfSense",
contexts: ["selection", "page", "link"],
});
// Analyze Token - for selected text (token address or symbol)
chrome.contextMenus.create({
id: "analyze-token",
parentId: "surfsense-parent",
title: "🔍 Analyze Token",
contexts: ["selection"],
});
// Check Safety - for selected text
chrome.contextMenus.create({
id: "check-safety",
parentId: "surfsense-parent",
title: "🛡️ Check Safety",
contexts: ["selection"],
});
// Add to Watchlist - for selected text
chrome.contextMenus.create({
id: "add-watchlist",
parentId: "surfsense-parent",
title: "⭐ Add to Watchlist",
contexts: ["selection"],
});
// Separator
chrome.contextMenus.create({
id: "separator-1",
parentId: "surfsense-parent",
type: "separator",
contexts: ["selection", "page", "link"],
});
// Copy Address - for selected text
chrome.contextMenus.create({
id: "copy-address",
parentId: "surfsense-parent",
title: "📋 Copy Address",
contexts: ["selection"],
});
// View on Explorer - for selected text
chrome.contextMenus.create({
id: "view-explorer",
parentId: "surfsense-parent",
title: "🔗 View on Explorer",
contexts: ["selection"],
});
// Separator
chrome.contextMenus.create({
id: "separator-2",
parentId: "surfsense-parent",
type: "separator",
contexts: ["selection", "page", "link"],
});
// Capture Page - for page context
chrome.contextMenus.create({
id: "capture-page",
parentId: "surfsense-parent",
title: "📸 Capture This Page",
contexts: ["page"],
});
// Ask AI about this page
chrome.contextMenus.create({
id: "ask-ai-page",
parentId: "surfsense-parent",
title: "💬 Ask AI About This Page",
contexts: ["page"],
});
});
// Handle context menu clicks
chrome.contextMenus.onClicked.addListener(async (info, tab) => {
const selectedText = info.selectionText?.trim() || "";
const storage = new Storage({ area: "local" });
// Store the action for sidepanel to pick up
const contextAction = {
action: info.menuItemId,
text: selectedText,
pageUrl: info.pageUrl,
linkUrl: info.linkUrl,
timestamp: Date.now(),
};
await storage.set("pendingContextAction", contextAction);
// Open sidepanel to handle the action
if (tab?.id) {
try {
await chrome.sidePanel.open({ tabId: tab.id });
} catch (error) {
console.error("Failed to open side panel:", error);
}
}
});
// ============================================
// Message Listeners
// ============================================
// Listen for messages from content scripts
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === "OPEN_SIDEPANEL") {
@ -16,6 +132,43 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
.catch((error) => console.error("Failed to open side panel:", error));
}
}
// Handle context action from sidepanel
if (message.type === "GET_CONTEXT_ACTION") {
const storage = new Storage({ area: "local" });
storage.get("pendingContextAction").then((action) => {
sendResponse(action);
// Clear the pending action
storage.remove("pendingContextAction");
});
return true; // Keep channel open for async response
}
});
// ============================================
// Keyboard Shortcuts (Epic 4.5)
// ============================================
chrome.commands.onCommand.addListener(async (command) => {
const storage = new Storage({ area: "local" });
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
if (!tab?.id) return;
// Store the keyboard command for sidepanel to pick up
const keyboardAction = {
action: command,
timestamp: Date.now(),
};
await storage.set("pendingKeyboardAction", keyboardAction);
// Open sidepanel for all commands
try {
await chrome.sidePanel.open({ tabId: tab.id });
} catch (error) {
console.error("Failed to open side panel:", error);
}
});
chrome.tabs.onCreated.addListener(async (tab: any) => {