text: # -*- coding: utf-8 -*-
  import os
  import ast
  import json
  import sys
  from prettytable import PrettyTable
  from datetime import datetime, timedelta
  import calendar
  import pytz
  import time
  import hashlib
  #import math currently unused module
  import random
  import logging
  import click
  from click_shell import shell
  import re
  from beem.instance import set_shared_blockchain_instance, shared_blockchain_instance
  from beem.amount import Amount
  from beem.price import Price
  from beem.account import Account
  from beem.steem import Steem
  from beem.hive import Hive
  from beem.blurt import Blurt
  from beem.comment import Comment
  from beem.message import Message
  from beem.market import Market
  from beem.block import Block
  from beem.profile import Profile
  from beem.wallet import Wallet
  from beem.hivesigner import HiveSigner
  from beem.memo import Memo
  from beem.asset import Asset
  from beem.witness import Witness, WitnessesRankedByVote, WitnessesVotedByAccount
  from beem.blockchain import Blockchain
  from beem.utils import formatTimeString, construct_authorperm, derive_beneficiaries, derive_tags, seperate_yaml_dict_from_body, derive_permlink, make_patch, create_new_password, import_coldcard_wif, generate_password, import_pubkeys, import_custom_json
  from beem.vote import AccountVotes, ActiveVotes, Vote
  from beem import exceptions
  from beem.version import version as __version__
  from beem.asciichart import AsciiChart
  from beem.transactionbuilder import TransactionBuilder
  from timeit import default_timer as timer
  from beembase import operations
  from beemgraphenebase.account import PrivateKey, PublicKey, BrainKey, PasswordKey, MnemonicKey, Mnemonic
  from beemgraphenebase.base58 import Base58
  from beem.nodelist import NodeList, node_answer_time
  from beem.conveyor import Conveyor
  from beem.imageuploader import ImageUploader
  from beem.rc import RC
  from beem.community import Communities, Community
  from beem.blockchaininstance import BlockChainInstance
  from beem.storage import get_default_config_store
  
  click.disable_unicode_literals_warning = True
  log = logging.getLogger(__name__)
  
  availableConfigurationKeys = [
      "default_account",
      "default_vote_weight",
      "nodes",
      "password_storage",
      "client_id",
      "default_canonical_url",
      "default_path",
      "use_tor"
  ]
  
  
  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 asset_callback(ctx, param, value):
      if value not in ["STEEM", "SBD", "HIVE", "HBD", "BLURT", "TBD", "TESTS"]:
          print("Please STEEM/HIVE/BLURT or SBD/HBD as asset!")
          ctx.abort()
      else:
          return value
  
  
  def prompt_flag_callback(ctx, param, value):
      if not value:
          ctx.abort()
  
  
  def is_keyring_available():
      KEYRING_AVAILABLE = False
      try:
          import keyring
          if not isinstance(keyring.get_keyring(), keyring.backends.fail.Keyring):
              KEYRING_AVAILABLE = True
          else:
              KEYRING_AVAILABLE = False
      except ImportError:
          KEYRING_AVAILABLE = False
      return KEYRING_AVAILABLE
  
  
  def unlock_wallet(stm, password=None, allow_wif=True):
      if stm.unsigned and stm.nobroadcast:
          return True
      if stm.use_ledger:
          return True
      if not stm.wallet.locked():
          return True
      if not stm.wallet.store.is_encrypted():
          return True
      password_storage = stm.config["password_storage"]
      if not password and password_storage == "keyring" and is_keyring_available():
          import keyring
          password = keyring.get_password("beem", "wallet")
      if not password and password_storage == "environment" and "UNLOCK" in os.environ:
          password = os.environ.get("UNLOCK")
      if bool(password):
          stm.wallet.unlock(password)
      else:
          if allow_wif:
              password = click.prompt("Password to unlock wallet or posting/active wif", confirmation_prompt=False, hide_input=True)
          else:
              password = click.prompt("Password to unlock wallet", confirmation_prompt=False, hide_input=True)
          if stm.wallet.is_encrypted():
              try:
                  stm.wallet.unlock(password)
              except:
                  try:
                      from beemstorage import InRamPlainKeyStore
                      stm.wallet.store = InRamPlainKeyStore()
                      stm.wallet.setKeys([password])
                      print("Wif accepted!")
                      return True
                  except:
                      if allow_wif:
                          raise exceptions.WrongMasterPasswordException("entered password is not a valid password/wif")
                      else:
                          raise exceptions.WrongMasterPasswordException("entered password is not a valid password")
          else:
              try:
                  stm.wallet.setKeys([password])
                  print("Wif accepted!")
                  return True
              except:
                  try:
                      from beemstorage import SqliteEncryptedKeyStore
                      stm.wallet.store = SqliteEncryptedKeyStore(config=stm.config)
                      stm.wallet.unlock(password)
                  except:
                      if allow_wif:
                          raise exceptions.WrongMasterPasswordException("entered password is not a valid password/wif")
                      else:
                          raise exceptions.WrongMasterPasswordException("entered password is not a valid password")
  
      if stm.wallet.locked():
          if password_storage == "keyring" or password_storage == "environment":
              print("Wallet could not be unlocked with %s!" % password_storage)
              password = click.prompt("Password to unlock wallet", confirmation_prompt=False, hide_input=True)
              if bool(password):
                  unlock_wallet(stm, password=password)
                  if not stm.wallet.locked():
                      return True
          else:
              print("Wallet could not be unlocked!")
          return False
      else:
          print("Wallet Unlocked!")
          return True
  
  
  def unlock_token_wallet(stm, sc2, password=None):
      if stm.unsigned and stm.nobroadcast:
          return True
      if stm.use_ledger:
          return True
      if not sc2.locked():
          return True
      if not sc2.store.is_encrypted():
          return True
      password_storage = stm.config["password_storage"]
      if not password and password_storage == "keyring" and is_keyring_available():
          import keyring
          password = keyring.get_password("beem", "wallet")
      if not password and password_storage == "environment" and "UNLOCK" in os.environ:
          password = os.environ.get("UNLOCK")
      if bool(password):
          sc2.unlock(password)
      else:
          password = click.prompt("Password to unlock wallet", confirmation_prompt=False, hide_input=True)
          try:
              sc2.unlock(password)
          except:
              raise exceptions.WrongMasterPasswordException("entered password is not a valid password")
  
      if sc2.locked():
          if password_storage == "keyring" or password_storage == "environment":
              print("Wallet could not be unlocked with %s!" % password_storage)
              password = click.prompt("Password to unlock wallet", confirmation_prompt=False, hide_input=True)
              if bool(password):
                  unlock_token_wallet(stm, sc2, password=password)
                  if not sc2.locked():
                      return True
          else:
              print("Wallet could not be unlocked!")
          return False
      else:
          print("Wallet Unlocked!")
          return True
  
  
  def export_trx(tx, export):
      if export is not None:
          with open(export, "w", encoding="utf-8") as f:
              json.dump(tx, f)
  
  
  @shell(prompt='beempy> ', intro='Starting beempy... (use help to list all commands)', chain=True)
  # @click.group(chain=True)
  @click.option(
      '--node', '-n', default="", help="URL for public Hive API (e.g. https://api.hive.blog)")
  @click.option(
      '--offline', '-o', is_flag=True, default=False, help="Prevent connecting to network")
  @click.option(
      '--no-broadcast', '-d', is_flag=True, default=False, help="Do not broadcast")
  @click.option(
      '--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, changes the default value of expires to 3600")
  @click.option(
      '--create-link', '-l', is_flag=True, default=False, help="Creates hivesigner links from all broadcast operations")
  @click.option(
      '--steem', '-s', is_flag=True, default=False, help="Connect to the Steem blockchain")
  @click.option(
      '--hive', '-h', is_flag=True, default=False, help="Connect to the Hive blockchain")
  @click.option(
      '--keys', '-k', help="JSON file that contains account keys, when set, the wallet cannot be used.")
  @click.option(
      '--use-ledger', '-u', is_flag=True, default=False, help="Uses the ledger device Nano S for signing.")
  @click.option(
      '--path', help="BIP32 path from which the keys are derived, when not set, default_path is used.")
  @click.option(
      '--token', '-t', is_flag=True, default=False, help="Uses a hivesigner token to broadcast (only broadcast operation with posting permission)")
  @click.option(
      '--expires', '-e', default=30,
      help='Delay in seconds until transactions are supposed to expire(defaults to 30)')
  @click.option(
      '--verbose', '-v', default=3, help='Verbosity')
  @click.version_option(version=__version__)
  def cli(node, offline, no_broadcast, no_wallet, unsigned, create_link, steem, hive, keys, use_ledger, path, token, 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)
  
      if unsigned and expires == 30:
          # Change expires to max duration when setting unsigned
          expires = 3600
  
      keys_list = []
      autoconnect = False
      if keys and keys != "":
          if not os.path.isfile(keys):
              raise Exception("File %s does not exist!" % keys)
          with open(keys) as fp:
              keyfile = fp.read()
          if keyfile.find('\0') > 0:
              with open(keys, encoding='utf-16') as fp:
                  keyfile = fp.read()
          keyfile = ast.literal_eval(keyfile)
          for account in keyfile:
              for role in ["owner", "active", "posting", "memo"]:
                  if role in keyfile[account]:
                      keys_list.append(keyfile[account][role])
      if len(keys_list) > 0:
          autoconnect = True
      if create_link:
          no_broadcast = True
          unsigned = True
          sc2 = HiveSigner()
      else:
          sc2 = None
      debug = verbose > 0
      blurt = False
      if not hive and not steem:
          config = get_default_config_store()
          if config["default_chain"].lower() == "hive":
              hive = True
          elif config["default_chain"].lower() == "steem":
              steem = True
          elif config["default_chain"].lower() == "blurt":
              blurt = True
      if hive:
          stm = Hive(
              node=node,
              nobroadcast=no_broadcast,
              keys=keys_list,
              offline=offline,
              nowallet=no_wallet,
              unsigned=unsigned,
              use_hs=token,
              expiration=expires,
              hivesigner=sc2,
              use_ledger=use_ledger,
              path=path,
              debug=debug,
              num_retries=10,
              num_retries_call=5,
              timeout=30,
              autoconnect=autoconnect
          )
      elif steem:
          stm = Steem(
              node=node,
              nobroadcast=no_broadcast,
              offline=offline,
              keys=keys_list,
              nowallet=no_wallet,
              unsigned=unsigned,
              use_sc2=token,
              expiration=expires,
              steemconnect=sc2,
              use_ledger=use_ledger,
              path=path,
              debug=debug,
              num_retries=10,
              num_retries_call=5,
              timeout=30,
              autoconnect=autoconnect
          )
      else:
          stm = Blurt(
              node=node,
              nobroadcast=no_broadcast,
              offline=offline,
              keys=keys_list,
              nowallet=no_wallet,
              unsigned=unsigned,
              use_sc2=token,
              expiration=expires,
              steemconnect=sc2,
              use_ledger=use_ledger,
              path=path,
              debug=debug,
              num_retries=10,
              num_retries_call=5,
              timeout=30,
              autoconnect=autoconnect
          )
  
      set_shared_blockchain_instance(stm)
  
      pass
  
  
  @cli.command()
  @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_blockchain_instance()
      if key == "default_account":
          if stm.rpc is not None:
              stm.rpc.rpcconnect()
          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("")
      elif key == "default_chain":
          stm.config["default_chain"] = value
      elif key == "password_storage":
          stm.config["password_storage"] = value
          if is_keyring_available() and value == "keyring":
              import keyring
              password = click.prompt("Password to unlock wallet (Will be stored in keyring)", confirmation_prompt=False, hide_input=True)
              password = keyring.set_password("beem", "wallet", password)
          elif is_keyring_available() and value != "keyring":
              import keyring
              try:
                  keyring.delete_password("beem", "wallet")
              except keyring.errors.PasswordDeleteError:
                  print("")
          if value == "environment":
              print("The wallet password can be stored in the UNLOCK environment variable to skip password prompt!")
      elif key == "client_id":
          stm.config["client_id"] = value
      elif key == "hot_sign_redirect_uri":
          stm.config["hot_sign_redirect_uri"] = value
      elif key == "sc2_api_url":
          stm.config["sc2_api_url"] = value
      elif key == "hs_api_url":
          stm.config["hs_api_url"] = value
      elif key == "oauth_base_url":
          stm.config["oauth_base_url"] = value
      elif key == "default_path":
          stm.config["default_path"] = value
      elif key == "default_canonical_url":
          stm.config["default_canonical_url"] = value
      elif key == "use_condenser":
          stm.config["use_condenser"] = value in ["true", "True"]
      elif key == "use_tor":
          stm.config["use_tor"] = value in ["true", "True"]
      else:
          print("wrong key")
  
  
  @cli.command()
  @click.option('--results', is_flag=True, default=False, help="Shows result of changing the node.")
  def nextnode(results):
      """ Uses the next node in list
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      stm.move_current_node_to_front()
      node = stm.get_default_nodes()
      offline = stm.offline
      if len(node) < 2 or isinstance(node, str):
          print("At least two nodes are needed!")
          return
      node = node[1:] + [node[0]]
      if not offline:
          stm.rpc.next()
          stm.get_blockchain_version()
      while not offline and node[0] != stm.rpc.url and len(node) > 1:
          node = node[1:] + [node[0]]
      stm.set_default_nodes(node)
      if not results:
          return
  
      t = PrettyTable(["Key", "Value"])
      t.align = "l"
      if not offline:
          t.add_row(["Node-Url", stm.rpc.url])
      else:
          t.add_row(["Node-Url", node[0]])
      if not offline:
          t.add_row(["Version", stm.get_blockchain_version()])
          t.add_row(["HIVE", stm.is_hive])
      else:
          t.add_row(["Version", "beempy is in offline mode..."])
      print(t)
  
  
  @cli.command()
  @click.option(
      '--sort', '-s', is_flag=True, default=False,
      help="Sort all nodes by ping value")
  @click.option(
      '--remove', '-r', is_flag=True, default=False,
      help="Remove node with errors from list")
  def pingnode(sort, remove):
      """ Returns the answer time in milliseconds
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      nodes = stm.get_default_nodes()
  
      t = PrettyTable(["Node", "Answer time [ms]"])
      t.align = "l"
      if sort:
          sorted_node_list = []
          nodelist = NodeList()
          sorted_nodes = nodelist.get_node_answer_time(nodes)
          for node in sorted_nodes:
              t.add_row([node["url"], "%.2f" % (node["delay_ms"])])
              sorted_node_list.append(node["url"])
          print(t)
          stm.set_default_nodes(sorted_node_list)
      else:
          node = stm.rpc.url
          rpc_answer_time = node_answer_time(node)
          rpc_time_str = "%.2f" % (rpc_answer_time * 1000)
          t.add_row([node, rpc_time_str])
          print(t)
  
  
  @cli.command()
  def about():
      """ About beempy"""
      print("")
      print("beempy version: %s" % __version__)
      print("")
      print("By @holger80")
      print("")
  
  
  @cli.command()
  @click.option(
      '--version', is_flag=True, default=False,
      help="Returns only the raw version value")
  @click.option(
      '--url', is_flag=True, default=False,
      help="Returns only the raw url value")
  def currentnode(version, url):
      """ Sets the currently working node at the first place in the list
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      offline = stm.offline
      stm.move_current_node_to_front()
      node = stm.get_default_nodes()
      if version and not offline:
          print(stm.get_blockchain_version())
          return
      elif version and offline:
          print("Node is offline")
          return
      if url and not offline:
          print(stm.rpc.url)
          return
      t = PrettyTable(["Key", "Value"])
      t.align = "l"
      if not offline:
          t.add_row(["Node-Url", stm.rpc.url])
      else:
          t.add_row(["Node-Url", node[0]])
      if not offline:
          t.add_row(["Version", stm.get_blockchain_version()])
          t.add_row(["Chain", stm.get_blockchain_name()])
      else:
          t.add_row(["Version", "steempy is in offline mode..."])
      print(t)
  
  
  @cli.command()
  @click.option(
      '--show', '-s', is_flag=True, default=False,
      help="Prints the updated nodes")
  @click.option(
      '--hive', '-h', is_flag=True, default=False,
      help="Switch to HIVE blockchain, when set to true.")
  @click.option(
      '--steem', '-e', is_flag=True, default=False,
      help="Switch to STEEM nodes, when set to true.")
  @click.option(
      '--blurt', '-b', is_flag=True, default=False,
      help="Switch to BLURT nodes, when set to true.")
  @click.option(
      '--test', '-t', is_flag=True, default=False,
      help="Do change the node list, only print the newest nodes setup.")
  @click.option(
      '--only-https', is_flag=True, default=False,
      help="Use only https nodes.")
  @click.option(
      '--only-wss', is_flag=True, default=False,
      help="Use only websocket nodes.")
  def updatenodes(show, hive, steem, blurt, test, only_https, only_wss):
      """ Update the nodelist from @fullnodeupdate
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if steem and hive:
          print("hive and steem cannot be active both")
          return
      t = PrettyTable(["node", "Version", "score"])
      t.align = "l"
      if steem:
          blockchain = "steem"
      elif hive:
          blockchain = "hive"
      elif blurt:
          blockchain = "blurt"
      else:
          blockchain = stm.config["default_chain"]
      nodelist = NodeList()
      nodelist.update_nodes(blockchain_instance=stm)
      if hive:
          nodes = nodelist.get_hive_nodes(wss=not only_https, https=not only_wss)
          if stm.config["default_chain"] != "hive":
              stm.config["default_chain"] = "hive"
      elif steem:
          nodes = nodelist.get_steem_nodes(wss=not only_https, https=not only_wss)
          if stm.config["default_chain"] != "steem":
              stm.config["default_chain"] = "steem"
      elif blurt:
          nodes = ["https://rpc.blurt.world", "https://blurt-rpc.steem.buzz"]
          if stm.config["default_chain"] != "blurt":
              stm.config["default_chain"] = "blurt"
      elif stm.config["default_chain"] == "steem":
          nodes = nodelist.get_steem_nodes(wss=not only_https, https=not only_wss)
      elif stm.config["default_chain"] == "blurt":
          nodes = ["https://rpc.blurt.world", "https://blurt-rpc.steem.buzz"]
      else:
          nodes = nodelist.get_hive_nodes(wss=not only_https, https=not only_wss)
      if show or test:
          sorted_nodes = sorted(nodelist, key=lambda node: node["score"], reverse=True)
          for node in sorted_nodes:
              if node["url"] in nodes:
                  score = float("{0:.1f}".format(node["score"]))
                  t.add_row([node["url"], node["version"], score])
          print(t)
      if not test:
          stm.set_default_nodes(nodes)
          stm.rpc.nodes.set_node_urls(nodes)
          stm.rpc.current_rpc = 0
          stm.rpc.rpcclose()
          stm.rpc.rpcconnect()
  
  
  @cli.command()
  def config():
      """ Shows local configuration
      """
      stm = shared_blockchain_instance()
      t = PrettyTable(["Key", "Value"])
      t.align = "l"
      for key in stm.config:
          # hide internal config data
          if key in availableConfigurationKeys and key != "nodes" and key != "node" and key != "use_tor":
              t.add_row([key, stm.config[key]])
      node = stm.get_default_nodes()
      blockchain = stm.config["default_chain"]
      nodes = json.dumps(node, indent=4)
      t.add_row(["default_chain", blockchain])
      t.add_row(["nodes", nodes])
      if "password_storage" not in availableConfigurationKeys:
          t.add_row(["password_storage", stm.config["password_storage"]])
      if not stm.config["use_condenser"]:
          t.add_row(["use_condenser", stm.config["use_condenser"]])
      t.add_row(["data_dir", stm.config.data_dir])
      t.add_row(["use_tor", bool(stm.config["use_tor"])])
      print(t)
  
  
  @cli.command()
  @click.option('--wipe', is_flag=True, default=False,
                help="Wipe old wallet without prompt.")
  def createwallet(wipe):
      """ Create new wallet with a new password
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if stm.wallet.created() and not wipe:
          wipe_answer = click.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! [y/n]",
                                     default="n")
          if wipe_answer in ["y", "ye", "yes"]:
              stm.wallet.wipe(True)
          else:
              return
      elif wipe:
          stm.wallet.wipe(True)
      password = None
      password = click.prompt("New wallet password", confirmation_prompt=True, hide_input=True)
      if not bool(password):
          print("Password cannot be empty! Quitting...")
          return
      password_storage = stm.config["password_storage"]
      if password_storage == "keyring" and is_keyring_available():
          import keyring
          password = keyring.set_password("beem", "wallet", password)
      elif password_storage == "environment":
          print("The new wallet password can be stored in the UNLOCK environment variable to skip password prompt!")
      stm.wallet.wipe(True)
      stm.wallet.create(password)
      set_shared_blockchain_instance(stm)
  
  
  @cli.command()
  @click.option('--unlock', '-u', is_flag=True, default=False, help='Unlock wallet')
  @click.option('--lock', '-l', is_flag=True, default=False, help='Lock wallet')
  def walletinfo(unlock, lock):
      """ Show info about wallet
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if lock:
          stm.wallet.lock()
      elif unlock:
          unlock_wallet(stm, allow_wif=False)
  
      t = PrettyTable(["Key", "Value"])
      t.align = "l"
      t.add_row(["created", stm.wallet.created()])
      t.add_row(["locked", stm.wallet.locked()])
      t.add_row(["Number of stored keys", len(stm.wallet.getPublicKeys())])
      t.add_row(["sql-file", stm.wallet.store.sqlite_file])
      password_storage = stm.config["password_storage"]
      t.add_row(["password_storage", password_storage])
      password = os.environ.get("UNLOCK")
      if password is not None:
          t.add_row(["UNLOCK env set", "yes"])
      else:
          t.add_row(["UNLOCK env set", "no"])
      if is_keyring_available():
          t.add_row(["keyring installed", "yes"])
      else:
          t.add_row(["keyring installed", "no"])
  
      if unlock:
          if unlock_wallet(stm, allow_wif=False):
              t.add_row(["Wallet unlock", "successful"])
          else:
              t.add_row(["Wallet unlock", "not working"])
      # t.add_row(["getPublicKeys", str(stm.wallet.getPublicKeys())])
      print(t)
  
  
  @cli.command()
  @click.option('--unsafe-import-key',
                help='WIF key to parse (unsafe, unless shell history is deleted afterwards)', multiple=True)
  def parsewif(unsafe_import_key):
      """ Parse a WIF private key without importing
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if unsafe_import_key:
          for key in unsafe_import_key:
              try:
                  pubkey = PrivateKey(key, prefix=stm.prefix).pubkey
                  print(pubkey)
                  account = stm.wallet.getAccountFromPublicKey(str(pubkey))
                  account = Account(account, blockchain_instance=stm)
                  key_type = stm.wallet.getKeyType(account, str(pubkey))
                  print("Account: %s - %s" % (account["name"], key_type))
              except Exception as e:
                  print(str(e))
      else:
          while True:
              wifkey = click.prompt("Enter private key", confirmation_prompt=False, hide_input=True)
              if not wifkey or wifkey == "quit" or wifkey == "exit":
                  break
              try:
                  pubkey = PrivateKey(wifkey, prefix=stm.prefix).pubkey
                  print(pubkey)
                  account = stm.wallet.getAccountFromPublicKey(str(pubkey))
                  account = Account(account, blockchain_instance=stm)
                  key_type = stm.wallet.getKeyType(account, str(pubkey))
                  print("Account: %s - %s" % (account["name"], key_type))
              except Exception as e:
                  print(str(e))
                  continue
  
  
  @cli.command()
  @click.option('--unsafe-import-key',
                help='Private key to import to wallet (unsafe, unless shell history is deleted afterwards)')
  def addkey(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_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not unlock_wallet(stm, allow_wif=False):
          return
      if not unsafe_import_key:
          unsafe_import_key = click.prompt("Enter private key", confirmation_prompt=False, hide_input=True)
      stm.wallet.addPrivateKey(unsafe_import_key)
      set_shared_blockchain_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.argument('pub')
  def delkey(confirm, pub):
      """ Delete key from the wallet
  
          PUB is the public key from the private key
          which will be deleted from the wallet
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not unlock_wallet(stm, allow_wif=False):
          return
      stm.wallet.removePrivateKeyFromPublicKey(pub)
      set_shared_blockchain_instance(stm)
  
  
  @cli.command()
  @click.option('--import-word-list', '-l', help='Imports a BIP39 wordlist and derives a private and public key', is_flag=True, default=False)
  @click.option('--strength', help='Defines word list length for BIP39 (default = 256).', default=256)
  @click.option('--passphrase', '-p', help='Sets a BIP39 passphrase', is_flag=True, default=False)
  @click.option('--path', '-m', help='Sets a path for BIP39 key creations. When path is set, network, role, account_keys, account and sequence is not used')
  @click.option('--network', '-n', help='Network index, when using BIP39, 0 for steem and 13 for hive, (default is 13)', default=13)
  @click.option('--role', '-r', help='Defines which key role should be created (default = owner).', default="owner")
  @click.option('--account-keys', '-k', help='Derives four BIP39 keys for each role', is_flag=True, default=False)
  @click.option('--sequence', '-s', help='Sequence key number, when using BIP39 (default is 0)', default=0)
  @click.option('--account', '-a', help='sequence number for BIP39 key, default = 0')
  @click.option('--wif', '-w', help='Defines how many times the password is replaced by its WIF representation for password based keys (default = 0).')
  @click.option('--export-pub', '-u', help='Exports the public account keys to a json file for account creation or keychange')
  @click.option('--export', '-e', help='The results are stored in a text file and will not be shown')
  def keygen(import_word_list, strength, passphrase, path, network, role, account_keys, sequence, account, wif, export_pub, export):
      """ Creates a new random BIP39 key and prints its derived private key and public key.
          The generated key is not stored. Can also be used to create new keys for an account.
          Can also be used to derive account keys from a password or BIP39 wordlist.
      """
      stm = shared_blockchain_instance()
      pub_json = {"owner": "", "active": "", "posting": "", "memo": ""}
  
      if not account_keys and len(role.split(",")) > 1:
          roles = role.split(",")
          account_keys = True
      else:
          roles = ['owner', 'active', 'posting', 'memo']
      if wif is not None:
          wif = int(wif)
      else:
          wif = 0
  
      if stm.use_ledger:
          if stm.rpc is not None:
              stm.rpc.rpcconnect()
          ledgertx = stm.new_tx()
          ledgertx.constructTx()
          if account is None:
              account = 0
          else:
              account = int(account)
          t = PrettyTable(["Key", "Value"])
          t_pub = PrettyTable(["Key", "Value"])
          t.align = "l"
          t_pub.align = "l"
          t.add_row(["Account sequence", account])
          t.add_row(["Key sequence", sequence])
  
  
          if account_keys and path is None:
              for r in roles:
                  path = ledgertx.ledgertx.build_path(r, account, sequence)
                  pubkey = ledgertx.ledgertx.get_pubkey(path, request_screen_approval=False)
                  aprove_key = PrettyTable(["Approve %s Key" % r])
                  aprove_key.align = "l"
                  aprove_key.add_row([format(pubkey, "STM")])
                  print(aprove_key)
                  ledgertx.ledgertx.get_pubkey(path, request_screen_approval=True)
                  t_pub.add_row(["%s Public Key" % r, format(pubkey, "STM")])
                  t.add_row(["%s path" % r, path])
                  pub_json[r] = format(pubkey, "STM")
          else:
              if path is None:
                  path = ledgertx.ledgertx.build_path(role, account, sequence)
              t.add_row(["Key role", role])
              t.add_row(["path", path])
              pubkey = ledgertx.ledgertx.get_pubkey(path, request_screen_approval=False)
              aprove_key = PrettyTable(["Approve %s Key" % role])
              aprove_key.align = "l"
              aprove_key.add_row([format(pubkey, "STM")])
              print(aprove_key)
              ledgertx.ledgertx.get_pubkey(path, request_screen_approval=True)
              t_pub.add_row(["Public Key", format(pubkey, "STM")])
              pub_json[role] = format(pubkey, "STM")
      else:
          if account is None:
              account = 0
          else:
              account = int(account)
          if import_word_list:
              n_words = click.prompt("Enter word list length or complete word list")
              if len(n_words.split(" ")) > 0:
                  word_list = n_words
              else:
                  n_words = int(n_words)
                  word_array = []
                  word = None
                  m = Mnemonic()
                  while len(word_array) < n_words:
                      word = click.prompt("Enter %d. mnemnoric word" % (len(word_array) + 1), type=str)
                      word = m.expand_word(word)
                      if m.check_word(word):
                          word_array.append(word)
                      print(" ".join(word_array))
                  word_list = " ".join(word_array)
              if passphrase:
                  passphrase = click.prompt("Enter passphrase", confirmation_prompt=True, hide_input=True)
              else:
                  passphrase = ""
              mk = MnemonicKey(word_list=word_list, passphrase=passphrase, account_sequence=account, key_sequence=sequence)
              if path is not None:
                  mk.set_path(path)
              else:
                  mk.set_path_BIP48(network_index=network, role=role, account_sequence=account, key_sequence=sequence)
          else:
              mk = MnemonicKey(account_sequence=account, key_sequence=sequence)
              if path is not None:
                  mk.set_path(path)
              else:
                  mk.set_path_BIP48(network_index=network, role=role, account_sequence=account, key_sequence=sequence)
              if passphrase:
                  passphrase = click.prompt("Enter passphrase", confirmation_prompt=True, hide_input=True)
              else:
                  passphrase = ""
              word_list = mk.generate_mnemonic(passphrase=passphrase, strength=strength)
          t = PrettyTable(["Key", "Value"])
          t_pub = PrettyTable(["Key", "Value"])
          t.align = "l"
          t_pub.align = "l"
          t.add_row(["Account sequence", account])
          t.add_row(["Key sequence", sequence])
          if account_keys and path is None:
              for r in roles:
                  t.add_row(["%s Private Key" % r, str(mk.get_private())])
                  mk.set_path_BIP48(network_index=network, role=r, account_sequence=account, key_sequence=sequence)
                  t_pub.add_row(["%s Public Key" % r, format(mk.get_public(), "STM")])
                  t.add_row(["%s path" % r, mk.get_path()])
                  pub_json[r] = format(mk.get_public(), "STM")
              if passphrase != "":
                  t.add_row(["Passphrase", passphrase])
              t.add_row(["BIP39 wordlist", word_list])
          else:
              t.add_row(["Key role", role])
              t.add_row(["path", mk.get_path()])
              t.add_row(["BIP39 wordlist", word_list.lower()])
              if passphrase != "":
                  t.add_row(["Passphrase", passphrase])
              t.add_row(["Private Key", str(mk.get_private())])
              t_pub.add_row(["Public Key", format(mk.get_public(), "STM")])
              pub_json[role] = format(mk.get_public(), "STM")
      if export_pub and export_pub != "":
          pub_json = json.dumps(pub_json, indent=4)
          with open(export_pub, 'w') as fp:
              fp.write(pub_json)
          print("%s was sucessfully saved." % export_pub)
      if export and export != "":
          with open(export, 'w') as fp:
              fp.write(str(t))
              fp.write("\n")
              fp.write(str(t_pub))
          print("%s was sucessfully saved." % export)
      else:
          print(t_pub)
          print(t)
  
  
  @cli.command()
  @click.option('--role', '-r', help='Defines which key role should be created. When owner is not set as role and an cold card wif is imported, the Master Password is not shown. (default = owner,active,posting,memo when creating account keys).', default="owner,active,posting,memo")
  @click.option('--account', '-a', help='account name for password based key generation')
  @click.option('--import-password', '-i', help='Imports a password and derives all four account keys', is_flag=True, default=False)
  @click.option('--import-coldcard', '-o', help='Text file with a BIP85 WIF generated by a coldcard. The imported WIF is used to derives all four account keys')
  @click.option('--wif', '-w', help='Defines how many times the password is replaced by its WIF representation for password based keys (default = 0 or 1 when importing a cold card wif).')
  @click.option('--export-pub', '-u', help='Exports the public account keys to a json file for account creation or keychange')
  @click.option('--export', '-e', help='The results are stored in a text file and will not be shown')
  def passwordgen(role, account, import_password, import_coldcard, wif, export_pub, export):
      """ Creates a new password based key and prints its derived private key and public key.
          The generated key is not stored. The password is used to create new keys for an account.
      """
      stm = shared_blockchain_instance()
      if not account:
          account = stm.config["default_account"]
      if import_password:
          import_password = click.prompt("Enter password", confirmation_prompt=False, hide_input=True)
      elif import_coldcard is not None:
          import_password, path = import_coldcard_wif(import_coldcard)
      else:
          import_password = create_new_password(length=32)
      pub_json = {"owner": "", "active": "", "posting": "", "memo": ""}
  
      if len(role.split(",")) > 1:
          roles = role.split(",")
      elif role in ['owner', 'active', 'posting', 'memo']:
          roles = [role]
      else:
          roles = ['owner', 'active', 'posting', 'memo']
      if wif is not None:
          wif = int(wif)
      elif import_coldcard:
          wif = 1
      else:
          wif = 0
  
      password = generate_password(import_password, wif)
      t = PrettyTable(["Key", "Value"])
      t_pub = PrettyTable(["Key", "Value"])
      t.add_row(["Username", account])
      t_pub.add_row(["Username", account])
      if import_coldcard:
          t_pub.add_row(["cold card path", path])
      t.align = "l"
      t_pub.align = "l"
      for r in roles:
          pk = PasswordKey(account, password, role=r)
          t.add_row(["%s Private Key" % r, str(pk.get_private())])
          t_pub.add_row(["%s Public Key" % r, format(pk.get_public(), "STM")])
          pub_json[r] = format(pk.get_public(), "STM")
      if "owner" in roles or import_coldcard is None:
          t.add_row(["Backup (Master) Password", password])
      if wif > 0:
          t.add_row(["WIF itersions", wif])
          if "owner" in roles or import_coldcard is None:
              t.add_row(["Entered/created Password", import_password])
  
      if export_pub and export_pub != "":
          pub_json = json.dumps(pub_json, indent=4)
          with open(export_pub, 'w') as fp:
              fp.write(pub_json)
          print("%s was sucessfully saved." % export_pub)
      if export and export != "":
          with open(export, 'w') as fp:
              fp.write(str(t))
              fp.write("\n")
              fp.write(str(t_pub))
          print("%s was sucessfully saved." % export)
      else:
          print(t_pub)
          print(t)
  
  
  @cli.command()
  @click.argument('name')
  @click.option('--unsafe-import-token',
                help='Private key to import to wallet (unsafe, unless shell history is deleted afterwards)')
  def addtoken(name, unsafe_import_token):
      """ 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_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      sc2 = HiveSigner(blockchain_instance=stm)
      if not unlock_token_wallet(stm, sc2):
          return
      if not unsafe_import_token:
          unsafe_import_token = click.prompt("Enter private token", confirmation_prompt=False, hide_input=True)
      sc2.addToken(name, unsafe_import_token)
      set_shared_blockchain_instance(stm)
  
  
  @cli.command()
  @click.option('--confirm',
                prompt='Are your sure?',
                hide_input=False, callback=prompt_flag_callback, is_flag=True,
                confirmation_prompt=False, help='Please confirm!')
  @click.argument('name')
  def deltoken(confirm, name):
      """ Delete name from the wallet
  
          name is the public name from the private token
          which will be deleted from the wallet
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      sc2 = HiveSigner(blockchain_instance=stm)
      if not unlock_token_wallet(stm, sc2):
          return
      sc2.removeTokenFromPublicName(name)
      set_shared_blockchain_instance(stm)
  
  
  @cli.command()
  @click.option('--path', '-p', help='Set path (when using ledger)')
  @click.option('--ledger-approval', '-a', is_flag=True, default=False, help='When set, you can confirm the shown pubkey on your ledger.')
  def listkeys(path, ledger_approval):
      """ Show stored keys
  
      Can be used to receive and approve the pubkey obtained from the ledger
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
  
      if stm.use_ledger:
          if path is None:
              path = stm.config["default_path"]
          t = PrettyTable(["Available Key for %s" % path])
          t.align = "l"
          ledgertx = stm.new_tx()
          ledgertx.constructTx()
          pubkey = ledgertx.ledgertx.get_pubkey(path, request_screen_approval=False)
          t.add_row([str(pubkey)])
          if ledger_approval:
              print(t)
              ledgertx.ledgertx.get_pubkey(path, request_screen_approval=True)
      else:
          t = PrettyTable(["Available Key"])
          t.align = "l"
          for key in stm.wallet.getPublicKeys():
              t.add_row([key])
      print(t)
  
  @cli.command()
  def listtoken():
      """ Show stored token
      """
      stm = shared_blockchain_instance()
      t = PrettyTable(["name", "scope", "status"])
      t.align = "l"
      sc2 = HiveSigner(blockchain_instance=stm)
      if not unlock_token_wallet(stm, sc2):
          return
      for name in sc2.getPublicNames():
          ret = sc2.me(username=name)
          if "error" in ret:
              t.add_row([name, "-", ret["error"]])
          else:
              t.add_row([name, ret["scope"], "ok"])
      print(t)
  
  
  @cli.command()
  @click.option('--role', '-r', help='When set, limits the shown keys for this role')
  @click.option('--max-account-index', '-a', help='Set maximum account index to check pubkeys (only when using ledger)', default=5)
  @click.option('--max-sequence', '-s', help='Set maximum key sequence to check pubkeys (only when using ledger)', default=2)
  def listaccounts(role, max_account_index, max_sequence):
      """Show stored accounts
  
      Can be used with the ledger to obtain all accounts that uses pubkeys derived from this ledger
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
  
      if stm.use_ledger:
          t = PrettyTable(["Name", "Type", "Available Key", "Path"])
          t.align = "l"
          ledgertx = stm.new_tx()
          ledgertx.constructTx()
          key_found = False
          path = None
          current_account_index = 0
          current_key_index = 0
          role_list = ["owner", "active", "posting", "memo"]
          if role:
              role_list = [role]
          while not key_found and current_account_index < max_account_index:
              for perm in role_list:
                  path = ledgertx.ledgertx.build_path(perm, current_account_index, current_key_index)
                  current_pubkey = ledgertx.ledgertx.get_pubkey(path)
                  account = stm.wallet.getAccountFromPublicKey(str(current_pubkey))
                  if account is not None:
                      t.add_row([str(account), perm, str(current_pubkey), path])
              if current_key_index < max_sequence:
                  current_key_index += 1
              else:
                  current_key_index = 0
                  current_account_index += 1
      else:
          t = PrettyTable(["Name", "Type", "Available Key"])
          t.align = "l"
          for account in stm.wallet.getAccounts():
              t.add_row([
                  account["name"] or "n/a", account["type"] or "n/a",
                  account["pubkey"]
              ])
      print(t)
  
  
  @cli.command()
  @click.argument('post', nargs=1)
  @click.option('--weight', '-w', help='Vote weight (from 0.1 to 100.0)')
  @click.option('--account', '-a', help='Voter account name')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def upvote(post, account, weight, export):
      """Upvote a post/comment
  
          POST is @author/permlink
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not weight:
          weight = stm.config["default_vote_weight"]
      else:
          weight = float(weight)
          if weight > 100:
              raise ValueError("Maximum vote weight is 100.0!")
          elif weight < 0:
              raise ValueError("Minimum vote weight is 0!")
  
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      try:
          post = Comment(post, blockchain_instance=stm)
          tx = post.upvote(weight, voter=account)
          if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
              tx = stm.steemconnect.url_from_tx(tx)
          elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
              tx = stm.hivesigner.url_from_tx(tx)
      except exceptions.VotingInvalidOnArchivedPost:
          print("Post/Comment is older than 7 days! Did not upvote.")
          tx = {}
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('post', nargs=1)
  @click.option('--account', '-a', help='Account name')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def delete(post, account, export):
      """delete a post/comment
  
          POST is @author/permlink
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
  
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      try:
          post = Comment(post, blockchain_instance=stm)
          tx = post.delete(account=account)
          if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
              tx = stm.steemconnect.url_from_tx(tx)
          elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
              tx = stm.hivesigner.url_from_tx(tx)
      except exceptions.VotingInvalidOnArchivedPost:
          print("Could not delete post.")
          tx = {}
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('post', nargs=1)
  @click.option('--account', '-a', help='Downvoter account name')
  @click.option('--weight', '-w', default=100, help='Downvote weight (from 0.1 to 100.0)')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def downvote(post, account, weight, export):
      """Downvote a post/comment
  
          POST is @author/permlink
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
  
      weight = float(weight)
      if weight > 100:
          raise ValueError("Maximum downvote weight is 100.0!")
      elif weight < 0:
          raise ValueError("Minimum downvote weight is 0!")
  
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      try:
          post = Comment(post, blockchain_instance=stm)
          tx = post.downvote(weight, voter=account)
          if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
              tx = stm.steemconnect.url_from_tx(tx)
          elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
              tx = stm.hivesigner.url_from_tx(tx)
      except exceptions.VotingInvalidOnArchivedPost:
          print("Post/Comment is older than 7 days! Did not downvote.")
          tx = {}
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('to', nargs=1)
  @click.argument('amount', nargs=1)
  @click.argument('asset', nargs=1, callback=asset_callback)
  @click.argument('memo', nargs=1, required=False)
  @click.option('--account', '-a', help='Transfer from this account')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def transfer(to, amount, asset, memo, account, export):
      """Transfer SBD/HBD or STEEM/HIVE"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not bool(memo):
          memo = ''
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      tx = acc.transfer(to, amount, asset, memo)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('amount', nargs=1)
  @click.option('--account', '-a', help='Powerup from this account')
  @click.option('--to', '-t', help='Powerup this account', default=None)
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def powerup(amount, account, to, export):
      """Power up (vest STEEM/HIVE as STEEM/HIVE POWER)"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      try:
          amount = float(amount)
      except:
          amount = str(amount)
      tx = acc.transfer_to_vesting(amount, to=to)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('amount', nargs=1)
  @click.option('--account', '-a', help='Powerup from this account')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def powerdown(amount, account, export):
      """Power down (start withdrawing VESTS from Steem POWER)
  
          amount is in VESTS
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      try:
          amount = float(amount)
      except:
          amount = str(amount)
      tx = acc.withdraw_vesting(amount)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('amount', nargs=1)
  @click.argument('to_account', nargs=1)
  @click.option('--account', '-a', help='Delegate from this account')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def delegate(amount, to_account, account, export):
      """Delegate (start delegating VESTS to another account)
  
          amount is in VESTS / Steem
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      try:
          amount = float(amount)
      except:
          amount = Amount(str(amount), blockchain_instance=stm)
          if amount.symbol == stm.token_symbol and isinstance(stm, Steem):
              amount = stm.sp_to_vests(float(amount))
          elif amount.symbol == stm.token_symbol and isinstance(stm, Hive):
              amount = stm.hp_to_vests(float(amount))
  
      tx = acc.delegate_vesting_shares(to_account, amount)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.option('--account', '-a', help="List outgoing delegations from this account")
  def listdelegations(account):
      """ List all outgoing delegations from an account.
  
      The default account is used if no other account name is given as
          option to this command.
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      acc = Account(account, blockchain_instance=stm)
      pt = PrettyTable(["Delegatee", stm.vests_symbol, "%s Power" % (stm.token_symbol)])
      pt.align = "r"
      start_account = ""
      limit = 100
      stop = False
      while stop is False:
          delegations = acc.get_vesting_delegations(
              start_account=start_account, limit=limit)
          if len(delegations) < limit:
              stop = True
          if start_account != "" and len(delegations) > 0:
              # skip first entry if it was already part of the previous call
              delegations = delegations[1:]
          for deleg in delegations:
              vests = Amount(deleg['vesting_shares'], blockchain_instance=stm)
              token_power = "%.3f" % (stm.vests_to_token_power(vests))
              pt.add_row([deleg['delegatee'], str(vests), token_power])
              start_account = deleg['delegatee']
      print(pt)
  
  
  @cli.command()
  @click.argument('to', nargs=1)
  @click.option('--percentage', default=100, help='The percent of the withdraw to go to the "to" account')
  @click.option('--account', '-a', help='Powerup from this account')
  @click.option('--auto_vest', help='Set to true if the from account should receive the VESTS as'
                'VESTS, or false if it should receive them as STEEM/HIVE.', is_flag=True)
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def powerdownroute(to, percentage, account, auto_vest, export):
      """Setup a powerdown route"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      tx = acc.set_withdraw_vesting_route(to, percentage, auto_vest=auto_vest)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  @cli.command()
  @click.argument('new_recovery_account', nargs=1)
  @click.option('--account', '-a', help='Change the recovery account from this account')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def changerecovery(new_recovery_account, account, export):
      """Changes the recovery account with the owner key (needs 30 days to be active)"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      #if not unlock_wallet(stm):
      #    return
      new_recovery_account = Account(new_recovery_account, blockchain_instance=stm)
      account = Account(account, blockchain_instance=stm)
      op = operations.Change_recovery_account(**{
          'account_to_recover': account['name'],
          'new_recovery_account': new_recovery_account['name'],
          'extensions': []
      })
  
      tb = TransactionBuilder(blockchain_instance=stm)
      tb.appendOps([op])
      if stm.unsigned:
          tb.addSigningInformation(account["name"], "owner")
          tx = tb
      else:
          key = click.prompt('Owner key for %s' % account["name"], confirmation_prompt=False, hide_input=True)
          owner_key = PrivateKey(wif=key)
          tb.appendWif(str(owner_key))
          tb.sign()
          tx = tb.broadcast()
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('amount', nargs=1)
  @click.option('--account', '-a', help='Powerup from this account')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def convert(amount, account, export):
      """Convert SBD/HBD to Steem/Hive (takes a week to settle)"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      try:
          amount = float(amount)
      except:
          amount = str(amount)
      tx = acc.convert(amount)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  def changewalletpassphrase():
      """ Change wallet password
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not unlock_wallet(stm, allow_wif=False):
          return
      newpassword = None
      newpassword = click.prompt("New wallet password", confirmation_prompt=True, hide_input=True)
      if not bool(newpassword):
          print("Password cannot be empty! Quitting...")
          return
      password_storage = stm.config["password_storage"]
      if password_storage == "keyring" and is_keyring_available():
          import keyring
          keyring.set_password("beem", "wallet", newpassword)
      elif password_storage == "environment":
          print("The new wallet password can be stored in the UNLOCK invironment variable to skip password prompt!")
      stm.wallet.changePassphrase(newpassword)
  
  
  @cli.command()
  @click.argument('account', nargs=-1)
  def power(account):
      """ Shows vote power and bandwidth
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if len(account) == 0:
          if "default_account" in stm.config:
              account = [stm.config["default_account"]]
      for name in account:
          a = Account(name, blockchain_instance=stm)
          print("\n@%s" % a.name)
          a.print_info(use_table=True)
  
  
  @cli.command()
  @click.argument('account', nargs=-1)
  def balance(account):
      """ Shows balance
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if len(account) == 0:
          if "default_account" in stm.config:
              account = [stm.config["default_account"]]
      for name in account:
          a = Account(name, blockchain_instance=stm)
          print("\n@%s" % a.name)
          t = PrettyTable(["Account", stm.token_symbol, stm.backed_token_symbol, "VESTS"])
          t.align = "r"
          t.add_row([
              'Available',
              str(a.balances['available'][0]),
              str(a.balances['available'][1]),
              str(a.balances['available'][2]),
          ])
          t.add_row([
              'Rewards',
              str(a.balances['rewards'][0]),
              str(a.balances['rewards'][1]),
              str(a.balances['rewards'][2]),
          ])
          t.add_row([
              'Savings',
              str(a.balances['savings'][0]),
              str(a.balances['savings'][1]),
              'N/A',
          ])
          t.add_row([
              'TOTAL',
              str(a.balances['total'][0]),
              str(a.balances['total'][1]),
              str(a.balances['total'][2]),
          ])
          print(t)
  
  
  @cli.command()
  @click.argument('account', nargs=-1, required=False)
  def interest(account):
      """ Get information about interest payment
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          if "default_account" in stm.config:
              account = [stm.config["default_account"]]
  
      t = PrettyTable([
          "Account", "Last Interest Payment", "Next Payment",
          "Interest rate", "Interest"
      ])
      t.align = "r"
      for a in account:
          a = Account(a, blockchain_instance=stm)
          i = a.interest()
          t.add_row([
              a["name"],
              i["last_payment"],
              "in %s" % (i["next_payment_duration"]),
              "%.1f%%" % i["interest_rate"],
              "%.3f %s" % (i["interest"], stm.backed_token_symbol),
          ])
      print(t)
  
  
  @cli.command()
  @click.argument('follow-type')
  @click.option('--account', '-a', help='Get follow list for this account')
  @click.option('--limit', '-l', help='Liimts the returned accounts', default=100)
  def followlist(follow_type, account, limit):
      """ Get information about followed lists
  
      follow_type can be blog
      On Hive, follow type can also be one the following: blacklisted, follow_blacklist, muted, or follow_muted
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          if "default_account" in stm.config:
              account = [stm.config["default_account"]]
      account = Account(account, blockchain_instance=stm)
      if follow_type == "blog":
          name_list = account.get_following(limit=limit)
      else:
          name_list = account.get_follow_list(follow_type, limit=limit)
      t = PrettyTable(["index", "name"])
      t.align = "r"
      i = 0
      for name in name_list:
          i += 1
          t.add_row([str(i), name])
      print(t)
  
  
  @cli.command()
  @click.argument('account', nargs=-1, required=False)
  def follower(account):
      """ Get information about followers
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          if "default_account" in stm.config:
              account = [stm.config["default_account"]]
      for a in account:
          a = Account(a, blockchain_instance=stm)
          print("\nFollowers statistics for @%s (please wait...)" % a.name)
          followers = a.get_followers(False)
          followers.print_summarize_table(tag_type="Followers")
  
  
  @cli.command()
  @click.argument('account', nargs=-1, required=False)
  def following(account):
      """ Get information about following
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          if "default_account" in stm.config:
              account = [stm.config["default_account"]]
      for a in account:
          a = Account(a, blockchain_instance=stm)
          print("\nFollowing statistics for @%s (please wait...)" % a.name)
          following = a.get_following(False)
          following.print_summarize_table(tag_type="Following")
  
  
  @cli.command()
  @click.argument('account', nargs=-1, required=False)
  def muter(account):
      """ Get information about muter
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          if "default_account" in stm.config:
              account = [stm.config["default_account"]]
      for a in account:
          a = Account(a, blockchain_instance=stm)
          print("\nMuters statistics for @%s (please wait...)" % a.name)
          muters = a.get_muters(False)
          muters.print_summarize_table(tag_type="Muters")
  
  
  @cli.command()
  @click.argument('account', nargs=-1, required=False)
  def muting(account):
      """ Get information about muting
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          if "default_account" in stm.config:
              account = [stm.config["default_account"]]
      for a in account:
          a = Account(a, blockchain_instance=stm)
          print("\nMuting statistics for @%s (please wait...)" % a.name)
          muting = a.get_mutings(False)
          muting.print_summarize_table(tag_type="Muting")
  
  
  @cli.command()
  @click.argument('account', nargs=1, required=False)
  @click.option('--limit', '-l', help='Limits shown notifications')
  @click.option('--all', '-a', help='Show all notifications (when not set, only unread are shown)', is_flag=True, default=False)
  @click.option('--mark_as_read', '-m', help='Broadcast a mark all as read custom json', is_flag=True, default=False)
  @click.option('--replies', '-r', help='Show only replies', is_flag=True, default=False)
  @click.option('--mentions', '-t', help='Show only mentions', is_flag=True, default=False)
  @click.option('--follows', '-f', help='Show only follows', is_flag=True, default=False)
  @click.option('--votes', '-v', help='Show only upvotes', is_flag=True, default=False)
  @click.option('--reblogs', '-b', help='Show only reblogs', is_flag=True, default=False)
  @click.option('--reverse', '-s', help='Reverse sorting of notifications', is_flag=True, default=False)
  def notifications(account, limit, all, mark_as_read, replies, mentions, follows, votes, reblogs, reverse):
      """ Show notifications of an account
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if account is None or account == "":
          if "default_account" in stm.config:
              account = stm.config["default_account"]
      if mark_as_read and not unlock_wallet(stm):
          return
      if not replies and not mentions and not follows and not votes and not reblogs:
          show_all = True
      else:
          show_all = False
      account = Account(account, blockchain_instance=stm)
      t = PrettyTable(["Date", "Type", "Message"], hrules=0)
      t.align = "r"
      last_read = None
      if limit is not None:
          limit = int(limit)
      all_notifications = account.get_notifications(only_unread=not all, limit=limit)
      if reverse:
          all_notifications = all_notifications[::-1]
      for note in all_notifications:
          if not show_all:
              if note["type"] == "reblog" and not reblogs:
                  continue
              elif note["type"] == "reply" and not replies:
                  continue
              elif note["type"] == "reply_comment" and not replies:
                  continue
              elif note["type"] == "mention" and not mentions:
                  continue
              elif note["type"] == "follow" and not follows:
                  continue
              elif note["type"] == "vote" and not votes:
                  continue
          t.add_row([
              str(datetime.fromtimestamp(calendar.timegm(note["date"].timetuple()))),
              note["type"],
              note["msg"],
          ])
          last_read = note["date"]
      print(t)
      if mark_as_read:
          account.mark_notifications_as_read(last_read=last_read)
  
  
  @cli.command()
  @click.argument('account', nargs=1, required=False)
  def permissions(account):
      """ Show permissions of an account
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          if "default_account" in stm.config:
              account = stm.config["default_account"]
      account = Account(account, blockchain_instance=stm)
      t = PrettyTable(["Permission", "Threshold", "Key/Account"], hrules=0)
      t.align = "r"
      for permission in ["owner", "active", "posting"]:
          auths = []
          for type_ in ["account_auths", "key_auths"]:
              for authority in account[permission][type_]:
                  auths.append("%s (%d)" % (authority[0], authority[1]))
          t.add_row([
              permission,
              account[permission]["weight_threshold"],
              "\n".join(auths),
          ])
      print(t)
  
  
  @cli.command()
  @click.argument('foreign_account', nargs=1, required=False)
  @click.option('--permission', default="posting", help='The permission to grant (defaults to "posting")')
  @click.option('--account', '-a', help='The account to allow action for')
  @click.option('--weight', '-w', help='The weight to use instead of the (full) threshold. '
                'If the weight is smaller than the threshold, '
                'additional signatures are required')
  @click.option('--threshold', '-t', help='The permission\'s threshold that needs to be reached '
                'by signatures to be able to interact')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def allow(foreign_account, permission, account, weight, threshold, export):
      """Allow an account/key to interact with your account
  
          foreign_account: The account or key that will be allowed to interact with account.
              When not given, password will be asked, from which a public key is derived.
              This derived key will then interact with your account.
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      if permission not in ["posting", "active", "owner"]:
          print("Wrong permission, please use: posting, active or owner!")
          return
      acc = Account(account, blockchain_instance=stm)
      if not foreign_account:
          from beemgraphenebase.account import PasswordKey
          pwd = click.prompt("Password for Key Derivation", confirmation_prompt=True, hide_input=True)
          foreign_account = format(PasswordKey(account, pwd, permission).get_public(), stm.prefix)
      if threshold is not None:
          threshold = int(threshold)
      tx = acc.allow(foreign_account, weight=weight, permission=permission, threshold=threshold)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('foreign_account', nargs=1, required=False)
  @click.option('--permission', '-p', default="posting", help='The permission to grant (defaults to "posting")')
  @click.option('--account', '-a', help='The account to disallow action for')
  @click.option('--threshold', '-t', help='The permission\'s threshold that needs to be reached '
                'by signatures to be able to interact')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def disallow(foreign_account, permission, account, threshold, export):
      """Remove allowance an account/key to interact with your account"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      if permission not in ["posting", "active", "owner"]:
          print("Wrong permission, please use: posting, active or owner!")
          return
      if threshold is not None:
          threshold = int(threshold)
      acc = Account(account, blockchain_instance=stm)
      if not foreign_account:
          from beemgraphenebase.account import PasswordKey
          pwd = click.prompt("Password for Key Derivation", confirmation_prompt=True)
          foreign_account = [format(PasswordKey(account, pwd, permission).get_public(), stm.prefix)]
      tx = acc.disallow(foreign_account, permission=permission, threshold=threshold)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('creator', nargs=1, required=True)
  @click.option('--fee', help='When fee is 0 (default) a subsidized account is claimed and can be created later with create_claimed_account', default=0.0)
  @click.option('--number', '-n', help='Number of subsidized accounts to be claimed (default = 1), when fee = 0 STEEM', default=1)
  @click.option('--export', '-e', help='When set, transaction is stored in a file (should be used with number = 1)')
  def claimaccount(creator, fee, number, export):
      """Claim account for claimed account creation."""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not creator:
          creator = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      creator = Account(creator, blockchain_instance=stm)
      fee = Amount("%.3f %s" % (float(fee), stm.token_symbol), blockchain_instance=stm)
      tx = None
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.claim_account(creator, fee=fee)
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.claim_account(creator, fee=fee)
          tx = stm.hivesigner.url_from_tx(tx)
      elif float(fee) == 0:
          rc = RC(blockchain_instance=stm)
          current_costs = rc.claim_account(tx_size=200)
          current_mana = creator.get_rc_manabar()["current_mana"]
          last_mana = current_mana
          cnt = 0
          print("Current costs %.2f G RC - current mana %.2f G RC" % (current_costs / 1e9, current_mana / 1e9))
          print("Account can claim %d accounts" % (int(current_mana / current_costs)))
          while current_costs + 10 < current_mana and cnt < number:
              if cnt > 0:
                  print("Current costs %.2f G RC - current mana %.2f G RC" % (current_costs / 1e9, current_mana / 1e9))
                  tx = json.dumps(tx, indent=4)
                  print(tx)
              cnt += 1
              tx = stm.claim_account(creator, fee=fee)
              time.sleep(10)
              creator.refresh()
              current_mana = creator.get_rc_manabar()["current_mana"]
              print("Account claimed and %.2f G RC paid." % ((last_mana - current_mana) / 1e9))
              last_mana = current_mana
          if cnt == 0:
              print("Not enough RC for a claim!")
      else:
          tx = stm.claim_account(creator, fee=fee)
      if tx is not None:
          export_trx(tx, export)
          tx = json.dumps(tx, indent=4)
          print(tx)
  
  
  @cli.command()
  @click.argument('account', nargs=1, required=True)
  @click.option('--owner', help='Main owner public key - when not given, a passphrase is used to create keys.')
  @click.option('--active', help='Active public key - when not given, a passphrase is used to create keys.')
  @click.option('--posting', help='posting public key - when not given, a passphrase is used to create keys.')
  @click.option('--memo', help='Memo public key - when not given, a passphrase is used to create keys.')
  @click.option('--import-pub', '-i', help='Load public keys from file.')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def changekeys(account, owner, active, posting, memo, import_pub, export):
      """Changes all keys for the specified account
      Keys are given in their public form.
      Asks for the owner key for broadcasting the op to the chain."""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      account = Account(account, blockchain_instance=stm)
  
      if import_pub and import_pub != "":
          owner, active, posting, memo = import_pubkeys(import_pub)
  
      if owner is None and active is None and memo is None and posting is None:
          raise ValueError("All pubkeys are None or empty!")
      if owner == "" or owner is None:
          owner = account["owner"]["key_auths"][0][0]
      if active == "" or active is None:
          active = account["active"]["key_auths"][0][0]
      if posting == "" or posting is None:
          posting = account["posting"]["key_auths"][0][0]
      if memo == "" or memo is None:
          memo = account["memo_key"]
  
      t = PrettyTable(["Key", "Value"])
      t.align = "l"
      t.add_row(["account", account["name"]])
      t.add_row(["new owner pubkey", str(owner)])
      t.add_row(["new active pubkey", str(active)])
      t.add_row(["new posting pubkey", str(posting)])
      t.add_row(["new memo pubkey", str(memo)])
      print(t)
      if not stm.unsigned:
          wif = click.prompt('Owner key for %s' % account["name"], confirmation_prompt=False, hide_input=True)
          stm.wallet.setKeys([wif])
  
      tx = stm.update_account(account, owner_key=owner, active_key=active,
                              posting_key=posting, memo_key=memo, password=None)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('accountname', nargs=1, required=True)
  @click.option('--account', '-a', help='Account that pays the fee or uses account tickets')
  @click.option('--owner', help='Main public owner key - when not given, a passphrase is used to create keys.')
  @click.option('--active', help='Active public key - when not given, a passphrase is used to create keys.')
  @click.option('--memo', help='Memo public key - when not given, a passphrase is used to create keys.')
  @click.option('--posting', help='posting public key - when not given, a passphrase is used to create keys.')
  @click.option('--wif', '-w', help='Defines how many times the password is replaced by its WIF representation for password based keys (default = 0).', default=0)
  @click.option('--create-claimed-account', '-c', help='Instead of paying the account creation fee a subsidized account is created.', is_flag=True, default=False)
  @click.option('--import-pub', '-i', help='Load public keys from file.')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def newaccount(accountname, account, owner, active, memo, posting, wif, create_claimed_account, import_pub, export):
      """Create a new account
         Default setting is that a fee is payed for account creation
         Use --create-claimed-account for free account creation
  
         Please use keygen and set public keys
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      if import_pub and import_pub != "":
          owner, active, posting, memo = import_pubkeys(import_pub)
          if create_claimed_account:
              tx = stm.create_claimed_account(accountname, creator=acc, owner_key=owner, active_key=active, memo_key=memo, posting_key=posting)
          else:
              tx = stm.create_account(accountname, creator=acc, owner_key=owner, active_key=active, memo_key=memo, posting_key=posting)
      elif owner is None or active is None or memo is None or posting is None:
          import_password = click.prompt("Keys were not given - Passphrase is used to create keys\n New Account Passphrase", confirmation_prompt=True, hide_input=True)
          if not import_password:
              print("You cannot chose an empty password")
              return
          password = generate_password(import_password, wif)
          if create_claimed_account:
              tx = stm.create_claimed_account(accountname, creator=acc, password=password)
          else:
              tx = stm.create_account(accountname, creator=acc, password=password)
      else:
          if create_claimed_account:
              tx = stm.create_claimed_account(accountname, creator=acc, owner_key=owner, active_key=active, memo_key=memo, posting_key=posting)
          else:
              tx = stm.create_account(accountname, creator=acc, owner_key=owner, active_key=active, memo_key=memo, posting_key=posting)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('variable', nargs=1, required=False)
  @click.argument('value', nargs=1, required=False)
  @click.option('--account', '-a', help='setprofile as this user')
  @click.option('--pair', '-p', help='"Key=Value" pairs', multiple=True)
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def setprofile(variable, value, account, pair, export):
      """Set a variable in an account\'s profile"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      keys = []
      values = []
      if pair:
          for p in pair:
              key, value = p.split("=")
              keys.append(key)
              values.append(value)
      if variable and value:
          keys.append(variable)
          values.append(value)
  
      profile = Profile(keys, values)
  
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
  
      json_metadata = Profile(acc["json_metadata"] if acc["json_metadata"] else {})
      json_metadata.update(profile)
      tx = acc.update_account_profile(json_metadata)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('variable', nargs=-1, required=True)
  @click.option('--account', '-a', help='delprofile as this user')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def delprofile(variable, account, export):
      """Delete a variable in an account\'s profile"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
  
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      json_metadata = Profile(acc["json_metadata"])
  
      for var in variable:
          json_metadata.remove(var)
  
      tx = acc.update_account_profile(json_metadata)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('account', nargs=1, required=True)
  @click.option('--roles', '-r', help='Import specified keys (owner, active, posting, memo).', default=["active", "posting", "memo"])
  @click.option('--import-coldcard', '-i', help='Text file with a BIP85 WIF generated by a coldcard. The imported WIF is used as passphrase')
  @click.option('--wif', '-w', help='Defines how many times the password is replaced by its WIF representation for password based keys (default = 0 or 1 when importing a cold card wif).')
  def importaccount(account, roles, import_coldcard, wif):
      """Import an account using a passphrase"""
      from beemgraphenebase.account import PasswordKey
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not unlock_wallet(stm):
          return
      account = Account(account, blockchain_instance=stm)
      imported = False
      if import_coldcard is None:
          password = click.prompt("Account Passphrase", confirmation_prompt=False, hide_input=True)
          if not password:
              print("You cannot chose an empty Passphrase")
              return
      else:
          password, path = import_coldcard_wif(import_coldcard)
      if wif is not None:
          wif = int(wif)
      elif import_coldcard is not None:
          wif = 1
      else:
          wif = 0
  
      password = generate_password(password, wif)
  
      if "owner" in roles:
          owner_key = PasswordKey(account["name"], password, role="owner")
          owner_pubkey = format(owner_key.get_public_key(), stm.prefix)
          if owner_pubkey in [x[0] for x in account["owner"]["key_auths"]]:
              print("Importing owner key!")
              owner_privkey = owner_key.get_private_key()
              stm.wallet.addPrivateKey(owner_privkey)
              imported = True
  
      if "active" in roles:
          active_key = PasswordKey(account["name"], password, role="active")
          active_pubkey = format(active_key.get_public_key(), stm.prefix)
          if active_pubkey in [x[0] for x in account["active"]["key_auths"]]:
              print("Importing active key!")
              active_privkey = active_key.get_private_key()
              stm.wallet.addPrivateKey(active_privkey)
              imported = True
  
      if "posting" in roles:
          posting_key = PasswordKey(account["name"], password, role="posting")
          posting_pubkey = format(posting_key.get_public_key(), stm.prefix)
          if posting_pubkey in [
              x[0] for x in account["posting"]["key_auths"]
          ]:
              print("Importing posting key!")
              posting_privkey = posting_key.get_private_key()
              stm.wallet.addPrivateKey(posting_privkey)
              imported = True
  
      if "memo" in roles:
          memo_key = PasswordKey(account["name"], password, role="memo")
          memo_pubkey = format(memo_key.get_public_key(), stm.prefix)
          if memo_pubkey == account["memo_key"]:
              print("Importing memo key!")
              memo_privkey = memo_key.get_private_key()
              stm.wallet.addPrivateKey(memo_privkey)
              imported = True
  
      if not imported:
          print("No matching key(s) found. Password correct?")
  
  
  @cli.command()
  @click.option('--account', '-a', help='The account to updatememokey action for')
  @click.option('--key', help='The new memo key')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def updatememokey(account, key, export):
      """Update an account\'s memo key"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      if not key:
          from beemgraphenebase.account import PasswordKey
          pwd = click.prompt("Password for Memo Key Derivation", confirmation_prompt=True, hide_input=True)
          memo_key = PasswordKey(account, pwd, "memo")
          key = format(memo_key.get_public_key(), stm.prefix)
          memo_privkey = memo_key.get_private_key()
          if not stm.nobroadcast:
              stm.wallet.addPrivateKey(memo_privkey)
      tx = acc.update_memo_key(key)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('authorperm', nargs=1)
  @click.argument('beneficiaries', nargs=-1)
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def beneficiaries(authorperm, beneficiaries, export):
      """Set beneficaries"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      c = Comment(authorperm, blockchain_instance=stm)
      account = c["author"]
  
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
  
      options = {"author": c["author"],
                 "permlink": c["permlink"],
                 "max_accepted_payout": c["max_accepted_payout"],
                 "allow_votes": c["allow_votes"],
                 "allow_curation_rewards": c["allow_curation_rewards"]}
      if "percent_steem_dollars" in c:
          options["percent_steem_dollars"] = c["percent_steem_dollars"]
      elif "percent_hbd" in c:
          options["percent_hbd"] = c["percent_hbd"]
  
      if isinstance(beneficiaries, tuple) and len(beneficiaries) == 1:
          beneficiaries = beneficiaries[0].split(",")
      beneficiaries_list_sorted = derive_beneficiaries(beneficiaries)
      for b in beneficiaries_list_sorted:
          Account(b["account"], blockchain_instance=stm)
      tx = stm.comment_options(options, authorperm, beneficiaries_list_sorted, account=account)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('message_file', nargs=1, required=False)
  @click.option('--account', '-a', help='Account which should sign')
  @click.option('--verify', '-v', help='Verify a message instead of signing it', is_flag=True, default=False)
  def message(message_file, account, verify):
      """Sign and verify a message
  
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if message_file is not None:
          with open(message_file) as f:
              message = f.read()
      elif verify:
          print("Please store the signed message into a text file and append the file path to beempy message -v")
          return
      else:
          message = input("Enter message: ")
      m = Message(message, blockchain_instance=stm)
      if verify:
          if m.verify():
              print("Could verify message!")
          else:
              print("Could not verify message!")
      else:
          if not unlock_wallet(stm):
              return
          out = m.sign(account)
      if message_file is not None:
          with open(message_file, "w", encoding="utf-8") as f:
              f.write(out)
      else:
          print(out)
  
  
  @cli.command()
  @click.argument('memo', nargs=-1)
  @click.option('--account', '-a', help='Account which decrypts the memo with its memo key')
  @click.option('--output', '-o', help='Output file name. Result is stored, when set instead of printed.')
  @click.option('--info', '-i', help='Shows information about public keys and used nonce', is_flag=True, default=False)
  @click.option('--text', '-t', help='Reads the text file content', is_flag=True, default=False)
  @click.option('--binary', '-b', help='Reads the binary file content', is_flag=True, default=False)
  def decrypt(memo, account, output, info, text, binary):
      """decrypt a (or more than one) decrypted memo/file with your memo key
  
      """
      if text and binary:
          print("You cannot set text and binary!")
          return
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      m = Memo(from_account=None, to_account=account, blockchain_instance=stm)
  
      if not unlock_wallet(stm):
          return
      for entry in memo:
          print("\n")
          if not binary and info:
              from_key, to_key, nonce = m.extract_decrypt_memo_data(entry)
              try:
                  from_account = stm.wallet.getAccountFromPublicKey(str(from_key))
                  to_account = stm.wallet.getAccountFromPublicKey(str(to_key))
                  if from_account is not None:
                      print("from: %s" % str(from_account))
                  else:
                      print("from: %s" % str(from_key))
                  if to_account is not None:
                      print("to: %s" % str(to_account))
                  else:
                      print("to: %s" % str(to_key))
                  print("nonce: %s" % nonce)
              except:
                  print("from: %s" % str(from_key))
                  print("to: %s" % str(to_key))
                  print("nonce: %s" % nonce)
          if text:
              with open(entry) as f:
                  message = f.read()
          elif binary:
              if output is None:
                  output = entry + ".dec"
              ret = m.decrypt_binary(entry, output, buffer_size=2048)
              if info:
                  t = PrettyTable(["Key", "Value"])
                  t.align = "l"
                  t.add_row(["file", entry])
                  for key in ret:
                      t.add_row([key, ret[key]])
                  print(t)
          else:
              message = entry
          if text:
              out = m.decrypt(message)
              if output is None:
                  output = entry
              with open(output, "w", encoding="utf-8") as f:
                  f.write(out)
          elif not binary:
              out = m.decrypt(message)
              if info:
                  print("message: %s" % out)
              if output:
                  with open(output, "w", encoding="utf-8") as f:
                      f.write(out)
              elif not info:
                  print(out)
  
  
  @cli.command()
  @click.argument('receiver', nargs=1)
  @click.argument('memo', nargs=-1)
  @click.option('--account', '-a', help='Account which encrypts the memo with its memo key')
  @click.option('--output', '-o', help='Output file name. Result is stored, when set instead of printed.')
  @click.option('--text', '-t', help='Reads the text file content', is_flag=True, default=False)
  @click.option('--binary', '-b', help='Reads the binary file content', is_flag=True, default=False)
  def encrypt(receiver, memo, account, output, text, binary):
      """encrypt a (or more than one) memo text/file with the your memo key
  
      """
      if text and binary:
          print("You cannot set text and binary!")
          return
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      m = Memo(from_account=account, to_account=receiver, blockchain_instance=stm)
      if not unlock_wallet(stm):
          return
      for entry in memo:
          print("\n")
          if text:
              with open(entry) as f:
                  message = f.read()
              if message[0] == "#":
                  message = message[1:]
          elif binary:
              if output is None:
                  output = entry + ".enc"
              m.encrypt_binary(entry, output, buffer_size=2048)
          else:
              message = entry
              if message[0] == "#":
                  message = message[1:]
  
          if text:
              out = m.encrypt(message)["message"]
              if output is None:
                  output = entry
              with open(output, "w", encoding="utf-8") as f:
                  f.write(out)
          elif not binary:
              out = m.encrypt(message)["message"]
              if output is None:
                  print(out)
              else:
                  with open(output, "w", encoding="utf-8") as f:
                      f.write(out)
  
  
  @cli.command()
  @click.argument('image', nargs=1)
  @click.option('--account', '-a', help='Account name')
  @click.option('--image-name', '-n', help='Image name')
  def uploadimage(image, account, image_name):
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      iu = ImageUploader(blockchain_instance=stm)
      tx = iu.upload(image, account, image_name)
      if image_name is None:
          print("![](%s)" % tx["url"])
      else:
          print("![%s](%s)" % (image_name, tx["url"]))
  
  @cli.command()
  @click.argument('permlink', nargs=-1)
  @click.option('--account', '-a', help='Account are you posting from')
  @click.option('--save', '-s', help="Saves markdown in current directoy as date_permlink.md", is_flag=True, default=False)
  @click.option('--export', '-e', default=None, help="Export markdown to given a md-file name")
  def download(permlink, account, save, export):
      """Download body with yaml header"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if account is None:
          account = stm.config["default_account"]
      account = Account(account, blockchain_instance=stm)
      if len(permlink) == 0:
          permlink = []
          progress_length = account.virtual_op_count()
          print("Reading post history...")
          last_index = 0
          with click.progressbar(length=progress_length) as bar:
              for h in account.history(only_ops=["comment"]):
                  if h["parent_author"] != '':
                      continue
                  if h["author"] != account["name"]:
                      continue
                  if h["permlink"] in permlink:
                      continue
                  else:
                      permlink.append(h["permlink"])
                      bar.update(h["index"] - last_index)
                      last_index = h["index"]
  
      for p in permlink:
          if p[0] == "@":
              authorperm = p
          elif os.path.exists(p):
              with open(p) as f:
                  content = f.read()
              body, parameter = seperate_yaml_dict_from_body(content)
              if "author" in parameter and "permlink" in parameter:
                  authorperm = construct_authorperm(parameter["author"], parameter["permlink"])
              else:
                  authorperm = construct_authorperm(account["name"], p)
          else:
              authorperm = construct_authorperm(account["name"], p)
          if len(permlink) > 1:
              print(authorperm)
          comment = Comment(authorperm, blockchain_instance=stm)
          if comment.parent_author != "" and comment.parent_permlink != "":
              reply_identifier = construct_authorperm(comment.parent_author, comment.parent_permlink)
          else:
              reply_identifier = None
  
          yaml_prefix = '---\n'
          if comment["title"] != "":
              yaml_prefix += 'title: "%s"\n' % comment["title"]
          yaml_prefix += 'permlink: %s\n' % comment["permlink"]
          yaml_prefix += 'author: %s\n' % comment["author"]
          if "author" in comment.json_metadata:
              yaml_prefix += 'authored by: %s\n' % comment.json_metadata["author"]
          if "description" in comment.json_metadata:
              yaml_prefix += 'description: "%s"\n' % comment.json_metadata["description"]
          if "canonical_url" in comment.json_metadata:
              yaml_prefix += 'canonical_url: %s\n' % comment.json_metadata["canonical_url"]
          if "app" in comment.json_metadata:
              yaml_prefix += 'app: %s\n' % comment.json_metadata["app"]
          if "last_update" in comment.json():
              yaml_prefix += 'last_update: %s\n' % comment.json()["last_update"]
          else:
              yaml_prefix += 'last_update: %s\n' % comment.json()["updated"]
          yaml_prefix += 'max_accepted_payout: %s\n' % str(comment["max_accepted_payout"])
          if "percent_steem_dollars" in comment:
              yaml_prefix += 'percent_steem_dollars: %s\n' %  str(comment["percent_steem_dollars"])
          elif "percent_hbd" in comment:
              yaml_prefix += 'percent_hbd: %s\n' %  str(comment["percent_hbd"])
          if "tags" in comment.json_metadata:
              if len(comment.json_metadata["tags"]) > 0 and comment["category"] != comment.json_metadata["tags"][0] and len(comment["category"]) > 0:
                  yaml_prefix += 'community: %s\n' % comment["category"]
              yaml_prefix += 'tags: %s\n' % ",".join(comment.json_metadata["tags"])
          if "beneficiaries" in comment:
              beneficiaries = []
              for b in comment["beneficiaries"]:
                  beneficiaries.append("%s:%.2f%%" % (b["account"], b["weight"] / 10000 * 100))
              if len(beneficiaries) > 0:
                  yaml_prefix += 'beneficiaries: %s\n' % ",".join(beneficiaries)
          if reply_identifier is not None:
              yaml_prefix += 'reply_identifier: %s\n' % reply_identifier
          yaml_prefix += '---\n'
          if save or export is not None:
              if export is None or len(permlink) > 0:
                  export = comment.json()["created"].replace(":", "-") + "_" + comment["permlink"] + ".md"
              if export[-3:] != ".md":
                  export += ".md"
  
              with open(export, "w", encoding="utf-8") as f:
                  f.write(yaml_prefix + comment["body"])
          else:
              print(yaml_prefix + comment["body"])
  
  
  @cli.command()
  @click.argument('markdown-file', nargs=1)
  @click.option('--account', '-a', help='Account are you posting from')
  @click.option('--title', '-t', help='Title of the post')
  @click.option('--tags', '-g', help='A komma separated list of tags to go with the post.')
  @click.option('--community', '-c', help=' Name of the community (optional)')
  @click.option('--beneficiaries', '-b', help='Post beneficiaries (komma separated, e.g. a:10%,b:20%)')
  @click.option('--percent-steem-dollars', '-d', help='50% SBD /50% SP is 10000 (default), 100% SP is 0')
  @click.option('--percent-hbd', '-h', help='50% HBD /50% HP is 10000 (default), 100% HP is 0')
  @click.option('--max-accepted-payout', '-m', help='Default is 1000000.000 [SBD]')
  @click.option('--no-parse-body', '-n', help='Disable parsing of links, tags and images', is_flag=True, default=False)
  def createpost(markdown_file, account, title, tags, community, beneficiaries, percent_steem_dollars, percent_hbd, max_accepted_payout, no_parse_body):
      """Creates a new markdown file with YAML header"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
  
      if account is None:
          account = input("author: ")
      if title is None:
          title = input("title: ")
      if tags is None:
          tags = input("tags (comma seperated): ")
      if community is None:
          community_found = False
          while not community_found:
              community = input("community account (name or title): ")
              try:
                  community = Community(community)
              except:
                  c = Communities(limit=1000)
                  comm_cand = c.search_title(community)
                  if len(comm_cand) == 0:
                      print("No community could be found!")
                      continue
                  print(comm_cand.printAsTable())
                  index = input("Enter community Nr:")
                  if int(index) - 1 >= len(comm_cand):
                      continue
                  community = comm_cand[int(index) - 1]
              ret = input("Selected community: %s - %s [yes/no]? " % (community["name"], community["title"]))
              if ret in ["y", "yes"]:
                  community_found = True
          community = community["name"]
  
      if beneficiaries is None:
          beneficiaries = input("beneficiaries (komma separated, e.g. a:10%,b:20%) [return to skip]: ")
      if percent_steem_dollars is None and percent_hbd is None:
          ret = None
          while ret is None:
              ret = input("50% or 100% Steem/Hive Power as post reward [50 or 100]? ")
              if ret not in ["50", "100"]:
                  ret = None
          if ret == "50":
              percent_steem_dollars = 10000
              percent_hbd = 10000
          else:
              percent_steem_dollars = 0
              percent_hbd = 0
      elif percent_steem_dollars is not None and percent_hbd is not None:
          raise ValueError("percent_hbd and percent_steem_dollars cannot be both set.")
      elif percent_steem_dollars is None:
          percent_steem_dollars = percent_hbd
      elif percent_hbd is None:
          percent_hbd = percent_steem_dollars
  
      if max_accepted_payout is None:
          max_accepted_payout = input("max accepted payout [return to skip]: ")
      yaml_prefix = '---\n'
      yaml_prefix += 'title: "%s"\n' % title
      yaml_prefix += 'author: %s\n' % account
      yaml_prefix += 'tags: %s\n' % tags
      if stm.is_hive:
          yaml_prefix += 'percent_hbd: %d\n' % percent_hbd
      else:
          yaml_prefix += 'percent_steem_dollars: %d\n' % percent_steem_dollars
      if community is not None and community != "":
          yaml_prefix += 'community: %s\n' % community
      if beneficiaries is not None and beneficiaries != "":
          yaml_prefix += 'beneficiaries: %s\n' % beneficiaries
      if max_accepted_payout is not None and max_accepted_payout != "":
          yaml_prefix += 'max_accepted_payout: %s\n' % max_accepted_payout
      yaml_prefix += '---\n'
      with open(markdown_file, "w", encoding="utf-8") as f:
          f.write(yaml_prefix)
  
  
  @cli.command()
  @click.argument('markdown-file', nargs=1)
  @click.option('--account', '-a', help='Account are you posting from')
  @click.option('--title', '-t', help='Title of the post')
  @click.option('--permlink', '-p', help='Manually set the permlink (optional)')
  @click.option('--tags', '-g', help='A komma separated list of tags to go with the post.')
  @click.option('--reply-identifier', '-r', help=' Identifier of the parent post/comment, when set a comment is broadcasted')
  @click.option('--community', '-c', help=' Name of the community (optional)')
  @click.option('--canonical-url', '-u', help='Canonical url, can also set to https://hive.blog or https://peakd.com (optional)')
  @click.option('--beneficiaries', '-b', help='Post beneficiaries (komma separated, e.g. a:10%,b:20%)')
  @click.option('--percent-steem-dollars', '-d', help='50% SBD /50% SP is 10000 (default), 100% SP is 0')
  @click.option('--percent-hbd', '-h', help='50% SBD /50% SP is 10000 (default), 100% SP is 0')
  @click.option('--max-accepted-payout', '-m', help='Default is 1000000.000 [SBD]')
  @click.option('--no-parse-body', '-n', help='Disable parsing of links, tags and images', is_flag=True, default=False)
  @click.option('--no-patch-on-edit', '-e', help='Disable patch posting on edits (when the permlink already exists)', is_flag=True, default=False)
  @click.option('--export', help='When set, transaction is stored in a file')
  def post(markdown_file, account, title, permlink, tags, reply_identifier, community, canonical_url, beneficiaries, percent_steem_dollars, percent_hbd, max_accepted_payout, no_parse_body, no_patch_on_edit, export):
      """broadcasts a post/comment. All image links which links to a file will be uploaded.
      The yaml header can contain:
  
      ---
      title: your title
      tags: tag1,tag2
      community: hive-100000
      beneficiaries: beempy:5%,holger80:5%
      ---
  
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
  
      with open(markdown_file) as f:
          content = f.read()
      body, parameter = seperate_yaml_dict_from_body(content)
      if title is not None:
          parameter["title"] = title
      if account is not None:
          parameter["author"] = account
      if tags is not None:
          parameter["tags"] = tags
      if permlink is not None:
          parameter["permlink"] = permlink
      if beneficiaries is not None:
          parameter["beneficiaries"] = beneficiaries
      if community is not None:
          parameter["community"] = community
      if reply_identifier is not None:
          parameter["reply_identifier"] = reply_identifier
      if percent_steem_dollars is not None:
          parameter["percent_steem_dollars"] = percent_steem_dollars
      elif "percent-steem-dollars" in parameter:
          parameter["percent_steem_dollars"] = parameter["percent-steem-dollars"]
      if percent_hbd is not None:
          parameter["percent_hbd"] = percent_hbd
      elif "percent-hbd" in parameter:
          parameter["percent_hbd"] = parameter["percent-hbd"]
      if max_accepted_payout is not None:
          parameter["max_accepted_payout"] = max_accepted_payout
      elif "max-accepted-payout" in parameter:
          parameter["max_accepted_payout"] = parameter["max-accepted-payout"]
  
      if canonical_url is not None:
          parameter["canonical_url"] = canonical_url
  
      if not unlock_wallet(stm):
          return
      tags = None
      if "tags" in parameter:
          tags = derive_tags(parameter["tags"])
      title = ""
      if "title" in parameter:
          title = parameter["title"]
      if "author" in parameter:
          author = parameter["author"]
      else:
          author = stm.config["default_account"]
      permlink = None
      if "permlink" in parameter:
          permlink = parameter["permlink"]
      reply_identifier = None
      if "reply_identifier" in parameter:
          reply_identifier = parameter["reply_identifier"]
      community = None
      if "community" in parameter:
          community = parameter["community"]
      if "parse_body" in parameter:
          parse_body = bool(parameter["parse_body"])
      else:
          parse_body = not no_parse_body
      max_accepted_payout = None
  
      percent_steem_dollars = None
      if "percent_steem_dollars" in parameter:
          percent_steem_dollars = parameter["percent_steem_dollars"]
      percent_hbd = None
      if "percent_hbd" in parameter:
          percent_hbd = parameter["percent_hbd"]
      max_accepted_payout = None
      if "max_accepted_payout" in parameter:
          max_accepted_payout = parameter["max_accepted_payout"]
      comment_options = None
      if max_accepted_payout is not None or percent_steem_dollars is not None or percent_hbd is not None:
          comment_options = {}
      if max_accepted_payout is not None:
          if stm.backed_token_symbol not in max_accepted_payout:
              max_accepted_payout = str(Amount(float(max_accepted_payout), stm.backed_token_symbol, blockchain_instance=stm))
          comment_options["max_accepted_payout"] = max_accepted_payout
      if percent_hbd is not None and stm.is_hive:
          comment_options["percent_hbd"] = percent_hbd
      elif percent_steem_dollars is not None and stm.is_hive:
          comment_options["percent_hbd"] = percent_steem_dollars
      elif percent_steem_dollars is not None:
          comment_options["percent_steem_dollars"] = percent_steem_dollars
      elif percent_hbd is not None:
          comment_options["percent_steem_dollars"] = percent_hbd
      beneficiaries = None
      if "beneficiaries" in parameter:
          beneficiaries = derive_beneficiaries(parameter["beneficiaries"])
          for b in beneficiaries:
              Account(b["account"], blockchain_instance=stm)
  
  
      if permlink is not None:
          try:
              comment = Comment(construct_authorperm(author, permlink), blockchain_instance=stm)
          except:
              comment = None
      else:
          comment = None
  
      iu = ImageUploader(blockchain_instance=stm)
      for link in list(re.findall(r'!\[[^"\'@\]\(]*\]\([^"\'@\(\)]*\.(?:png|jpg|jpeg|gif|png|svg)\)', body)):
          image = link.split("(")[1].split(")")[0]
          image_name = link.split("![")[1].split("]")[0]
          if image[:4] == "http":
              continue
          if stm.unsigned:
              continue
          basepath = os.path.dirname(markdown_file)
          if os.path.exists(image):
              tx = iu.upload(image, author, image_name)
              body = body.replace(image, tx["url"])
          elif os.path.exists(os.path.join(basepath, image)):
              tx = iu.upload(image, author, image_name)
              body = body.replace(image, tx["url"])
  
      if comment is None and permlink is None and reply_identifier is None:
          permlink = derive_permlink(title, with_suffix=False)
          try:
              comment = Comment(construct_authorperm(author, permlink), blockchain_instance=stm)
          except:
              comment = None
      if comment is None:
          json_metadata = {}
      else:
          json_metadata = comment.json_metadata
      if "authored_by" in parameter:
          json_metadata["authored_by"] = parameter["authored_by"]
      if "description" in parameter:
          json_metadata["description"] = parameter["description"]
      if "canonical_url" in parameter:
          json_metadata["canonical_url"] = parameter["canonical_url"]
      else:
          json_metadata["canonical_url"] = stm.config["default_canonical_url"] or "https://hive.blog"
  
      if "canonical_url" in json_metadata and json_metadata["canonical_url"].find("@") < 0:
          if json_metadata["canonical_url"][-1] != "/":
                  json_metadata["canonical_url"] += "/"
          if json_metadata["canonical_url"][:8] != 'https://':
              json_metadata["canonical_url"] = 'https://' + json_metadata["canonical_url"]
          if community is None:
              json_metadata["canonical_url"] += tags[0] + "/@" + author + "/" + permlink
          else:
              json_metadata["canonical_url"] += community + "/@" + author + "/" + permlink
  
      if comment is None or no_patch_on_edit:
  
          if reply_identifier is None and (len(tags) == 0 or tags is None):
              raise ValueError("Tags must not be empty!")
          tx = stm.post(title, body, author=author, permlink=permlink, reply_identifier=reply_identifier, community=community,
                        tags=tags, json_metadata=json_metadata, comment_options=comment_options, beneficiaries=beneficiaries, parse_body=parse_body,
                        app='beempy/%s' % (__version__))
      else:
          patch_text = make_patch(comment.body, body)
          if patch_text == "":
              print("No changes on post body detected.")
          else:
              print(patch_text)
          edit_ok = click.prompt("Should I broadcast %s [y/n]" % (str(permlink)))
          if edit_ok not in ["y", "ye", "yes"]:
              return
          tx = stm.post(title, patch_text, author=author, permlink=permlink, reply_identifier=reply_identifier, community=community,
                        tags=tags, json_metadata=json_metadata, parse_body=False, app='beempy/%s' % (__version__))
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('authorperm', nargs=1)
  @click.argument('body', nargs=1)
  @click.option('--account', '-a', help='Account are you posting from')
  @click.option('--title', '-t', help='Title of the post')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def reply(authorperm, body, account, title, export):
      """replies to a comment"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
  
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
  
      if title is None:
          title = ""
      tx = stm.post(title, body, json_metadata=None, author=account, reply_identifier=authorperm,
                    app='beempy/%s' % (__version__))
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('witness', nargs=1)
  @click.option('--account', '-a', help='Your account')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def approvewitness(witness, account, export):
      """Approve a witnesses"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      tx = acc.approvewitness(witness, approve=True)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('witness', nargs=1)
  @click.option('--account', '-a', help='Your account')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def disapprovewitness(witness, account, export):
      """Disapprove a witnesses"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      tx = acc.disapprovewitness(witness)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('proxy', nargs=1)
  @click.option('--account', '-a', help='Your account')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def setproxy(proxy, account, export):
      """Set your witness/proposal system proxy"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      tx = acc.setproxy(proxy, account)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.option('--account', '-a', help='Your account')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def delproxy(account, export):
      """Delete your witness/proposal system proxy"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      tx = acc.setproxy('', account)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.option('--file', '-i', help='Load transaction from file. If "-", read from stdin (defaults to "-")')
  @click.option('--outfile', '-o', help='Load transaction from file. If "-", read from stdin (defaults to "-")')
  def sign(file, outfile):
      """Sign a provided transaction with available and required keys"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not unlock_wallet(stm):
          return
      if file and file != "-":
          if not os.path.isfile(file):
              raise Exception("File %s does not exist!" % file)
          with open(file) as fp:
              tx = fp.read()
          if tx.find('\0') > 0:
              with open(file, encoding='utf-16') as fp:
                  tx = fp.read()
      else:
          tx = click.get_text_stream('stdin')
      tx = ast.literal_eval(tx)
      tx = stm.sign(tx, reconstruct_tx=False)
      tx = json.dumps(tx, indent=4)
      if outfile and outfile != "-":
          with open(outfile, 'w') as fp:
              fp.write(tx)
      else:
          print(tx)
  
  
  @cli.command()
  @click.option('--file', '-f', help='Load transaction from file. If "-", read from stdin (defaults to "-")')
  def broadcast(file):
      """broadcast a signed transaction"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if file and file != "-":
          if not os.path.isfile(file):
              raise Exception("File %s does not exist!" % file)
          with open(file) as fp:
              tx = fp.read()
          if tx.find('\0') > 0:
              with open(file, encoding='utf-16') as fp:
                  tx = fp.read()
      else:
          tx = click.get_text_stream('stdin')
      tx = ast.literal_eval(tx)
      tx = stm.broadcast(tx)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  @cli.command()
  @click.option('--lines', '-n', help='Defines how many ops should be shown', default=10)
  @click.option('--head', '-h', help='Stream mode: When set, it is set to head (default is irreversible)', is_flag=True, default=False)
  @click.option('--table', '-t', help='Output as table', is_flag=True, default=False)
  @click.option('--follow', '-f', help='Constantly stream output', is_flag=True, default=False)
  def stream(lines, head, table, follow):
      """ Stream operations
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      mode = "irreversible"
      if head:
          mode = "head"
      b = Blockchain(mode=mode, blockchain_instance=stm)
      op_count = 0
      if table:
          import pprint
          t = PrettyTable(["blocknum", "trx_num", "type", "content"])
          t.align = "l"
          t._max_width = {"content" : 80}
          last_block_num = 0
          for ops in b.stream(raw_ops=False):
              op_count += 1
              ops.pop("_id")
              block_num = ops.pop("block_num")
              ops_type = ops.pop("type")
              if last_block_num == 0:
                  last_block_num = block_num
              trx_num = ops.pop("trx_num")
              for key in ops:
                  if isinstance(ops[key], dict) and "nai" in ops[key]:
                      ops[key] = str(Amount(ops[key], blockchain_instance=stm))
                  elif key == "timestamp":
                      ops[key] = formatTimeString(ops[key])
              # value = json.dumps(ops, indent=4)
              if last_block_num < block_num:
                  print(t)
                  t = PrettyTable(["blocknum", "trx_num", "type", "content"])
                  t.align = "l"
                  t._max_width = {"content" : 80}
                  last_block_num = block_num
              content = ops
              if ops_type == "custom_json":
                  content = ops["id"]
              elif ops_type == "vote":
                  content = "%.2f%% @%s/%s - %s" % (ops["weight"] / 100, ops["author"], ops["permlink"][:30], ops["voter"])
              elif ops_type == "transfer":
                  content = "%s: @%s -> @%s" % (str(ops["amount"]), ops["from"], ops["to"])
              elif ops_type == "transfer_to_vesting":
                  content = "%s: @%s -> @%s" % (str(ops["amount"]), ops["from"], ops["to"])
              t.add_row([str(block_num), str(trx_num), ops_type, content])
              if op_count >= lines and not follow:
                  print(t)
                  return
      else:
  
          import pprint
          for ops in b.stream(raw_ops=True):
              op_count += 1
              ops["timestamp"] = formatTimeString(ops["timestamp"])
              pprint.pprint(ops)
              if op_count >= lines and not follow:
                  return
  
  @cli.command()
  @click.option('--sbd-to-steem', help='Show ticker in SBD/STEEM', is_flag=True, default=False)
  @click.option('--hbd-to-hive', '-i', help='Show ticker in HBD/HIVE', is_flag=True, default=False)
  def ticker(sbd_to_steem, hbd_to_hive):
      """ Show ticker
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      t = PrettyTable(["Key", "Value"])
      t.align = "l"
      market = Market(blockchain_instance=stm)
      ticker = market.ticker()
      for key in ticker:
          if key in ["highest_bid", "latest", "lowest_ask"] and (sbd_to_steem or hbd_to_hive):
              t.add_row([key, str(ticker[key].as_base(stm.backed_token_symbol))])
          elif key in "percent_change" and (sbd_to_steem or hbd_to_hive):
              t.add_row([key, "%.2f %%" % -ticker[key]])
          elif key in "percent_change":
              t.add_row([key, "%.2f %%" % ticker[key]])
          else:
              t.add_row([key, str(ticker[key])])
      print(t)
  
  
  @cli.command()
  @click.option('--width', '-w', help='Plot width (default 75)', default=75)
  @click.option('--height', '-h', help='Plot height (default 15)', default=15)
  @click.option('--ascii', help='Use only ascii symbols', is_flag=True, default=False)
  def pricehistory(width, height, ascii):
      """ Show price history
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      feed_history = stm.get_feed_history()
      current_base = Amount(feed_history['current_median_history']["base"], blockchain_instance=stm)
      current_quote = Amount(feed_history['current_median_history']["quote"], blockchain_instance=stm)
      price_history = feed_history["price_history"]
      price = []
      for h in price_history:
          base = Amount(h["base"], blockchain_instance=stm)
          quote = Amount(h["quote"], blockchain_instance=stm)
          price.append(float(base.amount / quote.amount))
      if ascii:
          charset = u'ascii'
      else:
          charset = u'utf8'
      chart = AsciiChart(height=height, width=width, offset=4, placeholder='{:6.2f} $', charset=charset)
      print("\n            Price history for %s (median price %4.2f $)\n" % (stm.token_symbol, float(current_base) / float(current_quote)))
  
      chart.adapt_on_series(price)
      chart.new_chart()
      chart.add_axis()
      if (float(current_base) / float(current_quote)) <= max(price):
          chart._draw_h_line(chart._map_y(float(current_base) / float(current_quote)), 1, int(chart.n / chart.skip), line=chart.char_set["curve_hl_dot"])
      chart.add_curve(price)
      print(str(chart))
  
  
  @cli.command()
  @click.option('--days', '-d', help='Limit the days of shown trade history (default 7)', default=7.)
  @click.option('--hours', help='Limit the intervall history intervall (default 2 hours)', default=2.0)
  @click.option('--sbd-to-steem', help='Show ticker in SBD/STEEM', is_flag=True, default=False)
  @click.option('--hbd-to-hive', '-i', help='Show ticker in HBD/HIVE', is_flag=True, default=False)
  @click.option('--limit', '-l', help='Limit number of trades which is fetched at each intervall point (default 100)', default=100)
  @click.option('--width', '-w', help='Plot width (default 75)', default=75)
  @click.option('--height', '-h', help='Plot height (default 15)', default=15)
  @click.option('--ascii', help='Use only ascii symbols', is_flag=True, default=False)
  def tradehistory(days, hours, sbd_to_steem, hbd_to_hive, limit, width, height, ascii):
      """ Show price history
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      m = Market(blockchain_instance=stm)
      utc = pytz.timezone('UTC')
      stop = utc.localize(datetime.utcnow())
      start = stop - timedelta(days=days)
      intervall = timedelta(hours=hours)
      trades = m.trade_history(start=start, stop=stop, limit=limit, intervall=intervall)
      price = []
      if sbd_to_steem or hbd_to_hive:
          base_str = stm.token_symbol
      else:
          base_str = stm.backed_token_symbol
      for trade in trades:
          base = 0
          quote = 0
          for order in trade:
              base += float(order.as_base(base_str)["base"])
              quote += float(order.as_base(base_str)["quote"])
          price.append(base / quote)
      if ascii:
          charset = u'ascii'
      else:
          charset = u'utf8'
      chart = AsciiChart(height=height, width=width, offset=3, placeholder='{:6.2f} ', charset=charset)
      if sbd_to_steem or hbd_to_hive:
          print("\n     Trade history %s - %s \n\n%s/%s" % (formatTimeString(start), formatTimeString(stop),
                                                            stm.backed_token_symbol, stm.token_symbol))
      else:
          print("\n     Trade history %s - %s \n\n%s/%s" % (formatTimeString(start), formatTimeString(stop),
                                                            stm.token_symbol, stm.backed_token_symbol))
      chart.adapt_on_series(price)
      chart.new_chart()
      chart.add_axis()
      chart.add_curve(price)
      print(str(chart))
  
  
  @cli.command()
  @click.option('--chart', help='Enable charting', is_flag=True)
  @click.option('--limit', '-l', help='Limit number of returned open orders (default 25)', default=25)
  @click.option('--show-date', help='Show dates', is_flag=True, default=False)
  @click.option('--width', '-w', help='Plot width (default 75)', default=75)
  @click.option('--height', '-h', help='Plot height (default 15)', default=15)
  @click.option('--ascii', help='Use only ascii symbols', is_flag=True, default=False)
  def orderbook(chart, limit, show_date, width, height, ascii):
      """Obtain orderbook of the internal market"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      market = Market(blockchain_instance=stm)
      orderbook = market.orderbook(limit=limit, raw_data=False)
      if not show_date:
          header = ["Asks Sum " + stm.backed_token_symbol, "Sell Orders", "Bids Sum " + stm.backed_token_symbol, "Buy Orders"]
      else:
          header = ["Asks date", "Sell Orders", "Bids date", "Buy Orders"]
      t = PrettyTable(header, hrules=0)
      t.align = "r"
      asks = []
      bids = []
      asks_date = []
      bids_date = []
      sumsum_asks = []
      sum_asks = 0
      sumsum_bids = []
      sum_bids = 0
      n = 0
      for order in orderbook["asks"]:
          asks.append(order)
          sum_asks += float(order.as_base(stm.backed_token_symbol)["base"])
          sumsum_asks.append(sum_asks)
      if n < len(asks):
          n = len(asks)
      for order in orderbook["bids"]:
          bids.append(order)
          sum_bids += float(order.as_base(stm.backed_token_symbol)["base"])
          sumsum_bids.append(sum_bids)
      if n < len(bids):
          n = len(bids)
      if show_date:
          for order in orderbook["asks_date"]:
              asks_date.append(order)
          if n < len(asks_date):
              n = len(asks_date)
          for order in orderbook["bids_date"]:
              bids_date.append(order)
          if n < len(bids_date):
              n = len(bids_date)
      if chart:
          if ascii:
              charset = u'ascii'
          else:
              charset = u'utf8'
          chart = AsciiChart(height=height, width=width, offset=4, placeholder=' {:10.2f} $', charset=charset)
          print("\n            Orderbook \n")
          chart.adapt_on_series(sumsum_asks[::-1] + sumsum_bids)
          chart.new_chart()
          chart.add_axis()
          y0 = chart._map_y(chart.minimum)
          y1 = chart._map_y(chart.maximum)
          chart._draw_v_line(y0 + 1, y1, int(chart.n / chart.skip / 2), line=chart.char_set["curve_vl_dot"])
          chart.add_curve(sumsum_asks[::-1] + sumsum_bids)
          print(str(chart))
          return
      for i in range(n):
          row = []
          if len(asks_date) > i:
              row.append(formatTimeString(asks_date[i]))
          elif show_date:
              row.append([""])
          if len(sumsum_asks) > i and not show_date:
              row.append("%.2f" % sumsum_asks[i])
          elif not show_date:
              row.append([""])
          if len(asks) > i:
              row.append(str(asks[i]))
          else:
              row.append([""])
          if len(bids_date) > i:
              row.append(formatTimeString(bids_date[i]))
          elif show_date:
              row.append([""])
          if len(sumsum_bids) > i and not show_date:
              row.append("%.2f" % sumsum_bids[i])
          elif not show_date:
              row.append([""])
          if len(bids) > i:
              row.append(str(bids[i]))
          else:
              row.append([""])
          t.add_row(row)
      print(t)
  
  
  @cli.command()
  @click.argument('amount', nargs=1)
  @click.argument('asset', nargs=1)
  @click.argument('price', nargs=1, required=False)
  @click.option('--account', '-a', help='Buy with this account (defaults to "default_account")')
  @click.option('--orderid', help='Set an orderid')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def buy(amount, asset, price, account, orderid, export):
      """Buy STEEM/HIVE or SBD/HBD from the internal market
  
          Limit buy price denoted in (SBD per STEEM or HBD per HIVE)
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if account is None:
          account = stm.config["default_account"]
      if asset == stm.backed_token_symbol:
          market = Market(base=Asset(stm.token_symbol), quote=Asset(stm.backed_token_symbol), blockchain_instance=stm)
      else:
          market = Market(base=Asset(stm.backed_token_symbol), quote=Asset(stm.token_symbol), blockchain_instance=stm)
      if price is None:
          orderbook = market.orderbook(limit=1, raw_data=False)
          if asset == stm.token_symbol and len(orderbook["bids"]) > 0:
              p = Price(orderbook["bids"][0]["base"], orderbook["bids"][0]["quote"], blockchain_instance=stm).invert()
              p_show = p
          elif len(orderbook["asks"]) > 0:
              p = Price(orderbook["asks"][0]["base"], orderbook["asks"][0]["quote"], blockchain_instance=stm).invert()
              p_show = p
          price_ok = click.prompt("Is the following Price ok: %s [y/n]" % (str(p_show)))
          if price_ok not in ["y", "ye", "yes"]:
              return
      else:
          p = Price(float(price), u"%s:%s" % (stm.backed_token_symbol, stm.token_symbol), blockchain_instance=stm)
      if not unlock_wallet(stm):
          return
  
      a = Amount(float(amount), asset, blockchain_instance=stm)
      acc = Account(account, blockchain_instance=stm)
      tx = market.buy(p, a, account=acc, orderid=orderid)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('amount', nargs=1)
  @click.argument('asset', nargs=1)
  @click.argument('price', nargs=1, required=False)
  @click.option('--account', '-a', help='Sell with this account (defaults to "default_account")')
  @click.option('--orderid', help='Set an orderid')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def sell(amount, asset, price, account, orderid, export):
      """Sell STEEM/HIVE or SBD/HBD from the internal market
  
          Limit sell price denoted in (SBD per STEEM) or (HBD per HIVE)
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if asset == stm.backed_token_symbol:
          market = Market(base=Asset(stm.token_symbol), quote=Asset(stm.backed_token_symbol), blockchain_instance=stm)
      else:
          market = Market(base=Asset(stm.backed_token_symbol), quote=Asset(stm.token_symbol), blockchain_instance=stm)
      if not account:
          account = stm.config["default_account"]
      if not price:
          orderbook = market.orderbook(limit=1, raw_data=False)
          if asset == stm.backed_token_symbol and len(orderbook["bids"]) > 0:
              p = Price(orderbook["bids"][0]["base"], orderbook["bids"][0]["quote"], blockchain_instance=stm).invert()
              p_show = p
          else:
              p = Price(orderbook["asks"][0]["base"], orderbook["asks"][0]["quote"], blockchain_instance=stm).invert()
              p_show = p
          price_ok = click.prompt("Is the following Price ok: %s [y/n]" % (str(p_show)))
          if price_ok not in ["y", "ye", "yes"]:
              return
      else:
          p = Price(float(price), u"%s:%s" % (stm.backed_token_symbol, stm.token_symbol), blockchain_instance=stm)
      if not unlock_wallet(stm):
          return
      a = Amount(float(amount), asset, blockchain_instance=stm)
      acc = Account(account, blockchain_instance=stm)
      tx = market.sell(p, a, account=acc, orderid=orderid)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('orderid', nargs=1)
  @click.option('--account', '-a', help='Sell with this account (defaults to "default_account")')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def cancel(orderid, account, export):
      """Cancel order in the internal market"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      market = Market(blockchain_instance=stm)
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      tx = market.cancel(orderid, account=acc)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('account', nargs=1, required=False)
  def openorders(account):
      """Show open orders"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      market = Market(blockchain_instance=stm)
      if not account:
          account = stm.config["default_account"]
      acc = Account(account, blockchain_instance=stm)
      openorders = market.accountopenorders(account=acc)
      t = PrettyTable(["Orderid", "Created", "Order", "Account"], hrules=0)
      t.align = "r"
      for order in openorders:
          t.add_row([order["orderid"],
                     formatTimeString(order["created"]),
                     str(order["order"]),
                     account])
      print(t)
  
  
  @cli.command()
  @click.argument('identifier', nargs=1)
  @click.option('--account', '-a', help='Reblog as this user')
  def reblog(identifier, account):
      """Reblog an existing post"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      post = Comment(identifier, blockchain_instance=stm)
      tx = post.resteem(account=acc)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('follow', nargs=-1)
  @click.option('--account', '-a', help='Follow from this account')
  @click.option('--what', help='Follow these objects (defaults to ["blog"])', default=["blog"])
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def follow(follow, account, what, export):
      """Follow another account
  
         Can be blog ignore blacklist unblacklist follow_blacklist unfollow_blacklist follow_muted unfollow_muted on HIVE
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if isinstance(what, str):
          what = [what]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      tx = acc.follow(follow, what=what)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('mute', nargs=1)
  @click.option('--account', '-a', help='Mute from this account')
  @click.option('--what', help='Mute these objects (defaults to ["ignore"])', default=["ignore"])
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def mute(mute, account, what, export):
      """Mute another account"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if isinstance(what, str):
          what = [what]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      tx = acc.follow(mute, what=what)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('unfollow', nargs=1)
  @click.option('--account', '-a', help='UnFollow/UnMute from this account')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def unfollow(unfollow, account, export):
      """Unfollow/Unmute another account"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      tx = acc.unfollow(unfollow)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.option('--witness', help='Witness name')
  @click.option('--maximum_block_size', help='Max block size')
  @click.option('--account_creation_fee', help='Account creation fee')
  @click.option('--sbd_interest_rate', help='SBD interest rate in percent')
  @click.option('--hbd_interest_rate', help='HBD interest rate in percent')
  @click.option('--url', help='Witness URL')
  @click.option('--signing_key', help='Signing Key')
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def witnessupdate(witness, maximum_block_size, account_creation_fee, sbd_interest_rate, hbd_interest_rate, url, signing_key, export):
      """Change witness properties"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not witness:
          witness = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      witness = Witness(witness, blockchain_instance=stm)
      props = witness["props"]
      if account_creation_fee is not None:
          props["account_creation_fee"] = str(
              Amount("%.3f %s" % (float(account_creation_fee), stm.token_symbol), blockchain_instance=stm))
      if maximum_block_size is not None:
          props["maximum_block_size"] = int(maximum_block_size)
      if sbd_interest_rate is not None:
          props["sbd_interest_rate"] = int(float(sbd_interest_rate) * 100)
      if hbd_interest_rate is not None:
          props["hbd_interest_rate"] = int(float(hbd_interest_rate) * 100)
      tx = witness.update(signing_key or witness["signing_key"], url or witness["url"], props)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('witness', nargs=1)
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def witnessdisable(witness, export):
      """Disable a witness"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not witness:
          witness = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      witness = Witness(witness, blockchain_instance=stm)
      if not witness.is_active:
          print("Cannot disable a disabled witness!")
          return
      props = witness["props"]
      tx = witness.update('STM1111111111111111111111111111111114T1Anm', witness["url"], props)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('witness', nargs=1)
  @click.argument('signing_key', nargs=1)
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def witnessenable(witness, signing_key, export):
      """Enable a witness"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not witness:
          witness = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      witness = Witness(witness, blockchain_instance=stm)
      props = witness["props"]
      tx = witness.update(signing_key, witness["url"], props)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('witness', nargs=1)
  @click.argument('pub_signing_key', nargs=1)
  @click.option('--maximum_block_size', help='Max block size', default=65536)
  @click.option('--account_creation_fee', help='Account creation fee', default=0.1)
  @click.option('--sbd_interest_rate', help='SBD interest rate in percent', default=0.0)
  @click.option('--hbd_interest_rate', help='HBD interest rate in percent', default=0.0)
  @click.option('--url', help='Witness URL', default="")
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def witnesscreate(witness, pub_signing_key, maximum_block_size, account_creation_fee, sbd_interest_rate, hbd_interest_rate, url, export):
      """Create a witness"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not unlock_wallet(stm):
          return
      if stm.is_hive and stm.hardfork >= 24:
  
          props = {
              "account_creation_fee":
                  Amount("%.3f %s" % (float(account_creation_fee), stm.token_symbol), blockchain_instance=stm),
              "maximum_block_size":
                  int(maximum_block_size),
              "hbd_interest_rate":
                  int(hbd_interest_rate * 100)
          }
      else:
          props = {
              "account_creation_fee":
                  Amount("%.3f %s" % (float(account_creation_fee), stm.token_symbol), blockchain_instance=stm),
              "maximum_block_size":
                  int(maximum_block_size),
              "sbd_interest_rate":
                  int(sbd_interest_rate * 100)
          }
  
      tx = stm.witness_update(pub_signing_key, url, props, account=witness)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('witness', nargs=1)
  @click.argument('wif', nargs=1)
  @click.option('--account_creation_fee', help='Account creation fee (float)')
  @click.option('--account_subsidy_budget', help='Account subisidy per block')
  @click.option('--account_subsidy_decay', help='Per block decay of the account subsidy pool')
  @click.option('--maximum_block_size', help='Max block size')
  @click.option('--sbd_interest_rate', help='SBD interest rate in percent')
  @click.option('--hbd_interest_rate', help='HBD interest rate in percent')
  @click.option('--new_signing_key', help='Set new signing key (pubkey)')
  @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, hbd_interest_rate, new_signing_key, url):
      """Update witness properties of witness WITNESS with the witness signing key WIF"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      # if not unlock_wallet(stm):
      #    return
      props = {}
      if account_creation_fee is not None:
          props["account_creation_fee"] = Amount("%.3f %s" % (float(account_creation_fee), stm.token_symbol), blockchain_instance=stm)
      if account_subsidy_budget is not None:
          props["account_subsidy_budget"] = int(account_subsidy_budget)
      if account_subsidy_decay is not None:
          props["account_subsidy_decay"] = int(account_subsidy_decay)
      if maximum_block_size is not None:
          props["maximum_block_size"] = int(maximum_block_size)
      if sbd_interest_rate is not None:
          props["sbd_interest_rate"] = int(float(sbd_interest_rate) * 100)
      if hbd_interest_rate is not None:
          props["hbd_interest_rate"] = int(float(hbd_interest_rate) * 100)
      if new_signing_key is not None:
          props["new_signing_key"] = new_signing_key
      if url is not None:
          props["url"] = url
  
      tx = stm.witness_set_properties(wif, witness, props)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('witness', nargs=1)
  @click.argument('wif', nargs=1, required=False)
  @click.option('--base', '-b', help='Set base manually, when not set the base is automatically calculated.')
  @click.option('--quote', '-q', help='Steem quote manually, when not set the base is automatically calculated.')
  @click.option('--support-peg', help='Supports peg adjusting the quote, is overwritten by --set-quote!', is_flag=True, default=False)
  def witnessfeed(witness, wif, base, quote, support_peg):
      """Publish price feed for a witness"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if wif is None:
          if not unlock_wallet(stm):
              return
      witness = Witness(witness, blockchain_instance=stm)
      market = Market(blockchain_instance=stm)
      use_hbd = False
      if "hbd_exchange_rate" in witness:
          use_hbd = True
          old_base = witness["hbd_exchange_rate"]["base"]
          old_quote = witness["hbd_exchange_rate"]["quote"]
          last_published_price = Price(witness["hbd_exchange_rate"], blockchain_instance=stm)
      else:
          old_base = witness["sbd_exchange_rate"]["base"]
          old_quote = witness["sbd_exchange_rate"]["quote"]
          last_published_price = Price(witness["sbd_exchange_rate"], blockchain_instance=stm)
  
      steem_usd = None
      hive_usd = None
      print("Old price %.3f (base: %s, quote %s)" % (float(last_published_price), old_base, old_quote))
      if quote is None and not support_peg:
          quote = Amount("1.000 %s" % stm.token_symbol, blockchain_instance=stm)
      elif quote is None and not stm.is_hive:
          latest_price = market.ticker()['latest']
          if steem_usd is None:
              steem_usd = market.steem_usd_implied()
          sbd_usd = float(latest_price.as_base(stm.backed_token_symbol)) * steem_usd
          quote = Amount(1. / sbd_usd, stm.token_symbol, blockchain_instance=stm)
      elif quote is None and stm.is_hive:
          latest_price = market.ticker()['latest']
          if hive_usd is None:
              hive_usd = market.hive_usd_implied()
          hbd_usd = float(latest_price.as_base(stm.backed_token_symbol)) * hive_usd
          quote = Amount(1. / hbd_usd, stm.token_symbol, blockchain_instance=stm)
      else:
          if str(quote[-5:]).upper() == stm.token_symbol:
              quote = Amount(quote, blockchain_instance=stm)
          else:
              quote = Amount(quote, stm.token_symbol, blockchain_instance=stm)
      if base is None and not stm.is_hive:
          if steem_usd is None:
              steem_usd = market.steem_usd_implied()
          base = Amount(steem_usd, stm.backed_token_symbol, blockchain_instance=stm)
      elif base is None and stm.is_hive:
          if hive_usd is None:
              hive_usd = market.hive_usd_implied()
          base = Amount(hive_usd, stm.backed_token_symbol, blockchain_instance=stm)
      else:
          if str(quote[-3:]).upper() == stm.backed_token_symbol:
              base = Amount(base, blockchain_instance=stm)
          else:
              base = Amount(base, stm.backed_token_symbol, blockchain_instance=stm)
      new_price = Price(base=base, quote=quote, blockchain_instance=stm)
      print("New price %.3f (base: %s, quote %s)" % (float(new_price), base, quote))
      if wif is not None and use_hbd:
          props = {"hbd_exchange_rate": new_price}
          tx = stm.witness_set_properties(wif, witness["owner"], props)
      elif wif is not None:
          props = {"sbd_exchange_rate": new_price}
          tx = stm.witness_set_properties(wif, witness["owner"], props)
      else:
          tx = witness.feed_publish(base, quote=quote)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('witness', nargs=1)
  def witness(witness):
      """ List witness information
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      witness = Witness(witness, blockchain_instance=stm)
      witness_json = witness.json()
      witness_schedule = stm.get_witness_schedule()
      config = stm.get_config()
      if "VIRTUAL_SCHEDULE_LAP_LENGTH2" in config:
          lap_length = int(config["VIRTUAL_SCHEDULE_LAP_LENGTH2"])
      elif "HIVE_VIRTUAL_SCHEDULE_LAP_LENGTH2" in config:
          lap_length = int(config["HIVE_VIRTUAL_SCHEDULE_LAP_LENGTH2"])
      else:
          lap_length = int(config["STEEM_VIRTUAL_SCHEDULE_LAP_LENGTH2"])
      rank = 0
      active_rank = 0
      found = False
      witnesses = WitnessesRankedByVote(limit=250, blockchain_instance=stm)
      vote_sum = witnesses.get_votes_sum()
      for w in witnesses:
          rank += 1
          if w.is_active:
              active_rank += 1
          if w["owner"] == witness["owner"]:
              found = True
              break
      virtual_time_to_block_num = int(witness_schedule["num_scheduled_witnesses"]) / (lap_length / (vote_sum + 1))
      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])
      if found:
          t.add_row(["rank", rank])
          t.add_row(["active_rank", active_rank])
      virtual_diff = int(witness_json["virtual_scheduled_time"]) - int(witness_schedule['current_virtual_time'])
      block_diff_est = virtual_diff * virtual_time_to_block_num
      if active_rank > 20:
          t.add_row(["virtual_time_diff", virtual_diff])
          t.add_row(["block_diff_est", int(block_diff_est)])
          next_block_s = int(block_diff_est) * 3
          next_block_min = next_block_s / 60
          next_block_h = next_block_min / 60
          next_block_d = next_block_h / 24
          time_diff_est = ""
          if next_block_d > 1:
              time_diff_est = "%.2f days" % next_block_d
          elif next_block_h > 1:
              time_diff_est = "%.2f hours" % next_block_h
          elif next_block_min > 1:
              time_diff_est = "%.2f minutes" % next_block_min
          else:
              time_diff_est = "%.2f seconds" % next_block_s
          t.add_row(["time_diff_est", time_diff_est])
      print(t)
  
  
  @cli.command()
  @click.argument('account', nargs=1, required=False)
  @click.option('--limit', help='How many witnesses should be shown', default=100)
  def witnesses(account, limit):
      """ List witnesses
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if account:
          account = Account(account, blockchain_instance=stm)
          account_name = account["name"]
          if account["proxy"] != "":
              account_name = account["proxy"]
              account_type = "Proxy"
          else:
              account_type = "Account"
          witnesses = WitnessesVotedByAccount(account_name, blockchain_instance=stm)
          print("%s: @%s (%d of 30)" % (account_type, account_name, len(witnesses)))
      else:
          witnesses = WitnessesRankedByVote(limit=limit, blockchain_instance=stm)
      witnesses.printAsTable()
  
  
  @cli.command()
  @click.argument('account', nargs=1, required=False)
  @click.option('--direction', default=None, help="in or out")
  @click.option('--outgoing', '-o', help='Show outgoing votes', is_flag=True, default=False)
  @click.option('--incoming', '-i', help='Show incoming votes', is_flag=True, default=False)
  @click.option('--days', '-d', default=2., help="Limit shown vote history by this amount of days (default: 2)")
  @click.option('--export', '-e', default=None, help="Export results to TXT-file")
  def votes(account, direction, outgoing, incoming, days, export):
      """ List outgoing/incoming account votes
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if direction is None and not incoming and not outgoing:
          direction = "in"
      utc = pytz.timezone('UTC')
      limit_time = utc.localize(datetime.utcnow()) - timedelta(days=days)
      out_votes_str = ""
      in_votes_str = ""
      if direction == "out" or outgoing:
          votes = AccountVotes(account, start=limit_time, blockchain_instance=stm)
          out_votes_str = votes.printAsTable(start=limit_time, return_str=True)
      if direction == "in" or incoming:
          account = Account(account, blockchain_instance=stm)
          votes_list = []
          for v in account.history(start=limit_time, only_ops=["vote"]):
              vote = Vote(v, blockchain_instance=stm)
              vote.refresh()
              votes_list.append(vote)
          votes = ActiveVotes(votes_list, blockchain_instance=stm)
          in_votes_str = votes.printAsTable(votee=account["name"], return_str=True)
      if export:
          with open(export, 'w') as w:
              w.write(out_votes_str)
              w.write("\n")
              w.write(in_votes_str)
      else:
          print(out_votes_str)
          print(in_votes_str)
  
  
  @cli.command()
  @click.argument('authorperm', nargs=1, required=False)
  @click.option('--account', '-a', help='Show only curation for this account')
  @click.option('--limit', '-m', help='Show only the first minutes')
  @click.option('--min-vote', '-v', help='Show only votes higher than the given value')
  @click.option('--max-vote', '-w', help='Show only votes lower than the given value')
  @click.option('--min-performance', '-x', help='Show only votes with performance higher than the given value in HBD/SBD')
  @click.option('--max-performance', '-y', help='Show only votes with performance lower than the given value in HBD/SBD')
  @click.option('--payout', default=None, help="Show the curation for a potential payout in SBD as float")
  @click.option('--export', '-e', default=None, help="Export results to HTML-file")
  @click.option('--short', '-s', is_flag=True, default=False, help="Show only Curation without sum")
  @click.option('--length', '-l', help='Limits the permlink character length', default=None)
  @click.option('--permlink', '-p', help='Show the permlink for each entry', is_flag=True, default=False)
  @click.option('--title', '-t', help='Show the title for each entry', is_flag=True, default=False)
  @click.option('--days', '-d', default=7., help="Limit shown rewards by this amount of days (default: 7), max is 7 days.")
  def curation(authorperm, account, limit, min_vote, max_vote, min_performance, max_performance, payout, export, short, length, permlink, title, days):
      """ Lists curation rewards of all votes for authorperm
  
          When authorperm is empty or "all", the curation rewards
          for all account votes are shown.
  
          authorperm can also be a number. e.g. 5 is equivalent to
          the fifth account vote in the given time duration (default is 7 days)
  
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      SP_symbol = "SP"
      if stm.is_hive:
          SP_symbol = "HP"
      if authorperm is None:
          authorperm = 'all'
      if account is None and authorperm != 'all':
          show_all_voter = True
      else:
          show_all_voter = False
      if authorperm == 'all' or authorperm.isdigit():
          if not account:
              account = stm.config["default_account"]
          utc = pytz.timezone('UTC')
          limit_time = utc.localize(datetime.utcnow()) - timedelta(days=7)
          votes = AccountVotes(account, start=limit_time, blockchain_instance=stm)
          authorperm_list = [vote.authorperm for vote in votes]
          if authorperm.isdigit():
              if len(authorperm_list) < int(authorperm):
                  raise ValueError("Authorperm id must be lower than %d" % (len(authorperm_list) + 1))
              authorperm_list = [authorperm_list[int(authorperm) - 1]]
              all_posts = False
          else:
              all_posts = True
      else:
          authorperm_list = [authorperm]
          all_posts = False
      if (all_posts) and permlink:
          t = PrettyTable(["Author", "permlink", "Voting time", "Vote", "Early vote loss", "Curation", "Performance"])
          t.align = "l"
      elif (all_posts) and title:
          t = PrettyTable(["Author", "permlink", "Voting time", "Vote", "Early vote loss", "Curation", "Performance"])
          t.align = "l"
      elif all_posts:
          t = PrettyTable(["Author", "Voting time", "Vote", "Early vote loss", "Curation", "Performance"])
          t.align = "l"
      elif (export) and permlink:
          t = PrettyTable(["Author", "permlink", "Voter", "Voting time", "Vote", "Early vote loss", "Curation", "Performance"])
          t.align = "l"
      elif (export) and title:
          t = PrettyTable(["Author", "permlink", "Voter", "Voting time", "Vote", "Early vote loss", "Curation", "Performance"])
          t.align = "l"
      elif export:
          t = PrettyTable(["Author", "Voter", "Voting time", "Vote", "Early vote loss", "Curation", "Performance"])
          t.align = "l"
      else:
          t = PrettyTable(["Voter", "Voting time", "Vote", "Early vote loss", "Curation", "Performance"])
          t.align = "l"
      index = 0
      for authorperm in authorperm_list:
          index += 1
          comment = Comment(authorperm, blockchain_instance=stm)
          if payout is not None and comment.is_pending():
              payout = float(payout)
          elif payout is not None:
              payout = None
          curation_rewards_SBD = comment.get_curation_rewards(pending_payout_SBD=True, pending_payout_value=payout)
          curation_rewards_SP = comment.get_curation_rewards(pending_payout_SBD=False, pending_payout_value=payout)
          rows = []
          sum_curation = [0, 0, 0, 0]
          max_curation = [0, 0, 0, 0, 0, 0]
          highest_vote = [0, 0, 0, 0, 0, 0]
          for vote in comment.get_votes():
              vote_time = vote["time"]
  
              vote_SBD = stm.rshares_to_token_backed_dollar(int(vote["rshares"]))
              curation_SBD = curation_rewards_SBD["active_votes"][vote["voter"]]
              curation_SP = curation_rewards_SP["active_votes"][vote["voter"]]
              if vote_SBD > 0:
                  penalty = ((comment.get_curation_penalty(vote_time=vote_time)) * vote_SBD)
                  performance = (float(curation_SBD) / vote_SBD * 100)
              else:
                  performance = 0
                  penalty = 0
              vote_befor_min = (((vote_time) - comment["created"]).total_seconds() / 60)
              sum_curation[0] += vote_SBD
              sum_curation[1] += penalty
              sum_curation[2] += float(curation_SP)
              sum_curation[3] += float(curation_SBD)
              row = [vote["voter"],
                     vote_befor_min,
                     vote_SBD,
                     penalty,
                     float(curation_SP),
                     performance]
  
  
              rows.append(row)
          sortedList = sorted(rows, key=lambda row: (row[1]), reverse=False)
          new_row = []
          new_row2 = []
          voter = []
          voter2 = []
          if (all_posts or export) and permlink:
              if length:
                  new_row = [comment.author, comment.permlink[:int(length)]]
              else:
                  new_row = [comment.author, comment.permlink]
              new_row2 = ["", ""]
          elif (all_posts or export) and title:
              if length:
                  new_row = [comment.author, comment.title[:int(length)]]
              else:
                  new_row = [comment.author, comment.title]
              new_row2 = ["", ""]
          elif (all_posts or export):
              new_row = [comment.author]
              new_row2 = [""]
          if not all_posts:
              voter = [""]
              voter2 = [""]
          found_voter = False
          for row in sortedList:
              if limit is not None and row[1] > float(limit):
                  continue
              if min_vote is not None and float(row[2]) < float(min_vote):
                  continue
              if max_vote is not None and float(row[2]) > float(max_vote):
                  continue
              if min_performance is not None and float(row[5]) < float(min_performance):
                  continue
              if max_performance is not None and float(row[5]) > float(max_performance):
                  continue
              if row[-1] > max_curation[-1]:
                  max_curation = row
              if row[2] > highest_vote[2]:
                  highest_vote = row
              if show_all_voter or account == row[0]:
                  if not all_posts:
                      voter = [row[0]]
                  if all_posts:
                      new_row[0] = "%d. %s" % (index, comment.author)
                  if not found_voter:
                      found_voter = True
                  t.add_row(new_row + voter + ["%.1f min" % row[1],
                                               "%.3f %s" % (float(row[2]), stm.backed_token_symbol),
                                               "%.3f %s" % (float(row[3]), stm.backed_token_symbol),
                                               "%.3f %s" % (row[4], SP_symbol),
                                               "%.1f %%" % (row[5])])
                  if len(authorperm_list) == 1:
                      new_row = new_row2
          if not short and found_voter:
              t.add_row(new_row2 + voter2 + ["", "", "", "", ""])
              if sum_curation[0] > 0:
                  curation_sum_percentage = sum_curation[3] / sum_curation[0] * 100
              else:
                  curation_sum_percentage = 0
              sum_line = new_row2 + voter2
              sum_line[-1] = "High. vote"
  
              t.add_row(sum_line + ["%.1f min" % highest_vote[1],
                                    "%.3f %s" % (float(highest_vote[2]), stm.backed_token_symbol),
                                    "%.3f %s" % (float(highest_vote[3]), stm.backed_token_symbol),
                                    "%.3f %s" % (highest_vote[4], SP_symbol),
                                    "%.1f %%" % (highest_vote[5])])
              sum_line[-1] = "High. Cur."
              t.add_row(sum_line + ["%.1f min" % max_curation[1],
                                    "%.3f %s" % (float(max_curation[2]), stm.backed_token_symbol),
                                    "%.3f %s" % (float(max_curation[3]), stm.backed_token_symbol),
                                    "%.3f %s" % (max_curation[4], SP_symbol),
                                    "%.1f %%" % (max_curation[5])])
              sum_line[-1] = "Sum"
              t.add_row(sum_line + ["-",
                                    "%.3f %s" % (sum_curation[0], stm.backed_token_symbol),
                                    "%.3f %s" % (sum_curation[1], stm.backed_token_symbol),
                                    "%.3f %s" % (sum_curation[2], SP_symbol),
                                    "%.2f %%" % curation_sum_percentage])
              if all_posts or export:
                  t.add_row(new_row2 + voter2 + ["-", "-", "-", "-", "-"])
          if not (all_posts or export):
              print("curation for %s" % (authorperm))
              print(t)
      if export:
          with open(export, 'w') as w:
              w.write(str(t.get_html_string()))
      elif all_posts:
          print("curation for @%s" % account)
          print(t)
  
  
  @cli.command()
  @click.argument('accounts', nargs=-1, required=False)
  @click.option('--only-sum', '-s', help='Show only the sum', is_flag=True, default=False)
  @click.option('--post', '-p', help='Show post payout', is_flag=True, default=False)
  @click.option('--comment', '-c', help='Show comments payout', is_flag=True, default=False)
  @click.option('--curation', '-v', help='Shows  curation', is_flag=True, default=False)
  @click.option('--length', '-l', help='Limits the permlink character length', default=None)
  @click.option('--author', '-a', help='Show the author for each entry', is_flag=True, default=False)
  @click.option('--permlink', '-e', help='Show the permlink for each entry', is_flag=True, default=False)
  @click.option('--title', '-t', help='Show the title for each entry', is_flag=True, default=False)
  @click.option('--days', '-d', default=7., help="Limit shown rewards by this amount of days (default: 7)")
  def rewards(accounts, only_sum, post, comment, curation, length, author, permlink, title, days):
      """ Lists received rewards
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not accounts:
          accounts = [stm.config["default_account"]]
      if not comment and not curation and not post:
          post = True
          permlink = True
      if days < 0:
          days = 1
  
      utc = pytz.timezone('UTC')
      now = utc.localize(datetime.utcnow())
      limit_time = now - timedelta(days=days)
      for account in accounts:
          sum_reward = [0, 0, 0, 0, 0]
          account = Account(account, blockchain_instance=stm)
          median_price = Price(stm.get_current_median_history(), blockchain_instance=stm)
          m = Market(blockchain_instance=stm)
          latest = m.ticker()["latest"]
          if author and permlink:
              t = PrettyTable(["Author", "Permlink", "Payout", stm.backed_token_symbol, "%sP + %s" % (stm.token_symbol[0], stm.token_symbol), "Liquid USD", "Invested USD"])
          elif author and title:
                  t = PrettyTable(["Author", "Title", "Payout", stm.backed_token_symbol, "%sP + %s" % (stm.token_symbol[0], stm.token_symbol), "Liquid USD", "Invested USD"])
          elif author:
              t = PrettyTable(["Author", "Payout", stm.backed_token_symbol, "%sP + %s" % (stm.token_symbol[0], stm.token_symbol), "Liquid USD", "Invested USD"])
          elif not author and permlink:
              t = PrettyTable(["Permlink", "Payout", stm.backed_token_symbol, "%sP + %s" % (stm.token_symbol[0], stm.token_symbol), "Liquid USD", "Invested USD"])
          elif not author and title:
              t = PrettyTable(["Title", "Payout", stm.backed_token_symbol, "%sP + %s" % (stm.token_symbol[0], stm.token_symbol), "Liquid USD", "Invested USD"])
          else:
              t = PrettyTable(["Received", stm.backed_token_symbol, "%sP + %s" % (stm.token_symbol[0], stm.token_symbol), "Liquid USD", "Invested USD"])
          t.align = "l"
          rows = []
          start_op = account.estimate_virtual_op_num(limit_time)
          if start_op > 0:
              start_op -= 1
          only_ops = ['author_reward', 'curation_reward']
          progress_length = (account.virtual_op_count() - start_op) / 1000
          with click.progressbar(account.history(start=start_op, use_block_num=False, only_ops=only_ops), length=progress_length) as comment_hist:
              for v in comment_hist:
                  if not curation and v["type"] == "curation_reward":
                      continue
                  if not post and not comment and v["type"] == "author_reward":
                      continue
                  if v["type"] == "author_reward":
                      c = Comment(v, blockchain_instance=stm)
                      try:
                          c.refresh()
                      except exceptions.ContentDoesNotExistsException:
                          continue
                      if not post and not c.is_comment():
                          continue
                      if not comment and c.is_comment():
                          continue
                      if "sbd_payout" in v:
                          payout_SBD = Amount(v["sbd_payout"], blockchain_instance=stm)
                          payout_STEEM = Amount(v["steem_payout"], blockchain_instance=stm)
                      else:
                          payout_SBD = Amount(v["hbd_payout"], blockchain_instance=stm)
                          payout_STEEM = Amount(v["hive_payout"], blockchain_instance=stm)
                      sum_reward[0] += float(payout_SBD)
                      sum_reward[1] += float(payout_STEEM)
                      payout_SP = stm.vests_to_token_power(Amount(v["vesting_payout"], blockchain_instance=stm))
                      sum_reward[2] += float(payout_SP)
                      liquid_USD = float(payout_SBD) / float(latest) * float(median_price) + float(payout_STEEM) * float(median_price)
                      sum_reward[3] += liquid_USD
                      invested_USD = float(payout_SP) * float(median_price)
                      sum_reward[4] += invested_USD
                      if c.is_comment():
                          permlink_row = c.parent_permlink
                      else:
                          if title:
                              permlink_row = c.title
                          else:
                              permlink_row = c.permlink
                      rows.append([c["author"],
                                   permlink_row,
                                   ((now - formatTimeString(v["timestamp"])).total_seconds() / 60 / 60 / 24),
                                   (payout_SBD),
                                   (payout_STEEM),
                                   (payout_SP),
                                   (liquid_USD),
                                   (invested_USD)])
                  elif v["type"] == "curation_reward":
                      reward = Amount(v["reward"], blockchain_instance=stm)
                      payout_SP = stm.vests_to_token_power(reward)
                      liquid_USD = 0
                      invested_USD = float(payout_SP) * float(median_price)
                      sum_reward[2] += float(payout_SP)
                      sum_reward[4] += invested_USD
                      if title:
                          c = Comment(construct_authorperm(v["comment_author"], v["comment_permlink"]), blockchain_instance=stm)
                          permlink_row = c.title
                      else:
                          permlink_row = v["comment_permlink"]
                      rows.append([v["comment_author"],
                                   permlink_row,
                                   ((now - formatTimeString(v["timestamp"])).total_seconds() / 60 / 60 / 24),
                                   0.000,
                                   0.000,
                                   payout_SP,
                                   (liquid_USD),
                                   (invested_USD)])
          sortedList = sorted(rows, key=lambda row: (row[2]), reverse=False)
          if only_sum:
              sortedList = []
          for row in sortedList:
              if length:
                  permlink_row = row[1][:int(length)]
              else:
                  permlink_row = row[1]
              if author and (permlink or title):
                  t.add_row([row[0],
                             permlink_row,
                             "%.1f days" % row[2],
                             "%.3f" % float(row[3]),
                             "%.3f" % (float(row[4]) + float(row[5])),
                             "%.2f $" % (row[6]),
                             "%.2f $" % (row[7])])
              elif author and not (permlink or title):
                  t.add_row([row[0],
                             "%.1f days" % row[2],
                             "%.3f" % float(row[3]),
                             "%.3f" % (float(row[4]) + float(row[5])),
                             "%.2f $" % (row[5]),
                             "%.2f $" % (row[6])])
              elif not author and (permlink or title):
                  t.add_row([permlink_row,
                             "%.1f days" % row[2],
                             "%.3f" % float(row[3]),
                             "%.3f" % (float(row[4]) + float(row[5])),
                             "%.2f $" % (row[5]),
                             "%.2f $" % (row[6])])
              else:
                  t.add_row(["%.1f days" % row[2],
                             "%.3f" % float(row[3]),
                             "%.3f" % (float(row[4]) + float(row[5])),
                             "%.2f $" % (row[5]),
                             "%.2f $" % (row[6])])
  
          if author and (permlink or title):
              if not only_sum:
                  t.add_row(["", "", "", "", "", "", ""])
              t.add_row(["Sum",
                         "-",
                         "-",
                         "%.2f %s" % (sum_reward[0], stm.backed_token_symbol),
                         "%.2f %sP" % (sum_reward[1] + sum_reward[2], stm.token_symbol[0]),
                         "%.2f $" % (sum_reward[3]),
                         "%.2f $" % (sum_reward[4])])
          elif not author and not (permlink or title):
              t.add_row(["", "", "", "", ""])
              t.add_row(["Sum",
                         "%.2f %s" % (sum_reward[0], stm.backed_token_symbol),
                         "%.2f %sP" % (sum_reward[1] + sum_reward[2], stm.token_symbol[0]),
                         "%.2f $" % (sum_reward[2]),
                         "%.2f $" % (sum_reward[3])])
          else:
              t.add_row(["", "", "", "", "", ""])
              t.add_row(["Sum",
                         "-",
                         "%.2f %s" % (sum_reward[0], stm.backed_token_symbol),
                         "%.2f %sP" % (sum_reward[1] + sum_reward[2], stm.token_symbol[0]),
                         "%.2f $" % (sum_reward[3]),
                         "%.2f $" % (sum_reward[4])])
          message = "\nShowing "
          if post:
              if comment + curation == 0:
                  message += "post "
              elif comment + curation == 1:
                  message += "post and "
              else:
                  message += "post, "
          if comment:
              if curation == 0:
                  message += "comment "
              else:
                  message += "comment and "
          if curation:
              message += "curation "
          message += "rewards for @%s" % account.name
          print(message)
          print(t)
  
  
  @cli.command()
  @click.argument('accounts', nargs=-1, required=False)
  @click.option('--only-sum', '-s', help='Show only the sum', is_flag=True, default=False)
  @click.option('--post', '-p', help='Show pending post payout', is_flag=True, default=False)
  @click.option('--comment', '-c', help='Show pending comments payout', is_flag=True, default=False)
  @click.option('--curation', '-v', help='Shows  pending curation', is_flag=True, default=False)
  @click.option('--length', '-l', help='Limits the permlink character length', default=None)
  @click.option('--author', '-a', help='Show the author for each entry', is_flag=True, default=False)
  @click.option('--permlink', '-e', help='Show the permlink for each entry', is_flag=True, default=False)
  @click.option('--title', '-t', help='Show the title for each entry', is_flag=True, default=False)
  @click.option('--days', '-d', default=7., help="Limit shown rewards by this amount of days (default: 7), max is 7 days.")
  @click.option('--from', '-f', '_from', default=0., help="Start day from which on rewards are shown (default: 0), max is 7 days.")
  def pending(accounts, only_sum, post, comment, curation, length, author, permlink, title, days, _from):
      """ Lists pending rewards
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not accounts:
          accounts = [stm.config["default_account"]]
      if not comment and not curation and not post:
          post = True
          permlink = True
      if days < 0:
          days = 1
      if days > 7:
          days = 7
      if _from < 0:
          _from = 0
      if _from > 7:
          _from = 7
      if _from + days > 7:
          days = 7 - _from
      sp_symbol = "SP"
      if stm.is_hive:
          sp_symbol = "HP"
  
      utc = pytz.timezone('UTC')
      max_limit_time = utc.localize(datetime.utcnow()) - timedelta(days=7)
      limit_time = utc.localize(datetime.utcnow()) - timedelta(days=_from + days)
      start_time = utc.localize(datetime.utcnow()) - timedelta(days=_from)
      for account in accounts:
          sum_reward = [0, 0, 0, 0]
          account = Account(account, blockchain_instance=stm)
          median_price = Price(stm.get_current_median_history(), blockchain_instance=stm)
          m = Market(blockchain_instance=stm)
          latest = m.ticker()["latest"]
          if author and permlink:
              t = PrettyTable(["Author", "Permlink", "Cashout", stm.backed_token_symbol, sp_symbol, "Liquid USD", "Invested USD"])
          elif author and title:
              t = PrettyTable(["Author", "Title", "Cashout", stm.backed_token_symbol, sp_symbol, "Liquid USD", "Invested USD"])
          elif author:
              t = PrettyTable(["Author", "Cashout", stm.backed_token_symbol, sp_symbol, "Liquid USD", "Invested USD"])
          elif not author and permlink:
              t = PrettyTable(["Permlink", "Cashout", stm.backed_token_symbol, sp_symbol, "Liquid USD", "Invested USD"])
          elif not author and title:
              t = PrettyTable(["Title", "Cashout", stm.backed_token_symbol, sp_symbol, "Liquid USD", "Invested USD"])
          else:
              t = PrettyTable(["Cashout", stm.backed_token_symbol, sp_symbol, "Liquid USD", "Invested USD"])
          t.align = "l"
          rows = []
          c_list = {}
          start_op = account.estimate_virtual_op_num(limit_time)
          stop_op = account.estimate_virtual_op_num(start_time)
          if start_op > 0:
              start_op -= 1
          progress_length = (stop_op - start_op) / 1000
          with click.progressbar(map(Comment, account.history(start=start_op, stop=stop_op, use_block_num=False, only_ops=["comment"])), length=progress_length) as comment_hist:
              for v in comment_hist:
                  try:
                      v.refresh()
                  except exceptions.ContentDoesNotExistsException:
                      continue
                  author_reward = v.get_author_rewards()
                  if float(author_reward["total_payout_SBD"]) < 0.001:
                      continue
                  if v.permlink in c_list:
                      continue
                  c_list[v.permlink] = 1
                  if not v.is_pending():
                      continue
                  if not post and not v.is_comment():
                      continue
                  if not comment and v.is_comment():
                      continue
                  if v["author"] != account["name"]:
                      continue
                  payout_SBD = author_reward["payout_SBD"]
                  sum_reward[0] += float(payout_SBD)
                  payout_SP = author_reward["payout_SP"]
                  sum_reward[1] += float(payout_SP)
                  liquid_USD = float(author_reward["payout_SBD"]) / float(latest) * float(median_price)
                  sum_reward[2] += liquid_USD
                  invested_USD = float(author_reward["payout_SP"]) * float(median_price)
                  sum_reward[3] += invested_USD
                  if v.is_comment():
                      permlink_row = v.permlink
                  else:
                      if title:
                          permlink_row = v.title
                      else:
                          permlink_row = v.permlink
                  rows.append([v["author"],
                               permlink_row,
                               ((v["created"] - max_limit_time).total_seconds() / 60 / 60 / 24),
                               (payout_SBD),
                               (payout_SP),
                               (liquid_USD),
                               (invested_USD)])
          if curation:
              votes = AccountVotes(account, start=limit_time, stop=start_time, blockchain_instance=stm)
              for vote in votes:
                  authorperm = construct_authorperm(vote["author"], vote["permlink"])
                  try:
                      c = Comment(authorperm, blockchain_instance=stm)
                  except exceptions.ContentDoesNotExistsException:
                      continue
                  rewards = c.get_curation_rewards()
                  if not rewards["pending_rewards"]:
                      continue
                  days_to_payout = ((c["created"] - max_limit_time).total_seconds() / 60 / 60 / 24)
                  if days_to_payout < 0:
                      continue
                  payout_SP = rewards["active_votes"][account["name"]]
                  liquid_USD = 0
                  invested_USD = float(payout_SP) * float(median_price)
                  sum_reward[1] += float(payout_SP)
                  sum_reward[3] += invested_USD
                  if title:
                      permlink_row = c.title
                  else:
                      permlink_row = c.permlink
                  rows.append([c["author"],
                               permlink_row,
                               days_to_payout,
                               0.000,
                               payout_SP,
                               (liquid_USD),
                               (invested_USD)])
          sortedList = sorted(rows, key=lambda row: (row[2]), reverse=True)
          if only_sum:
              sortedList = []
          for row in sortedList:
              if length:
                  permlink_row = row[1][:int(length)]
              else:
                  permlink_row = row[1]
              if author and (permlink or title):
                  t.add_row([row[0],
                             permlink_row,
                             "%.1f days" % row[2],
                             "%.3f" % float(row[3]),
                             "%.3f" % float(row[4]),
                             "%.2f $" % (row[5]),
                             "%.2f $" % (row[6])])
              elif author and not (permlink or title):
                  t.add_row([row[0],
                             "%.1f days" % row[2],
                             "%.3f" % float(row[3]),
                             "%.3f" % float(row[4]),
                             "%.2f $" % (row[5]),
                             "%.2f $" % (row[6])])
              elif not author and (permlink or title):
                  t.add_row([permlink_row,
                             "%.1f days" % row[2],
                             "%.3f" % float(row[3]),
                             "%.3f" % float(row[4]),
                             "%.2f $" % (row[5]),
                             "%.2f $" % (row[6])])
              else:
                  t.add_row(["%.1f days" % row[2],
                             "%.3f" % float(row[3]),
                             "%.3f" % float(row[4]),
                             "%.2f $" % (row[5]),
                             "%.2f $" % (row[6])])
  
          if author and (permlink or title):
              if not only_sum:
                  t.add_row(["", "", "", "", "", "", ""])
              t.add_row(["Sum",
                         "-",
                         "-",
                         "%.2f %s" % (sum_reward[0], stm.backed_token_symbol),
                         "%.2f %s" % (sum_reward[1], sp_symbol),
                         "%.2f $" % (sum_reward[2]),
                         "%.2f $" % (sum_reward[3])])
          elif not author and not (permlink or title):
              t.add_row(["", "", "", "", ""])
              t.add_row(["Sum",
                         "%.2f %s" % (sum_reward[0], stm.backed_token_symbol),
                         "%.2f %s" % (sum_reward[1], sp_symbol),
                         "%.2f $" % (sum_reward[2]),
                         "%.2f $" % (sum_reward[3])])
          else:
              t.add_row(["", "", "", "", "", ""])
              t.add_row(["Sum",
                         "-",
                         "%.2f %s" % (sum_reward[0], stm.backed_token_symbol),
                         "%.2f %s" % (sum_reward[1], sp_symbol),
                         "%.2f $" % (sum_reward[2]),
                         "%.2f $" % (sum_reward[3])])
          message = "\nShowing pending "
          if post:
              if comment + curation == 0:
                  message += "post "
              elif comment + curation == 1:
                  message += "post and "
              else:
                  message += "post, "
          if comment:
              if curation == 0:
                  message += "comment "
              else:
                  message += "comment and "
          if curation:
              message += "curation "
          message += "rewards for @%s" % account.name
          print(message)
          print(t)
  
  
  @cli.command()
  @click.argument('account', nargs=1, required=False)
  @click.option('--reward_steem', help='Amount of STEEM/HIVE you would like to claim', default=0)
  @click.option('--reward_sbd', help='Amount of SBD/HBD you would like to claim', default=0)
  @click.option('--reward_vests', help='Amount of VESTS you would like to claim', default=0)
  @click.option('--claim_all_steem', help='Claim all STEEM/HIVE, overwrites reward_steem', is_flag=True)
  @click.option('--claim_all_sbd', help='Claim all SBD/HBD, overwrites reward_sbd', is_flag=True)
  @click.option('--claim_all_vests', help='Claim all VESTS, overwrites reward_vests', is_flag=True)
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def claimreward(account, reward_steem, reward_sbd, reward_vests, claim_all_steem, claim_all_sbd, claim_all_vests, export):
      """Claim reward balances
  
          By default, this will claim ``all`` outstanding balances.
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      acc = Account(account, blockchain_instance=stm)
      r = acc.balances["rewards"]
      if len(r) == 3 and r[0].amount + r[1].amount + r[2].amount == 0:
          print("Nothing to claim.")
          return
      elif len(r) == 2 and r[0].amount + r[1].amount:
          print("Nothing to claim.")
          return
      if not unlock_wallet(stm):
          return
      if claim_all_steem:
          reward_steem = r[0]
      if claim_all_sbd:
          reward_sbd = r[1]
      if claim_all_vests:
          reward_vests = r[2]
  
      tx = acc.claim_reward_balance(reward_steem, reward_sbd, reward_vests)
      if stm.unsigned and stm.nobroadcast and stm.steemconnect is not None:
          tx = stm.steemconnect.url_from_tx(tx)
      elif stm.unsigned and stm.nobroadcast and stm.hivesigner is not None:
          tx = stm.hivesigner.url_from_tx(tx)
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('jsonid', nargs=1)
  @click.argument('json_data', nargs=-1)
  @click.option('--account', '-a', help='The account which broadcasts the custom_json')
  @click.option('--active', '-t', help='When set, the active key is used for broadcasting', is_flag=True, default=False)
  @click.option('--export', '-e', help='When set, transaction is stored in a file')
  def customjson(jsonid, json_data, account, active, export):
      """Broadcasts a custom json
  
          First parameter is the cusom json id, the second field is a json file or a json key value combination
          e.g. beempy customjson -a holger80 dw-heist username holger80 amount 100
      """
      if jsonid is None:
          print("First argument must be the custom_json id")
      if json_data is None:
          print("Second argument must be the json_data, can be a string or a file name.")
      data = import_custom_json(jsonid, json_data)
      if data is None:
          return
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if not unlock_wallet(stm):
          return
      acc = Account(account, blockchain_instance=stm)
      if active:
          tx = stm.custom_json(jsonid, data, required_auths=[account])
      else:
          tx = stm.custom_json(jsonid, data, required_posting_auths=[account])
      export_trx(tx, export)
      tx = json.dumps(tx, indent=4)
      print(tx)
  
  
  @cli.command()
  @click.argument('blocknumber', nargs=1, required=False)
  @click.option('--trx', '-t', help='Show only one transaction number', default=None)
  @click.option('--use-api', '-u', help='Uses the get_potential_signatures api call', is_flag=True, default=False)
  def verify(blocknumber, trx, use_api):
      """Returns the public signing keys for a block"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      b = Blockchain(blockchain_instance=stm)
      i = 0
      if not blocknumber:
          blocknumber = b.get_current_block_num()
      try:
          int(blocknumber)
          block = Block(blocknumber, blockchain_instance=stm)
          if trx is not None:
              i = int(trx)
              trxs = [block.json_transactions[int(trx)]]
          else:
              trxs = block.json_transactions
      except Exception:
          trxs = [b.get_transaction(blocknumber)]
          blocknumber = trxs[0]["block_num"]
      wallet = Wallet(blockchain_instance=stm)
      t = PrettyTable(["trx", "Signer key", "Account"])
      t.align = "l"
      if not use_api:
          from beembase.signedtransactions import Signed_Transaction
      for trx in trxs:
          if not use_api:
              # trx is now identical to the output of get_transaction
              # This is just for testing porpuse
              if True:
                  signed_tx = Signed_Transaction(trx.copy())
              else:
                  tx = b.get_transaction(trx["transaction_id"])
                  signed_tx = Signed_Transaction(tx)
              public_keys = []
              for key in signed_tx.verify(chain=stm.chain_params, recover_parameter=True):
                  public_keys.append(format(Base58(key, prefix=stm.prefix), stm.prefix))
          else:
              tx = TransactionBuilder(tx=trx, blockchain_instance=stm)
              public_keys = tx.get_potential_signatures()
          accounts = []
          empty_public_keys = []
          for key in public_keys:
              account = wallet.getAccountFromPublicKey(key)
              if account is None:
                  empty_public_keys.append(key)
              else:
                  accounts.append(account)
          new_public_keys = []
          for key in public_keys:
              if key not in empty_public_keys or use_api:
                  new_public_keys.append(key)
          if len(new_public_keys) == 0:
              for key in public_keys:
                  new_public_keys.append(key)
          if isinstance(new_public_keys, list) and len(new_public_keys) == 1:
              new_public_keys = new_public_keys[0]
          else:
              new_public_keys = json.dumps(new_public_keys, indent=4)
          if isinstance(accounts, list) and len(accounts) == 1:
              accounts = accounts[0]
          else:
              accounts = json.dumps(accounts, indent=4)
          t.add_row(["%d" % i, new_public_keys, accounts])
          i += 1
      print(t)
  
  
  @cli.command()
  def chainconfig():
      """ Prints chain config in a table"""
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      chain_config = stm.get_config()
      t = PrettyTable(["Key", "Value"])
      t.align = "l"
      for key in chain_config:
          if isinstance(chain_config[key], dict) and 'amount' in chain_config[key]:
              t.add_row([key, str(Amount(chain_config[key], blockchain_instance=stm))])
          else:
              t.add_row([key, chain_config[key]])
      print(t)
  
  
  @cli.command()
  @click.argument('objects', nargs=-1)
  def info(objects):
      """ Show basic blockchain info
  
          General information about the blockchain, a block, an account,
          a post/comment and a public key
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not objects:
          t = PrettyTable(["Key", "Value"])
          t.align = "l"
          info = stm.get_dynamic_global_properties()
          median_price = stm.get_current_median_history()
          token_per_mvest = stm.get_token_per_mvest()
          chain_props = stm.get_chain_properties()
          try:
              price = (Amount(median_price["base"], blockchain_instance=stm).amount / Amount(median_price["quote"], blockchain_instance=stm).amount)
          except:
              price = None
          for key in info:
              if isinstance(info[key], dict) and 'amount' in info[key]:
                  t.add_row([key, str(Amount(info[key], blockchain_instance=stm))])
              else:
                  t.add_row([key, info[key]])
          t.add_row(["%s per mvest" % stm.token_symbol, token_per_mvest])
          if price is not None:
              t.add_row(["internal price", price])
          t.add_row(["account_creation_fee", str(Amount(chain_props["account_creation_fee"], blockchain_instance=stm))])
          print(t.get_string(sortby="Key"))
          # Block
      for obj in objects:
          if re.match(r"^[0-9-]*$", obj) or re.match(r"^-[0-9]*$", obj) or re.match(r"^[0-9-]*:[0-9]", obj) or re.match(r"^[0-9-]*:-[0-9]", obj):
              tran_nr = ''
              if re.match(r"^[0-9-]*:[0-9-]", obj):
                  obj, tran_nr = obj.split(":")
              if int(obj) < 1:
                  b = Blockchain(blockchain_instance=stm)
                  block_number = b.get_current_block_num() + int(obj) - 1
              else:
                  block_number = obj
              block = Block(block_number, blockchain_instance=stm)
              if block:
                  t = PrettyTable(["Key", "Value"])
                  t.align = "l"
                  block_json = block.json()
                  for key in sorted(block_json):
                      value = block_json[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 - 1 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 not bool(tran_nr):
                          t.add_row(["Nr. of transaction_ids", len(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) > tran_nr - 1 and tran_nr > -1:
                              t.add_row(["transaction_id %d/%d" % (int(tran_nr), len(value)), value[tran_nr]])
                      else:
                          t.add_row([key, value])
                  print(t)
              else:
                  print("Block number %s unknown" % obj)
          elif re.match(r"^[a-zA-Z0-9\-\._]{2,16}$", obj):
              account = Account(obj, blockchain_instance=stm)
              t = PrettyTable(["Key", "Value"])
              t.align = "l"
              t._max_width = {"Value" : 80}
              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, blockchain_instance=stm)
                  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(r"^" + stm.prefix + ".{48,55}$", obj):
              account = stm.wallet.getAccountFromPublicKey(obj)
              if account:
                  account = Account(account, blockchain_instance=stm)
                  key_type = stm.wallet.getKeyType(account, obj)
                  t = PrettyTable(["Account", "Key_type"])
                  t.align = "l"
                  t._max_width = {"Value" : 80}
                  t.add_row([account["name"], key_type])
                  print(t)
              else:
                  print("Public Key %s not known" % obj)
          # Post identifier
          elif re.match(r".*@.{3,16}/.*$", obj):
              post = Comment(obj, blockchain_instance=stm)
              post_json = post.json()
              if post_json:
                  t = PrettyTable(["Key", "Value"])
                  t.align = "l"
                  t._max_width = {"Value" : 80}
                  for key in sorted(post_json):
                      if key in ["body", "active_votes"]:
                          value = "not shown"
                      else:
                          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)
          elif re.match(r"^[a-zA-Z0-9\_]{40}$", obj):
              b = Blockchain(blockchain_instance=stm)
              from beemapi.exceptions import UnknownTransaction
              try:
                  trx = b.get_transaction(obj)
              except UnknownTransaction:
                  print("%s is unknown!" % obj)
                  return
              t = PrettyTable(["Key", "Value"])
              t.align = "l"
              t._max_width = {"Value" : 80}
              for key in trx:
                  value = trx[key]
                  if key in ["operations", "signatures"]:
                      value = json.dumps(value, indent=4)
                  t.add_row([key, value])
              print(t)
          else:
              print("Couldn't identify object to read")
  
  
  @cli.command()
  @click.argument('account', nargs=1, required=False)
  @click.option('--signing-account', '-s', help='Signing account, when empty account is used.')
  def userdata(account, signing_account):
      """ Get the account's email address and phone number.
  
          The request has to be signed by the requested account or an admin account.
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not unlock_wallet(stm):
          return
      if not account:
          if "default_account" in stm.config:
              account = stm.config["default_account"]
      account = Account(account, blockchain_instance=stm)
      if signing_account is not None:
          signing_account = Account(signing_account, blockchain_instance=stm)
      c = Conveyor(blockchain_instance=stm)
      user_data = c.get_user_data(account, signing_account=signing_account)
      t = PrettyTable(["Key", "Value"])
      t.align = "l"
      for key in user_data:
          # hide internal config data
          t.add_row([key, user_data[key]])
      print(t)
  
  
  @cli.command()
  @click.argument('account', nargs=1, required=False)
  @click.option('--limit', '-l', help='Defines how many ops should be printed (default=10)', default=10)
  @click.option('--sort', '-s', help='Defines the printing sorting, 1 ->, -1 <- (default=-1)', default=-1)
  @click.option('--max-length', '-m', help='Maximum printed string length', default=80)
  @click.option('--virtual-ops', '-v', help='When set, virtual ops are also shown', is_flag=True, default=False)
  @click.option('--only-ops', '-o', help='Included komma seperated list of op types, which limits the shown operations. When set, virtual-ops is always set to true')
  @click.option('--exclude-ops', '-e', help='Excluded komma seperated list of op types, which limits the shown operations.')
  @click.option('--json-file', '-j', help='When set, the results are written into a json file')
  def history(account, limit, sort, max_length, virtual_ops, only_ops, exclude_ops, json_file):
      """ Returns account history operations as table
  
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          if "default_account" in stm.config:
              account = stm.config["default_account"]
      account = Account(account, blockchain_instance=stm)
      t = PrettyTable(["Index","Type", "Hist op"])
      t.align = "l"
      t._max_width = {"Hist op" : max_length}
      cnt = 0
      batch_size = 1000
      if batch_size > int(limit) + 1 and int(limit) > 0:
          batch_size = int(limit) + 1
      if only_ops is None:
          only_ops = []
      else:
          only_ops = only_ops.split(",")
      if exclude_ops is None:
          exclude_ops = []
      else:
          exclude_ops = exclude_ops.split(",")
      if len(only_ops) > 0:
          virtual_ops = True
      data = []
      if int(sort) == -1:
          hist = account.history_reverse(batch_size=batch_size, only_ops=only_ops, exclude_ops=exclude_ops)
      else:
          hist = account.history(batch_size=batch_size, only_ops=only_ops, exclude_ops=exclude_ops)
      for h in hist:
  
          if h["virtual_op"] == 1 and not virtual_ops:
              continue
  
          cnt += 1
          if cnt > int(limit) and int(limit) > 0:
              break
          if json_file is not None:
              data.append(h)
          else:
              # if key in ["operations", "signatures"]:
              index = h.pop("index")
              op_type = h.pop("type")
              h.pop("trx_in_block")
              h.pop("op_in_trx")
              h.pop("virtual_op")
              h.pop("_id")
              if h["trx_id"] == "0000000000000000000000000000000000000000":
                  h.pop("trx_id")
              for key in h:
                  if isinstance(h[key], dict) and "nai" in h[key]:
                      h[key] = str(Amount(h[key], blockchain_instance=stm))
                  if key == "json" or key == "json_metadata" and h[key] is not None and h[key] != "":
                      h[key] = json.loads(h[key])
              value = json.dumps(h, indent=4)
              t.add_row([str(index), op_type, value])
  
      if json_file is not None:
          with open(json_file, "w", encoding="utf-8") as f:
              json.dump(data, f)
      else:
          print(t)
  
  
  @cli.command()
  @click.argument('account', nargs=1, required=False)
  @click.option('--signing-account', '-s', help='Signing account, when empty account is used.')
  def featureflags(account, signing_account):
      """ Get the account's feature flags.
  
          The request has to be signed by the requested account or an admin account.
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not unlock_wallet(stm):
          return
      if not account:
          if "default_account" in stm.config:
              account = stm.config["default_account"]
      account = Account(account, blockchain_instance=stm)
      if signing_account is not None:
          signing_account = Account(signing_account, blockchain_instance=stm)
      c = Conveyor(blockchain_instance=stm)
      user_data = c.get_feature_flags(account, signing_account=signing_account)
      t = PrettyTable(["Key", "Value"])
      t.align = "l"
      for key in user_data:
          # hide internal config data
          t.add_row([key, user_data[key]])
      print(t)
  
  
  @cli.command()
  @click.option('--block', '-b', help='Select a block number, when skipped the latest block is used.', default=None)
  @click.option('--trx-id', '-t', help='Select a trx-id, When skipped, the latest one is used.', default=None)
  @click.option('--draws', '-d', help='Number of draws (default = 1)', default=1)
  @click.option('--participants', '-p', help='Number of participants or file name including participants (one participant per line), (default = 100)', default="100")
  @click.option('--hashtype', '-h', help='Can be md5, sha256, sha512 (default = sha256)', default="sha256")
  @click.option('--separator', '-s', help='Is used for sha256 and sha512 to seperate the draw number from the seed (default = ,)', default=",")
  @click.option('--account', '-a', help='The account which broadcasts the reply')
  @click.option('--reply', '-r', help='Parent post/comment authorperm. When set, the results will be broadcasted as reply to this authorperm.', default=None)
  @click.option('--without-replacement', '-w', help='When set, numbers are drawed without replacement.', is_flag=True, default=False)
  @click.option('--markdown', '-m', help='When set, results are returned in markdown format', is_flag=True, default=False)
  def draw(block, trx_id, draws, participants, hashtype, separator, account, reply, without_replacement, markdown):
      """ Generate pseudo-random numbers based on trx id, block id and previous block id.
  
      When using --reply, the result is directly broadcasted as comment
      """
      stm = shared_blockchain_instance()
      if stm.rpc is not None:
          stm.rpc.rpcconnect()
      if not account:
          account = stm.config["default_account"]
      if reply is not None:
          if not unlock_wallet(stm):
              return
          reply_comment = Comment(reply, blockchain_instance=stm)
      if block is not None and block != "":
          block = Block(int(block), blockchain_instance=stm)
      else:
          blockchain = Blockchain(blockchain_instance=stm)
          block = blockchain.get_current_block()
      data = None
  
      for trx in block.transactions:
          if trx["transaction_id"] == trx_id:
              data = trx
          elif trx_id is None:
              trx_id = trx["transaction_id"]
              data = trx
      if trx_id is None:
          trx_id = "0"
  
      if os.path.exists(participants):
          with open(participants) as f:
              content = f.read()
          if content.find(",") > 0:
              participants_list = content.split(",")
          else:
              participants_list = content.split("\n")
          if participants_list[-1] == "":
              participants_list = participants_list[:-1]
          participants = len(participants_list)
      else:
          participants = int(participants)
          participants_list = []
  
      if without_replacement:
          assert draws <= participants
      trx = data["operations"][0]["value"]
      if hashtype == "md5":
          seed = hashlib.md5((trx_id + block["block_id"] + block["previous"]).encode()).hexdigest()
      elif hashtype == "sha256":
          seed = hashlib.sha256((trx_id + block["block_id"] + block["previous"]).encode()).hexdigest()
      elif hashtype == "sha512":
          seed = hashlib.sha512((trx_id + block["block_id"] + block["previous"]).encode()).hexdigest()
      random.seed(a=seed, version=2)
      t = PrettyTable(["Key", "Value"])
      t.align = "l"
      t.add_row(["block number", block["id"]])
      t.add_row(["trx id", trx_id])
      t.add_row(["block id", block["block_id"]])
      t.add_row(["previous", block["previous"]])
      t.add_row(["hash type", hashtype])
      t.add_row(["draws", draws])
      t.add_row(["participants", participants])
      draw_list = [x + 1 for x in range(participants)]
      results = []
      for i in range(int(draws)):
          if hashtype == "md5":
              number = int(random.random() * len(draw_list))
          elif hashtype == "sha256":
              seed = hashlib.sha256((trx_id + block["block_id"] + block["previous"] + separator +str(i + 1)).encode()).digest()
              bigRand = int.from_bytes(seed, 'big')
              number = bigRand % (len(draw_list))
          elif hashtype == "sha512":
              seed = hashlib.sha512((trx_id + block["block_id"] + block["previous"] + separator +str(i + 1)).encode()).digest()
              bigRand = int.from_bytes(seed, 'big')
              number = bigRand % (len(draw_list))
          results.append(draw_list[number])
          if len(participants_list) > 0:
              t.add_row(["%d. draw" % (i + 1), "%d - %s" % (draw_list[number], participants_list[draw_list[number] - 1])])
          else:
              t.add_row(["%d. draw" % (i + 1), draw_list[number]])
          if without_replacement:
              draw_list.pop(number)
  
      body = "The following results can be checked with:\n"
      body += "```\n"
      if without_replacement:
          body += "beempy draw -d %d -p %d -b %d -t %s -h %s -s '%s' -w\n" % (draws, participants, block["id"], trx_id, hashtype, separator)
      else:
          body += "beempy draw -d %d -p %d -b %d -t %s -h %s -s '%s'\n" % (draws, participants, block["id"], trx_id, hashtype, separator)
      body += "```\n\n"
      body += "| key | value |\n"
      body += "| --- | --- |\n"
      body += "| block number | [%d](https://hiveblocks.com/b/%d#%s) |\n" % (block["id"], block["id"], trx_id)
      body += "| trx id | [%s](https://hiveblocks.com/tx/%s) |\n" % (trx_id, trx_id)
      body += "| block id | %s |\n" % block["block_id"]
      body += "| previous id | %s |\n" % block["previous"]
      body += "| hash type | %s |\n" % hashtype
      body += "| draws | %d |\n" % draws
      body += "| participants | %d |\n" % participants
      i = 0
      for result in results:
          i += 1
          if len(participants_list) > 0:
              body += "| %d. draw | %d - %s |\n" % (i, result, participants_list[result - 1])
          else:
              body += "| %d. draw | %d |\n" % (i, result)
      if markdown:
          print(body)
      else:
          print(t)
      if reply:
          reply_comment.reply(body, author=account)
  
  
  if __name__ == "__main__":
      if getattr(sys, 'frozen', False):
          os.environ['SSL_CERT_FILE'] = os.path.join(sys._MEIPASS, 'lib', 'cert.pem')
          cli(sys.argv[1:])
      else:
          cli()
  