132 lines
5.4 KiB
Python
Executable File
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:'+str(error))
|
|
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) |