Compare commits

...

10 Commits

Author SHA1 Message Date
Vivek Teega
836de91fb3 Bug fixes + cleanup 2024-08-16 06:28:54 +00:00
Sai Raj
4293c79e63 bug fixes 2024-08-12 21:31:41 -04:00
Sai Raj
a71c15fe6c Adding flags to indicate status of backend
- API responses now have a warning message if backend is still syncing
- API v2 responses now have HTTP codes 200, 206, 400, 404, 500, 503
200: response is ok
206: reponse is ok, but backend is still syncing, thus data might not be final
404: data not found error
503: data not found, but backend is still syncing
400: client request error
500: internal server error
2024-08-12 21:09:08 -04:00
Sai Raj
63e5a0da87 Multi-threaded fetches for scanning blocks
- speedup scanBlocks using batch fetch threading from API
- fixes for check_for_reorg and process restart when reorg happens
2024-08-09 01:02:18 -04:00
Sai Raj
1b9f75ebb4 thread bug fix for sqlite 2024-08-03 17:37:15 -04:00
Sai Raj
40f43aefb2 bug fix 2024-08-03 16:06:30 -04:00
Sai Raj
fff6824b30 Threading and bug fixes 2024-08-03 15:59:03 -04:00
Sai Raj
c8881c23de Uploading the main file for combine system
main file to process the config file and start the backend process and then API server
2024-07-18 05:59:44 -04:00
Sai Raj
ac5913d3a1 rename tokenscanner py file to backend_main.py 2024-07-18 05:35:26 -04:00
Sai Raj
0c5365b510 Update flosights ro blockbook 2024-07-18 05:32:38 -04:00
10 changed files with 612 additions and 228 deletions

View File

@ -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
View 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()

View File

@ -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)

View File

@ -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)
"""

View File

@ -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')

View File

@ -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

View File

@ -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

View File

@ -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']

View File

@ -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
View 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"])