From 7ee4bc5caed80e41fb4789330e5fc88ae22cb206 Mon Sep 17 00:00:00 2001 From: Holger Nahrstaedt <holgernahrstaedt@gmx.de> Date: Mon, 7 Sep 2020 12:46:35 +0200 Subject: [PATCH] Fix broadcasting amounts that have a higher precision than allowed * Use floor instead of round in beembase/Amount in order to handle floats which have a higher precision than allowed * json_str parameter has been added to beembase.Amount, when True, a json dict is returned as string (needing when broadcasting with use_condenser=False) --- CHANGELOG.rst | 2 + beem/account.py | 5 + beem/blockchaininstance.py | 22 +++-- beem/market.py | 2 + beem/witness.py | 1 + beembase/objects.py | 13 +-- beembase/operations.py | 68 ++++++++----- tests/beem/test_amount.py | 2 +- tests/beem/test_hive.py | 171 ++++++++++++++++++++++++--------- tests/beem/test_steem.py | 155 +++++++++++++++++++++--------- tests/beembase/test_objects.py | 15 +++ 11 files changed, 326 insertions(+), 130 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 83458809..bd1f06d7 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,8 @@ Changelog * import keyring only when needed * Add use_condenser to config (can be set wtih beempy set), when set to False, condenser calls are not used * Add set_expiration to Object Cache +* Use floor instead of round in beembase/Amount in order to handle floats which have a higher precision than allowed +* json_str parameter has been added to beembase.Amount, when True, a json dict is returned as string (needing when broadcasting with use_condenser=False) 0.24.8 ------ diff --git a/beem/account.py b/beem/account.py index 5a6915a7..ec9a9985 100644 --- a/beem/account.py +++ b/beem/account.py @@ -2791,6 +2791,7 @@ class Account(BlockchainObject): "memo": memo, "from": account["name"], "prefix": self.blockchain.prefix, + "json_str": not bool(self.blockchain.config["use_condenser"]), "replace_hive_by_steem": replace_hive_by_steem, }) return self.blockchain.finalizeOp(op, account, "active", **kwargs) @@ -2820,6 +2821,7 @@ class Account(BlockchainObject): "to": to["name"], "amount": amount, "prefix": self.blockchain.prefix, + "json_str": not bool(self.blockchain.config["use_condenser"]), "replace_hive_by_steem": replace_hive_by_steem, }) return self.blockchain.finalizeOp(op, account, "active", **kwargs) @@ -2850,6 +2852,7 @@ class Account(BlockchainObject): "requestid": request_id, "amount": amount, "prefix": self.blockchain.prefix, + "json_str": not bool(self.blockchain.config["use_condenser"]), "replace_hive_by_steem": replace_hive_by_steem, }) @@ -2888,6 +2891,7 @@ class Account(BlockchainObject): "amount": amount, "memo": memo, "prefix": self.blockchain.prefix, + "json_str": not bool(self.blockchain.config["use_condenser"]), "replace_hive_by_steem": replace_hive_by_steem, }) return self.blockchain.finalizeOp(op, account, "active", **kwargs) @@ -2939,6 +2943,7 @@ class Account(BlockchainObject): "amount": amount, "memo": memo, "prefix": self.blockchain.prefix, + "json_str": not bool(self.blockchain.config["use_condenser"]), "replace_hive_by_steem": replace_hive_by_steem, }) return self.blockchain.finalizeOp(op, account, "active", **kwargs) diff --git a/beem/blockchaininstance.py b/beem/blockchaininstance.py index 9750bef7..176edbdb 100644 --- a/beem/blockchaininstance.py +++ b/beem/blockchaininstance.py @@ -769,22 +769,24 @@ class BlockChainInstance(object): @property def is_hive(self): - config = self.get_config() + config = self.get_config(use_stored_data=True) if config is None: return False - return 'HIVE_CHAIN_ID' in self.get_config() + return 'HIVE_CHAIN_ID' in config @property def is_steem(self): - config = self.get_config() + config = self.get_config(use_stored_data=True) if config is None: return False - return 'STEEM_CHAIN_ID' in self.get_config() + return 'STEEM_CHAIN_ID' in config def get_replace_hive_by_steem(self): - hf_version = int(self.get_blockchain_version().split('.')[1]) + if not self.is_hive: + return False + hf_version = int(self.get_blockchain_version(use_stored_data=True).split('.')[1]) replace_hive_by_steem = True - if self.is_hive and hf_version >= 24: + if hf_version >= 24: replace_hive_by_steem = False return replace_hive_by_steem @@ -1072,6 +1074,7 @@ class BlockChainInstance(object): "fee": Amount(fee, blockchain_instance=self), "creator": creator["name"], "prefix": self.prefix, + "json_str": not bool(self.config["use_condenser"]), "replace_hive_by_steem": replace_hive_by_steem, } op = operations.Claim_account(**op) @@ -1252,6 +1255,7 @@ class BlockChainInstance(object): "fee": Amount(fee, blockchain_instance=self), "creator": creator["name"], "prefix": self.prefix, + "json_str": not bool(self.config["use_condenser"]), "replace_hive_by_steem": replace_hive_by_steem, } op = operations.Claim_account(**op) @@ -1470,6 +1474,7 @@ class BlockChainInstance(object): 'memo_key': memo, "json_metadata": json_meta or {}, "prefix": self.prefix, + "json_str": not bool(self.config["use_condenser"]), "replace_hive_by_steem": replace_hive_by_steem, } op = operations.Account_create(**op) @@ -1680,7 +1685,9 @@ class BlockChainInstance(object): for k in props: props_list.append([k, props[k]]) replace_hive_by_steem = self.get_replace_hive_by_steem() - op = operations.Witness_set_properties({"owner": owner["name"], "props": props_list, "prefix": self.prefix, "replace_hive_by_steem": replace_hive_by_steem}) + op = operations.Witness_set_properties({"owner": owner["name"], "props": props_list, "prefix": self.prefix, + "json_str": not bool(self.config["use_condenser"]), + "replace_hive_by_steem": replace_hive_by_steem}) tb = TransactionBuilder(blockchain_instance=self) tb.appendOps([op]) tb.appendWif(wif) @@ -1726,6 +1733,7 @@ class BlockChainInstance(object): "props": props, "fee": Amount(0, self.token_symbol, blockchain_instance=self), "prefix": self.prefix, + "json_str": not bool(self.config["use_condenser"]), "replace_hive_by_steem": replace_hive_by_steem, }) return self.finalizeOp(op, account, "active", **kwargs) diff --git a/beem/market.py b/beem/market.py index 94635b7e..281ef6f6 100644 --- a/beem/market.py +++ b/beem/market.py @@ -607,6 +607,7 @@ class Market(dict): "expiration": formatTimeFromNow(expiration), "fill_or_kill": killfill, "prefix": self.blockchain.prefix, + "json_str": not bool(self.blockchain.config["use_condenser"]), "replace_hive_by_steem": replace_hive_by_steem, }) @@ -692,6 +693,7 @@ class Market(dict): "expiration": formatTimeFromNow(expiration), "fill_or_kill": killfill, "prefix": self.blockchain.prefix, + "json_str": not bool(self.blockchain.config["use_condenser"]), "replace_hive_by_steem": replace_hive_by_steem, }) if returnOrderId: diff --git a/beem/witness.py b/beem/witness.py index f78ea981..5c25f883 100644 --- a/beem/witness.py +++ b/beem/witness.py @@ -167,6 +167,7 @@ class Witness(BlockchainObject): "quote": quote, }, "prefix": self.blockchain.prefix, + "json_str": not bool(self.blockchain.config["use_condenser"]), "replace_hive_by_steem": replace_hive_by_steem, }) return self.blockchain.finalizeOp(op, account, "active") diff --git a/beembase/objects.py b/beembase/objects.py index 7e4cbd4a..8dd1416c 100644 --- a/beembase/objects.py +++ b/beembase/objects.py @@ -6,6 +6,7 @@ from builtins import bytes, int, str from builtins import object from future.utils import python_2_unicode_compatible import json +from math import floor from beemgraphenebase.py23 import py23_bytes, bytes_types, integer_types, string_types, text_type from collections import OrderedDict from beemgraphenebase.types import ( @@ -26,8 +27,9 @@ default_prefix = "STM" class Amount(object): - def __init__(self, d, prefix=default_prefix, replace_hive_by_steem=True): + def __init__(self, d, prefix=default_prefix, replace_hive_by_steem=True, json_str=False): self.replace_hive_by_steem = replace_hive_by_steem + self.json_str = json_str if isinstance(d, string_types): self.amount, self.symbol = d.strip().split(" ") self.precision = None @@ -47,7 +49,7 @@ class Amount(object): self.asset = asset["asset"] if self.precision is None: raise Exception("Asset unknown") - self.amount = round(float(self.amount) * 10 ** self.precision) + self.amount = floor(float(self.amount) * 10 ** self.precision) # Workaround to allow transfers in HIVE if self.symbol == "HBD" and replace_hive_by_steem: @@ -94,7 +96,7 @@ class Amount(object): self.symbol = "STEEM" self.asset = d.asset["asset"] self.precision = d.asset["precision"] - self.amount = round(float(self.amount) * 10 ** self.precision) + self.amount = floor(float(self.amount) * 10 ** self.precision) self.str_repr = str(d) # self.str_repr = json.dumps((d.json())) # self.str_repr = '{:.{}f} {}'.format((float(self.amount) / 10 ** self.precision), self.precision, self.asset) @@ -111,7 +113,8 @@ class Amount(object): py23_bytes(symbol, "ascii")) def __str__(self): - # return json.dumps({"amount": self.amount, "precision": self.precision, "nai": self.asset}) + if self.json_str: + return json.dumps({"amount": str(self.amount), "precision": self.precision, "nai": self.asset}) return self.str_repr @@ -127,8 +130,6 @@ class Operation(GPHOperation): return class_ def operations(self): - if self.prefix == "WLS": - return operations_wls return operations def getOperationNameForId(self, i): diff --git a/beembase/operations.py b/beembase/operations.py index a14b7b23..c83d1965 100644 --- a/beembase/operations.py +++ b/beembase/operations.py @@ -52,6 +52,7 @@ class Transfer(GrapheneObject): kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) replace_hive_by_steem = kwargs.get("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) if "memo" not in kwargs: kwargs["memo"] = "" if isinstance(kwargs["memo"], dict): @@ -65,7 +66,7 @@ class Transfer(GrapheneObject): super(Transfer, self).__init__(OrderedDict([ ('from', String(kwargs["from"])), ('to', String(kwargs["to"])), - ('amount', Amount(kwargs["amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), + ('amount', Amount(kwargs["amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), ('memo', memo), ])) @@ -92,10 +93,11 @@ class Transfer_to_vesting(GrapheneObject): kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) replace_hive_by_steem = kwargs.get("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) super(Transfer_to_vesting, self).__init__(OrderedDict([ ('from', String(kwargs["from"])), ('to', String(kwargs["to"])), - ('amount', Amount(kwargs["amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), + ('amount', Amount(kwargs["amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), ])) @@ -184,6 +186,7 @@ class Account_create(GrapheneObject): kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) replace_hive_by_steem = kwargs.get("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) if not len(kwargs["new_account_name"]) <= 16: raise AssertionError("Account name must be at most 16 chars long") @@ -195,7 +198,7 @@ class Account_create(GrapheneObject): meta = kwargs["json_metadata"] super(Account_create, self).__init__(OrderedDict([ - ('fee', Amount(kwargs["fee"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), + ('fee', Amount(kwargs["fee"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), ('creator', String(kwargs["creator"])), ('new_account_name', String(kwargs["new_account_name"])), ('owner', Permission(kwargs["owner"], prefix=prefix)), @@ -215,6 +218,7 @@ class Account_create_with_delegation(GrapheneObject): kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) replace_hive_by_steem = kwargs.get("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) if not len(kwargs["new_account_name"]) <= 16: raise AssertionError("Account name must be at most 16 chars long") @@ -226,8 +230,8 @@ class Account_create_with_delegation(GrapheneObject): meta = kwargs["json_metadata"] super(Account_create_with_delegation, self).__init__(OrderedDict([ - ('fee', Amount(kwargs["fee"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), - ('delegation', Amount(kwargs["delegation"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), + ('fee', Amount(kwargs["fee"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), + ('delegation', Amount(kwargs["delegation"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), ('creator', String(kwargs["creator"])), ('new_account_name', String(kwargs["new_account_name"])), ('owner', Permission(kwargs["owner"], prefix=prefix)), @@ -342,6 +346,7 @@ class Create_proposal(GrapheneObject): kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) replace_hive_by_steem = kwargs.get("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) extensions = Array([]) super(Create_proposal, self).__init__( @@ -350,7 +355,7 @@ class Create_proposal(GrapheneObject): ('receiver', String(kwargs["receiver"])), ('start_date', PointInTime(kwargs["start_date"])), ('end_date', PointInTime(kwargs["end_date"])), - ('daily_pay', Amount(kwargs["daily_pay"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), + ('daily_pay', Amount(kwargs["daily_pay"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), ('subject', String(kwargs["subject"])), ('permlink', String(kwargs["permlink"])), ('extensions', extensions) @@ -424,6 +429,7 @@ class Witness_set_properties(GrapheneObject): kwargs = args[0] prefix = kwargs.pop("prefix", default_prefix) replace_hive_by_steem = kwargs.get("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) extensions = Array([]) props = {} for k in kwargs["props"]: @@ -449,9 +455,9 @@ class Witness_set_properties(GrapheneObject): elif isinstance(k[1], int) and k[0] in ["hbd_interest_rate"]: props[k[0]] = (hexlify(Uint16(k[1]).__bytes__())).decode() elif not isinstance(k[1], str) and k[0] in ["account_creation_fee"]: - props[k[0]] = (hexlify(Amount(k[1], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem).__bytes__())).decode() + props[k[0]] = (hexlify(Amount(k[1], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str).__bytes__())).decode() elif not is_hex and isinstance(k[1], str) and k[0] in ["account_creation_fee"]: - props[k[0]] = (hexlify(Amount(k[1], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem).__bytes__())).decode() + props[k[0]] = (hexlify(Amount(k[1], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str).__bytes__())).decode() elif not isinstance(k[1], str) and k[0] in ["sbd_exchange_rate"]: if 'prefix' not in k[1]: k[1]['prefix'] = prefix @@ -493,6 +499,7 @@ class Witness_update(GrapheneObject): kwargs = args[0] prefix = kwargs.pop("prefix", default_prefix) replace_hive_by_steem = kwargs.pop("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) if "block_signing_key" in kwargs and kwargs["block_signing_key"]: block_signing_key = (PublicKey(kwargs["block_signing_key"], prefix=prefix)) else: @@ -508,7 +515,7 @@ class Witness_update(GrapheneObject): ('url', String(kwargs["url"])), ('block_signing_key', block_signing_key), ('props', WitnessProps(kwargs["props"])), - ('fee', Amount(kwargs["fee"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), + ('fee', Amount(kwargs["fee"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), ])) @@ -573,6 +580,7 @@ class Comment_options(GrapheneObject): kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) replace_hive_by_steem = kwargs.get("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) # handle beneficiaries if "beneficiaries" in kwargs and kwargs['beneficiaries']: kwargs['extensions'] = [[0, {'beneficiaries': kwargs['beneficiaries']}]] @@ -585,7 +593,7 @@ class Comment_options(GrapheneObject): ('author', String(kwargs["author"])), ('permlink', String(kwargs["permlink"])), ('max_accepted_payout', - Amount(kwargs["max_accepted_payout"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), + Amount(kwargs["max_accepted_payout"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), ('percent_steem_dollars', Uint16(int(kwargs["percent_steem_dollars"]))), ('allow_votes', Bool(bool(kwargs["allow_votes"]))), @@ -630,6 +638,7 @@ class Feed_publish(GrapheneObject): kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) replace_hive_by_steem = kwargs.get("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) if 'prefix' not in kwargs['exchange_rate']: kwargs['exchange_rate']['prefix'] = prefix if 'replace_hive_by_steem' not in kwargs['exchange_rate']: @@ -649,11 +658,12 @@ class Convert(GrapheneObject): kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) replace_hive_by_steem = kwargs.get("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) super(Convert, self).__init__( OrderedDict([ ('owner', String(kwargs["owner"])), ('requestid', Uint32(kwargs["requestid"])), - ('amount', Amount(kwargs["amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), + ('amount', Amount(kwargs["amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), ])) @@ -693,10 +703,11 @@ class Claim_account(GrapheneObject): kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) replace_hive_by_steem = kwargs.get("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) super(Claim_account, self).__init__( OrderedDict([ ('creator', String(kwargs["creator"])), - ('fee', Amount(kwargs["fee"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), + ('fee', Amount(kwargs["fee"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), ('extensions', Array([])), ])) @@ -755,12 +766,13 @@ class Limit_order_create(GrapheneObject): kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) replace_hive_by_steem = kwargs.get("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) super(Limit_order_create, self).__init__( OrderedDict([ ('owner', String(kwargs["owner"])), ('orderid', Uint32(kwargs["orderid"])), - ('amount_to_sell', Amount(kwargs["amount_to_sell"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), - ('min_to_receive', Amount(kwargs["min_to_receive"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), + ('amount_to_sell', Amount(kwargs["amount_to_sell"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), + ('min_to_receive', Amount(kwargs["min_to_receive"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), ('fill_or_kill', Bool(kwargs["fill_or_kill"])), ('expiration', PointInTime(kwargs["expiration"])), ])) @@ -774,6 +786,7 @@ class Limit_order_create2(GrapheneObject): kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) replace_hive_by_steem = kwargs.get("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) if 'prefix' not in kwargs['exchange_rate']: kwargs['exchange_rate']['prefix'] = prefix if 'replace_hive_by_steem' not in kwargs['exchange_rate']: @@ -782,7 +795,7 @@ class Limit_order_create2(GrapheneObject): OrderedDict([ ('owner', String(kwargs["owner"])), ('orderid', Uint32(kwargs["orderid"])), - ('amount_to_sell', Amount(kwargs["amount_to_sell"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), + ('amount_to_sell', Amount(kwargs["amount_to_sell"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), ('fill_or_kill', Bool(kwargs["fill_or_kill"])), ('exchange_rate', ExchangeRate(kwargs["exchange_rate"])), ('expiration', PointInTime(kwargs["expiration"])), @@ -811,6 +824,7 @@ class Transfer_from_savings(GrapheneObject): kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) replace_hive_by_steem = kwargs.get("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) if "memo" not in kwargs: kwargs["memo"] = "" @@ -819,7 +833,7 @@ class Transfer_from_savings(GrapheneObject): ('from', String(kwargs["from"])), ('request_id', Uint32(kwargs["request_id"])), ('to', String(kwargs["to"])), - ('amount', Amount(kwargs["amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), + ('amount', Amount(kwargs["amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), ('memo', String(kwargs["memo"])), ])) @@ -845,12 +859,13 @@ class Claim_reward_balance(GrapheneObject): kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) replace_hive_by_steem = kwargs.get("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) if "reward_sbd" in kwargs and "reward_steem" in kwargs: super(Claim_reward_balance, self).__init__( OrderedDict([ ('account', String(kwargs["account"])), - ('reward_steem', Amount(kwargs["reward_steem"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), - ('reward_sbd', Amount(kwargs["reward_sbd"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), + ('reward_steem', Amount(kwargs["reward_steem"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), + ('reward_sbd', Amount(kwargs["reward_sbd"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), ('reward_vests', Amount(kwargs["reward_vests"], prefix=prefix)), ])) elif "reward_hbd" in kwargs and "reward_hive" in kwargs: @@ -865,7 +880,7 @@ class Claim_reward_balance(GrapheneObject): super(Claim_reward_balance, self).__init__( OrderedDict([ ('account', String(kwargs["account"])), - ('reward_steem', Amount(kwargs["reward_steem"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), + ('reward_steem', Amount(kwargs["reward_steem"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), ('reward_vests', Amount(kwargs["reward_vests"], prefix=prefix)), ])) else: @@ -885,13 +900,14 @@ class Transfer_to_savings(GrapheneObject): kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) replace_hive_by_steem = kwargs.get("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) if "memo" not in kwargs: kwargs["memo"] = "" super(Transfer_to_savings, self).__init__( OrderedDict([ ('from', String(kwargs["from"])), ('to', String(kwargs["to"])), - ('amount', Amount(kwargs["amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), + ('amount', Amount(kwargs["amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), ('memo', String(kwargs["memo"])), ])) @@ -939,6 +955,7 @@ class Escrow_transfer(GrapheneObject): kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) replace_hive_by_steem = kwargs.get("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) meta = "" if "json_meta" in kwargs and kwargs["json_meta"]: if (isinstance(kwargs["json_meta"], dict) or isinstance(kwargs["json_meta"], list)): @@ -952,9 +969,9 @@ class Escrow_transfer(GrapheneObject): ('to', String(kwargs["to"])), ('agent', String(kwargs["agent"])), ('escrow_id', Uint32(kwargs["escrow_id"])), - ('sbd_amount', Amount(kwargs["sbd_amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), - ('steem_amount', Amount(kwargs["steem_amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), - ('fee', Amount(kwargs["fee"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), + ('sbd_amount', Amount(kwargs["sbd_amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), + ('steem_amount', Amount(kwargs["steem_amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), + ('fee', Amount(kwargs["fee"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), ('ratification_deadline', PointInTime(kwargs["ratification_deadline"])), ('escrow_expiration', PointInTime(kwargs["escrow_expiration"])), ('json_meta', String(meta)), @@ -998,6 +1015,7 @@ class Escrow_release(GrapheneObject): kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) replace_hive_by_steem = kwargs.get("replace_hive_by_steem", True) + json_str = kwargs.get("json_str", False) if "steem_amount" in kwargs and "sbd_amount" in kwargs: super(Escrow_release, self).__init__( OrderedDict([ @@ -1005,8 +1023,8 @@ class Escrow_release(GrapheneObject): ('to', String(kwargs["to"])), ('who', String(kwargs["who"])), ('escrow_id', Uint32(kwargs["escrow_id"])), - ('sbd_amount', Amount(kwargs["sbd_amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), - ('steem_amount', Amount(kwargs["steem_amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem)), + ('sbd_amount', Amount(kwargs["sbd_amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), + ('steem_amount', Amount(kwargs["steem_amount"], prefix=prefix, replace_hive_by_steem=replace_hive_by_steem, json_str=json_str)), ])) else: super(Escrow_release, self).__init__( diff --git a/tests/beem/test_amount.py b/tests/beem/test_amount.py index 233d0814..a64d8687 100644 --- a/tests/beem/test_amount.py +++ b/tests/beem/test_amount.py @@ -78,7 +78,7 @@ class Testcases(unittest.TestCase): self.dotest(amount, 1.3001, symbol) amount = Amount(amount=1.3001, asset=Asset("SBD", steem_instance=stm), fixed_point_arithmetic=True, steem_instance=stm) - self.dotest(amount, 1.3, symbol) + self.dotest(amount, 1.3, symbol) # keyword inits amount = Amount(amount=1.3, asset=dict(Asset("SBD", steem_instance=stm)), steem_instance=stm) diff --git a/tests/beem/test_hive.py b/tests/beem/test_hive.py index 35922886..79521d86 100644 --- a/tests/beem/test_hive.py +++ b/tests/beem/test_hive.py @@ -10,7 +10,7 @@ from parameterized import parameterized import random import json from pprint import pprint -from beem import Hive, exceptions +from beem import Hive, exceptions, Steem from beem.amount import Amount from beem.version import version as beem_version from beem.account import Account @@ -45,12 +45,20 @@ class Testcases(unittest.TestCase): acc.blockchain.txbuffer.clear() tx = acc.transfer( "test", 1.33, acc.blockchain.backed_token_symbol, memo="Foobar", account="test1") - self.assertEqual( - tx["operations"][0][0], - "transfer" - ) self.assertEqual(len(tx["operations"]), 1) - op = tx["operations"][0][1] + if isinstance(tx["operations"][0], list): + self.assertEqual( + tx["operations"][0][0], + "transfer" + ) + op = tx["operations"][0][1] + else: + self.assertEqual( + tx["operations"][0]["type"], + "transfer_operation" + ) + + op = tx["operations"][0]["value"] self.assertIn("memo", op) self.assertEqual(op["memo"], "Foobar") self.assertEqual(op["from"], "test1") @@ -88,11 +96,18 @@ class Testcases(unittest.TestCase): additional_posting_accounts=["test3"], storekeys=False, ) - self.assertEqual( - tx["operations"][0][0], - "account_create" - ) - op = tx["operations"][0][1] + if isinstance(tx["operations"][0], list): + self.assertEqual( + tx["operations"][0][0], + "account_create" + ) + op = tx["operations"][0][1] + else: + self.assertEqual( + tx["operations"][0]["type"], + "account_create_operation" + ) + op = tx["operations"][0]["value"] role = "active" self.assertIn( format(key5.pubkey, core_unit), @@ -149,11 +164,18 @@ class Testcases(unittest.TestCase): additional_active_accounts=["test1"], storekeys=False, ) - self.assertEqual( - tx["operations"][0][0], - "account_create" - ) - op = tx["operations"][0][1] + if isinstance(tx["operations"][0], list): + self.assertEqual( + tx["operations"][0][0], + "account_create" + ) + op = tx["operations"][0][1] + else: + self.assertEqual( + tx["operations"][0]["type"], + "account_create_operation" + ) + op = tx["operations"][0]["value"] role = "active" self.assertIn( format(key5.pubkey, core_unit), @@ -247,11 +269,19 @@ class Testcases(unittest.TestCase): threshold=1, permission="owner", ) - self.assertEqual( - (tx["operations"][0][0]), - "account_update" - ) - op = tx["operations"][0][1] + if isinstance(tx["operations"][0], list): + + self.assertEqual( + (tx["operations"][0][0]), + "account_update" + ) + op = tx["operations"][0][1] + else: + self.assertEqual( + (tx["operations"][0]["type"]), + "account_update_operation" + ) + op = tx["operations"][0]["value"] self.assertIn("owner", op) self.assertIn( [wif, '1'], @@ -288,11 +318,19 @@ class Testcases(unittest.TestCase): self.assertEqual(acc.blockchain.prefix, prefix) acc.blockchain.txbuffer.clear() tx = acc.update_memo_key(pkey) - self.assertEqual( - (tx["operations"][0][0]), - "account_update" - ) - op = tx["operations"][0][1] + if isinstance(tx["operations"][0], list): + self.assertEqual( + (tx["operations"][0][0]), + "account_update" + ) + op = tx["operations"][0][1] + else: + self.assertEqual( + (tx["operations"][0]["type"]), + "account_update_operation" + ) + op = tx["operations"][0]["value"] + self.assertEqual( op["memo_key"], pkey) @@ -301,11 +339,18 @@ class Testcases(unittest.TestCase): w = self.account w.blockchain.txbuffer.clear() tx = w.approvewitness("test1") - self.assertEqual( - (tx["operations"][0][0]), - "account_witness_vote" - ) - op = tx["operations"][0][1] + if isinstance(tx["operations"][0], list): + self.assertEqual( + (tx["operations"][0][0]), + "account_witness_vote" + ) + op = tx["operations"][0][1] + else: + self.assertEqual( + (tx["operations"][0]["type"]), + "account_witness_vote_operation" + ) + op = tx["operations"][0]["value"] self.assertIn( "test1", op["witness"]) @@ -316,11 +361,18 @@ class Testcases(unittest.TestCase): tx = bts.post("title", "body", author="test", permlink=None, reply_identifier=None, json_metadata=None, comment_options=None, community="test", tags=["a", "b", "c", "d", "e"], beneficiaries=[{'account': 'test1', 'weight': 5000}, {'account': 'test2', 'weight': 5000}], self_vote=True) - self.assertEqual( - (tx["operations"][0][0]), - "comment" - ) - op = tx["operations"][0][1] + if isinstance(tx["operations"][0], list): + self.assertEqual( + (tx["operations"][0][0]), + "comment" + ) + op = tx["operations"][0][1] + else: + self.assertEqual( + (tx["operations"][0]["type"]), + "comment_operation" + ) + op = tx["operations"][0]["value"] self.assertEqual(op["body"], "body") self.assertEqual(op["title"], "title") self.assertTrue(op["permlink"].startswith("title")) @@ -329,22 +381,38 @@ class Testcases(unittest.TestCase): json_metadata = json.loads(op["json_metadata"]) self.assertEqual(json_metadata["tags"], ["a", "b", "c", "d", "e"]) self.assertEqual(json_metadata["app"], "beem/%s" % (beem_version)) - self.assertEqual( - (tx["operations"][1][0]), - "comment_options" - ) - op = tx["operations"][1][1] + if isinstance(tx["operations"][1], list): + self.assertEqual( + (tx["operations"][1][0]), + "comment_options" + ) + op = tx["operations"][1][1] + else: + + self.assertEqual( + (tx["operations"][1]["type"]), + "comment_options_operation" + ) + op = tx["operations"][1]["value"] self.assertEqual(len(op['extensions'][0][1]['beneficiaries']), 2) def test_comment_option(self): bts = self.bts bts.txbuffer.clear() tx = bts.comment_options({}, "@gtg/witness-gtg-log", account="test") - self.assertEqual( - (tx["operations"][0][0]), - "comment_options" - ) - op = tx["operations"][0][1] + if isinstance(tx["operations"][0], list): + self.assertEqual( + (tx["operations"][0][0]), + "comment_options" + ) + op = tx["operations"][0][1] + else: + self.assertEqual( + (tx["operations"][0]["type"]), + "comment_options_operation" + ) + op = tx["operations"][0]["value"] + self.assertIn( "gtg", op["author"]) @@ -466,3 +534,14 @@ class Testcases(unittest.TestCase): assert not bts.is_hive bts.switch_blockchain("hive", update_nodes=True) assert bts.is_hive + + def test_switch_blockchain(self): + bts = self.bts + nodes_hive = self.nodelist.get_hive_nodes() + nodes_steem = self.nodelist.get_steem_nodes() + rpc = Steem(nodes_steem) + assert rpc.is_steem + assert not rpc.get_replace_hive_by_steem() + rpc = Hive(nodes_hive) + assert rpc.is_hive + assert rpc.get_replace_hive_by_steem() diff --git a/tests/beem/test_steem.py b/tests/beem/test_steem.py index 8a730260..b563ea59 100644 --- a/tests/beem/test_steem.py +++ b/tests/beem/test_steem.py @@ -44,12 +44,21 @@ class Testcases(unittest.TestCase): acc.blockchain.txbuffer.clear() tx = acc.transfer( "test", 1.33, acc.blockchain.sbd_symbol, memo="Foobar", account="test1") - self.assertEqual( - tx["operations"][0][0], - "transfer" - ) self.assertEqual(len(tx["operations"]), 1) - op = tx["operations"][0][1] + if isinstance(tx["operations"][0], list): + self.assertEqual( + tx["operations"][0][0], + "transfer" + ) + + op = tx["operations"][0][1] + else: + self.assertEqual( + tx["operations"][0]["type"], + "transfer_operation" + ) + + op = tx["operations"][0]["value"] self.assertIn("memo", op) self.assertEqual(op["memo"], "Foobar") self.assertEqual(op["from"], "test1") @@ -87,11 +96,18 @@ class Testcases(unittest.TestCase): additional_posting_accounts=["test3"], storekeys=False, ) - self.assertEqual( - tx["operations"][0][0], - "account_create" - ) - op = tx["operations"][0][1] + if isinstance(tx["operations"][0], list): + self.assertEqual( + tx["operations"][0][0], + "account_create" + ) + op = tx["operations"][0][1] + else: + self.assertEqual( + tx["operations"][0]["type"], + "account_create_operation" + ) + op = tx["operations"][0]["value"] role = "active" self.assertIn( format(key5.pubkey, core_unit), @@ -148,11 +164,18 @@ class Testcases(unittest.TestCase): additional_active_accounts=["test1"], storekeys=False, ) - self.assertEqual( - tx["operations"][0][0], - "account_create" - ) - op = tx["operations"][0][1] + if isinstance(tx["operations"][0], list): + self.assertEqual( + tx["operations"][0][0], + "account_create" + ) + op = tx["operations"][0][1] + else: + self.assertEqual( + tx["operations"][0]["type"], + "account_create_operation" + ) + op = tx["operations"][0]["value"] role = "active" self.assertIn( format(key5.pubkey, core_unit), @@ -246,11 +269,18 @@ class Testcases(unittest.TestCase): threshold=1, permission="owner", ) - self.assertEqual( - (tx["operations"][0][0]), - "account_update" - ) - op = tx["operations"][0][1] + if isinstance(tx["operations"][0], list): + self.assertEqual( + (tx["operations"][0][0]), + "account_update" + ) + op = tx["operations"][0][1] + else: + self.assertEqual( + (tx["operations"][0]["type"]), + "account_update_operation" + ) + op = tx["operations"][0]["value"] self.assertIn("owner", op) self.assertIn( [wif, '1'], @@ -287,11 +317,18 @@ class Testcases(unittest.TestCase): self.assertEqual(acc.blockchain.prefix, prefix) acc.blockchain.txbuffer.clear() tx = acc.update_memo_key(pkey) - self.assertEqual( - (tx["operations"][0][0]), - "account_update" - ) - op = tx["operations"][0][1] + if isinstance(tx["operations"][0], list): + self.assertEqual( + (tx["operations"][0][0]), + "account_update" + ) + op = tx["operations"][0][1] + else: + self.assertEqual( + (tx["operations"][0]["type"]), + "account_update_operation" + ) + op = tx["operations"][0]["value"] self.assertEqual( op["memo_key"], pkey) @@ -300,11 +337,18 @@ class Testcases(unittest.TestCase): w = self.account w.blockchain.txbuffer.clear() tx = w.approvewitness("test1") - self.assertEqual( - (tx["operations"][0][0]), - "account_witness_vote" - ) - op = tx["operations"][0][1] + if isinstance(tx["operations"][0], list): + self.assertEqual( + (tx["operations"][0][0]), + "account_witness_vote" + ) + op = tx["operations"][0][1] + else: + self.assertEqual( + (tx["operations"][0]["type"]), + "account_witness_vote_operation" + ) + op = tx["operations"][0]["value"] self.assertIn( "test1", op["witness"]) @@ -315,11 +359,18 @@ class Testcases(unittest.TestCase): tx = bts.post("title", "body", author="test", permlink=None, reply_identifier=None, json_metadata=None, comment_options=None, community="test", tags=["a", "b", "c", "d", "e"], beneficiaries=[{'account': 'test1', 'weight': 5000}, {'account': 'test2', 'weight': 5000}], self_vote=True) - self.assertEqual( - (tx["operations"][0][0]), - "comment" - ) - op = tx["operations"][0][1] + if isinstance(tx["operations"][0], list): + self.assertEqual( + (tx["operations"][0][0]), + "comment" + ) + op = tx["operations"][0][1] + else: + self.assertEqual( + (tx["operations"][0]["type"]), + "comment_operation" + ) + op = tx["operations"][0]["value"] self.assertEqual(op["body"], "body") self.assertEqual(op["title"], "title") self.assertTrue(op["permlink"].startswith("title")) @@ -328,22 +379,36 @@ class Testcases(unittest.TestCase): json_metadata = json.loads(op["json_metadata"]) self.assertEqual(json_metadata["tags"], ["a", "b", "c", "d", "e"]) self.assertEqual(json_metadata["app"], "beem/%s" % (beem_version)) - self.assertEqual( - (tx["operations"][1][0]), - "comment_options" - ) - op = tx["operations"][1][1] + if isinstance(tx["operations"][1], list): + self.assertEqual( + (tx["operations"][1][0]), + "comment_options" + ) + op = tx["operations"][1][1] + else: + self.assertEqual( + (tx["operations"][1]["type"]), + "comment_options_operation" + ) + op = tx["operations"][1]["value"] self.assertEqual(len(op['extensions'][0][1]['beneficiaries']), 2) def test_comment_option(self): bts = self.bts bts.txbuffer.clear() tx = bts.comment_options({}, "@gtg/witness-gtg-log", account="test") - self.assertEqual( - (tx["operations"][0][0]), - "comment_options" - ) - op = tx["operations"][0][1] + if isinstance(tx["operations"][0], list): + self.assertEqual( + (tx["operations"][0][0]), + "comment_options" + ) + op = tx["operations"][0][1] + else: + self.assertEqual( + (tx["operations"][0]["type"]), + "comment_options_operation" + ) + op = tx["operations"][0]["value"] self.assertIn( "gtg", op["author"]) diff --git a/tests/beembase/test_objects.py b/tests/beembase/test_objects.py index 30776289..de11091a 100644 --- a/tests/beembase/test_objects.py +++ b/tests/beembase/test_objects.py @@ -25,11 +25,26 @@ class Testcases(unittest.TestCase): self.assertEqual(a, t.__str__()) self.assertEqual(a, str(t)) + t = Amount(a, json_str=True, prefix="STM") + self.assertEqual({"amount": "1000", "precision": 3, "nai": "@@000000021"}, json.loads(str(t))) + a = {"amount": "3000", "precision": 3, "nai": "@@000000037"} t = Amount(a, prefix="STM") # self.assertEqual(str(a), t.__str__()) self.assertEqual(a, json.loads(str(t))) + + + def test_Amount_overflow(self): + a = "0.9999 STEEM" + t = Amount(a) + self.assertEqual("0.999 STEEM", t.__str__()) + self.assertEqual("0.999 STEEM", str(t)) + a = "0.9991 STEEM" + t = Amount(a) + self.assertEqual("0.999 STEEM", t.__str__()) + self.assertEqual("0.999 STEEM", str(t)) + def test_Operation(self): a = {"amount": '1000', "precision": 3, "nai": '@@000000013'} j = ["transfer", {'from': 'a', 'to': 'b', 'amount': a, 'memo': 'c'}] -- GitLab