New year commit
This commit is contained in:
parent
79b45e4cec
commit
77628d206a
43
parsing.py
43
parsing.py
@ -1,5 +1,9 @@
|
|||||||
import re
|
import re
|
||||||
import arrow
|
import arrow
|
||||||
|
import configparser
|
||||||
|
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read('config.ini')
|
||||||
|
|
||||||
marker = None
|
marker = None
|
||||||
operation = None
|
operation = None
|
||||||
@ -164,7 +168,7 @@ def extractContractConditions(text, contracttype, marker, blocktime):
|
|||||||
rulelist = []
|
rulelist = []
|
||||||
numberList = re.findall(r'\(\d\d*\)', rulestext)
|
numberList = re.findall(r'\(\d\d*\)', rulestext)
|
||||||
|
|
||||||
for idx,item in enumerate(numberList):
|
for idx, item in enumerate(numberList):
|
||||||
numberList[idx] = int(item[1:-1])
|
numberList[idx] = int(item[1:-1])
|
||||||
|
|
||||||
numberList = sorted(numberList)
|
numberList = sorted(numberList)
|
||||||
@ -198,7 +202,7 @@ def extractContractConditions(text, contracttype, marker, blocktime):
|
|||||||
return None
|
return None
|
||||||
extractedRules['expiryTime'] = expirytime
|
extractedRules['expiryTime'] = expirytime
|
||||||
except:
|
except:
|
||||||
print('Expiry time not in right format')
|
print('Error parsing expiry time')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for rule in rulelist:
|
for rule in rulelist:
|
||||||
@ -211,7 +215,7 @@ def extractContractConditions(text, contracttype, marker, blocktime):
|
|||||||
try:
|
try:
|
||||||
extractedRules['contractAmount'] = float(contractamount)
|
extractedRules['contractAmount'] = float(contractamount)
|
||||||
except:
|
except:
|
||||||
print("something is wrong with contract amount entered")
|
print("Contract amount entered is not a decimal")
|
||||||
elif rule[:11] == 'userchoices':
|
elif rule[:11] == 'userchoices':
|
||||||
pattern = re.compile('[^userchoices\s*=\s*].*')
|
pattern = re.compile('[^userchoices\s*=\s*].*')
|
||||||
conditions = pattern.search(rule).group(0)
|
conditions = pattern.search(rule).group(0)
|
||||||
@ -226,7 +230,7 @@ def extractContractConditions(text, contracttype, marker, blocktime):
|
|||||||
try:
|
try:
|
||||||
extractedRules['minimumsubscriptionamount'] = float(minimumsubscriptionamount)
|
extractedRules['minimumsubscriptionamount'] = float(minimumsubscriptionamount)
|
||||||
except:
|
except:
|
||||||
print("something is wrong with minimum subscription amount entered")
|
print("Minimum subscription amount entered is not a decimal")
|
||||||
elif rule[:25] == 'maximumsubscriptionamount':
|
elif rule[:25] == 'maximumsubscriptionamount':
|
||||||
pattern = re.compile('[^maximumsubscriptionamount\s*=\s*].*')
|
pattern = re.compile('[^maximumsubscriptionamount\s*=\s*].*')
|
||||||
searchResult = pattern.search(rule).group(0)
|
searchResult = pattern.search(rule).group(0)
|
||||||
@ -234,8 +238,8 @@ def extractContractConditions(text, contracttype, marker, blocktime):
|
|||||||
try:
|
try:
|
||||||
extractedRules['maximumsubscriptionamount'] = float(maximumsubscriptionamount)
|
extractedRules['maximumsubscriptionamount'] = float(maximumsubscriptionamount)
|
||||||
except:
|
except:
|
||||||
print("something is wrong with maximum subscription amount entered")
|
print("Maximum subscription amount entered is not a decimal")
|
||||||
elif rule[:12] == 'payeeAddress':
|
elif rule[:12] == 'payeeaddress':
|
||||||
pattern = re.compile('[^payeeAddress\s*=\s*].*')
|
pattern = re.compile('[^payeeAddress\s*=\s*].*')
|
||||||
searchResult = pattern.search(rule).group(0)
|
searchResult = pattern.search(rule).group(0)
|
||||||
payeeAddress = searchResult.split(marker)[0]
|
payeeAddress = searchResult.split(marker)[0]
|
||||||
@ -258,7 +262,7 @@ def extractTriggerCondition(text):
|
|||||||
|
|
||||||
|
|
||||||
# Combine test
|
# Combine test
|
||||||
def parse_flodata(string, blockinfo):
|
def parse_flodata(string, blockinfo, netvariable):
|
||||||
|
|
||||||
# todo Rule 20 - remove 'text:' from the start of flodata if it exists
|
# todo Rule 20 - remove 'text:' from the start of flodata if it exists
|
||||||
if string[0:5] == 'text:':
|
if string[0:5] == 'text:':
|
||||||
@ -319,7 +323,7 @@ def parse_flodata(string, blockinfo):
|
|||||||
parsed_data = {'type': 'noise'}
|
parsed_data = {'type': 'noise'}
|
||||||
|
|
||||||
# todo Rule 32 - if number of # is 1 and number of @ is 1, then process for smart contract transfer or creation
|
# todo Rule 32 - if number of # is 1 and number of @ is 1, then process for smart contract transfer or creation
|
||||||
elif len(hashList)==1 and len(atList)==1:
|
elif len(hashList) == 1 and len(atList) == 1:
|
||||||
# Passing the above check means Smart Contract creation or transfer
|
# Passing the above check means Smart Contract creation or transfer
|
||||||
incorporation = isIncorp(cleanstring)
|
incorporation = isIncorp(cleanstring)
|
||||||
transfer = isTransfer(cleanstring)
|
transfer = isTransfer(cleanstring)
|
||||||
@ -334,13 +338,22 @@ def parse_flodata(string, blockinfo):
|
|||||||
contractaddress = extractAddress(nospacestring)
|
contractaddress = extractAddress(nospacestring)
|
||||||
contractconditions = extractContractConditions(cleanstring, contracttype, marker=hashList[0][:-1], blocktime=blockinfo['time'])
|
contractconditions = extractContractConditions(cleanstring, contracttype, marker=hashList[0][:-1], blocktime=blockinfo['time'])
|
||||||
|
|
||||||
if None not in [contracttype, contractaddress, contractconditions]:
|
if config['DEFAULT']['NET'] == 'mainnet' and blockinfo['height'] < 3454510:
|
||||||
parsed_data = {'type': 'smartContractIncorporation', 'contractType': contracttype[:-1],
|
if None not in [contracttype, contractconditions]:
|
||||||
'tokenIdentification': hashList[0][:-1], 'contractName': atList[0][:-1],
|
parsed_data = {'type': 'smartContractIncorporation', 'contractType': contracttype[:-1],
|
||||||
'contractAddress': contractaddress[:-1], 'flodata': string,
|
'tokenIdentification': hashList[0][:-1], 'contractName': atList[0][:-1],
|
||||||
'contractConditions': contractconditions}
|
'contractAddress': contractaddress[:-1], 'flodata': string,
|
||||||
|
'contractConditions': contractconditions}
|
||||||
|
else:
|
||||||
|
parsed_data = {'type': 'noise'}
|
||||||
else:
|
else:
|
||||||
parsed_data = {'type': 'noise'}
|
if None not in [contracttype, contractaddress, contractconditions]:
|
||||||
|
parsed_data = {'type': 'smartContractIncorporation', 'contractType': contracttype[:-1],
|
||||||
|
'tokenIdentification': hashList[0][:-1], 'contractName': atList[0][:-1],
|
||||||
|
'contractAddress': contractaddress[:-1], 'flodata': string,
|
||||||
|
'contractConditions': contractconditions}
|
||||||
|
else:
|
||||||
|
parsed_data = {'type': 'noise'}
|
||||||
|
|
||||||
# todo Rule 35 - if it is not incorporation and it is transfer, then extract smart contract amount to be locked and userPreference. If any of them is missing, then reject
|
# todo Rule 35 - if it is not incorporation and it is transfer, then extract smart contract amount to be locked and userPreference. If any of them is missing, then reject
|
||||||
elif not incorporation and transfer:
|
elif not incorporation and transfer:
|
||||||
@ -367,7 +380,7 @@ def parse_flodata(string, blockinfo):
|
|||||||
if triggerCondition is not None:
|
if triggerCondition is not None:
|
||||||
parsed_data = {'type': 'smartContractPays', 'contractName': atList[0][:-1], 'triggerCondition': triggerCondition.group().strip()[1:-1]}
|
parsed_data = {'type': 'smartContractPays', 'contractName': atList[0][:-1], 'triggerCondition': triggerCondition.group().strip()[1:-1]}
|
||||||
else:
|
else:
|
||||||
parsed_data = {'type':'noise'}
|
parsed_data = {'type': 'noise'}
|
||||||
else:
|
else:
|
||||||
parsed_data = {'type': 'noise'}
|
parsed_data = {'type': 'noise'}
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,34 @@ app.clients = set()
|
|||||||
app = cors(app, allow_origin="*")
|
app = cors(app, allow_origin="*")
|
||||||
|
|
||||||
|
|
||||||
|
# helper functions
|
||||||
|
def retryRequest(tempserverlist, apicall):
|
||||||
|
if len(tempserverlist)!=0:
|
||||||
|
try:
|
||||||
|
response = requests.get('{}api/{}'.format(tempserverlist[0], apicall))
|
||||||
|
except:
|
||||||
|
tempserverlist.pop(0)
|
||||||
|
return retryRequest(tempserverlist, apicall)
|
||||||
|
else:
|
||||||
|
if response.status_code == 200:
|
||||||
|
return json.loads(response.content)
|
||||||
|
else:
|
||||||
|
tempserverlist.pop(0)
|
||||||
|
return retryRequest(tempserverlist, apicall)
|
||||||
|
else:
|
||||||
|
logger.error("None of the APIs are responding for the call {}".format(apicall))
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
def multiRequest(apicall, net):
|
||||||
|
testserverlist = ['http://0.0.0.0:9000/', 'https://testnet.flocha.in/', 'https://testnet-flosight.duckdns.org/']
|
||||||
|
mainserverlist = ['http://0.0.0.0:9001/', 'https://livenet.flocha.in/', 'https://testnet-flosight.duckdns.org/']
|
||||||
|
if net == 'mainnet':
|
||||||
|
return retryRequest(mainserverlist, apicall)
|
||||||
|
elif net == 'testnet':
|
||||||
|
return retryRequest(testserverlist, apicall)
|
||||||
|
|
||||||
|
|
||||||
# FLO TOKEN APIs
|
# FLO TOKEN APIs
|
||||||
|
|
||||||
@app.route('/api/v1.0/getTokenList', methods=['GET'])
|
@app.route('/api/v1.0/getTokenList', methods=['GET'])
|
||||||
@ -48,17 +76,32 @@ async def getTokenInfo():
|
|||||||
conn = sqlite3.connect(dblocation)
|
conn = sqlite3.connect(dblocation)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
else:
|
else:
|
||||||
return 'Token doesn\'t exist'
|
return jsonify(result='error', description='token doesn\'t exist')
|
||||||
c.execute('SELECT * FROM transactionHistory WHERE id=1')
|
c.execute('SELECT * FROM transactionHistory WHERE id=1')
|
||||||
incorporationRow = c.fetchall()[0]
|
incorporationRow = c.fetchall()[0]
|
||||||
c.execute('SELECT COUNT (DISTINCT address) FROM activeTable')
|
c.execute('SELECT COUNT (DISTINCT address) FROM activeTable')
|
||||||
numberOf_distinctAddresses = c.fetchall()[0][0]
|
numberOf_distinctAddresses = c.fetchall()[0][0]
|
||||||
c.execute('select max(id) from transactionHistory')
|
c.execute('select max(id) from transactionHistory')
|
||||||
numberOf_transactions = c.fetchall()[0][0]
|
numberOf_transactions = c.fetchall()[0][0]
|
||||||
|
c.execute(
|
||||||
|
'select contractName, contractAddress, blockNumber, blockHash, transactionHash from tokenContractAssociation')
|
||||||
|
associatedContracts = c.fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
associatedContractList = []
|
||||||
|
for item in associatedContracts:
|
||||||
|
tempdict = {}
|
||||||
|
item = list(item)
|
||||||
|
tempdict['contractName'] = item[0]
|
||||||
|
tempdict['contractAddress'] = item[1]
|
||||||
|
tempdict['blockNumber'] = item[2]
|
||||||
|
tempdict['blockHash'] = item[3]
|
||||||
|
tempdict['transactionHash'] = item[4]
|
||||||
|
associatedContractList.append(tempdict)
|
||||||
|
|
||||||
return jsonify(result='ok', token=token, incorporationAddress=incorporationRow[1], tokenSupply=incorporationRow[3],
|
return jsonify(result='ok', token=token, incorporationAddress=incorporationRow[1], tokenSupply=incorporationRow[3],
|
||||||
transactionHash=incorporationRow[6], blockchainReference=incorporationRow[7],
|
transactionHash=incorporationRow[6], blockchainReference=incorporationRow[7],
|
||||||
activeAddress_no=numberOf_distinctAddresses, totalTransactions = numberOf_transactions)
|
activeAddress_no=numberOf_distinctAddresses, totalTransactions = numberOf_transactions, associatedSmartContracts=associatedContractList)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/v1.0/getTokenTransactions', methods=['GET'])
|
@app.route('/api/v1.0/getTokenTransactions', methods=['GET'])
|
||||||
@ -68,7 +111,6 @@ async def getTokenTransactions():
|
|||||||
destFloAddress = request.args.get('destFloAddress')
|
destFloAddress = request.args.get('destFloAddress')
|
||||||
limit = request.args.get('limit')
|
limit = request.args.get('limit')
|
||||||
|
|
||||||
|
|
||||||
if token is None:
|
if token is None:
|
||||||
return jsonify(result='error')
|
return jsonify(result='error')
|
||||||
|
|
||||||
@ -78,46 +120,46 @@ async def getTokenTransactions():
|
|||||||
conn.row_factory = sqlite3.Row
|
conn.row_factory = sqlite3.Row
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
else:
|
else:
|
||||||
return 'Token doesn\'t exist'
|
return jsonify(result='error', description='token doesn\'t exist')
|
||||||
|
|
||||||
if senderFloAddress and not destFloAddress:
|
if senderFloAddress and not destFloAddress:
|
||||||
if limit is None:
|
if limit is None:
|
||||||
c.execute('SELECT blockNumber, sourceFloAddress, destFloAddress, transferAmount, blockchainReference, transactionHash FROM transactionHistory WHERE sourceFloAddress="{}" ORDER BY id DESC LIMIT 100'.format(senderFloAddress))
|
c.execute('SELECT jsonData FROM transactionHistory WHERE sourceFloAddress="{}" ORDER BY id DESC LIMIT 100'.format(senderFloAddress))
|
||||||
else:
|
else:
|
||||||
c.execute('SELECT blockNumber, sourceFloAddress, destFloAddress, transferAmount, blockchainReference, transactionHash FROM transactionHistory WHERE sourceFloAddress="{}" ORDER BY id DESC LIMIT {}'.format(senderFloAddress,limit))
|
c.execute('SELECT jsonData FROM transactionHistory WHERE sourceFloAddress="{}" ORDER BY id DESC LIMIT {}'.format(senderFloAddress,limit))
|
||||||
elif not senderFloAddress and destFloAddress:
|
elif not senderFloAddress and destFloAddress:
|
||||||
if limit is None:
|
if limit is None:
|
||||||
c.execute(
|
c.execute(
|
||||||
'SELECT blockNumber, sourceFloAddress, destFloAddress, transferAmount, blockchainReference, transactionHash FROM transactionHistory WHERE destFloAddress="{}" ORDER BY id DESC LIMIT 100'.format(
|
'SELECT jsonData FROM transactionHistory WHERE destFloAddress="{}" ORDER BY id DESC LIMIT 100'.format(
|
||||||
destFloAddress))
|
destFloAddress))
|
||||||
else:
|
else:
|
||||||
c.execute(
|
c.execute(
|
||||||
'SELECT blockNumber, sourceFloAddress, destFloAddress, transferAmount, blockchainReference, transactionHash FROM transactionHistory WHERE destFloAddress="{}" ORDER BY id DESC LIMIT {}'.format(
|
'SELECT jsonData FROM transactionHistory WHERE destFloAddress="{}" ORDER BY id DESC LIMIT {}'.format(
|
||||||
destFloAddress, limit))
|
destFloAddress, limit))
|
||||||
elif senderFloAddress and destFloAddress:
|
elif senderFloAddress and destFloAddress:
|
||||||
if limit is None:
|
if limit is None:
|
||||||
c.execute(
|
c.execute(
|
||||||
'SELECT blockNumber, sourceFloAddress, destFloAddress, transferAmount, blockchainReference, transactionHash FROM transactionHistory WHERE sourceFloAddress="{}" AND destFloAddress="{}" ORDER BY id DESC LIMIT 100'.format(
|
'SELECT jsonData FROM transactionHistory WHERE sourceFloAddress="{}" AND destFloAddress="{}" ORDER BY id DESC LIMIT 100'.format(
|
||||||
senderFloAddress, destFloAddress))
|
senderFloAddress, destFloAddress))
|
||||||
else:
|
else:
|
||||||
c.execute(
|
c.execute(
|
||||||
'SELECT blockNumber, sourceFloAddress, destFloAddress, transferAmount, blockchainReference, transactionHash FROM transactionHistory WHERE sourceFloAddress="{}" AND destFloAddress="{}" ORDER BY id DESC LIMIT {}'.format(
|
'SELECT jsonData FROM transactionHistory WHERE sourceFloAddress="{}" AND destFloAddress="{}" ORDER BY id DESC LIMIT {}'.format(
|
||||||
senderFloAddress, destFloAddress, limit))
|
senderFloAddress, destFloAddress, limit))
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if limit is None:
|
if limit is None:
|
||||||
c.execute(
|
c.execute(
|
||||||
'SELECT blockNumber, sourceFloAddress, destFloAddress, transferAmount, blockchainReference, transactionHash FROM transactionHistory ORDER BY id DESC LIMIT 100')
|
'SELECT jsonData FROM transactionHistory ORDER BY id DESC LIMIT 100')
|
||||||
else:
|
else:
|
||||||
c.execute(
|
c.execute(
|
||||||
'SELECT blockNumber, sourceFloAddress, destFloAddress, transferAmount, blockchainReference, transactionHash FROM transactionHistory ORDER BY id DESC LIMIT {}'.format(limit))
|
'SELECT jsonData FROM transactionHistory ORDER BY id DESC LIMIT {}'.format(limit))
|
||||||
latestTransactions = c.fetchall()
|
latestTransactions = c.fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
rowarray_list = []
|
rowarray_list = {}
|
||||||
for row in latestTransactions:
|
for row in latestTransactions:
|
||||||
d = dict(zip(row.keys(), row)) # a dict with column names as keys
|
jsonData = row[row.keys()[0]]
|
||||||
rowarray_list.append(d)
|
jsonData = json.loads(jsonData)
|
||||||
|
rowarray_list[jsonData['txid']]=jsonData
|
||||||
return jsonify(result='ok', token=token, transactions=rowarray_list)
|
return jsonify(result='ok', token=token, transactions=rowarray_list)
|
||||||
|
|
||||||
|
|
||||||
@ -132,23 +174,22 @@ async def getTokenBalances():
|
|||||||
conn = sqlite3.connect(dblocation)
|
conn = sqlite3.connect(dblocation)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
else:
|
else:
|
||||||
return 'Token doesn\'t exist'
|
return jsonify(result='error', description='token doesn\'t exist')
|
||||||
c.execute('SELECT address,SUM(transferBalance) FROM activeTable GROUP BY address')
|
c.execute('SELECT address,SUM(transferBalance) FROM activeTable GROUP BY address')
|
||||||
addressBalances = c.fetchall()
|
addressBalances = c.fetchall()
|
||||||
|
|
||||||
returnList = []
|
returnList = {}
|
||||||
|
|
||||||
for address in addressBalances:
|
for address in addressBalances:
|
||||||
tempdict = {}
|
returnList[address[0]] = address[1]
|
||||||
tempdict['floAddress'] = address[0]
|
|
||||||
tempdict['balance'] = address[1]
|
|
||||||
returnList.append(tempdict)
|
|
||||||
|
|
||||||
return jsonify(result='ok', token=token, balances=returnList)
|
return jsonify(result='ok', token=token, balances=returnList)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/v1.0/getFloAddressDetails', methods=['GET'])
|
# FLO address APIs
|
||||||
async def getFloAddressDetails():
|
|
||||||
|
@app.route('/api/v1.0/getFloAddressInfo', methods=['GET'])
|
||||||
|
async def getFloAddressInfo():
|
||||||
floAddress = request.args.get('floAddress')
|
floAddress = request.args.get('floAddress')
|
||||||
|
|
||||||
if floAddress is None:
|
if floAddress is None:
|
||||||
@ -161,8 +202,11 @@ async def getFloAddressDetails():
|
|||||||
c.execute('select token from tokenAddressMapping where tokenAddress="{}"'.format(floAddress))
|
c.execute('select token from tokenAddressMapping where tokenAddress="{}"'.format(floAddress))
|
||||||
tokenNames = c.fetchall()
|
tokenNames = c.fetchall()
|
||||||
|
|
||||||
|
c.execute(f"select contractName, status, tokenIdentification, contractType, transactionHash, blockNumber, blockHash from activecontracts where contractAddress='{floAddress}'")
|
||||||
|
incorporatedContracts = c.fetchall()
|
||||||
|
|
||||||
if len(tokenNames) != 0:
|
if len(tokenNames) != 0:
|
||||||
detailList = []
|
detailList = {}
|
||||||
|
|
||||||
for token in tokenNames:
|
for token in tokenNames:
|
||||||
token = token[0]
|
token = token[0]
|
||||||
@ -175,84 +219,133 @@ async def getFloAddressDetails():
|
|||||||
balance = c.fetchall()[0][0]
|
balance = c.fetchall()[0][0]
|
||||||
tempdict['balance'] = balance
|
tempdict['balance'] = balance
|
||||||
tempdict['token'] = token
|
tempdict['token'] = token
|
||||||
detailList.append(tempdict)
|
detailList[token] = tempdict
|
||||||
|
|
||||||
return jsonify(result='ok', floAddress=floAddress, floAddressDetails=detailList)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Address is not associated with any token
|
# Address is not associated with any token
|
||||||
return jsonify(result='error', description='FLO address is not associated with any tokens')
|
return jsonify(result='error', description='FLO address is not associated with any tokens')
|
||||||
|
|
||||||
|
if len(incorporatedContracts) != 0:
|
||||||
|
incorporatedSmartContracts = []
|
||||||
|
for contract in incorporatedContracts:
|
||||||
|
tempdict = {}
|
||||||
|
tempdict['contractName'] = contract[0]
|
||||||
|
tempdict['contractAddress'] = floAddress
|
||||||
|
tempdict['status'] = contract[1]
|
||||||
|
tempdict['tokenIdentification'] = contract[2]
|
||||||
|
tempdict['contractType'] = contract[3]
|
||||||
|
tempdict['transactionHash'] = contract[4]
|
||||||
|
tempdict['blockNumber'] = contract[5]
|
||||||
|
tempdict['blockHash'] = contract[6]
|
||||||
|
incorporatedSmartContracts.append(tempdict)
|
||||||
|
|
||||||
|
return jsonify(result='ok', floAddress=floAddress, floAddressBalances=detailList, incorporatedSmartContracts=incorporatedContracts)
|
||||||
|
else:
|
||||||
|
return jsonify(result='ok', floAddress=floAddress, floAddressBalances=detailList,
|
||||||
|
incorporatedSmartContracts=None)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/v1.0/getFloAddressBalance', methods=['GET'])
|
@app.route('/api/v1.0/getFloAddressBalance', methods=['GET'])
|
||||||
async def getAddressBalance():
|
async def getAddressBalance():
|
||||||
floAddress = request.args.get('floAddress')
|
floAddress = request.args.get('floAddress')
|
||||||
token = request.args.get('token')
|
token = request.args.get('token')
|
||||||
|
|
||||||
if floAddress is None or token is None:
|
if floAddress is None:
|
||||||
return jsonify(result='error')
|
return jsonify(result='error', description='floAddress hasn\'t been passed')
|
||||||
|
|
||||||
dblocation = dbfolder + '/tokens/' + str(token) + '.db'
|
if token is None:
|
||||||
if os.path.exists(dblocation):
|
dblocation = dbfolder + '/system.db'
|
||||||
conn = sqlite3.connect(dblocation)
|
if os.path.exists(dblocation):
|
||||||
c = conn.cursor()
|
conn = sqlite3.connect(dblocation)
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute('select token from tokenAddressMapping where tokenAddress="{}"'.format(floAddress))
|
||||||
|
tokenNames = c.fetchall()
|
||||||
|
|
||||||
|
if len(tokenNames) != 0:
|
||||||
|
detailList = {}
|
||||||
|
|
||||||
|
for token in tokenNames:
|
||||||
|
token = token[0]
|
||||||
|
dblocation = dbfolder + '/tokens/' + str(token) + '.db'
|
||||||
|
if os.path.exists(dblocation):
|
||||||
|
tempdict = {}
|
||||||
|
conn = sqlite3.connect(dblocation)
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute('SELECT SUM(transferBalance) FROM activeTable WHERE address="{}"'.format(floAddress))
|
||||||
|
balance = c.fetchall()[0][0]
|
||||||
|
tempdict['balance'] = balance
|
||||||
|
tempdict['token'] = token
|
||||||
|
detailList[token] = tempdict
|
||||||
|
|
||||||
|
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')
|
||||||
else:
|
else:
|
||||||
return 'Token doesn\'t exist'
|
dblocation = dbfolder + '/tokens/' + str(token) + '.db'
|
||||||
c.execute('SELECT SUM(transferBalance) FROM activeTable WHERE address="{}"'.format(floAddress))
|
if os.path.exists(dblocation):
|
||||||
balance = c.fetchall()[0][0]
|
conn = sqlite3.connect(dblocation)
|
||||||
conn.close()
|
c = conn.cursor()
|
||||||
return jsonify(result='ok', token=token, floAddress=floAddress, balance=balance)
|
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)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/v1.0/getFloAddressTransactions', methods=['GET'])
|
@app.route('/api/v1.0/getFloAddressTransactions', methods=['GET'])
|
||||||
async def getAddressTransactions():
|
async def getAddressTransactions():
|
||||||
floAddress = request.args.get('floAddress')
|
floAddress = request.args.get('floAddress')
|
||||||
|
token = request.args.get('token')
|
||||||
limit = request.args.get('limit')
|
limit = request.args.get('limit')
|
||||||
|
|
||||||
if floAddress is None:
|
if floAddress is None:
|
||||||
return jsonify(result='error', description='floAddress has not been passed')
|
return jsonify(result='error', description='floAddress has not been passed')
|
||||||
|
|
||||||
dblocation = dbfolder + '/system.db'
|
if token is None:
|
||||||
if os.path.exists(dblocation):
|
dblocation = dbfolder + '/system.db'
|
||||||
conn = sqlite3.connect(dblocation)
|
if os.path.exists(dblocation):
|
||||||
c = conn.cursor()
|
conn = sqlite3.connect(dblocation)
|
||||||
c.execute('select token from tokenAddressMapping where tokenAddress="{}"'.format(floAddress))
|
c = conn.cursor()
|
||||||
tokenNames = c.fetchall()
|
c.execute('select token from tokenAddressMapping where tokenAddress="{}"'.format(floAddress))
|
||||||
|
tokenNames = c.fetchall()
|
||||||
|
else:
|
||||||
|
dblocation = dbfolder + '/tokens/' + str(token) + '.db'
|
||||||
|
if os.path.exists(dblocation):
|
||||||
|
tokenNames = [[str(token),]]
|
||||||
|
else:
|
||||||
|
return jsonify(result='error', description='token doesn\'t exist')
|
||||||
|
|
||||||
|
|
||||||
if len(tokenNames) != 0:
|
if len(tokenNames) != 0:
|
||||||
allTransactionList = []
|
allTransactionList = {}
|
||||||
|
|
||||||
for token in tokenNames:
|
for tokenname in tokenNames:
|
||||||
token = token[0]
|
tokenname = tokenname[0]
|
||||||
dblocation = dbfolder + '/tokens/' + str(token) + '.db'
|
dblocation = dbfolder + '/tokens/' + str(tokenname) + '.db'
|
||||||
if os.path.exists(dblocation):
|
if os.path.exists(dblocation):
|
||||||
tempdict = {}
|
tempdict = {}
|
||||||
conn = sqlite3.connect(dblocation)
|
conn = sqlite3.connect(dblocation)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
if limit is None:
|
if limit is None:
|
||||||
c.execute('SELECT blockNumber, sourceFloAddress, destFloAddress, transferAmount, blockchainReference, transactionHash FROM transactionHistory ORDER BY id DESC LIMIT 100')
|
c.execute('SELECT jsonData FROM transactionHistory WHERE sourceFloAddress="{}" OR destFloAddress="{}" ORDER BY id DESC LIMIT 100'.format(floAddress, floAddress))
|
||||||
else:
|
else:
|
||||||
c.execute('SELECT blockNumber, sourceFloAddress, destFloAddress, transferAmount, blockchainReference, transactionHash FROM transactionHistory ORDER BY id DESC LIMIT {}'.format(limit))
|
c.execute('SELECT jsonData FROM transactionHistory WHERE sourceFloAddress="{}" OR destFloAddress="{}" ORDER BY id DESC LIMIT {}'.format(floAddress, floAddress, limit))
|
||||||
latestTransactions = c.fetchall()
|
latestTransactions = c.fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
rowarray_list = []
|
rowarray_list = []
|
||||||
for row in latestTransactions:
|
for row in latestTransactions:
|
||||||
row = list(row)
|
row = json.loads(row[0])
|
||||||
d = {}
|
row['token'] = str(tokenname)
|
||||||
d['blockNumber'] = row[0]
|
allTransactionList[row['txid']] = row
|
||||||
d['sourceFloAddress'] = row[1]
|
|
||||||
d['destFloAddress'] = row[2]
|
|
||||||
d['transferAmount'] = row[3]
|
|
||||||
d['blockchainReference'] = row[4]
|
|
||||||
d['transactionHash'] = row[5]
|
|
||||||
rowarray_list.append(d)
|
|
||||||
|
|
||||||
tempdict['token'] = token
|
if token is None:
|
||||||
tempdict['transactions'] = rowarray_list
|
return jsonify(result='ok', floAddress=floAddress, transactions=allTransactionList)
|
||||||
allTransactionList.append(tempdict)
|
else:
|
||||||
|
return jsonify(result='ok', floAddress=floAddress, transactions=allTransactionList, token=token)
|
||||||
return jsonify(result='ok', floAddress=floAddress, allTransactions=allTransactionList)
|
|
||||||
else:
|
else:
|
||||||
return jsonify(result='error', description='No token transactions present present on this address')
|
return jsonify(result='error', description='No token transactions present present on this address')
|
||||||
|
|
||||||
@ -277,12 +370,15 @@ async def getContractList():
|
|||||||
contractDict['contractName'] = contract[1]
|
contractDict['contractName'] = contract[1]
|
||||||
contractDict['contractAddress'] = contract[2]
|
contractDict['contractAddress'] = contract[2]
|
||||||
contractDict['status'] = contract[3]
|
contractDict['status'] = contract[3]
|
||||||
contractDict['transactionHash'] = contract[4]
|
contractDict['tokenIdentification'] = contract[4]
|
||||||
contractDict['incorporationDate'] = contract[5]
|
contractDict['contractType'] = contract[5]
|
||||||
if contract[6]:
|
contractDict['transactionHash'] = contract[6]
|
||||||
contractDict['expiryDate'] = contract[6]
|
contractDict['blockNumber'] = contract[7]
|
||||||
if contract[7]:
|
contractDict['incorporationDate'] = contract[8]
|
||||||
contractDict['closeDate'] = contract[7]
|
if contract[9]:
|
||||||
|
contractDict['expiryDate'] = contract[9]
|
||||||
|
if contract[10]:
|
||||||
|
contractDict['closeDate'] = contract[10]
|
||||||
|
|
||||||
contractList.append(contractDict)
|
contractList.append(contractDict)
|
||||||
|
|
||||||
@ -294,12 +390,15 @@ async def getContractList():
|
|||||||
contractDict['contractName'] = contract[1]
|
contractDict['contractName'] = contract[1]
|
||||||
contractDict['contractAddress'] = contract[2]
|
contractDict['contractAddress'] = contract[2]
|
||||||
contractDict['status'] = contract[3]
|
contractDict['status'] = contract[3]
|
||||||
contractDict['transactionHash'] = contract[4]
|
contractDict['tokenIdentification'] = contract[4]
|
||||||
contractDict['incorporationDate'] = contract[5]
|
contractDict['contractType'] = contract[5]
|
||||||
if contract[6]:
|
contractDict['transactionHash'] = contract[6]
|
||||||
contractDict['expiryDate'] = contract[6]
|
contractDict['blockNumber'] = contract[7]
|
||||||
if contract[7]:
|
contractDict['incorporationDate'] = contract[8]
|
||||||
contractDict['closeDate'] = contract[7]
|
if contract[9]:
|
||||||
|
contractDict['expiryDate'] = contract[9]
|
||||||
|
if contract[10]:
|
||||||
|
contractDict['closeDate'] = contract[10]
|
||||||
|
|
||||||
contractList.append(contractDict)
|
contractList.append(contractDict)
|
||||||
|
|
||||||
@ -311,12 +410,15 @@ async def getContractList():
|
|||||||
contractDict['contractName'] = contract[1]
|
contractDict['contractName'] = contract[1]
|
||||||
contractDict['contractAddress'] = contract[2]
|
contractDict['contractAddress'] = contract[2]
|
||||||
contractDict['status'] = contract[3]
|
contractDict['status'] = contract[3]
|
||||||
contractDict['transactionHash'] = contract[4]
|
contractDict['tokenIdentification'] = contract[4]
|
||||||
contractDict['incorporationDate'] = contract[5]
|
contractDict['contractType'] = contract[5]
|
||||||
if contract[6]:
|
contractDict['transactionHash'] = contract[6]
|
||||||
contractDict['expiryDate'] = contract[6]
|
contractDict['blockNumber'] = contract[7]
|
||||||
if contract[7]:
|
contractDict['incorporationDate'] = contract[8]
|
||||||
contractDict['closeDate'] = contract[7]
|
if contract[9]:
|
||||||
|
contractDict['expiryDate'] = contract[9]
|
||||||
|
if contract[10]:
|
||||||
|
contractDict['closeDate'] = contract[10]
|
||||||
|
|
||||||
contractList.append(contractDict)
|
contractList.append(contractDict)
|
||||||
|
|
||||||
@ -328,12 +430,15 @@ async def getContractList():
|
|||||||
contractDict['contractName'] = contract[1]
|
contractDict['contractName'] = contract[1]
|
||||||
contractDict['contractAddress'] = contract[2]
|
contractDict['contractAddress'] = contract[2]
|
||||||
contractDict['status'] = contract[3]
|
contractDict['status'] = contract[3]
|
||||||
contractDict['transactionHash'] = contract[4]
|
contractDict['tokenIdentification'] = contract[4]
|
||||||
contractDict['incorporationDate'] = contract[5]
|
contractDict['contractType'] = contract[5]
|
||||||
if contract[6]:
|
contractDict['transactionHash'] = contract[6]
|
||||||
contractDict['expiryDate'] = contract[6]
|
contractDict['blockNumber'] = contract[7]
|
||||||
if contract[7]:
|
contractDict['incorporationDate'] = contract[8]
|
||||||
contractDict['closeDate'] = contract[7]
|
if contract[9]:
|
||||||
|
contractDict['expiryDate'] = contract[9]
|
||||||
|
if contract[10]:
|
||||||
|
contractDict['closeDate'] = contract[10]
|
||||||
|
|
||||||
contractList.append(contractDict)
|
contractList.append(contractDict)
|
||||||
|
|
||||||
@ -362,17 +467,23 @@ async def getContractInfo():
|
|||||||
'SELECT attribute,value FROM contractstructure')
|
'SELECT attribute,value FROM contractstructure')
|
||||||
result = c.fetchall()
|
result = c.fetchall()
|
||||||
|
|
||||||
returnval = {'userChoice': []}
|
contractStructure = {}
|
||||||
temp = 0
|
conditionDict = {}
|
||||||
for row in result:
|
counter = 0
|
||||||
if row[0] == 'exitconditions':
|
for item in result:
|
||||||
if temp == 0:
|
if list(item)[0] == 'exitconditions':
|
||||||
returnval["userChoice"] = [row[1]]
|
conditionDict[counter] = list(item)[1]
|
||||||
temp = temp + 1
|
counter = counter + 1
|
||||||
else:
|
else:
|
||||||
returnval['userChoice'].append(row[1])
|
contractStructure[list(item)[0]] = list(item)[1]
|
||||||
continue
|
if len(conditionDict) > 0:
|
||||||
returnval[row[0]] = row[1]
|
contractStructure['exitconditions'] = conditionDict
|
||||||
|
del counter, conditionDict
|
||||||
|
|
||||||
|
returnval = contractStructure
|
||||||
|
returnval['userChoice'] = contractStructure['exitconditions']
|
||||||
|
returnval.pop('exitconditions')
|
||||||
|
|
||||||
|
|
||||||
c.execute('select count(participantAddress) from contractparticipants')
|
c.execute('select count(participantAddress) from contractparticipants')
|
||||||
noOfParticipants = c.fetchall()[0][0]
|
noOfParticipants = c.fetchall()[0][0]
|
||||||
@ -383,6 +494,7 @@ async def getContractInfo():
|
|||||||
returnval['tokenAmountDeposited'] = totalAmount
|
returnval['tokenAmountDeposited'] = totalAmount
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
|
||||||
conn = sqlite3.connect(os.path.join(dbfolder, 'system.db'))
|
conn = sqlite3.connect(os.path.join(dbfolder, 'system.db'))
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute('select status, incorporationDate, expiryDate, closeDate from activecontracts where contractName=="{}" and contractAddress=="{}"'.format(contractName.strip(), contractAddress.strip()))
|
c.execute('select status, incorporationDate, expiryDate, closeDate from activecontracts where contractName=="{}" and contractAddress=="{}"'.format(contractName.strip(), contractAddress.strip()))
|
||||||
@ -397,6 +509,40 @@ async def getContractInfo():
|
|||||||
if result[3]:
|
if result[3]:
|
||||||
returnval['closeDate'] = result[3]
|
returnval['closeDate'] = result[3]
|
||||||
|
|
||||||
|
if returnval['status'] == 'closed':
|
||||||
|
conn = sqlite3.connect(filelocation)
|
||||||
|
c = conn.cursor()
|
||||||
|
if returnval['contractType'] == 'one-time-event':
|
||||||
|
# pull out trigger information
|
||||||
|
# check if the trigger was succesful or failed
|
||||||
|
c.execute(
|
||||||
|
f"select transactionType, transactionSubType from contractTransactionHistory where transactionType='trigger'")
|
||||||
|
triggerntype = c.fetchall()
|
||||||
|
|
||||||
|
if len(triggerntype) == 1:
|
||||||
|
triggerntype = list(triggerntype[0])
|
||||||
|
|
||||||
|
returnval['triggerType'] = triggerntype[1]
|
||||||
|
|
||||||
|
if 'userChoice' in returnval:
|
||||||
|
# Contract is of the type external trigger
|
||||||
|
if triggerntype[0]=='trigger' and triggerntype[1] is None:
|
||||||
|
# this is a normal trigger
|
||||||
|
|
||||||
|
# find the winning condition
|
||||||
|
c.execute('select userchoice from contractparticipants where winningAmount is not null limit 1')
|
||||||
|
returnval['winningChoice'] = c.fetchall()[0][0]
|
||||||
|
# find the winning participants
|
||||||
|
c.execute(
|
||||||
|
'select participantAddress, winningAmount from contractparticipants where winningAmount is not null')
|
||||||
|
winnerparticipants = c.fetchall()
|
||||||
|
|
||||||
|
returnval['numberOfWinners'] = len(winnerparticipants)
|
||||||
|
|
||||||
|
else:
|
||||||
|
return jsonify(result='error', details='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)
|
return jsonify(result='ok', contractName=contractName, contractAddress=contractAddress, contractInfo=returnval)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -422,15 +568,68 @@ async def getcontractparticipants():
|
|||||||
conn = sqlite3.connect(filelocation)
|
conn = sqlite3.connect(filelocation)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute(
|
c.execute(
|
||||||
'SELECT id,participantAddress, tokenAmount, userChoice, transactionHash, winningAmount FROM contractparticipants')
|
'SELECT attribute,value FROM contractstructure')
|
||||||
result = c.fetchall()
|
result = c.fetchall()
|
||||||
conn.close()
|
|
||||||
returnval = {}
|
|
||||||
for row in result:
|
|
||||||
returnval[row[0]] = {'participantFloAddress': row[1], 'tokenAmount': row[2], 'userChoice': row[3], 'transactionHash': row[4], 'winningAmount': row[5]}
|
|
||||||
|
|
||||||
return jsonify(result='ok', contractName=contractName, contractAddress=contractAddress, participantInfo=returnval)
|
contractStructure = {}
|
||||||
|
conditionDict = {}
|
||||||
|
counter = 0
|
||||||
|
for item in result:
|
||||||
|
if list(item)[0] == 'exitconditions':
|
||||||
|
conditionDict[counter] = list(item)[1]
|
||||||
|
counter = counter + 1
|
||||||
|
else:
|
||||||
|
contractStructure[list(item)[0]] = list(item)[1]
|
||||||
|
if len(conditionDict) > 0:
|
||||||
|
contractStructure['exitconditions'] = conditionDict
|
||||||
|
del counter, conditionDict
|
||||||
|
|
||||||
|
if 'exitconditions' in contractStructure:
|
||||||
|
# contract is of the type external trigger
|
||||||
|
# check if the contract has been closed
|
||||||
|
c.execute('select * from contractTransactionHistory where transactionType="trigger"')
|
||||||
|
trigger = c.fetchall()
|
||||||
|
|
||||||
|
if len(trigger) == 1:
|
||||||
|
c.execute(
|
||||||
|
'SELECT id,participantAddress, tokenAmount, userChoice, transactionHash, winningAmount FROM contractparticipants')
|
||||||
|
result = c.fetchall()
|
||||||
|
conn.close()
|
||||||
|
returnval = {}
|
||||||
|
for row in result:
|
||||||
|
returnval[row[1]] = {'participantFloAddress': row[1], 'tokenAmount': row[2], 'userChoice': row[3],
|
||||||
|
'transactionHash': row[4], 'winningAmount': row[5]}
|
||||||
|
|
||||||
|
return jsonify(result='ok', contractName=contractName, contractAddress=contractAddress,
|
||||||
|
participantInfo=returnval)
|
||||||
|
elif len(trigger) == 0:
|
||||||
|
c.execute(
|
||||||
|
'SELECT id,participantAddress, tokenAmount, userChoice, transactionHash FROM contractparticipants')
|
||||||
|
result = c.fetchall()
|
||||||
|
conn.close()
|
||||||
|
returnval = {}
|
||||||
|
for row in result:
|
||||||
|
returnval[row[1]] = {'participantFloAddress': row[1], 'tokenAmount': row[2], 'userChoice': row[3],
|
||||||
|
'transactionHash': row[4]}
|
||||||
|
|
||||||
|
return jsonify(result='ok', contractName=contractName, contractAddress=contractAddress,
|
||||||
|
participantInfo=returnval)
|
||||||
|
else:
|
||||||
|
return jsonify(result='error', description='More than 1 trigger present. This is unusual, please check your code')
|
||||||
|
|
||||||
|
elif 'payeeAddress' in contractStructure:
|
||||||
|
# contract is of the type internal trigger
|
||||||
|
c.execute(
|
||||||
|
'SELECT id,participantAddress, tokenAmount, userChoice, transactionHash FROM contractparticipants')
|
||||||
|
result = c.fetchall()
|
||||||
|
conn.close()
|
||||||
|
returnval = {}
|
||||||
|
for row in result:
|
||||||
|
returnval[row[1]] = {'participantFloAddress': row[1], 'tokenAmount': row[2], 'userChoice': row[3],
|
||||||
|
'transactionHash': row[4]}
|
||||||
|
|
||||||
|
return jsonify(result='ok', contractName=contractName, contractAddress=contractAddress,
|
||||||
|
participantInfo=returnval)
|
||||||
else:
|
else:
|
||||||
return jsonify(result='error', details='Smart Contract with the given name doesn\'t exist')
|
return jsonify(result='error', details='Smart Contract with the given name doesn\'t exist')
|
||||||
|
|
||||||
@ -438,73 +637,25 @@ async def getcontractparticipants():
|
|||||||
@app.route('/api/v1.0/getParticipantDetails', methods=['GET'])
|
@app.route('/api/v1.0/getParticipantDetails', methods=['GET'])
|
||||||
async def getParticipantDetails():
|
async def getParticipantDetails():
|
||||||
floAddress = request.args.get('floAddress')
|
floAddress = request.args.get('floAddress')
|
||||||
|
contractName = request.args.get('contractName')
|
||||||
|
contractAddress = request.args.get('contractAddress')
|
||||||
|
|
||||||
if floAddress is None:
|
if floAddress is None:
|
||||||
return jsonify(result='error', details='FLO address hasn\'t been passed')
|
return jsonify(result='error', details='FLO address hasn\'t been passed')
|
||||||
dblocation = os.path.join(dbfolder, 'system.db')
|
dblocation = os.path.join(dbfolder, 'system.db')
|
||||||
|
|
||||||
print(dblocation)
|
if (contractName and contractAddress is None) or (contractName is None and contractAddress):
|
||||||
|
return jsonify(result='error', details='pass both, contractName and contractAddress as url parameters')
|
||||||
|
|
||||||
if os.path.isfile(dblocation):
|
if os.path.isfile(dblocation):
|
||||||
# Make db connection and fetch data
|
# Make db connection and fetch data
|
||||||
conn = sqlite3.connect(dblocation)
|
conn = sqlite3.connect(dblocation)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
|
|
||||||
# Check if its a contract address
|
|
||||||
c.execute("select contractAddress from activecontracts")
|
|
||||||
activeContracts = c.fetchall()
|
|
||||||
activeContracts = list(zip(*activeContracts))
|
|
||||||
|
|
||||||
if floAddress in list(activeContracts[0]):
|
|
||||||
c.execute("select contractName from activecontracts where contractAddress=='" + floAddress + "'")
|
|
||||||
contract_names = c.fetchall()
|
|
||||||
|
|
||||||
if len(contract_names) != 0:
|
|
||||||
|
|
||||||
contractlist = []
|
|
||||||
|
|
||||||
for contract_name in contract_names:
|
|
||||||
contractName = '{}-{}.db'.format(contract_name[0].strip(), floAddress.strip())
|
|
||||||
filelocation = os.path.join(dbfolder, 'smartContracts', contractName)
|
|
||||||
|
|
||||||
if os.path.isfile(filelocation):
|
|
||||||
# Make db connection and fetch data
|
|
||||||
conn = sqlite3.connect(filelocation)
|
|
||||||
c = conn.cursor()
|
|
||||||
c.execute(
|
|
||||||
'SELECT attribute,value FROM contractstructure')
|
|
||||||
result = c.fetchall()
|
|
||||||
|
|
||||||
returnval = {'exitconditions': []}
|
|
||||||
temp = 0
|
|
||||||
for row in result:
|
|
||||||
if row[0] == 'exitconditions':
|
|
||||||
if temp == 0:
|
|
||||||
returnval["exitconditions"] = [row[1]]
|
|
||||||
temp = temp + 1
|
|
||||||
else:
|
|
||||||
returnval['exitconditions'].append(row[1])
|
|
||||||
continue
|
|
||||||
returnval[row[0]] = row[1]
|
|
||||||
|
|
||||||
c.execute('select count(participantAddress) from contractparticipants')
|
|
||||||
noOfParticipants = c.fetchall()[0][0]
|
|
||||||
returnval['numberOfParticipants'] = noOfParticipants
|
|
||||||
|
|
||||||
c.execute('select sum(tokenAmount) from contractparticipants')
|
|
||||||
totalAmount = c.fetchall()[0][0]
|
|
||||||
returnval['tokenAmountDeposited'] = totalAmount
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
contractlist.append(returnval)
|
|
||||||
|
|
||||||
return jsonify(result='ok', floAddress=floAddress, type='contract', contractList=contractlist)
|
|
||||||
|
|
||||||
# Check if its a participant address
|
# Check if its a participant address
|
||||||
queryString = "SELECT id, participantAddress,contractName, contractAddress, tokenAmount, transactionHash FROM contractParticipantMapping where participantAddress=='" + floAddress + "'"
|
queryString = f"SELECT id, address,contractName, contractAddress, tokenAmount, transactionHash, blockNumber, blockHash FROM contractAddressMapping where address='{floAddress}' and addressType='participant'"
|
||||||
c.execute(queryString)
|
c.execute(queryString)
|
||||||
result = c.fetchall()
|
result = c.fetchall()
|
||||||
conn.close()
|
|
||||||
if len(result) != 0:
|
if len(result) != 0:
|
||||||
participationDetailsList = []
|
participationDetailsList = []
|
||||||
for row in result:
|
for row in result:
|
||||||
@ -513,6 +664,66 @@ async def getParticipantDetails():
|
|||||||
detailsDict['contractAddress'] = row[3]
|
detailsDict['contractAddress'] = row[3]
|
||||||
detailsDict['tokenAmount'] = row[4]
|
detailsDict['tokenAmount'] = row[4]
|
||||||
detailsDict['transactionHash'] = row[5]
|
detailsDict['transactionHash'] = row[5]
|
||||||
|
|
||||||
|
c.execute(f"select status, tokenIdentification, contractType, blockNumber, blockHash, incorporationDate, expiryDate, closeDate from activecontracts where contractName='{detailsDict['contractName']}' and contractAddress='{detailsDict['contractAddress']}'")
|
||||||
|
temp = c.fetchall()
|
||||||
|
detailsDict['status'] = temp[0][0]
|
||||||
|
detailsDict['tokenIdentification'] = temp[0][1]
|
||||||
|
detailsDict['contractType'] = temp[0][2]
|
||||||
|
detailsDict['blockNumber'] = temp[0][3]
|
||||||
|
detailsDict['blockHash'] = temp[0][4]
|
||||||
|
detailsDict['incorporationDate'] = temp[0][5]
|
||||||
|
if temp[0][6]:
|
||||||
|
detailsDict['expiryDate'] = temp[0][6]
|
||||||
|
if temp[0][7]:
|
||||||
|
detailsDict['closeDate'] = temp[0][7]
|
||||||
|
|
||||||
|
# check if the contract has been closed
|
||||||
|
contractDbName = '{}-{}.db'.format(detailsDict['contractName'].strip(),
|
||||||
|
detailsDict['contractAddress'].strip())
|
||||||
|
filelocation = os.path.join(dbfolder, 'smartContracts', contractDbName)
|
||||||
|
if os.path.isfile(filelocation):
|
||||||
|
# Make db connection and fetch data
|
||||||
|
conn = sqlite3.connect(filelocation)
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute(
|
||||||
|
'SELECT attribute,value FROM contractstructure')
|
||||||
|
result = c.fetchall()
|
||||||
|
|
||||||
|
contractStructure = {}
|
||||||
|
conditionDict = {}
|
||||||
|
counter = 0
|
||||||
|
for item in result:
|
||||||
|
if list(item)[0] == 'exitconditions':
|
||||||
|
conditionDict[counter] = list(item)[1]
|
||||||
|
counter = counter + 1
|
||||||
|
else:
|
||||||
|
contractStructure[list(item)[0]] = list(item)[1]
|
||||||
|
if len(conditionDict) > 0:
|
||||||
|
contractStructure['exitconditions'] = conditionDict
|
||||||
|
del counter, conditionDict
|
||||||
|
|
||||||
|
|
||||||
|
if 'exitconditions' in contractStructure:
|
||||||
|
# contract is of the type external trigger
|
||||||
|
# check if the contract has been closed
|
||||||
|
c.execute('select * from contractTransactionHistory where transactionType="trigger"')
|
||||||
|
trigger = c.fetchall()
|
||||||
|
|
||||||
|
if detailsDict['status']=='closed':
|
||||||
|
c.execute(
|
||||||
|
f"SELECT userChoice, winningAmount FROM contractparticipants where participantAddress='{floAddress}'")
|
||||||
|
result = c.fetchall()
|
||||||
|
conn.close()
|
||||||
|
detailsDict['userChoice'] = result[0][0]
|
||||||
|
detailsDict['winningAmount'] = result[0][1]
|
||||||
|
else:
|
||||||
|
c.execute(
|
||||||
|
f"SELECT userChoice FROM contractparticipants where participantAddress='{floAddress}'")
|
||||||
|
result = c.fetchall()
|
||||||
|
conn.close()
|
||||||
|
detailsDict['userChoice'] = result[0][0]
|
||||||
|
|
||||||
participationDetailsList.append(detailsDict)
|
participationDetailsList.append(detailsDict)
|
||||||
return jsonify(result='ok', floAddress=floAddress, type='participant', participatedContracts=participationDetailsList)
|
return jsonify(result='ok', floAddress=floAddress, type='participant', participatedContracts=participationDetailsList)
|
||||||
else:
|
else:
|
||||||
@ -539,142 +750,64 @@ async def getsmartcontracttransactions():
|
|||||||
# Make db connection and fetch data
|
# Make db connection and fetch data
|
||||||
conn = sqlite3.connect(filelocation)
|
conn = sqlite3.connect(filelocation)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute('select transactionHash from contractparticipants')
|
c.execute('select jsonData from contractTransactionHistory')
|
||||||
result = c.fetchall()
|
result = c.fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
returnval = {}
|
returnval = {}
|
||||||
for i,row in enumerate(result):
|
|
||||||
row = list(row)
|
|
||||||
transactionDetails = requests.get('https://ranchimallflo.duckdns.org/api/v1.0/getTransactionDetails/{}'.format(row[0]))
|
|
||||||
transactionDetails = json.loads(transactionDetails.content)
|
|
||||||
returnval[i] = transactionDetails
|
|
||||||
|
|
||||||
|
for transaction in result:
|
||||||
|
transactionJson = json.loads(transaction[0])
|
||||||
|
returnval[transactionJson['txid']] = transactionJson
|
||||||
return jsonify(result='ok', contractName=contractName, contractAddress=contractAddress, contractTransactions=returnval)
|
return jsonify(result='ok', contractName=contractName, contractAddress=contractAddress, contractTransactions=returnval)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return jsonify(result='error', details='Smart Contract with the given name doesn\'t exist')
|
return jsonify(result='error', details='Smart Contract with the given name doesn\'t exist')
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/v1.0/getBlockDetails', methods=['GET'])
|
@app.route('/api/v1.0/getBlockDetails/<blockdetail>', methods=['GET'])
|
||||||
async def getblockdetails():
|
async def getblockdetails(blockdetail):
|
||||||
blockHash = request.args.get('blockHash')
|
|
||||||
blockHeight = request.args.get('blockHeight')
|
|
||||||
|
|
||||||
if blockHash is None and blockHeight is None:
|
if blockdetail.isdigit():
|
||||||
return jsonify(result='error', details='Pass either blockHash or blockHeight')
|
blockHash = None
|
||||||
|
blockHeight = int(blockdetail)
|
||||||
|
else:
|
||||||
|
blockHash = str(blockdetail)
|
||||||
|
blockHeight = None
|
||||||
|
|
||||||
elif blockHash is not None and blockHeight is not None:
|
# open the latest block database
|
||||||
return jsonify(result='error', details='Pass either blockHash or blockHeight. Not both.')
|
conn = sqlite3.connect(os.path.join(dbfolder, 'latestCache.db'))
|
||||||
elif blockHash:
|
c = conn.cursor()
|
||||||
blockdetails = requests.get('{}block/{}'.format(apiUrl,blockHash))
|
|
||||||
blockdetails = json.loads(blockdetails.content)
|
if blockHash:
|
||||||
return jsonify(blockDetails=blockdetails, blockHash=blockHash)
|
c.execute(f"select jsonData from latestBlocks where blockHash='{blockHash}'")
|
||||||
elif blockHeight:
|
elif blockHeight:
|
||||||
blockhash = requests.get('{}block-index/{}'.format(apiUrl,blockHeight))
|
c.execute(f"select jsonData from latestBlocks where blockNumber='{blockHeight}'")
|
||||||
blockhash = json.loads(blockhash.content)
|
|
||||||
|
|
||||||
blockdetails = requests.get('{}block/{}'.format(apiUrl,blockhash['blockHash']))
|
blockJson = c.fetchall()
|
||||||
blockdetails = json.loads(blockdetails.content)
|
if len(blockJson) != 0:
|
||||||
return jsonify(blockDetails=blockdetails, blockHeight=blockHeight)
|
blockJson = json.loads(blockJson[0][0])
|
||||||
|
return jsonify(result='ok', blockDetails=blockJson)
|
||||||
|
else:
|
||||||
|
return jsonify(result='error', details='Block doesn\'t exist in database')
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/v1.0/getTransactionDetails/<transactionHash>', methods=['GET'])
|
@app.route('/api/v1.0/getTransactionDetails/<transactionHash>', methods=['GET'])
|
||||||
async def gettransactiondetails(transactionHash):
|
async def gettransactiondetails(transactionHash):
|
||||||
transactionDetails = requests.get('{}tx/{}'.format(apiUrl,transactionHash))
|
|
||||||
transactionDetails = json.loads(transactionDetails.content)
|
|
||||||
|
|
||||||
if (len(transactionDetails['vin'])!=1) and (len(transactionDetails['vout']) not in [1,2]):
|
# open the latest block database
|
||||||
return jsonify(result='error', details='Transaction doesnt exist as part of the Token and Smart Contract system')
|
conn = sqlite3.connect(os.path.join(dbfolder, 'latestCache.db'))
|
||||||
|
c = conn.cursor()
|
||||||
|
|
||||||
flodata = transactionDetails['floData']
|
c.execute(f"select jsonData,parsedFloData from latestTransactions where transactionHash='{transactionHash}'")
|
||||||
|
transactionJsonData = c.fetchall()
|
||||||
|
|
||||||
blockdetails = requests.get('{}block/{}'.format(apiUrl,transactionDetails['blockhash']))
|
if len(transactionJsonData) != 0:
|
||||||
blockdetails = json.loads(blockdetails.content)
|
transactionJson = json.loads(transactionJsonData[0][0])
|
||||||
|
parseResult = json.loads(transactionJsonData[0][1])
|
||||||
|
|
||||||
parseResult = parsing.parse_flodata(flodata, blockdetails)
|
return jsonify(parsedFloData=parseResult, transactionDetails=transactionJson, transactionHash=transactionHash, result='ok')
|
||||||
|
else:
|
||||||
# now check what kind of transaction it is and if it exists in our database
|
return jsonify(result='error', details='Transaction doesn\'t exist in database')
|
||||||
|
|
||||||
if parseResult["type"] == "noise":
|
|
||||||
return jsonify(result='error', description='Transaction is of the type noise')
|
|
||||||
|
|
||||||
elif parseResult["type"] == "tokenIncorporation":
|
|
||||||
# open db of the token specified and check if the transaction exists there
|
|
||||||
dblocation = os.path.join(dbfolder, 'tokens' , parseResult['tokenIdentification']+'.db')
|
|
||||||
print(dblocation)
|
|
||||||
|
|
||||||
if os.path.isfile(dblocation):
|
|
||||||
# Make db connection and fetch data
|
|
||||||
conn = sqlite3.connect(dblocation)
|
|
||||||
c = conn.cursor()
|
|
||||||
temp = c.execute('select transactionHash from transactionHistory where transactionHash="{}"'.format(transactionHash)).fetchall()
|
|
||||||
|
|
||||||
if len(temp) == 0:
|
|
||||||
return jsonify(result='error', details='Transaction doesnt exist as part of the Token and Smart Contract system')
|
|
||||||
elif len(temp) > 1:
|
|
||||||
return jsonify(result='error', details='More than 2 instances of this txid exists in the db. This is unusual, please report to the developers. https://github.com/ranchimall/floscout')
|
|
||||||
|
|
||||||
|
|
||||||
elif parseResult["type"] == "transfer":
|
|
||||||
if parseResult["transferType"] == "token":
|
|
||||||
# open db of the token specified and check if the transaction exists there
|
|
||||||
dblocation = os.path.join(dbfolder, 'tokens' , parseResult['tokenIdentification']+'.db')
|
|
||||||
print(dblocation)
|
|
||||||
|
|
||||||
if os.path.isfile(dblocation):
|
|
||||||
# Make db connection and fetch data
|
|
||||||
conn = sqlite3.connect(dblocation)
|
|
||||||
c = conn.cursor()
|
|
||||||
temp = c.execute('select transactionHash from transactionHistory where transactionHash="{}"'.format(transactionHash)).fetchall()
|
|
||||||
|
|
||||||
if len(temp) == 0:
|
|
||||||
return jsonify(result='error', details='Transaction doesnt exist as part of the Token and Smart Contract system')
|
|
||||||
elif len(temp) > 1:
|
|
||||||
return jsonify(result='error', details='More than 2 instances of this txid exists in the db. This is unusual, please report to the developers. https://github.com/ranchimall/floscout')
|
|
||||||
|
|
||||||
elif parseResult["transferType"] == "smartContract":
|
|
||||||
# find the address of smart contract
|
|
||||||
contractAddress = None
|
|
||||||
|
|
||||||
for voutItem in transactionDetails['vout']:
|
|
||||||
if voutItem['scriptPubKey']['addresses'][0] != transactionDetails['vin'][0]['addr']:
|
|
||||||
contractAddress = voutItem['scriptPubKey']['addresses'][0];
|
|
||||||
|
|
||||||
# open db of the contract specified and check if the transaction exists there
|
|
||||||
dblocation = os.path.join(dbfolder, 'smartContracts' , parseResult['contractName'] + '-' + contractAddress + '.db')
|
|
||||||
print(dblocation)
|
|
||||||
|
|
||||||
if os.path.isfile(dblocation):
|
|
||||||
# Make db connection and fetch data
|
|
||||||
conn = sqlite3.connect(dblocation)
|
|
||||||
c = conn.cursor()
|
|
||||||
temp = c.execute('select transactionHash from contractparticipants where transactionHash="{}"'.format(transactionHash)).fetchall()
|
|
||||||
|
|
||||||
if len(temp) == 0:
|
|
||||||
return jsonify(result='error', details='Transaction doesnt exist as part of the Token and Smart Contract system')
|
|
||||||
elif len(temp) > 1:
|
|
||||||
return jsonify(result='error', details='More than 2 instances of this txid exists in the db. This is unusual, please report to the developers. https://github.com/ranchimall/floscout')
|
|
||||||
|
|
||||||
elif parseResult["type"] == "smartContractIncorporation":
|
|
||||||
print('smart contract incorporation')
|
|
||||||
|
|
||||||
elif parseResult["type"] == "smartContractPays":
|
|
||||||
print('smart contract pays')
|
|
||||||
|
|
||||||
|
|
||||||
return jsonify(parsedFloData=parseResult, transactionDetails=transactionDetails, transactionHash=transactionHash, result='ok')
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/v1.0/getVscoutDetails', methods=['GET'])
|
|
||||||
async def getVscoutDetails():
|
|
||||||
latestBlock = requests.get('{}blocks?limit=1'.format(apiUrl))
|
|
||||||
latestBlock = json.loads(latestBlock)
|
|
||||||
|
|
||||||
# get details of the last s4 blocks
|
|
||||||
blockurl = '{}block/{}'.format(apiUrl,latestBlock["blocks"]['hash'])
|
|
||||||
blockdetails = requests.get('{}block/{}'.format(apiUrl,latestBlock["blocks"]['hash']))
|
|
||||||
block4details = json.loads(blockdetails)
|
|
||||||
return jsonify(block4details)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/v1.0/getLatestTransactionDetails', methods=['GET'])
|
@app.route('/api/v1.0/getLatestTransactionDetails', methods=['GET'])
|
||||||
@ -693,7 +826,7 @@ async def getLatestTransactionDetails():
|
|||||||
c.execute('SELECT * FROM latestTransactions WHERE blockNumber IN (SELECT DISTINCT blockNumber FROM latestTransactions ORDER BY blockNumber DESC LIMIT {}) ORDER BY id ASC;'.format(int(numberOfLatestBlocks)))
|
c.execute('SELECT * FROM latestTransactions WHERE blockNumber IN (SELECT DISTINCT blockNumber FROM latestTransactions ORDER BY blockNumber DESC LIMIT {}) ORDER BY id ASC;'.format(int(numberOfLatestBlocks)))
|
||||||
latestTransactions = c.fetchall()
|
latestTransactions = c.fetchall()
|
||||||
c.close()
|
c.close()
|
||||||
tempdict = []
|
tempdict = {}
|
||||||
for idx, item in enumerate(latestTransactions):
|
for idx, item in enumerate(latestTransactions):
|
||||||
item = list(item)
|
item = list(item)
|
||||||
tx_parsed_details = {}
|
tx_parsed_details = {}
|
||||||
@ -701,12 +834,12 @@ async def getLatestTransactionDetails():
|
|||||||
tx_parsed_details['parsedFloData'] = json.loads(item[5])
|
tx_parsed_details['parsedFloData'] = json.loads(item[5])
|
||||||
tx_parsed_details['parsedFloData']['transactionType'] = item[4]
|
tx_parsed_details['parsedFloData']['transactionType'] = item[4]
|
||||||
tx_parsed_details['transactionDetails']['blockheight'] = int(item[2])
|
tx_parsed_details['transactionDetails']['blockheight'] = int(item[2])
|
||||||
tempdict.append(tx_parsed_details)
|
tempdict[json.loads(item[3])['txid']] = tx_parsed_details
|
||||||
else:
|
else:
|
||||||
c.execute('''SELECT * FROM latestTransactions WHERE blockNumber IN (SELECT DISTINCT blockNumber FROM latestTransactions ORDER BY blockNumber DESC LIMIT 100) ORDER BY id ASC;''')
|
c.execute('''SELECT * FROM latestTransactions WHERE blockNumber IN (SELECT DISTINCT blockNumber FROM latestTransactions ORDER BY blockNumber DESC LIMIT 100) ORDER BY id ASC;''')
|
||||||
latestTransactions = c.fetchall()
|
latestTransactions = c.fetchall()
|
||||||
c.close()
|
c.close()
|
||||||
tempdict = []
|
tempdict = {}
|
||||||
for idx, item in enumerate(latestTransactions):
|
for idx, item in enumerate(latestTransactions):
|
||||||
item = list(item)
|
item = list(item)
|
||||||
tx_parsed_details = {}
|
tx_parsed_details = {}
|
||||||
@ -714,7 +847,7 @@ async def getLatestTransactionDetails():
|
|||||||
tx_parsed_details['parsedFloData'] = json.loads(item[5])
|
tx_parsed_details['parsedFloData'] = json.loads(item[5])
|
||||||
tx_parsed_details['parsedFloData']['transactionType'] = item[4]
|
tx_parsed_details['parsedFloData']['transactionType'] = item[4]
|
||||||
tx_parsed_details['transactionDetails']['blockheight'] = int(item[2])
|
tx_parsed_details['transactionDetails']['blockheight'] = int(item[2])
|
||||||
tempdict.append(tx_parsed_details)
|
tempdict[json.loads(item[3])['txid']] = tx_parsed_details
|
||||||
return jsonify(result='ok', latestTransactions=tempdict)
|
return jsonify(result='ok', latestTransactions=tempdict)
|
||||||
|
|
||||||
|
|
||||||
@ -737,9 +870,9 @@ async def getLatestBlockDetails():
|
|||||||
c.execute('SELECT * FROM ( SELECT * FROM latestBlocks ORDER BY blockNumber DESC LIMIT {}) ORDER BY id ASC;'.format(limit))
|
c.execute('SELECT * FROM ( SELECT * FROM latestBlocks ORDER BY blockNumber DESC LIMIT {}) ORDER BY id ASC;'.format(limit))
|
||||||
latestBlocks = c.fetchall()
|
latestBlocks = c.fetchall()
|
||||||
c.close()
|
c.close()
|
||||||
tempdict = []
|
tempdict = {}
|
||||||
for idx, item in enumerate(latestBlocks):
|
for idx, item in enumerate(latestBlocks):
|
||||||
tempdict.append(json.loads(item[3]))
|
tempdict[json.loads(item[3])['hash']] = json.loads(item[3])
|
||||||
return jsonify(result='ok', latestBlocks=tempdict)
|
return jsonify(result='ok', latestBlocks=tempdict)
|
||||||
|
|
||||||
|
|
||||||
@ -795,12 +928,16 @@ async def getTokenSmartContractList():
|
|||||||
contractDict['contractName'] = contract[1]
|
contractDict['contractName'] = contract[1]
|
||||||
contractDict['contractAddress'] = contract[2]
|
contractDict['contractAddress'] = contract[2]
|
||||||
contractDict['status'] = contract[3]
|
contractDict['status'] = contract[3]
|
||||||
contractDict['transactionHash'] = contract[4]
|
contractDict['tokenIdentification'] = contract[4]
|
||||||
contractDict['incorporationDate'] = contract[5]
|
contractDict['contractType'] = contract[5]
|
||||||
if contract[6]:
|
contractDict['transactionHash'] = contract[6]
|
||||||
contractDict['expiryDate'] = contract[6]
|
contractDict['blockNumber'] = contract[7]
|
||||||
if contract[7]:
|
contractDict['blockHash'] = contract[8]
|
||||||
contractDict['closeDate'] = contract[7]
|
contractDict['incorporationDate'] = contract[9]
|
||||||
|
if contract[10]:
|
||||||
|
contractDict['expiryDate'] = contract[10]
|
||||||
|
if contract[11]:
|
||||||
|
contractDict['closeDate'] = contract[11]
|
||||||
|
|
||||||
contractList.append(contractDict)
|
contractList.append(contractDict)
|
||||||
|
|
||||||
@ -815,7 +952,7 @@ async def systemData():
|
|||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
tokenAddressCount = c.execute('select count(distinct tokenAddress) from tokenAddressMapping').fetchall()[0][0]
|
tokenAddressCount = c.execute('select count(distinct tokenAddress) from tokenAddressMapping').fetchall()[0][0]
|
||||||
tokenCount = c.execute('select count(distinct token) from tokenAddressMapping').fetchall()[0][0]
|
tokenCount = c.execute('select count(distinct token) from tokenAddressMapping').fetchall()[0][0]
|
||||||
contractCount = c.execute('select count(distinct contractName) from contractParticipantMapping').fetchall()[0][0]
|
contractCount = c.execute('select count(distinct contractName) from contractAddressMapping').fetchall()[0][0]
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
# query for total number of validated blocks
|
# query for total number of validated blocks
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user