From 18384e8eef3b3fd7f807f74352abe66fcffb8f77 Mon Sep 17 00:00:00 2001 From: Vivek Teega Date: Sun, 13 Nov 2022 12:04:08 +0000 Subject: [PATCH] 1.1.1 Addition of multiple payouts in internal trigger contract --- parsing.py | 55 ++++++++++-- statef_processing.py | 12 +++ tracktokens_smartcontracts.py | 159 +++++++++++++--------------------- 3 files changed, 123 insertions(+), 103 deletions(-) diff --git a/parsing.py b/parsing.py index 517fd5f..bb2533b 100644 --- a/parsing.py +++ b/parsing.py @@ -3,6 +3,7 @@ import re import arrow import pyflo import logging +import json """ Find make lists of #, *, @ words @@ -896,6 +897,7 @@ def text_preprocessing(original_text): return clean_text,processed_text +# TODO - REMOVE SAMPLE TEXT text_list = [ "create 500 million rmt#", @@ -939,9 +941,21 @@ text_list2 = [ (2) accepting_token = rupee# (3) selling_token = sreeram# (4) price = "15" - (5) priceType="predetermined" end-contract-conditions''' + (5) priceType="predetermined" end-contract-conditions''', + + ''' + Create a smart contract of the name simple-crowd-fund@ of the type one-time-event* using asset bioscope# at the FLO address oQkpZCBcAWc945viKqFmJVbVG4aKY4V3Gz$ with contract-conditions:(1) expiryTime= Tue Sep 13 2022 16:10:00 GMT+0530 (2) payeeAddress=oQotdnMBAP1wZ6Kiofx54S2jNjKGiFLYD7 end-contract-conditions + ''', + + ''' + Create a smart contract of the name simple-crowd-fund@ of the type one-time-event* using asset bioscope# at the FLO address oQkpZCBcAWc945viKqFmJVbVG4aKY4V3Gz$ with contract-conditions:(1) expiryTime= Tue Sep 13 2022 16:10:00 GMT+0530 (2) payeeAddress=oU412TvcMe2ah2xzqFpA95vBJ1RoPZY1LR:10:oVq6QTUeNLh8sapQ6J6EjMQMKHxFCt3uAq:20:oLE79kdHPEZ2bxa3PwtysbJeLo9hvPgizU:60:ocdCT9RAzWVsUncMu24r3HXKXFCXD7gTqh:10 end-contract-conditions + ''', + ''' + Create a smart contract of the name simple-crowd-fund@ of the type one-time-event* using asset bioscope# at the FLO address oQkpZCBcAWc945viKqFmJVbVG4aKY4V3Gz$ with contract-conditions:(1) expiryTime= Tue Sep 13 2022 16:10:00 GMT+0530 (2) payeeAddress=oU412TvcMe2ah2xzqFpA95vBJ1RoPZY1LR end-contract-conditions + ''' ] +# todo - REMOVE STUB blockinfo_stub = {'hash': '28505c54c2099f9f3d25e9ceffb72bffd14156b12449b6d73a5b9d2d061f1643', 'size': 253, 'height': 5587001, 'version': 536870912, 'merkleroot': '8bbc603573019a832ee82d637bd40d340e1194e760027f9a2959e6443f311547', 'tx': ['8bbc603573019a832ee82d637bd40d340e1194e760027f9a2959e6443f311547'], 'time': 1660188965, 'nonce': 646198852, 'bits': 470123011, 'difficulty': 50, 'chainwork': '00000000000000000000000000000000000000000000000110720a0f9acc471d', 'confirmations': 569, 'previousblockhash': 'c62937e8fd60e00cb07b28071acd7201501cb55b1fc0899ea1c89256d804a554', 'nextblockhash': '6dcc78c447ec4705a37a2b1531691b28e7c1f2eada0f5af2278c3a087c7c459f', 'reward': 1.5625, 'isMainChain': True, 'poolInfo': {}} @@ -1072,10 +1086,40 @@ def parse_flodata(text, blockinfo, net): return outputreturn('one-time-event-userchoice-smartcontract-incorporation',f"{contract_token}", f"{contract_name}", f"{contract_address}", f"{clean_text}", f"{contractAmount}", f"{minimum_subscription_amount}" , f"{maximum_subscription_amount}", f"{contract_conditions['userchoices']}", f"{contract_conditions['expiryTime']}", stateF_mapping) elif 'payeeAddress' in contract_conditions.keys(): contract_conditions['payeeAddress'] = find_word_index_fromstring(clean_text,contract_conditions['payeeAddress']) - if not check_flo_address(contract_conditions['payeeAddress'], is_testnet): - return outputreturn('noise') - else: - return outputreturn('one-time-event-time-smartcontract-incorporation',f"{contract_token}", f"{contract_name}", f"{contract_address}", f"{clean_text}", f"{contractAmount}", f"{minimum_subscription_amount}" , f"{maximum_subscription_amount}", f"{contract_conditions['payeeAddress']}", f"{contract_conditions['expiryTime']}", stateF_mapping) + # check if colon exists in the payeeAddress string + if ':' in contract_conditions['payeeAddress']: + colon_split = contract_conditions['payeeAddress'].split(':') + if len(colon_split)%2 != 0: + return outputreturn('noise') + split_total = 0 + payeeAddress_split_dictionary = {} + for idx, item in enumerate(colon_split): + if idx%2 == 0: + # check if floid + if not check_flo_address(item, is_testnet): + return outputreturn('noise') + if idx%2 == 1: + # check if number + try: + item = float(item) + if item <= 0: + return outputreturn('noise') + payeeAddress_split_dictionary[colon_split[idx-1]] = item + split_total += item + except: + return outputreturn('noise') + if split_total != 100: + return outputreturn('noise') + else: + contract_conditions['payeeAddress'] = payeeAddress_split_dictionary + return outputreturn('one-time-event-time-smartcontract-incorporation',f"{contract_token}", f"{contract_name}", f"{contract_address}", f"{clean_text}", f"{contractAmount}", f"{minimum_subscription_amount}" , f"{maximum_subscription_amount}", contract_conditions['payeeAddress'], f"{contract_conditions['expiryTime']}", stateF_mapping) + else: + if not check_flo_address(contract_conditions['payeeAddress'], is_testnet): + return outputreturn('noise') + else: + contract_conditions['payeeAddress'] = {f"{contract_conditions['payeeAddress']}":100} + return outputreturn('one-time-event-time-smartcontract-incorporation',f"{contract_token}", f"{contract_name}", f"{contract_address}", f"{clean_text}", f"{contractAmount}", f"{minimum_subscription_amount}" , f"{maximum_subscription_amount}", contract_conditions['payeeAddress'], f"{contract_conditions['expiryTime']}", stateF_mapping) + if first_classification['categorization'] == 'smart-contract-participation-deposit-C': # either participation of one-time-event contract or @@ -1196,4 +1240,3 @@ def parse_flodata(text, blockinfo, net): return outputreturn('noise') -#print(parse_flodata(text_list2[0], blockinfo_stub, 'testnet')) \ No newline at end of file diff --git a/statef_processing.py b/statef_processing.py index 8f8b4c5..6137062 100644 --- a/statef_processing.py +++ b/statef_processing.py @@ -12,6 +12,18 @@ import pdb "bitcoin_price_source":"bitpay", "usd_inr_exchange_source":"bitpay" } +''' + +''' +stateF notes for amount split on contracts + +stateF_object = { + "floaddresses": "oPkHWcvqBHfCortTHScrVBjXLsZhWie99C-oPkHWcvqBHfCortTHScrVBjXLsZhWie99C-oPkHWcvqBHfCortTHScrVBjXLsZhWie99C", + "splits": "10-20-30", +} + + + ''' # stateF diff --git a/tracktokens_smartcontracts.py b/tracktokens_smartcontracts.py index 9cca817..c2fae4e 100755 --- a/tracktokens_smartcontracts.py +++ b/tracktokens_smartcontracts.py @@ -131,6 +131,10 @@ def processBlock(blockindex=None, blockhash=None): blockinfo = newMultiRequest(f"block/{blockhash}") + pause_index = 2211701 + if blockindex == pause_index: + print(f'Paused at {pause_index}') + pdb.set_trace() # Check smartContracts which will be triggered locally, and not by the contract committee checkLocaltriggerContracts(blockinfo) # Check if any deposits have to be returned @@ -142,8 +146,7 @@ def processBlock(blockindex=None, blockhash=None): # Scan every transaction logger.info("Before tx loop") transaction_counter = 0 - if blockindex == 2211700: - pdb.set_trace() + for transaction in blockinfo["tx"]: transaction_counter = transaction_counter + 1 logger.info(f"Transaction {transaction_counter} : {transaction}") @@ -391,17 +394,47 @@ def transferToken(tokenIdentification, tokenAmount, inputAddress, outputAddress, return 1 +def trigger_internal_contract(tokenAmount_sum, contractStructure, transaction_data, blockinfo, parsed_data, connection, contract_name, contract_address, transaction_subType): + # Trigger the contract + payeeAddress = json.loads(contractStructure['payeeAddress']) + tokenIdentification = contractStructure['tokenIdentification'] + contractAddress = contractStructure['contractAddress'] + + for floaddress in payeeAddress.keys(): + transferAmount = tokenAmount_sum * (payeeAddress[floaddress]/100) + returnval = transferToken(tokenIdentification, transferAmount, contractAddress, floaddress, transaction_data=transaction_data, blockinfo = blockinfo, parsed_data = parsed_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="{}"'.format(transferAmount)) + + # Add transaction to ContractTransactionHistory + session = create_database_session_orm('smart_contract', {'contract_name': f"{contract_name}", 'contract_address': f"{contract_address}"}, ContractBase) + session.add(ContractTransactionHistory(transactionType='trigger', + transactionSubType=transaction_subType, + sourceFloAddress=contractAddress, + destFloAddress=floaddress, + transferAmount=transferAmount, + blockNumber=blockinfo['height'], + blockHash=blockinfo['hash'], + time=blockinfo['time'])) + session.commit() + session.close() + return 1 + + +def check_local_trigger_conditions(): + pass + + def checkLocaltriggerContracts(blockinfo): connection = create_database_connection('system_dbs', {'db_name':"system"}) # todo : filter activeContracts which only have local triggers activeContracts = connection.execute('select contractName, contractAddress from activecontracts where status=="active"').fetchall() connection.close() - #todo - remove temp variable - temp = 0 for contract in activeContracts: # pull out the contract structure into a dictionary - print(f"HEYYYYY {temp}") connection = create_database_connection('smart_contract', {'contract_name':f"{contract[0]}", 'contract_address':f"{contract[1]}"}) print(f"Contract being processed is {contract[0]}-{contract[1]}") @@ -426,7 +459,6 @@ def checkLocaltriggerContracts(blockinfo): parsed_data = {} parsed_data['type'] = 'internalTrigger' - if 'contractAddress' not in contractStructure.keys(): contractStructure['contractAddress'] = contract[1] @@ -459,8 +491,7 @@ def checkLocaltriggerContracts(blockinfo): if returnval is None: logger.critical("Something went wrong in the token transfer method while doing local Smart Contract Trigger. THIS IS CRITICAL ERROR") return - connection.execute('update contractparticipants set winningAmount="{}" where participantAddress="{}" and transactionHash="{}"'.format( - (participant[1], participant[0], participant[2]))) + connection.execute('update contractparticipants set winningAmount="{}" where participantAddress="{}" and transactionHash="{}"'.format((participant[1], participant[0], participant[2]))) # add transaction to ContractTransactionHistory session = create_database_session_orm('smart_contract', {'contract_name': f"{contract[0]}", 'contract_address': f"{contract[1]}"}, ContractBase) @@ -495,46 +526,19 @@ def checkLocaltriggerContracts(blockinfo): elif 'payeeAddress' in contractStructure: # This is a local trigger contract + tokenAmount_sum = connection.execute('select sum(tokenAmount) from contractparticipants').fetchall()[0][0] if 'maximumsubscriptionamount' in contractStructure: 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 - payeeAddress = contractStructure['payeeAddress'] - tokenIdentification = contractStructure['tokenIdentification'] - contractAddress = contractStructure['contractAddress'] - returnval = transferToken(tokenIdentification, tokenAmount_sum, contractAddress, payeeAddress, blockinfo = blockinfo) - if returnval is None: - logger.critical( - "Something went wrong in the token transfer method while doing local Smart Contract Trigger") - return - connection.execute( - 'update contractparticipants set winningAmount="{}"'.format( - (0))) - - # add transaction to ContractTransactionHistory - session = create_database_session_orm('smart_contract', {'contract_name': f"{contract[0]}", 'contract_address': f"{contract[1]}"}, ContractBase) - session.add(ContractTransactionHistory(transactionType='trigger', - transactionSubType='maximumsubscriptionamount', - sourceFloAddress=contractAddress, - destFloAddress=payeeAddress, - transferAmount=tokenAmount_sum, - blockNumber=blockinfo['height'], - blockHash=blockinfo['hash'], - time=blockinfo['time'])) - session.commit() - session.close() - + success_returnval = trigger_internal_contract(tokenAmount_sum, contractStructure, transaction_data, blockinfo, parsed_data, connection, contract_name=contract[0], contract_address=contract[1], transaction_subType='maximumsubscriptionamount') + if not success_returnval: + return 0 + connection = create_database_connection('system_dbs', {'db_name':'system'}) - connection.execute( - 'update activecontracts set status="closed" where contractName="{}" and contractAddress="{}"'.format( - contract[0], contract[1])) - connection.execute( - 'update activecontracts set closeDate="{}" where contractName="{}" and contractAddress="{}"'.format( - blockinfo['time'], contract[0], contract[1])) - connection.execute( - 'update activecontracts set expiryDate="{}" where contractName="{}" and contractAddress="{}"'.format( - blockinfo['time'], contract[0], contract[1])) + connection.execute('update activecontracts set status="closed" where contractName="{}" and contractAddress="{}"'.format(contract[0], contract[1])) + connection.execute('update activecontracts set closeDate="{}" where contractName="{}" and contractAddress="{}"'.format(blockinfo['time'], contract[0], contract[1])) + connection.execute('update activecontracts set expiryDate="{}" where contractName="{}" and contractAddress="{}"'.format(blockinfo['time'], contract[0], contract[1])) connection.close() return @@ -547,27 +551,18 @@ def checkLocaltriggerContracts(blockinfo): if blocktime_object > expirytime_object: if 'minimumsubscriptionamount' in contractStructure: minimumsubscriptionamount = contractStructure['minimumsubscriptionamount'] - tokenAmount_sum = connection.execute('select sum(tokenAmount) from contractparticipants').fetchall()[0][0] if tokenAmount_sum < minimumsubscriptionamount: # Initialize payback to contract participants contractParticipants = connection.execute('select participantAddress, tokenAmount, transactionHash from contractparticipants').fetchall()[0][0] for participant in contractParticipants: - tokenIdentification = connection.execute( - 'select * from contractstructure where attribute="tokenIdentification"').fetchall()[ - 0][ - 0] - contractAddress = connection.execute( - 'select * from contractstructure where attribute="contractAddress"').fetchall()[0][ - 0] + tokenIdentification = connection.execute('select * from contractstructure where attribute="tokenIdentification"').fetchall()[0][0] + contractAddress = connection.execute('select * from contractstructure where attribute="contractAddress"').fetchall()[0][0] returnval = transferToken(tokenIdentification, participant[1], contractAddress, participant[0], blockinfo = blockinfo) if returnval is None: - logger.critical( - "Something went wrong in the token transfer method while doing local Smart Contract Trigger") + logger.critical("Something went wrong in the token transfer method while doing local Smart Contract Trigger") return - connection.execute( - 'update contractparticipants set winningAmount="{}" where participantAddress="{}" and transactionHash="{}"'.format( - (participant[1], participant[0], participant[2]))) + connection.execute('update contractparticipants set winningAmount="{}" where participantAddress="{}" and transactionHash="{}"'.format((participant[1], participant[0], participant[2]))) # add transaction to ContractTransactionHistory session = create_database_session_orm('smart_contract', {'contract_name': f"{contract[0]}", 'contract_address': f"{contract[1]}"}, ContractBase) @@ -581,49 +576,24 @@ def checkLocaltriggerContracts(blockinfo): session.close() connection = create_database_connection('system_dbs', {'db_name':'system'}) - connection.execute('update activecontracts set status="closed" where contractName="{}" and contractAddress="{}"'.format( - contract[0], contract[1])) - connection.execute('update activecontracts set closeDate="{}" where contractName="{}" and contractAddress="{}"'.format( - blockinfo['time'], contract[0], contract[1])) - connection.execute('update activecontracts set expiryDate="{}" where contractName="{}" and contractAddress="{}"'.format( - blockinfo['time'], contract[0], contract[1])) + connection.execute('update activecontracts set status="closed" where contractName="{}" and contractAddress="{}"'.format(contract[0], contract[1])) + connection.execute('update activecontracts set closeDate="{}" where contractName="{}" and contractAddress="{}"'.format(blockinfo['time'], contract[0], contract[1])) + connection.execute('update activecontracts set expiryDate="{}" where contractName="{}" and contractAddress="{}"'.format(blockinfo['time'], contract[0], contract[1])) connection.close() return # Trigger the contract - payeeAddress = contractStructure['payeeAddress'] - tokenIdentification = contractStructure['tokenIdentification'] - contractAddress = contractStructure['contractAddress'] - connection = create_database_connection('smart_contract', {'contract_name':f"{contract[0]}", 'contract_address':f"{contract[1]}"}) - tokenAmount_sum = connection.execute('select sum(tokenAmount) from contractparticipants').fetchall()[0][0] - - returnval = transferToken(tokenIdentification, tokenAmount_sum, contractAddress, payeeAddress, transaction_data=transaction_data, blockinfo = blockinfo, parsed_data = parsed_data) - if returnval is None: - logger.critical("Something went wrong in the token transfer method while doing local Smart Contract Trigger") - return - connection.execute('update contractparticipants set winningAmount="{}"'.format(0)) - - # add transaction to ContractTransactionHistory - session = create_database_session_orm('smart_contract', {'contract_name': f"{contract[0]}", 'contract_address': f"{contract[1]}"}, ContractBase) - session.add(ContractTransactionHistory(transactionType='trigger', - transactionSubType='expiryTime', - sourceFloAddress=contractAddress, - destFloAddress=payeeAddress, - transferAmount=tokenAmount_sum, - blockNumber=blockinfo['height'], - blockHash=blockinfo['hash'], - time=blockinfo['time'])) - session.commit() - session.close() + success_returnval = trigger_internal_contract(tokenAmount_sum, contractStructure, transaction_data, blockinfo, parsed_data, connection, contract_name=contract[0], contract_address=contract[1], transaction_subType='expiryTime') + if not success_returnval: + return 0 connection = create_database_connection('system_dbs', {'db_name':'system'}) - connection.execute( - 'update activecontracts set status="closed" where contractName="{}" and contractAddress="{}"'.format(contract[0], contract[1])) + connection.execute('update activecontracts set status="closed" where contractName="{}" and contractAddress="{}"'.format(contract[0], contract[1])) connection.execute('update activecontracts set closeDate="{}" where contractName="{}" and contractAddress="{}"'.format(blockinfo['time'], contract[0], contract[1])) connection.execute('update activecontracts set expiryDate="{}" where contractName="{}" and contractAddress="{}"'.format(blockinfo['time'], contract[0], contract[1])) connection.close() return - + def checkReturnDeposits(blockinfo): # Connect to system.db with a session @@ -765,8 +735,7 @@ def checkReturnDeposits(blockinfo): if returnval is None: logger.critical("Something went wrong in the token transfer method while doing local Smart Contract Trigger. THIS IS CRITICAL ERROR") return - connection.execute('update contractparticipants set winningAmount="{}" where participantAddress="{}" and transactionHash="{}"'.format( - (participant[1], participant[0], participant[2]))) + connection.execute('update contractparticipants set winningAmount="{}" where participantAddress="{}" and transactionHash="{}"'.format((participant[1], participant[0], participant[2]))) # add transaction to ContractTransactionHistory session = create_database_session_orm('smart_contract', {'contract_name': f"{contract[0]}", 'contract_address': f"{contract[1]}"}, ContractBase) @@ -813,7 +782,7 @@ def checkReturnDeposits(blockinfo): if returnval is None: logger.critical("Something went wrong in the token transfer method while doing local Smart Contract Trigger") return - connection.execute('update contractparticipants set winningAmount="{}"'.format((0))) + connection.execute('update contractparticipants set winningAmount="{}"'.format(0)) # add transaction to ContractTransactionHistory session = create_database_session_orm('smart_contract', {'contract_name': f"{contract[0]}", 'contract_address': f"{contract[1]}"}, ContractBase) @@ -2039,11 +2008,7 @@ def processTransaction(transaction_data, parsed_data, blockinfo): if 'payeeAddress' in parsed_data['contractConditions']: # in this case, expirydate( or maximumamount) is the trigger internally. Keep a track of expiry dates - session.add( - ContractStructure(attribute='payeeAddress', index=0, - value=parsed_data['contractConditions']['payeeAddress'])) - - session.commit() + session.add(ContractStructure(attribute='payeeAddress', index=0, value=json.dumps(parsed_data['contractConditions']['payeeAddress']))) # Store transfer as part of ContractTransactionHistory blockchainReference = neturl + 'tx/' + transaction_data['txid']