From 1851516491a238c83818390cb460b941b77398f7 Mon Sep 17 00:00:00 2001
From: Holger Nahrstaedt <holgernahrstaedt@gmx.de>
Date: Sun, 7 Jun 2020 11:11:41 +0200
Subject: [PATCH] get_block_params added to TransactionBuilder

* add participation_rate to Blockchain
* beembase.transactions is deprecated
* get_block_params added to TransactionBuilder
---
 CHANGELOG.rst                            |  6 ++++++
 beem/blockchain.py                       |  5 +++++
 beem/transactionbuilder.py               | 27 ++++++++++++++++++++++--
 beembase/ledgertransactions.py           |  4 ++--
 beembase/transactions.py                 | 16 ++++----------
 beemgraphenebase/unsignedtransactions.py |  4 ++--
 examples/using_steem_offline.py          |  5 +++--
 7 files changed, 47 insertions(+), 20 deletions(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index a64c545b..74f8cd80 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,5 +1,11 @@
 Changelog
 =========
+0.23.12
+-------
+* add participation_rate to Blockchain
+* beembase.transactions is deprecated
+* get_block_params added to TransactionBuilder
+
 0.23.11
 -------
 * replace asn1 by asn1crypto
diff --git a/beem/blockchain.py b/beem/blockchain.py
index 21ca5e12..6e90f2ba 100644
--- a/beem/blockchain.py
+++ b/beem/blockchain.py
@@ -390,6 +390,11 @@ class Blockchain(object):
         ).time()
         return int(time.mktime(block_time.timetuple()))
 
+    @property
+    def participation_rate(self):
+        """ Returns the witness participation rate in a range from 0 to 1"""
+        return bin(int(self.blockchain.get_dynamic_global_properties(use_stored_data=False)["recent_slots_filled"])).count("1") / 128
+
     def blocks(self, start=None, stop=None, max_batch_size=None, threading=False, thread_num=8, only_ops=False, only_virtual_ops=False):
         """ Yields blocks starting from ``start``.
 
diff --git a/beem/transactionbuilder.py b/beem/transactionbuilder.py
index 2a91dd41..4ed74f79 100644
--- a/beem/transactionbuilder.py
+++ b/beem/transactionbuilder.py
@@ -6,6 +6,8 @@ from __future__ import unicode_literals
 from builtins import str
 from future.utils import python_2_unicode_compatible
 import logging
+import struct
+from binascii import unhexlify
 from beemgraphenebase.py23 import bytes_types, integer_types, string_types, text_type
 from .account import Account
 from .utils import formatTimeFromNow
@@ -314,8 +316,7 @@ class TransactionBuilder(dict):
             self.expiration or self.blockchain.expiration
         )
         if ref_block_num is None or ref_block_prefix is None:
-            ref_block_num, ref_block_prefix = transactions.getBlockParams(
-                self.blockchain.rpc)
+            ref_block_num, ref_block_prefix = self.get_block_params()
         if self._use_ledger:
             self.ledgertx = Ledger_Transaction(
                 ref_block_prefix=ref_block_prefix,
@@ -338,6 +339,28 @@ class TransactionBuilder(dict):
         super(TransactionBuilder, self).update(self.tx.json())
         self._unset_require_reconstruction()
 
+    def get_block_params(self, use_head_block=False):
+        """ Auxiliary method to obtain ``ref_block_num`` and
+            ``ref_block_prefix``. Requires a connection to a
+            node!
+        """
+
+        dynBCParams = self.blockchain.get_dynamic_global_properties(use_stored_data=False)
+        if use_head_block:
+            ref_block_num = dynBCParams["head_block_number"] & 0xFFFF
+            ref_block_prefix = struct.unpack_from(
+                "<I", unhexlify(dynBCParams["head_block_id"]), 4
+            )[0]
+        else:
+            # need to get subsequent block because block head doesn't return 'id' - stupid
+            from .block import BlockHeader
+            block = BlockHeader(int(dynBCParams["last_irreversible_block_num"]) + 1, blockchain_instance=self.blockchain)
+            ref_block_num = dynBCParams["last_irreversible_block_num"] & 0xFFFF
+            ref_block_prefix = struct.unpack_from(
+                "<I", unhexlify(block["previous"]), 4
+            )[0]
+        return ref_block_num, ref_block_prefix
+
     def sign(self, reconstruct_tx=True):
         """ Sign a provided transaction with the provided key(s)
             One or many wif keys to use for signing a transaction.
diff --git a/beembase/ledgertransactions.py b/beembase/ledgertransactions.py
index e6e2a82e..d5601206 100644
--- a/beembase/ledgertransactions.py
+++ b/beembase/ledgertransactions.py
@@ -20,8 +20,8 @@ log = logging.getLogger(__name__)
 class Ledger_Transaction(GrapheneUnsigned_Transaction):
     """ Create an unsigned transaction and offer method to send it to a ledger device for signing
 
-        :param num refNum: parameter ref_block_num (see :func:`beembase.transactions.getBlockParams`)
-        :param num refPrefix: parameter ref_block_prefix (see :func:`beembase.transactions.getBlockParams`)
+        :param num ref_block_num:
+        :param num ref_block_prefix:
         :param str expiration: expiration date
         :param array operations:  array of operations
         :param dict custom_chains: custom chain which should be added to the known chains
diff --git a/beembase/transactions.py b/beembase/transactions.py
index 00d831ff..53182e8b 100644
--- a/beembase/transactions.py
+++ b/beembase/transactions.py
@@ -2,14 +2,6 @@ from __future__ import absolute_import
 from __future__ import division
 from __future__ import print_function
 from __future__ import unicode_literals
-from binascii import hexlify, unhexlify
-import struct
-from beemgraphenebase.account import PublicKey
-from .signedtransactions import Signed_Transaction
-from .operations import (
-    Op_wrapper,
-    Account_create,
-)
 
 
 def getBlockParams(ws):
@@ -17,7 +9,7 @@ def getBlockParams(ws):
         ``ref_block_prefix``. Requires a websocket connection to a
         witness node!
     """
-    dynBCParams = ws.get_dynamic_global_properties()
-    ref_block_num = dynBCParams["head_block_number"] & 0xFFFF
-    ref_block_prefix = struct.unpack_from("<I", unhexlify(dynBCParams["head_block_id"]), 4)[0]
-    return ref_block_num, ref_block_prefix
+    raise DeprecationWarning(
+        "This method shouldn't be called anymore. It is part of "
+        "transactionbuilder now"
+    )
diff --git a/beemgraphenebase/unsignedtransactions.py b/beemgraphenebase/unsignedtransactions.py
index 5511c0d6..8d086bdb 100644
--- a/beemgraphenebase/unsignedtransactions.py
+++ b/beemgraphenebase/unsignedtransactions.py
@@ -119,8 +119,8 @@ class GrapheneObjectASN1(object):
 class Unsigned_Transaction(GrapheneObjectASN1):
     """ Create an unsigned transaction with ASN1 encoder for using it with ledger
 
-        :param num refNum: parameter ref_block_num (see :func:`beembase.transactions.getBlockParams`)
-        :param num refPrefix: parameter ref_block_prefix (see :func:`beembase.transactions.getBlockParams`)
+        :param num ref_block_num:
+        :param num ref_block_prefix:
         :param str expiration: expiration date
         :param array operations:  array of operations
     """
diff --git a/examples/using_steem_offline.py b/examples/using_steem_offline.py
index e1290601..1bb467c8 100644
--- a/examples/using_steem_offline.py
+++ b/examples/using_steem_offline.py
@@ -19,7 +19,7 @@ from beem.steem import Steem
 from beem.utils import parse_time, formatTimedelta
 from beemapi.exceptions import NumRetriesReached
 from beem.nodelist import NodeList
-from beembase.transactions import getBlockParams
+from beem.transactionbuilder import TransactionBuilder
 log = logging.getLogger(__name__)
 logging.basicConfig(level=logging.INFO)
 
@@ -29,7 +29,8 @@ wif = "5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3"
 
 if __name__ == "__main__":
     stm_online = Steem()
-    ref_block_num, ref_block_prefix = getBlockParams(stm_online)
+    trx_builder = TransactionBuilder(blockchain_instance=stm_online)
+    ref_block_num, ref_block_prefix = trx_builder.get_block_params()
     print("ref_block_num %d - ref_block_prefix %d" % (ref_block_num, ref_block_prefix))
 
     stm = Steem(offline=True)
-- 
GitLab