diff --git a/beem/account.py b/beem/account.py
index f8fac1d2dbc5f781f8468c3df796e2525bd12c58..3e15c87d2ae2e474efed14061837f9f73defbec0 100644
--- a/beem/account.py
+++ b/beem/account.py
@@ -614,13 +614,19 @@ class Account(BlockchainObject):
             return last_item
         else:
             try:
+                op_count = 0
+                self.steem.rpc.set_next_node_on_empty_reply(True)
                 if self.steem.rpc.get_use_appbase():
                     try:
-                        return self.steem.rpc.get_account_history({'account': self["name"], 'start': -1, 'limit': 0}, api="account_history")['history'][0][0]
+                        op_count = self.steem.rpc.get_account_history({'account': self["name"], 'start': -1, 'limit': 0}, api="account_history")['history']
                     except:
-                        return self.steem.rpc.get_account_history(self["name"], -1, 0)[0][0]
+                        op_count = self.steem.rpc.get_account_history(self["name"], -1, 0)
                 else:
-                    return self.steem.rpc.get_account_history(self["name"], -1, 0, api="database")[0][0]
+                    op_count = self.steem.rpc.get_account_history(self["name"], -1, 0, api="database")
+                if isinstance(op_count, list) and len(op_count) > 0 and len(op_count[0]) > 0:
+                    return op_count[0][0]
+                else:
+                    return 0
             except IndexError:
                 return 0
 
diff --git a/beem/cli.py b/beem/cli.py
index 9e24c1beb931afbcdb3219c4c008052f92765475..6ff14e88d64f12d4fdcde4cddd401fdbe1e8ae4f 100644
--- a/beem/cli.py
+++ b/beem/cli.py
@@ -9,11 +9,15 @@ from beem.amount import Amount
 from beem.account import Account
 from beem.steem import Steem
 from beem.comment import Comment
-from beem.storage import configStorage
+from beem.block import Block
+from beem.witness import Witness
+from beem.blockchain import Blockchain
+from beem import exceptions
 from beem.version import version as __version__
 from datetime import datetime, timedelta
 import pytz
 from beembase import operations
+
 from beemgraphenebase.account import PrivateKey, PublicKey
 import json
 from prettytable import PrettyTable
@@ -21,6 +25,7 @@ import math
 import random
 import logging
 import click
+import re
 click.disable_unicode_literals_warning = True
 log = logging.getLogger(__name__)
 
@@ -32,15 +37,30 @@ availableConfigurationKeys = [
 ]
 
 
+def prompt_callback(ctx, param, value):
+    if value in ["yes", "y", "ye"]:
+        value = True
+    else:
+        print("Please write yes, ye or y to confirm!")
+        ctx.abort()
+
+
+def prompt_flag_callback(ctx, param, value):
+    if not value:
+        ctx.abort()
+
+
 @click.group(chain=True)
 @click.option(
-    '--node', '-n', default="", help="URL for public Steem API")
+    '--node', '-n', default="", help="URL for public Steem API (e.g. https://api.steemit.com)")
 @click.option(
-    '--offline', is_flag=True, default=False, help="Prevent connecting to network")
+    '--offline', '-o', is_flag=True, default=False, help="Prevent connecting to network")
 @click.option(
-    '--nobroadcast', '-d', is_flag=True, default=False, help="Do not broadcast")
+    '--no-broadcast', '-d', is_flag=True, default=False, help="Do not broadcast")
 @click.option(
-    '--unsigned', is_flag=True, default=False, help="Nothing will be signed")
+    '--no-wallet', '-p', is_flag=True, default=False, help="Do not load the wallet")
+@click.option(
+    '--unsigned', '-x', is_flag=True, default=False, help="Nothing will be signed")
 @click.option(
     '--blocking', is_flag=True, default=False,
     help="Wait for broadcasted transactions to be included in a block and return full transaction")
@@ -48,45 +68,67 @@ availableConfigurationKeys = [
     '--bundle', is_flag=True, default=False,
     help="Do not broadcast transactions right away, but allow to bundle operations ")
 @click.option(
-    '--expiration', '-e', default=30,
+    '--expires', '-e', default=30,
     help='Delay in seconds until transactions are supposed to expire(defaults to 60)')
 @click.option(
-    '--debug', is_flag=True, default=False, help='Enables Debug output')
+    '--verbose', '-v', default=3, help='Verbosity')
 @click.version_option(version=__version__)
-def cli(node, offline, nobroadcast, unsigned, blocking, bundle, expiration, debug):
+def cli(node, offline, no_broadcast, no_wallet, unsigned, blocking, bundle, expires, verbose):
+
+    # Logging
+    log = logging.getLogger(__name__)
+    verbosity = ["critical", "error", "warn", "info", "debug"][int(
+        min(verbose, 4))]
+    log.setLevel(getattr(logging, verbosity.upper()))
+    formatter = logging.Formatter(
+        '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+    ch = logging.StreamHandler()
+    ch.setLevel(getattr(logging, verbosity.upper()))
+    ch.setFormatter(formatter)
+    log.addHandler(ch)
+
+    debug = verbose > 0
     stm = Steem(
         node=node,
-        nobroadcast=nobroadcast,
+        nobroadcast=no_broadcast,
+        offline=offline,
+        nowallet=no_wallet,
         unsigned=unsigned,
         blocking=blocking,
         bundle=bundle,
-        expiration=expiration,
+        expiration=expires,
         debug=debug
     )
     set_shared_steem_instance(stm)
+
     pass
 
 
 @cli.command()
-@click.option(
-    '--account', '-a', multiple=False, help="Set default account")
-@click.option(
-    '--weight', '-w', multiple=False, help="Set your default vote weight")
-@click.option(
-    '--node', '-n', multiple=True, help="Set nodes")
-def set(account, weight, node):
-    """ Set configuration
+@click.argument('key')
+@click.argument('value')
+def set(key, value):
+    """ Set default_account, default_vote_weight or nodes
+
+        set [key] [value]
+
+        Examples:
+
+        Set the default vote weight to 50 %:
+        set default_vote_weight 50
     """
     stm = shared_steem_instance()
-    if account:
-        stm.set_default_account(account)
-    if weight:
-        configStorage["default_vote_weight"] = weight
-    if len(node) > 0:
-        nodes = []
-        for n in node:
-            nodes.append(n)
-        configStorage["node"] = nodes
+    if key == "default_account":
+        stm.set_default_account(value)
+    elif key == "default_vote_weight":
+        stm.set_default_vote_weight(value)
+    elif key == "nodes" or key == "node":
+        if bool(value) or value != "default":
+            stm.set_default_nodes(value)
+        else:
+            stm.set_default_nodes("")
+    else:
+        print("wrong key")
 
 
 @cli.command()
@@ -100,23 +142,28 @@ def config():
         # hide internal config data
         if key in availableConfigurationKeys:
             t.add_row([key, stm.config[key]])
-    for node in stm.config.nodes:
-        t.add_row(["node", node])
+    if "default_nodes" in stm.config and bool(stm.config["default_nodes"]):
+        node = stm.config["default_nodes"]
+    elif "node" in stm.config:
+        node = stm.config["node"]
+    nodes = json.dumps(node, indent=4)
+    t.add_row(["nodes", nodes])
     t.add_row(["data_dir", stm.config.data_dir])
     print(t)
 
 
 @cli.command()
-@click.option('--password', prompt=True, hide_input=True,
-              confirmation_prompt=True)
 @click.option(
     '--wipe', is_flag=True, default=False,
+    prompt='Do you want to wipe your wallet? Are your sure? This is IRREVERSIBLE! If you dont have a backup you may lose access to your account!',
     help="Delete old wallet. All wallet data are deleted!")
-def createwallet(password, purge):
+@click.option('--password', prompt=True, hide_input=True,
+              confirmation_prompt=True)
+def createwallet(wipe, password):
     """ Create new wallet with password
     """
     stm = shared_steem_instance()
-    if purge and click.confirm('Do you want to continue to wipe your Wallet?'):
+    if wipe and click.confirm('Do you want to continue to wipe your Wallet?'):
         stm.wallet.wipe(True)
     stm.wallet.create(password)
     set_shared_steem_instance(stm)
@@ -138,10 +185,14 @@ def walletinfo():
 
 @cli.command()
 @click.option('--password', prompt=True, hide_input=True,
-              confirmation_prompt=False)
-@click.option('--key')
-def addkey(password, key):
+              confirmation_prompt=False, help='Password to unlock wallet')
+@click.option('--unsafe-import-key', prompt='Enter private key', hide_input=False,
+              confirmation_prompt=False, help='Private key to import to wallet (unsafe, unless shell history is deleted afterwards)')
+def addkey(password, unsafe_import_key):
     """ Add key to wallet
+
+        When no [OPTION] is given, a password prompt for unlocking the wallet
+        and a prompt for entering the private key are shown.
     """
     stm = shared_steem_instance()
     if not stm.wallet.locked():
@@ -151,7 +202,34 @@ def addkey(password, key):
         print("Could not be unlocked!")
     else:
         print("Unlocked!")
-        stm.wallet.addPrivateKey(key)
+        stm.wallet.addPrivateKey(unsafe_import_key)
+    set_shared_steem_instance(stm)
+
+
+@cli.command()
+@click.option('--confirm',
+              prompt='Are your sure? This is IRREVERSIBLE! If you dont have a backup you may lose access to your account!',
+              hide_input=False, callback=prompt_flag_callback, is_flag=True,
+              confirmation_prompt=False, help='Please confirm!')
+@click.option('--password', prompt=True, hide_input=True,
+              confirmation_prompt=False, help='Password to unlock wallet')
+@click.argument('pub')
+def delkey(confirm, password, pub):
+    """ Delete key from the wallet
+
+        PUB is the public key from the private key
+        which will be deleted from the wallet
+    """
+    stm = shared_steem_instance()
+    if not stm.wallet.locked():
+        return
+    stm.wallet.unlock(password)
+    if stm.wallet.locked():
+        print("Could not be unlocked!")
+    else:
+        print("Unlocked!")
+        if click.confirm('Do you want to continue to wipe the private key?'):
+            stm.wallet.removePrivateKeyFromPublicKey(pub)
     set_shared_steem_instance(stm)
 
 
@@ -160,20 +238,10 @@ def listkeys():
     """ Show stored keys
     """
     stm = shared_steem_instance()
-    t = PrettyTable(["Available Key", "Account", "Type"])
+    t = PrettyTable(["Available Key"])
     t.align = "l"
     for key in stm.wallet.getPublicKeys():
-        if key[0:2] != stm.prefix:
-            continue
-        account = stm.wallet.getAccount(key)
-        if account["name"] is None:
-            accountName = ""
-            keyType = "Memo"
-        else:
-            accountName = account["name"]
-            keyType = account["type"]
-        # keyType = stm.wallet.getKeyType(account, key)
-        t.add_row([key, accountName, keyType])
+        t.add_row([key])
     print(t)
 
 
@@ -193,18 +261,48 @@ def listaccounts():
 
 @cli.command()
 @click.argument('post', nargs=1)
-@click.option('--account', '-a')
+@click.option('--account', '-a', help='Voter account name')
 @click.option('--weight', '-w', default=100.0, help='Vote weight (from 0.1 to 100.0)')
 def upvote(post, account, weight):
-    """Upvote a post/comment"""
+    """Upvote a post/comment
+
+        POST is @author/permlink
+    """
+    stm = shared_steem_instance()
     if not weight:
-        weight = configStorage["default_vote_weight"]
+        weight = stm.config["default_vote_weight"]
     if not account:
-        account = configStorage["default_account"]
-    post = Comment(post)
+        account = stm.config["default_account"]
+    try:
+        post = Comment(post)
+    except Exception as e:
+        log.error(str(e))
+        return
     post.upvote(weight, voter=account)
 
 
+@cli.command()
+@click.argument('post', nargs=1)
+@click.option('--account', '-a', help='Voter account name')
+@click.option('--weight', '-w', default=100.0, help='Vote weight (from 0.1 to 100.0)')
+def downvote(post, account, weight):
+    """Downvote a post/comment
+
+        POST is @author/permlink
+    """
+    stm = shared_steem_instance()
+    if not weight:
+        weight = stm.config["default_vote_weight"]
+    if not account:
+        account = stm.config["default_account"]
+    try:
+        post = Comment(post)
+    except Exception as e:
+        log.error(str(e))
+        return
+    post.downvote(weight, voter=account)
+
+
 @cli.command()
 @click.option('--password', prompt=True, hide_input=True,
               confirmation_prompt=True)
@@ -260,7 +358,10 @@ def balance(account):
 @cli.command()
 @click.argument('objects', nargs=-1)
 def info(objects):
-    """ Show info
+    """ Show basic blockchain info
+
+        General information about the blockchain, a block, an account,
+        a post/comment and a public key
     """
     stm = shared_steem_instance()
     if not objects:
@@ -276,10 +377,109 @@ def info(objects):
         t.add_row(["steem per mvest", steem_per_mvest])
         t.add_row(["internal price", price])
         print(t.get_string(sortby="Key"))
-    for o in objects:
-        a = Account(o, steem_instance=stm)
-        a.print_info()
-        print("\n")
+        # Block
+    for obj in objects:
+        if re.match("^[0-9-]*$", obj) or re.match("^-[0-9]*$", obj) or re.match("^[0-9-]*:[0-9]", obj) or re.match("^[0-9-]*:-[0-9]", obj):
+            tran_nr = ''
+            if re.match("^[0-9-]*:[0-9-]", obj):
+                obj, tran_nr = obj.split(":")
+            if int(obj) < 1:
+                b = Blockchain()
+                block_number = b.get_current_block_num() + int(obj) - 1
+            else:
+                block_number = obj
+            block = Block(block_number)
+            if block:
+                t = PrettyTable(["Key", "Value"])
+                t.align = "l"
+                for key in sorted(block):
+                    value = block[key]
+                    if key == "transactions" and not bool(tran_nr):
+                        t.add_row(["Nr. of transactions", len(value)])
+                    elif key == "transactions" and bool(tran_nr):
+                        if int(tran_nr) < 0:
+                            tran_nr = len(value) + int(tran_nr)
+                        else:
+                            tran_nr = int(tran_nr)
+                        if len(value) > tran_nr and tran_nr > -1:
+                            t_value = json.dumps(value[tran_nr], indent=4)
+                            t.add_row(["transaction %d/%d" % (tran_nr, len(value)), t_value])
+                    elif key == "transaction_ids" and bool(tran_nr):
+                        if int(tran_nr) < 0:
+                            tran_nr = len(value) + int(tran_nr)
+                        else:
+                            tran_nr = int(tran_nr)
+                        if len(value) > int(tran_nr) and int(tran_nr) > -1:
+                            t.add_row(["transaction_id %d/%d" % (int(tran_nr), len(value)), value[int(tran_nr)]])
+                    else:
+                        t.add_row([key, value])
+                print(t)
+            else:
+                print("Block number %s unknown" % obj)
+        elif re.match("^[a-zA-Z0-9\-\._]{2,16}$", obj):
+            account = Account(obj, steem_instance=stm)
+            t = PrettyTable(["Key", "Value"])
+            t.align = "l"
+            account_json = account.json()
+            for key in sorted(account_json):
+                value = account_json[key]
+                if key == "json_metadata":
+                    value = json.dumps(json.loads(value or "{}"), indent=4)
+                elif key in ["posting", "witness_votes", "active", "owner"]:
+                    value = json.dumps(value, indent=4)
+                elif key == "reputation" and int(value) > 0:
+                    value = int(value)
+                    rep = account.rep
+                    value = "{:.2f} ({:d})".format(rep, value)
+                elif isinstance(value, dict) and "asset" in value:
+                    value = str(account[key])
+                t.add_row([key, value])
+            print(t)
+
+            # witness available?
+            try:
+                witness = Witness(obj)
+                witness_json = witness.json()
+                t = PrettyTable(["Key", "Value"])
+                t.align = "l"
+                for key in sorted(witness_json):
+                    value = witness_json[key]
+                    if key in ["props", "sbd_exchange_rate"]:
+                        value = json.dumps(value, indent=4)
+                    t.add_row([key, value])
+                print(t)
+            except exceptions.WitnessDoesNotExistsException as e:
+                print(str(e))
+        # Public Key
+        elif re.match("^STM.{48,55}$", obj):
+            account = stm.wallet.getAccountFromPublicKey(obj)
+            if account:
+                t = PrettyTable(["Account"])
+                t.align = "l"
+                t.add_row([account])
+                print(t)
+            else:
+                print("Public Key not known" % obj)
+        # Post identifier
+        elif re.match(".*@.{3,16}/.*$", obj):
+            post = Comment(obj)
+            post_json = post.json()
+            if post_json:
+                t = PrettyTable(["Key", "Value"])
+                t.align = "l"
+                for key in sorted(post_json):
+                    value = post_json[key]
+                    if (key in ["json_metadata"]):
+                        value = json.loads(value)
+                        value = json.dumps(value, indent=4)
+                    elif (key in ["tags", "active_votes"]):
+                        value = json.dumps(value, indent=4)
+                    t.add_row([key, value])
+                print(t)
+            else:
+                print("Post now known" % obj)
+        else:
+            print("Couldn't identify object to read")
 
 
 if __name__ == "__main__":
diff --git a/beem/steem.py b/beem/steem.py
index 09ef7c9b883d8e50b52c0e20dc81ff12f9080c97..7a568080af761cee9e58f82f6581e900aed58841 100644
--- a/beem/steem.py
+++ b/beem/steem.py
@@ -622,6 +622,19 @@ class Steem(object):
         Account(account, steem_instance=self)
         config["default_account"] = account
 
+    def set_default_nodes(self, nodes):
+        """ Set the default nodes to be used
+        """
+        if bool(nodes):
+            config["node"] = nodes
+        else:
+            config.delete("node")
+
+    def set_default_vote_weight(self, vote_weight):
+        """ Set the default vote weight to be used
+        """
+        config["default_vote_weight"] = vote_weight
+
     def finalizeOp(self, ops, account, permission, **kwargs):
         """ This method obtains the required private keys if present in
             the wallet, finalizes the transaction, signs it and
diff --git a/tests/beem/test_cli.py b/tests/beem/test_cli.py
index 4e2ed9e44624abdf9ad46e1c857b88c174b2da52..ad2872800ac67e41bca998c594d7e121bf57eaa2 100644
--- a/tests/beem/test_cli.py
+++ b/tests/beem/test_cli.py
@@ -12,29 +12,24 @@ from pprint import pprint
 from beem import Steem, exceptions
 from beem.account import Account
 from beem.amount import Amount
+from beemgraphenebase.account import PrivateKey
 from beem.cli import cli, balance
 from beem.instance import set_shared_steem_instance
 from beembase.operationids import getOperationNameForId
 from beem.utils import get_node_list
 
-wif = "5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3"
+wif = "5Jt2wTfhUt5GkZHV1HYVfkEaJ6XnY8D2iA4qjtK9nnGXAhThM3w"
 
 
 class Testcases(unittest.TestCase):
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
-
-        self.bts = Steem(
-            node=get_node_list(appbase=False),
-            nobroadcast=True,
-            bundle=False,
-            # Overwrite wallet to use this list of wifs only
-            wif={"active": wif},
-            num_retries=10
-        )
-        self.bts.set_default_account("test")
-        set_shared_steem_instance(self.bts)
+        runner = CliRunner()
+        runner.invoke(cli, ['set', 'default_vote_weight', '100'])
+        runner.invoke(cli, ['set', 'default_account', 'beem'])
+        runner.invoke(cli, ['set', 'nodes', 'wss://testnet.steem.vc'])
+        runner.invoke(cli, ['createwallet', '--wipe True'], input='test\ntest\n')
 
     def test_balance(self):
         runner = CliRunner()
@@ -46,12 +41,17 @@ class Testcases(unittest.TestCase):
         result = runner.invoke(cli, ['config'])
         self.assertEqual(result.exit_code, 0)
 
-    def test_listkeys(self):
+    def test_addkey(self):
         runner = CliRunner()
-        result = runner.invoke(cli, ['addkey', '--password test', '--key ' + wif])
+        result = runner.invoke(cli, ['addkey', '--password test', '--unsafe-import-key ' + wif])
         self.assertEqual(result.exit_code, 2)
 
-    def test_addkeys(self):
+    def test_delkey(self):
+        runner = CliRunner()
+        result = runner.invoke(cli, ['delkey', '--password test', wif])
+        self.assertEqual(result.exit_code, 2)
+
+    def test_listkeys(self):
         runner = CliRunner()
         result = runner.invoke(cli, ['listkeys'])
         self.assertEqual(result.exit_code, 0)
@@ -65,7 +65,11 @@ class Testcases(unittest.TestCase):
         runner = CliRunner()
         result = runner.invoke(cli, ['info'])
         self.assertEqual(result.exit_code, 0)
-        result = runner.invoke(cli, ['info', 'test'])
+        result = runner.invoke(cli, ['info', 'beem'])
+        self.assertEqual(result.exit_code, 0)
+        result = runner.invoke(cli, ['info', '100'])
+        self.assertEqual(result.exit_code, 0)
+        result = runner.invoke(cli, ['info', '--', '-1'])
         self.assertEqual(result.exit_code, 0)
 
     def test_changepassword(self):
@@ -85,5 +89,5 @@ class Testcases(unittest.TestCase):
 
     def test_set(self):
         runner = CliRunner()
-        result = runner.invoke(cli, ['set', '-w 100'])
+        result = runner.invoke(cli, ['set', 'set_default_vote_weight', '100'])
         self.assertEqual(result.exit_code, 0)
diff --git a/tests/beem/test_testnet.py b/tests/beem/test_testnet.py
index a19caa2bb7e745716a370752af3cb3244edb52a2..6009e25a3af12aaf785b13c03678ff8ed8a20d5d 100644
--- a/tests/beem/test_testnet.py
+++ b/tests/beem/test_testnet.py
@@ -182,13 +182,16 @@ class Testcases(unittest.TestCase):
                                  "memo": '2 of 2 serialized/deserialized transaction'}))
 
         tx.appendSigner("elf", "active")
+        tx.addSigningInformation("elf", "active")
         tx.sign()
         tx.clearWifs()
         self.assertEqual(len(tx['signatures']), 1)
-        new_tx = TransactionBuilder(tx=tx.json(), steem_instance=steem)
+        steem.wallet.removeAccount("elf")
+        tx_json = tx.json()
+        del tx
+        new_tx = TransactionBuilder(tx=tx_json, steem_instance=steem)
         self.assertEqual(len(new_tx['signatures']), 1)
         steem.wallet.addPrivateKey(self.active_private_key_of_steemfiles)
-        new_tx.addSigningInformation("steemfiles", "active", reconstruct_tx=False)
         new_tx.appendMissingSignatures()
         new_tx.sign(reconstruct_tx=False)
         self.assertEqual(len(new_tx['signatures']), 2)
@@ -224,6 +227,42 @@ class Testcases(unittest.TestCase):
         steem.nobroadcast = True
         steem.wallet.addPrivateKey(self.active_private_key_of_elf)
 
+    def test_transfer_2of2_wif(self):
+        # Send a 2 of 2 transaction from elf which needs steemfiles's cosign to send
+        # funds but sign the transaction with elf's key and then serialize the transaction
+        # and deserialize the transaction.  After that, sign with steemfiles's key.
+        steem = Steem(
+            node=["wss://testnet.steem.vc"],
+            num_retries=10,
+            keys=[self.active_private_key_of_elf]
+        )
+
+        tx = TransactionBuilder(steem_instance=steem)
+        tx.appendOps(Transfer(**{"from": 'elf',
+                                 "to": 'leprechaun',
+                                 "amount": '0.01 SBD',
+                                 "memo": '2 of 2 serialized/deserialized transaction'}))
+
+        tx.appendSigner("elf", "active")
+        tx.addSigningInformation("elf", "active")
+        tx.sign()
+        tx.clearWifs()
+        self.assertEqual(len(tx['signatures']), 1)
+        tx_json = tx.json()
+        del steem
+        del tx
+
+        steem = Steem(
+            node=["wss://testnet.steem.vc"],
+            num_retries=10,
+            keys=[self.active_private_key_of_steemfiles]
+        )
+        new_tx = TransactionBuilder(tx=tx_json, steem_instance=steem)
+        new_tx.appendMissingSignatures()
+        new_tx.sign(reconstruct_tx=False)
+        self.assertEqual(len(new_tx['signatures']), 2)
+        new_tx.broadcast()
+
     def test_verifyAuthority(self):
         stm = self.bts
         stm.wallet.unlock("123")