Compare commits
10 Commits
a3859016a2
...
836de91fb3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
836de91fb3 | ||
|
|
4293c79e63 | ||
|
|
a71c15fe6c | ||
|
|
63e5a0da87 | ||
|
|
1b9f75ebb4 | ||
|
|
40f43aefb2 | ||
|
|
fff6824b30 | ||
|
|
c8881c23de | ||
|
|
ac5913d3a1 | ||
|
|
0c5365b510 |
@ -21,7 +21,7 @@ BLOCKBOOK_NETURL = "https://blockbook.ranchimall.net/"
|
||||
TOKENAPI_SSE_URL = "https://ranchimallflo.duckdns.org/"
|
||||
MAINNET_BLOCKBOOK_SERVER_LIST = ["https://blockbook.ranchimall.net/"]
|
||||
TESTNET_BLOCKBOOK_SERVER_LIST = ["https://blockbook-testnet.ranchimall.net/"]
|
||||
IGNORE_BLOCK_LIST = 902446
|
||||
IGNORE_BLOCK_LIST = [902446]
|
||||
#IGNORE_TRANSACTION_LIST = "b4ac4ddb51188b28b39bcb3aa31357d5bfe562c21e8aaf8dde0ec560fc893174"
|
||||
|
||||
"""?NOT USED?
|
||||
|
||||
39
main.py
Normal file
39
main.py
Normal file
@ -0,0 +1,39 @@
|
||||
import sys
|
||||
import time
|
||||
import threading
|
||||
from src.api.api_main import start_api_server
|
||||
from src.backend.backend_main import start_backend_process
|
||||
import config as config
|
||||
from src.flags import set_run_start
|
||||
|
||||
DELAY_API_SERVER_START = 60 # 1 min
|
||||
|
||||
def convert_to_dict(module):
|
||||
context = {}
|
||||
for setting in dir(module):
|
||||
if not setting.startswith("__"):
|
||||
context[setting] = getattr(module, setting)
|
||||
return context
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# parse the config file into dict
|
||||
_config = convert_to_dict(config)
|
||||
set_run_start()
|
||||
|
||||
# start the backend process (token scanner). pass reset=True if --reset is in command-line args
|
||||
if "--reset" in sys.argv or "-r" in sys.argv:
|
||||
t1 = threading.Thread(target=lambda:start_backend_process(config=_config, reset=True))
|
||||
else:
|
||||
t1 = threading.Thread(target=lambda:start_backend_process(config=_config))
|
||||
t1.start()
|
||||
# sleep until backend is started, so that API server can function correctly (TODO: sleep until backend process returns some flag indicating its started)
|
||||
#time.sleep(DELAY_API_SERVER_START)
|
||||
|
||||
# start the API server
|
||||
start_api_server(config=_config)
|
||||
#t2 = threading.Thread(target=lambda: start_api_server(config=_config))
|
||||
#t2.start()
|
||||
|
||||
t1.join()
|
||||
#t2.join()
|
||||
@ -10,7 +10,7 @@ from quart import jsonify, make_response, Quart, render_template, request, flash
|
||||
from quart_cors import cors
|
||||
import asyncio
|
||||
from typing import Optional
|
||||
import parsing
|
||||
import src.api.parsing as parsing
|
||||
import subprocess
|
||||
from apscheduler.schedulers.background import BackgroundScheduler
|
||||
import atexit
|
||||
@ -19,22 +19,19 @@ from operator import itemgetter
|
||||
import pdb
|
||||
import ast
|
||||
import time
|
||||
from src.flags import is_backend_ready
|
||||
|
||||
app = Quart(__name__)
|
||||
app.clients = set()
|
||||
app = cors(app, allow_origin="*")
|
||||
|
||||
INTERNAL_ERROR = "Unable to process request, try again later"
|
||||
BACKEND_NOT_READY_ERROR = "Server is still syncing, try again later!"
|
||||
BACKEND_NOT_READY_WARNING = "Server is still syncing, data may not be final"
|
||||
|
||||
# Global values and configg
|
||||
internalTransactionTypes = [ 'tokenswapDepositSettlement', 'tokenswapParticipationSettlement', 'smartContractDepositReturn']
|
||||
|
||||
if net == 'mainnet':
|
||||
is_testnet = False
|
||||
elif net == 'testnet':
|
||||
is_testnet = True
|
||||
|
||||
|
||||
# Validation functionss
|
||||
def check_flo_address(floaddress, is_testnet=False):
|
||||
return pyflo.is_address_valid(floaddress, testnet=is_testnet)
|
||||
@ -681,6 +678,8 @@ async def broadcastTx(raw_transaction_hash):
|
||||
# FLO TOKEN APIs
|
||||
@app.route('/api/v1.0/getTokenList', methods=['GET'])
|
||||
async def getTokenList():
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='error', description=BACKEND_NOT_READY_ERROR)
|
||||
try:
|
||||
filelist = []
|
||||
for item in os.listdir(os.path.join(DATA_PATH, 'tokens')):
|
||||
@ -704,7 +703,10 @@ async def getTokenInfo():
|
||||
conn = sqlite3.connect(dblocation)
|
||||
c = conn.cursor()
|
||||
else:
|
||||
return jsonify(result='error', description='token doesn\'t exist')
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='error', description=BACKEND_NOT_READY_ERROR)
|
||||
else:
|
||||
return jsonify(result='error', description='token doesn\'t exist')
|
||||
c.execute('SELECT * FROM transactionHistory WHERE id=1')
|
||||
incorporationRow = c.fetchall()[0]
|
||||
c.execute('SELECT COUNT (DISTINCT address) FROM activeTable')
|
||||
@ -725,8 +727,11 @@ async def getTokenInfo():
|
||||
tempdict['blockHash'] = item[3]
|
||||
tempdict['transactionHash'] = item[4]
|
||||
associatedContractList.append(tempdict)
|
||||
|
||||
return jsonify(result='ok', token=token, incorporationAddress=incorporationRow[1], tokenSupply=incorporationRow[3], time=incorporationRow[6], blockchainReference=incorporationRow[7], activeAddress_no=numberOf_distinctAddresses, totalTransactions=numberOf_transactions, associatedSmartContracts=associatedContractList)
|
||||
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='ok', token=token, incorporationAddress=incorporationRow[1], tokenSupply=incorporationRow[3], time=incorporationRow[6], blockchainReference=incorporationRow[7], activeAddress_no=numberOf_distinctAddresses, totalTransactions=numberOf_transactions, associatedSmartContracts=associatedContractList, warning=BACKEND_NOT_READY_WARNING)
|
||||
else:
|
||||
return jsonify(result='ok', token=token, incorporationAddress=incorporationRow[1], tokenSupply=incorporationRow[3], time=incorporationRow[6], blockchainReference=incorporationRow[7], activeAddress_no=numberOf_distinctAddresses, totalTransactions=numberOf_transactions, associatedSmartContracts=associatedContractList)
|
||||
|
||||
except Exception as e:
|
||||
print("getTokenInfo:", e)
|
||||
@ -750,7 +755,10 @@ async def getTokenTransactions():
|
||||
conn.row_factory = sqlite3.Row
|
||||
c = conn.cursor()
|
||||
else:
|
||||
return jsonify(result='error', description='token doesn\'t exist')
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='error', description=BACKEND_NOT_READY_ERROR)
|
||||
else:
|
||||
return jsonify(result='error', description='token doesn\'t exist')
|
||||
|
||||
if senderFloAddress and not destFloAddress:
|
||||
if limit is None:
|
||||
@ -782,7 +790,10 @@ async def getTokenTransactions():
|
||||
transactions_object['transactionDetails'] = update_transaction_confirmations(transactions_object['transactionDetails'])
|
||||
transactions_object['parsedFloData'] = json.loads(row[1])
|
||||
rowarray_list[transactions_object['transactionDetails']['txid']] = transactions_object
|
||||
return jsonify(result='ok', token=token, transactions=rowarray_list)
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='ok', token=token, transactions=rowarray_list, warning=BACKEND_NOT_READY_WARNING)
|
||||
else:
|
||||
return jsonify(result='ok', token=token, transactions=rowarray_list)
|
||||
|
||||
except Exception as e:
|
||||
print("getTokenTransactions:", e)
|
||||
@ -801,7 +812,10 @@ async def getTokenBalances():
|
||||
conn = sqlite3.connect(dblocation)
|
||||
c = conn.cursor()
|
||||
else:
|
||||
return jsonify(result='error', description='token doesn\'t exist')
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='error', description=BACKEND_NOT_READY_ERROR)
|
||||
else:
|
||||
return jsonify(result='error', description='token doesn\'t exist')
|
||||
c.execute('SELECT address,SUM(transferBalance) FROM activeTable GROUP BY address')
|
||||
addressBalances = c.fetchall()
|
||||
|
||||
@ -809,8 +823,12 @@ async def getTokenBalances():
|
||||
|
||||
for address in addressBalances:
|
||||
returnList[address[0]] = address[1]
|
||||
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='ok', token=token, balances=returnList, warning=BACKEND_NOT_READY_WARNING)
|
||||
else:
|
||||
return jsonify(result='ok', token=token, balances=returnList)
|
||||
|
||||
return jsonify(result='ok', token=token, balances=returnList)
|
||||
except Exception as e:
|
||||
print("getTokenBalances:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
@ -850,7 +868,10 @@ async def getFloAddressInfo():
|
||||
detailList[token] = tempdict
|
||||
else:
|
||||
# Address is not associated with any token
|
||||
return jsonify(result='error', description='FLO address is not associated with any tokens')
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='error', description=BACKEND_NOT_READY_ERROR)
|
||||
else:
|
||||
return jsonify(result='error', description='FLO address is not associated with any tokens')
|
||||
|
||||
if len(incorporatedContracts) != 0:
|
||||
incorporatedSmartContracts = []
|
||||
@ -865,10 +886,13 @@ async def getFloAddressInfo():
|
||||
tempdict['blockNumber'] = contract[5]
|
||||
tempdict['blockHash'] = contract[6]
|
||||
incorporatedSmartContracts.append(tempdict)
|
||||
|
||||
else:
|
||||
incorporatedSmartContracts = None
|
||||
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='ok', floAddress=floAddress, floAddressBalances=detailList, incorporatedSmartContracts=incorporatedContracts)
|
||||
else:
|
||||
return jsonify(result='ok', floAddress=floAddress, floAddressBalances=detailList, incorporatedSmartContracts=None)
|
||||
return jsonify(result='ok', warning=BACKEND_NOT_READY_WARNING, floAddress=floAddress, floAddressBalances=detailList, incorporatedSmartContracts=incorporatedContracts)
|
||||
|
||||
except Exception as e:
|
||||
print("getFloAddressInfo:", e)
|
||||
@ -907,24 +931,35 @@ async def getAddressBalance():
|
||||
tempdict['balance'] = balance
|
||||
tempdict['token'] = token
|
||||
detailList[token] = tempdict
|
||||
|
||||
return jsonify(result='ok', floAddress=floAddress, floAddressBalances=detailList)
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='ok', warning=BACKEND_NOT_READY_WARNING, floAddress=floAddress, floAddressBalances=detailList)
|
||||
else:
|
||||
return jsonify(result='ok', floAddress=floAddress, floAddressBalances=detailList)
|
||||
|
||||
else:
|
||||
# Address is not associated with any token
|
||||
return jsonify(result='error', description='FLO address is not associated with any tokens')
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='error', description=BACKEND_NOT_READY_ERROR)
|
||||
else:
|
||||
return jsonify(result='error', description='FLO address is not associated with any tokens')
|
||||
else:
|
||||
dblocation = DATA_PATH + '/tokens/' + str(token) + '.db'
|
||||
if os.path.exists(dblocation):
|
||||
conn = sqlite3.connect(dblocation)
|
||||
c = conn.cursor()
|
||||
else:
|
||||
return jsonify(result='error', description='token doesn\'t exist')
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='error', description=BACKEND_NOT_READY_ERROR)
|
||||
else:
|
||||
return jsonify(result='error', description='token doesn\'t exist')
|
||||
c.execute(
|
||||
'SELECT SUM(transferBalance) FROM activeTable WHERE address="{}"'.format(floAddress))
|
||||
balance = c.fetchall()[0][0]
|
||||
conn.close()
|
||||
return jsonify(result='ok', token=token, floAddress=floAddress, balance=balance)
|
||||
if not is_backend_ready():
|
||||
jsonify(result='ok', warning=BACKEND_NOT_READY_WARNING, token=token, floAddress=floAddress, balance=balance)
|
||||
else:
|
||||
return jsonify(result='ok', token=token, floAddress=floAddress, balance=balance)
|
||||
|
||||
except Exception as e:
|
||||
print("getAddressBalance:", e)
|
||||
@ -953,7 +988,10 @@ async def getFloAddressTransactions():
|
||||
if os.path.exists(dblocation):
|
||||
tokenNames = [[str(token), ]]
|
||||
else:
|
||||
return jsonify(result='error', description='token doesn\'t exist')
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='error', description=BACKEND_NOT_READY_ERROR)
|
||||
else:
|
||||
return jsonify(result='error', description='token doesn\'t exist')
|
||||
|
||||
if len(tokenNames) != 0:
|
||||
allTransactionList = {}
|
||||
@ -979,11 +1017,20 @@ async def getFloAddressTransactions():
|
||||
allTransactionList[transactions_object['transactionDetails']['txid']] = transactions_object
|
||||
|
||||
if token is None:
|
||||
return jsonify(result='ok', floAddress=floAddress, transactions=allTransactionList)
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='ok', warning=BACKEND_NOT_READY_WARNING, floAddress=floAddress, transactions=allTransactionList)
|
||||
else:
|
||||
return jsonify(result='ok', floAddress=floAddress, transactions=allTransactionList)
|
||||
else:
|
||||
return jsonify(result='ok', floAddress=floAddress, transactions=allTransactionList, token=token)
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='ok', warning=BACKEND_NOT_READY_WARNING, floAddress=floAddress, transactions=allTransactionList, token=token)
|
||||
else:
|
||||
return jsonify(result='ok', floAddress=floAddress, transactions=allTransactionList, token=token)
|
||||
else:
|
||||
return jsonify(result='error', description='No token transactions present present on this address')
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='error', description=BACKEND_NOT_READY_ERROR)
|
||||
else:
|
||||
return jsonify(result='error', description='No token transactions present present on this address')
|
||||
|
||||
except Exception as e:
|
||||
print("getFloAddressTransactions:", e)
|
||||
@ -1082,7 +1129,10 @@ async def getContractList():
|
||||
|
||||
contractList.append(contractDict)
|
||||
|
||||
return jsonify(smartContracts=contractList, result='ok')
|
||||
if not is_backend_ready():
|
||||
return jsonify(smartContracts=contractList, result='ok', warning=BACKEND_NOT_READY_WARNING)
|
||||
else:
|
||||
return jsonify(smartContracts=contractList, result='ok')
|
||||
|
||||
|
||||
except Exception as e:
|
||||
@ -1183,11 +1233,16 @@ async def getContractInfo():
|
||||
|
||||
else:
|
||||
return jsonify(result='error', description='There is more than 1 trigger in the database for the smart contract. Please check your code, this shouldnt happen')
|
||||
|
||||
return jsonify(result='ok', contractName=contractName, contractAddress=contractAddress, contractInfo=returnval)
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='ok', warning=BACKEND_NOT_READY_WARNING, contractName=contractName, contractAddress=contractAddress, contractInfo=returnval)
|
||||
else:
|
||||
return jsonify(result='ok', contractName=contractName, contractAddress=contractAddress, contractInfo=returnval)
|
||||
|
||||
else:
|
||||
return jsonify(result='error', details='Smart Contract with the given name doesn\'t exist')
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='error', description=BACKEND_NOT_READY_ERROR)
|
||||
else:
|
||||
return jsonify(result='error', details='Smart Contract with the given name doesn\'t exist')
|
||||
|
||||
except Exception as e:
|
||||
print("getContractInfo:", e)
|
||||
@ -1270,10 +1325,15 @@ async def getcontractparticipants():
|
||||
'swapAmount': row[7]
|
||||
}
|
||||
conn.close()
|
||||
|
||||
return jsonify(result='ok', contractName=contractName, contractAddress=contractAddress, participantInfo=returnval)
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='ok', warning=BACKEND_NOT_READY_WARNING, contractName=contractName, contractAddress=contractAddress, participantInfo=returnval)
|
||||
else:
|
||||
return jsonify(result='ok', contractName=contractName, contractAddress=contractAddress, participantInfo=returnval)
|
||||
else:
|
||||
return jsonify(result='error', description='Smart Contract with the given name doesn\'t exist')
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='error', description=BACKEND_NOT_READY_ERROR)
|
||||
else:
|
||||
return jsonify(result='error', description='Smart Contract with the given name doesn\'t exist')
|
||||
|
||||
except Exception as e:
|
||||
print("getcontractparticipants:", e)
|
||||
@ -1475,10 +1535,16 @@ async def getParticipantDetails():
|
||||
|
||||
participationDetailsList.append(detailsDict)
|
||||
|
||||
return jsonify(result='ok', floAddress=floAddress, type='participant', participatedContracts=participationDetailsList)
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='ok', warning=BACKEND_NOT_READY_WARNING, floAddress=floAddress, type='participant', participatedContracts=participationDetailsList)
|
||||
else:
|
||||
return jsonify(result='ok', floAddress=floAddress, type='participant', participatedContracts=participationDetailsList)
|
||||
|
||||
else:
|
||||
return jsonify(result='error', description='Address hasn\'t participated in any other contract')
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='error', description=BACKEND_NOT_READY_ERROR)
|
||||
else:
|
||||
return jsonify(result='error', description='Address hasn\'t participated in any other contract')
|
||||
else:
|
||||
return jsonify(result='error', description='System error. System db is missing')
|
||||
|
||||
@ -1518,10 +1584,16 @@ async def getsmartcontracttransactions():
|
||||
transactions_object['parsedFloData'] = json.loads(item[1])
|
||||
returnval[transactions_object['transactionDetails']['txid']] = transactions_object
|
||||
|
||||
return jsonify(result='ok', contractName=contractName, contractAddress=contractAddress, contractTransactions=returnval)
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='ok', warning=BACKEND_NOT_READY_WARNING, contractName=contractName, contractAddress=contractAddress, contractTransactions=returnval)
|
||||
else:
|
||||
return jsonify(result='ok', contractName=contractName, contractAddress=contractAddress, contractTransactions=returnval)
|
||||
|
||||
else:
|
||||
return jsonify(result='error', description='Smart Contract with the given name doesn\'t exist')
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='error', description=BACKEND_NOT_READY_ERROR)
|
||||
else:
|
||||
return jsonify(result='error', description='Smart Contract with the given name doesn\'t exist')
|
||||
|
||||
except Exception as e:
|
||||
print("getParticipantDetails:", e)
|
||||
@ -1536,7 +1608,10 @@ async def getblockdetails(blockdetail):
|
||||
blockJson = json.loads(blockJson[0][0])
|
||||
return jsonify(result='ok', blockDetails=blockJson)
|
||||
else:
|
||||
return jsonify(result='error', description='Block doesn\'t exist in database')
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='error', description=BACKEND_NOT_READY_ERROR)
|
||||
else:
|
||||
return jsonify(result='error', description='Block doesn\'t exist in database')
|
||||
except Exception as e:
|
||||
print("getblockdetails:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
@ -1553,7 +1628,10 @@ async def gettransactiondetails(transactionHash):
|
||||
|
||||
return jsonify(parsedFloData=parseResult, transactionDetails=transactionJson, transactionHash=transactionHash, result='ok')
|
||||
else:
|
||||
return jsonify(result='error', description='Transaction doesn\'t exist in database')
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='error', description=BACKEND_NOT_READY_ERROR)
|
||||
else:
|
||||
return jsonify(result='error', description='Transaction doesn\'t exist in database')
|
||||
except Exception as e:
|
||||
print("gettransactiondetails:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
@ -1600,7 +1678,10 @@ async def getLatestTransactionDetails():
|
||||
tx_parsed_details['parsedFloData']['transactionType'] = item[4]
|
||||
tx_parsed_details['transactionDetails']['blockheight'] = int(item[2])
|
||||
tempdict[json.loads(item[3])['txid']] = tx_parsed_details
|
||||
return jsonify(result='ok', latestTransactions=tempdict)
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='ok', warning=BACKEND_NOT_READY_WARNING, latestTransactions=tempdict)
|
||||
else:
|
||||
return jsonify(result='ok', latestTransactions=tempdict)
|
||||
except Exception as e:
|
||||
print("getLatestTransactionDetails:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
@ -1628,7 +1709,10 @@ async def getLatestBlockDetails():
|
||||
tempdict = {}
|
||||
for idx, item in enumerate(latestBlocks):
|
||||
tempdict[json.loads(item[3])['hash']] = json.loads(item[3])
|
||||
return jsonify(result='ok', latestBlocks=tempdict)
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='ok', warning=BACKEND_NOT_READY_WARNING, latestBlocks=tempdict)
|
||||
else:
|
||||
return jsonify(result='ok', latestBlocks=tempdict)
|
||||
|
||||
except Exception as e:
|
||||
print("getsmartcontracttransactions:", e)
|
||||
@ -1654,7 +1738,10 @@ async def getblocktransactions(blockdetail):
|
||||
}
|
||||
return jsonify(result='ok', transactions=blocktxs, blockKeyword=blockdetail)
|
||||
else:
|
||||
return jsonify(result='error', description='Block doesn\'t exist in database')
|
||||
if not is_backend_ready():
|
||||
return jsonify(result='error', description=BACKEND_NOT_READY_ERROR)
|
||||
else:
|
||||
return jsonify(result='error', description='Block doesn\'t exist in database')
|
||||
|
||||
|
||||
except Exception as e:
|
||||
@ -1729,7 +1816,10 @@ async def getTokenSmartContractList():
|
||||
contractDict['closeDate'] = contract[11]
|
||||
contractList.append(contractDict)
|
||||
|
||||
return jsonify(tokens=filelist, smartContracts=contractList, result='ok')
|
||||
if not is_backend_ready():
|
||||
return jsonify(tokens=filelist, warning=BACKEND_NOT_READY_WARNING, smartContracts=contractList, result='ok')
|
||||
else:
|
||||
return jsonify(tokens=filelist, smartContracts=contractList, result='ok')
|
||||
except Exception as e:
|
||||
print("getTokenSmartContractList:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
@ -1758,12 +1848,14 @@ async def info():
|
||||
validatedBlockCount = c.execute('SELECT COUNT(distinct blockNumber) FROM latestBlocks').fetchall()[0][0]
|
||||
validatedTransactionCount = c.execute('SELECT COUNT(distinct transactionHash) FROM latestTransactions').fetchall()[0][0]
|
||||
conn.close()
|
||||
|
||||
return jsonify(systemAddressCount=tokenAddressCount, systemBlockCount=validatedBlockCount, systemTransactionCount=validatedTransactionCount, systemSmartContractCount=contractCount, systemTokenCount=tokenCount, lastscannedblock=lastscannedblock), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, systemAddressCount=tokenAddressCount, systemBlockCount=validatedBlockCount, systemTransactionCount=validatedTransactionCount, systemSmartContractCount=contractCount, systemTokenCount=tokenCount, lastscannedblock=lastscannedblock), 206
|
||||
else:
|
||||
return jsonify(systemAddressCount=tokenAddressCount, systemBlockCount=validatedBlockCount, systemTransactionCount=validatedTransactionCount, systemSmartContractCount=contractCount, systemTokenCount=tokenCount, lastscannedblock=lastscannedblock), 200
|
||||
|
||||
except Exception as e:
|
||||
print("info:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
|
||||
@app.route('/api/v2/broadcastTx/<raw_transaction_hash>')
|
||||
@ -1775,7 +1867,7 @@ async def broadcastTx_v2(raw_transaction_hash):
|
||||
|
||||
except Exception as e:
|
||||
print("broadcastTx_v2:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
# FLO TOKEN APIs
|
||||
@app.route('/api/v2/tokenList', methods=['GET'])
|
||||
@ -1785,10 +1877,13 @@ async def tokenList():
|
||||
for item in os.listdir(os.path.join(DATA_PATH, 'tokens')):
|
||||
if os.path.isfile(os.path.join(DATA_PATH, 'tokens', item)):
|
||||
filelist.append(item[:-3])
|
||||
return jsonify(tokens=filelist), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, tokens=filelist), 206
|
||||
else:
|
||||
return jsonify(tokens=filelist), 200
|
||||
except Exception as e:
|
||||
print("tokenList:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
|
||||
|
||||
@ -1804,7 +1899,10 @@ async def tokenInfo(token):
|
||||
conn = sqlite3.connect(dblocation)
|
||||
c = conn.cursor()
|
||||
else:
|
||||
return jsonify(description="Token doesn't exist"), 404
|
||||
if not is_backend_ready():
|
||||
return jsonify(description=BACKEND_NOT_READY_ERROR), 503
|
||||
else:
|
||||
return jsonify(description="Token doesn't exist"), 404
|
||||
c.execute('SELECT * FROM transactionHistory WHERE id=1')
|
||||
incorporationRow = c.fetchall()[0]
|
||||
c.execute('SELECT COUNT (DISTINCT address) FROM activeTable')
|
||||
@ -1826,11 +1924,14 @@ async def tokenInfo(token):
|
||||
tempdict['transactionHash'] = item[4]
|
||||
associatedContractList.append(tempdict)
|
||||
|
||||
return jsonify(token=token, incorporationAddress=incorporationRow[1], tokenSupply=incorporationRow[3], time=incorporationRow[6], blockchainReference=incorporationRow[7], activeAddress_no=numberOf_distinctAddresses, totalTransactions=numberOf_transactions, associatedSmartContracts=associatedContractList), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, token=token, incorporationAddress=incorporationRow[1], tokenSupply=incorporationRow[3], time=incorporationRow[6], blockchainReference=incorporationRow[7], activeAddress_no=numberOf_distinctAddresses, totalTransactions=numberOf_transactions, associatedSmartContracts=associatedContractList), 206
|
||||
else:
|
||||
return jsonify(token=token, incorporationAddress=incorporationRow[1], tokenSupply=incorporationRow[3], time=incorporationRow[6], blockchainReference=incorporationRow[7], activeAddress_no=numberOf_distinctAddresses, totalTransactions=numberOf_transactions, associatedSmartContracts=associatedContractList), 200
|
||||
|
||||
except Exception as e:
|
||||
print("tokenInfo:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
|
||||
@app.route('/api/v2/tokenTransactions/<token>', methods=['GET'])
|
||||
@ -1866,13 +1967,19 @@ async def tokenTransactions(token):
|
||||
if os.path.isfile(filelocation):
|
||||
transactionJsonData = fetch_token_transactions(token, senderFloAddress, destFloAddress, limit, use_AND)
|
||||
sortedFormattedTransactions = sort_transactions(transactionJsonData)
|
||||
return jsonify(token=token, transactions=sortedFormattedTransactions), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, token=token, transactions=sortedFormattedTransactions), 206
|
||||
else:
|
||||
return jsonify(token=token, transactions=sortedFormattedTransactions), 200
|
||||
else:
|
||||
return jsonify(description='Token with the given name doesn\'t exist'), 404
|
||||
if not is_backend_ready():
|
||||
return jsonify(description=BACKEND_NOT_READY_ERROR), 503
|
||||
else:
|
||||
return jsonify(description='Token with the given name doesn\'t exist'), 404
|
||||
|
||||
except Exception as e:
|
||||
print("tokenTransactions:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
|
||||
@app.route('/api/v2/tokenBalances/<token>', methods=['GET'])
|
||||
@ -1886,19 +1993,25 @@ async def tokenBalances(token):
|
||||
conn = sqlite3.connect(dblocation)
|
||||
c = conn.cursor()
|
||||
else:
|
||||
return jsonify(description="Token doesn't exist"), 404
|
||||
if not is_backend_ready():
|
||||
return jsonify(description=BACKEND_NOT_READY_ERROR), 503
|
||||
else:
|
||||
return jsonify(description="Token doesn't exist"), 404
|
||||
c.execute('SELECT address,SUM(transferBalance) FROM activeTable GROUP BY address')
|
||||
addressBalances = c.fetchall()
|
||||
returnList = {}
|
||||
for address in addressBalances:
|
||||
returnList[address[0]] = address[1]
|
||||
|
||||
return jsonify(token=token, balances=returnList), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, token=token, balances=returnList), 206
|
||||
else:
|
||||
return jsonify(token=token, balances=returnList), 200
|
||||
|
||||
|
||||
except Exception as e:
|
||||
print("tokenBalances:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
# FLO Address APIs
|
||||
@app.route('/api/v2/floAddressInfo/<floAddress>', methods=['GET'])
|
||||
@ -1952,11 +2065,14 @@ async def floAddressInfo(floAddress):
|
||||
tempdict['blockHash'] = contract[6]
|
||||
incorporatedSmartContracts.append(tempdict)
|
||||
|
||||
return jsonify(floAddress=floAddress, floAddressBalances=detailList, incorporatedSmartContracts=incorporatedSmartContracts), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, floAddress=floAddress, floAddressBalances=detailList, incorporatedSmartContracts=incorporatedSmartContracts), 206
|
||||
else:
|
||||
return jsonify(floAddress=floAddress, floAddressBalances=detailList, incorporatedSmartContracts=incorporatedSmartContracts), 200
|
||||
|
||||
except Exception as e:
|
||||
print("floAddressInfo:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
|
||||
@app.route('/api/v2/floAddressBalance/<floAddress>', methods=['GET'])
|
||||
@ -1991,25 +2107,37 @@ async def floAddressBalance(floAddress):
|
||||
tempdict['balance'] = balance
|
||||
tempdict['token'] = token
|
||||
detailList[token] = tempdict
|
||||
return jsonify(floAddress=floAddress, floAddressBalances=detailList), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, floAddress=floAddress, floAddressBalances=detailList), 206
|
||||
else:
|
||||
return jsonify(floAddress=floAddress, floAddressBalances=detailList), 200
|
||||
else:
|
||||
# Address is not associated with any token
|
||||
return jsonify(floAddress=floAddress, floAddressBalances={}), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, floAddress=floAddress, floAddressBalances={}), 206
|
||||
else:
|
||||
return jsonify(floAddress=floAddress, floAddressBalances={}), 200
|
||||
else:
|
||||
dblocation = DATA_PATH + '/tokens/' + str(token) + '.db'
|
||||
if os.path.exists(dblocation):
|
||||
conn = sqlite3.connect(dblocation)
|
||||
c = conn.cursor()
|
||||
else:
|
||||
return jsonify(description="Token doesn't exist"), 404
|
||||
if not is_backend_ready():
|
||||
return jsonify(description=BACKEND_NOT_READY_ERROR), 503
|
||||
else:
|
||||
return jsonify(description="Token doesn't exist"), 404
|
||||
c.execute(f'SELECT SUM(transferBalance) FROM activeTable WHERE address="{floAddress}"')
|
||||
balance = c.fetchall()[0][0]
|
||||
conn.close()
|
||||
return jsonify(floAddress=floAddress, token=token, balance=balance), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, floAddress=floAddress, token=token, balance=balance), 206
|
||||
else:
|
||||
return jsonify(floAddress=floAddress, token=token, balance=balance), 200
|
||||
|
||||
except Exception as e:
|
||||
print("floAddressBalance:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
|
||||
@app.route('/api/v2/floAddressTransactions/<floAddress>', methods=['GET'])
|
||||
@ -2036,7 +2164,10 @@ async def floAddressTransactions(floAddress):
|
||||
if os.path.exists(dblocation):
|
||||
tokenNames = [[str(token), ]]
|
||||
else:
|
||||
return jsonify(description="Token doesn't exist"), 404
|
||||
if not is_backend_ready():
|
||||
return jsonify(description=BACKEND_NOT_READY_ERROR), 503
|
||||
else:
|
||||
return jsonify(description="Token doesn't exist"), 404
|
||||
|
||||
if len(tokenNames) != 0:
|
||||
allTransactionList = []
|
||||
@ -2047,15 +2178,24 @@ async def floAddressTransactions(floAddress):
|
||||
|
||||
sortedFormattedTransactions = sort_transactions(allTransactionList)
|
||||
if token is None:
|
||||
return jsonify(floAddress=floAddress, transactions=sortedFormattedTransactions), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, floAddress=floAddress, transactions=sortedFormattedTransactions), 206
|
||||
else:
|
||||
return jsonify(floAddress=floAddress, transactions=sortedFormattedTransactions), 200
|
||||
else:
|
||||
return jsonify(floAddress=floAddress, transactions=sortedFormattedTransactions, token=token), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, floAddress=floAddress, transactions=sortedFormattedTransactions, token=token), 206
|
||||
else:
|
||||
return jsonify(floAddress=floAddress, transactions=sortedFormattedTransactions, token=token), 200
|
||||
else:
|
||||
return jsonify(floAddress=floAddress, transactions=[], token=token), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, floAddress=floAddress, transactions=[], token=token), 206
|
||||
else:
|
||||
return jsonify(floAddress=floAddress, transactions=[], token=token), 200
|
||||
|
||||
except Exception as e:
|
||||
print("floAddressTransactions:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
|
||||
# SMART CONTRACT APIs
|
||||
@ -2082,12 +2222,15 @@ async def getContractList_v2():
|
||||
|
||||
committeeAddressList = refresh_committee_list(APP_ADMIN, apiUrl, int(time.time()))
|
||||
|
||||
return jsonify(smartContracts=smart_contracts_morphed, smartContractCommittee=committeeAddressList), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, smartContracts=smart_contracts_morphed, smartContractCommittee=committeeAddressList), 206
|
||||
else:
|
||||
return jsonify(smartContracts=smart_contracts_morphed, smartContractCommittee=committeeAddressList), 200
|
||||
|
||||
|
||||
except Exception as e:
|
||||
print("getContractList_v2:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
@app.route('/api/v2/smartContractInfo', methods=['GET'])
|
||||
async def getContractInfo_v2():
|
||||
@ -2163,13 +2306,19 @@ async def getContractInfo_v2():
|
||||
returnval['closeDate'] = status_time_info[3]
|
||||
returnval['contractSubtype'] = 'time-trigger'
|
||||
|
||||
return jsonify(contractName=contractName, contractAddress=contractAddress, contractInfo=returnval), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, contractName=contractName, contractAddress=contractAddress, contractInfo=returnval), 206
|
||||
else:
|
||||
return jsonify(contractName=contractName, contractAddress=contractAddress, contractInfo=returnval), 200
|
||||
else:
|
||||
return jsonify(details="Smart Contract with the given name doesn't exist"), 404
|
||||
if not is_backend_ready():
|
||||
return jsonify(description=BACKEND_NOT_READY_ERROR), 503
|
||||
else:
|
||||
return jsonify(details="Smart Contract with the given name doesn't exist"), 404
|
||||
|
||||
except Exception as e:
|
||||
print("getContractInfo_v2:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
|
||||
@app.route('/api/v2/smartContractParticipants', methods=['GET'])
|
||||
@ -2219,7 +2368,10 @@ async def getcontractparticipants_v2():
|
||||
for row in result:
|
||||
participation = {'participantFloAddress': row[1], 'tokenAmount': row[2], 'userChoice': row[3], 'transactionHash': row[4]}
|
||||
returnval.append(participation)
|
||||
return jsonify(contractName=contractName, contractAddress=contractAddress, contractType=contractStructure['contractType'], contractSubtype='external-trigger', participantInfo=returnval), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, contractName=contractName, contractAddress=contractAddress, contractType=contractStructure['contractType'], contractSubtype='external-trigger', participantInfo=returnval), 206
|
||||
else:
|
||||
return jsonify(contractName=contractName, contractAddress=contractAddress, contractType=contractStructure['contractType'], contractSubtype='external-trigger', participantInfo=returnval), 200
|
||||
elif 'payeeAddress' in contractStructure:
|
||||
# contract is of the type internal trigger
|
||||
c.execute('SELECT id, participantAddress, tokenAmount, userChoice, transactionHash FROM contractparticipants')
|
||||
@ -2229,7 +2381,10 @@ async def getcontractparticipants_v2():
|
||||
for row in result:
|
||||
participation = {'participantFloAddress': row[1], 'tokenAmount': row[2], 'transactionHash': row[4]}
|
||||
returnval.append(participation)
|
||||
return jsonify(contractName=contractName, contractAddress=contractAddress, contractType=contractStructure['contractType'], contractSubtype='time-trigger', participantInfo=returnval), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, contractName=contractName, contractAddress=contractAddress, contractType=contractStructure['contractType'], contractSubtype='time-trigger', participantInfo=returnval), 206
|
||||
else:
|
||||
return jsonify(contractName=contractName, contractAddress=contractAddress, contractType=contractStructure['contractType'], contractSubtype='time-trigger', participantInfo=returnval), 200
|
||||
elif contractStructure['contractType'] == 'continuos-event' and contractStructure['subtype'] == 'tokenswap':
|
||||
c.execute('SELECT * FROM contractparticipants')
|
||||
contract_participants = c.fetchall()
|
||||
@ -2246,13 +2401,19 @@ async def getcontractparticipants_v2():
|
||||
}
|
||||
returnval.append(participation)
|
||||
conn.close()
|
||||
return jsonify(contractName=contractName, contractAddress=contractAddress, contractType=contractStructure['contractType'], contractSubtype=contractStructure['subtype'], participantInfo=returnval), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, contractName=contractName, contractAddress=contractAddress, contractType=contractStructure['contractType'], contractSubtype=contractStructure['subtype'], participantInfo=returnval), 206
|
||||
else:
|
||||
return jsonify(contractName=contractName, contractAddress=contractAddress, contractType=contractStructure['contractType'], contractSubtype=contractStructure['subtype'], participantInfo=returnval), 200
|
||||
else:
|
||||
return jsonify(description='Smart Contract with the given name doesn\'t exist'), 404
|
||||
if not is_backend_ready():
|
||||
return jsonify(description=BACKEND_NOT_READY_ERROR), 503
|
||||
else:
|
||||
return jsonify(description='Smart Contract with the given name doesn\'t exist'), 404
|
||||
|
||||
except Exception as e:
|
||||
print("getcontractparticipants_v2:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
|
||||
@app.route('/api/v2/participantDetails/<floAddress>', methods=['GET'])
|
||||
@ -2405,15 +2566,21 @@ async def participantDetails(floAddress):
|
||||
detailsDict['userChoice'] = result[0][0]
|
||||
participationDetailsList.append(detailsDict)
|
||||
|
||||
return jsonify(floAddress=floAddress, type='participant', participatedContracts=participationDetailsList), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, floAddress=floAddress, type='participant', participatedContracts=participationDetailsList), 206
|
||||
else:
|
||||
return jsonify(floAddress=floAddress, type='participant', participatedContracts=participationDetailsList), 200
|
||||
else:
|
||||
return jsonify(description="Address hasn't participated in any other contract"), 404
|
||||
if not is_backend_ready():
|
||||
return jsonify(description=BACKEND_NOT_READY_ERROR), 503
|
||||
else:
|
||||
return jsonify(description="Address hasn't participated in any other contract"), 404
|
||||
else:
|
||||
return jsonify(description='System error. System.db is missing. This is unusual, please report on https://github.com/ranchimall/ranchimallflo-api'), 500
|
||||
|
||||
except Exception as e:
|
||||
print("participantDetails:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
|
||||
@app.route('/api/v2/smartContractTransactions', methods=['GET'])
|
||||
@ -2445,13 +2612,19 @@ async def smartcontracttransactions():
|
||||
# Make db connection and fetch data
|
||||
transactionJsonData = fetch_contract_transactions(contractName, contractAddress, _from, to)
|
||||
transactionJsonData = sort_transactions(transactionJsonData)
|
||||
return jsonify(contractName=contractName, contractAddress=contractAddress, contractTransactions=transactionJsonData), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, contractName=contractName, contractAddress=contractAddress, contractTransactions=transactionJsonData), 206
|
||||
else:
|
||||
return jsonify(contractName=contractName, contractAddress=contractAddress, contractTransactions=transactionJsonData), 200
|
||||
else:
|
||||
return jsonify(description='Smart Contract with the given name doesn\'t exist'), 404
|
||||
if not is_backend_ready():
|
||||
return jsonify(description=BACKEND_NOT_READY_ERROR), 503
|
||||
else:
|
||||
return jsonify(description='Smart Contract with the given name doesn\'t exist'), 404
|
||||
|
||||
except Exception as e:
|
||||
print("smartcontracttransactions:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
|
||||
# todo - add options to only ask for active/consumed/returned deposits
|
||||
@ -2498,14 +2671,20 @@ async def smartcontractdeposits():
|
||||
deposit_info.append(obj)
|
||||
c.execute('SELECT SUM(depositBalance) AS totalDepositBalance FROM contractdeposits c1 WHERE id = ( SELECT MAX(id) FROM contractdeposits c2 WHERE c1.transactionHash = c2.transactionHash);')
|
||||
currentDepositBalance = c.fetchall()[0][0]
|
||||
return jsonify(currentDepositBalance=currentDepositBalance, depositInfo=deposit_info), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, currentDepositBalance=currentDepositBalance, depositInfo=deposit_info), 206
|
||||
else:
|
||||
return jsonify(currentDepositBalance=currentDepositBalance, depositInfo=deposit_info), 200
|
||||
else:
|
||||
return jsonify(description='Smart Contract with the given name doesn\'t exist'), 404
|
||||
if not is_backend_ready():
|
||||
return jsonify(description=BACKEND_NOT_READY_ERROR), 503
|
||||
else:
|
||||
return jsonify(description='Smart Contract with the given name doesn\'t exist'), 404
|
||||
|
||||
|
||||
except Exception as e:
|
||||
print("smartcontractdeposits:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
@app.route('/api/v2/blockDetails/<blockHash>', methods=['GET'])
|
||||
async def blockdetails(blockHash):
|
||||
@ -2516,10 +2695,13 @@ async def blockdetails(blockHash):
|
||||
blockJson = json.loads(blockJson[0][0])
|
||||
return jsonify(blockDetails=blockJson), 200
|
||||
else:
|
||||
return jsonify(description='Block doesn\'t exist in database'), 404
|
||||
if not is_backend_ready():
|
||||
return jsonify(description=BACKEND_NOT_READY_ERROR), 503
|
||||
else:
|
||||
return jsonify(description='Block doesn\'t exist in database'), 404
|
||||
except Exception as e:
|
||||
print("blockdetails:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
|
||||
|
||||
@ -2618,11 +2800,14 @@ async def transactiondetails1(transactionHash):
|
||||
mergeTx['operationDetails'] = operationDetails
|
||||
return jsonify(mergeTx), 200
|
||||
else:
|
||||
return jsonify(description='Transaction doesn\'t exist in database'), 404
|
||||
if not is_backend_ready():
|
||||
return jsonify(description=BACKEND_NOT_READY_ERROR), 503
|
||||
else:
|
||||
return jsonify(description='Transaction doesn\'t exist in database'), 404
|
||||
|
||||
except Exception as e:
|
||||
print("transactiondetails1:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
|
||||
@app.route('/api/v2/latestTransactionDetails', methods=['GET'])
|
||||
@ -2658,10 +2843,13 @@ async def latestTransactionDetails():
|
||||
# TODO (CRITICAL): Write conditions to include and filter on chain and offchain transactions
|
||||
tx_parsed_details['onChain'] = True
|
||||
tx_list.append(tx_parsed_details)
|
||||
return jsonify(latestTransactions=tx_list), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, latestTransactions=tx_list), 206
|
||||
else:
|
||||
return jsonify(latestTransactions=tx_list), 200
|
||||
except Exception as e:
|
||||
print("latestTransactionDetails:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
|
||||
|
||||
@ -2690,11 +2878,14 @@ async def latestBlockDetails():
|
||||
for idx, item in enumerate(latestBlocks):
|
||||
templst.append(json.loads(item[0]))
|
||||
|
||||
return jsonify(latestBlocks=templst), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, latestBlocks=templst), 206
|
||||
else:
|
||||
return jsonify(latestBlocks=templst), 200
|
||||
|
||||
except Exception as e:
|
||||
print("latestBlockDetails:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
|
||||
@app.route('/api/v2/blockTransactions/<blockHash>', methods=['GET'])
|
||||
@ -2715,12 +2906,15 @@ async def blocktransactions(blockHash):
|
||||
#blocktxs['onChain'] = True
|
||||
return jsonify(transactions=blocktxs, blockKeyword=blockHash), 200
|
||||
else:
|
||||
return jsonify(description='Block doesn\'t exist in database'), 404
|
||||
if not is_backend_ready():
|
||||
return jsonify(description=BACKEND_NOT_READY_ERROR), 503
|
||||
else:
|
||||
return jsonify(description='Block doesn\'t exist in database'), 404
|
||||
|
||||
|
||||
except Exception as e:
|
||||
print("blocktransactions:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
@app.route('/api/v2/categoriseString/<urlstring>')
|
||||
async def categoriseString_v2(urlstring):
|
||||
@ -2754,7 +2948,7 @@ async def categoriseString_v2(urlstring):
|
||||
|
||||
except Exception as e:
|
||||
print("categoriseString_v2:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
|
||||
@app.route('/api/v2/tokenSmartContractList', methods=['GET'])
|
||||
@ -2784,12 +2978,15 @@ async def tokenSmartContractList():
|
||||
conn.close()
|
||||
|
||||
committeeAddressList = refresh_committee_list(APP_ADMIN, apiUrl, int(time.time()))
|
||||
return jsonify(tokens=filelist, smartContracts=smart_contracts_morphed, smartContractCommittee=committeeAddressList), 200
|
||||
if not is_backend_ready():
|
||||
return jsonify(warning=BACKEND_NOT_READY_WARNING, tokens=filelist, smartContracts=smart_contracts_morphed, smartContractCommittee=committeeAddressList), 206
|
||||
else:
|
||||
return jsonify(tokens=filelist, smartContracts=smart_contracts_morphed, smartContractCommittee=committeeAddressList), 200
|
||||
|
||||
|
||||
except Exception as e:
|
||||
print("tokenSmartContractList:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
class ServerSentEvent:
|
||||
def __init__(
|
||||
@ -2856,7 +3053,7 @@ async def priceData():
|
||||
return jsonify(prices=prices), 200
|
||||
except Exception as e:
|
||||
print("priceData:", e)
|
||||
return jsonify(result='error', description=INTERNAL_ERROR)
|
||||
return jsonify(description=INTERNAL_ERROR), 500
|
||||
|
||||
|
||||
|
||||
@ -2883,15 +3080,23 @@ def initialize_db():
|
||||
updatePrices()
|
||||
|
||||
def set_configs(config):
|
||||
global DATA_PATH, apiUrl, FLO_DATA_DIR, API_VERIFY, debug_status, HOST, PORT, APP_ADMIN
|
||||
global DATA_PATH, apiUrl, FLO_DATA_DIR, API_VERIFY, debug_status, HOST, PORT, APP_ADMIN, NET, is_testnet
|
||||
DATA_PATH = config["DATA_PATH"]
|
||||
apiUrl = config["apiUrl"]
|
||||
FLO_DATA_DIR = config["FLO_DATA_DIR"]
|
||||
API_VERIFY = config["API_VERIFY"] or True
|
||||
if "API_VERIFY" in config:
|
||||
API_VERIFY = config["API_VERIFY"]
|
||||
else:
|
||||
API_VERIFY = True
|
||||
debug_status = config["debug_status"]
|
||||
HOST = config["HOST"]
|
||||
PORT = config["PORT"]
|
||||
APP_ADMIN = config["APP_ADMIN"]
|
||||
NET = config["NET"]
|
||||
if NET == 'mainnet':
|
||||
is_testnet = False
|
||||
elif NET == 'testnet':
|
||||
is_testnet = True
|
||||
|
||||
def init_process():
|
||||
initialize_db()
|
||||
@ -2905,4 +3110,5 @@ def init_process():
|
||||
def start_api_server(config):
|
||||
set_configs(config)
|
||||
init_process()
|
||||
print("Starting API server at port=", PORT)
|
||||
app.run(debug=debug_status, host=HOST, port=PORT)
|
||||
@ -1,34 +1,37 @@
|
||||
import argparse
|
||||
import configparser
|
||||
#import argparse
|
||||
#import configparser
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import threading
|
||||
#import pyflo
|
||||
import requests
|
||||
from sqlalchemy import create_engine, func, and_
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
import time
|
||||
import arrow
|
||||
import parsing
|
||||
from parsing import perform_decimal_operation
|
||||
import src.backend.parsing as parsing
|
||||
from src.backend.parsing import perform_decimal_operation
|
||||
import re
|
||||
from datetime import datetime
|
||||
from ast import literal_eval
|
||||
from models import SystemData, TokenBase, ActiveTable, ConsumedTable, TransferLogs, TransactionHistory, TokenContractAssociation, ContractBase, ContractStructure, ContractParticipants, ContractTransactionHistory, ContractDeposits, ConsumedInfo, ContractWinners, ContinuosContractBase, ContractStructure2, ContractParticipants2, ContractDeposits2, ContractTransactionHistory2, SystemBase, ActiveContracts, SystemData, ContractAddressMapping, TokenAddressMapping, DatabaseTypeMapping, TimeActions, RejectedContractTransactionHistory, RejectedTransactionHistory, LatestCacheBase, LatestTransactions, LatestBlocks
|
||||
from statef_processing import process_stateF
|
||||
from src.backend.models import SystemData, TokenBase, ActiveTable, ConsumedTable, TransferLogs, TransactionHistory, TokenContractAssociation, ContractBase, ContractStructure, ContractParticipants, ContractTransactionHistory, ContractDeposits, ConsumedInfo, ContractWinners, ContinuosContractBase, ContractStructure2, ContractParticipants2, ContractDeposits2, ContractTransactionHistory2, SystemBase, ActiveContracts, SystemData, ContractAddressMapping, TokenAddressMapping, DatabaseTypeMapping, TimeActions, RejectedContractTransactionHistory, RejectedTransactionHistory, LatestCacheBase, LatestTransactions, LatestBlocks
|
||||
from src.backend.statef_processing import process_stateF
|
||||
import asyncio
|
||||
import websockets
|
||||
from decimal import Decimal
|
||||
import pdb
|
||||
from util_rollback import rollback_to_block
|
||||
from src.backend.util_rollback import rollback_to_block
|
||||
from src.flags import set_backend_start, set_backend_stop, set_backend_sync_start, set_backend_sync_stop, set_backend_ready, set_backend_not_ready, is_backend_ready, is_backend_syncing
|
||||
|
||||
|
||||
RETRY_TIMEOUT_LONG = 30 * 60 # 30 mins
|
||||
RETRY_TIMEOUT_SHORT = 60 # 1 min
|
||||
DB_RETRY_TIMEOUT = 60 # 60 seconds
|
||||
|
||||
BLOCK_SYNC_BATCHSIZE = 1
|
||||
BACK_TRACK_BLOCKS = 1000
|
||||
|
||||
def newMultiRequest(apicall):
|
||||
current_server = serverlist[0]
|
||||
@ -86,7 +89,7 @@ def refresh_committee_list_old(admin_flo_id, api_url, blocktime):
|
||||
if response.status_code == 200:
|
||||
response = response.json()
|
||||
else:
|
||||
logger.info('Response from the Flosight API failed')
|
||||
logger.info('Response from the Blockbook API failed')
|
||||
sys.exit(0)
|
||||
|
||||
committee_list = []
|
||||
@ -127,11 +130,11 @@ def refresh_committee_list(admin_flo_id, api_url, blocktime):
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
else:
|
||||
logger.info(f'Response from the Flosight API failed. Retry in {RETRY_TIMEOUT_SHORT}s')
|
||||
logger.info(f'Response from the Blockbook API failed. Retry in {RETRY_TIMEOUT_SHORT}s')
|
||||
#sys.exit(0)
|
||||
time.sleep(RETRY_TIMEOUT_SHORT)
|
||||
except:
|
||||
logger.info(f'Fetch from the Flosight API failed. Retry in {RETRY_TIMEOUT_LONG}s...')
|
||||
logger.info(f'Fetch from the Blockbook API failed. Retry in {RETRY_TIMEOUT_LONG}s...')
|
||||
time.sleep(RETRY_TIMEOUT_LONG)
|
||||
|
||||
url = f'{api_url}api/v1/address/{admin_flo_id}?details=txs'
|
||||
@ -208,26 +211,26 @@ def find_sender_receiver(transaction_data):
|
||||
|
||||
def check_database_existence(type, parameters):
|
||||
if type == 'token':
|
||||
path = os.path.join(_config['DEFAULT']['DATA_PATH'], 'tokens', f'{parameters["token_name"]}.db')
|
||||
path = os.path.join(_config['DATA_PATH'], 'tokens', f'{parameters["token_name"]}.db')
|
||||
return os.path.isfile(path)
|
||||
|
||||
if type == 'smart_contract':
|
||||
path = os.path.join(_config['DEFAULT']['DATA_PATH'], 'smartContracts', f"{parameters['contract_name']}-{parameters['contract_address']}.db")
|
||||
path = os.path.join(_config['DATA_PATH'], 'smartContracts', f"{parameters['contract_name']}-{parameters['contract_address']}.db")
|
||||
return os.path.isfile(path)
|
||||
|
||||
|
||||
def create_database_connection(type, parameters=None):
|
||||
if type == 'token':
|
||||
path = os.path.join(_config['DEFAULT']['DATA_PATH'], 'tokens', f"{parameters['token_name']}.db")
|
||||
path = os.path.join(_config['DATA_PATH'], 'tokens', f"{parameters['token_name']}.db")
|
||||
engine = create_engine(f"sqlite:///{path}", echo=True)
|
||||
elif type == 'smart_contract':
|
||||
path = os.path.join(_config['DEFAULT']['DATA_PATH'], 'smartContracts', f"{parameters['contract_name']}-{parameters['contract_address']}.db")
|
||||
path = os.path.join(_config['DATA_PATH'], 'smartContracts', f"{parameters['contract_name']}-{parameters['contract_address']}.db")
|
||||
engine = create_engine(f"sqlite:///{path}", echo=True)
|
||||
elif type == 'system_dbs':
|
||||
path = os.path.join(_config['DEFAULT']['DATA_PATH'], f"system.db")
|
||||
path = os.path.join(_config['DATA_PATH'], f"system.db")
|
||||
engine = create_engine(f"sqlite:///{path}", echo=False)
|
||||
elif type == 'latest_cache':
|
||||
path = os.path.join(_config['DEFAULT']['DATA_PATH'], f"latestCache.db")
|
||||
path = os.path.join(_config['DATA_PATH'], f"latestCache.db")
|
||||
engine = create_engine(f"sqlite:///{path}", echo=False)
|
||||
|
||||
connection = engine.connect()
|
||||
@ -236,19 +239,19 @@ def create_database_connection(type, parameters=None):
|
||||
|
||||
def create_database_session_orm(type, parameters, base):
|
||||
if type == 'token':
|
||||
path = os.path.join(_config['DEFAULT']['DATA_PATH'], 'tokens', f"{parameters['token_name']}.db")
|
||||
path = os.path.join(_config['DATA_PATH'], 'tokens', f"{parameters['token_name']}.db")
|
||||
engine = create_engine(f"sqlite:///{path}", echo=True)
|
||||
base.metadata.create_all(bind=engine)
|
||||
session = sessionmaker(bind=engine)()
|
||||
|
||||
elif type == 'smart_contract':
|
||||
path = os.path.join(_config['DEFAULT']['DATA_PATH'], 'smartContracts', f"{parameters['contract_name']}-{parameters['contract_address']}.db")
|
||||
path = os.path.join(_config['DATA_PATH'], 'smartContracts', f"{parameters['contract_name']}-{parameters['contract_address']}.db")
|
||||
engine = create_engine(f"sqlite:///{path}", echo=True)
|
||||
base.metadata.create_all(bind=engine)
|
||||
session = sessionmaker(bind=engine)()
|
||||
|
||||
elif type == 'system_dbs':
|
||||
path = os.path.join(_config['DEFAULT']['DATA_PATH'], f"{parameters['db_name']}.db")
|
||||
path = os.path.join(_config['DATA_PATH'], f"{parameters['db_name']}.db")
|
||||
engine = create_engine(f"sqlite:///{path}", echo=False)
|
||||
base.metadata.create_all(bind=engine)
|
||||
session = sessionmaker(bind=engine)()
|
||||
@ -258,7 +261,7 @@ def create_database_session_orm(type, parameters, base):
|
||||
|
||||
def delete_contract_database(parameters):
|
||||
if check_database_existence('smart_contract', {'contract_name':f"{parameters['contract_name']}", 'contract_address':f"{parameters['contract_address']}"}):
|
||||
path = os.path.join(_config['DEFAULT']['DATA_PATH'], 'smartContracts', f"{parameters['contract_name']}-{parameters['contract_address']}.db")
|
||||
path = os.path.join(_config['DATA_PATH'], 'smartContracts', f"{parameters['contract_name']}-{parameters['contract_address']}.db")
|
||||
os.remove(path)
|
||||
|
||||
|
||||
@ -497,22 +500,8 @@ def fetchDynamicSwapPrice(contractStructure, blockinfo):
|
||||
|
||||
return float(contractStructure['price'])
|
||||
|
||||
|
||||
def processBlock(blockindex=None, blockhash=None):
|
||||
if blockindex is not None and blockhash is None:
|
||||
logger.info(f'Processing block {blockindex}')
|
||||
# Get block details
|
||||
while blockhash is None or blockhash == '':
|
||||
response = newMultiRequest(f"block-index/{blockindex}")
|
||||
try:
|
||||
blockhash = response['blockHash']
|
||||
except:
|
||||
logger.info(f"API call block-index/{blockindex} failed to give proper response. Retrying.")
|
||||
|
||||
blockinfo = newMultiRequest(f"block/{blockhash}")
|
||||
|
||||
#TODO: Check for reorg in here
|
||||
|
||||
def processBlockData(blockinfo):
|
||||
|
||||
# Check and perform operations which do not require blockchain intervention
|
||||
checkLocal_expiry_trigger_deposit(blockinfo)
|
||||
|
||||
@ -532,7 +521,7 @@ def processBlock(blockindex=None, blockhash=None):
|
||||
text = text.replace("\n", " \n ")
|
||||
# todo Rule 9 - Reject all noise transactions. Further rules are in parsing.py
|
||||
returnval = None
|
||||
parsed_data = parsing.parse_flodata(text, blockinfo, _config['DEFAULT']['NET'])
|
||||
parsed_data = parsing.parse_flodata(text, blockinfo, _config['NET'])
|
||||
if parsed_data['type'] not in ['noise', None, '']:
|
||||
logger.info(f"Processing transaction {transaction}")
|
||||
logger.info(f"flodata {text} is parsed to {parsed_data}")
|
||||
@ -565,6 +554,54 @@ def processBlock(blockindex=None, blockhash=None):
|
||||
logger.info(f"Unable to connect to 'system' database... retrying in {DB_RETRY_TIMEOUT} seconds")
|
||||
time.sleep(DB_RETRY_TIMEOUT)
|
||||
|
||||
def fetchBlockData(blockindex, blockhash = None):
|
||||
logger.info(f'Processing block {blockindex}')
|
||||
# Get block details
|
||||
while blockhash is None or blockhash == '':
|
||||
response = newMultiRequest(f"block-index/{blockindex}")
|
||||
try:
|
||||
blockhash = response['blockHash']
|
||||
except:
|
||||
logger.info(f"API call block-index/{blockindex} failed to give proper response. Retrying.")
|
||||
blockinfo = newMultiRequest(f"block/{blockhash}")
|
||||
return blockinfo
|
||||
|
||||
def processBlock(blockindex=None, blockhash=None):
|
||||
blockinfo = fetchBlockData(blockindex, blockhash)
|
||||
processBlockData(blockinfo)
|
||||
|
||||
def processBlocksInBatch(startIndex, stopIndex, batchsize = BLOCK_SYNC_BATCHSIZE):
|
||||
i_index = startIndex
|
||||
blockinfos = [None] * batchsize
|
||||
threads = [None] * batchsize
|
||||
|
||||
def fetchDataAndStore(blockindex, i):
|
||||
blockinfos[i] = fetchBlockData(blockindex)
|
||||
|
||||
while i_index <= stopIndex:
|
||||
|
||||
# clear blockinfo array
|
||||
for j in range(batchsize):
|
||||
blockinfos[j] = None
|
||||
threads[j] = None
|
||||
|
||||
# fetch data for blocks
|
||||
for j in range(batchsize):
|
||||
if (i_index <= stopIndex) and (i_index not in IGNORE_BLOCK_LIST):
|
||||
threads[j] = threading.Thread(target=fetchDataAndStore, args=(i_index, j))
|
||||
threads[j].start()
|
||||
i_index += 1 # increment blockindex
|
||||
|
||||
# wait for all threads in the batch to complete
|
||||
for j in range(batchsize):
|
||||
if threads[j] is not None: # if i_index > stopIndex or in ignore list, then threads[j] will be None
|
||||
threads[j].join()
|
||||
|
||||
# process the blockdata in linear (order of blockindex)
|
||||
for j in range(batchsize):
|
||||
if threads[j] is not None: # if i_index > stopIndex or in ignore list, then threads[j] will be None
|
||||
processBlockData(blockinfos[j])
|
||||
|
||||
|
||||
def updateLatestTransaction(transactionData, parsed_data, db_reference, transactionType=None ):
|
||||
# connect to latest transaction db
|
||||
@ -1051,10 +1088,9 @@ def checkLocal_expiry_trigger_deposit(blockinfo):
|
||||
updateLatestTransaction(transaction_data, parsed_data, f"{query.contractName}-{query.contractAddress}")
|
||||
|
||||
|
||||
def check_reorg():
|
||||
def check_for_reorg(backtrack_count = BACK_TRACK_BLOCKS):
|
||||
|
||||
connection = create_database_connection('system_dbs')
|
||||
blockbook_api_url = 'https://blockbook.ranchimall.net/'
|
||||
BACK_TRACK_BLOCKS = 1000
|
||||
|
||||
# find latest block number in local database
|
||||
latest_block = list(connection.execute("SELECT max(blockNumber) from latestBlocks").fetchone())[0]
|
||||
@ -1065,22 +1101,19 @@ def check_reorg():
|
||||
block_hash = list(connection.execute(f"SELECT blockHash from latestBlocks WHERE blockNumber = {block_number}").fetchone())[0]
|
||||
|
||||
# Check if the block is in blockbook (i.e, not dropped in reorg)
|
||||
response = requests.get(f'{blockbook_api_url}api/block/{block_number}', verify=API_VERIFY)
|
||||
if response.status_code == 200:
|
||||
response = response.json()
|
||||
if response['hash'] == block_hash: # local blockhash matches with blockbook hash
|
||||
break
|
||||
else: # check for older blocks to trace where reorg has happened
|
||||
block_number -= BACK_TRACK_BLOCKS
|
||||
continue
|
||||
else:
|
||||
logger.info('Response from the Blockbook API failed')
|
||||
sys.exit(0) #TODO test reorg fix and remove this
|
||||
response = newMultiRequest(f"block/{block_number}")
|
||||
if response['hash'] == block_hash: # local blockhash matches with blockbook hash
|
||||
break
|
||||
else: # check for older blocks to trace where reorg has happened
|
||||
block_number -= backtrack_count
|
||||
continue
|
||||
|
||||
connection.close()
|
||||
|
||||
# rollback if needed
|
||||
if block_number != latest_block:
|
||||
set_backend_not_ready()
|
||||
stop_sync_loop() # stop the syncing process
|
||||
rollback_to_block(block_number)
|
||||
|
||||
return block_number
|
||||
@ -1549,10 +1582,10 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
|
||||
query_data = contract_session.query(ContractDeposits.depositBalance).filter(ContractDeposits.id.in_(subquery)).filter(ContractDeposits.status != 'deposit-return').filter(ContractDeposits.status == 'active').all()
|
||||
|
||||
available_deposit_sum = sum(Decimal(f"{amount[0]}") if amount[0] is not None else Decimal(0) for amount in query_data)
|
||||
if available_deposit_sum==0 or available_deposit_sum[0][0] is None:
|
||||
if available_deposit_sum==0 or available_deposit_sum is None:
|
||||
available_deposit_sum = 0
|
||||
else:
|
||||
available_deposit_sum = float(available_deposit_sum[0][0])
|
||||
available_deposit_sum = float(available_deposit_sum)
|
||||
|
||||
if available_deposit_sum >= swapAmount:
|
||||
# accepting token transfer from participant to smart contract address
|
||||
@ -1577,7 +1610,7 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
|
||||
for a_deposit in available_deposits:
|
||||
if a_deposit.depositBalance > remaining_amount:
|
||||
# accepting token transfer from the contract to depositor's address
|
||||
returnval = transferToken(contractStructure['accepting_token'], perform_decimal_operation('multiply', remaining_amount, swapPrice), contractStructure['contractAddress'], a_deposit.depositorAddress, transaction_data=transaction_data, parsed_data=parsed_data, isInfiniteToken=None, blockinfo=blockinfo, transactionType='tokenswapDepositSettlement')
|
||||
returnval = transferToken(contractStructure['accepting_token'], perform_decimal_operation('multiplication', remaining_amount, swapPrice), contractStructure['contractAddress'], a_deposit.depositorAddress, transaction_data=transaction_data, parsed_data=parsed_data, isInfiniteToken=None, blockinfo=blockinfo, transactionType='tokenswapDepositSettlement')
|
||||
if returnval == 0:
|
||||
logger.info("CRITICAL ERROR | Something went wrong in the token transfer method while doing local Smart Contract Particiaption deposit swap operation")
|
||||
return 0
|
||||
@ -2445,18 +2478,31 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
|
||||
return 0
|
||||
|
||||
|
||||
def scanBlockchain():
|
||||
_is_scan_active = False
|
||||
|
||||
def scanBlockchain(startup = False):
|
||||
|
||||
global _is_scan_active
|
||||
|
||||
if _is_scan_active: # if there's already an instance of scan running, do nothing for this instance
|
||||
return
|
||||
|
||||
_is_scan_active = True # set scanning as True, to prevent multiple instances of scanBlockchain from running
|
||||
|
||||
# Read start block no
|
||||
while True:
|
||||
try:
|
||||
session = create_database_session_orm('system_dbs', {'db_name': "system"}, SystemBase)
|
||||
startblock = int(session.query(SystemData).filter_by(attribute='lastblockscanned').all()[0].value) + 1
|
||||
session.commit()
|
||||
session.close()
|
||||
break
|
||||
except:
|
||||
logger.info(f"Unable to connect to 'system' database... retrying in {DB_RETRY_TIMEOUT} seconds")
|
||||
time.sleep(DB_RETRY_TIMEOUT)
|
||||
if startup:
|
||||
while True:
|
||||
try:
|
||||
session = create_database_session_orm('system_dbs', {'db_name': "system"}, SystemBase)
|
||||
startblock = int(session.query(SystemData).filter_by(attribute='lastblockscanned').all()[0].value) + 1
|
||||
session.commit()
|
||||
session.close()
|
||||
break
|
||||
except:
|
||||
logger.info(f"Unable to connect to 'system' database... retrying in {DB_RETRY_TIMEOUT} seconds")
|
||||
time.sleep(DB_RETRY_TIMEOUT)
|
||||
else:
|
||||
startblock = check_for_reorg() + 1 # returns the current last block scanned (db is rollbacked if reorg happens)
|
||||
|
||||
# todo Rule 6 - Find current block height
|
||||
# Rule 7 - Start analysing the block contents from starting block to current height
|
||||
@ -2476,13 +2522,18 @@ def scanBlockchain():
|
||||
logger.info("Current block height is %s" % str(current_index))
|
||||
break
|
||||
|
||||
for blockindex in range(startblock, current_index):
|
||||
if blockindex in IGNORE_BLOCK_LIST:
|
||||
continue
|
||||
processBlock(blockindex=blockindex)
|
||||
processBlocksInBatch(startblock, current_index)
|
||||
|
||||
#for blockindex in range(startblock, current_index):
|
||||
# if blockindex in IGNORE_BLOCK_LIST:
|
||||
# continue
|
||||
# processBlock(blockindex=blockindex)
|
||||
|
||||
# At this point the script has updated to the latest block
|
||||
# Now we connect to flosight's websocket API to get information about the latest blocks
|
||||
set_backend_ready()
|
||||
# Now we connect to Blockbook's websocket API to get information about the latest blocks
|
||||
if not startup and not isactive_sync_loop():
|
||||
start_sync_loop()
|
||||
|
||||
def switchNeturl(currentneturl):
|
||||
# Use modulo operation to simplify the logic
|
||||
@ -2491,9 +2542,9 @@ def switchNeturl(currentneturl):
|
||||
|
||||
|
||||
def reconnectWebsocket(socket_variable):
|
||||
# Switch a to different flosight
|
||||
# Switch a to different Blockbook
|
||||
# neturl = switchNeturl(neturl)
|
||||
# Connect to Flosight websocket to get data on new incoming blocks
|
||||
# Connect to Blockbook websocket to get data on new incoming blocks
|
||||
i=0
|
||||
newurl = serverlist[0]
|
||||
while(not socket_variable.connected):
|
||||
@ -2518,7 +2569,13 @@ def get_websocket_uri(testnet=False):
|
||||
return "wss://blockbook.ranchimall.net/websocket"
|
||||
|
||||
async def connect_to_websocket(uri):
|
||||
|
||||
# global flag to pass termination when needed
|
||||
set_backend_sync_start()
|
||||
|
||||
while True:
|
||||
if not is_backend_syncing():
|
||||
return
|
||||
try:
|
||||
async with websockets.connect(uri) as websocket:
|
||||
subscription_request = {
|
||||
@ -2528,6 +2585,9 @@ async def connect_to_websocket(uri):
|
||||
}
|
||||
await websocket.send(json.dumps(subscription_request))
|
||||
while True:
|
||||
if not is_backend_syncing():
|
||||
websocket.close()
|
||||
return scanBlockchain()
|
||||
response = await websocket.recv()
|
||||
logger.info(f"Received: {response}")
|
||||
response = json.loads(response)
|
||||
@ -2538,13 +2598,20 @@ async def connect_to_websocket(uri):
|
||||
if response['data']['hash'] is None or response['data']['hash']=='':
|
||||
print('blockhash is none')
|
||||
# todo: remove these debugger lines
|
||||
# If this is the issue need to proceed forward only once blockbook has consolitated
|
||||
# If this is the issue need to proceed forward only once blockbook has consolitated
|
||||
|
||||
check_for_reorg()
|
||||
if not is_backend_syncing(): #if reorg happens, is_backend_syncing() becomes False as sync is closed
|
||||
websocket.close()
|
||||
return scanBlockchain()
|
||||
processBlock(blockindex=response['data']['height'], blockhash=response['data']['hash'])
|
||||
|
||||
except Exception as e:
|
||||
logger.info(f"Connection error: {e}")
|
||||
# Add a delay before attempting to reconnect
|
||||
await asyncio.sleep(5) # You can adjust the delay as needed
|
||||
if not is_backend_syncing():
|
||||
return
|
||||
scanBlockchain()
|
||||
|
||||
def create_dir_if_not_exist(dir_path, reset = False):
|
||||
@ -2571,22 +2638,22 @@ def init_lastestcache_db():
|
||||
def init_storage_if_not_exist(reset = False):
|
||||
# Delete database and smartcontract directory if reset is set to True
|
||||
|
||||
token_dir_path = os.path.join(_config['DEFAULT']['DATA_PATH'], 'tokens')
|
||||
token_dir_path = os.path.join(_config['DATA_PATH'], 'tokens')
|
||||
create_dir_if_not_exist(token_dir_path, reset)
|
||||
|
||||
smart_contract_dir_path = os.path.join(_config['DEFAULT']['DATA_PATH'], 'smartContracts')
|
||||
smart_contract_dir_path = os.path.join(_config['DATA_PATH'], 'smartContracts')
|
||||
create_dir_if_not_exist(smart_contract_dir_path, reset)
|
||||
|
||||
system_db_path = os.path.join(_config['DEFAULT']['DATA_PATH'], 'system.db')
|
||||
system_db_path = os.path.join(_config['DATA_PATH'], 'system.db')
|
||||
if os.path.exists(system_db_path):
|
||||
if reset:
|
||||
os.remove(system_db_path)
|
||||
init_system_db(int(_config['DEFAULT']['START_BLOCK']))
|
||||
init_system_db(int(_config['START_BLOCK']))
|
||||
else:
|
||||
init_system_db(int(_config['DEFAULT']['START_BLOCK']))
|
||||
init_system_db(int(_config['START_BLOCK']))
|
||||
|
||||
|
||||
latestCache_db_path = os.path.join(_config['DEFAULT']['DATA_PATH'], 'latestCache.db')
|
||||
latestCache_db_path = os.path.join(_config['DATA_PATH'], 'latestCache.db')
|
||||
if os.path.exists(latestCache_db_path):
|
||||
if reset:
|
||||
os.remove(latestCache_db_path)
|
||||
@ -2602,7 +2669,7 @@ def initiate_process():
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
formatter = logging.Formatter('%(asctime)s:%(name)s:%(message)s')
|
||||
file_handler = logging.FileHandler(os.path.join(_config['DEFAULT']['DATA_PATH'],'tracking.log'))
|
||||
file_handler = logging.FileHandler(os.path.join(_config['DATA_PATH'],'tracking.log'))
|
||||
file_handler.setLevel(logging.INFO)
|
||||
file_handler.setFormatter(formatter)
|
||||
|
||||
@ -2613,70 +2680,90 @@ def initiate_process():
|
||||
logger.addHandler(stream_handler)
|
||||
|
||||
|
||||
dirpath = os.path.join(_config['DEFAULT']['DATA_PATH'], 'tokens')
|
||||
dirpath = os.path.join(_config['DATA_PATH'], 'tokens')
|
||||
if not os.path.isdir(dirpath):
|
||||
os.mkdir(dirpath)
|
||||
dirpath = os.path.join(_config['DEFAULT']['DATA_PATH'], 'smartContracts')
|
||||
dirpath = os.path.join(_config['DATA_PATH'], 'smartContracts')
|
||||
if not os.path.isdir(dirpath):
|
||||
os.mkdir(dirpath)
|
||||
|
||||
# Read configuration
|
||||
|
||||
# todo - write all assertions to make sure default configs are right
|
||||
if (_config['DEFAULT']['NET'] != 'mainnet') and (_config['DEFAULT']['NET'] != 'testnet'):
|
||||
logger.error("NET parameter in _config.ini invalid. Options are either 'mainnet' or 'testnet'. Script is exiting now")
|
||||
if (_config['NET'] != 'mainnet') and (_config['NET'] != 'testnet'):
|
||||
logger.error("NET parameter in config.ini invalid. Options are either 'mainnet' or 'testnet'. Script is exiting now")
|
||||
sys.exit(0)
|
||||
|
||||
# Specify mainnet and testnet server list for API calls and websocket calls
|
||||
# Specify ADMIN ID
|
||||
global serverlist, APP_ADMIN, websocket_uri
|
||||
serverlist = None
|
||||
if _config['DEFAULT']['NET'] == 'mainnet':
|
||||
serverlist = _config['DEFAULT']['MAINNET_FLOSIGHT_SERVER_LIST']
|
||||
if _config['NET'] == 'mainnet':
|
||||
serverlist = _config['MAINNET_BLOCKBOOK_SERVER_LIST']
|
||||
APP_ADMIN = 'FNcvkz9PZNZM3HcxM1XTrVL4tgivmCkHp9'
|
||||
websocket_uri = get_websocket_uri(testnet=False)
|
||||
elif _config['DEFAULT']['NET'] == 'testnet':
|
||||
serverlist = _config['DEFAULT']['TESTNET_FLOSIGHT_SERVER_LIST']
|
||||
elif _config['NET'] == 'testnet':
|
||||
serverlist = _config['TESTNET_BLOCKBOOK_SERVER_LIST']
|
||||
APP_ADMIN = 'oWooGLbBELNnwq8Z5YmjoVjw8GhBGH3qSP'
|
||||
websocket_uri = get_websocket_uri(testnet=True)
|
||||
serverlist = serverlist.split(',')
|
||||
|
||||
#serverlist = serverlist.split(',')
|
||||
global neturl
|
||||
neturl = _config['DEFAULT']['FLOSIGHT_NETURL']
|
||||
neturl = _config['BLOCKBOOK_NETURL']
|
||||
global api_url
|
||||
api_url = neturl
|
||||
global tokenapi_sse_url
|
||||
tokenapi_sse_url = _config['DEFAULT']['TOKENAPI_SSE_URL']
|
||||
tokenapi_sse_url = _config['TOKENAPI_SSE_URL']
|
||||
global API_VERIFY
|
||||
API_VERIFY = _config['DEFAULT']['API_VERIFY']
|
||||
if API_VERIFY == 'False':
|
||||
API_VERIFY = False
|
||||
elif API_VERIFY == 'True':
|
||||
API_VERIFY = True
|
||||
if 'API_VERIFY' in _config:
|
||||
if isinstance(_config['API_VERIFY'], bool):
|
||||
API_VERIFY = _config['API_VERIFY']
|
||||
elif isinstance(_config['API_VERIFY'], str):
|
||||
API_VERIFY = False if _config['API_VERIFY'] == 'False' else True
|
||||
else:
|
||||
API_VERIFY = bool(_config['API_VERIFY'])
|
||||
else:
|
||||
API_VERIFY = True
|
||||
|
||||
global IGNORE_BLOCK_LIST #, IGNORE_TRANSACTION_LIST
|
||||
IGNORE_BLOCK_LIST = _config['IGNORE_BLOCK_LIST']
|
||||
#IGNORE_BLOCK_LIST = [int(s) for s in IGNORE_BLOCK_LIST]
|
||||
#IGNORE_TRANSACTION_LIST = _config['IGNORE_TRANSACTION_LIST']
|
||||
|
||||
global IGNORE_BLOCK_LIST, IGNORE_TRANSACTION_LIST
|
||||
IGNORE_BLOCK_LIST = _config['DEFAULT']['IGNORE_BLOCK_LIST'].split(',')
|
||||
IGNORE_BLOCK_LIST = [int(s) for s in IGNORE_BLOCK_LIST]
|
||||
IGNORE_TRANSACTION_LIST = _config['DEFAULT']['IGNORE_TRANSACTION_LIST'].split(',')
|
||||
def start_sync_loop():
|
||||
global _sync_loop
|
||||
_sync_loop = asyncio.get_event_loop()
|
||||
_sync_loop.run_until_complete(connect_to_websocket(websocket_uri))
|
||||
|
||||
def isactive_sync_loop():
|
||||
if _sync_loop is None:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def stop_sync_loop():
|
||||
set_backend_sync_stop()
|
||||
global _sync_loop
|
||||
if (_sync_loop is not None) and _sync_loop.is_running():
|
||||
_sync_loop.stop()
|
||||
_sync_loop = None
|
||||
|
||||
def start_backend_process(config, reset = False):
|
||||
global _config
|
||||
_config = config
|
||||
set_backend_start()
|
||||
set_backend_not_ready()
|
||||
initiate_process()
|
||||
init_storage_if_not_exist(reset)
|
||||
# MAIN LOGIC STARTS
|
||||
# scan from the latest block saved locally to latest network block
|
||||
scanBlockchain()
|
||||
scanBlockchain(startup=True)
|
||||
logger.debug("Completed first scan")
|
||||
# At this point the script has updated to the latest block
|
||||
# Now we connect to flosight's websocket API to get information about the latest blocks
|
||||
# Neturl is the URL for Flosight API whose websocket endpoint is being connected to
|
||||
|
||||
asyncio.get_event_loop().run_until_complete(connect_to_websocket(websocket_uri))
|
||||
# Now we connect to Blockbook's websocket API to get information about the latest blocks
|
||||
# Neturl is the URL for Blockbook API whose websocket endpoint is being connected to
|
||||
start_sync_loop()
|
||||
|
||||
"""
|
||||
# Determine API source for block and transaction information
|
||||
if __name__ == "__main__":
|
||||
|
||||
@ -2703,3 +2790,4 @@ if __name__ == "__main__":
|
||||
else:
|
||||
start_backend_process(config)
|
||||
|
||||
"""
|
||||
@ -88,5 +88,4 @@ for contract in contract_deposits:
|
||||
systemdb_session = create_database_session_orm('system_dbs', {'db_name':'system'}, SystemBase)
|
||||
query = systemdb_session.query(TokenAddressMapping).filter(TokenAddressMapping.tokenAddress == 'contractAddress')
|
||||
results = query.all()
|
||||
pdb.set_trace()
|
||||
print('Lets investigate this now')
|
||||
@ -2,7 +2,7 @@ from sqlalchemy import create_engine, desc, func
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from models import SystemData, TokenBase, ActiveTable, ConsumedTable, TransferLogs, TransactionHistory, TokenContractAssociation, ContractBase, ContractStructure, ContractParticipants, ContractTransactionHistory, ContractDeposits, ConsumedInfo, ContractWinners, ContinuosContractBase, ContractStructure2, ContractParticipants2, ContractDeposits2, ContractTransactionHistory2, SystemBase, ActiveContracts, SystemData, ContractAddressMapping, TokenAddressMapping, DatabaseTypeMapping, TimeActions, RejectedContractTransactionHistory, RejectedTransactionHistory, LatestCacheBase, LatestTransactions, LatestBlocks
|
||||
import json
|
||||
from tracktokens_smartcontracts import processTransaction, checkLocal_expiry_trigger_deposit, newMultiRequest
|
||||
from backend_main import processTransaction, checkLocal_expiry_trigger_deposit, newMultiRequest
|
||||
import os
|
||||
import logging
|
||||
import argparse
|
||||
@ -129,11 +129,11 @@ if (config['DEFAULT']['NET'] != 'mainnet') and (config['DEFAULT']['NET'] != 'tes
|
||||
# Specify mainnet and testnet server list for API calls and websocket calls
|
||||
serverlist = None
|
||||
if config['DEFAULT']['NET'] == 'mainnet':
|
||||
serverlist = config['DEFAULT']['MAINNET_FLOSIGHT_SERVER_LIST']
|
||||
serverlist = config['DEFAULT']['MAINNET_BLOCKBOOK_SERVER_LIST']
|
||||
elif config['DEFAULT']['NET'] == 'testnet':
|
||||
serverlist = config['DEFAULT']['TESTNET_FLOSIGHT_SERVER_LIST']
|
||||
serverlist = config['DEFAULT']['TESTNET_BLOCKBOOK_SERVER_LIST']
|
||||
serverlist = serverlist.split(',')
|
||||
neturl = config['DEFAULT']['FLOSIGHT_NETURL']
|
||||
neturl = config['DEFAULT']['BLOCKBOOK_NETURL']
|
||||
tokenapi_sse_url = config['DEFAULT']['TOKENAPI_SSE_URL']
|
||||
|
||||
# Delete database and smartcontract directory if reset is set to 1
|
||||
|
||||
@ -2,7 +2,7 @@ from sqlalchemy import create_engine, desc, func
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from models import SystemData, TokenBase, ActiveTable, ConsumedTable, TransferLogs, TransactionHistory, TokenContractAssociation, ContractBase, ContractStructure, ContractParticipants, ContractTransactionHistory, ContractDeposits, ConsumedInfo, ContractWinners, ContinuosContractBase, ContractStructure2, ContractParticipants2, ContractDeposits2, ContractTransactionHistory2, SystemBase, ActiveContracts, SystemData, ContractAddressMapping, TokenAddressMapping, DatabaseTypeMapping, TimeActions, RejectedContractTransactionHistory, RejectedTransactionHistory, LatestCacheBase, LatestTransactions, LatestBlocks
|
||||
import json
|
||||
from tracktokens_smartcontracts import processTransaction, checkLocal_expiry_trigger_deposit, newMultiRequest
|
||||
from backend_main import processTransaction, checkLocal_expiry_trigger_deposit, newMultiRequest
|
||||
import os
|
||||
import logging
|
||||
import argparse
|
||||
@ -131,11 +131,11 @@ if (config['DEFAULT']['NET'] != 'mainnet') and (config['DEFAULT']['NET'] != 'tes
|
||||
# Specify mainnet and testnet server list for API calls and websocket calls
|
||||
serverlist = None
|
||||
if config['DEFAULT']['NET'] == 'mainnet':
|
||||
serverlist = config['DEFAULT']['MAINNET_FLOSIGHT_SERVER_LIST']
|
||||
serverlist = config['DEFAULT']['MAINNET_BLOCKBOOK_SERVER_LIST']
|
||||
elif config['DEFAULT']['NET'] == 'testnet':
|
||||
serverlist = config['DEFAULT']['TESTNET_FLOSIGHT_SERVER_LIST']
|
||||
serverlist = config['DEFAULT']['TESTNET_BLOCKBOOK_SERVER_LIST']
|
||||
serverlist = serverlist.split(',')
|
||||
neturl = config['DEFAULT']['FLOSIGHT_NETURL']
|
||||
neturl = config['DEFAULT']['BLOCKBOOK_NETURL']
|
||||
tokenapi_sse_url = config['DEFAULT']['TOKENAPI_SSE_URL']
|
||||
|
||||
# Delete database and smartcontract directory if reset is set to 1
|
||||
|
||||
@ -2,7 +2,7 @@ from sqlalchemy import create_engine, desc, func
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from models import SystemData, TokenBase, ActiveTable, ConsumedTable, TransferLogs, TransactionHistory, TokenContractAssociation, ContractBase, ContractStructure, ContractParticipants, ContractTransactionHistory, ContractDeposits, ConsumedInfo, ContractWinners, ContinuosContractBase, ContractStructure2, ContractParticipants2, ContractDeposits2, ContractTransactionHistory2, SystemBase, ActiveContracts, SystemData, ContractAddressMapping, TokenAddressMapping, DatabaseTypeMapping, TimeActions, RejectedContractTransactionHistory, RejectedTransactionHistory, LatestCacheBase, LatestTransactions, LatestBlocks
|
||||
import json
|
||||
from tracktokens_smartcontracts import processTransaction, checkLocal_expiry_trigger_deposit, newMultiRequest
|
||||
from backend_main import processTransaction, checkLocal_expiry_trigger_deposit, newMultiRequest
|
||||
import os
|
||||
import logging
|
||||
import argparse
|
||||
@ -95,11 +95,11 @@ if (config['DEFAULT']['NET'] != 'mainnet') and (config['DEFAULT']['NET'] != 'tes
|
||||
# Specify mainnet and testnet server list for API calls and websocket calls
|
||||
serverlist = None
|
||||
if config['DEFAULT']['NET'] == 'mainnet':
|
||||
serverlist = config['DEFAULT']['MAINNET_FLOSIGHT_SERVER_LIST']
|
||||
serverlist = config['DEFAULT']['MAINNET_BLOCKBOOK_SERVER_LIST']
|
||||
elif config['DEFAULT']['NET'] == 'testnet':
|
||||
serverlist = config['DEFAULT']['TESTNET_FLOSIGHT_SERVER_LIST']
|
||||
serverlist = config['DEFAULT']['TESTNET_BLOCKBOOK_SERVER_LIST']
|
||||
serverlist = serverlist.split(',')
|
||||
neturl = config['DEFAULT']['FLOSIGHT_NETURL']
|
||||
neturl = config['DEFAULT']['BLOCKBOOK_NETURL']
|
||||
tokenapi_sse_url = config['DEFAULT']['TOKENAPI_SSE_URL']
|
||||
|
||||
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import argparse
|
||||
from sqlalchemy import create_engine, func
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from models import SystemData, TokenBase, ActiveTable, ConsumedTable, TransferLogs, TransactionHistory, TokenContractAssociation, RejectedTransactionHistory, ContractBase, ContractStructure, ContractParticipants, ContractTransactionHistory, ContractDeposits, ConsumedInfo, ContractWinners, ContinuosContractBase, ContractStructure2, ContractParticipants2, ContractDeposits2, ContractTransactionHistory2, SystemBase, ActiveContracts, SystemData, ContractAddressMapping, TokenAddressMapping, DatabaseTypeMapping, TimeActions, RejectedContractTransactionHistory, RejectedTransactionHistory, LatestCacheBase, LatestTransactions, LatestBlocks
|
||||
from src.backend.models import SystemData, TokenBase, ActiveTable, ConsumedTable, TransferLogs, TransactionHistory, TokenContractAssociation, RejectedTransactionHistory, ContractBase, ContractStructure, ContractParticipants, ContractTransactionHistory, ContractDeposits, ConsumedInfo, ContractWinners, ContinuosContractBase, ContractStructure2, ContractParticipants2, ContractDeposits2, ContractTransactionHistory2, SystemBase, ActiveContracts, SystemData, ContractAddressMapping, TokenAddressMapping, DatabaseTypeMapping, TimeActions, RejectedContractTransactionHistory, RejectedTransactionHistory, LatestCacheBase, LatestTransactions, LatestBlocks
|
||||
from ast import literal_eval
|
||||
import os
|
||||
import json
|
||||
import logging
|
||||
import sys
|
||||
from parsing import perform_decimal_operation
|
||||
from src.backend.parsing import perform_decimal_operation
|
||||
|
||||
|
||||
apppath = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
52
src/flags.py
Normal file
52
src/flags.py
Normal file
@ -0,0 +1,52 @@
|
||||
FLAGS = {}
|
||||
|
||||
FLAGS["is_running"] = None
|
||||
FLAGS["is_backend_active"] = None
|
||||
FLAGS["is_backend_syncing"] = None
|
||||
FLAGS["is_backend_ready"] = None
|
||||
FLAGS["is_api_server_active"] = None
|
||||
|
||||
def is_running():
|
||||
return bool(FLAGS["is_running"])
|
||||
|
||||
def set_run_start():
|
||||
FLAGS["is_running"] = True
|
||||
|
||||
def set_run_stop():
|
||||
FLAGS["is_running"] = False
|
||||
|
||||
def set_backend_start():
|
||||
FLAGS["is_backend_active"] = True
|
||||
|
||||
def set_backend_stop():
|
||||
FLAGS["is_backend_active"] = False
|
||||
|
||||
def is_backend_active():
|
||||
return bool(FLAGS["is_backend_active"])
|
||||
|
||||
def set_backend_sync_start():
|
||||
FLAGS["is_backend_syncing"] = True
|
||||
|
||||
def set_backend_sync_stop():
|
||||
FLAGS["is_backend_syncing"] = False
|
||||
|
||||
def is_backend_syncing():
|
||||
return bool(FLAGS["is_backend_syncing"])
|
||||
|
||||
def set_backend_ready():
|
||||
FLAGS["is_backend_ready"] = True
|
||||
|
||||
def set_backend_not_ready():
|
||||
FLAGS["is_backend_ready"] = False
|
||||
|
||||
def is_backend_ready():
|
||||
return bool(FLAGS["is_backend_ready"])
|
||||
|
||||
def set_api_start():
|
||||
FLAGS["is_api_server_active"] = True
|
||||
|
||||
def set_api_stop():
|
||||
FLAGS["is_api_server_active"] = False
|
||||
|
||||
def is_api_active():
|
||||
return bool(FLAGS["is_api_server_active"])
|
||||
Loading…
Reference in New Issue
Block a user