Skip to main content

Usage Examples

Complete TypeScript Class

class TradingAppIframe {
  private iframe: HTMLIFrameElement;
  private isReady: boolean = false;
  private messageQueue: IframeMessage[] = [];

  constructor(iframeId: string) {
    this.iframe = document.getElementById(iframeId) as HTMLIFrameElement;
    this.setupMessageListener();
  }

  private setupMessageListener(): void {
    window.addEventListener('message', (event: MessageEvent<IframeResponse>) => {
      if (event.source !== this.iframe.contentWindow) return;
      this.handleMessage(event.data);
    });
  }

  private handleMessage(data: IframeResponse): void {
    switch (data.type) {
      case 'IFRAME_READY':
        this.isReady = true;
        this.processMessageQueue();
        break;
      
      case 'WALLETS_ADDED':
        console.log(`Successfully added ${data.count} wallets`);
        break;
      
      case 'WALLETS_CLEARED':
        console.log('Cleared all iframe wallets');
        break;
      
      case 'CURRENT_WALLETS':
        console.log('Current wallets:', data.wallets);
        break;
      
      case 'WHITELIST_TRADING_STATS':
        console.log('Trading stats updated:', {
          bought: `${data.data.bought.toFixed(3)} SOL`,
          sold: `${data.data.sold.toFixed(3)} SOL`,
          net: `${data.data.net.toFixed(3)} SOL`,
          trades: data.data.trades,
          solPrice: `$${data.data.solPrice.toFixed(2)}`
        });
        break;
      
      case 'SOL_PRICE_UPDATE':
        console.log('SOL price updated:', `$${data.data.solPrice.toFixed(2)}`);
        break;
      
      case 'WHITELIST_TRADE':
        console.log('New whitelist trade:', {
          type: data.data.type,
          address: data.data.address,
          tokensAmount: data.data.tokensAmount,
          solAmount: `${data.data.solAmount.toFixed(3)} SOL`
        });
        break;
      
      case 'TOKEN_PRICE_UPDATE':
        console.log('Token price updated:', {
          tokenPrice: data.data.tokenPrice,
          tradeType: data.data.tradeType,
          volume: `${data.data.volume.toFixed(3)} SOL`
        });
        break;
    }
  }

  private sendMessage(message: IframeMessage): void {
    if (!this.isReady) {
      this.messageQueue.push(message);
      return;
    }
    this.iframe.contentWindow?.postMessage(message, '*');
  }

  private processMessageQueue(): void {
    while (this.messageQueue.length > 0) {
      const message = this.messageQueue.shift();
      if (message) this.sendMessage(message);
    }
  }

  // Public API methods
  addWallets(wallets: (string | Wallet)[]): void {
    this.sendMessage({ type: 'ADD_WALLETS', wallets });
  }

  clearWallets(): void {
    this.sendMessage({ type: 'CLEAR_WALLETS' });
  }

  getCurrentWallets(): void {
    this.sendMessage({ type: 'GET_WALLETS' });
  }
}

React Hook

import { useEffect, useRef, useState } from 'react';

interface TradingStats {
  bought: number;
  sold: number;
  net: number;
  trades: number;
  timestamp: number;
}

interface WhitelistTrade {
  type: 'buy' | 'sell';
  address: string;
  tokensAmount: number;
  avgPrice: number;
  solAmount: number;
  timestamp: number;
  signature: string;
}

interface TokenPriceData {
  tokenPrice: number;
  tokenMint: string;
  timestamp: number;
  tradeType: 'buy' | 'sell';
  volume: number;
}

export function useTradingIframe(iframeRef: React.RefObject<HTMLIFrameElement>) {
  const [isReady, setIsReady] = useState(false);
  const [currentWallets, setCurrentWallets] = useState<WhitelistItem[]>([]);
  const [tradingStats, setTradingStats] = useState<TradingStats | null>(null);
  const [solPrice, setSolPrice] = useState<number | null>(null);
  const [recentTrades, setRecentTrades] = useState<WhitelistTrade[]>([]);
  const [tokenPrice, setTokenPrice] = useState<TokenPriceData | null>(null);
  const messageQueue = useRef<IframeMessage[]>([]);

  useEffect(() => {
    const handleMessage = (event: MessageEvent<IframeResponse>) => {
      if (!iframeRef.current || event.source !== iframeRef.current.contentWindow) return;
      
      switch (event.data.type) {
        case 'IFRAME_READY':
          setIsReady(true);
          messageQueue.current.forEach(msg => sendMessage(msg));
          messageQueue.current = [];
          break;
        case 'CURRENT_WALLETS':
          setCurrentWallets(event.data.wallets);
          break;
        case 'WHITELIST_TRADING_STATS':
          setTradingStats(event.data.data);
          break;
        case 'SOL_PRICE_UPDATE':
          setSolPrice(event.data.data.solPrice);
          break;
        case 'WHITELIST_TRADE':
          setRecentTrades(prev => [event.data.data, ...prev].slice(0, 50));
          break;
        case 'TOKEN_PRICE_UPDATE':
          setTokenPrice(event.data.data);
          break;
      }
    };

    window.addEventListener('message', handleMessage);
    return () => window.removeEventListener('message', handleMessage);
  }, [iframeRef]);

  const sendMessage = (message: IframeMessage): void => {
    if (!isReady || !iframeRef.current) {
      messageQueue.current.push(message);
      return;
    }
    iframeRef.current.contentWindow?.postMessage(message, '*');
  };

  return {
    addWallets: (wallets: (string | Wallet)[]) => sendMessage({ type: 'ADD_WALLETS', wallets }),
    clearWallets: () => sendMessage({ type: 'CLEAR_WALLETS' }),
    getCurrentWallets: () => sendMessage({ type: 'GET_WALLETS' }),
    isReady,
    currentWallets,
    tradingStats,
    solPrice,
    recentTrades,
    tokenPrice
  };
}