Cleaner external trigger logic

This commit is contained in:
Vivek Teega 2019-12-22 22:18:57 +05:30
parent 44134365e5
commit acd85a6a02

View File

@ -64,10 +64,10 @@ def multiRequest(apicall, net):
def pushData_SSEapi(message): def pushData_SSEapi(message):
signature = pybtc.sign_message(message.encode(), privKey) signature = pybtc.sign_message(message.encode(), privKey)
headers = {'Accept': 'application/json', 'Content-Type': 'application/json', 'Signature': signature} headers = {'Accept': 'application/json', 'Content-Type': 'application/json', 'Signature': signature}
try: '''try:
r = requests.post(sseAPI_url, json={'message': '{}'.format(message)}, headers=headers) r = requests.post(sseAPI_url, json={'message': '{}'.format(message)}, headers=headers)
except: except:
logger.error("couldn't push the following message to SSE api {}".format(message)) logger.error("couldn't push the following message to SSE api {}".format(message))'''
def processBlock(blockindex): def processBlock(blockindex):
@ -543,7 +543,7 @@ def processTransaction(transaction_data, parsed_data):
pushData_SSEapi(f"Error | Something went wrong while doing the internal db transactions for {transaction_data['txid']}") pushData_SSEapi(f"Error | Something went wrong while doing the internal db transactions for {transaction_data['txid']}")
return 0 return 0
else: else:
updateLatestTransaction(transaction_data, parsed_data, transaction_data['blockheight']) updateLatestTransaction(transaction_data, parsed_data)
# If this is the first interaction of the outputlist's address with the given token name, add it to token mapping # If this is the first interaction of the outputlist's address with the given token name, add it to token mapping
engine = create_engine('sqlite:///system.db', echo=True) engine = create_engine('sqlite:///system.db', echo=True)
@ -559,7 +559,7 @@ def processTransaction(transaction_data, parsed_data):
# Pass information to SSE channel # Pass information to SSE channel
url = 'https://ranchimallflo.duckdns.org/' url = 'https://ranchimallflo.duckdns.org/'
headers = {'Accept': 'application/json', 'Content-Type': 'application/json'} headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
r = requests.post(url, json={f"message': 'Token Transfer | name:{parsed_data['tokenIdentification']} | transactionHash:{transaction_data['txid']}"}, headers=headers) #r = requests.post(url, json={f"message': 'Token Transfer | name:{parsed_data['tokenIdentification']} | transactionHash:{transaction_data['txid']}"}, headers=headers)
else: else:
logger.info( logger.info(
f"Token transfer at transaction {transaction_data['txid']} rejected as a token with the name {parsed_data['tokenIdentification']} doesnt not exist") f"Token transfer at transaction {transaction_data['txid']} rejected as a token with the name {parsed_data['tokenIdentification']} doesnt not exist")
@ -630,9 +630,9 @@ def processTransaction(transaction_data, parsed_data):
url = 'https://ranchimallflo.duckdns.org/' url = 'https://ranchimallflo.duckdns.org/'
headers = {'Accept': 'application/json', 'Content-Type': 'application/json'} headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
r = requests.post(url, json={ '''r = requests.post(url, json={
'message': f"Error | Contract participation at transaction {transaction_data['txid']} rejected as contractAddress specified in flodata, {parsed_data['contractAddress']}, doesnt not match with transaction's output address {outputlist[0]}"}, 'message': f"Error | Contract participation at transaction {transaction_data['txid']} rejected as contractAddress specified in flodata, {parsed_data['contractAddress']}, doesnt not match with transaction's output address {outputlist[0]}"},
headers=headers) headers=headers)'''
return 0 return 0
# Pass information to SSE channel # Pass information to SSE channel
@ -673,9 +673,9 @@ def processTransaction(transaction_data, parsed_data):
url = 'https://ranchimallflo.duckdns.org/' url = 'https://ranchimallflo.duckdns.org/'
headers = {'Accept': 'application/json', 'Content-Type': 'application/json'} headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
r = requests.post(url, json={ '''r = requests.post(url, json={
'message': f"Error | Transaction {parsed_data['txid']} closed as Smart contract {parsed_data['contractName']} at the {outputlist[0]} is closed"}, 'message': f"Error | Transaction {parsed_data['txid']} closed as Smart contract {parsed_data['contractName']} at the {outputlist[0]} is closed"},
headers=headers) headers=headers)'''
return 0 return 0
else: else:
engine = create_engine( engine = create_engine(
@ -1140,9 +1140,9 @@ def processTransaction(transaction_data, parsed_data):
url = 'https://ranchimallflo.duckdns.org/' url = 'https://ranchimallflo.duckdns.org/'
headers = {'Accept': 'application/json', 'Content-Type': 'application/json'} headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
r = requests.post(url, json={ '''r = requests.post(url, json={
'message': f"Error | Transaction {transaction_data['txid']} rejected as the participation doesn't belong to any valid contract type"}, 'message': f"Error | Transaction {transaction_data['txid']} rejected as the participation doesn't belong to any valid contract type"},
headers=headers) headers=headers)'''
return 0 return 0
else: else:
@ -1171,9 +1171,9 @@ def processTransaction(transaction_data, parsed_data):
url = 'https://ranchimallflo.duckdns.org/' url = 'https://ranchimallflo.duckdns.org/'
headers = {'Accept': 'application/json', 'Content-Type': 'application/json'} headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
r = requests.post(url, json={ '''r = requests.post(url, json={
'message': f"Error | Contract transaction {transaction_data['txid']} rejected as a smartcontract with same name {parsed_data['contractName']}-{parsed_data['contractAddress']} dosent exist "}, 'message': f"Error | Contract transaction {transaction_data['txid']} rejected as a smartcontract with same name {parsed_data['contractName']}-{parsed_data['contractAddress']} dosent exist "},
headers=headers) headers=headers)'''
return 0 return 0
# todo Rule 47 - If the parsed data type is token incorporation, then check if the name hasn't been taken already # todo Rule 47 - If the parsed data type is token incorporation, then check if the name hasn't been taken already
@ -1412,73 +1412,70 @@ def processTransaction(transaction_data, parsed_data):
url = 'https://ranchimallflo.duckdns.org/' url = 'https://ranchimallflo.duckdns.org/'
headers = {'Accept': 'application/json', 'Content-Type': 'application/json'} headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
r = requests.post(url, json={ '''r = requests.post(url, json={
'message': 'Error | Contract Incorporation rejected as a smartcontract with same name {}-{} is active currentlyt at transaction {}'.format(parsed_data['contractName'], parsed_data['contractAddress'], transaction_data['txid'])}, headers=headers) 'message': 'Error | Contract Incorporation rejected as a smartcontract with same name {}-{} is active currentlyt at transaction {}'.format(parsed_data['contractName'], parsed_data['contractAddress'], transaction_data['txid'])}, headers=headers)
'''
return 0 return 0
elif parsed_data['type'] == 'smartContractPays': elif parsed_data['type'] == 'smartContractPays':
logger.debug('Found a transaction of the type smartContractPays') logger.debug(f"Transaction {transaction_data['txid']} is of the type smartContractPays")
# Check if input address is a committee address # Check if input address is a committee address
if inputlist[0] in committeeAddressList: if inputlist[0] in committeeAddressList:
# Check if the output address is an active Smart contract address # check if the contract exists
engine = create_engine('sqlite:///system.db', echo=True) if os.path.isfile(f"./smartContracts/{parsed_data['contractName']}-{parsed_data['contractAddress']}.db"):
connection = engine.connect()
# todo : Get only activeContracts which have non-local trigger ie. committee triggers them
contractDetails = connection.execute('select contractName, contractAddress from activecontracts where status=="expired"').fetchall() # Check if the transaction hash already exists in the contract db (Safety check)
connection.close() engine = create_engine(
contractList = [] 'sqlite:///smartContracts/{}-{}.db'.format(parsed_data['contractName'], outputlist[0]), echo=True)
connection = engine.connect()
participantAdd_txhash = connection.execute(
'select participantAddress, transactionHash from contractparticipants').fetchall()
participantAdd_txhash_T = list(zip(*participantAdd_txhash))
counter = 0 if len(participantAdd_txhash) != 0 and transaction_data['txid'] in list(participantAdd_txhash_T[1]):
for contract in contractDetails: logger.warning(
if contract[0] == parsed_data['contractName'] and contract[1] == outputlist[0]: f"Transaction {transaction_data['txid']} rejected as it already exists in the Smart Contract db. This is unusual, please check your code")
counter = counter + 1 pushData_SSEapi(
f"Error | Transaction {transaction_data['txid']} rejected as it already exists in the Smart Contract db. This is unusual, please check your code")
if counter != 1: return 0
logger.info('Active Smart contract with the given name doesn\'t exist\n This committee trigger will be rejected')
return 0
# Check if the contract has maximumsubscriptionamount and if it has reached it
engine = create_engine('sqlite:///smartContracts/{}-{}.db'.format(parsed_data['contractName'], outputlist[0]), echo=True)
connection = engine.connect()
ContractBase.metadata.create_all(bind=engine)
session = sessionmaker(bind=engine)()
# todo : filter activeContracts which only have local triggers
contractStructure = connection.execute('select * from contractstructure').fetchall()
contractStructure_T = list(zip(*contractStructure))
if 'maximumsubscriptionamount' in list(contractStructure_T[1]):
maximumsubscriptionamount = connection.execute('select value from contractstructure where attribute=="maximumsubscriptionamount"').fetchall()[0][0]
tokenAmount_sum = connection.execute('select sum(tokenAmount) from contractparticipants').fetchall()[0][0]
if tokenAmount_sum >= maximumsubscriptionamount:
# Trigger the contract
contractWinners = connection.execute(
'select * from contractparticipants where userChoice="{}"'.format(
parsed_data['triggerCondition'])).fetchall()
tokenSum = connection.execute('select sum(tokenAmount) from contractparticipants').fetchall()[0][0]
winnerSum = connection.execute(
'select sum(tokenAmount) from contractparticipants where userChoice="{}"'.format(
parsed_data['triggerCondition'])).fetchall()[0][0]
tokenIdentification = connection.execute(
'select value from contractstructure where attribute="tokenIdentification"').fetchall()[0][0]
for winner in contractWinners:
winnerAmount = "%.8f" % ((winner[2] / winnerSum) * tokenSum)
returnval = transferToken(tokenIdentification, winnerAmount,
outputlist[0], winner[1], transaction_data)
if returnval is None:
logger.critical("Something went wrong in the token transfer method while doing local Smart Contract Trigger")
return 0
connection.execute(
'update contractparticipants set winningAmount="{}" where participantAddress="{}" and transactionHash="{}"'.format(
(winnerAmount, winner[1], winner[4])))
# add transaction to ContractTransactionHistory # pull out the contract structure into a dictionary
engine = create_engine(
'sqlite:///smartContracts/{}-{}.db'.format(parsed_data['contractName'], outputlist[0]), echo=True)
connection = engine.connect()
attributevaluepair = connection.execute(
"select attribute, value from contractstructure where attribute != 'contractName' and attribute != 'flodata' and attribute != 'contractAddress'").fetchall()
contractStructure = {}
conditionDict = {}
counter = 0
for item in attributevaluepair:
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
# check if output address is contract Incorporation address
if outputlist[0] != conditionDict['contractAddress']:
logger.warning(
f"Transaction {transaction_data['txid']} rejected as Smart Contract named {parsed_data['contractName']} at the address {outputlist[0]} hasn't expired yet")
# Store transfer as part of RejectedContractTransactionHistory
engine = create_engine(
f"sqlite:///smartContracts/{parsed_data['contractName']}-{outputlist[0]}.db",
echo=True)
ContractBase.metadata.create_all(bind=engine)
session = sessionmaker(bind=engine)()
blockchainReference = neturl + 'tx/' + transaction_data['txid'] blockchainReference = neturl + 'tx/' + transaction_data['txid']
session.add(ContractTransactionHistory(transactionType='trigger', sourceFloAddress=inputadd, session.add(
RejectedContractTransactionHistory(transactionType='trigger',
sourceFloAddress=inputadd,
destFloAddress=outputlist[0], destFloAddress=outputlist[0],
transferAmount=None, transferAmount=None,
blockNumber=transaction_data['blockheight'], blockNumber=transaction_data['blockheight'],
@ -1486,47 +1483,172 @@ def processTransaction(transaction_data, parsed_data):
time=transaction_data['blocktime'], time=transaction_data['blocktime'],
transactionHash=transaction_data['txid'], transactionHash=transaction_data['txid'],
blockchainReference=blockchainReference, blockchainReference=blockchainReference,
jsonData=json.dumps(transaction_data))) jsonData=json.dumps(transaction_data),
rejectComment=f"Transaction {transaction_data['txid']} rejected as Smart Contract named {parsed_data['contractName']} at the address {outputlist[0]} hasn't expired yet"))
engine = create_engine('sqlite:///system.db', echo=True) pushData_SSEapi(
connection = engine.connect() f"Error | Transaction {transaction_data['txid']} rejected as Smart Contract named {parsed_data['contractName']} at the address {outputlist[0]} hasn't expired yet")
connection.execute( return 0
'update activecontracts set status="closed" where contractName="{}" and contractAddress="{}"'.format(parsed_data['contractName'], outputlist[0]))
connection.execute(
'update activecontracts set closeDate="{}" where contractName="{}" and contractAddress="{}"'.format(transaction_data['blocktime'],
parsed_data['contractName'], outputlist[0]))
connection.close()
updateLatestTransaction(transaction_data, parsed_data)
pushData_SSEapi('Trigger | Contract triggered of the name {}-{} is active currently at transaction {}'.format(parsed_data['contractName'], outputlist[0], transaction_data['txid']))
return
# Check if contract has passed expiry time # check the type of smart contract ie. external trigger or internal trigger
expiryTime = connection.execute('select value from contractstructure where attribute=="expiryTime"').fetchall()[0][0] if 'payeeAdress' in contractStructure:
expirytime_split = expiryTime.split(' ') logger.warning(
parse_string = '{}/{}/{} {}'.format(expirytime_split[3], parsing.months[expirytime_split[1]], f"Transaction {transaction_data['txid']} rejected as Smart Contract named {parsed_data['contractName']} at the address {outputlist[0]} has an internal trigger")
expirytime_split[2], expirytime_split[4]) # Store transfer as part of RejectedContractTransactionHistory
expirytime_object = parsing.arrow.get(parse_string, 'YYYY/M/D HH:mm:ss').replace( engine = create_engine(
tzinfo=expirytime_split[5][3:]) f"sqlite:///smartContracts/{parsed_data['contractName']}-{outputlist[0]}.db",
blocktime_object = parsing.arrow.get(transaction_data['blocktime']).to('Asia/Kolkata') echo=True)
connection.close() ContractBase.metadata.create_all(bind=engine)
session = sessionmaker(bind=engine)()
if blocktime_object > expirytime_object: blockchainReference = neturl + 'tx/' + transaction_data['txid']
# Check if the minimum subscription amount has been reached if it exists as part of the structure session.add(
engine = create_engine('sqlite:///smartContracts/{}-{}.db'.format(parsed_data['contractName'], outputlist[0]), echo=True) RejectedContractTransactionHistory(transactionType='trigger',
ContractBase.metadata.create_all(bind=engine) sourceFloAddress=inputadd,
session = sessionmaker(bind=engine)() destFloAddress=outputlist[0],
result = session.query(ContractStructure).filter_by(attribute='minimumsubscriptionamount').all() transferAmount=None,
session.close() blockNumber=transaction_data['blockheight'],
if result: blockHash=transaction_data['blockhash'],
minimumsubscriptionamount = float(result[0].value.strip()) time=transaction_data['blocktime'],
engine = create_engine('sqlite:///smartContracts/{}-{}.db'.format(parsed_data['contractName'], outputlist[0]), transactionHash=transaction_data['txid'],
echo=True) blockchainReference=blockchainReference,
jsonData=json.dumps(transaction_data),
rejectComment=f"Transaction {transaction_data['txid']} rejected as Smart Contract named {parsed_data['contractName']} at the address {outputlist[0]} has an internal trigger"))
pushData_SSEapi(
pushData_SSEapi(
f"Error | Transaction {transaction_data['txid']} rejected as Smart Contract named {parsed_data['contractName']} at the address {outputlist[0]} has an internal trigger")
return 0
# check the status of the contract
engine = create_engine('sqlite:///system.db', echo=True)
connection = engine.connect()
contractStatus = connection.execute(
f"select status from activecontracts where contractName=='{parsed_data['contractName']}' and contractAddress='{outputlist[0]}'").fetchall()[
0][0]
connection.close()
contractList = []
if contractStatus == 'closed':
logger.info(
f"Transaction {parsed_data['txid']} closed as Smart contract {parsed_data['contractName']} at the {outputlist[0]} is closed")
# Store transfer as part of RejectedContractTransactionHistory
engine = create_engine(
f"sqlite:///smartContracts/{parsed_data['contractName']}-{outputlist[0]}.db",
echo=True)
ContractBase.metadata.create_all(bind=engine)
session = sessionmaker(bind=engine)()
blockchainReference = neturl + 'tx/' + transaction_data['txid']
session.add(
RejectedContractTransactionHistory(transactionType='trigger',
sourceFloAddress=inputadd,
destFloAddress=outputlist[0],
transferAmount=None,
blockNumber=transaction_data['blockheight'],
blockHash=transaction_data['blockhash'],
time=transaction_data['blocktime'],
transactionHash=transaction_data['txid'],
blockchainReference=blockchainReference,
jsonData=json.dumps(transaction_data),
rejectComment=f"Transaction {parsed_data['txid']} closed as Smart contract {parsed_data['contractName']} at the {outputlist[0]} is closed"))
session.commit()
session.close()
url = 'https://ranchimallflo.duckdns.org/'
headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
'''r = requests.post(url, json={
'message': f"Error | Transaction {parsed_data['txid']} closed as Smart contract {parsed_data['contractName']} at the {outputlist[0]} is closed"},
headers=headers)'''
return 0
else:
engine = create_engine(
'sqlite:///smartContracts/{}-{}.db'.format(parsed_data['contractName'], outputlist[0]),
echo=True)
ContractBase.metadata.create_all(bind=engine)
session = sessionmaker(bind=engine)()
result = session.query(ContractStructure).filter_by(attribute='expiryTime').all()
session.close()
if result:
# now parse the expiry time in python
expirytime = result[0].value.strip()
expirytime_split = expirytime.split(' ')
parse_string = '{}/{}/{} {}'.format(expirytime_split[3],
parsing.months[expirytime_split[1]],
expirytime_split[2], expirytime_split[4])
expirytime_object = parsing.arrow.get(parse_string, 'YYYY/M/D HH:mm:ss').replace(
tzinfo=expirytime_split[5][3:])
blocktime_object = parsing.arrow.get(transaction_data['blocktime']).to('Asia/Kolkata')
if blocktime_object <= expirytime_object:
logger.info(
f"Transaction {parsed_data['txid']} rejected as Smart contract {parsed_data['contractName']}-{outputlist[0]} has not expired and will not trigger")
# Store transfer as part of RejectedContractTransactionHistory
engine = create_engine(
f"sqlite:///smartContracts/{parsed_data['contractName']}-{outputlist[0]}.db",
echo=True)
ContractBase.metadata.create_all(bind=engine)
session = sessionmaker(bind=engine)()
blockchainReference = neturl + 'tx/' + transaction_data['txid']
session.add(
RejectedContractTransactionHistory(transactionType='trigger',
sourceFloAddress=inputadd,
destFloAddress=outputlist[0],
transferAmount=None,
blockNumber=transaction_data['blockheight'],
blockHash=transaction_data['blockhash'],
time=transaction_data['blocktime'],
transactionHash=transaction_data['txid'],
blockchainReference=blockchainReference,
jsonData=json.dumps(transaction_data),
rejectComment=f"Transaction {parsed_data['txid']} rejected as Smart contract {parsed_data['contractName']}-{outputlist[0]} has not expired and will not trigger"))
session.commit()
session.close()
pushData_SSEapi(
f"Error| Transaction {parsed_data['txid']} rejected as Smart contract {parsed_data['contractName']}-{outputlist[0]} has not expired and will not trigger")
return 0
# check if the user choice passed is part of the contract structure
tempchoiceList = []
for item in contractStructure['exitconditions']:
tempchoiceList.append(contractStructure['exitconditions'][item])
if parsed_data['userChoice'] not in tempchoiceList:
logger.info(
f"Transaction {parsed_data['txid']} rejected as userChoice, {parsed_data['userChoice']}, has been passed to Smart Contract named {parsed_data['contractName']} at the address {outputlist[0]} which doesn't accept any userChoice of the given name")
# Store transfer as part of RejectedContractTransactionHistory
engine = create_engine(
f"sqlite:///smartContracts/{parsed_data['contractName']}-{outputlist[0]}.db",
echo=True)
ContractBase.metadata.create_all(bind=engine)
session = sessionmaker(bind=engine)()
blockchainReference = neturl + 'tx/' + transaction_data['txid']
session.add(
RejectedContractTransactionHistory(transactionType='participation',
sourceFloAddress=inputadd,
destFloAddress=outputlist[0],
transferAmount=None,
blockNumber=transaction_data['blockheight'],
blockHash=transaction_data['blockhash'],
time=transaction_data['blocktime'],
transactionHash=transaction_data['txid'],
blockchainReference=blockchainReference,
jsonData=json.dumps(transaction_data),
rejectComment=f"Transaction {parsed_data['txid']} rejected as userChoice, {parsed_data['userChoice']}, has been passed to Smart Contract named {parsed_data['contractName']} at the address {outputlist[0]} which doesn't accept any userChoice of the given name"))
session.commit()
session.close()
pushData_SSEapi(
f"Error | Transaction {parsed_data['txid']} rejected as userChoice, {parsed_data['userChoice']}, has been passed to Smart Contract named {parsed_data['contractName']} at the address {outputlist[0]} which doesn't accept any userChoice of the given name)
return 0
# check if minimumsubscriptionamount exists as part of the contract structure
if 'minimumsubscriptionamount' in contractStructure:
# if it has not been reached, close the contract and return money
minimumsubscriptionamount = float(contractStructure['minimumsubscriptionamount'])
engine = create_engine(
'sqlite:///smartContracts/{}-{}.db'.format(parsed_data['contractName'], outputlist[0]),
echo=True)
ContractBase.metadata.create_all(bind=engine) ContractBase.metadata.create_all(bind=engine)
session = sessionmaker(bind=engine)() session = sessionmaker(bind=engine)()
result = session.query(ContractStructure).filter_by(attribute='minimumsubscriptionamount').all()
amountDeposited = session.query(func.sum(ContractParticipants.tokenAmount)).all()[0][0] amountDeposited = session.query(func.sum(ContractParticipants.tokenAmount)).all()[0][0]
session.close() session.close()
@ -1534,13 +1656,17 @@ def processTransaction(transaction_data, parsed_data):
amountDeposited = 0 amountDeposited = 0
if amountDeposited < minimumsubscriptionamount: if amountDeposited < minimumsubscriptionamount:
logger.info('Minimum subscription amount hasn\'t been reached\n The token will be returned back') # close the contract and return the money
logger.info(
'Minimum subscription amount hasn\'t been reached\n The token will be returned back')
# Initialize payback to contract participants # Initialize payback to contract participants
engine = create_engine('sqlite:///smartContracts/{}-{}.db'.format(parsed_data['contractName'], outputlist[0]), engine = create_engine(
echo=True) 'sqlite:///smartContracts/{}-{}.db'.format(parsed_data['contractName'], outputlist[0]),
echo=True)
connection = engine.connect() connection = engine.connect()
contractParticipants = connection.execute( contractParticipants = connection.execute(
'select participantAddress, tokenAmount, transactionHash from contractparticipants').fetchall()[0][0] 'select participantAddress, tokenAmount, transactionHash from contractparticipants').fetchall()[
0][0]
for participant in contractParticipants: for participant in contractParticipants:
tokenIdentification = connection.execute( tokenIdentification = connection.execute(
@ -1559,7 +1685,6 @@ def processTransaction(transaction_data, parsed_data):
'update contractparticipants set winningAmount="{}" where participantAddress="{}" and transactionHash="{}"'.format( 'update contractparticipants set winningAmount="{}" where participantAddress="{}" and transactionHash="{}"'.format(
(participant[1], participant[0], participant[4]))) (participant[1], participant[0], participant[4])))
# add transaction to ContractTransactionHistory # add transaction to ContractTransactionHistory
blockchainReference = neturl + 'tx/' + transaction_data['txid'] blockchainReference = neturl + 'tx/' + transaction_data['txid']
session.add(ContractTransactionHistory(transactionType='trigger', sourceFloAddress=inputadd, session.add(ContractTransactionHistory(transactionType='trigger', sourceFloAddress=inputadd,
@ -1578,31 +1703,41 @@ def processTransaction(transaction_data, parsed_data):
'update activecontracts set status="closed" where contractName="{}" and contractAddress="{}"'.format( 'update activecontracts set status="closed" where contractName="{}" and contractAddress="{}"'.format(
parsed_data['contractName'], outputlist[0])) parsed_data['contractName'], outputlist[0]))
connection.execute( connection.execute(
'update activecontracts set status="{}" where contractName="{}" and contractAddress="{}"'.format(transaction_data['blocktime'], 'update activecontracts set status="{}" where contractName="{}" and contractAddress="{}"'.format(
transaction_data['blocktime'],
parsed_data['contractName'], outputlist[0])) parsed_data['contractName'], outputlist[0]))
connection.close() connection.close()
pushData_SSEapi('Trigger | Minimum subscription amount not reached at contract {}-{} at transaction {}. Tokens will be refunded'.format( pushData_SSEapi(
'Trigger | Minimum subscription amount not reached at contract {}-{} at transaction {}. Tokens will be refunded'.format(
parsed_data['contractName'], outputlist[0], transaction_data['txid'])) parsed_data['contractName'], outputlist[0], transaction_data['txid']))
return return
engine = create_engine('sqlite:///smartContracts/{}-{}.db'.format(parsed_data['contractName'], outputlist[0]), echo=True)
connection = engine.connect() # Trigger the contract
contractWinners = connection.execute('select * from contractparticipants where userChoice="{}"'.format(parsed_data['triggerCondition'])).fetchall() contractWinners = connection.execute(
tokenSum = connection.execute('select sum(tokenAmount) from contractparticipants').fetchall()[0][0] 'select * from contractparticipants where userChoice="{}"'.format(
winnerSum = connection.execute('select sum(tokenAmount) from contractparticipants where userChoice="{}"'.format(parsed_data['triggerCondition'])).fetchall()[0][0] parsed_data['triggerCondition'])).fetchall()
tokenIdentification = connection.execute('select value from contractstructure where attribute="tokenIdentification"').fetchall()[0][0] tokenSum = \
connection.execute('select sum(tokenAmount) from contractparticipants').fetchall()[0][0]
winnerSum = connection.execute(
'select sum(tokenAmount) from contractparticipants where userChoice="{}"'.format(
parsed_data['triggerCondition'])).fetchall()[0][0]
tokenIdentification = connection.execute(
'select value from contractstructure where attribute="tokenIdentification"').fetchall()[0][
0]
for winner in contractWinners: for winner in contractWinners:
winner = list(winner) winnerAmount = "%.8f" % ((winner[2] / winnerSum) * tokenSum)
winnerAmount = "%.8f" % ((winner[2]/winnerSum)*tokenSum) returnval = transferToken(tokenIdentification, winnerAmount,
returnval = transferToken(tokenIdentification, winnerAmount, outputlist[0], winner[1], transaction_data) outputlist[0], winner[1], transaction_data)
if returnval is None: if returnval is None:
logger.info( logger.critical(
"CRITICAL ERROR | Something went wrong in the token transfer method while doing local Smart Contract Trigger") "Something went wrong in the token transfer method while doing local Smart Contract Trigger")
return 0 return 0
connection.execute('update contractparticipants set winningAmount="{}" where participantAddress="{}" and transactionHash="{}"'.format(winnerAmount, winner[1], winner[4])) connection.execute(
connection.close() 'update contractparticipants set winningAmount="{}" where participantAddress="{}" and transactionHash="{}"'.format(
(winnerAmount, winner[1], winner[4])))
# add transaction to ContractTransactionHistory # add transaction to ContractTransactionHistory
blockchainReference = neturl + 'tx/' + transaction_data['txid'] blockchainReference = neturl + 'tx/' + transaction_data['txid']
@ -1622,18 +1757,42 @@ def processTransaction(transaction_data, parsed_data):
'update activecontracts set status="closed" where contractName="{}" and contractAddress="{}"'.format( 'update activecontracts set status="closed" where contractName="{}" and contractAddress="{}"'.format(
parsed_data['contractName'], outputlist[0])) parsed_data['contractName'], outputlist[0]))
connection.execute( connection.execute(
'update activecontracts set closeDate="{}" where contractName="{}" and contractAddress="{}"'.format(transaction_data['blocktime'], 'update activecontracts set closeDate="{}" where contractName="{}" and contractAddress="{}"'.format(
transaction_data['blocktime'],
parsed_data['contractName'], outputlist[0])) parsed_data['contractName'], outputlist[0]))
connection.close() connection.close()
updateLatestTransaction(transaction_data, parsed_data, transaction_data['blockheight']) updateLatestTransaction(transaction_data, parsed_data)
pushData_SSEapi('Trigger | Contract triggered of the name {}-{} is active currentlyt at transaction {}'.format( pushData_SSEapi(
'Trigger | Contract triggered of the name {}-{} is active currently at transaction {}'.format(
parsed_data['contractName'], outputlist[0], transaction_data['txid'])) parsed_data['contractName'], outputlist[0], transaction_data['txid']))
return
else: else:
logger.info('Input address is not part of the committee address list. This trigger is rejected') logger.info(
pushData_SSEapi('Error | Smart contract pay\'s input address is not part of the committee address. Contract will be rejected'.format(parsed_data['contractName'], outputlist[0], transaction_data['txid'])) f"Transaction {transaction_data['txid']} rejected as input address, {inputlist[0]}, is not part of the committee address list")
# Store transfer as part of RejectedContractTransactionHistory
engine = create_engine(
f"sqlite:///smartContracts/{parsed_data['contractName']}-{parsed_data['contractAddress']}.db",
echo=True)
ContractBase.metadata.create_all(bind=engine)
session = sessionmaker(bind=engine)()
blockchainReference = neturl + 'tx/' + transaction_data['txid']
session.add(RejectedContractTransactionHistory(transactionType='incorporation', sourceFloAddress=inputadd,
destFloAddress=outputlist[0],
transferAmount=None,
blockNumber=transaction_data['blockheight'],
blockHash=transaction_data['blockhash'],
time=transaction_data['blocktime'],
transactionHash=transaction_data['txid'],
blockchainReference=blockchainReference,
jsonData=json.dumps(transaction_data),
rejectComment=f"Transaction {transaction_data['txid']} rejected as input address, {inputlist[0]}, is not part of the committee address list"))
session.commit()
session.close()
pushData_SSEapi(f"Transaction {transaction_data['txid']} rejected as input address, {inputlist[0]}, is not part of the committee address list")