Example #1
0
def calculate_token_eth_price(
        token_address: ChecksumAddress,
        redis_key: str,
        force_recalculation: bool = False) -> Optional[float]:
    """
    Do price calculation for token in an async way and store it on redis
    :param token_address: Token address
    :param redis_key: Redis key for token price
    :param force_recalculation: Force a new calculation even if an old one is on cache
    :return: token price (in ether) when calculated
    """
    redis = get_redis()
    key_was_set = redis.set(redis_key, 0, ex=50, nx=True)
    if key_was_set or force_recalculation:
        price_service = PriceServiceProvider()
        eth_price = price_service.get_token_eth_value(token_address)
        if not eth_price:  # Try usd oracles
            usd_price = price_service.get_token_usd_price(token_address)
            if usd_price:
                eth_usd_price = price_service.get_eth_usd_price()
                eth_price = usd_price / eth_usd_price
        redis_expiration_time = 60 * 30  # Expire in 30 minutes
        redis.setex(redis_key, redis_expiration_time, eth_price)
        if eth_price and not getattr(settings, 'CELERY_ALWAYS_EAGER', False):
            # Recalculate price before cache expires and prevents recursion checking Celery Eager property
            calculate_token_eth_price.apply_async(
                (token_address, redis_key), {'force_recalculation': True},
                countdown=redis_expiration_time - 300)
        return eth_price
    else:
        float(redis.get(redis_key))
def get_token_info_from_blockchain(token_address: ChecksumAddress) -> bool:
    """
    Retrieve token information from blockchain
    :param token_address:
    :return: `True` if found, `False` otherwise
    """
    redis = get_redis()
    key = f'token-task:{token_address}'
    if result := redis.get(key):
        return bool(int(result))
def calculate_token_eth_price_task(
        token_address: ChecksumAddress,
        redis_key: str,
        force_recalculation: bool = False) -> Optional[EthValueWithTimestamp]:
    """
    Do price calculation for token in an async way and store it with its timestamp on redis
    :param token_address: Token address
    :param redis_key: Redis key for token price
    :param force_recalculation: Force a new calculation even if an old one is on cache
    :return: token price (in ether) when calculated
    """
    redis_expiration_time = 60 * 30  # Expire in 30 minutes
    redis = get_redis()
    now = timezone.now()
    current_timestamp = int(now.timestamp())
    key_was_set = redis.set(redis_key,
                            f'0:{current_timestamp}',
                            ex=60 * 15,
                            nx=True)  # Expire in 15 minutes
    if key_was_set or force_recalculation:
        price_service = PriceServiceProvider()
        eth_price = price_service.get_token_eth_value(token_address)
        if not eth_price:  # Try usd oracles
            usd_price = price_service.get_token_usd_price(token_address)
            if usd_price:
                eth_usd_price = price_service.get_eth_usd_price()
                eth_price = usd_price / eth_usd_price
        if eth_price:
            eth_value_with_timestamp = EthValueWithTimestamp(eth_price, now)
            redis.setex(redis_key, redis_expiration_time,
                        str(eth_value_with_timestamp))
            if not getattr(settings, 'CELERY_ALWAYS_EAGER', False):
                # Recalculate price before cache expires and prevents recursion checking Celery Eager property
                calculate_token_eth_price_task.apply_async(
                    (token_address, redis_key), {'force_recalculation': True},
                    countdown=redis_expiration_time - 300)
        else:
            logger.warning('Cannot calculate eth price for token=%s',
                           token_address)
        return EthValueWithTimestamp(eth_price, now)
    else:
        return EthValueWithTimestamp.from_string(redis.get(redis_key).decode())
 def __new__(cls):
     if not hasattr(cls, 'instance'):
         cls.instance = PriceService(EthereumClientProvider(), get_redis())
     return cls.instance
 def __init__(self, address: Optional[str], payload: Dict[str, Any]):
     self.redis = get_redis()
     self.address = address
     self.payload = payload
     self.redis_payload = self._get_redis_payload(address, payload)