i need the whole script here fixed the spacing is off can u plesae just give me back the same code without the spacing issues import asyncio
import logging
from typing import Dict, Optional, List, Any
import json
import websockets
from datetime import datetime
import torch
from solana_rust_bot import PyHeliusBot
from pathlib import Path
import base64

Path("logs").mkdir(exist_ok=True)

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('logs/data_bridge.log'),
        logging.StreamHandler()
    ]
)

class QuantumDataBridge:
    def __init__(self, bot: PyHeliusBot):
        self.bot = bot
        self.data_cache = {}
        self.subscribers = {}
        self.last_update = {}
        self.ws_url = "wss://marga-e56m84-fast-mainnet.helius-rpc.com/"
        
        # Read keypair from file
        with open("C:\\solana_rust_bot\\id.json", "rb") as f:
            self.keypair_bytes = f.read()
        
        self.UPDATE_INTERVALS = {
            'price': 0.2,
            'pools': 0.5,
            'metrics': 1.0,
            'positions': 0.5,
            'market': 1.0
        }
        
        if torch.cuda.is_available():
            self.setup_cuda()
            logging.info(f"CUDA enabled for data processing on {torch.cuda.get_device_name(0)}")

    def setup_cuda(self):
        self.device = torch.device("cuda:0")
        self.price_tensor = torch.zeros((1000,), device=self.device)
        self.volume_tensor = torch.zeros((1000,), device=self.device)
        torch.cuda.empty_cache()

    async def connect_websocket(self):
        async with websockets.connect(self.ws_url) as websocket:
            auth_message = {
                "jsonrpc": "2.0",
                "id": 1,
                "method": "authorize",
                "params": [list(self.keypair_bytes)]
            }
            await websocket.send(json.dumps(auth_message))
            auth_response = await websocket.recv()
            logging.info(f"Auth response: {auth_response}")
            
            subscribe_msg = {
                "jsonrpc": "2.0",
                "id": 2,
                "method": "programSubscribe",
                "params": [
                    "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8",
                    {"encoding": "base64", "commitment": "confirmed"}
                ]
            }
            await websocket.send(json.dumps(subscribe_msg))
            return websocket

    async def pool_update_loop(self):
        while True:
            try:
                websocket = await self.connect_websocket()
                
                while True:
                    msg = await websocket.recv()
                    data = json.loads(msg)
                    
                    if 'params' in data and 'result' in data['params']:
                        account_data = data['params']['result']['value']['account']['data'][0]
                        decoded = base64.b64decode(account_data)
                        
                        pool_metrics = {
                            'address': data['params']['result']['value']['pubkey'],
                            'metrics': {
                                'liquidity': float(int.from_bytes(decoded[64:72], 'little')),
                                'volume_24h': float(int.from_bytes(decoded[72:80], 'little')),
                                'price_impact': float(int.from_bytes(decoded[80:88], 'little')) / 1e6,
                                'score': 0  # We'll calculate this after getting the metrics
                            }
                        }
                        
                        pool_metrics['metrics']['score'] = self.calculate_pool_score(pool_metrics['metrics'])
                        
                        self.data_cache['pools'] = [pool_metrics]
                        await self.notify_subscribers('pools', [pool_metrics])
                        logging.info(f"Pool data processed: {pool_metrics['address']}")

            except websockets.exceptions.ConnectionClosed:
                logging.warning("WebSocket connection closed, reconnecting...")
                await asyncio.sleep(1)
            except Exception as e:
                logging.error(f"Pool update error: {str(e)}")
                await asyncio.sleep(1)
        def calculate_pool_score(self, metrics):
        try:
            liquidity = float(metrics['liquidity'])
            volume = float(metrics['volume_24h'])
            price_impact = float(metrics['price_impact'])
            
            score = (liquidity * 0.4 + volume * 0.4) * (1 - price_impact * 2)
            return min(max(score, 0), 100)
        except Exception:
            return 0

    async def price_update_loop(self):
        while True:
            try:
                price = await asyncio.to_thread(float, self.bot.get_pool_price())
                
                if torch.cuda.is_available():
                    with torch.no_grad():
                        self.price_tensor = torch.roll(self.price_tensor, -1)
                        self.price_tensor[-1] = price

                price_data = {
                    'price': price,
                    'timestamp': datetime.now().isoformat()
                }
                
                self.data_cache['price'] = price_data
                await self.notify_subscribers('price', price_data)
                await asyncio.sleep(self.UPDATE_INTERVALS['price'])
                
            except Exception as e:
                logging.error(f"Price update error: {e}")
                await asyncio.sleep(1)

    async def metrics_update_loop(self):
        while True:
            try:
                metrics = await asyncio.to_thread(self.bot.get_market_metrics)
                
                if torch.cuda.is_available():
                    with torch.no_grad():
                        self.volume_tensor = torch.roll(self.volume_tensor, -1)
                        self.volume_tensor[-1] = metrics.get('volume_24h', 0)

                metrics_data = {
                    'metrics': metrics,
                    'timestamp': datetime.now().isoformat()
                }
                
                self.data_cache['metrics'] = metrics_data
                await self.notify_subscribers('metrics', metrics_data)
                await asyncio.sleep(self.UPDATE_INTERVALS['metrics'])
                
            except Exception as e:
                logging.error(f"Metrics update error: {e}")
                await asyncio.sleep(1)

    async def position_update_loop(self):
        while True:
            try:
                positions = await asyncio.to_thread(self.bot.get_positions)
                if isinstance(positions, str):
                    positions = json.loads(positions)
                
                position_data = {
                    'positions': positions,
                    'timestamp': datetime.now().isoformat()
                }
                
                self.data_cache['positions'] = position_data
                await self.notify_subscribers('positions', position_data)
                await asyncio.sleep(self.UPDATE_INTERVALS['positions'])
                
            except Exception as e:
                logging.error(f"Position update error: {e}")
                await asyncio.sleep(1)

    async def market_update_loop(self):
        while True:
            try:
                market_data = {
                    'price': self.data_cache.get('price', {}).get('price', 0),
                    'metrics': self.data_cache.get('metrics', {}).get('metrics', {}),
                    'active_pools': len(self.data_cache.get('pools', [])),
                    'positions': len(self.data_cache.get('positions', {}).get('positions', [])),
                    'timestamp': datetime.now().isoformat()
                }

                if torch.cuda.is_available():
                    with torch.no_grad():
                        returns = torch.diff(self.price_tensor[-100:])
                        volatility = float(torch.std(returns).cpu())
                        volume_change = float(torch.mean(torch.diff(self.volume_tensor[-20:])).cpu())
                        
                        market_data.update({
                            'volatility': volatility,
                            'volume_trend': volume_change
                        })

                self.data_cache['market'] = market_data
                await self.notify_subscribers('market', market_data)
                await asyncio.sleep(self.UPDATE_INTERVALS['market'])
                
            except Exception as e:
                logging.error(f"Market update error: {e}")
                await asyncio.sleep(1)

    async def start(self):
        tasks = [
            self.price_update_loop(),
            self.pool_update_loop(),
            self.metrics_update_loop(),
            self.position_update_loop(),
            self.market_update_loop()
        ]
        await asyncio.gather(*tasks)

    def subscribe(self, data_type: str, callback: callable):
        if data_type not in self.subscribers:
            self.subscribers[data_type] = []
        self.subscribers[data_type].append(callback)

    async def notify_subscribers(self, data_type: str, data: Any):
        if data_type in self.subscribers:
            for callback in self.subscribers[data_type]:
                try:
                    await callback(data)
                except Exception as e:
                    logging.error(f"Error notifying subscriber for {data_type}: {e}")

    def get_cached_data(self, data_type: str) -> Optional[Dict]:
        return self.data_cache.get(data_type)

    def get_all_cached_data(self) -> Dict:
        return self.data_cache

    async def clear_cache(self):
        self.data_cache = {}
        if torch.cuda.is_available():
            torch.cuda.empty_cache()

    async def cleanup(self):
        try:
            await self.clear_cache()
            self.subscribers = {}
            logging.info("Data bridge cleanup completed")
        except Exception as e:
            logging.error(f"Cleanup error: {e}")

async def test_bridge():
    bot = PyHeliusBot()
    bridge = QuantumDataBridge(bot)
    
    async def price_callback(price_data):
        print(f"Price update: {price_data}")
    
    try:
        bridge.subscribe('price', price_callback)
        await bridge.start()
        
    except KeyboardInterrupt:
        print("Testing stopped")
        await bridge.cleanup()
    except Exception as e:
        print(f"Error: {e}")
        await bridge.cleanup()

if __name__ == "__main__":
    asyncio.run(test_bridge())