Spine of betting smart contract
This commit introduces the betting smart contract on FLO blockchain
This commit is contained in:
parent
11a4aa09c6
commit
f49693d71b
@ -1,6 +1,6 @@
|
|||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
NET = testnet
|
NET = testnet
|
||||||
FLO_CLI_PATH = /usr/local/bin/flo-cli
|
FLO_CLI_PATH = /usr/local/bin/flo-cli
|
||||||
START_BLOCK = 489130
|
START_BLOCK = 498770
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
15
models.py
15
models.py
@ -3,6 +3,7 @@ from sqlalchemy import Column, Integer, Float, String, ForeignKey
|
|||||||
|
|
||||||
Base = declarative_base()
|
Base = declarative_base()
|
||||||
ContractBase = declarative_base()
|
ContractBase = declarative_base()
|
||||||
|
SystemBase = declarative_base()
|
||||||
|
|
||||||
class Extra(Base):
|
class Extra(Base):
|
||||||
__tablename__ = "extra"
|
__tablename__ = "extra"
|
||||||
@ -52,4 +53,18 @@ class ContractStructure(ContractBase):
|
|||||||
index = Column('index', Integer)
|
index = Column('index', Integer)
|
||||||
value = Column('value', String)
|
value = Column('value', String)
|
||||||
|
|
||||||
|
class ContractParticipants(ContractBase):
|
||||||
|
__tablename__ = "contractparticipants"
|
||||||
|
|
||||||
|
id = Column('id', Integer, primary_key=True)
|
||||||
|
participantAddress = Column('participantAddress', String)
|
||||||
|
tokenAmount = Column('tokenAmount', Float)
|
||||||
|
contractCondition = Column('contractCondition', String)
|
||||||
|
|
||||||
|
class ActiveContracts(SystemBase):
|
||||||
|
__tablename__ = "activecontracts"
|
||||||
|
|
||||||
|
id = Column('id', Integer, primary_key=True)
|
||||||
|
contractName = Column('contractName', String)
|
||||||
|
contractAddress = Column('contractAddress', String)
|
||||||
|
|
||||||
|
|||||||
143
parsing.py
143
parsing.py
@ -27,7 +27,9 @@ def isIncorp(text):
|
|||||||
def isSmartContract(text):
|
def isSmartContract(text):
|
||||||
textList = text.split(' ')
|
textList = text.split(' ')
|
||||||
for word in textList:
|
for word in textList:
|
||||||
if word[-1] == '@':
|
if word == '':
|
||||||
|
continue
|
||||||
|
if word.endswith('@'):
|
||||||
return word
|
return word
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -48,27 +50,13 @@ def isSmartContractPay(text):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def extractOperation(text):
|
def extractAmount(text, marker):
|
||||||
operationList = ['send', 'transfer', 'give'] # keep everything lowercase
|
|
||||||
count = 0
|
|
||||||
returnval = None
|
|
||||||
for operation in operationList:
|
|
||||||
count = count + text.count(operation)
|
|
||||||
if count > 1:
|
|
||||||
return 'Too many'
|
|
||||||
if count == 1 and (returnval is None):
|
|
||||||
returnval = operation
|
|
||||||
return returnval
|
|
||||||
|
|
||||||
|
|
||||||
# todo pass marker to the function and support all types
|
|
||||||
def extractAmount(text):
|
|
||||||
count = 0
|
count = 0
|
||||||
returnval = None
|
returnval = None
|
||||||
splitText = re.split("\W+", text)
|
splitText = re.split("\W+", text)
|
||||||
|
|
||||||
for word in splitText:
|
for word in splitText:
|
||||||
word = word.replace('rmt', '')
|
word = word.replace(marker, '')
|
||||||
try:
|
try:
|
||||||
float(word)
|
float(word)
|
||||||
count = count + 1
|
count = count + 1
|
||||||
@ -84,7 +72,9 @@ def extractAmount(text):
|
|||||||
def extractMarker(text):
|
def extractMarker(text):
|
||||||
textList = text.split(' ')
|
textList = text.split(' ')
|
||||||
for word in textList:
|
for word in textList:
|
||||||
if word[-1] == '#':
|
if word == '':
|
||||||
|
continue
|
||||||
|
if word.endswith('#'):
|
||||||
return word
|
return word
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -97,17 +87,20 @@ def extractInitTokens(text):
|
|||||||
result = float(word)
|
result = float(word)
|
||||||
if textList[idx+1] in base_units:
|
if textList[idx+1] in base_units:
|
||||||
return result*base_units[textList[idx+1]]
|
return result*base_units[textList[idx+1]]
|
||||||
return res
|
return result
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def extractAddress(text):
|
def extractAddress(text):
|
||||||
textList = text.split(' ')
|
textList = text.split(' ')
|
||||||
for word in textList:
|
for word in textList:
|
||||||
|
if word == '':
|
||||||
|
continue
|
||||||
if word[-1] == '$':
|
if word[-1] == '$':
|
||||||
return word
|
return word
|
||||||
return False
|
return None
|
||||||
|
|
||||||
|
|
||||||
def extractContractType(text):
|
def extractContractType(text):
|
||||||
@ -124,7 +117,11 @@ def extractContractType(text):
|
|||||||
|
|
||||||
|
|
||||||
def extractContractCondition(text):
|
def extractContractCondition(text):
|
||||||
return text.split("contractcondition:")[1][1:-1]
|
result = text.split("contractcondition:")
|
||||||
|
if len(result) != 1:
|
||||||
|
return result[1].strip()[1:-1]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def extractContractConditions(text, contracttype, marker):
|
def extractContractConditions(text, contracttype, marker):
|
||||||
@ -149,9 +146,19 @@ def extractContractConditions(text, contracttype, marker):
|
|||||||
else:
|
else:
|
||||||
print("something is wrong with smartcontractpays conditions")
|
print("something is wrong with smartcontractpays conditions")
|
||||||
|
|
||||||
|
if 'userassetcommitment' in extractedRules and 'smartcontractpays' in extractedRules:
|
||||||
return extractedRules
|
return extractedRules
|
||||||
return False
|
else:
|
||||||
|
return None
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def extractTriggerCondition(text):
|
||||||
|
searchResult = re.search('\".*\"', text)
|
||||||
|
if searchResult is None:
|
||||||
|
searchResult = re.search('\'.*\'', text)
|
||||||
|
return searchResult
|
||||||
|
return searchResult
|
||||||
|
|
||||||
|
|
||||||
# Combine test
|
# Combine test
|
||||||
@ -163,45 +170,83 @@ def parse_flodata(string):
|
|||||||
nospacestring = re.sub(' +', ' ', string)
|
nospacestring = re.sub(' +', ' ', string)
|
||||||
cleanstring = nospacestring.lower()
|
cleanstring = nospacestring.lower()
|
||||||
|
|
||||||
|
atList = []
|
||||||
|
hashList = []
|
||||||
|
|
||||||
if isTransfer(cleanstring):
|
for word in cleanstring.split(' '):
|
||||||
if isSmartContract(cleanstring):
|
if word.endswith('@'):
|
||||||
contractname = isSmartContract(cleanstring)
|
atList.append(word)
|
||||||
marker = extractMarker(cleanstring)
|
if word.endswith('#'):
|
||||||
operation = extractOperation(cleanstring)
|
hashList.append(word)
|
||||||
amount = extractAmount(cleanstring)
|
|
||||||
contractcondition = extractContractCondition(cleanstring)
|
# Filter noise first - check if the words end with either @ or #
|
||||||
parsed_data = { 'type': 'transfer', 'transferType': 'smartContract', 'flodata': string, 'tokenIdentification': marker[:-1],
|
if (len(atList)==0 and len(hashList)==0) or len(atList)>1 or len(hashList)>1:
|
||||||
'operation': operation, 'tokenAmount': amount, 'contractName': contractname, 'contractCondition': contractcondition}
|
parsed_data = {'type': 'noise'}
|
||||||
|
|
||||||
|
elif len(hashList)==1 and len(atList)==0:
|
||||||
|
# Passing the above check means token creation or transfer
|
||||||
|
incorporation = isIncorp(cleanstring)
|
||||||
|
transfer = isTransfer(cleanstring)
|
||||||
|
|
||||||
|
if incorporation and not transfer:
|
||||||
|
initTokens = extractInitTokens(cleanstring)
|
||||||
|
if initTokens is not None:
|
||||||
|
parsed_data = {'type': 'tokenIncorporation', 'flodata': string, 'tokenIdentification': hashList[0][:-1],
|
||||||
|
'tokenAmount': initTokens}
|
||||||
else:
|
else:
|
||||||
marker = extractMarker(cleanstring)
|
parsed_data = {'type': 'noise'}
|
||||||
operation = extractOperation(cleanstring)
|
elif not incorporation and transfer:
|
||||||
amount = extractAmount(cleanstring)
|
amount = extractAmount(cleanstring, hashList[0][:-1])
|
||||||
address = extractAddress(nospacestring)
|
address = extractAddress(nospacestring)
|
||||||
parsed_data = {'type': 'transfer', 'transferType': 'token', 'flodata': string, 'tokenIdentification': marker[:-1], 'operation': operation,
|
if None not in [amount, address]:
|
||||||
'amount': amount, 'address': address}
|
parsed_data = {'type': 'transfer', 'transferType': 'token', 'flodata': string,
|
||||||
|
'tokenIdentification': hashList[0][:-1],
|
||||||
|
'tokenAmount': amount, 'address': address[:-1]}
|
||||||
|
else:
|
||||||
|
parsed_data = {'type': 'noise'}
|
||||||
|
else:
|
||||||
|
parsed_data = {'type': 'noise'}
|
||||||
|
|
||||||
elif isSmartContractPay(nospacestring):
|
elif len(hashList)==1 and len(atList)==1:
|
||||||
contractConditions = isSmartContractPay(nospacestring)
|
# Passing the above check means Smart Contract creation or transfer
|
||||||
parsed_data = {'type': 'smartContractPays', 'flodata': string, 'smartContractTrigger':contractConditions['smartContractTrigger'], 'smartContractName':contractConditions['smartContractName']}
|
incorporation = isIncorp(cleanstring)
|
||||||
|
transfer = isTransfer(cleanstring)
|
||||||
|
|
||||||
elif isSmartContract(cleanstring):
|
if incorporation and not transfer:
|
||||||
contractname = isSmartContract(cleanstring)
|
|
||||||
marker = extractMarker(cleanstring)
|
|
||||||
contracttype = extractContractType(cleanstring)
|
contracttype = extractContractType(cleanstring)
|
||||||
contractaddress = extractAddress(nospacestring)
|
contractaddress = extractAddress(nospacestring)
|
||||||
contractconditions = extractContractConditions(cleanstring, 'betting*', marker)
|
contractconditions = extractContractConditions(cleanstring, 'betting*', marker)
|
||||||
parsed_data = {'type': 'smartContractIncorporation', 'contractType': contracttype[:-1], 'tokenIdentification': marker[:-1], 'contractName': contractname[:-1], 'contractAddress':contractaddress[:-1], 'flodata': string, 'contractConditions': contractconditions}
|
|
||||||
|
|
||||||
elif isIncorp(cleanstring):
|
if None not in [contracttype, contractaddress, contractconditions]:
|
||||||
incMarker = extractMarker(cleanstring)
|
parsed_data = {'type': 'smartContractIncorporation', 'contractType': contracttype[:-1],
|
||||||
initTokens = extractInitTokens(cleanstring)
|
'tokenIdentification': hashList[0][:-1], 'contractName': atList[0][:-1],
|
||||||
parsed_data = {'type': 'tokenIncorporation', 'flodata': string, 'tokenIdentification': incMarker[:-1], 'tokenAmount': initTokens}
|
'contractAddress': contractaddress[:-1], 'flodata': string,
|
||||||
|
'contractConditions': contractconditions}
|
||||||
|
else:
|
||||||
|
parsed_data = {'type': 'noise'}
|
||||||
|
elif not incorporation and transfer:
|
||||||
|
amount = extractAmount(cleanstring, hashList[0][:-1])
|
||||||
|
contractcondition = extractContractCondition(cleanstring)
|
||||||
|
if None not in [amount, contractcondition]:
|
||||||
|
parsed_data = {'type': 'transfer', 'transferType': 'smartContract', 'flodata': string,
|
||||||
|
'tokenIdentification': hashList[0][:-1],
|
||||||
|
'operation': 'transfer', 'tokenAmount': amount, 'contractName': atList[0][:-1],
|
||||||
|
'contractCondition': contractcondition}
|
||||||
|
else:
|
||||||
|
parsed_data = {'type': 'noise'}
|
||||||
|
else:
|
||||||
|
parsed_data = {'type': 'noise'}
|
||||||
|
|
||||||
|
|
||||||
|
elif len(hashList)==0 and len(atList)==1:
|
||||||
|
# Passing the above check means Smart Contract pays | exitcondition triggered from the committee
|
||||||
|
triggerCondition = extractTriggerCondition(cleanstring)
|
||||||
|
if triggerCondition is not None:
|
||||||
|
parsed_data = {'type': 'smartContractPays', 'contractName': atList[0][:-1], 'triggerCondition': triggerCondition.group().strip()[1:-1]}
|
||||||
else:
|
else:
|
||||||
parsed_data = {'type':'noise'}
|
parsed_data = {'type':'noise'}
|
||||||
|
|
||||||
return parsed_data
|
return parsed_data
|
||||||
|
|
||||||
result = parse_flodata('create electionbetting@ at address oM4pCYsbT5xg7bqLNCTXmoADUs6zBwLfXi$ of type betting* using the token rmt# with contractconditions: 1. userAssetCommitment="1rmt" 2. smartContractPays="NAMO=WIN | NAMO=LOOSE 3. expirydate=1553040000"')
|
result = parse_flodata("for contractname@ Smart Contract System says 'NAMO=WIN'")
|
||||||
print(result)
|
print(result)
|
||||||
Binary file not shown.
BIN
tokens/rmt.db
BIN
tokens/rmt.db
Binary file not shown.
@ -1,302 +0,0 @@
|
|||||||
import requests
|
|
||||||
import json
|
|
||||||
import sqlite3
|
|
||||||
import argparse
|
|
||||||
import configparser
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import parsing
|
|
||||||
from sqlalchemy.orm import sessionmaker, relationship
|
|
||||||
from sqlalchemy import create_engine, func, desc
|
|
||||||
from models import Extra, TransactionHistory, TransactionTable, TransferLogs, Webtable, Base, ContractStructure
|
|
||||||
|
|
||||||
|
|
||||||
def startWorking(transaction_data, parsed_data):
|
|
||||||
engine = create_engine('sqlite:///databases/{}.db'.format(parsed_data['marker'][:-1]), echo=True)
|
|
||||||
Base.metadata.create_all(bind=engine)
|
|
||||||
Session = sessionmaker(bind=engine)
|
|
||||||
session = Session()
|
|
||||||
|
|
||||||
# Play area
|
|
||||||
if parsed_data['type'] == 'transfer':
|
|
||||||
if parsed_data['amount'] is None:
|
|
||||||
print("Value for token transfer has not been specified")
|
|
||||||
return
|
|
||||||
elif parsed_data['type'] == 'incorporation':
|
|
||||||
if parsed_data['initTokens'] is None:
|
|
||||||
print("Value for token transfer has not been specified")
|
|
||||||
return
|
|
||||||
|
|
||||||
inputlist = []
|
|
||||||
querylist = []
|
|
||||||
|
|
||||||
for obj in transaction_data["vin"]:
|
|
||||||
querylist.append([obj["txid"], obj["vout"]])
|
|
||||||
|
|
||||||
inputval = 0
|
|
||||||
inputadd = ''
|
|
||||||
|
|
||||||
for query in querylist:
|
|
||||||
string = "{} getrawtransaction {} 1".format(localapi, str(query[0]))
|
|
||||||
response = subprocess.check_output(string, shell=True)
|
|
||||||
content = json.loads(response.decode("utf-8"))
|
|
||||||
|
|
||||||
for objec in content["vout"]:
|
|
||||||
if objec["n"] == query[1]:
|
|
||||||
inputadd = objec["scriptPubKey"]["addresses"][0]
|
|
||||||
inputval = inputval + objec["value"]
|
|
||||||
|
|
||||||
inputlist = [[inputadd, inputval]]
|
|
||||||
|
|
||||||
if len(inputlist) > 1:
|
|
||||||
print("Program has detected more than one input address ")
|
|
||||||
print("This transaction will be discarded")
|
|
||||||
break
|
|
||||||
|
|
||||||
outputlist = []
|
|
||||||
for obj in transaction_data["vout"]:
|
|
||||||
if obj["scriptPubKey"]["type"] == "pubkeyhash":
|
|
||||||
if inputlist[0][0] == obj["scriptPubKey"]["addresses"][0]:
|
|
||||||
continue
|
|
||||||
temp = []
|
|
||||||
temp.append(obj["scriptPubKey"]["addresses"][0])
|
|
||||||
temp.append(obj["value"])
|
|
||||||
|
|
||||||
outputlist.append(temp)
|
|
||||||
|
|
||||||
print("\n\nInput List")
|
|
||||||
print(inputlist)
|
|
||||||
print("\nOutput List")
|
|
||||||
print(outputlist)
|
|
||||||
|
|
||||||
if len(inputlist) > 1:
|
|
||||||
print("Program has detected more than one input address ")
|
|
||||||
print("This transaction will be discarded")
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Check if the transaction is of the type 'incorporation' or 'smartcontract'
|
|
||||||
if parsed_data['type'] == 'smartcontract':
|
|
||||||
print("I JUST FOUND THE INCORPORATION OF SMART CONTRACT \n" + str(parsed_data))
|
|
||||||
if parsed_data['contracttype'] == 'betting*':
|
|
||||||
print("Smart contract is of the type betting")
|
|
||||||
if parsed_data['contractname'] is not None and parsed_data['contractaddress'][:-1] == outputlist[0][0]:
|
|
||||||
print("Hey I have passed the first test for smart contract")
|
|
||||||
#check if a db with contractname exists
|
|
||||||
scengine = create_engine('sqlite:///smartContracts/{}.db'.format(parsed_data['contractname'][:-1]), echo=True)
|
|
||||||
Base.metadata.create_all(bind=scengine)
|
|
||||||
scsession = sessionmaker(bind=scengine)()
|
|
||||||
scsession.add(ContractStructure(attribute='contracttype', index=0, value=parsed_data['contracttype'][:-1]))
|
|
||||||
scsession.add(ContractStructure(attribute='contractname', index=0, value=parsed_data['contractname'][:-1]))
|
|
||||||
scsession.add(
|
|
||||||
ContractStructure(attribute='marker', index=0, value=parsed_data['marker'][:-1]))
|
|
||||||
|
|
||||||
scsession.commit()
|
|
||||||
scsession.close()
|
|
||||||
|
|
||||||
sys.exit(0)
|
|
||||||
elif parsed_data['type'] == 'incorporation':
|
|
||||||
session.add(TransactionTable(address=outputlist[0][0], parentid=0, transferBalance=parsed_data['initTokens']))
|
|
||||||
session.commit()
|
|
||||||
#transferDescription = "Root address = " + str(root_address) + " has been initialized with " + str(root_init_value) + " tokens"
|
|
||||||
#blockchainReference = '{}tx/'.format(neturl)
|
|
||||||
#session.add(TransferLogs(primaryIDReference=1, transferDescription=transferDescription, transferIDConsumed=0, blockchainReference=blockchainReference))
|
|
||||||
#session.add(TransactionHistory(blockno=root_block_index, fromAddress='', toAddress=root_address, amount=root_init_value, blockchainReference=blockchainReference))
|
|
||||||
#session.commit()
|
|
||||||
return
|
|
||||||
|
|
||||||
availableTokens = session.query(func.sum(TransactionTable.transferBalance)).filter_by(address=inputlist[0][0]).all()[0][0]
|
|
||||||
commentTransferAmount = parsed_data['amount']
|
|
||||||
|
|
||||||
if availableTokens is None:
|
|
||||||
print("The input address dosen't exist in our database ")
|
|
||||||
|
|
||||||
elif availableTokens < commentTransferAmount:
|
|
||||||
print("\nThe transfer amount passed in the comments is more than the user owns\nThis transaction will be discarded\n")
|
|
||||||
continue
|
|
||||||
|
|
||||||
elif availableTokens >= commentTransferAmount:
|
|
||||||
'''if len(commentTransferAmount) != len(outputlist):
|
|
||||||
print("The parameters in the comments aren't enough")
|
|
||||||
print("This transaction will be discarded")
|
|
||||||
continue'''
|
|
||||||
|
|
||||||
# if output[0] == inputlist[0][0]:
|
|
||||||
# continue
|
|
||||||
|
|
||||||
#c.execute("SELECT * FROM transactiontable WHERE address=?", (inputlist[0][0],))
|
|
||||||
#table = c.fetchall()
|
|
||||||
table = session.query(TransactionTable).filter_by(address=inputlist[0][0]).all()
|
|
||||||
|
|
||||||
pidlst = []
|
|
||||||
checksum = 0
|
|
||||||
for row in table:
|
|
||||||
if checksum >= commentTransferAmount:
|
|
||||||
break
|
|
||||||
pidlst.append(row.id)
|
|
||||||
checksum = checksum + row.transferBalance
|
|
||||||
|
|
||||||
balance = commentTransferAmount
|
|
||||||
#c.execute("SELECT sum(transferBalance) FROM transactiontable WHERE address=?", (outputlist[i][0],))
|
|
||||||
#opbalance = c.fetchall()[0][0]
|
|
||||||
opbalance = session.query(func.sum(TransactionTable.transferBalance)).filter_by(address=outputlist[0][0]).all()[0][0]
|
|
||||||
|
|
||||||
if opbalance is None:
|
|
||||||
opbalance = 0
|
|
||||||
|
|
||||||
#c.execute("SELECT sum(transferBalance) FROM transactiontable WHERE address=?", (inputlist[0][0],))
|
|
||||||
#ipbalance = c.fetchall()[0][0]
|
|
||||||
ipbalance = session.query(func.sum(TransactionTable.transferBalance)).filter_by(address=inputlist[0][0]).all()[0][0]
|
|
||||||
|
|
||||||
for pid in pidlst:
|
|
||||||
#c.execute("SELECT transferBalance FROM transactiontable WHERE id=?", (pid,))
|
|
||||||
#temp = c.fetchall()
|
|
||||||
#temp = temp[0][0]
|
|
||||||
temp = session.query(TransactionTable.transferBalance).filter_by(id=pid).all()[0][0]
|
|
||||||
|
|
||||||
if balance <= temp:
|
|
||||||
#c.execute("INSERT INTO transactiontable (address, parentid, transferBalance) VALUES (?,?,?)",
|
|
||||||
# (outputlist[i][0], pid, balance))
|
|
||||||
#c.execute("UPDATE transactiontable SET transferBalance=? WHERE id=?", (temp - balance, pid))
|
|
||||||
|
|
||||||
session.add(TransactionTable(address=outputlist[0][0], parentid=pid, transferBalance=balance))
|
|
||||||
entry = session.query(TransactionTable).filter(TransactionTable.id == pid).all()
|
|
||||||
entry[0].transferBalance = temp - balance
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
## transaction logs section ##
|
|
||||||
result = session.query(TransactionTable.id).order_by(desc(TransactionTable.id)).all()
|
|
||||||
lastid = result[-1].id
|
|
||||||
transferDescription = str(balance) + " tokens transferred to " + str(
|
|
||||||
outputlist[0][0]) + " from " + str(inputlist[0][0])
|
|
||||||
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
|
|
||||||
session.add(TransferLogs(primaryIDReference=lastid, transferDescription=transferDescription,
|
|
||||||
transferIDConsumed=pid, blockchainReference=blockchainReference))
|
|
||||||
transferDescription = str(inputlist[0][0]) + " balance UPDATED from " + str(
|
|
||||||
temp) + " to " + str(temp - balance)
|
|
||||||
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
|
|
||||||
session.add(TransferLogs(primaryIDReference=pid, transferDescription=transferDescription,
|
|
||||||
blockchainReference=blockchainReference))
|
|
||||||
|
|
||||||
## transaction history table ##
|
|
||||||
session.add(TransactionHistory(blockno=blockindex, fromAddress=inputlist[0][0],
|
|
||||||
toAddress=outputlist[0][0], amount=str(balance),
|
|
||||||
blockchainReference=blockchainReference))
|
|
||||||
|
|
||||||
##webpage table section ##
|
|
||||||
transferDescription = str(commentTransferAmount) + " tokens transferred from " + str(
|
|
||||||
inputlist[0][0]) + " to " + str(outputlist[0][0])
|
|
||||||
session.add(
|
|
||||||
Webtable(transferDescription=transferDescription, blockchainReference=blockchainReference))
|
|
||||||
|
|
||||||
transferDescription = "UPDATE " + str(outputlist[0][0]) + " balance from " + str(
|
|
||||||
opbalance) + " to " + str(opbalance + commentTransferAmount)
|
|
||||||
session.add(
|
|
||||||
Webtable(transferDescription=transferDescription, blockchainReference=blockchainReference))
|
|
||||||
|
|
||||||
transferDescription = "UPDATE " + str(inputlist[0][0]) + " balance from " + str(
|
|
||||||
ipbalance) + " to " + str(ipbalance - commentTransferAmount)
|
|
||||||
session.add(
|
|
||||||
Webtable(transferDescription=transferDescription, blockchainReference=blockchainReference))
|
|
||||||
|
|
||||||
balance = 0
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
elif balance > temp:
|
|
||||||
session.add(TransactionTable(address=outputlist[0][0], parentid=pid, transferBalance=temp))
|
|
||||||
entry = session.query(TransactionTable).filter(TransactionTable.id == pid).all()
|
|
||||||
entry[0].transferBalance = 0
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
##transaction logs section ##
|
|
||||||
session.query(TransactionTable.id).order_by(desc(TransactionTable.id))
|
|
||||||
result = session.query(TransactionTable.id).order_by(desc(TransactionTable.id)).all()
|
|
||||||
lastid = result[-1].id
|
|
||||||
transferDescription = str(temp) + " tokens transferred to " + str(
|
|
||||||
outputlist[0][0]) + " from " + str(inputlist[0][0])
|
|
||||||
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
|
|
||||||
session.add(TransactionTable(primaryIDReference=lastid, transferDescription=transferDescription,
|
|
||||||
transferIDConsumed=pid, blockchainReference=blockchainReference))
|
|
||||||
|
|
||||||
transferDescription = str() + " balance UPDATED from " + str(temp) + " to " + str(0)
|
|
||||||
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
|
|
||||||
session.add(TransactionTable(primaryIDReference=pid, transferDescription=transferDescription,
|
|
||||||
blockchainReference=blockchainReference))
|
|
||||||
|
|
||||||
## transaction history table ##
|
|
||||||
session.add(TransactionHistory(blockno=blockindex, fromAddress=inputlist[0][0],
|
|
||||||
toAddress=outputlist[0][0], amount=str(balance),
|
|
||||||
blockchainReference=blockchainReference))
|
|
||||||
balance = balance - temp
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
# Finishing statements
|
|
||||||
session.commit()
|
|
||||||
session.close()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Read configuration
|
|
||||||
config = configparser.ConfigParser()
|
|
||||||
config.read('config.ini')
|
|
||||||
|
|
||||||
# Read command line arguments
|
|
||||||
parser = argparse.ArgumentParser(description='Script tracks RMT using FLO data on the FLO blockchain - https://flo.cash')
|
|
||||||
parser.add_argument('-r', '--reset', nargs='?', const=1, type=int, help='Purge existing db and rebuild it')
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
# Assignment the flo-cli command
|
|
||||||
if config['DEFAULT']['NET'] == 'mainnet':
|
|
||||||
neturl = 'https://florincoin.info/'
|
|
||||||
localapi = config['DEFAULT']['FLO_CLI_PATH']
|
|
||||||
elif config['DEFAULT']['NET'] == 'testnet':
|
|
||||||
neturl = 'https://testnet.florincoin.info/'
|
|
||||||
localapi = '{} --testnet'.format(config['DEFAULT']['FLO_CLI_PATH'])
|
|
||||||
else:
|
|
||||||
print("NET parameter is wrong\nThe script will exit now ")
|
|
||||||
|
|
||||||
|
|
||||||
# Delete database directory if reset is set to 1
|
|
||||||
if args.reset == 1:
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
apppath = os.path.dirname(os.path.realpath(__file__))
|
|
||||||
dirpath = os.path.join(apppath, 'databases')
|
|
||||||
shutil.rmtree(dirpath)
|
|
||||||
os.mkdir(dirpath)
|
|
||||||
|
|
||||||
|
|
||||||
# Read start block no
|
|
||||||
startblock = int(config['DEFAULT']['START_BLOCK'])
|
|
||||||
|
|
||||||
# Find current block height
|
|
||||||
string = "{} getblockcount".format(localapi)
|
|
||||||
response = subprocess.check_output(string, shell=True)
|
|
||||||
current_index = json.loads(response.decode("utf-8"))
|
|
||||||
print("current_block_height : " + str(current_index))
|
|
||||||
|
|
||||||
|
|
||||||
for blockindex in range( startblock, current_index ):
|
|
||||||
print(blockindex)
|
|
||||||
|
|
||||||
# Scan every block
|
|
||||||
string = "{} getblockhash {}".format(localapi, str(blockindex))
|
|
||||||
response = subprocess.check_output(string, shell=True)
|
|
||||||
blockhash = response.decode("utf-8")
|
|
||||||
|
|
||||||
string = "{} getblock {}".format(localapi, str(blockhash))
|
|
||||||
response = subprocess.check_output(string, shell=True)
|
|
||||||
blockinfo = json.loads(response.decode("utf-8"))
|
|
||||||
|
|
||||||
# Scan every transaction
|
|
||||||
for transaction in blockinfo["tx"]:
|
|
||||||
string = "{} getrawtransaction {} 1".format(localapi, str(transaction))
|
|
||||||
response = subprocess.check_output(string, shell=True)
|
|
||||||
transaction_data = json.loads(response.decode("utf-8"))
|
|
||||||
text = transaction_data["floData"]
|
|
||||||
text = text[5:]
|
|
||||||
|
|
||||||
parsed_data = parsing.parse_flodata(text)
|
|
||||||
if parsed_data['type'] != 'noise':
|
|
||||||
print(blockindex)
|
|
||||||
print(parsed_data['type'])
|
|
||||||
startWorking(transaction_data, parsed_data)
|
|
||||||
351
track-tokens.py
351
track-tokens.py
@ -1,351 +0,0 @@
|
|||||||
import requests
|
|
||||||
import json
|
|
||||||
import sqlite3
|
|
||||||
import argparse
|
|
||||||
import configparser
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
|
|
||||||
# Read configuration
|
|
||||||
config = configparser.ConfigParser()
|
|
||||||
config.read('config.ini')
|
|
||||||
|
|
||||||
# Read command line arguments
|
|
||||||
parser = argparse.ArgumentParser(description='Script tracks RMT using FLO data on the FLO blockchain - https://flo.cash')
|
|
||||||
parser.add_argument('-r', '--reset', nargs='?', const=1, type=int, help='Purge existing db and rebuild it')
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
if config['DEFAULT']['NET'] == 'mainnet':
|
|
||||||
neturl = 'https://florincoin.info/'
|
|
||||||
localapi = config['DEFAULT']['FLO_CLI_PATH']
|
|
||||||
elif config['DEFAULT']['NET'] == 'testnet':
|
|
||||||
neturl = 'https://testnet.florincoin.info/'
|
|
||||||
localapi = '{} --testnet'.format(config['DEFAULT']['FLO_CLI_PATH'])
|
|
||||||
else:
|
|
||||||
print('NET parameter is wrong')
|
|
||||||
|
|
||||||
|
|
||||||
def listcheck(lst):
|
|
||||||
for element in lst:
|
|
||||||
try:
|
|
||||||
float(element)
|
|
||||||
except ValueError:
|
|
||||||
print("values to be transferred aren't in the right format")
|
|
||||||
return 1
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def startTracking(blockindex, config, conn, c):
|
|
||||||
string = "{} getblockhash {}".format(localapi, str(blockindex))
|
|
||||||
response = subprocess.check_output(string, shell=True)
|
|
||||||
blockhash = response.decode("utf-8")
|
|
||||||
|
|
||||||
string = "{} getblock {}".format(localapi, str(blockhash))
|
|
||||||
response = subprocess.check_output(string, shell=True)
|
|
||||||
blockinfo = json.loads(response.decode("utf-8"))
|
|
||||||
|
|
||||||
for transaction in blockinfo["tx"]:
|
|
||||||
string = "{} getrawtransaction {} 1".format(localapi, str(transaction))
|
|
||||||
response = subprocess.check_output(string, shell=True)
|
|
||||||
data = json.loads(response.decode("utf-8"))
|
|
||||||
text = data["floData"]
|
|
||||||
text = text[5:]
|
|
||||||
comment_list = text.split("#")
|
|
||||||
|
|
||||||
if comment_list[0] == config['DEFAULT']['PREFIX']:
|
|
||||||
print("I just saw "+str(config['DEFAULT']['PREFIX']))
|
|
||||||
commentTransferAmount = comment_list[1:]
|
|
||||||
|
|
||||||
#if not all(isinstance(x, (int, float)) for x in commentTransferAmount):
|
|
||||||
# print("Values to be transffered aren't in the right format")
|
|
||||||
# continue
|
|
||||||
|
|
||||||
if len(commentTransferAmount) == 0:
|
|
||||||
print("Value for token transfer has not been specified")
|
|
||||||
continue
|
|
||||||
|
|
||||||
returnval = listcheck(commentTransferAmount)
|
|
||||||
if returnval == 1:
|
|
||||||
continue
|
|
||||||
|
|
||||||
commentTransferAmount = list(map(float, commentTransferAmount))
|
|
||||||
|
|
||||||
inputlist = []
|
|
||||||
querylist = []
|
|
||||||
|
|
||||||
for obj in data["vin"]:
|
|
||||||
querylist.append([obj["txid"], obj["vout"]])
|
|
||||||
|
|
||||||
inputval = 0
|
|
||||||
inputadd = ''
|
|
||||||
|
|
||||||
for query in querylist:
|
|
||||||
string = "{} getrawtransaction {} 1".format(localapi, str(query[0]))
|
|
||||||
response = subprocess.check_output(string, shell=True)
|
|
||||||
content = json.loads(response.decode("utf-8"))
|
|
||||||
|
|
||||||
for objec in content["vout"]:
|
|
||||||
if objec["n"] == query[1]:
|
|
||||||
inputadd = objec["scriptPubKey"]["addresses"][0]
|
|
||||||
inputval = inputval + objec["value"]
|
|
||||||
|
|
||||||
inputlist = [[inputadd, inputval]]
|
|
||||||
|
|
||||||
if len(inputlist) > 1:
|
|
||||||
print("Program has detected more than one input address ")
|
|
||||||
print("This transaction will be discarded")
|
|
||||||
continue
|
|
||||||
|
|
||||||
outputlist = []
|
|
||||||
for obj in data["vout"]:
|
|
||||||
if obj["scriptPubKey"]["type"] == "pubkeyhash":
|
|
||||||
if inputlist[0][0] == obj["scriptPubKey"]["addresses"][0]:
|
|
||||||
continue
|
|
||||||
temp = []
|
|
||||||
temp.append(obj["scriptPubKey"]["addresses"][0])
|
|
||||||
temp.append(obj["value"])
|
|
||||||
|
|
||||||
outputlist.append(temp)
|
|
||||||
|
|
||||||
|
|
||||||
print("\n\nInput List")
|
|
||||||
print(inputlist)
|
|
||||||
print("\nOutput List")
|
|
||||||
print(outputlist)
|
|
||||||
|
|
||||||
if len(inputlist) > 1:
|
|
||||||
print("Program has detected more than one input address ")
|
|
||||||
print("This transaction will be discarded")
|
|
||||||
continue
|
|
||||||
|
|
||||||
c.execute("SELECT sum(transferBalance) FROM transactiontable WHERE address=?" , (inputlist[0][0],))
|
|
||||||
availableTokens = c.fetchall()
|
|
||||||
availableTokens = availableTokens[0][0]
|
|
||||||
|
|
||||||
if availableTokens is None:
|
|
||||||
print("The input address dosen't exist in our database ")
|
|
||||||
|
|
||||||
elif availableTokens < sum(commentTransferAmount):
|
|
||||||
print("\nThe transfer amount passed in the comments is more than the user owns\nThis transaction will be discarded\n")
|
|
||||||
continue
|
|
||||||
|
|
||||||
elif availableTokens >= sum(commentTransferAmount):
|
|
||||||
if len(commentTransferAmount) != len(outputlist):
|
|
||||||
print("The parameters in the comments aren't enough")
|
|
||||||
print("This transaction will be discarded")
|
|
||||||
continue
|
|
||||||
|
|
||||||
for i in range(len(commentTransferAmount)):
|
|
||||||
# if output[0] == inputlist[0][0]:
|
|
||||||
# continue
|
|
||||||
|
|
||||||
c.execute("SELECT * FROM transactiontable WHERE address=?",(inputlist[0][0],))
|
|
||||||
table = c.fetchall()
|
|
||||||
|
|
||||||
pidlst = []
|
|
||||||
checksum = 0
|
|
||||||
for row in table:
|
|
||||||
if checksum >= commentTransferAmount[i]:
|
|
||||||
break
|
|
||||||
pidlst.append(row[0])
|
|
||||||
checksum = checksum + row[3]
|
|
||||||
|
|
||||||
balance = commentTransferAmount[i]
|
|
||||||
c.execute("SELECT sum(transferBalance) FROM transactiontable WHERE address=?", ( outputlist[i][0],))
|
|
||||||
opbalance = c.fetchall()[0][0]
|
|
||||||
if opbalance is None:
|
|
||||||
opbalance = 0
|
|
||||||
|
|
||||||
c.execute("SELECT sum(transferBalance) FROM transactiontable WHERE address=?", ( inputlist[0][0],))
|
|
||||||
ipbalance = c.fetchall()[0][0]
|
|
||||||
|
|
||||||
for pid in pidlst:
|
|
||||||
c.execute("SELECT transferBalance FROM transactiontable WHERE id=?", (pid,))
|
|
||||||
temp = c.fetchall()
|
|
||||||
temp = temp[0][0]
|
|
||||||
|
|
||||||
if balance <= temp:
|
|
||||||
c.execute("INSERT INTO transactiontable (address, parentid, transferBalance) VALUES (?,?,?)", (outputlist[i][0],pid,balance))
|
|
||||||
c.execute("UPDATE transactiontable SET transferBalance=? WHERE id=?", (temp-balance, pid))
|
|
||||||
|
|
||||||
## transaction logs section ##
|
|
||||||
c.execute("SELECT id FROM transactiontable ORDER BY id DESC LIMIT 1")
|
|
||||||
lastid = c.fetchall()[0][0]
|
|
||||||
transferDescription = str(balance) + " tokens transferred to " + str(outputlist[i][0]) + " from " + str(inputlist[0][0])
|
|
||||||
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
|
|
||||||
c.execute("""INSERT INTO transferlogs (primaryIDReference, transferDescription, transferIDConsumed, blockchainReference)
|
|
||||||
VALUES (?,?,?,?)""", ( lastid, transferDescription, pid, blockchainReference))
|
|
||||||
|
|
||||||
transferDescription = str(inputlist[0][0]) + " balance UPDATED from " + str(temp) + " to " + str(temp-balance)
|
|
||||||
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
|
|
||||||
c.execute("""INSERT INTO transferlogs (primaryIDReference, transferDescription, blockchainReference)
|
|
||||||
VALUES (?,?,?)""", ( pid, transferDescription, blockchainReference))
|
|
||||||
|
|
||||||
## transaction history table ##
|
|
||||||
c.execute(
|
|
||||||
'''INSERT INTO transactionHistory (blockno, fromAddress, toAddress, amount, blockchainReference) VALUES (?,?,?,?,?)''',
|
|
||||||
(blockindex, inputlist[0][0], outputlist[0][0], str(balance), blockchainReference))
|
|
||||||
|
|
||||||
##webpage table section ##
|
|
||||||
transferDescription = str(commentTransferAmount[i]) + " tokens transferred from " + str(inputlist[0][0]) + " to " + str(outputlist[i][0])
|
|
||||||
c.execute("""INSERT INTO webtable (transferDescription, blockchainReference)
|
|
||||||
VALUES (?,?)""", ( transferDescription, blockchainReference))
|
|
||||||
|
|
||||||
transferDescription = "UPDATE " + str(outputlist[i][0]) + " balance from " + str(opbalance) + " to " + str(opbalance + commentTransferAmount[i])
|
|
||||||
c.execute("""INSERT INTO webtable (transferDescription, blockchainReference)
|
|
||||||
VALUES (?,?)""", ( transferDescription, blockchainReference))
|
|
||||||
|
|
||||||
transferDescription = "UPDATE " + str(inputlist[0][0]) + " balance from " + str(ipbalance) + " to " + str(ipbalance - commentTransferAmount[i])
|
|
||||||
c.execute("""INSERT INTO webtable (transferDescription, blockchainReference)
|
|
||||||
VALUES (?,?)""", ( transferDescription, blockchainReference))
|
|
||||||
|
|
||||||
balance = 0
|
|
||||||
conn.commit()
|
|
||||||
elif balance > temp:
|
|
||||||
c.execute("INSERT INTO transactiontable (address, parentid, transferBalance) VALUES (?,?,?)", (outputlist[i][0], pid, temp ))
|
|
||||||
c.execute("UPDATE transactiontable SET transferBalance=? WHERE id=?", (0, pid))
|
|
||||||
|
|
||||||
##transaction logs section ##
|
|
||||||
c.execute("SELECT id FROM transactiontable ORDER BY id DESC LIMIT 1")
|
|
||||||
lastid = c.fetchall()[0][0]
|
|
||||||
transferDescription = str(temp) + " tokens transferred to " + str(outputlist[i][0]) + " from " + str(inputlist[0][0])
|
|
||||||
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
|
|
||||||
c.execute("""INSERT INTO transferlogs (primaryIDReference, transferDescription, transferIDConsumed, blockchainReference)
|
|
||||||
VALUES (?,?,?,?)""", ( lastid, transferDescription, pid, blockchainReference))
|
|
||||||
|
|
||||||
transferDescription = str() + " balance UPDATED from " + str(temp) + " to " + str(0)
|
|
||||||
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
|
|
||||||
c.execute("""INSERT INTO transferlogs (primaryIDReference, transferDescription, blockchainReference)
|
|
||||||
VALUES (?,?,?)""", ( pid, transferDescription, blockchainReference))
|
|
||||||
|
|
||||||
## transaction history table ##
|
|
||||||
c.execute(
|
|
||||||
'''INSERT INTO transactionHistory (blockno, fromAddress, toAddress, amount, blockchainReference) VALUES (?,?,?,?,?)''',
|
|
||||||
(blockindex, inputlist[0][0], outputlist[0][0], str(balance), blockchainReference))
|
|
||||||
|
|
||||||
balance = balance - temp
|
|
||||||
conn.commit()
|
|
||||||
|
|
||||||
def resetDatabase(c, conn):
|
|
||||||
c.execute("DROP TABLE IF EXISTS transactiontable")
|
|
||||||
c.execute("""CREATE TABLE transactiontable (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
address TEXT,
|
|
||||||
parentid INT,
|
|
||||||
transferBalance REAL
|
|
||||||
)""")
|
|
||||||
|
|
||||||
c.execute("DROP TABLE IF EXISTS transferlogs")
|
|
||||||
c.execute("""CREATE TABLE transferlogs (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
primaryIDReference INTEGER,
|
|
||||||
transferDescription TEXT,
|
|
||||||
transferIDConsumed INT,
|
|
||||||
blockchainReference TEXT
|
|
||||||
)""")
|
|
||||||
|
|
||||||
c.execute("DROP TABLE IF EXISTS webtable")
|
|
||||||
c.execute("""CREATE TABLE webtable (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
transferDescription TEXT,
|
|
||||||
blockchainReference TEXT
|
|
||||||
)""")
|
|
||||||
|
|
||||||
c.execute("DROP TABLE IF EXISTS transactionHistory")
|
|
||||||
c.execute("""CREATE TABLE transactionHistory (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
blockno INT,
|
|
||||||
fromAddress TEXT,
|
|
||||||
toAddress TEXT,
|
|
||||||
amount REAL,
|
|
||||||
blockchainReference TEXT
|
|
||||||
)""")
|
|
||||||
|
|
||||||
c.execute("DROP TABLE IF EXISTS extra")
|
|
||||||
c.execute("CREATE TABLE extra ( id INTEGER PRIMARY KEY , lastblockscanned INT)")
|
|
||||||
conn.commit()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
|
|
||||||
# Connect to db
|
|
||||||
conn = sqlite3.connect(config['DEFAULT']['DB_NAME'])
|
|
||||||
c = conn.cursor()
|
|
||||||
|
|
||||||
# get current block height
|
|
||||||
string = "{} getblockcount".format(localapi)
|
|
||||||
response = subprocess.check_output(string, shell=True)
|
|
||||||
current_index = json.loads(response.decode("utf-8"))
|
|
||||||
print("current_block_height : " + str(current_index))
|
|
||||||
|
|
||||||
if args.reset == 1:
|
|
||||||
resetDatabase(c, conn)
|
|
||||||
# Read root address
|
|
||||||
root_address = config['DEFAULT']['ROOT_ADDRESS']
|
|
||||||
root_init_value = int(config['DEFAULT']['INIT_TOKEN_NO'])
|
|
||||||
|
|
||||||
# Find root address's block no
|
|
||||||
string = "{}ext/getaddress/{}/".format(neturl, str(root_address))
|
|
||||||
response = requests.get(string)
|
|
||||||
content = json.loads(response.content.decode("utf-8"))
|
|
||||||
root_trans_hash = ''
|
|
||||||
for cur in content["last_txs"]:
|
|
||||||
if cur["type"] == "vout":
|
|
||||||
root_trans_hash = cur["addresses"]
|
|
||||||
break
|
|
||||||
|
|
||||||
string = "{} getrawtransaction {} 1".format(localapi, str(root_trans_hash))
|
|
||||||
response = subprocess.check_output(string, shell=True)
|
|
||||||
content = json.loads(response.decode("utf-8"))
|
|
||||||
root_block_hash = content["blockhash"]
|
|
||||||
|
|
||||||
string = "{} getblock {}".format(localapi, str(root_block_hash))
|
|
||||||
response = subprocess.check_output(string, shell=True)
|
|
||||||
content = json.loads(response.decode("utf-8"))
|
|
||||||
root_block_index = content["height"]
|
|
||||||
# root_block_index = 26066
|
|
||||||
|
|
||||||
print("root_block_index = " + str(root_block_index))
|
|
||||||
|
|
||||||
c.execute("INSERT INTO transactiontable ( address, parentid, transferBalance) VALUES (?,?,?)",
|
|
||||||
(root_address, 0, root_init_value))
|
|
||||||
conn.commit()
|
|
||||||
|
|
||||||
transferDescription = "Root address = " + str(root_address) + " has been initialized with " + str(
|
|
||||||
root_init_value) + " tokens"
|
|
||||||
blockchainReference = '{}tx/'.format(neturl)
|
|
||||||
c.execute("""INSERT INTO transferlogs (primaryIDReference, transferDescription, transferIDConsumed, blockchainReference)
|
|
||||||
VALUES (?,?,?,?)""",
|
|
||||||
(1, transferDescription, 0, blockchainReference))
|
|
||||||
|
|
||||||
c.execute(
|
|
||||||
'''INSERT INTO transactionHistory (blockno, fromAddress, toAddress, amount, blockchainReference) VALUES (?,?,?,?,?)''',
|
|
||||||
(root_block_index, '', root_address, root_init_value, blockchainReference))
|
|
||||||
|
|
||||||
c.execute("INSERT INTO extra (id, lastblockscanned) VALUES (?,?)", (1, root_block_index))
|
|
||||||
conn.commit()
|
|
||||||
lastblockscanned = root_block_index
|
|
||||||
|
|
||||||
else:
|
|
||||||
response = requests.get("{}api/getblockcount".format(neturl))
|
|
||||||
string = "{} getblockcount".format(localapi)
|
|
||||||
response = subprocess.check_output(string, shell=True)
|
|
||||||
current_index = json.loads(response.decode("utf-8"))
|
|
||||||
|
|
||||||
c.execute("SELECT lastblockscanned FROM extra WHERE id=1")
|
|
||||||
lastblockscanned = c.fetchall()[0][0]
|
|
||||||
|
|
||||||
|
|
||||||
# run loop and pass blockno
|
|
||||||
for blockindex in range(lastblockscanned + 1, current_index+1):
|
|
||||||
if blockindex == 3127800:
|
|
||||||
print('hi')
|
|
||||||
print(blockindex)
|
|
||||||
startTracking(blockindex, config, conn, c)
|
|
||||||
c.execute("UPDATE extra SET lastblockscanned=? WHERE id=?", (blockindex,1))
|
|
||||||
conn.commit()
|
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
@ -10,7 +10,121 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
from sqlalchemy.orm import sessionmaker, relationship
|
from sqlalchemy.orm import sessionmaker, relationship
|
||||||
from sqlalchemy import create_engine, func, desc
|
from sqlalchemy import create_engine, func, desc
|
||||||
from models import Extra, TransactionHistory, TransactionTable, TransferLogs, Webtable, Base, ContractStructure, ContractBase
|
from models import Extra, TransactionHistory, TransactionTable, TransferLogs, Webtable, Base, ContractStructure, ContractBase, ContractParticipants, SystemBase, ActiveContracts
|
||||||
|
|
||||||
|
|
||||||
|
committeeAddressList = ['oUc4dVvxwK7w5MHUHtev8UawN3eDjiZnNx']
|
||||||
|
|
||||||
|
def transferToken(tokenIdentification, tokenAmount, inputAddress, outputAddress):
|
||||||
|
engine = create_engine('sqlite:///tokens/{}.db'.format(tokenIdentification), echo=True)
|
||||||
|
Base.metadata.create_all(bind=engine)
|
||||||
|
session = sessionmaker(bind=engine)()
|
||||||
|
availableTokens = session.query(func.sum(TransactionTable.transferBalance)).filter_by(address=inputAddress).all()[0][0]
|
||||||
|
commentTransferAmount = tokenAmount
|
||||||
|
if availableTokens is None:
|
||||||
|
print("The input address dosen't exist in our database ")
|
||||||
|
session.close()
|
||||||
|
return None
|
||||||
|
|
||||||
|
elif availableTokens < commentTransferAmount:
|
||||||
|
print(
|
||||||
|
"\nThe transfer amount passed in the comments is more than the user owns\nThis transaction will be discarded\n")
|
||||||
|
session.close()
|
||||||
|
return None
|
||||||
|
|
||||||
|
elif availableTokens >= commentTransferAmount:
|
||||||
|
table = session.query(TransactionTable).filter(TransactionTable.address==inputAddress, TransactionTable.transferBalance>0).all()
|
||||||
|
pidlst = []
|
||||||
|
checksum = 0
|
||||||
|
for row in table:
|
||||||
|
if checksum >= commentTransferAmount:
|
||||||
|
break
|
||||||
|
pidlst.append(row.id)
|
||||||
|
checksum = checksum + row.transferBalance
|
||||||
|
|
||||||
|
balance = commentTransferAmount
|
||||||
|
opbalance = session.query(func.sum(TransactionTable.transferBalance)).filter_by(address=outputAddress).all()[0][0]
|
||||||
|
|
||||||
|
if opbalance is None:
|
||||||
|
opbalance = 0
|
||||||
|
|
||||||
|
ipbalance = availableTokens
|
||||||
|
|
||||||
|
for pid in pidlst:
|
||||||
|
temp = session.query(TransactionTable.transferBalance).filter_by(id=pid).all()[0][0]
|
||||||
|
|
||||||
|
if balance <= temp:
|
||||||
|
|
||||||
|
session.add(TransactionTable(address=outputAddress, parentid=pid, transferBalance=balance))
|
||||||
|
entry = session.query(TransactionTable).filter(TransactionTable.id == pid).all()
|
||||||
|
entry[0].transferBalance = temp - balance
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
## transaction logs section ##
|
||||||
|
result = session.query(TransactionTable.id).order_by(desc(TransactionTable.id)).all()
|
||||||
|
lastid = result[-1].id
|
||||||
|
transferDescription = str(balance) + " tokens transferred to " + str(
|
||||||
|
outputAddress) + " from " + str(inputAddress)
|
||||||
|
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
|
||||||
|
session.add(TransferLogs(primaryIDReference=lastid, transferDescription=transferDescription,
|
||||||
|
transferIDConsumed=pid, blockchainReference=blockchainReference))
|
||||||
|
transferDescription = str(inputAddress) + " balance UPDATED from " + str(
|
||||||
|
temp) + " to " + str(temp - balance)
|
||||||
|
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
|
||||||
|
session.add(TransferLogs(primaryIDReference=pid, transferDescription=transferDescription,
|
||||||
|
blockchainReference=blockchainReference))
|
||||||
|
|
||||||
|
## transaction history table ##
|
||||||
|
session.add(TransactionHistory(blockno=blockindex, fromAddress=inputAddress,
|
||||||
|
toAddress=outputAddress, amount=str(balance),
|
||||||
|
blockchainReference=blockchainReference))
|
||||||
|
|
||||||
|
##webpage table section ##
|
||||||
|
transferDescription = str(commentTransferAmount) + " tokens transferred from " + str(
|
||||||
|
inputAddress) + " to " + str(outputAddress)
|
||||||
|
session.add(
|
||||||
|
Webtable(transferDescription=transferDescription, blockchainReference=blockchainReference))
|
||||||
|
|
||||||
|
transferDescription = "UPDATE " + str(outputAddress) + " balance from " + str(
|
||||||
|
opbalance) + " to " + str(opbalance + commentTransferAmount)
|
||||||
|
session.add(
|
||||||
|
Webtable(transferDescription=transferDescription, blockchainReference=blockchainReference))
|
||||||
|
|
||||||
|
transferDescription = "UPDATE " + str(inputAddress) + " balance from " + str(
|
||||||
|
ipbalance) + " to " + str(ipbalance - commentTransferAmount)
|
||||||
|
session.add(
|
||||||
|
Webtable(transferDescription=transferDescription, blockchainReference=blockchainReference))
|
||||||
|
|
||||||
|
balance = 0
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
elif balance > temp:
|
||||||
|
session.add(TransactionTable(address=outputAddress, parentid=pid, transferBalance=temp))
|
||||||
|
entry = session.query(TransactionTable).filter(TransactionTable.id == pid).all()
|
||||||
|
entry[0].transferBalance = 0
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
##transaction logs section ##
|
||||||
|
result = session.query(TransactionTable.id).order_by(desc(TransactionTable.id)).all()
|
||||||
|
lastid = result[-1].id
|
||||||
|
transferDescription = str(temp) + " tokens transferred to " + str(outputAddress) + " from " + str(inputAddress)
|
||||||
|
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
|
||||||
|
session.add(TransferLogs(primaryIDReference=lastid, transferDescription=transferDescription,
|
||||||
|
transferIDConsumed=pid, blockchainReference=blockchainReference))
|
||||||
|
|
||||||
|
transferDescription = str() + " balance UPDATED from " + str(temp) + " to " + str(0)
|
||||||
|
blockchainReference = '{}tx/{}'.format(neturl, str(transaction))
|
||||||
|
session.add(TransferLogs(primaryIDReference=pid, transferDescription=transferDescription,
|
||||||
|
blockchainReference=blockchainReference))
|
||||||
|
|
||||||
|
## transaction history table ##
|
||||||
|
session.add(TransactionHistory(blockno=blockindex, fromAddress=inputAddress,
|
||||||
|
toAddress=outputAddress, amount=str(balance),
|
||||||
|
blockchainReference=blockchainReference))
|
||||||
|
balance = balance - temp
|
||||||
|
session.commit()
|
||||||
|
session.close()
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
def startWorking(transaction_data, parsed_data):
|
def startWorking(transaction_data, parsed_data):
|
||||||
@ -67,25 +181,30 @@ def startWorking(transaction_data, parsed_data):
|
|||||||
if parsed_data['type'] == 'transfer':
|
if parsed_data['type'] == 'transfer':
|
||||||
print('Found a transaction of the type transfer')
|
print('Found a transaction of the type transfer')
|
||||||
|
|
||||||
if parsed_data['transferType'] == 'smartContract':
|
if parsed_data['transferType'] == 'token':
|
||||||
print('do something')
|
|
||||||
|
|
||||||
elif parsed_data['transferType'] == 'token':
|
returnval = transferToken(parsed_data['tokenIdentification'], parsed_data['tokenAmount'], inputlist[0][0], outputlist[0][0])
|
||||||
engine = create_engine('sqlite:///tokens/{}.db'.format(parsed_data['tokenIdentification']), echo=True)
|
if returnval is None:
|
||||||
|
print("Something went wrong in the token transfer method")
|
||||||
|
|
||||||
|
elif parsed_data['transferType'] == 'smartContract':
|
||||||
|
|
||||||
|
# Check if the tokenAmount being transferred exists in the address & do the token transfer
|
||||||
|
returnval = transferToken(parsed_data['tokenIdentification'], parsed_data['tokenAmount'], inputlist[0][0], outputlist[0][0])
|
||||||
|
if returnval is not None:
|
||||||
|
# Store participant details in the smart contract's db
|
||||||
|
engine = create_engine('sqlite:///smartContracts/{}.db'.format(parsed_data['contractName']), echo=True)
|
||||||
Base.metadata.create_all(bind=engine)
|
Base.metadata.create_all(bind=engine)
|
||||||
session = sessionmaker(bind=engine)()
|
session = sessionmaker(bind=engine)()
|
||||||
availableTokens = session.query(func.sum(TransactionTable.transferBalance)).filter_by(address=inputlist[0][0]).all()[0][0]
|
session.add(ContractParticipants(participantAddress=inputadd, tokenAmount=parsed_data['tokenAmount'],
|
||||||
commentTransferAmount = parsed_data['amount']
|
contractCondition=parsed_data['contractCondition']))
|
||||||
if availableTokens is None:
|
session.commit()
|
||||||
print("The input address dosen't exist in our database ")
|
session.close()
|
||||||
|
|
||||||
elif availableTokens < commentTransferAmount:
|
|
||||||
print(
|
|
||||||
"\nThe transfer amount passed in the comments is more than the user owns\nThis transaction will be discarded\n")
|
|
||||||
return
|
|
||||||
|
|
||||||
elif availableTokens >= commentTransferAmount:
|
else:
|
||||||
print("well i've reached here")
|
print("Something went wrong in the smartcontract token transfer method")
|
||||||
|
|
||||||
|
|
||||||
elif parsed_data['type'] == 'tokenIncorporation':
|
elif parsed_data['type'] == 'tokenIncorporation':
|
||||||
if not os.path.isfile('./tokens/{}.db'.format(parsed_data['tokenIdentification'])):
|
if not os.path.isfile('./tokens/{}.db'.format(parsed_data['tokenIdentification'])):
|
||||||
@ -112,7 +231,7 @@ def startWorking(transaction_data, parsed_data):
|
|||||||
session.add(
|
session.add(
|
||||||
ContractStructure(attribute='tokenIdentification', index=0, value=parsed_data['tokenIdentification']))
|
ContractStructure(attribute='tokenIdentification', index=0, value=parsed_data['tokenIdentification']))
|
||||||
session.add(
|
session.add(
|
||||||
ContractStructure(attribute='contractAddress', index=0, value=parsed_data['contractAddress'][:-1]))
|
ContractStructure(attribute='contractAddress', index=0, value=parsed_data['contractAddress']))
|
||||||
session.add(
|
session.add(
|
||||||
ContractStructure(attribute='flodata', index=0,
|
ContractStructure(attribute='flodata', index=0,
|
||||||
value=parsed_data['flodata']))
|
value=parsed_data['flodata']))
|
||||||
@ -123,11 +242,50 @@ def startWorking(transaction_data, parsed_data):
|
|||||||
session.add(ContractStructure(attribute='exitconditions', index=key, value=value))
|
session.add(ContractStructure(attribute='exitconditions', index=key, value=value))
|
||||||
session.commit()
|
session.commit()
|
||||||
session.close()
|
session.close()
|
||||||
|
|
||||||
|
# Store smart contract address in system's db, to be ignored during future transfers
|
||||||
|
engine = create_engine('sqlite:///system.db',
|
||||||
|
echo=True)
|
||||||
|
SystemBase.metadata.create_all(bind=engine)
|
||||||
|
session = sessionmaker(bind=engine)()
|
||||||
|
session.add(
|
||||||
|
ActiveContracts(contractName=parsed_data['contractName'], contractAddress=parsed_data['contractAddress']))
|
||||||
|
session.commit()
|
||||||
|
session.close()
|
||||||
else:
|
else:
|
||||||
print('Transaction rejected as a smartcontract with same name has already been incorporated')
|
print('Transaction rejected as a smartcontract with same name has already been incorporated')
|
||||||
elif parsed_data['type'] == 'smartContractPays':
|
elif parsed_data['type'] == 'smartContractPays':
|
||||||
print('Found a transaction of the type smartContractPays')
|
print('Found a transaction of the type smartContractPays')
|
||||||
|
|
||||||
|
# Check if input address is a committee address
|
||||||
|
if inputlist[0][0] in committeeAddressList:
|
||||||
|
|
||||||
|
# Check if the output address is an active Smart contract address
|
||||||
|
engine = create_engine('sqlite:///system.db', echo=True)
|
||||||
|
connection = engine.connect()
|
||||||
|
activeContracts = connection.execute('select * from activecontracts').fetchall()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
# Change columns into rows - https://stackoverflow.com/questions/44360162/how-to-access-a-column-in-a-list-of-lists-in-python
|
||||||
|
activeContracts = list(zip(*activeContracts))
|
||||||
|
if outputlist[0][0] in activeContracts[2] and parsed_data['contractName'] in activeContracts[1]:
|
||||||
|
|
||||||
|
engine = create_engine('sqlite:///smartContracts/{}.db'.format(parsed_data['contractName']), echo=True)
|
||||||
|
connection = engine.connect()
|
||||||
|
contractWinners = connection.execute('select * from contractparticipants where contractCondition="{}"'.format(parsed_data['triggerCondition'])).fetchall()
|
||||||
|
tokenSum = connection.execute('select sum(tokenAmount) from contractparticipants').fetchall()[0][0]
|
||||||
|
tokenIdentification = connection.execute('select value from contractstructure where attribute="tokenIdentification"').fetchall()[0][0]
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
contractWinners = list(zip(*contractWinners))
|
||||||
|
for address in contractWinners[1]:
|
||||||
|
transferToken(tokenIdentification, tokenSum/len(contractWinners[1]), outputlist[0][0], address)
|
||||||
|
|
||||||
|
else:
|
||||||
|
print('This trigger doesn\'t apply to an active contract. It will be discarded')
|
||||||
|
|
||||||
|
else:
|
||||||
|
print('Input address is not part of the committee address list. This trigger is rejected')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -150,6 +308,13 @@ elif config['DEFAULT']['NET'] == 'testnet':
|
|||||||
else:
|
else:
|
||||||
print("NET parameter is wrong\nThe script will exit now ")
|
print("NET parameter is wrong\nThe script will exit now ")
|
||||||
|
|
||||||
|
apppath = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
dirpath = os.path.join(apppath, 'tokens')
|
||||||
|
if not os.path.isdir(dirpath):
|
||||||
|
os.mkdir(dirpath)
|
||||||
|
dirpath = os.path.join(apppath, 'smartContracts')
|
||||||
|
if not os.path.isdir(dirpath):
|
||||||
|
os.mkdir(dirpath)
|
||||||
|
|
||||||
# Delete database and smartcontract directory if reset is set to 1
|
# Delete database and smartcontract directory if reset is set to 1
|
||||||
if args.reset == 1:
|
if args.reset == 1:
|
||||||
@ -160,6 +325,9 @@ if args.reset == 1:
|
|||||||
dirpath = os.path.join(apppath, 'smartContracts')
|
dirpath = os.path.join(apppath, 'smartContracts')
|
||||||
shutil.rmtree(dirpath)
|
shutil.rmtree(dirpath)
|
||||||
os.mkdir(dirpath)
|
os.mkdir(dirpath)
|
||||||
|
dirpath = os.path.join(apppath, 'system.db')
|
||||||
|
if os.path.exists(dirpath):
|
||||||
|
os.remove(dirpath)
|
||||||
|
|
||||||
|
|
||||||
# Read start block no
|
# Read start block no
|
||||||
@ -191,6 +359,9 @@ for blockindex in range( startblock, current_index ):
|
|||||||
transaction_data = json.loads(response.decode("utf-8"))
|
transaction_data = json.loads(response.decode("utf-8"))
|
||||||
text = transaction_data["floData"]
|
text = transaction_data["floData"]
|
||||||
|
|
||||||
|
if blockindex == 498385:
|
||||||
|
print('debug point')
|
||||||
|
|
||||||
parsed_data = parsing.parse_flodata(text)
|
parsed_data = parsing.parse_flodata(text)
|
||||||
if parsed_data['type'] != 'noise':
|
if parsed_data['type'] != 'noise':
|
||||||
print(blockindex)
|
print(blockindex)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user