import logging import sys from typing import List, Optional, Union from cic_eth.server import cache, converters from cic_eth.server.cache import setup_cache from cic_eth.server.celery import create_celery_wrapper from cic_eth.server.models import (DefaultToken, Token, TokenBalance, Transaction) from fastapi import FastAPI, Query log = logging.getLogger(__name__) def create_app(chain_spec, celery_queue, redis_host, redis_port, redis_db, redis_timeout): setup_cache(redis_db=redis_db, redis_host=redis_host, redis_port=redis_port) celery_wrapper = create_celery_wrapper(celery_queue=celery_queue, chain_spec=chain_spec, redis_db=redis_db, redis_host=redis_host, redis_port=redis_port, redis_timeout=redis_timeout) app = FastAPI(debug=True, title="Grassroots Economics", description="CIC ETH API", version="0.0.1", terms_of_service="https://www.grassrootseconomics.org/pages/terms-and-conditions.html", contact={ "name": "Grassroots Economics", "url": "https://www.grassrootseconomics.org", "email": "will@grassecon.org" }, license_info={ "name": "GPLv3", }) @app.get("/transactions", response_model=List[Transaction]) def transactions(address: str, limit: Optional[str] = 10): return celery_wrapper('list', address, limit=limit) @app.get("/balance", response_model=List[TokenBalance]) def balance(token_symbol: str, address: str = Query(..., title="Address", min_length=40, max_length=42), include_pending: bool = True): log.info(f"address: {address}") log.info(f"token_symbol: {token_symbol}") data = celery_wrapper('balance', address, token_symbol, include_pending=include_pending) for b in data: token = get_token(token_symbol) b['balance_network'] = converters.from_wei( token.decimals, int(b['balance_network'])) b['balance_incoming'] = converters.from_wei( token.decimals, int(b['balance_incoming'])) b['balance_outgoing'] = converters.from_wei( token.decimals, int(b['balance_outgoing'])) b.update({ "balance_available": int(b['balance_network']) + int(b['balance_incoming']) - int(b['balance_outgoing']) }) return data @app.post("/create_account") def create_account(password: Optional[str] = None, register: bool = True): data = celery_wrapper( 'create_account', password=password, register=register) return data # def refill_gas(start_response, query: dict): # address = query.pop('address') # data = celery_wrapper('refill_gas', address) # return data # def ping(start_response, query: dict): # data = celery_wrapper('ping', **query) # return data @app.post("/transfer") def transfer(from_address: str, to_address: str, value: int, token_symbol: str): token = get_token( token_symbol) wei_value = converters.to_wei(token.decimals, int(value)) data = celery_wrapper('transfer', from_address, to_address, wei_value, token_symbol) return data @app.post("/transfer_from") def transfer_from(from_address: str, to_address: str, value: int, token_symbol: str, spender_address: str): token = get_token( token_symbol) wei_value = converters.to_wei(token.decimals, int(value)) data = celery_wrapper('transfer_from', from_address, to_address, wei_value, token_symbol, spender_address) return data @app.get("/token", response_model=Token) def token(token_symbol: str, proof: Optional[str] = None): token = get_token(token_symbol) if token == None: sys.stderr.write(f"Cached Token {token_symbol} not found") data = celery_wrapper('token', token_symbol, proof=proof) cache.set_token_data(token_symbol, data) token = Token.new(data) sys.stderr.write(f"Token {token}") return token @app.get("/tokens", response_model=List[Token]) def tokens(token_symbols: Optional[List[str]] = Query(None), proof: Optional[Union[str, List[str], List[List[str]]]] = None): data = celery_wrapper('tokens', token_symbols, catch=len(token_symbols), proof=proof) if data: tokens = [] for token in data: print(f"Token: {token}") tokens.append(Token.new(token)) return tokens return None @app.get("/default_token", response_model=DefaultToken) def default_token(): data = cache.get_default_token() if data is None: data = celery_wrapper('default_token') if data is not None: cache.set_default_token(data) return data def get_token(token_symbol: str): data = cache.get_token_data(token_symbol) log.debug(f"cached token data: {data}") if data == None: data = celery_wrapper('token', token_symbol) log.debug( f"No token data setting token data for: {token_symbol} to {data}") cache.set_token_data(token_symbol, data) return Token.new(data) return app