From 24fc73d7cfe303fc5044f1d4e868f462c2e6250c Mon Sep 17 00:00:00 2001 From: djeck1432 Date: Thu, 26 Sep 2024 18:02:10 +0200 Subject: [PATCH] add new dashboard logic --- web_app/api/serializers/dashboard.py | 59 ++++++++++++++++++++++++++++ web_app/api/tools/__init__.py | 0 web_app/api/tools/redis_cache.py | 54 +++++++++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 web_app/api/serializers/dashboard.py create mode 100644 web_app/api/tools/__init__.py create mode 100644 web_app/api/tools/redis_cache.py diff --git a/web_app/api/serializers/dashboard.py b/web_app/api/serializers/dashboard.py new file mode 100644 index 00000000..82c9773c --- /dev/null +++ b/web_app/api/serializers/dashboard.py @@ -0,0 +1,59 @@ +from decimal import Decimal +from pydantic import BaseModel, Field, validator +from typing import Optional, Dict, List + +from web_app.contract_tools.constants import TokenParams + + +class PositionData(BaseModel): + apy: str + group: Optional[int] + lending: bool + collateral: bool + debt: bool + + +class Position(BaseModel): + token_address: Optional[str] = Field(None, alias="tokenAddress") # Made optional + total_balances: Dict[str, str] = Field(alias="totalBalances") + data: PositionData + + @validator('total_balances', pre=True, each_item=False) + def convert_total_balances(cls, balances, values): + """ + Convert total_balances to their decimal values based on token decimals. + """ + converted_balances = {} + for token_address, balance in balances.items(): + try: + # Fetch the token decimals from TokenParams + decimals = TokenParams.get_token_decimals(token_address) + # Convert the balance using the decimals + converted_balances[token_address] = str(Decimal(balance) / Decimal(10 ** decimals)) + except ValueError as e: + raise ValueError(f"Error in balance conversion: {str(e)}") + return converted_balances + + + + +class GroupData(BaseModel): + health_ratio: str = Field(alias="healthRatio") + + +class Product(BaseModel): + name: str + manage_url: Optional[str] = Field(None, alias="manageUrl") # This field might not always be present + groups: Dict[str, GroupData] + positions: Optional[List[Position]] + type: str + + +class Dapp(BaseModel): + dappId: str + products: List[Product] + + +class ZkLendPositionResponse(BaseModel): + dapps: List[Dapp] + nonce: int \ No newline at end of file diff --git a/web_app/api/tools/__init__.py b/web_app/api/tools/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/web_app/api/tools/redis_cache.py b/web_app/api/tools/redis_cache.py new file mode 100644 index 00000000..45510b93 --- /dev/null +++ b/web_app/api/tools/redis_cache.py @@ -0,0 +1,54 @@ +import redis.asyncio as aioredis + +WALLET_ID_EXPIRATION = 60 * 60 * 24 # 24 hours + + +class RedisCache: + _instance = None # Singleton instance + + def __new__(cls, *args, **kwargs): + if not cls._instance: + cls._instance = super(RedisCache, cls).__new__(cls, *args, **kwargs) + return cls._instance + + def __init__(self, redis_url: str = "redis://localhost:6379"): + if not hasattr(self, 'redis_url'): # Ensure initialization happens only once + self.redis_url = redis_url + self.redis = None + + async def connect(self): + """ + Connect to the Redis server. + """ + if self.redis is None: # Only connect if not already connected + self.redis = await aioredis.from_url(self.redis_url, decode_responses=True) + + async def close(self): + """ + Close the Redis connection. + """ + if self.redis: + await self.redis.close() + self.redis = None # Reset the connection + + async def set(self, key: str, value: str, expiration: int = WALLET_ID_EXPIRATION): + """ + Set a key-value pair in Redis with optional expiration time. + """ + await self.redis.set(key, value, ex=expiration) + + async def get(self, key: str): + """ + Get a value from Redis by key. + """ + return await self.redis.get(key) + + async def delete(self, key: str): + """ + Delete a key from Redis. + """ + await self.redis.delete(key) + + +# Global singleton instance +redis_cache = RedisCache()