def fetch_transactions(block_hash: str): client = RClient(TARGET_RNODE_HOST, TARGET_RNODE_PORT, ( ('grpc.keepalive_time_ms', 10000), ('grpc.max_receive_message_length', 1619430400), ), True) client.install_param(mainnet_param) logging.info("request {} getTransaction from server {}".format( block_hash, TARGET_RNODE_HOST)) transactions = client.get_transaction(block_hash) logging.info("receive {} getTransaction {} from server {}".format( block_hash, transactions, TARGET_RNODE_HOST)) client.close() return json.dumps(to_dict(transactions)).encode('utf8')
class rgovAPI: def __init__(self, net_name: str): if net_name in NETWORKS: #print('Using ', net_name) network = NETWORKS[net_name] self.client = RClient(network['observerBase']['host'], network['observerBase']['port']) self.network = network self.net_name = net_name self.keyVault = self.import_shared_private_keys() else: reason = 'Network ' + net_name + ' NOT Found as an option' raise Exception(reason) def close(self) -> None: self.client.close() def __enter__(self) -> 'rgovAPI': return self def __exit__(self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType]) -> None: self.close() def import_shared_private_keys(self) -> Mapping[str, str]: search = PRIVATE_KEYS + "pk.*" keys = {} for fname in glob.glob(search): name = fname.split("/")[-1] names = name.split(".") if len(names) == 2: file = open(fname) pk = file.read() file.close() keys[names[1]] = pk return keys def get_private_key(self, name: str) -> PrivateKey: if name in self.keyVault: return PrivateKey.from_hex(self.keyVault[name]) reason = 'No key found in vault for ' + name raise Exception(reason) def getDeploy(self, deployId: str, tries: int = 10): print("getBlock ", self.network['validatorBase']['host']) url = self.network['validatorBase']['url'] + self.network[ 'validatorBase']['host'] if self.network['validatorBase']['port'] > 0: url += ':' + str(self.network['validatorBase']['port']) url += '/api/deploy/' + deployId print("Get Deploy ", url) while tries > 0: result = requests.get(url) print("Got ", result) if result.status_code == 200: break tries = tries - 1 time.sleep(1.0) print("Try again ", tries) print(result.json()) return result.json() def getBlock(self, block_hash: str): print("getBlock ", self.network['validatorBase']['host']) url = self.network['validatorBase']['url'] + self.network[ 'validatorBase']['host'] if self.network['validatorBase']['port'] > 0: url += ':' + str(self.network['validatorBase']['port']) url += '/api/block/' + block_hash print("Get Block ", url) result = requests.get(url) return result.json() def getDeployData(self, block_hash: str): #print("getDeployData ", self.network['validatorBase']['host']) url = self.network['validatorBase']['url'] + self.network[ 'validatorBase']['host'] if self.network['validatorBase']['port'] > 0: url += ':' + str(self.network['validatorBase']['port']) url += '/api/data-at-name' data = '{"depth": 1, "name": {"UnforgDeploy": {"data": "' + block_hash + '"}}}' #print("Post ", url, data) headers = {'Content-type': 'text/plain', 'Accept': '*/*'} result = requests.post(url, data, headers=headers) return result.json() def propose(self) -> None: if self.network['adminBase']['url']: url = self.network['adminBase']['url'] + self.network['adminBase'][ 'host'] if self.network['adminBase']['port'] > 0: url += ':' + str(self.network['adminBase']['port']) url += '/api/propose' time.sleep(0.5) result = requests.post(url) return result.json() def checkBalance(self, rev_addr: str, block_hash: str = '') -> int: contract = render_contract_template( CHECK_BALANCE_RHO_TPL, { 'addr': rev_addr, 'myBalance': "mybal" }, ) result = self.client.exploratory_deploy(contract, block_hash) return result[0].exprs[0].e_list_body.ps[2].exprs[0].g_int def transfer(self, from_addr: str, to_addr: str, amount: int, key: PrivateKey) -> str: contract = render_contract_template( TRANSFER_RHO_TPL, { 'from': from_addr, 'to': to_addr, 'amount': amount }, ) deployId = self.client.deploy_with_vabn_filled(key, contract, TRANSFER_PHLO_PRICE, TRANSFER_PHLO_LIMIT) #print("transfer ", deployId) self.propose() result = self.client.get_data_at_deploy_id(deployId, 5) result = result.blockInfo[0].postBlockData[0].exprs[0].e_tuple_body status = result.ps[0].exprs[0].g_bool msg = result.ps[1].exprs[0].g_string return [status, msg] def newInbox(self, key: PrivateKey) -> str: fname = MASTERURI + self.net_name + '.json' file = open(fname) masterstr = file.read() file.close() start = masterstr.find('rho:id:') end = masterstr.find('`', start) if start < 0 or end < 0: return [False, "masterURI file corrupt"] masterURI = masterstr[start:end] contract = render_contract_template( NEWINBOX_RHO_TPL, {'masterURI': masterURI}, #, 'inbox': 'inboxURI'}, ) deployId = self.client.deploy_with_vabn_filled(key, contract, TRANSFER_PHLO_PRICE, TRANSFER_PHLO_LIMIT) print("newInbox ", deployId) result = self.propose() result = self.client.get_data_at_deploy_id(deployId, 5) if result is None: return [False, "no deploy data"] if len(result.blockInfo) == 0: return [False, "no deploy data"] if (len(result.blockInfo[0].postBlockData)) == 0: return [False, "no deploy data"] status = [False, "URI not found"] if (len(result.blockInfo[0].postBlockData[0].exprs) > 0): if (result.blockInfo[0].postBlockData[0].exprs[0].HasField( 'e_list_body')): for data in result.blockInfo[0].postBlockData[0].exprs[ 0].e_list_body.ps: #if data.exprs[0].HasField("g_string"): # print("Found (mystuff)", data.exprs[0].g_string) if data.exprs[0].HasField("e_map_body"): for kvs in data.exprs[0].e_map_body.kvs: if kvs.key.exprs[0].g_string == "inbox": if kvs.value.exprs[0].HasField("e_map_body"): for inbox in kvs.value.exprs[ 0].e_map_body.kvs: if inbox.key.exprs[ 0].g_string == "URI": status = [ True, inbox.value.exprs[0].g_uri ] return status def newIssue(self, key: PrivateKey, inbox: str, issue: str, options: list) -> str: if len(options) < 2: return [False, "newIssue: options must have at least 2 choices"] choices = '"' + '", "'.join(options) + '"' contract = render_contract_template( NEWISSUE_RHO_TPL, { 'inbox': inbox, 'issue': issue, 'choices': choices }, ) deployId = self.client.deploy_with_vabn_filled(key, contract, TRANSFER_PHLO_PRICE, TRANSFER_PHLO_LIMIT) print("newIssue ", deployId) self.propose() result = self.client.get_data_at_deploy_id(deployId, 5) if result is None: return [False, "no deploy data"] msg = "No status messages found" status = False if (len(result.blockInfo[0].postBlockData) > 0): for post in result.blockInfo[0].postBlockData: if post.exprs[0].HasField("g_string"): if status: msg = msg + " " + post.exprs[0].g_string else: msg = post.exprs[0].g_string status = True return [status, msg, result] def addVoterToIssue(self, key: PrivateKey, locker: str, voter: str, issue: str) -> str: contract = render_contract_template( ADDVOTER_RHO_TPL, { 'inbox': locker, 'voterURI': voter, 'issue': issue }, ) deployId = self.client.deploy_with_vabn_filled(key, contract, TRANSFER_PHLO_PRICE, TRANSFER_PHLO_LIMIT) print("addVoterToIssue ", deployId) self.propose() result = self.client.get_data_at_deploy_id(deployId) if result is None: return [False, "no deploy data"] return [True, result] def peekInbox(self, key: PrivateKey, inbox: str, type: str, subtype: str): contract = render_contract_template( PEEKINBOX_RHO_TPL, { 'inbox': inbox, 'type': type, 'subtype': subtype }, ) deployId = self.client.deploy_with_vabn_filled(key, contract, TRANSFER_PHLO_PRICE, TRANSFER_PHLO_LIMIT) print("peekInbox ", deployId) self.propose() result = self.client.get_data_at_deploy_id(deployId, 5) if result is None: return [False, "no deploy data"] status = [False, "URI Not found"] if len(result.blockInfo) > 0: for post in result.blockInfo[0].postBlockData: if len(post.exprs) > 0: if post.exprs[0].HasField("e_map_body"): for kvs in post.exprs[0].e_map_body.kvs: if kvs.key.exprs[0].HasField("g_string"): if kvs.key.exprs[0].g_string == "URI": status = [True, kvs.value.exprs[0].g_uri] return status def castVote(self, key: PrivateKey, inbox: str, issue: str, choice: str): contract = render_contract_template( CASTVOTE_RHO_TPL, { 'inbox': inbox, 'issue': issue, 'choice': choice }, ) deployId = self.client.deploy_with_vabn_filled(key, contract, TRANSFER_PHLO_PRICE, TRANSFER_PHLO_LIMIT) print("castVote ", deployId) self.propose() result = self.client.get_data_at_deploy_id(deployId) if result is None: return [False, "no deploy data"] oldvote = "" newvote = "" badvote = "" choices = "" if len(result.blockInfo) == 1: for post in result.blockInfo[0].postBlockData: if post.exprs[0].HasField("e_list_body"): if post.exprs[0].e_list_body.ps[0].exprs[ 0].g_string == "oldvote was": if len(post.exprs[0].e_list_body.ps) > 1: if len(post.exprs[0].e_list_body.ps[1].exprs) > 0: oldvote = post.exprs[0].e_list_body.ps[ 1].exprs[0].g_string if post.exprs[0].e_list_body.ps[0].exprs[ 0].g_string == "newvote is": if len(post.exprs[0].e_list_body.ps) > 1: if len(post.exprs[0].e_list_body.ps[1].exprs) > 0: newvote = post.exprs[0].e_list_body.ps[ 1].exprs[0].g_string if post.exprs[0].HasField("e_map_body"): for kvs in post.exprs[0].e_map_body.kvs: if kvs.key.exprs[0].g_string == "unknown proposal": badvote = kvs.value.exprs[0].g_string if kvs.key.exprs[0].g_string == "valid proposals": for proposals in kvs.value.exprs[0].e_set_body.ps: if choices == "": choices = proposals.exprs[0].g_string else: choices = choices + ", " + proposals.exprs[ 0].g_string if badvote != "": return [False, [badvote, choices]] else: return [True, [oldvote, newvote]] def delegateVote(self, key: PrivateKey, inbox: str, issue: str, delegate: str) -> str: contract = render_contract_template( DELEGATEVOTE_RHO_TPL, { 'inbox': inbox, 'issue': issue, 'delegate': delegate }, ) deployId = self.client.deploy_with_vabn_filled(key, contract, TRANSFER_PHLO_PRICE, TRANSFER_PHLO_LIMIT) print("delegateVote ", deployId) self.propose() result = self.client.get_data_at_deploy_id(deployId) if result.length == 0: return [False, "No issue found"] status = [False, "URI Not found"] for post in result.blockInfo[0].postBlockData: if len(post.exprs) > 0: if post.exprs[0].HasField("e_tuple_body"): body = post.exprs[0].e_tuple_body status = [ True, [ body.ps[1].exprs[0].g_string, body.ps[2].exprs[0].g_uri ] ] return status def tallyVotes(self, key: PrivateKey, inbox: str, issue: str) -> str: contract = render_contract_template( TALLYVOTES_RHO_TPL, { 'inbox': inbox, 'issue': issue }, ) deployId = self.client.deploy_with_vabn_filled(key, contract, TRANSFER_PHLO_PRICE, TRANSFER_PHLO_LIMIT) print("tallyVotes ", deployId) self.propose() #result = self.getDeployData(deployId) result = self.client.get_data_at_deploy_id(deployId) if result.length == 0: return [False, "No issue found"] votes = {} found_counts = False found_done = False for BData in result.blockInfo[0].postBlockData: if len(BData.exprs) > 0: if BData.exprs[0].HasField("g_string"): found_done = True if BData.exprs[0].HasField("e_list_body"): for BList in BData.exprs[0].e_list_body.ps: if BList.exprs[0].HasField("g_string"): if BList.exprs[0].g_string == "counts": found_counts = True if BList.exprs[0].HasField("e_map_body"): for voted in BList.exprs[0].e_map_body.kvs: votes[voted.key.exprs[0]. g_string] = voted.value.exprs[0].g_int return [found_counts and found_done, votes]