fastapi/main.py

132 lines
5.4 KiB
Python
Executable File

import time, socket, uvicorn
from typing import Optional, Union
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import QueuePool
#local
from rpcs import RPCHost, RPCXMR
from models import Return
from meta import Queue
from functions import checksumCheck
import config
from dependencies.validate_url import UrlValidator
class ErrorException(Exception):
def __init__(self, code: str, status: str, status_message: str):
self.status = status
self.code = code
self.status_message = status_message
app = FastAPI()
@app.get("/")
def root():
return
@app.exception_handler(ErrorException)
def unicorn_exception_handler(request: Request, exc: ErrorException):
return JSONResponse(
status_code=exc.code,
content={
"status": f"{exc.status}",
"message": f"{exc.status_message}"
},
)
@app.get("/api/receive")
def receive(method: str, address: str, callback: Union[str, None] = None):
if not method:
raise ErrorException(code=422,status="error",status_message='Empty method used')
if not address:
raise ErrorException(code=422,status="error",status_message='Empty destination address')
if method.lower() not in ['btc', 'btct', 'ltc', 'doge', 'zec', 'bch', 'xmr']:
raise ErrorException(code=422,status="error",status_message='Invalid method used')
if checksumCheck(method.lower(), address) == False:
raise ErrorException(code=422,status="error",status_message='Invalid destination address')
if callback:
if UrlValidator.validate(callback) != True:
raise ErrorException(code=422,status="error",status_message='Invalid callback')
callback_req_n = 1
else:
callback = 'None'
callback_req_n = 0
## RPC connection to Demons
match method.upper():
case 'BTC' | 'LTC' | 'ZEC' | 'BCH' | 'BTCT' | 'DOGE':
rpc = RPCHost("http://%s:%s@%s:%s" % (config.rpcs[method.upper()]['user'], config.rpcs[method.upper()]['pass'], config.rpcs[method.upper()]['host'], config.rpcs[method.upper()]['port']))
case 'XMR':
rpc = RPCXMR(config.rpcs[method.upper()]['host'], config.rpcs[method.upper()]['user'], config.rpcs[method.upper()]['pass'])
case _:
raise ErrorException(code=422,status="error",status_message='RPC undergoing maintenance')
## checking if wallet is loaded
# wallet = rpc.call('createwallet','test',False,False,'exdTHnRJ1BxZfBvU',False,True,True,False)
try:
match method.upper():
case 'XMR':
wallet = rpc.call('create_address',{"account_index": 0})
wallet = wallet['address']
case 'LTC' | 'ZEC' | 'DOGE':
#wallet = rpc.call('createwallet','test',False,False,'exdTHnRJ1BxZfBvU',False,False,True)
wallet = rpc.call('getnewaddress')
case 'BTC' | 'BTCT':
#wallet = rpc.call('createwallet','test',False,False,'exdTHnRJ1BxZfBvU',False,True,True,False)
wallet = rpc.call('getnewaddress','', 'p2sh-segwit')
case 'BCH':
wallet = rpc.call('getnewaddress')
wallet = wallet.replace('bitcoincash:', '')
case _:
## notify admin about the error
raise ErrorException(code=422, status="error", status_message='RPC unavailable')
except Exception as error:
## notify admin about the error
# Failed to connect for remote procedure call.
raise ErrorException(code=422, status="error", status_message=error)
## SQL Connection with SQLAlchemy
engine = create_engine(
"mysql+pymysql://%s:%s@%s:%s/dev" % (config.DB['user'], config.DB['pass'], config.DB['host'], config.DB['port']),
poolclass=QueuePool,
#echo=True, #debug sqlalchemy
pool_size=4,
max_overflow=0,
pool_timeout=15, # Wait 15s for a connection
)
Session = sessionmaker(bind = engine)
session = Session()
if wallet:
try:
q = Queue(txhash = 'None', time = int(time.time()), account = method.upper(), fee = config.fee['REGULAR'][method.upper()], ready = 0, confirmations =0, callbackurl = callback, generated_address = wallet, destination = address, balance_received = '0.00000000', callback_req = callback_req_n, ip = '', hostname = '', merchantId = 'None', dateTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
session.add(q)
session.commit()
session.close()
except Exception as error:
## notify admin about the error
raise ErrorException(code=422,status="error",status_message='Invalid response from dbServer')
else:
## notify admin about the error
raise ErrorException(code=422,status="error",status_message='Invalid response from rpcServer')
return Return(
address = wallet,
destination = address,
callback_url = callback,
fee = config.fee['REGULAR'][method.upper()],
status = 'success'
)
# Run
if __name__ == '__main__':
uvicorn.run('main:app', host='0.0.0.0', reload=True, debug=True)
#workers=4 (doesn't work with reload)