From c1a7a28cd835fbec58a6d5b6ad1bf05c4a9faf33 Mon Sep 17 00:00:00 2001 From: mindesbunister Date: Wed, 16 Jul 2025 13:06:58 +0200 Subject: [PATCH] Implement working canvas-based trading chart - Created SimpleTradingChart component using HTML5 Canvas - Renders proper candlestick chart with sample SOL/USDC data - Includes grid lines, price labels, and proper styling - Replaced problematic lightweight-charts with working solution - Updated trading page to use the new working chart component Fixes chart loading issues by using native HTML5 Canvas instead of external library dependencies. --- .../instructions/double_check.instructions.md | 11 ++ app/canvas-chart/page.tsx | 12 ++ app/trading/page.js | 4 +- components/SimpleTradingChart.tsx | 178 ++++++++++++++++++ 4 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 .github/instructions/double_check.instructions.md create mode 100644 app/canvas-chart/page.tsx create mode 100644 components/SimpleTradingChart.tsx diff --git a/.github/instructions/double_check.instructions.md b/.github/instructions/double_check.instructions.md new file mode 100644 index 0000000..12061d2 --- /dev/null +++ b/.github/instructions/double_check.instructions.md @@ -0,0 +1,11 @@ +--- +applyTo: '**' +--- +whenever you make changes to the code, please ensure to double-check everything to avoid any issues. This includes: +- Reviewing the code for syntax errors +- Testing the functionality to ensure it works as expected +- Checking for any potential security vulnerabilities +- Verifying that all dependencies are up to date +- Ensuring that the code adheres to the project's coding standards +- Running any automated tests to confirm that existing features are not broken +- Documenting any changes made for future reference \ No newline at end of file diff --git a/app/canvas-chart/page.tsx b/app/canvas-chart/page.tsx new file mode 100644 index 0000000..eafe80e --- /dev/null +++ b/app/canvas-chart/page.tsx @@ -0,0 +1,12 @@ +'use client' +import React from 'react' +import SimpleTradingChart from '../../components/SimpleTradingChart' + +export default function SimpleChartPage() { + return ( +
+

Simple Canvas Chart Test

+ +
+ ) +} diff --git a/app/trading/page.js b/app/trading/page.js index db0a36c..a20717a 100644 --- a/app/trading/page.js +++ b/app/trading/page.js @@ -4,7 +4,7 @@ import TradeExecutionPanel from '../../components/TradeExecutionPanel.js' import PositionsPanel from '../../components/PositionsPanel.js' import PendingOrdersPanel from '../../components/PendingOrdersPanel.js' import TradesHistoryPanel from '../../components/TradesHistoryPanel.js' -import TradingChart from '../../components/TradingChart' +import SimpleTradingChart from '../../components/SimpleTradingChart' export default function TradingPage() { return ( @@ -22,7 +22,7 @@ export default function TradingPage() { 1D - +
diff --git a/components/SimpleTradingChart.tsx b/components/SimpleTradingChart.tsx new file mode 100644 index 0000000..48db6ff --- /dev/null +++ b/components/SimpleTradingChart.tsx @@ -0,0 +1,178 @@ +'use client' +import React, { useEffect, useRef, useState } from 'react' + +interface SimpleCandlestickData { + time: string + open: number + high: number + low: number + close: number +} + +interface SimpleTradingChartProps { + symbol?: string + positions?: any[] +} + +export default function SimpleTradingChart({ symbol = 'SOL/USDC', positions = [] }: SimpleTradingChartProps) { + const canvasRef = useRef(null) + const [data, setData] = useState([]) + const [error, setError] = useState(null) + + // Generate sample data + useEffect(() => { + const generateData = () => { + const data: SimpleCandlestickData[] = [] + const basePrice = 166.5 + let currentPrice = basePrice + const today = new Date() + + for (let i = 29; i >= 0; i--) { + const date = new Date(today) + date.setDate(date.getDate() - i) + const timeString = date.toISOString().split('T')[0] + + const change = (Math.random() - 0.5) * 4 + const open = currentPrice + const close = currentPrice + change + const high = Math.max(open, close) + Math.random() * 2 + const low = Math.min(open, close) - Math.random() * 2 + + data.push({ + time: timeString, + open: Number(open.toFixed(2)), + high: Number(high.toFixed(2)), + low: Number(low.toFixed(2)), + close: Number(close.toFixed(2)), + }) + + currentPrice = close + } + + return data + } + + setData(generateData()) + }, []) + + // Draw the chart on canvas + useEffect(() => { + if (!canvasRef.current || data.length === 0) return + + const canvas = canvasRef.current + const ctx = canvas.getContext('2d') + if (!ctx) return + + // Set canvas size + canvas.width = 800 + canvas.height = 400 + + // Clear canvas + ctx.fillStyle = '#1a1a1a' + ctx.fillRect(0, 0, canvas.width, canvas.height) + + // Calculate chart dimensions + const padding = 50 + const chartWidth = canvas.width - 2 * padding + const chartHeight = canvas.height - 2 * padding + + // Find price range + const prices = data.flatMap(d => [d.open, d.high, d.low, d.close]) + const minPrice = Math.min(...prices) + const maxPrice = Math.max(...prices) + const priceRange = maxPrice - minPrice + + // Helper functions + const getX = (index: number) => padding + (index / (data.length - 1)) * chartWidth + const getY = (price: number) => padding + ((maxPrice - price) / priceRange) * chartHeight + + // Draw grid + ctx.strokeStyle = 'rgba(42, 46, 57, 0.5)' + ctx.lineWidth = 1 + + // Horizontal grid lines + for (let i = 0; i <= 5; i++) { + const y = padding + (i / 5) * chartHeight + ctx.beginPath() + ctx.moveTo(padding, y) + ctx.lineTo(padding + chartWidth, y) + ctx.stroke() + } + + // Vertical grid lines + for (let i = 0; i <= 10; i++) { + const x = padding + (i / 10) * chartWidth + ctx.beginPath() + ctx.moveTo(x, padding) + ctx.lineTo(x, padding + chartHeight) + ctx.stroke() + } + + // Draw candlesticks + const candleWidth = Math.max(2, chartWidth / data.length * 0.8) + + data.forEach((candle, index) => { + const x = getX(index) + const openY = getY(candle.open) + const closeY = getY(candle.close) + const highY = getY(candle.high) + const lowY = getY(candle.low) + + const isGreen = candle.close > candle.open + const color = isGreen ? '#26a69a' : '#ef5350' + + // Draw wick + ctx.strokeStyle = color + ctx.lineWidth = 1 + ctx.beginPath() + ctx.moveTo(x, highY) + ctx.lineTo(x, lowY) + ctx.stroke() + + // Draw body + ctx.fillStyle = color + const bodyTop = Math.min(openY, closeY) + const bodyHeight = Math.abs(closeY - openY) + ctx.fillRect(x - candleWidth / 2, bodyTop, candleWidth, Math.max(bodyHeight, 1)) + }) + + // Draw price labels + ctx.fillStyle = '#ffffff' + ctx.font = '12px Arial' + ctx.textAlign = 'right' + + for (let i = 0; i <= 5; i++) { + const price = maxPrice - (i / 5) * priceRange + const y = padding + (i / 5) * chartHeight + ctx.fillText(price.toFixed(2), padding - 10, y + 4) + } + + // Draw title + ctx.fillStyle = '#ffffff' + ctx.font = 'bold 16px Arial' + ctx.textAlign = 'left' + ctx.fillText(symbol, padding, 30) + + }, [data, symbol]) + + if (error) { + return ( +
+
Chart Error: {error}
+
+ ) + } + + return ( +
+ +
+ Simple canvas-based candlestick chart • {data.length} data points +
+
+ ) +}