Changes fotokenswap & stateF addition to contracts

This commit is contained in:
Vivek Teega 2022-10-29 10:51:57 +00:00
parent a77fed3c1b
commit b327ca5d58
7 changed files with 271 additions and 109 deletions

1
.gitignore vendored
View File

@ -13,3 +13,4 @@ py3/
__pycache__/
*.pyc
.vscode/
error-notes.txt

View File

@ -1 +0,0 @@
3.9.0

View File

@ -263,7 +263,6 @@ class TimeActions(SystemBase):
transactionHash = Column('transactionHash', String)
blockNumber = Column('blockNumber', Integer)
class LatestTransactions(LatestCacheBase):
__tablename__ = "latestTransactions"

View File

@ -136,6 +136,33 @@ def apply_rule1(*argv):
return a
def extract_substing_between(test_str, sub1, sub2):
# getting index of substrings
idx1 = test_str.index(sub1)
idx2 = test_str.index(sub2)
# length of substring 1 is added to
# get string from next character
res = test_str[idx1 + len(sub1) + 1: idx2]
# return result
return res
# StateF functions
def isStateF(text):
try:
statef_string = extract_substing_between(text, 'statef', 'end-statef').strip()
i=iter(statef_string.split(":"))
statef_list = [":".join(x) for x in zip(i,i)]
statef = {}
for keyval in statef_list:
keyval = keyval.split(':')
statef[keyval[0]] = keyval[1]
return statef
except:
return False
# conflict_list = [['userchoice','payeeaddress'],['userchoice','xxx']]
def resolve_incategory_conflict(input_dictionary , conflict_list):
for conflict_pair in conflict_list:
@ -166,7 +193,8 @@ def outputreturn(*argv):
'type': 'tokenIncorporation',
'flodata': argv[1], #string
'tokenIdentification': argv[2], #hashList[0][:-1]
'tokenAmount': argv[3] #initTokens
'tokenAmount': argv[3], #initTokens
'stateF': argv[4]
}
return parsed_data
elif argv[0] == 'token_transfer':
@ -175,7 +203,8 @@ def outputreturn(*argv):
'transferType': 'token',
'flodata': argv[1], #string
'tokenIdentification': argv[2], #hashList[0][:-1]
'tokenAmount': argv[3] #amount
'tokenAmount': argv[3], #amount
'stateF': argv[4]
}
return parsed_data
elif argv[0] == 'one-time-event-userchoice-smartcontract-incorporation':
@ -192,7 +221,8 @@ def outputreturn(*argv):
'maximumsubscriptionamount' : argv[7],
'userchoices' : argv[8],
'expiryTime' : argv[9]
}
},
'stateF': argv[10]
}
return remove_empty_from_dict(parsed_data)
elif argv[0] == 'one-time-event-userchoice-smartcontract-participation':
@ -205,14 +235,16 @@ def outputreturn(*argv):
'tokenAmount': argv[3], #amount
'contractName': argv[4], #atList[0][:-1]
'contractAddress': argv[5],
'userChoice': argv[6] #userChoice
'userChoice': argv[6], #userChoice
'stateF': argv[7]
}
return remove_empty_from_dict(parsed_data)
elif argv[0] == 'one-time-event-userchoice-smartcontract-trigger':
parsed_data = {
'type': 'smartContractPays',
'contractName': argv[1], #atList[0][:-1]
'triggerCondition': argv[2] #triggerCondition.group().strip()[1:-1]
'triggerCondition': argv[2], #triggerCondition.group().strip()[1:-1]
'stateF': argv[3]
}
return parsed_data
elif argv[0] == 'one-time-event-time-smartcontract-incorporation':
@ -229,7 +261,8 @@ def outputreturn(*argv):
'maximumsubscriptionamount' : argv[7],
'payeeAddress' : argv[8],
'expiryTime' : argv[9]
}
},
'stateF': argv[10]
}
return remove_empty_from_dict(parsed_data)
elif argv[0] == 'continuos-event-token-swap-incorporation':
@ -246,7 +279,8 @@ def outputreturn(*argv):
'selling_token' : argv[7],
'pricetype' : argv[8],
'price' : argv[9],
}
},
'stateF': argv[10]
}
return parsed_data
elif argv[0] == 'continuos-event-token-swap-deposit':
@ -258,7 +292,8 @@ def outputreturn(*argv):
'flodata': argv[4], #string
'depositConditions': {
'expiryTime' : argv[5]
}
},
'stateF': argv[6]
}
return parsed_data
elif argv[0] == 'smart-contract-one-time-event-continuos-event-participation':
@ -269,7 +304,8 @@ def outputreturn(*argv):
'tokenIdentification': argv[2], #hashList[0][:-1]
'tokenAmount': argv[3], #amount
'contractName': argv[4], #atList[0][:-1]
'contractAddress': argv[5]
'contractAddress': argv[5],
'stateF': argv[6]
}
return remove_empty_from_dict(parsed_data)
elif argv[0] == 'nft_create':
@ -278,7 +314,8 @@ def outputreturn(*argv):
'flodata': argv[1], #string
'tokenIdentification': argv[2], #hashList[0][:-1]
'tokenAmount': argv[3], #initTokens,
'nftHash': argv[4] #nftHash
'nftHash': argv[4], #nftHash
'stateF': argv[5]
}
return parsed_data
elif argv[0] == 'nft_transfer':
@ -288,6 +325,7 @@ def outputreturn(*argv):
'flodata': argv[1], #string
'tokenIdentification': argv[2], #hashList[0][:-1]
'tokenAmount': argv[3], #initTokens,
'stateF': argv[4]
}
return parsed_data
elif argv[0] == 'infinite_token_create':
@ -295,9 +333,10 @@ def outputreturn(*argv):
'type': 'infiniteTokenIncorporation',
'flodata': argv[1], #string
'tokenIdentification': argv[2], #hashList[0][:-1]
'stateF': argv[3]
}
return parsed_data
def extract_specialcharacter_words(rawstring, special_characters):
wordList = []
@ -308,7 +347,13 @@ def extract_specialcharacter_words(rawstring, special_characters):
def extract_contract_conditions(text, contract_type, marker=None, blocktime=None):
rulestext = re.split('contract-conditions:\s*', text)[-1]
try:
rulestext = extract_substing_between(text, 'contract-conditions', 'end-contract-conditions')
except:
return False
if rulestext.strip()[0] == ':':
rulestext = rulestext.strip()[1:].strip()
#rulestext = re.split('contract-conditions:\s*', text)[-1]
# rulelist = re.split('\d\.\s*', rulestext)
rulelist = []
numberList = re.findall(r'\(\d\d*\)', rulestext)
@ -416,6 +461,7 @@ def extract_contract_conditions(text, contract_type, marker=None, blocktime=None
elif rule[:9].lower() == 'pricetype':
pattern = re.compile('[^pricetype\s*=\s*].*')
priceType = pattern.search(rule).group(0)
priceType = priceType.replace("'","").replace('"', '')
extractedRules['priceType'] = priceType
elif rule[:5] == 'price':
pattern = re.compile('[^price\s*=\s*].*')
@ -886,6 +932,19 @@ text_list1 = [
'Transfer 20 rmt#'
]
text_list2 = [
'''Create Smart Contract with the name swap-rupee-bioscope@ of the type continuous-event*
at the address stateF=bitcoin_price_source:bitpay:usd_inr_exchange_source:bitpay end-stateF oYzeeUBWRpzRuczW6myh2LHGnXPyR2Bc6k$ with contract-conditions :
(1) subtype = tokenswap
(2) accepting_token = rupee#
(3) selling_token = sreeram#
(4) price = "15"
(5) priceType="predetermined" end-contract-conditions'''
]
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': {}}
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
@ -911,6 +970,9 @@ def parse_flodata(text, blockinfo, net):
return outputreturn('noise')
clean_text, processed_text = text_preprocessing(text)
# System state
print("Processing stateF")
stateF_mapping = isStateF(processed_text)
first_classification = firstclassification_rawstring(processed_text)
parsed_data = None
@ -920,7 +982,7 @@ def parse_flodata(text, blockinfo, net):
if not check_regex("^[A-Za-z][A-Za-z0-9_-]*[A-Za-z0-9]$", tokenname):
return outputreturn('noise')
isNFT = check_word_existence_instring('nft', processed_text)
isNFT = check_word_existence_instring('nft', processed_text )
isInfinite = check_word_existence_instring('infinite-token', processed_text)
@ -938,12 +1000,12 @@ def parse_flodata(text, blockinfo, net):
operation = apply_rule1(selectCategory, processed_text, send_category, create_category)
if operation == 'category1' and tokenamount is not None:
if isNFT:
return outputreturn('nft_transfer',f"{processed_text}", f"{tokenname}", tokenamount)
return outputreturn('nft_transfer',f"{processed_text}", f"{tokenname}", tokenamount, stateF_mapping)
else:
return outputreturn('token_transfer',f"{processed_text}", f"{tokenname}", tokenamount)
return outputreturn('token_transfer',f"{processed_text}", f"{tokenname}", tokenamount, stateF_mapping)
elif operation == 'category2':
if isInfinite:
return outputreturn('infinite_token_create',f"{processed_text}", f"{tokenname}")
return outputreturn('infinite_token_create',f"{processed_text}", f"{tokenname}", stateF_mapping)
else:
if tokenamount is None:
return outputreturn('noise')
@ -951,9 +1013,9 @@ def parse_flodata(text, blockinfo, net):
nft_hash = extract_NFT_hash(clean_text)
if nft_hash is False:
return outputreturn('noise')
return outputreturn('nft_create',f"{processed_text}", f"{tokenname}", tokenamount, f"{nft_hash}")
return outputreturn('nft_create',f"{processed_text}", f"{tokenname}", tokenamount, f"{nft_hash}", stateF_mapping)
else:
return outputreturn('token_incorporation',f"{processed_text}", f"{first_classification['wordlist'][0][:-1]}", tokenamount)
return outputreturn('token_incorporation',f"{processed_text}", f"{first_classification['wordlist'][0][:-1]}", tokenamount, stateF_mapping)
else:
return outputreturn('noise')
@ -981,9 +1043,16 @@ def parse_flodata(text, blockinfo, net):
return outputreturn('noise')
contract_conditions = extract_contract_conditions(processed_text, contract_type, contract_token, blocktime=blockinfo['time'])
if not resolve_incategory_conflict(contract_conditions,[['userchoices','payeeAddress']]) or contract_conditions == False:
if contract_conditions == False or not resolve_incategory_conflict(contract_conditions,[['userchoices','payeeAddress']]):
return outputreturn('noise')
else:
contractAmount = ''
if 'contractAmount' in contract_conditions.keys():
contractAmount = contract_conditions['contractAmount']
try:
float(contractAmount)
except:
return outputreturn('noise')
minimum_subscription_amount = ''
if 'minimumsubscriptionamount' in contract_conditions.keys():
minimum_subscription_amount = contract_conditions['minimumsubscriptionamount']
@ -1000,13 +1069,13 @@ def parse_flodata(text, blockinfo, net):
return outputreturn('noise')
if 'userchoices' in contract_conditions.keys():
return outputreturn('one-time-event-userchoice-smartcontract-incorporation',f"{contract_token}", f"{contract_name}", f"{contract_address}", f"{clean_text}", f"{contract_conditions['contractAmount']}", f"{minimum_subscription_amount}" , f"{maximum_subscription_amount}", f"{contract_conditions['userchoices']}", f"{contract_conditions['expiryTime']}")
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"{contract_conditions['contractAmount']}", f"{minimum_subscription_amount}" , f"{maximum_subscription_amount}", f"{contract_conditions['payeeAddress']}", f"{contract_conditions['expiryTime']}")
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)
if first_classification['categorization'] == 'smart-contract-participation-deposit-C':
# either participation of one-time-event contract or
@ -1039,7 +1108,7 @@ def parse_flodata(text, blockinfo, net):
if not userchoice:
return outputreturn('noise')
return outputreturn('one-time-event-userchoice-smartcontract-participation',f"{clean_text}", f"{tokenname}", tokenamount, f"{contract_name}", f"{contract_address}", f"{userchoice}")
return outputreturn('one-time-event-userchoice-smartcontract-participation',f"{clean_text}", f"{tokenname}", tokenamount, f"{contract_name}", f"{contract_address}", f"{userchoice}", stateF_mapping)
elif operation == 'category2':
tokenamount = apply_rule1(extractAmount_rule_new1, processed_text, 'deposit-conditions:', 'pre')
@ -1048,7 +1117,7 @@ def parse_flodata(text, blockinfo, net):
deposit_conditions = extract_deposit_conditions(processed_text, blocktime=blockinfo['time'])
if not deposit_category:
return outputreturn("noise")
return outputreturn('continuos-event-token-swap-deposit', f"{tokenname}", tokenamount, f"{contract_name}", f"{clean_text}", f"{deposit_conditions['expiryTime']}")
return outputreturn('continuos-event-token-swap-deposit', f"{tokenname}", tokenamount, f"{contract_name}", f"{clean_text}", f"{deposit_conditions['expiryTime']}", stateF_mapping)
if first_classification['categorization'] == 'smart-contract-participation-ote-ce-C':
# There is no way to properly differentiate between one-time-event-time-trigger participation and token swap participation
@ -1074,8 +1143,8 @@ def parse_flodata(text, blockinfo, net):
if not check_flo_address(contract_address, is_testnet):
return outputreturn('noise')
return outputreturn('smart-contract-one-time-event-continuos-event-participation', f"{clean_text}", f"{tokenname}", tokenamount, f"{contract_name}", f"{contract_address}")
return outputreturn('smart-contract-one-time-event-continuos-event-participation', f"{clean_text}", f"{tokenname}", tokenamount, f"{contract_name}", f"{contract_address}", stateF_mapping)
if first_classification['categorization'] == 'userchoice-trigger':
contract_name = extract_special_character_word(first_classification['wordlist'],'@')
if not check_regex("^[A-Za-z][A-Za-z0-9_-]*[A-Za-z0-9]$", contract_name):
@ -1084,7 +1153,7 @@ def parse_flodata(text, blockinfo, net):
trigger_condition = extract_trigger_condition(processed_text)
if not trigger_condition:
return outputreturn('noise')
return outputreturn('one-time-event-userchoice-smartcontract-trigger', f"{contract_name}", f"{trigger_condition}")
return outputreturn('one-time-event-userchoice-smartcontract-trigger', f"{contract_name}", f"{trigger_condition}", stateF_mapping)
if first_classification['categorization'] == 'smart-contract-creation-ce-tokenswap':
operation = apply_rule1(selectCategory, processed_text, create_category, send_category+deposit_category)
@ -1119,9 +1188,12 @@ def parse_flodata(text, blockinfo, net):
if contract_conditions['priceType']=="'determined'" or contract_conditions['priceType']=='"determined"' or contract_conditions['priceType']=="determined" or contract_conditions['priceType']=="'predetermined'" or contract_conditions['priceType']=='"predetermined"' or contract_conditions['priceType']=="predetermined":
assert float(contract_conditions['price'])
else:
assert check_flo_address(find_original_case(contract_conditions['priceType'], clean_text), is_testnet)
#assert check_flo_address(find_original_case(contract_conditions['priceType'], clean_text), is_testnet)
assert contract_conditions['priceType'] == 'statef'
except AssertionError:
return outputreturn('noise')
return outputreturn('continuos-event-token-swap-incorporation', f"{contract_token}", f"{contract_name}", f"{contract_address}", f"{clean_text}", f"{contract_conditions['subtype']}", f"{contract_conditions['accepting_token']}", f"{contract_conditions['selling_token']}", f"{contract_conditions['priceType']}", f"{contract_conditions['price']}")
return outputreturn('continuos-event-token-swap-incorporation', f"{contract_token}", f"{contract_name}", f"{contract_address}", f"{clean_text}", f"{contract_conditions['subtype']}", f"{contract_conditions['accepting_token']}", f"{contract_conditions['selling_token']}", f"{contract_conditions['priceType']}", f"{contract_conditions['price']}", stateF_mapping)
return outputreturn('noise')
#print(parse_flodata(text_list2[0], blockinfo_stub, 'testnet'))

77
statef_processing.py Normal file
View File

@ -0,0 +1,77 @@
import requests
from operator import attrgetter
import json
import pdb
'''
USD-INR
https://api.exchangerate-api.com/v4/latest/usd
Parsed stateF
"stateF":{
"bitcoin_price_source":"bitpay",
"usd_inr_exchange_source":"bitpay"
}
'''
# stateF
stateF_address = 'oPkHWcvqBHfCortTHScrVBjXLsZhWie99C'
stateF_object = {
"bitcoin_price_source":"bitpay",
"usd_inr_exchange_source":"bitpay"
}
# Flodata object
flodata_object = {
"bitpay": {
"bitcoin_price_source":{
"api" : "https://bitpay.com/api/rates",
"path" : [2,"rate"],
"data_type" : "float"
},
"usd_inr_exchange_source":{
"api" : "https://api.exchangerate-api.com/v4/latest/usd",
"path" : ["rates","INR"],
"data_type" : "float"
}
}
}
def pull_stateF(floID):
response = requests.get(f"https://testnet-flosight.duckdns.org/api/txs/?address={floID}")
if response.status_code == 200:
address_details = response.json()
latest_stateF = address_details['txs'][0]['floData']
latest_stateF = json.loads(latest_stateF)
return latest_stateF['stateF']
else:
print('API response not valid')
def query_api(api_object):
api, path, data_type = api_object.values()
response = requests.get(api)
if response.status_code == 200:
# Use path keys to reach the value
api_response = response.json()
for key in path:
api_response = api_response[key]
# todo: how to use datatype to convert
if data_type == 'float':
value_at_path = float(api_response)
return value_at_path
else:
print('API response not valid')
def process_stateF(stateF_object, stateF_address):
flodata_object = pull_stateF(stateF_address)
processed_values = {}
for key, value in stateF_object.items():
external_value = query_api(flodata_object[value][key])
processed_values[key] = external_value
return processed_values
if __name__ == '__main__':
processed_statef = process_stateF(stateF_object, stateF_address)
print(processed_statef)

View File

@ -412,7 +412,6 @@ def return_token_contract_set(rollback_block):
def initiate_rollback_process():
'''
tokendb_set, smartcontractdb_set = return_token_contract_set(rollback_block)
pdb.set_trace()
'''
# Connect to system.db
systemdb_session = create_database_session_orm('system_dbs', {'db_name': 'system'}, SystemBase)
@ -421,7 +420,7 @@ def initiate_rollback_process():
if db.db_type in ['token', 'nft', 'infinite-token']:
if db.blockNumber > rollback_block:
delete_database(rollback_block, f"{db.db_name}")
else:
else:
rollback_database(rollback_block, 'token', f"{db.db_name}")
elif db.db_type in ['smartcontract']:
if db.blockNumber > rollback_block:

View File

@ -6,7 +6,7 @@ import os
import shutil
import sqlite3
import sys
import pyflo
import pyflo
import requests
import socketio
from sqlalchemy import create_engine, func
@ -18,7 +18,8 @@ from config import *
from datetime import datetime
from ast import literal_eval
from models import SystemData, ActiveTable, ConsumedTable, TransferLogs, TransactionHistory, RejectedTransactionHistory, Base, ContractStructure, ContractBase, ContractParticipants, SystemBase, ActiveContracts, ContractAddressMapping, LatestCacheBase, ContractTransactionHistory, RejectedContractTransactionHistory, TokenContractAssociation, ContinuosContractBase, ContractStructure1, ContractParticipants1, ContractDeposits, ContractTransactionHistory1, DatabaseTypeMapping, TimeActions, ConsumedInfo
from statef_processing import process_stateF
import pdb
goodblockset = {}
goodtxset = {}
@ -55,7 +56,7 @@ def pushData_SSEapi(message):
def check_database_existence(type, parameters):
if type == 'token':
path = os.path.join(config['DEFAULT']['DATA_PATH'], 'tokens', f"{parameters['token_name']}.db")
path = os.path.join(config['DEFAULT']['DATA_PATH'], 'tokens', f'{parameters["token_name"]}.db')
return os.path.isfile(path)
if type == 'smart_contract':
@ -111,7 +112,7 @@ def convert_datetime_to_arrowobject(expiryTime):
return expirytime_object
def check_if_contract_address(floAddress):
def is_a_contract_address(floAddress):
# check contract address mapping db if the address is present, and return True or False based on that
system_db = create_database_session_orm('system_dbs', {'db_name':'system'}, SystemBase)
contract_number = system_db.query(func.sum(ContractAddressMapping.contractAddress)).filter(ContractAddressMapping.contractAddress == floAddress).all()[0][0]
@ -122,14 +123,13 @@ def check_if_contract_address(floAddress):
def processBlock(blockindex=None, blockhash=None):
if blockindex is not None and blockhash is None:
logger.info(f'Processing block {blockindex}')
# Get block details
# Get block details
response = newMultiRequest(f"block-index/{blockindex}")
blockhash = response['blockHash']
blockinfo = newMultiRequest(f"block/{blockhash}")
blockinfo = newMultiRequest(f"block/{blockhash}")
# Check smartContracts which will be triggered locally, and not by the contract committee
checkLocaltriggerContracts(blockinfo)
@ -141,20 +141,32 @@ def processBlock(blockindex=None, blockhash=None):
acceptedTxList = []
# Scan every transaction
logger.info("Before tx loop")
counter = 0
transaction_counter = 0
if blockindex == 2211700:
pdb.set_trace()
for transaction in blockinfo["tx"]:
counter = counter + 1
logger.info(f"Transaction {counter} {transaction}")
transaction_counter = transaction_counter + 1
logger.info(f"Transaction {transaction_counter} : {transaction}")
current_index = -1
if transaction in ['adcbcf1781bb319645a1e115831dc0fa54b3391cec780db48e54dae3c58f4470','c6eb7adc731a60b2ffa0c48d0d72d33b2ec3a33e666156e729a63b25f6c5cd56','ac00adb1a1537d485b287b8a9d4aa135c9e99f30659e7355906f5e7a8ff0552a','066337542c568dd339a4b30f727e1466e07bf0c6a2823e5f5157e0c8cf4721b1','ebf3219efb29b783fa0d6ee5f1d1aaf1a9c55ffdae55c174c82faa2e49bcd74d','ec9a852aa8a27877ba79ae99cc1359c0e04f6e7f3097521279bcc68e3883d760','77c92bcf40a86cd2e2ba9fa678249a9f4753c98c8038b1b9e9a74008f0ec93e8', '9110512d1696dae01701d8d156264a48ca1100f96c3551904ac3941b363138a1', 'b3e5c6343e3fc989e1d563b703573a21e0d409eb2ca7a9392dff7c7c522b1551', '1e5d1cb60449f15b0e9d44db177605d7e86999ba149effcc1d276c2178ceac3d',
'1586711334961abea5c0b9769cbc626cbc016a59c9c8a423a03e401da834083a', 'bb6cef5e9612363ed263291e8d3b39533661b3ba1b3ce8c2e9500158124266b8','511f16a69c5f62ad1cce70a2f9bfba133589e3ddc560d406c4fbf3920eae8469']:
pass
# TODO CLEANUP - REMOVE THIS WHILE SECTION, WHY IS IT HERE?
while(current_index == -1):
transaction_data = newMultiRequest(f"tx/{transaction}")
try:
text = transaction_data["floData"]
# TODO CLEANUP - REMOVE TEXT STUB AFTER TESTING
'''text = Create Smart Contract with the name swap-bitcoin-bioscope@ of the type continuous-event*
at the address stateF=address:oPkHWcvqBHfCortTHScrVBjXLsZhWie99C:bitcoin_price_source:bitpay:usd_inr_exchange_source:bitpay end-stateF oYzeeUBWRpzRuczW6myh2LHGnXPyR2Bc6k$ with contract-conditions :
(1) subtype = tokenswap
(2) accepting_token = bitcoin#
(3) selling_token = bioscope#
(4) price = "15"
(5) priceType="statef" end-contract-conditions'''
text = text.replace("\n", " \n ")
current_index = 2
except:
@ -199,7 +211,7 @@ def updateLatestTransaction(transactionData, parsed_data, db_reference, transact
if transaction_type is None:
transaction_type = parsed_data['type']
conn.execute("INSERT INTO latestTransactions(transactionHash, blockNumber, jsonData, transactionType, parsedFloData, db_reference) VALUES (?,?,?,?,?,?)", (transactionData['txid'], transactionData['blockheight'], json.dumps(transactionData), transaction_type, json.dumps(parsed_data), db_reference))
conn.commit()
#conn.commit()
conn.close()
@ -207,7 +219,7 @@ def updateLatestBlock(blockData):
# connect to latest block db
conn = create_database_connection('latest_cache', {'db_name':"latestCache"})
conn.execute('INSERT INTO latestBlocks(blockNumber, blockHash, jsonData) VALUES (?,?,?)', (blockData['height'], blockData['hash'], json.dumps(blockData)))
conn.commit()
#conn.commit()
conn.close()
@ -367,17 +379,13 @@ def transferToken(tokenIdentification, tokenAmount, inputAddress, outputAddress,
# move the pids consumed in the transaction to consumedTable and delete them from activeTable
session.execute('INSERT INTO consumedTable (id, address, parentid, consumedpid, transferBalance, addressBalance, orphaned_parentid, blockNumber) SELECT id, address, parentid, consumedpid, transferBalance, addressBalance, orphaned_parentid, blockNumber FROM activeTable WHERE id={}'.format(piditem[0]))
session.execute('DELETE FROM activeTable WHERE id={}'.format(piditem[0]))
session.commit()
session.commit()
blockchainReference = neturl + 'tx/' + transaction_data['txid']
session.add(TransactionHistory(sourceFloAddress=inputAddress, destFloAddress=outputAddress,
transferAmount=tokenAmount, blockNumber=blockinfo['height'],
blockHash=blockinfo['hash'], time=blockinfo['time'],
transactionHash=transaction_data['txid'],
blockchainReference=blockchainReference, jsonData=json.dumps(transaction_data),
transactionType=parsed_data['type'],
parsedFloData=json.dumps(parsed_data)))
session.add(TransactionHistory(sourceFloAddress=inputAddress, destFloAddress=outputAddress,transferAmount=tokenAmount, blockNumber=blockinfo['height'],
blockHash=blockinfo['hash'], time=blockinfo['time'],
transactionHash=transaction_data['txid'],
blockchainReference=blockchainReference, jsonData=json.dumps(transaction_data), transactionType=parsed_data['type'], parsedFloData=json.dumps(parsed_data)))
session.commit()
session.close()
return 1
@ -386,15 +394,19 @@ def transferToken(tokenIdentification, tokenAmount, inputAddress, outputAddress,
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()
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]}")
# todo : filter activeContracts which only have local triggers
attributevaluepair = connection.execute(
"select attribute, value from contractstructure where attribute != 'contractName' and attribute != 'flodata' and attribute != 'contractAddress'").fetchall()
attributevaluepair = connection.execute("select attribute, value from contractstructure where attribute != 'contractName' and attribute != 'flodata' and attribute != 'contractAddress'").fetchall()
contractStructure = {}
conditionDict = {}
counter = 0
@ -408,6 +420,16 @@ def checkLocaltriggerContracts(blockinfo):
contractStructure['exitconditions'] = conditionDict
del counter, conditionDict
# TODO - FIGURE A BETTER SOLUTION FOR THIS
transaction_data = {}
transaction_data['txid'] = 'internalTrigger'
parsed_data = {}
parsed_data['type'] = 'internalTrigger'
if 'contractAddress' not in contractStructure.keys():
contractStructure['contractAddress'] = contract[1]
if contractStructure['contractType'] == 'one-time-event':
# Check if the contract has blockchain trigger or committee trigger
if 'exitconditions' in contractStructure:
@ -474,11 +496,8 @@ def checkLocaltriggerContracts(blockinfo):
elif 'payeeAddress' in contractStructure:
# This is a local trigger contract
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]
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']
@ -521,17 +540,14 @@ def checkLocaltriggerContracts(blockinfo):
expiryTime = contractStructure['expiryTime']
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:])
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(blockinfo['time']).to('Asia/Kolkata')
if blocktime_object > expirytime_object:
if 'minimumsubscriptionamount' in contractStructure:
minimumsubscriptionamount = contractStructure['minimumsubscriptionamount']
tokenAmount_sum = \
connection.execute('select sum(tokenAmount) from contractparticipants').fetchall()[0][0]
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]
@ -580,7 +596,8 @@ def checkLocaltriggerContracts(blockinfo):
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, blockinfo = blockinfo)
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
@ -601,17 +618,12 @@ def checkLocaltriggerContracts(blockinfo):
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]))
'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
@ -982,14 +994,14 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
# All FLO checks completed at this point.
# Semantic rules for parsed data begins
# todo Rule 44 - Process as per the type of transaction
if parsed_data['type'] == 'transfer':
logger.info(f"Transaction {transaction_data['txid']} is of the type transfer")
# todo Rule 45 - If the transfer type is token, then call the function transferToken to adjust the balances
if parsed_data['transferType'] == 'token':
if not check_if_contract_address(inputlist[0]) and not check_if_contract_address(outputlist[0]):
if not is_a_contract_address(inputlist[0]) and not is_a_contract_address(outputlist[0]):
# check if the token exists in the database
if check_database_existence('token', {'token_name':f"{parsed_data['tokenIdentification']}"}):
# Pull details of the token type from system.db database
@ -1601,8 +1613,6 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
logger.info("Something went wrong in the smartcontract token transfer method")
return 0
elif contract_type == 'continuos-event':
contract_subtype = contract_session.query(ContractStructure.value).filter(ContractStructure.attribute == 'subtype').first()[0]
if contract_subtype == 'tokenswap':
@ -1867,7 +1877,7 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
# todo Rule 47 - If the parsed data type is token incorporation, then check if the name hasn't been taken already
# if it has been taken then reject the incorporation. Else incorporate it
elif parsed_data['type'] == 'tokenIncorporation':
if not check_if_contract_address(inputlist[0]):
if not is_a_contract_address(inputlist[0]):
if not check_database_existence('token', {'token_name':f"{parsed_data['tokenIdentification']}"}):
session = create_database_session_orm('token', {'token_name': f"{parsed_data['tokenIdentification']}"}, Base)
session.add(ActiveTable(address=inputlist[0], parentid=0, transferBalance=parsed_data['tokenAmount'], addressBalance=parsed_data['tokenAmount'], blockNumber=blockinfo['height']))
@ -2010,7 +2020,7 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
session.add(ContractStructure(attribute='contractAddress', index=0, value=parsed_data['contractAddress']))
session.add(ContractStructure(attribute='flodata', index=0, value=parsed_data['flodata']))
session.add(ContractStructure(attribute='expiryTime', index=0, value=parsed_data['contractConditions']['expiryTime']))
if 'contractAmount' in parsed_data['contractConditions']:
if 'contractAmount' in parsed_data['contractConditions'].keys():
session.add(
ContractStructure(attribute='contractAmount', index=0,
value=parsed_data['contractConditions']['contractAmount']))
@ -2099,7 +2109,7 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
contractName=parsed_data['contractName'],
contractAddress=inputadd,
contractType='one-time-event-trigger',
tokens_db=[parsed_data['tokenIdentification']],
tokens_db=json.dumps([parsed_data['tokenIdentification']]),
parsed_data=json.dumps(parsed_data),
transactionHash=transaction_data['txid'],
blockNumber=transaction_data['blockheight']))
@ -2150,11 +2160,17 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
session.add(ContractStructure(attribute='contractName', index=0, value=parsed_data['contractName']))
session.add(ContractStructure(attribute='contractAddress', index=0, value=parsed_data['contractAddress']))
session.add(ContractStructure(attribute='flodata', index=0, value=parsed_data['flodata']))
if parsed_data['stateF'] != {}:
for key, value in parsed_data['stateF'].items():
session.add(ContractStructure(attribute=f'statef-{key}', index=0, value=value))
if 'subtype' in parsed_data['contractConditions']:
# todo: Check if the both the tokens mentioned exist if its a token swap
if (parsed_data['contractConditions']['subtype'] == 'tokenswap') and (check_database_existence('token', {'token_name':f"{parsed_data['contractConditions']['accepting_token'].split('#')[0]}"})) and (check_database_existence('token', {'token_name':f"{parsed_data['contractConditions']['selling_token'].split('#')[0]}"})):
#if (parsed_data['contractConditions']['subtype'] == 'tokenswap') and (check_database_existence('token', {'token_name':f"{parsed_data['contractConditions']['accepting_token'].split('#')[0]}"})) and (check_database_existence('token', {'token_name':f"{parsed_data['contractConditions']['selling_token'].split('#')[0]}"})):
if (parsed_data['contractConditions']['subtype'] == 'tokenswap') and (check_database_existence('token', {'token_name':f"{parsed_data['contractConditions']['selling_token'].split('#')[0]}"})):
#if (parsed_data['contractConditions']['subtype'] == 'tokenswap'):
if parsed_data['contractConditions']['pricetype'] in ['predetermined','determined']:
if parsed_data['contractConditions']['pricetype'] in ['predetermined','statef']:
session.add(ContractStructure(attribute='subtype', index=0, value=parsed_data['contractConditions']['subtype']))
session.add(ContractStructure(attribute='accepting_token', index=0, value=parsed_data['contractConditions']['accepting_token']))
session.add(ContractStructure(attribute='selling_token', index=0, value=parsed_data['contractConditions']['selling_token']))
@ -2162,9 +2178,10 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
session.add(ContractStructure(attribute='pricetype', index=0, value=parsed_data['contractConditions']['pricetype']))
session.add(ContractStructure(attribute='price', index=0, value=parsed_data['contractConditions']['price']))
# Store transfer as part of ContractTransactionHistory
# Store transfer as part of ContractTransactionHistory
blockchainReference = neturl + 'tx/' + transaction_data['txid']
session.add(ContractTransactionHistory(transactionType='incorporation', sourceFloAddress=inputadd,
session.add(ContractTransactionHistory(transactionType='incorporation',
sourceFloAddress=inputadd,
destFloAddress=outputlist[0],
transferAmount=None,
blockNumber=transaction_data['blockheight'],
@ -2184,6 +2201,8 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
accepting_sending_tokenlist = [parsed_data['contractConditions']['accepting_token'], parsed_data['contractConditions']['selling_token']]
for token_name in accepting_sending_tokenlist:
token_name = token_name.split('#')[0]
if token_name == 'bitcoin':
continue
session = create_database_session_orm('token', {'token_name': f"{token_name}"}, Base)
session.add(TokenContractAssociation(tokenIdentification=token_name,
contractName=parsed_data['contractName'],
@ -2226,9 +2245,7 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
blockNumber=transaction_data['blockheight']))
session.commit()
session.close()
updateLatestTransaction(transaction_data, parsed_data, f"{parsed_data['contractName']}-{parsed_data['contractAddress']}")
pushData_SSEapi('Contract | Contract incorporated at transaction {} with name {}-{}'.format(transaction_data['txid'], parsed_data['contractName'], parsed_data['contractAddress']))
return 1
@ -2286,8 +2303,8 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
session.close()
return 0
session.commit()
session.close()
session.commit()
session.close()
else:
logger.info(f"Transaction {transaction_data['txid']} rejected as a Smart Contract with the name {parsed_data['contractName']} at address {parsed_data['contractAddress']} already exists")
@ -2319,7 +2336,6 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
elif parsed_data['type'] == 'smartContractPays':
logger.info(f"Transaction {transaction_data['txid']} is of the type smartContractPays")
# Check if input address is a committee address
if inputlist[0] in committeeAddressList:
# check if the contract exists
@ -2595,15 +2611,11 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
# Trigger the contract
connection = create_database_connection('smart_contract', {'contract_name':f"{parsed_data['contractName']}", 'contract_address':f"{outputlist[0]}"})
contractWinners = connection.execute(
'select * from contractparticipants where userChoice="{}"'.format(
parsed_data['triggerCondition'])).fetchall()
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(
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]
tokenIdentification = connection.execute('select value from contractstructure where attribute="tokenIdentification"').fetchall()[0][0]
for winner in contractWinners:
winnerAmount = "%.8f" % ((winner[2] / winnerSum) * tokenSum)
@ -2611,8 +2623,7 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
if returnval is None:
logger.critical("Something went wrong in the token transfer method while doing local Smart Contract Trigger")
return 0
connection.execute(
f"update contractparticipants set winningAmount='{winnerAmount}' where participantAddress='{winner[1]}' and transactionHash='{winner[4]}'")
connection.execute(f"update contractparticipants set winningAmount='{winnerAmount}' where participantAddress='{winner[1]}' and transactionHash='{winner[4]}'")
# add transaction to ContractTransactionHistory
blockchainReference = neturl + 'tx/' + transaction_data['txid']
@ -2645,9 +2656,7 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
updateLatestTransaction(transaction_data, parsed_data, f"{parsed_data['contractName']}-{outputlist[0]}")
pushData_SSEapi(
'Trigger | Contract triggered of the name {}-{} is active currently at transaction {}'.format(
parsed_data['contractName'], outputlist[0], transaction_data['txid']))
pushData_SSEapi('Trigger | Contract triggered of the name {}-{} is active currently at transaction {}'.format(parsed_data['contractName'], outputlist[0], transaction_data['txid']))
return 1
else:
logger.info(f"Transaction {transaction_data['txid']} rejected as Smart Contract named {parsed_data['contractName']} at the address {outputlist[0]} doesn't exist")
@ -2851,7 +2860,7 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
Creation and transfer amount .. only integer parts will be taken
Keyword nft must be present in both creation and transfer
'''
if not check_if_contract_address(inputlist[0]):
if not is_a_contract_address(inputlist[0]):
if not check_database_existence('token', {'token_name':f"{parsed_data['tokenIdentification']}"}):
session = create_database_session_orm('token', {'token_name': f"{parsed_data['tokenIdentification']}"}, Base)
session.add(ActiveTable(address=inputlist[0], parentid=0, transferBalance=parsed_data['tokenAmount'], blockNumber=blockinfo['height']))
@ -2924,9 +2933,9 @@ def processTransaction(transaction_data, parsed_data, blockinfo):
session.close()
pushData_SSEapi(f"NFT incorporation at transaction {transaction_data['txid']} rejected as either the input address is part of a contract address")
return 0
elif parsed_data['type'] == 'infiniteTokenIncorporation':
if not check_if_contract_address(inputlist[0]) and not check_if_contract_address(outputlist[0]):
if not is_a_contract_address(inputlist[0]) and not is_a_contract_address(outputlist[0]):
if not check_database_existence('token', {'token_name':f"{parsed_data['tokenIdentification']}"}):
parsed_data['tokenAmount'] = 0
tokendb_session = create_database_session_orm('token', {'token_name': f"{parsed_data['tokenIdentification']}"}, Base)
@ -3026,6 +3035,8 @@ def scanBlockchain():
break
for blockindex in range(startblock, current_index):
if blockindex in IGNORE_BLOCK_LIST:
continue
processBlock(blockindex=blockindex)
# At this point the script has updated to the latest block
@ -3118,6 +3129,10 @@ serverlist = serverlist.split(',')
neturl = config['DEFAULT']['FLOSIGHT_NETURL']
tokenapi_sse_url = config['DEFAULT']['TOKENAPI_SSE_URL']
IGNORE_BLOCK_LIST = config['DEFAULT']['IGNORE_BLOCK_LIST'].split(',')
IGNORE_BLOCK_LIST = [int(s) for s in IGNORE_BLOCK_LIST]
IGNORE_TRANSACTION_LIST = config['DEFAULT']['IGNORE_TRANSACTION_LIST'].split(',')
# Delete database and smartcontract directory if reset is set to 1
if args.reset == 1:
logger.info("Resetting the database. ")