From 433451f1706d4460acf890620f53c72f336a25a1 Mon Sep 17 00:00:00 2001
From: Holger <holger@nahrstaedt.de>
Date: Fri, 5 Oct 2018 00:39:07 +0200
Subject: [PATCH] prepare next release

* add claim_account RC calculation
* fix Bytes type
* Improve testnet example
* test_types improved
---
 beem/cli.py                         |   2 +-
 beem/nodelist.py                    |  16 ++-
 beem/rc.py                          |   5 +
 beem/version.py                     |   2 +-
 beemapi/version.py                  |   2 +-
 beembase/version.py                 |   2 +-
 beemgraphenebase/types.py           |  12 +-
 beemgraphenebase/version.py         |   2 +-
 examples/op_on_testnet.py           |  13 ++-
 setup.py                            |   2 +-
 tests/beembase/test_objects.py      |   6 +-
 tests/beembase/test_operations.py   |   2 +-
 tests/beembase/test_transactions.py |  28 ++---
 tests/beemgraphene/test_types.py    | 165 ++++++++++++++++++++++++++--
 14 files changed, 208 insertions(+), 51 deletions(-)

diff --git a/beem/cli.py b/beem/cli.py
index eaaae6d0..d390136c 100644
--- a/beem/cli.py
+++ b/beem/cli.py
@@ -2012,7 +2012,7 @@ def witnesscreate(witness, pub_signing_key, maximum_block_size, account_creation
 @click.option('--new_signing_key', help='Set new signing key')
 @click.option('--url', help='Witness URL')
 def witnessproperties(witness, wif, account_creation_fee, account_subsidy_budget, account_subsidy_decay, maximum_block_size, sbd_interest_rate, new_signing_key, url):
-    """Update witness properties without pricefeed"""
+    """Update witness properties of witness WITNESS with the witness signing key WIF"""
     stm = shared_steem_instance()
     if stm.rpc is not None:
         stm.rpc.rpcconnect()
diff --git a/beem/nodelist.py b/beem/nodelist.py
index a739fbd5..f0a82927 100644
--- a/beem/nodelist.py
+++ b/beem/nodelist.py
@@ -273,8 +273,20 @@ class NodeList(list):
                 nl.update_nodes(weights)
         """
         steem = steem_instance or shared_steem_instance()
-        account = Account("fullnodeupdate", steem_instance=steem)
-        metadata = json.loads(account["json_metadata"])
+        metadata = None
+        account = None
+        cnt = 0
+        while metadata is None and cnt < 5:
+            cnt += 1
+            try:
+                account = Account("fullnodeupdate", steem_instance=steem)
+                metadata = json.loads(account["json_metadata"])
+            except:
+                steem.rpc.next()
+                account = None
+                metadata = None
+        if metadata is None:
+            return
         report = metadata["report"]
         failing_nodes = metadata["failing_nodes"]
         parameter = metadata["parameter"]
diff --git a/beem/rc.py b/beem/rc.py
index 3cdd8b3a..6c903474 100644
--- a/beem/rc.py
+++ b/beem/rc.py
@@ -180,3 +180,8 @@ class RC(object):
         tx_size = self.get_tx_size(op)
         resource_count = self.get_resource_count(tx_size)
         return self.steem.get_rc_cost(resource_count)
+
+    def claim_account(self, tx_size=300):
+        """Claim account"""
+        resource_count = self.get_resource_count(tx_size, new_account_op_count=1)
+        return self.steem.get_rc_cost(resource_count)
diff --git a/beem/version.py b/beem/version.py
index 60b46443..e857757f 100644
--- a/beem/version.py
+++ b/beem/version.py
@@ -1,2 +1,2 @@
 """THIS FILE IS GENERATED FROM beem SETUP.PY."""
-version = '0.20.5'
+version = '0.20.6'
diff --git a/beemapi/version.py b/beemapi/version.py
index 60b46443..e857757f 100644
--- a/beemapi/version.py
+++ b/beemapi/version.py
@@ -1,2 +1,2 @@
 """THIS FILE IS GENERATED FROM beem SETUP.PY."""
-version = '0.20.5'
+version = '0.20.6'
diff --git a/beembase/version.py b/beembase/version.py
index 60b46443..e857757f 100644
--- a/beembase/version.py
+++ b/beembase/version.py
@@ -1,2 +1,2 @@
 """THIS FILE IS GENERATED FROM beem SETUP.PY."""
-version = '0.20.5'
+version = '0.20.6'
diff --git a/beemgraphenebase/types.py b/beemgraphenebase/types.py
index 56171768..ca9c822c 100644
--- a/beemgraphenebase/types.py
+++ b/beemgraphenebase/types.py
@@ -39,8 +39,7 @@ def varintdecode(data):
     """Varint decoding."""
     shift = 0
     result = 0
-    for c in data:
-        b = ord(c)
+    for b in bytes(data):
         result |= ((b & 0x7f) << shift)
         if not (b & 0x80):
             break
@@ -216,18 +215,13 @@ class String(object):
 
 @python_2_unicode_compatible
 class Bytes(object):
-    def __init__(self, d, length=None):
+    def __init__(self, d):
         self.data = d
-        if length:
-            self.length = length
-        else:
-            self.length = len(self.data)
 
     def __bytes__(self):
         """Returns data as bytes."""
-        # FIXME constraint data to self.length
         d = unhexlify(bytes(self.data, 'utf-8'))
-        return varint(len(self.data)) + d
+        return varint(len(d)) + d
 
     def __str__(self):
         """Returns data as string."""
diff --git a/beemgraphenebase/version.py b/beemgraphenebase/version.py
index 60b46443..e857757f 100644
--- a/beemgraphenebase/version.py
+++ b/beemgraphenebase/version.py
@@ -1,2 +1,2 @@
 """THIS FILE IS GENERATED FROM beem SETUP.PY."""
-version = '0.20.5'
+version = '0.20.6'
diff --git a/examples/op_on_testnet.py b/examples/op_on_testnet.py
index 22752ec9..7e170c91 100644
--- a/examples/op_on_testnet.py
+++ b/examples/op_on_testnet.py
@@ -23,16 +23,17 @@ logging.basicConfig(level=logging.INFO)
 password = "secretPassword"
 username = "beem"
 useWallet = False
+walletpassword = "123"
 
 if __name__ == "__main__":
-    nodelist = NodeList()
-    stm = Steem(node=nodelist.get_nodes(normal=False, appbase=False, testnet=True))
+    testnet_node = "https://testnet.steem.vc"
+    stm = Steem(node=testnet_node)
     prefix = stm.prefix
     # curl --data "username=username&password=secretPassword" https://testnet.steem.vc/create
-    stm.wallet.wipe(True)
     if useWallet:
-        stm.wallet.create("123")
-        stm.wallet.unlock("123")
+        stm.wallet.wipe(True)
+        stm.wallet.create(walletpassword)
+        stm.wallet.unlock(walletpassword)
     active_key = PasswordKey(username, password, role="active", prefix=prefix)
     owner_key = PasswordKey(username, password, role="owner", prefix=prefix)
     posting_key = PasswordKey(username, password, role="posting", prefix=prefix)
@@ -51,7 +52,7 @@ if __name__ == "__main__":
         stm.wallet.addPrivateKey(memo_privkey)
         stm.wallet.addPrivateKey(posting_privkey)
     else:
-        stm = Steem(node=nodelist.get_nodes(normal=False, appbase=False, testnet=True),
+        stm = Steem(node=testnet_node,
                     wif={'active': str(active_privkey),
                          'posting': str(posting_privkey),
                          'memo': str(memo_privkey)})
diff --git a/setup.py b/setup.py
index a0cbb357..244c7332 100755
--- a/setup.py
+++ b/setup.py
@@ -16,7 +16,7 @@ except LookupError:
     ascii = codecs.lookup('ascii')
     codecs.register(lambda name, enc=ascii: {True: enc}.get(name == 'mbcs'))
 
-VERSION = '0.20.5'
+VERSION = '0.20.6'
 
 tests_require = ['mock >= 2.0.0', 'pytest', 'pytest-mock', 'parameterized']
 
diff --git a/tests/beembase/test_objects.py b/tests/beembase/test_objects.py
index 463631b5..30776289 100644
--- a/tests/beembase/test_objects.py
+++ b/tests/beembase/test_objects.py
@@ -25,13 +25,13 @@ class Testcases(unittest.TestCase):
         self.assertEqual(a, t.__str__())
         self.assertEqual(a, str(t))
 
-        a = ["3000", 3, "@@00000032"]
-        t = Amount(a)
+        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_Operation(self):
-        a = ['1000', 3, '@@000000013']
+        a = {"amount": '1000', "precision": 3, "nai": '@@000000013'}
         j = ["transfer", {'from': 'a', 'to': 'b', 'amount': a, 'memo': 'c'}]
         o = Operation(j)
         self.assertEqual(o.json()[1], j[1])
diff --git a/tests/beembase/test_operations.py b/tests/beembase/test_operations.py
index 8466c8ce..21e55b09 100644
--- a/tests/beembase/test_operations.py
+++ b/tests/beembase/test_operations.py
@@ -30,7 +30,7 @@ class Testcases(unittest.TestCase):
         self.assertEqual(transferJson, t.toJson())
         self.assertEqual(transferJson, t.__json__())
 
-        transferJson = {'from': 'test', 'to': 'test1', 'amount': ['3000', 3, '@@00000032'], 'memo': 'foobar'}
+        transferJson = {'from': 'test', 'to': 'test1', 'amount': ['3000', 3, '@@000000037'], 'memo': 'foobar'}
         t = Transfer(transferJson)
         self.assertEqual(transferJson, json.loads(str(t)))
         self.assertEqual(transferJson, t.json())
diff --git a/tests/beembase/test_transactions.py b/tests/beembase/test_transactions.py
index 365a1bf1..c9b1d8f1 100644
--- a/tests/beembase/test_transactions.py
+++ b/tests/beembase/test_transactions.py
@@ -300,10 +300,10 @@ class Testcases(unittest.TestCase):
             **{
                 "owner": "alice",
                 "orderid": 492991,
-                "amount_to_sell": ["1", 3, "@@000000013"],
+                "amount_to_sell": {"amount": "1", "precision": 3, "nai": "@@000000013"},
                 "exchange_rate": {
-                    "base": ["1", 3, "@@000000013"],
-                    "quote": ["10", 3, "@@000000021"]
+                    "base": {"amount": "1", "precision": 3, "nai": "@@000000013"},
+                    "quote": {"amount": "10", "precision": 3, "nai": "@@000000021"}
                 },
                 "fill_or_kill": False,
                 "expiration": "2017-05-12T23:11:13",
@@ -878,11 +878,11 @@ class Testcases(unittest.TestCase):
             **{
                 "from": "alice",
                 "to": "bob",
-                "sbd_amount": ["1000", 3, "@@000000013"],
-                "steem_amount": ["0", 3, "@@000000021"],
+                "sbd_amount": {"amount": "1000", "precision": 3, "nai": "@@000000013"},
+                "steem_amount": {"amount": "0", "precision": 3, "nai": "@@000000021"},
                 "escrow_id": 23456789,
                 "agent": "charlie",
-                "fee": ["100", 3, "@@000000013"],
+                "fee": {"amount": "100", "precision": 3, "nai": "@@000000013"},
                 "json_meta": "{}",
                 "ratification_deadline": "2017-02-26T11:22:39",
                 "escrow_expiration": "2017-02-28T11:22:39",
@@ -920,8 +920,8 @@ class Testcases(unittest.TestCase):
                 "to": "bob",
                 "who": "charlie",
                 "escrow_id": 72526562,
-                "sbd_amount": ["5000", 3, "@@000000013"],
-                "steem_amount": ["0", 3, "@@000000021"],
+                "sbd_amount": {"amount": "5000", "precision": 3, "nai": "@@000000013"},
+                "steem_amount": {"amount": "0", "precision": 3, "nai": "@@000000021"},
                 "prefix": default_prefix,
             })
 
@@ -967,9 +967,9 @@ class Testcases(unittest.TestCase):
         self.op = operations.Claim_reward_balance(
             **{
                 "account": "alice",
-                "reward_steem": ["17", 3, "@@000000021"],
-                "reward_sbd": ["11", 3, "@@000000013"],
-                "reward_vests": ["185025103", 6, "@@000000037"],
+                "reward_steem": {"amount": "17", "precision": 3, "nai": "@@000000021"},
+                "reward_sbd": {"amount": "11", "precision": 3, "nai": "@@000000013"},
+                "reward_vests": {"amount": "185025103", "precision": 6, "nai": "@@000000037"},
                 "prefix": default_prefix,
             })
 
@@ -985,7 +985,7 @@ class Testcases(unittest.TestCase):
             **{
                 "delegator": "alice",
                 "delegatee": "bob",
-                "vesting_shares": ["94599167138276", 6, "@@000000037"],
+                "vesting_shares": {"amount": "94599167138276", "precision": 6, "nai": "@@000000037"},
                 "prefix": default_prefix,
             })
 
@@ -998,8 +998,8 @@ class Testcases(unittest.TestCase):
     def test_account_create_with_delegation(self):
         self.op = operations.Account_create_with_delegation(
             **{
-                "fee": ["3000", 3, "@@000000021"],
-                "delegation": ["0", 6, "@@000000037"],
+                "fee": {"amount": "3000", "precision": 3, "nai": "@@000000021"},
+                "delegation": {"amount": "0", "precision": 6, "nai": "@@000000037"},
                 "creator": "steemit",
                 "new_account_name": "alice",
                 "owner": {
diff --git a/tests/beemgraphene/test_types.py b/tests/beemgraphene/test_types.py
index 42ef5070..fb62efba 100644
--- a/tests/beemgraphene/test_types.py
+++ b/tests/beemgraphene/test_types.py
@@ -11,15 +11,160 @@ from beem import Steem
 
 
 class Testcases(unittest.TestCase):
-    def test_JsonObj(self):
-        j = {"a": 2, "b": "abcde", "c": ["a", "b"]}
-        j2 = types.JsonObj(json.dumps(j))
-        self.assertEqual(j, j2)
 
-        stm = Steem(
-            offline=True
+    def test_varint(self):
+        expected = [
+            None,
+            b'\x01', b'\x02', b'\x03', b'\x04', b'\x05', b'\x06', b'\x07',
+            b'\x08', b'\t', b'\n', b'\x0b', b'\x0c', b'\r', b'\x0e', b'\x0f',
+            b'\x10', b'\x11', b'\x12', b'\x13', b'\x14', b'\x15', b'\x16',
+            b'\x17', b'\x18', b'\x19', b'\x1a', b'\x1b', b'\x1c', b'\x1d',
+            b'\x1e', b'\x1f', b' ', b'!', b'"', b'#', b'$', b'%', b'&', b"'",
+            b'(', b')', b'*', b'+', b',', b'-', b'.', b'/', b'0', b'1', b'2',
+            b'3', b'4', b'5', b'6', b'7', b'8', b'9', b':', b';', b'<', b'=',
+            b'>', b'?', b'@', b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H',
+            b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P', b'Q', b'R', b'S',
+            b'T', b'U', b'V', b'W', b'X', b'Y', b'Z', b'[', b'\\', b']', b'^',
+            b'_', b'`', b'a', b'b', b'c', b'd', b'e', b'f', b'g', b'h', b'i',
+            b'j', b'k', b'l', b'm', b'n', b'o', b'p', b'q', b'r', b's', b't',
+            b'u', b'v', b'w', b'x', b'y', b'z', b'{', b'|', b'}', b'~',
+            b'\x7f', b'\x80\x01', b'\x81\x01', b'\x82\x01', b'\x83\x01',
+            b'\x84\x01', b'\x85\x01', b'\x86\x01', b'\x87\x01', b'\x88\x01',
+            b'\x89\x01', b'\x8a\x01', b'\x8b\x01', b'\x8c\x01', b'\x8d\x01',
+            b'\x8e\x01', b'\x8f\x01', b'\x90\x01', b'\x91\x01', b'\x92\x01',
+            b'\x93\x01', b'\x94\x01', b'\x95\x01', b'\x96\x01', b'\x97\x01',
+            b'\x98\x01', b'\x99\x01', b'\x9a\x01', b'\x9b\x01', b'\x9c\x01',
+            b'\x9d\x01', b'\x9e\x01', b'\x9f\x01', b'\xa0\x01', b'\xa1\x01',
+            b'\xa2\x01', b'\xa3\x01', b'\xa4\x01', b'\xa5\x01', b'\xa6\x01',
+            b'\xa7\x01', b'\xa8\x01', b'\xa9\x01', b'\xaa\x01', b'\xab\x01',
+            b'\xac\x01', b'\xad\x01', b'\xae\x01', b'\xaf\x01', b'\xb0\x01',
+            b'\xb1\x01', b'\xb2\x01', b'\xb3\x01', b'\xb4\x01', b'\xb5\x01',
+            b'\xb6\x01', b'\xb7\x01', b'\xb8\x01', b'\xb9\x01', b'\xba\x01',
+            b'\xbb\x01', b'\xbc\x01', b'\xbd\x01', b'\xbe\x01', b'\xbf\x01',
+            b'\xc0\x01', b'\xc1\x01', b'\xc2\x01', b'\xc3\x01', b'\xc4\x01',
+            b'\xc5\x01', b'\xc6\x01', b'\xc7\x01']
+        for i in range(1, 200):
+            self.assertEqual(types.varint(i), expected[i])
+            self.assertEqual(types.varintdecode(expected[i]), i)
+
+    def test_variable_buffer(self):
+        self.assertEqual(
+            types.variable_buffer(b"Hello"),
+            b"\x05Hello"
         )
-        a = Amount("1 SBD", steem_instance=stm)
-        j = a.json()
-        j2 = types.JsonObj(json.dumps(j))
-        self.assertEqual(j, j2)
+
+    def test_JsonObj(self):
+        j = types.JsonObj(json.dumps(dict(foo="bar")))
+        self.assertIn("foo", j)
+        self.assertEqual(j["foo"], "bar")
+
+    def test_uint8(self):
+        u = types.Uint8(10)
+        self.assertEqual(bytes(u), b"\n")
+        self.assertEqual(str(u), "10")
+
+    def test_uint16(self):
+        u = types.Uint16(2**16 - 1)
+        self.assertEqual(bytes(u), b"\xff\xff")
+        self.assertEqual(str(u), str(2**16 - 1))
+
+    def test_uint32(self):
+        u = types.Uint32(2**32 - 1)
+        self.assertEqual(bytes(u), b"\xff\xff\xff\xff")
+        self.assertEqual(str(u), str(2**32 - 1))
+
+    def test_uint64(self):
+        u = types.Uint64(2**64 - 1)
+        self.assertEqual(bytes(u), b"\xff\xff\xff\xff\xff\xff\xff\xff")
+        self.assertEqual(str(u), str(2**64 - 1))
+
+    def test_int64(self):
+        u = types.Int64(2**63 - 1)
+        self.assertEqual(bytes(u), b"\xff\xff\xff\xff\xff\xff\xff\x7f")
+        self.assertEqual(str(u), str(9223372036854775807))
+
+    def test_int16(self):
+        u = types.Int16(2**15 - 1)
+        self.assertEqual(bytes(u), b"\xff\x7f")
+        self.assertEqual(str(u), str(2**15 - 1))
+
+    def test_varint32(self):
+        u = types.Varint32(2**32 - 1)
+        self.assertEqual(bytes(u), b"\xff\xff\xff\xff\x0f")
+        self.assertEqual(str(u), str(4294967295))
+        u = types.Id(2**32 - 1)
+        self.assertEqual(bytes(u), b"\xff\xff\xff\xff\x0f")
+        self.assertEqual(str(u), str(4294967295))
+
+    def test_string(self):
+        u = types.String("HelloFoobar")
+        self.assertEqual(bytes(u), b"\x0bHelloFoobar")
+        self.assertEqual(str(u), "HelloFoobar")
+
+        u = types.String("\x07\x08\x09\x0a\x0b\x0c\x0d\x0e")
+        self.assertEqual(bytes(u), b"\x14u0007b\t\nu000bf\ru000e")
+        self.assertEqual(str(u), "\x07\x08\x09\x0a\x0b\x0c\x0d\x0e")
+
+    def test_void(self):
+        u = types.Void()
+        self.assertEqual(bytes(u), b"")
+        self.assertEqual(str(u), "")
+
+    def test_array(self):
+        u = types.Array([types.Uint8(10) for x in range(2)] + [11])
+        self.assertEqual(bytes(u), b'\x03\n\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+        self.assertEqual(str(u), "[10, 10, 11]")
+        u = types.Set([types.Uint16(10) for x in range(10)])
+        self.assertEqual(bytes(u), b"\n\n\x00\n\x00\n\x00\n\x00\n\x00\n\x00\n\x00\n\x00\n\x00\n\x00")
+        self.assertEqual(str(u), "[10, 10, 10, 10, 10, 10, 10, 10, 10, 10]")
+        u = types.Array(["Foobar"])
+        # We do not support bytes of Array containing String only!
+        # self.assertEqual(bytes(u), b'')
+        self.assertEqual(str(u), '["Foobar"]')
+
+    def test_PointInTime(self):
+        u = types.PointInTime("2018-07-06T22:10:00")
+        self.assertEqual(bytes(u), b"\xb8\xe8?[")
+        self.assertEqual(str(u), "2018-07-06T22:10:00")
+
+    def test_Signature(self):
+        u = types.Signature(b"\x00" * 33)
+        self.assertEqual(bytes(u), b"\x00" * 33)
+        self.assertEqual(str(u), '"000000000000000000000000000000000000000000000000000000000000000000"')
+
+    def test_Bytes(self):
+        u = types.Bytes("00" * 5)
+        self.assertEqual(bytes(u), b'\x05\x00\x00\x00\x00\x00')
+        self.assertEqual(str(u), "00" * 5)
+
+    def test_Bool(self):
+        u = types.Bool(True)
+        self.assertEqual(bytes(u), b"\x01")
+        self.assertEqual(str(u), 'true')
+        u = types.Bool(False)
+        self.assertEqual(bytes(u), b"\x00")
+        self.assertEqual(str(u), 'false')
+
+    def test_Optional(self):
+        u = types.Optional(types.Uint16(10))
+        self.assertEqual(bytes(u), b"\x01\n\x00")
+        self.assertEqual(str(u), '10')
+        self.assertFalse(u.isempty())
+        u = types.Optional(None)
+        self.assertEqual(bytes(u), b"\x00")
+        self.assertEqual(str(u), 'None')
+        self.assertTrue(u.isempty())
+
+    def test_Static_variant(self):
+        class Tmp(types.Uint16):
+            def json(self):
+                return "Foobar"
+
+        u = types.Static_variant(Tmp(10), 10)
+        self.assertEqual(bytes(u), b"\n\n\x00")
+        self.assertEqual(str(u), '[10, "Foobar"]')
+
+    def test_Map(self):
+        u = types.Map([[types.Uint16(10), types.Uint16(11)]])
+        self.assertEqual(bytes(u), b"\x01\n\x00\x0b\x00")
+        self.assertEqual(str(u), '[["10", "11"]]')
-- 
GitLab