{"id":28475332,"url":"https://github.com/razedotbot/solana-ui","last_synced_at":"2026-04-13T03:03:23.478Z","repository":{"id":287923949,"uuid":"965842540","full_name":"razedotbot/solana-ui","owner":"razedotbot","description":"Solana Multi Wallet Trading Platform - Pump.fun • Raydium • Launchpad • Letsbonk","archived":false,"fork":false,"pushed_at":"2025-07-24T21:58:55.000Z","size":1239,"stargazers_count":29,"open_issues_count":0,"forks_count":20,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-24T22:07:04.980Z","etag":null,"topics":["blockchain","bonk","bonkbot","bundler","devtools","jupiter","launchlab","launchpad","letsbonk","memecoin","moonshot","pumpfun","pumpswap","raydium","solana","solana-volume-bot","solanabot","solanabundler"],"latest_commit_sha":null,"homepage":"https://sol.app.raze.bot/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/razedotbot.png","metadata":{"files":{"readme":"README-IFRAME-INTEGRATION.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":"AUDIT.md","citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-04-14T02:02:29.000Z","updated_at":"2025-07-24T21:58:59.000Z","dependencies_parsed_at":"2025-04-14T17:34:24.378Z","dependency_job_id":"09700c3b-bec6-499e-a0a4-c55794761604","html_url":"https://github.com/razedotbot/solana-ui","commit_stats":null,"previous_names":["furydotbot/solana-ui","furydotbot/raze.bot","razedotbot/solana-ui"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/razedotbot/solana-ui","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razedotbot%2Fsolana-ui","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razedotbot%2Fsolana-ui/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razedotbot%2Fsolana-ui/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razedotbot%2Fsolana-ui/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/razedotbot","download_url":"https://codeload.github.com/razedotbot/solana-ui/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razedotbot%2Fsolana-ui/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269683183,"owners_count":24458628,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-10T02:00:08.965Z","response_time":71,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blockchain","bonk","bonkbot","bundler","devtools","jupiter","launchlab","launchpad","letsbonk","memecoin","moonshot","pumpfun","pumpswap","raydium","solana","solana-volume-bot","solanabot","solanabundler"],"created_at":"2025-06-07T14:06:02.025Z","updated_at":"2026-04-11T00:04:10.217Z","avatar_url":"https://github.com/razedotbot.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Trading App Iframe Integration with TypeScript\n\nThis guide shows how to integrate the trading app as an iframe in your TypeScript application and control wallet whitelisting programmatically.\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Basic Setup](#basic-setup)\n- [TypeScript Types](#typescript-types)\n- [API Reference](#api-reference)\n- [Usage Examples](#usage-examples)\n- [Security Considerations](#security-considerations)\n- [Error Handling](#error-handling)\n\n## Installation\n\n1. Embed the trading app as an iframe in your application:\n\n```html\n\u003ciframe \n  id=\"trading-iframe\" \n  src=\"https://frame.fury.bot\" \n  frameborder=\"0\"\u003e\n\u003c/iframe\u003e\n```\n\n## Basic Setup\n\n```typescript\n// Get iframe reference\nconst iframe = document.getElementById('trading-iframe') as HTMLIFrameElement;\n\n// Listen for messages from iframe\nwindow.addEventListener('message', (event: MessageEvent\u003cIframeResponse\u003e) =\u003e {\n  if (event.source !== iframe.contentWindow) return;\n  \n  handleIframeMessage(event.data);\n});\n\n// Send message to iframe\nfunction sendMessage(message: IframeMessage): void {\n  iframe.contentWindow?.postMessage(message, '*');\n}\n```\n\n## TypeScript Types\n\n```typescript\n// Wallet types\ninterface Wallet {\n  address: string;\n  label?: string;\n}\n\ninterface WhitelistItem {\n  id: string;\n  address: string;\n  label?: string;\n  isActive: boolean;\n  addedAt: number;\n}\n\n// Message types sent TO iframe\ntype IframeMessage = \n  | AddWalletsMessage\n  | ClearWalletsMessage\n  | GetWalletsMessage;\n\ninterface AddWalletsMessage {\n  type: 'ADD_WALLETS';\n  wallets: (string | Wallet)[];\n}\n\ninterface ClearWalletsMessage {\n  type: 'CLEAR_WALLETS';\n}\n\ninterface GetWalletsMessage {\n  type: 'GET_WALLETS';\n}\n\n// Response types received FROM iframe\ntype IframeResponse = \n  | IframeReadyResponse\n  | WalletsAddedResponse\n  | WalletsClearedResponse\n  | CurrentWalletsResponse;\n\ninterface IframeReadyResponse {\n  type: 'IFRAME_READY';\n}\n\ninterface WalletsAddedResponse {\n  type: 'WALLETS_ADDED';\n  success: boolean;\n  count: number;\n}\n\ninterface WalletsClearedResponse {\n  type: 'WALLETS_CLEARED';\n  success: boolean;\n}\n\ninterface CurrentWalletsResponse {\n  type: 'CURRENT_WALLETS';\n  wallets: WhitelistItem[];\n}\n```\n\n## API Reference\n\n### Commands (Sent to Iframe)\n\n#### ADD_WALLETS\nAdds wallets to the whitelist.\n\n```typescript\ninterface AddWalletsMessage {\n  type: 'ADD_WALLETS';\n  wallets: (string | Wallet)[];\n}\n```\n\n**Wallet Formats:**\n- String: `\"ABCD\"` or `\"ABCD:Label\"`\n- Object: `{ address: \"ABCD\", label: \"Label\" }`\n\n#### CLEAR_WALLETS\nRemoves all iframe-added wallets from the whitelist.\n\n```typescript\ninterface ClearWalletsMessage {\n  type: 'CLEAR_WALLETS';\n}\n```\n\n#### GET_WALLETS\nRetrieves current whitelist.\n\n```typescript\ninterface GetWalletsMessage {\n  type: 'GET_WALLETS';\n}\n```\n\n### Responses (Received from Iframe)\n\n#### IFRAME_READY\nSent when iframe is loaded and ready for communication.\n\n#### WALLETS_ADDED\nConfirms wallets were added successfully.\n\n#### WALLETS_CLEARED\nConfirms iframe wallets were cleared.\n\n#### CURRENT_WALLETS\nReturns current whitelist data.\n\n#### WHITELIST_TRADING_STATS\nSent automatically whenever whitelist trading statistics update. Contains real-time trading data for whitelisted addresses.\n\n```typescript\ninterface WhitelistTradingStatsResponse {\n  type: 'WHITELIST_TRADING_STATS';\n  data: {\n    bought: number;    // Total SOL bought by whitelisted addresses\n    sold: number;      // Total SOL sold by whitelisted addresses\n    net: number;       // Net SOL (sold - bought)\n    trades: number;    // Total number of trades\n    solPrice: number;  // Current SOL price in USD\n    timestamp: number; // When the stats were calculated\n  };\n}\n```\n\n#### SOL_PRICE_UPDATE\nSent automatically whenever the SOL price updates. Provides real-time SOL price data.\n\n```typescript\ninterface SolPriceUpdateResponse {\n  type: 'SOL_PRICE_UPDATE';\n  data: {\n    solPrice: number;  // Current SOL price in USD\n    timestamp: number; // When the price was updated\n  };\n}\n```\n\n#### WHITELIST_TRADE\nSent automatically for each individual trade made by whitelisted addresses. Provides real-time individual trade data.\n\n```typescript\ninterface WhitelistTradeResponse {\n  type: 'WHITELIST_TRADE';\n  data: {\n    type: 'buy' | 'sell';     // Trade type\n    address: string;          // Trader's wallet address (signer)\n    tokensAmount: number;     // Amount of tokens traded\n    avgPrice: number;         // Average price per token\n    solAmount: number;        // SOL amount involved in trade\n    timestamp: number;        // When the trade occurred\n    signature: string;        // Transaction signature\n  };\n}\n```\n\n#### TOKEN_PRICE_UPDATE\nSent automatically for every trade (including non-whitelisted). Provides real-time token price updates from all trading activity.\n\n```typescript\ninterface TokenPriceUpdateResponse {\n  type: 'TOKEN_PRICE_UPDATE';\n  data: {\n    tokenPrice: number;       // Current token price from latest trade\n    tokenMint: string;        // Token mint address\n    timestamp: number;        // When the trade occurred\n    tradeType: 'buy' | 'sell'; // Type of trade that updated the price\n    volume: number;           // SOL volume of the trade\n  };\n}\n```\n\n## Usage Examples\n\n### 1. Complete TypeScript Class\n\n```typescript\nclass TradingAppIframe {\n  private iframe: HTMLIFrameElement;\n  private isReady: boolean = false;\n  private messageQueue: IframeMessage[] = [];\n\n  constructor(iframeId: string) {\n    this.iframe = document.getElementById(iframeId) as HTMLIFrameElement;\n    this.setupMessageListener();\n  }\n\n  private setupMessageListener(): void {\n    window.addEventListener('message', (event: MessageEvent\u003cIframeResponse\u003e) =\u003e {\n      if (event.source !== this.iframe.contentWindow) return;\n      \n      this.handleMessage(event.data);\n    });\n  }\n\n  private handleMessage(data: IframeResponse): void {\n    switch (data.type) {\n      case 'IFRAME_READY':\n        this.isReady = true;\n        this.processMessageQueue();\n        break;\n      \n      case 'WALLETS_ADDED':\n        console.log(`Successfully added ${data.count} wallets`);\n        break;\n      \n      case 'WALLETS_CLEARED':\n        console.log('Cleared all iframe wallets');\n        break;\n      \n      case 'CURRENT_WALLETS':\n        console.log('Current wallets:', data.wallets);\n        break;\n      \n      case 'WHITELIST_TRADING_STATS':\n        console.log('Trading stats updated:', {\n          bought: `${data.data.bought.toFixed(3)} SOL`,\n          sold: `${data.data.sold.toFixed(3)} SOL`,\n          net: `${data.data.net.toFixed(3)} SOL`,\n          trades: data.data.trades,\n          solPrice: `$${data.data.solPrice.toFixed(2)}`\n        });\n        // You can update your UI here with the new trading statistics\n        this.updateTradingStatsUI(data.data);\n        break;\n      \n      case 'SOL_PRICE_UPDATE':\n        console.log('SOL price updated:', `$${data.data.solPrice.toFixed(2)}`);\n        // You can update your UI here with the new SOL price\n        this.updateSolPriceUI(data.data.solPrice);\n        break;\n      \n      case 'WHITELIST_TRADE':\n        console.log('New whitelist trade:', {\n          type: data.data.type,\n          address: data.data.address,\n          tokensAmount: data.data.tokensAmount,\n          avgPrice: data.data.avgPrice,\n          solAmount: `${data.data.solAmount.toFixed(3)} SOL`\n        });\n        // You can update your UI here with the new trade data\n        this.updateTradeUI(data.data);\n        break;\n      \n      case 'TOKEN_PRICE_UPDATE':\n        console.log('Token price updated:', {\n          tokenPrice: data.data.tokenPrice,\n          tokenMint: data.data.tokenMint,\n          tradeType: data.data.tradeType,\n          volume: `${data.data.volume.toFixed(3)} SOL`\n        });\n        // You can update your UI here with the new token price\n        this.updateTokenPriceUI(data.data);\n        break;\n    }\n  }\n\n  private updateTradingStatsUI(stats: any): void {\n    // Example: Update DOM elements with trading statistics\n    // document.getElementById('bought-amount')?.textContent = `${stats.bought.toFixed(3)} SOL`;\n    // document.getElementById('sold-amount')?.textContent = `${stats.sold.toFixed(3)} SOL`;\n    // document.getElementById('net-amount')?.textContent = `${stats.net.toFixed(3)} SOL`;\n    // document.getElementById('trade-count')?.textContent = stats.trades.toString();\n  }\n\n  private updateSolPriceUI(solPrice: number): void {\n    // Example: Update DOM elements with SOL price\n    // document.getElementById('sol-price')?.textContent = `$${solPrice.toFixed(2)}`;\n  }\n\n  private updateTradeUI(trade: any): void {\n    // Example: Update DOM elements with new trade data\n    // const tradeElement = document.createElement('div');\n    // tradeElement.innerHTML = `${trade.type.toUpperCase()}: ${trade.tokensAmount} tokens at $${trade.avgPrice.toFixed(4)} by ${trade.address.slice(0, 8)}...`;\n    // document.getElementById('trades-list')?.appendChild(tradeElement);\n  }\n\n  private updateTokenPriceUI(priceData: any): void {\n    // Example: Update DOM elements with new token price\n    // document.getElementById('token-price')?.textContent = `$${priceData.tokenPrice.toFixed(6)}`;\n    // document.getElementById('last-trade-type')?.textContent = priceData.tradeType.toUpperCase();\n    // document.getElementById('trade-volume')?.textContent = `${priceData.volume.toFixed(3)} SOL`;\n  }\n\n  private sendMessage(message: IframeMessage): void {\n    if (!this.isReady) {\n      this.messageQueue.push(message);\n      return;\n    }\n\n    this.iframe.contentWindow?.postMessage(message, '*');\n  }\n\n  private processMessageQueue(): void {\n    while (this.messageQueue.length \u003e 0) {\n      const message = this.messageQueue.shift();\n      if (message) {\n        this.sendMessage(message);\n      }\n    }\n  }\n\n  // Public API methods\n  addWallets(wallets: (string | Wallet)[]): void {\n    this.sendMessage({\n      type: 'ADD_WALLETS',\n      wallets\n    });\n  }\n\n  clearWallets(): void {\n    this.sendMessage({\n      type: 'CLEAR_WALLETS'\n    });\n  }\n\n  getCurrentWallets(): void {\n    this.sendMessage({\n      type: 'GET_WALLETS'\n    });\n  }\n}\n```\n\n### 2. Usage with React Hook\n\n```typescript\nimport { useEffect, useRef, useState } from 'react';\n\ninterface TradingStats {\n  bought: number;\n  sold: number;\n  net: number;\n  trades: number;\n  timestamp: number;\n}\n\ninterface WhitelistTrade {\n  type: 'buy' | 'sell';\n  address: string;\n  tokensAmount: number;\n  avgPrice: number;\n  solAmount: number;\n  timestamp: number;\n  signature: string;\n}\n\ninterface TokenPriceData {\n  tokenPrice: number;\n  tokenMint: string;\n  timestamp: number;\n  tradeType: 'buy' | 'sell';\n  volume: number;\n}\n\ninterface UseTradingIframeReturn {\n  addWallets: (wallets: (string | Wallet)[]) =\u003e void;\n  clearWallets: () =\u003e void;\n  getCurrentWallets: () =\u003e void;\n  isReady: boolean;\n  currentWallets: WhitelistItem[];\n  tradingStats: TradingStats | null;\n  solPrice: number | null;\n  recentTrades: WhitelistTrade[];\n  tokenPrice: TokenPriceData | null;\n}\n\nexport function useTradingIframe(iframeRef: React.RefObject\u003cHTMLIFrameElement\u003e): UseTradingIframeReturn {\n  const [isReady, setIsReady] = useState(false);\n  const [currentWallets, setCurrentWallets] = useState\u003cWhitelistItem[]\u003e([]);\n  const [tradingStats, setTradingStats] = useState\u003cTradingStats | null\u003e(null);\n  const [solPrice, setSolPrice] = useState\u003cnumber | null\u003e(null);\n  const [recentTrades, setRecentTrades] = useState\u003cWhitelistTrade[]\u003e([]);\n  const [tokenPrice, setTokenPrice] = useState\u003cTokenPriceData | null\u003e(null);\n  const messageQueue = useRef\u003cIframeMessage[]\u003e([]);\n\n  useEffect(() =\u003e {\n    const handleMessage = (event: MessageEvent\u003cIframeResponse\u003e) =\u003e {\n      if (!iframeRef.current || event.source !== iframeRef.current.contentWindow) return;\n      \n      switch (event.data.type) {\n        case 'IFRAME_READY':\n          setIsReady(true);\n          // Process queued messages\n          messageQueue.current.forEach(message =\u003e {\n            sendMessage(message);\n          });\n          messageQueue.current = [];\n          break;\n        \n        case 'CURRENT_WALLETS':\n          setCurrentWallets(event.data.wallets);\n          break;\n        \n        case 'WHITELIST_TRADING_STATS':\n          setTradingStats(event.data.data);\n          break;\n        \n        case 'SOL_PRICE_UPDATE':\n          setSolPrice(event.data.data.solPrice);\n          break;\n        \n        case 'WHITELIST_TRADE':\n          setRecentTrades(prev =\u003e {\n            const newTrades = [event.data.data, ...prev];\n            // Keep only the last 50 trades to prevent memory issues\n            return newTrades.slice(0, 50);\n          });\n          break;\n        \n        case 'TOKEN_PRICE_UPDATE':\n          setTokenPrice(event.data.data);\n          break;\n      }\n    };\n\n    window.addEventListener('message', handleMessage);\n    return () =\u003e window.removeEventListener('message', handleMessage);\n  }, [iframeRef]);\n\n  const sendMessage = (message: IframeMessage): void =\u003e {\n    if (!isReady || !iframeRef.current) {\n      messageQueue.current.push(message);\n      return;\n    }\n\n    iframeRef.current.contentWindow?.postMessage(message, '*');\n  };\n\n  const addWallets = (wallets: (string | Wallet)[]): void =\u003e {\n    sendMessage({ type: 'ADD_WALLETS', wallets });\n  };\n\n  const clearWallets = (): void =\u003e {\n    sendMessage({ type: 'CLEAR_WALLETS' });\n  };\n\n  const getCurrentWallets = (): void =\u003e {\n    sendMessage({ type: 'GET_WALLETS' });\n  };\n\n  return {\n    addWallets,\n    clearWallets,\n    getCurrentWallets,\n    isReady,\n    currentWallets,\n    tradingStats,\n    solPrice,\n    recentTrades,\n    tokenPrice\n  };\n}\n```\n\n### 3. React Component Example\n\n```typescript\nimport React, { useRef } from 'react';\n\nconst TradingDashboard: React.FC = () =\u003e {\n  const iframeRef = useRef\u003cHTMLIFrameElement\u003e(null);\n  const { addWallets, clearWallets, getCurrentWallets, isReady, tradingStats, solPrice, recentTrades, tokenPrice } = useTradingIframe(iframeRef);\n\n  const handleAddExampleWallets = (): void =\u003e {\n    const wallets: Wallet[] = [\n      { address: 'ABCD', label: 'Whale Trader' },\n      { address: 'EFGH', label: 'Smart Money' },\n      { address: '1234' } // No label\n    ];\n    \n    addWallets(wallets);\n  };\n\n  const handleAddStringWallets = (): void =\u003e {\n    const wallets = [\n      'XYZ1:DeFi Protocol',\n      'XYZ2:Market Maker',\n      'XYZ3' // No label\n    ];\n    \n    addWallets(wallets);\n  };\n\n  return (\n    \u003cdiv\u003e\n      \u003cdiv style={{ marginBottom: '20px' }}\u003e\n        \u003ch3\u003eTrading App Controls\u003c/h3\u003e\n        \u003cp\u003eStatus: {isReady ? 'Ready' : 'Loading...'}\u003c/p\u003e\n        \n        \u003cbutton onClick={handleAddExampleWallets} disabled={!isReady}\u003e\n          Add Example Wallets (Objects)\n        \u003c/button\u003e\n        \n        \u003cbutton onClick={handleAddStringWallets} disabled={!isReady}\u003e\n          Add Example Wallets (Strings)\n        \u003c/button\u003e\n        \n        \u003cbutton onClick={getCurrentWallets} disabled={!isReady}\u003e\n          Get Current Wallets\n        \u003c/button\u003e\n        \n        \u003cbutton onClick={clearWallets} disabled={!isReady}\u003e\n          Clear Wallets\n        \u003c/button\u003e\n      \u003c/div\u003e\n      \n      {/* SOL Price Display */}\n      {solPrice \u0026\u0026 (\n        \u003cdiv style={{ marginBottom: '20px', padding: '15px', border: '1px solid #ddd', borderRadius: '5px' }}\u003e\n          \u003ch4\u003eReal-time SOL Price\u003c/h4\u003e\n          \u003cdiv style={{ fontSize: '24px', fontWeight: 'bold', color: '#22C55E' }}\u003e\n            ${solPrice.toFixed(2)}\n          \u003c/div\u003e\n        \u003c/div\u003e\n      )}\n      \n      {/* Trading Statistics Display */}\n      {tradingStats \u0026\u0026 (\n        \u003cdiv style={{ marginBottom: '20px', padding: '15px', border: '1px solid #ddd', borderRadius: '5px' }}\u003e\n          \u003ch4\u003eWhitelist Trading Statistics\u003c/h4\u003e\n          \u003cdiv style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '10px' }}\u003e\n            \u003cdiv\u003e\n              \u003cstrong\u003eBought:\u003c/strong\u003e\n              \u003cdiv style={{ color: '#22C55E' }}\u003e{tradingStats.bought.toFixed(3)} SOL\u003c/div\u003e\n            \u003c/div\u003e\n            \u003cdiv\u003e\n              \u003cstrong\u003eSold:\u003c/strong\u003e\n              \u003cdiv style={{ color: '#EF4444' }}\u003e{tradingStats.sold.toFixed(3)} SOL\u003c/div\u003e\n            \u003c/div\u003e\n            \u003cdiv\u003e\n              \u003cstrong\u003eNet:\u003c/strong\u003e\n              \u003cdiv style={{ color: tradingStats.net \u003e= 0 ? '#22C55E' : '#EF4444' }}\u003e\n                {tradingStats.net.toFixed(3)} SOL\n              \u003c/div\u003e\n            \u003c/div\u003e\n            \u003cdiv\u003e\n              \u003cstrong\u003eTrades:\u003c/strong\u003e\n              \u003cdiv\u003e{tradingStats.trades}\u003c/div\u003e\n            \u003c/div\u003e\n          \u003c/div\u003e\n          \u003cdiv style={{ marginTop: '10px', fontSize: '12px', color: '#666' }}\u003e\n            Last updated: {new Date(tradingStats.timestamp).toLocaleTimeString()}\n          \u003c/div\u003e\n        \u003c/div\u003e\n      )}\n      \n      {/* Recent Trades Display */}\n      {recentTrades.length \u003e 0 \u0026\u0026 (\n        \u003cdiv style={{ marginBottom: '20px', padding: '15px', border: '1px solid #ddd', borderRadius: '5px' }}\u003e\n          \u003ch4\u003eRecent Whitelist Trades\u003c/h4\u003e\n          \u003cdiv style={{ maxHeight: '300px', overflowY: 'auto' }}\u003e\n            {recentTrades.map((trade, index) =\u003e (\n              \u003cdiv key={`${trade.signature}-${index}`} style={{\n                padding: '10px',\n                marginBottom: '8px',\n                backgroundColor: trade.type === 'buy' ? '#f0f9ff' : '#fef2f2',\n                border: `1px solid ${trade.type === 'buy' ? '#3b82f6' : '#ef4444'}`,\n                borderRadius: '4px'\n              }}\u003e\n                \u003cdiv style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}\u003e\n                  \u003cdiv\u003e\n                    \u003cspan style={{\n                      fontWeight: 'bold',\n                      color: trade.type === 'buy' ? '#3b82f6' : '#ef4444',\n                      textTransform: 'uppercase'\n                    }}\u003e\n                      {trade.type}\n                    \u003c/span\u003e\n                    \u003cspan style={{ marginLeft: '10px', fontSize: '14px' }}\u003e\n                      {trade.tokensAmount.toLocaleString()} tokens @ ${trade.avgPrice.toFixed(4)}\n                    \u003c/span\u003e\n                  \u003c/div\u003e\n                  \u003cdiv style={{ fontSize: '12px', color: '#666' }}\u003e\n                    {new Date(trade.timestamp).toLocaleTimeString()}\n                  \u003c/div\u003e\n                \u003c/div\u003e\n                \u003cdiv style={{ fontSize: '12px', color: '#666', marginTop: '4px' }}\u003e\n                  Trader: {trade.address.slice(0, 8)}...{trade.address.slice(-4)} | \n                  SOL Amount: {trade.solAmount.toFixed(3)}\n                \u003c/div\u003e\n              \u003c/div\u003e\n            ))}\n          \u003c/div\u003e\n        \u003c/div\u003e\n      )}\n      \n      \u003ciframe\n        ref={iframeRef}\n        src=\"http://localhost:3001\"\n        width=\"100%\"\n        height=\"800px\"\n        style={{ border: '1px solid #ccc' }}\n      /\u003e\n    \u003c/div\u003e\n  );\n};\n\nexport default TradingDashboard;\n```\n\n### 4. Advanced Example with Error Handling\n\n```typescript\nclass TradingAppManager {\n  private iframe: HTMLIFrameElement;\n  private isReady: boolean = false;\n  private timeout: number = 10000; // 10 seconds\n\n  constructor(iframeId: string) {\n    this.iframe = document.getElementById(iframeId) as HTMLIFrameElement;\n    this.setupMessageListener();\n  }\n\n  async addWallets(wallets: (string | Wallet)[]): Promise\u003cboolean\u003e {\n    return new Promise((resolve, reject) =\u003e {\n      if (!this.isReady) {\n        reject(new Error('Iframe not ready'));\n        return;\n      }\n\n      const timeout = setTimeout(() =\u003e {\n        reject(new Error('Timeout waiting for response'));\n      }, this.timeout);\n\n      const handleResponse = (event: MessageEvent\u003cIframeResponse\u003e) =\u003e {\n        if (event.source !== this.iframe.contentWindow) return;\n        \n        if (event.data.type === 'WALLETS_ADDED') {\n          clearTimeout(timeout);\n          window.removeEventListener('message', handleResponse);\n          resolve(event.data.success);\n        }\n      };\n\n      window.addEventListener('message', handleResponse);\n      \n      this.iframe.contentWindow?.postMessage({\n        type: 'ADD_WALLETS',\n        wallets\n      }, '*');\n    });\n  }\n\n  async getCurrentWallets(): Promise\u003cWhitelistItem[]\u003e {\n    return new Promise((resolve, reject) =\u003e {\n      if (!this.isReady) {\n        reject(new Error('Iframe not ready'));\n        return;\n      }\n\n      const timeout = setTimeout(() =\u003e {\n        reject(new Error('Timeout waiting for response'));\n      }, this.timeout);\n\n      const handleResponse = (event: MessageEvent\u003cIframeResponse\u003e) =\u003e {\n        if (event.source !== this.iframe.contentWindow) return;\n        \n        if (event.data.type === 'CURRENT_WALLETS') {\n          clearTimeout(timeout);\n          window.removeEventListener('message', handleResponse);\n          resolve(event.data.wallets);\n        }\n      };\n\n      window.addEventListener('message', handleResponse);\n      \n      this.iframe.contentWindow?.postMessage({\n        type: 'GET_WALLETS'\n      }, '*');\n    });\n  }\n}\n```\n\n## Security Considerations\n\n### 1. Origin Validation\n\nIn production, validate the origin of messages:\n\n```typescript\nwindow.addEventListener('message', (event: MessageEvent\u003cIframeResponse\u003e) =\u003e {\n  // Validate origin\n  if (event.origin !== 'https://your-trading-app-domain.com') {\n    console.warn('Received message from untrusted origin:', event.origin);\n    return;\n  }\n  \n  // Process message\n  handleMessage(event.data);\n});\n```\n\n### 2. Content Security Policy\n\nAdd CSP headers to allow iframe embedding:\n\n```\nContent-Security-Policy: frame-ancestors 'self' https://trusted-domain.com;\n```\n\n### 3. Input Validation\n\nValidate wallet addresses before sending:\n\n```typescript\nfunction isValidSolanaAddress(address: string): boolean {\n  // Basic Solana address validation\n  return /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(address);\n}\n\nfunction validateWallets(wallets: (string | Wallet)[]): boolean {\n  return wallets.every(wallet =\u003e {\n    const address = typeof wallet === 'string' \n      ? wallet.split(':')[0] \n      : wallet.address;\n    \n    return address \u0026\u0026 address.length \u003e= 3; // Allow partial addresses\n  });\n}\n```\n\n## Error Handling\n\n```typescript\ninterface ErrorResponse {\n  type: 'ERROR';\n  message: string;\n  code?: string;\n}\n\n// Enhanced message handler with error handling\nfunction handleMessage(data: IframeResponse | ErrorResponse): void {\n  if (data.type === 'ERROR') {\n    console.error('Iframe error:', data.message);\n    return;\n  }\n  \n  // Handle normal responses\n  switch (data.type) {\n    case 'IFRAME_READY':\n      console.log('Iframe ready for communication');\n      break;\n    // ... other cases\n  }\n}\n```\n\n## Best Practices\n\n1. **Wait for Ready Signal**: Always wait for `IFRAME_READY` before sending commands\n2. **Queue Messages**: Queue messages if iframe isn't ready yet\n3. **Validate Input**: Validate wallet addresses before sending\n4. **Handle Timeouts**: Implement timeouts for async operations\n5. **Error Handling**: Always handle potential errors and edge cases\n6. **Type Safety**: Use TypeScript types for better development experience\n7. **Security**: Validate message origins in production\n\n## Troubleshooting\n\n### Common Issues\n\n1. **Messages not received**: Check if iframe is fully loaded\n2. **CORS errors**: Ensure proper CORS configuration\n3. **Type errors**: Verify message structure matches interfaces\n4. **Timeout errors**: Increase timeout or check network connectivity\n\n### Debug Mode\n\n```typescript\nconst DEBUG = true;\n\nfunction debugLog(message: string, data?: any): void {\n  if (DEBUG) {\n    console.log(`[TradingIframe] ${message}`, data);\n  }\n}\n```\n\nThis comprehensive guide should help you integrate the trading app iframe with full TypeScript support and proper error handling.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frazedotbot%2Fsolana-ui","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frazedotbot%2Fsolana-ui","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frazedotbot%2Fsolana-ui/lists"}