Package Exports
- funhi-chart
- funhi-chart/package.json
Readme
FunhiChart 📊
A professional trading chart component for React applications. Display beautiful, interactive candlestick charts with real-time updates, multiple timeframes, and live market data.
Built with TradingView's Lightweight Charts library and optimized for crypto trading platforms.
🎯 What is FunhiChart?
FunhiChart is a React component that you can drop into any React application to display professional candlestick charts. It works everywhere:
- ✅ Create React App
- ✅ Next.js (App Router & Pages Router)
- ✅ Vite
- ✅ Remix
- ✅ Any React framework
Two Ways to Use:
- Standalone - Just pass a token address, and it displays a chart (perfect for demos or testing)
- Connected - Pass your own WebSocket connection and data for full real-time updates (production use)
⚡ Quick Start (30 seconds)
1. Install
npm install funhi-chart react react-dom lightweight-charts socket.io-client axios2. Use in Your App
import { FunhiChart } from 'funhi-chart';
function App() {
return (
<FunhiChart
mint="YourTokenMintAddress"
ticker="SOL"
tokenName="Solana"
/>
);
}That's it! 🎉 You now have a working chart.
📚 Complete Examples
Example 1: Basic Usage (Any React App)
Works in Create React App, Vite, or any React setup:
import React from 'react';
import { FunhiChart } from 'funhi-chart';
function TradingPage() {
return (
<div style={{ width: '100%', height: '600px' }}>
<FunhiChart
mint="SolTokenMintAddress"
ticker="SOL"
tokenName="Solana"
/>
</div>
);
}
export default TradingPage;Example 2: With Your Own WebSocket (Recommended)
Connect to your backend for real-time updates:
import React, { useState, useEffect } from 'react';
import { FunhiChart } from 'funhi-chart';
import { io } from 'socket.io-client';
function LiveChart() {
const [socket, setSocket] = useState(null);
const [connected, setConnected] = useState(false);
const [marketCap, setMarketCap] = useState(0);
useEffect(() => {
// Connect to your backend
const newSocket = io('https://your-backend.com');
newSocket.on('connect', () => setConnected(true));
newSocket.on('marketCap', (data) => setMarketCap(data.value));
setSocket(newSocket);
return () => newSocket.close();
}, []);
return (
<FunhiChart
mint="TokenAddress"
ticker="TOKEN"
tokenName="My Token"
// Connect to your WebSocket
socket={socket}
isConnected={connected}
currentMarketCap={marketCap}
/>
);
}Example 3: Next.js (App Router)
For Next.js, use dynamic import to avoid SSR issues:
'use client';
import dynamic from 'next/dynamic';
const FunhiChart = dynamic(
() => import('funhi-chart').then(mod => mod.FunhiChart),
{ ssr: false }
);
export default function ChartPage() {
return <FunhiChart mint="TokenAddress" ticker="SOL" />;
}Example 4: TypeScript
Full type safety with TypeScript:
import React from 'react';
import { FunhiChart, ChartProps } from 'funhi-chart';
import { Socket } from 'socket.io-client';
interface MyChartProps {
tokenAddress: string;
symbol: string;
socket?: Socket;
}
const MyChart: React.FC<MyChartProps> = ({ tokenAddress, symbol, socket }) => {
return (
<FunhiChart
mint={tokenAddress}
ticker={symbol}
socket={socket}
/>
);
};🎨 Features
- 🚀 Real-time Updates - Connect your WebSocket for live price updates
- 📊 Multiple Timeframes - 1m, 5m, 15m, 1h, 4h, 1d candlestick charts
- 🎨 Beautiful UI - Professional TradingView-style interface
- ⚡ High Performance - Handles thousands of data points smoothly
- 📱 Responsive - Works on mobile, tablet, and desktop
- 🎯 TypeScript - Full type definitions included
- 🔌 Flexible - Use standalone or with your own data
- 💾 Data Persistence - Automatic candle data caching
📖 API Reference
Props
All available props for the FunhiChart component:
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
mint |
string |
✅ Yes | - | Token mint address (Solana address) |
ticker |
string |
No | "" |
Token symbol (e.g., "SOL", "BTC") |
tokenName |
string |
No | "" |
Full token name (e.g., "Solana") |
socket |
Socket |
No | null |
Your Socket.IO connection for live updates |
isConnected |
boolean |
No | false |
WebSocket connection status |
currentMarketCap |
number |
No | 0 |
Live market cap to display |
analyticsConnected |
boolean |
No | false |
Analytics connection status |
analyticsLoading |
boolean |
No | false |
Loading state for analytics |
TypeScript Types
import { Socket } from 'socket.io-client';
interface ChartProps {
// Required
mint: string;
// Optional - Display
ticker?: string;
tokenName?: string;
// Optional - Real-time Data
socket?: Socket | null;
isConnected?: boolean;
currentMarketCap?: number;
analyticsConnected?: boolean;
analyticsLoading?: boolean;
}Exports
// Main component
import { FunhiChart } from 'funhi-chart';
// TypeScript types
import type { ChartProps } from 'funhi-chart';
// Utility services (if needed)
import { candleStorageService, candleAggregation } from 'funhi-chart';🚀 Framework-Specific Guides
Create React App / Vite
Standard import works perfectly:
import { FunhiChart } from 'funhi-chart';
function App() {
return <FunhiChart mint="address" ticker="SOL" />;
}Next.js (Important!)
Next.js requires dynamic import with ssr: false because the chart uses browser APIs:
'use client';
import dynamic from 'next/dynamic';
const FunhiChart = dynamic(
() => import('funhi-chart').then(mod => mod.FunhiChart),
{ ssr: false, loading: () => <div>Loading...</div> }
);
export default function Page() {
return <FunhiChart mint="address" ticker="SOL" />;
}Remix
Use client-side only rendering:
import { ClientOnly } from 'remix-utils';
import { FunhiChart } from 'funhi-chart';
export default function Route() {
return (
<ClientOnly>
{() => <FunhiChart mint="address" ticker="SOL" />}
</ClientOnly>
);
}Gatsby
Use loadable-components or dynamic import in useEffect:
import React, { useEffect, useState } from 'react';
function ChartPage() {
const [Chart, setChart] = useState(null);
useEffect(() => {
import('funhi-chart').then(mod => setChart(() => mod.FunhiChart));
}, []);
if (!Chart) return <div>Loading...</div>;
return <Chart mint="address" ticker="SOL" />;
}💡 Common Use Cases
1. Quick Demo or Prototype
Just need a chart fast? One line does it:
<FunhiChart mint="SolanaTokenAddress" ticker="SOL" />2. Static Portfolio Tracker
Display charts for multiple tokens without live updates:
{tokens.map(token => (
<FunhiChart
key={token.mint}
mint={token.mint}
ticker={token.symbol}
tokenName={token.name}
/>
))}3. Live Trading Dashboard
Connect to your backend for real-time candle updates:
const { socket, connected } = useYourSocket();
<FunhiChart
mint={selectedToken}
ticker="BTC"
socket={socket}
isConnected={connected}
/>4. Full Analytics Platform
Pass all data for complete monitoring:
<FunhiChart
mint={token.mint}
ticker={token.symbol}
tokenName={token.name}
socket={websocket}
isConnected={socketStatus}
currentMarketCap={liveMarketCap}
analyticsConnected={analyticsStatus}
analyticsLoading={isLoading}
/>🔧 Advanced Features
Timeframe Switching
The chart includes built-in buttons to switch between timeframes:
- 1m - 1 minute candles
- 5m - 5 minute candles
- 15m - 15 minute candles
- 1h - 1 hour candles
- 4h - 4 hour candles
- 1d - 1 day candles
Users can click to switch anytime - the chart automatically aggregates data.
Data Persistence
Candle data is automatically saved to your backend database:
import { candleStorageService } from 'funhi-chart';
// Manually save candles (usually handled automatically)
await candleStorageService.saveCandles({
mint: 'your-token-mint',
candles: candleData,
timeFrame: 60 // 1 minute
});
// Retrieve candles
const candles = await candleStorageService.getCandles({
mint: 'your-token-mint',
timeFrame: 60,
limit: 1000
});Custom Aggregation
The chart includes utilities for aggregating 1-minute candles to larger timeframes:
import { candleAggregation, CandleData } from 'funhi-chart';
const oneMinuteCandles: CandleData[] = [...]; // Your 1m candle data
// Aggregate to 5-minute candles
const fiveMinuteCandles = candleAggregation.aggregateCandles(
oneMinuteCandles,
300 // 5 minutes in seconds
);
// Fill gaps in candle data
const filledCandles = candleAggregation.fillGaps(
fiveMinuteCandles,
300 // timeframe in seconds
);API Reference
Components
FunhiChart
Main chart component that displays real-time candlestick data.
<FunhiChart
mint="TokenMintAddress"
ticker="TOKEN"
tokenName="Token Name"
/>Hooks
useSocket
Hook for managing Socket.IO connections:
import { useSocket } from 'funhi-chart';
function MyComponent() {
const { socket, isConnected } = useSocket(socketInstance);
// Use socket connection
}useOptimizedTokenAnalytics
Hook for accessing token analytics data:
import { useOptimizedTokenAnalytics } from 'funhi-chart';
function MyComponent() {
const analytics = useOptimizedTokenAnalytics('token-mint', analyticsData);
console.log(analytics.currentPrice);
console.log(analytics.currentMarketCap);
}Services
candleStorageService
Service for managing candle data persistence:
import { candleStorageService } from 'funhi-chart';
// Save candles
await candleStorageService.saveCandles({
mint: 'token-mint',
candles: [...],
timeFrame: 60
});
// Get candles
const candles = await candleStorageService.getCandles({
mint: 'token-mint',
timeFrame: 60,
limit: 1000
});Utils
candleAggregation
Utility for aggregating candle data:
import { candleAggregation } from 'funhi-chart';
// Aggregate candles
const aggregated = candleAggregation.aggregateCandles(
oneMinuteCandles,
300 // target timeframe in seconds
);
// Fill gaps
const filled = candleAggregation.fillGaps(
candles,
300 // timeframe in seconds
);
// Get required candle count
const required = candleAggregation.getRequiredOneMinuteCandles(
3600, // 1 hour
1000 // target 1000 candles
);Backend Requirements
The chart component expects a backend API with the following endpoints:
Get Candles
GET /api/ohlcv/candles/:mint?timeFrame=60&limit=1000Response:
{
"success": true,
"data": {
"candles": [
{
"time": 1234567890,
"open": 100.5,
"high": 102.3,
"low": 99.8,
"close": 101.2,
"volume": 1500
}
]
}
}Save Candles
POST /api/ohlcv/candles/saveRequest body:
{
"mint": "token-mint-address",
"timeFrame": 60,
"candles": [...]
}WebSocket Events
The backend should support these Socket.IO events:
ohlcv:subscribe- Subscribe to OHLCV updatesohlcv:update- Receive candle updatesheartbeat- Receive periodic updateschartUpdate- Receive chart data updates
Styling
The chart uses Tailwind CSS classes. Make sure you have Tailwind CSS configured in your project, or provide custom CSS:
/* Custom styling example */
.chart-container {
width: 100%;
height: 600px;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}Examples
Example 1: Basic Integration
import React from 'react';
import { FunhiChart } from 'funhi-chart';
export default function TradingPage() {
return (
<div className="container mx-auto p-4">
<h1 className="text-2xl font-bold mb-4">Live Trading Chart</h1>
<FunhiChart
mint="YOUR_TOKEN_MINT_ADDRESS"
ticker="TOKEN"
tokenName="Your Token Name"
/>
</div>
);
}Example 2: With Custom Analytics
import React, { useState, useEffect } from 'react';
import { FunhiChart } from 'funhi-chart';
import axios from 'axios';
export default function AdvancedChart() {
const [analyticsData, setAnalyticsData] = useState(null);
useEffect(() => {
// Fetch analytics data from your API
async function fetchAnalytics() {
const response = await axios.get('/api/token/analytics');
setAnalyticsData(response.data);
}
fetchAnalytics();
}, []);
return (
<div className="w-full">
<FunhiChart
mint="YOUR_TOKEN_MINT_ADDRESS"
ticker="TOKEN"
tokenName="Your Token Name"
/>
{analyticsData && (
<div className="mt-4">
<h2>Token Analytics</h2>
{/* Display analytics data */}
</div>
)}
</div>
);
}Example 3: Multiple Charts
import React from 'react';
import { FunhiChart } from 'funhi-chart';
const tokens = [
{ mint: 'TOKEN1_MINT', ticker: 'TK1', name: 'Token 1' },
{ mint: 'TOKEN2_MINT', ticker: 'TK2', name: 'Token 2' },
{ mint: 'TOKEN3_MINT', ticker: 'TK3', name: 'Token 3' },
];
export default function MultiChart() {
return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 p-4">
{tokens.map(token => (
<div key={token.mint} className="border rounded-lg p-4">
<h3 className="text-lg font-bold mb-2">{token.name}</h3>
<FunhiChart
mint={token.mint}
ticker={token.ticker}
tokenName={token.name}
/>
</div>
))}
</div>
);
}TypeScript Support
This package is written in TypeScript and includes type definitions:
import { FunhiChart, CandleData, TimeFrame } from 'funhi-chart';
const candle: CandleData = {
time: 1234567890,
open: 100,
high: 102,
low: 99,
close: 101,
volume: 1000
};
const timeFrame: TimeFrame = {
label: '1m',
value: '1m',
seconds: 60
};Performance Optimization
Tips for Optimal Performance
- Limit Data: Use the
limitparameter when fetching candles:
const candles = await candleStorageService.getCandles({
mint: 'token-mint',
timeFrame: 60,
limit: 500 // Limit to last 500 candles
});Debounce Updates: The chart automatically debounces real-time updates to prevent excessive re-renders.
Use Memoization: When passing data to the chart, use React.memo() or useMemo():
const ChartComponent = React.memo(() => (
<FunhiChart mint={mint} ticker={ticker} tokenName={tokenName} />
));❓ Frequently Asked Questions
Can I use this without Next.js?
Yes! FunhiChart works with any React application:
- Create React App ✅
- Vite ✅
- Remix ✅
- Gatsby ✅
- Plain React ✅
Only Next.js requires special handling (dynamic import with ssr: false).
Do I need a backend?
For basic use, no. The chart can work standalone with just a mint address.
For real-time updates, yes. You need:
- A WebSocket server (Socket.IO)
- An API that provides candle data
Can I use my own WebSocket connection?
Yes! Pass your socket as a prop:
<FunhiChart mint="address" socket={yourSocket} isConnected={true} />This is the recommended approach for production apps.
Does it work with non-Solana tokens?
The mint prop is designed for Solana token addresses, but you can pass any unique identifier. The chart itself is blockchain-agnostic - it just displays candlestick data.
Can I customize the appearance?
The chart has a professional design out of the box. The component itself doesn't expose styling props currently, but you can wrap it in a container with custom dimensions:
<div style={{ width: '100%', height: '600px', background: '#000' }}>
<FunhiChart mint="address" />
</div>How do I show real-time market cap?
Pass the currentMarketCap prop:
<FunhiChart
mint="address"
currentMarketCap={123456789}
analyticsConnected={true}
/>What's the difference between standalone and connected mode?
| Feature | Standalone | Connected |
|---|---|---|
| Setup | Just pass mint |
Pass socket and data props |
| Real-time updates | ❌ No | ✅ Yes |
| Live market cap | ❌ No | ✅ Yes |
| Connection badge | Shows "Disconnected" | Shows "Connected" |
| Best for | Demos, testing | Production apps |
Can I display multiple charts on one page?
Yes! Just render multiple components:
<FunhiChart mint="token1" ticker="SOL" />
<FunhiChart mint="token2" ticker="BTC" />
<FunhiChart mint="token3" ticker="ETH" />Each chart is independent.
Is TypeScript required?
No. The package works with JavaScript. TypeScript types are included as a bonus if you use TypeScript.
What license is this?
MIT License - free to use in commercial projects!
🐛 Troubleshooting
Chart shows "Disconnected" badge
This means no WebSocket is connected. Either:
- You're using standalone mode (expected behavior)
- Pass
socketandisConnectedprops for real-time mode
Next.js: "window is not defined" error
You forgot to use dynamic import! See the Next.js section.
Chart not displaying data
- Verify the
mintaddress is correct - Check browser console for API errors
- Ensure your backend API is running
- Check the API URL is configured correctly
Performance issues with multiple charts
Use virtualization or lazy loading:
import { lazy, Suspense } from 'react';
const FunhiChart = lazy(() => import('funhi-chart').then(m => ({ default: m.FunhiChart })));
<Suspense fallback={<Loading />}>
<FunhiChart mint="address" />
</Suspense>Contributing
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT © Funhi Team
Support
- Issues: GitHub Issues
- Email: support@funhi.com
- Documentation: Full Documentation
📝 Changelog
Version 1.0.0 (Current)
New Features:
- ✨ Component renamed to
FunhiChart(with backward compatibility) - 🔌 External socket prop support for seamless integration
- 📊 Live analytics props (market cap, connection status)
- 🎯 Works with any React framework
- ⚡ Production-ready with real-time updates
- 📱 Fully responsive design
- 🎨 Multiple timeframes (1m, 5m, 15m, 1h, 4h, 1d)
- 💾 Automatic data persistence
- 🎯 Full TypeScript support
Breaking Changes:
- None! Fully backward compatible with
FunhiChart
🙏 Credits
Built with:
- Lightweight Charts by TradingView
- Socket.IO for real-time communication
- React for UI
- Love ❤️ by the Funhi Team