async def get_coin_records_by_spent(
     self, spent: bool, spend_before_height: Optional[uint32] = None
 ) -> Set[WalletCoinRecord]:
     """ Returns set of CoinRecords that have not been spent yet. """
     coins = set()
     if spend_before_height:
         cursor = await self.db_connection.execute(
             "SELECT * from coin_record WHERE spent=? OR spent_index>=?",
             (int(spent), spend_before_height),
         )
     else:
         cursor = await self.db_connection.execute(
             "SELECT * from coin_record WHERE spent=?", (int(spent),)
         )
     rows = await cursor.fetchall()
     await cursor.close()
     for row in rows:
         coin = Coin(
             bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), row[7]
         )
         coins.add(
             WalletCoinRecord(
                 coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9]
             )
         )
     return coins
    async def get_unspent_coins_for_wallet(
            self, wallet_id: int) -> Set[WalletCoinRecord]:
        """ Returns set of CoinRecords that have not been spent yet for a wallet. """
        async with self.wallet_cache_lock:
            if wallet_id in self.coin_wallet_record_cache:
                wallet_coins: Dict[
                    bytes32, WalletCoinRecord] = self.coin_wallet_record_cache[
                        wallet_id]
                return set(wallet_coins.values())

            coin_set = set()

            cursor = await self.db_connection.execute(
                "SELECT * from coin_record WHERE spent=0 and wallet_id=?",
                (wallet_id, ),
            )
            rows = await cursor.fetchall()
            await cursor.close()
            cache_dict = {}
            for row in rows:
                coin = Coin(bytes32(bytes.fromhex(row[6])),
                            bytes32(bytes.fromhex(row[5])),
                            uint64.from_bytes(row[7]))
                coin_record = WalletCoinRecord(coin, row[1], row[2],
                                               row[3], row[4],
                                               WalletType(row[8]), row[9])
                coin_set.add(coin_record)
                cache_dict[coin.name()] = coin_record

            self.coin_wallet_record_cache[wallet_id] = cache_dict
            return coin_set
    async def get_spendable_for_index(
        self, index: uint32, wallet_id: int
    ) -> Set[WalletCoinRecord]:
        """
        Returns set of unspent coin records that are not coinbases, or if they are coinbases,
        must have been confirmed at or before index.
        """
        coins = set()

        cursor_coinbase_coins = await self.db_connection.execute(
            "SELECT * from coin_record WHERE spent=? and confirmed_index<=? and wallet_id=? and coinbase=?",
            (0, int(index), wallet_id, 1),
        )

        coinbase_rows = await cursor_coinbase_coins.fetchall()
        await cursor_coinbase_coins.close()

        cursor_regular_coins = await self.db_connection.execute(
            "SELECT * from coin_record WHERE spent=? and wallet_id=? and coinbase=?",
            (0, wallet_id, 0,),
        )

        regular_rows = await cursor_regular_coins.fetchall()
        await cursor_regular_coins.close()

        for row in coinbase_rows + regular_rows:
            coin = Coin(
                bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), row[7]
            )
            coins.add(
                WalletCoinRecord(
                    coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9]
                )
            )
        return coins
 async def get_unspent_coins_at_height(
     self, height: Optional[uint32] = None
 ) -> Set[WalletCoinRecord]:
     """
     Returns set of CoinRecords that have not been spent yet. If a height is specified,
     We can also return coins that were unspent at this height (but maybe spent later).
     Finally, the coins must be confirmed at the height or less.
     """
     coins = set()
     if height is not None:
         cursor = await self.db_connection.execute(
             "SELECT * from coin_record WHERE (spent=? OR spent_index>?) AND confirmed_index<=?",
             (0, height, height),
         )
     else:
         cursor = await self.db_connection.execute(
             "SELECT * from coin_record WHERE spent=?", (0,)
         )
     rows = await cursor.fetchall()
     await cursor.close()
     for row in rows:
         coin = Coin(
             bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), row[7]
         )
         coins.add(
             WalletCoinRecord(
                 coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9]
             )
         )
     return coins
Exemple #5
0
async def print_balances(args, wallet_client, fingerprint: int):
    summaries_response = await wallet_client.get_wallets()
    print(f"Balances, fingerprint: {fingerprint}")
    for summary in summaries_response:
        wallet_id = summary["id"]
        balances = await wallet_client.get_wallet_balance(wallet_id)
        typ = WalletType(int(summary["type"])).name
        if typ != "STANDARD_WALLET":
            print(f"Wallet ID {wallet_id} type {typ} {summary['name']}")
            print(
                f"   -Confirmed: balances['confirmed_wallet_balance']"
                f"{balances['confirmed_wallet_balance']/units['colouredcoin']}"
            )
            print(
                f"   -Unconfirmed: {balances['unconfirmed_wallet_balance']/units['colouredcoin']}"
            )
            print(
                f"   -Spendable: {balances['spendable_balance']/units['colouredcoin']}"
            )
            print(
                f"   -Pending change: {balances['pending_change']/units['colouredcoin']}"
            )
        else:
            print(f"Wallet ID {wallet_id} type {typ}")
            print(
                f"   -Confirmed: {balances['confirmed_wallet_balance']} mojo "
                f"({balances['confirmed_wallet_balance']/units['chia']} TXCH)")
            print(
                f"   -Unconfirmed: {balances['unconfirmed_wallet_balance']} mojo "
                f"({balances['unconfirmed_wallet_balance']/units['chia']} TXCH)"
            )
            print(f"   -Spendable: {balances['spendable_balance']} mojo "
                  f"({balances['spendable_balance']/units['chia']} TXCH)")
            print(f"   -Pending change: {balances['pending_change']} mojo "
                  f"({balances['pending_change']/units['chia']} TXCH)")
 async def get_coin_records_by_puzzle_hash(self, puzzle_hash: bytes32) -> List[WalletCoinRecord]:
     """Returns a list of all coin records with the given puzzle hash"""
     coins = set()
     cursor = await self.db_connection.execute("SELECT * from coin_record WHERE puzzle_hash=?", (puzzle_hash.hex(),))
     rows = await cursor.fetchall()
     await cursor.close()
     for row in rows:
         coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7]))
         coins.add(WalletCoinRecord(coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9]))
     return list(coins)
    async def get_coin_record_by_coin_id(self, coin_id: bytes32) -> Optional[WalletCoinRecord]:
        """Returns a coin records with the given name, if it exists"""
        cursor = await self.db_connection.execute("SELECT * from coin_record WHERE coin_name=?", (coin_id.hex(),))
        row = await cursor.fetchone()
        await cursor.close()
        if row is None:
            return None

        coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7]))
        coin_record = WalletCoinRecord(coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9])
        return coin_record
    async def get_all_coins(self) -> Set[WalletCoinRecord]:
        """ Returns set of all CoinRecords."""
        coins = set()

        cursor = await self.db_connection.execute("SELECT * from coin_record")
        rows = await cursor.fetchall()
        await cursor.close()
        for row in rows:
            coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7]))
            coins.add(WalletCoinRecord(coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9]))
        return coins
 async def get_coin_record(self, coin_name: bytes32) -> Optional[WalletCoinRecord]:
     """ Returns CoinRecord with specified coin id. """
     if coin_name in self.coin_record_cache:
         return self.coin_record_cache[coin_name]
     cursor = await self.db_connection.execute("SELECT * from coin_record WHERE coin_name=?", (coin_name.hex(),))
     row = await cursor.fetchone()
     await cursor.close()
     if row is not None:
         coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7]))
         return WalletCoinRecord(coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9])
     return None
    async def get_all_wallets(self) -> List[WalletInfo]:
        """
        Return a set containing all wallets
        """

        cursor = await self.db_connection.execute("SELECT * from users_wallets")
        rows = await cursor.fetchall()
        await cursor.close()
        result = []

        for row in rows:
            result.append(WalletInfo(row[0], row[1], WalletType(row[2]), row[3]))

        return result
    async def get_wallet_by_id(self, id: int) -> Optional[WalletInfo]:
        """
        Return a wallet by id
        """

        cursor = await self.db_connection.execute(
            "SELECT * from users_wallets WHERE id=?", (id, ))
        row = await cursor.fetchone()
        await cursor.close()

        if row is None:
            return None

        return WalletInfo(row[0], row[1], WalletType(row[2]), row[3])
    async def get_wallet_action(self, id: int) -> Optional[WalletAction]:
        """
        Return a wallet action by id
        """

        cursor = await self.db_connection.execute(
            "SELECT * from action_queue WHERE id=?", (id, ))
        row = await cursor.fetchone()
        await cursor.close()

        if row is None:
            return None

        return WalletAction(row[0], row[1], row[2], WalletType(row[3]), row[4],
                            bool(row[5]), row[6])
Exemple #13
0
    async def wallet_info_for_puzzle_hash(self, puzzle_hash: bytes32) -> Optional[Tuple[uint32, WalletType]]:
        """
        Returns the derivation path for the puzzle_hash.
        Returns None if not present.
        """

        cursor = await self.db_connection.execute(
            "SELECT * from derivation_paths WHERE puzzle_hash=?", (puzzle_hash.hex(),)
        )
        row = await cursor.fetchone()
        await cursor.close()

        if row is not None:
            return row[4], WalletType(row[3])

        return None
Exemple #14
0
async def print_balances(args: dict, wallet_client: WalletRpcClient,
                         fingerprint: int) -> None:
    summaries_response = await wallet_client.get_wallets()
    config = load_config(DEFAULT_ROOT_PATH, "config.yaml")
    address_prefix = config["network_overrides"]["config"][
        config["selected_network"]]["address_prefix"]

    print(f"Wallet height: {await wallet_client.get_height_info()}")
    print(f"Balances, fingerprint: {fingerprint}")
    for summary in summaries_response:
        wallet_id = summary["id"]
        balances = await wallet_client.get_wallet_balance(wallet_id)
        typ = WalletType(int(summary["type"])).name
        if typ != "STANDARD_WALLET":
            print(f"Wallet ID {wallet_id} type {typ} {summary['name']}")
            print(
                f"   -Confirmed: "
                f"{balances['confirmed_wallet_balance']/units['colouredcoin']}"
            )
            print(
                f"   -Unconfirmed: {balances['unconfirmed_wallet_balance']/units['colouredcoin']}"
            )
            print(
                f"   -Spendable: {balances['spendable_balance']/units['colouredcoin']}"
            )
            print(
                f"   -Pending change: {balances['pending_change']/units['colouredcoin']}"
            )
        else:
            print(f"Wallet ID {wallet_id} type {typ}")
            print(
                f"   -Confirmed: {balances['confirmed_wallet_balance']} mojo "
                f"({balances['confirmed_wallet_balance']/units['chia']} {address_prefix})"
            )
            print(
                f"   -Unconfirmed: {balances['unconfirmed_wallet_balance']} mojo "
                f"({balances['unconfirmed_wallet_balance']/units['chia']} {address_prefix})"
            )
            print(
                f"   -Spendable: {balances['spendable_balance']} mojo "
                f"({balances['spendable_balance']/units['chia']} {address_prefix})"
            )
            print(
                f"   -Pending change: {balances['pending_change']} mojo "
                f"({balances['pending_change']/units['chia']} {address_prefix})"
            )
Exemple #15
0
    async def get_unspent_coins_for_wallet(
            self, wallet_id: int) -> Set[WalletCoinRecord]:
        """ Returns set of CoinRecords that have not been spent yet for a wallet. """
        coins = set()

        cursor = await self.db_connection.execute(
            "SELECT * from coin_record WHERE spent=0 and wallet_id=?",
            (wallet_id, ),
        )
        rows = await cursor.fetchall()
        await cursor.close()
        for row in rows:
            coin = Coin(bytes32(bytes.fromhex(row[6])),
                        bytes32(bytes.fromhex(row[5])), row[7])
            coins.add(
                WalletCoinRecord(coin, row[1], row[2], row[3], row[4],
                                 WalletType(row[8]), row[9]))
        return coins
    async def get_all_pending_actions(self) -> List[WalletAction]:
        """
        Returns list of all pending action
        """
        result: List[WalletAction] = []
        cursor = await self.db_connection.execute(
            "SELECT * from action_queue WHERE done=?", (0, ))
        rows = await cursor.fetchall()
        await cursor.close()

        if rows is None:
            return result

        for row in rows:
            action = WalletAction(row[0], row[1], row[2], WalletType(row[3]),
                                  row[4], bool(row[5]), row[6])
            result.append(action)

        return result
Exemple #17
0
async def print_balances(wallet_client):
    summaries_response = await wallet_client.get_wallets()
    print("Balances")
    for summary in summaries_response:
        wallet_id = summary["id"]
        balances = await wallet_client.get_wallet_balance(wallet_id)
        typ = WalletType(int(summary["type"])).name
        if "name" in summary:
            print(f"Wallet ID {wallet_id} type {typ} {summary['name']}")
            print(
                f"   -Confirmed: {balances['confirmed_wallet_balance']/units['colouredcoin']}"
            )
            print(
                f"   -Unconfirmed: {balances['unconfirmed_wallet_balance']/units['colouredcoin']}"
            )
            print(
                f"   -Spendable: {balances['spendable_balance']/units['colouredcoin']}"
            )
            print(
                f"   -Frozen: {balances['frozen_balance']/units['colouredcoin']}"
            )
            print(
                f"   -Pending change: {balances['pending_change']/units['colouredcoin']}"
            )
        else:
            print(f"Wallet ID {wallet_id} type {typ}")
            print(
                f"   -Confirmed: {balances['confirmed_wallet_balance']/units['chia']} TXCH"
            )
            print(
                f"   -Unconfirmed: {balances['unconfirmed_wallet_balance']/units['chia']} TXCH"
            )
            print(
                f"   -Spendable: {balances['spendable_balance']/units['chia']} TXCH"
            )
            print(
                f"   -Frozen: {balances['frozen_balance']/units['chia']} TXCH")
            print(
                f"   -Pending change: {balances['pending_change']/units['chia']} TXCH"
            )
Exemple #18
0
def get_backup_info(file_path, private_key):
    json_dict = open_backup_file(file_path, private_key)
    data = json_dict["data"]
    wallet_list_json = data["wallet_list"]

    info_dict = {}
    wallets = []
    for wallet_info in wallet_list_json:
        wallet = {}
        wallet["name"] = wallet_info["name"]
        wallet["type"] = wallet_info["type"]
        wallet["type_name"] = WalletType(wallet_info["type"]).name
        wallet["id"] = wallet_info["id"]
        wallet["data"] = wallet_info["data"]
        wallets.append(wallet)

    info_dict["version"] = data["version"]
    info_dict["fingerprint"] = data["fingerprint"]
    info_dict["timestamp"] = data["timestamp"]
    info_dict["wallets"] = wallets

    return info_dict
    async def create_more_puzzle_hashes(self, from_zero: bool = False):
        """
        For all wallets in the user store, generates the first few puzzle hashes so
        that we can restore the wallet from only the private keys.
        """
        targets = list(self.wallets.keys())

        unused: Optional[uint32] = await self.puzzle_store.get_unused_derivation_path()
        if unused is None:
            # This handles the case where the database has entries but they have all been used
            unused = await self.puzzle_store.get_last_derivation_path()
            if unused is None:
                # This handles the case where the database is empty
                unused = uint32(0)

        if self.new_wallet:
            to_generate = self.config["initial_num_public_keys_new_wallet"]
        else:
            to_generate = self.config["initial_num_public_keys"]

        for wallet_id in targets:
            target_wallet = self.wallets[wallet_id]

            last: Optional[uint32] = await self.puzzle_store.get_last_derivation_path_for_wallet(wallet_id)

            start_index = 0
            derivation_paths: List[DerivationRecord] = []

            if last is not None:
                start_index = last + 1

            # If the key was replaced (from_zero=True), we should generate the puzzle hashes for the new key
            if from_zero:
                start_index = 0

            for index in range(start_index, unused + to_generate):
                if WalletType(target_wallet.type()) == WalletType.RATE_LIMITED:
                    if target_wallet.rl_info.initialized is False:
                        break
                    wallet_type = target_wallet.rl_info.type
                    if wallet_type == "user":
                        rl_pubkey = G1Element.from_bytes(target_wallet.rl_info.user_pubkey)
                    else:
                        rl_pubkey = G1Element.from_bytes(target_wallet.rl_info.admin_pubkey)
                    rl_puzzle: Program = target_wallet.puzzle_for_pk(rl_pubkey)
                    puzzle_hash: bytes32 = rl_puzzle.get_tree_hash()

                    rl_index = self.get_derivation_index(rl_pubkey)
                    if rl_index == -1:
                        break

                    derivation_paths.append(
                        DerivationRecord(
                            uint32(rl_index),
                            puzzle_hash,
                            rl_pubkey,
                            target_wallet.type(),
                            uint32(target_wallet.id()),
                        )
                    )
                    break

                pubkey: G1Element = self.get_public_key(uint32(index))
                puzzle: Program = target_wallet.puzzle_for_pk(bytes(pubkey))
                if puzzle is None:
                    self.log.warning(f"Unable to create puzzles with wallet {target_wallet}")
                    break
                puzzlehash: bytes32 = puzzle.get_tree_hash()
                self.log.info(f"Puzzle at index {index} wallet ID {wallet_id} puzzle hash {puzzlehash.hex()}")
                derivation_paths.append(
                    DerivationRecord(
                        uint32(index),
                        puzzlehash,
                        pubkey,
                        target_wallet.type(),
                        uint32(target_wallet.id()),
                    )
                )

            await self.puzzle_store.add_derivation_paths(derivation_paths)
        if unused > 0:
            await self.puzzle_store.set_used_up_to(uint32(unused - 1))
Exemple #20
0
async def show_async(args, parser):

    # TODO read configuration for rpc_port instead of assuming default

    try:
        config = load_config(DEFAULT_ROOT_PATH, "config.yaml")
        self_hostname = config["self_hostname"]
        if "rpc_port" not in args or args.rpc_port is None:
            rpc_port = config["full_node"]["rpc_port"]
        else:
            rpc_port = args.rpc_port
        client = await FullNodeRpcClient.create(self_hostname, rpc_port)

        if args.state:
            blockchain_state = await client.get_blockchain_state()
            lca_block = blockchain_state["lca"]
            tips = blockchain_state["tips"]
            difficulty = blockchain_state["difficulty"]
            ips = blockchain_state["ips"]
            sync_mode = blockchain_state["sync"]["sync_mode"]
            total_iters = lca_block.data.total_iters
            num_blocks: int = 10

            if sync_mode:
                sync_max_block = blockchain_state["sync"]["sync_tip_height"]
                sync_current_block = blockchain_state["sync"][
                    "sync_progress_height"]
                # print (max_block)
                print(
                    "Current Blockchain Status: Full Node syncing to",
                    sync_max_block,
                    "\nCurrently synched to tip:",
                    sync_current_block,
                )
            else:
                print("Current Blockchain Status: Full Node Synced")
            print("Latest Common Ancestor:\n    ", lca_block.header_hash)
            lca_time = struct_time(localtime(lca_block.data.timestamp))
            # Should auto format the align right of LCA height
            print(
                "     LCA time:",
                time.strftime("%a %b %d %Y %T %Z", lca_time),
                "       LCA height:",
                lca_block.height,
            )
            print("Heights of tips: " + str([h.height for h in tips]))
            print(f"Current difficulty: {difficulty}")
            print(f"Current VDF iterations per second: {ips:.0f}")
            print("Total iterations since genesis:", total_iters)
            print("")
            heads: List[HeaderBlock] = tips
            added_blocks: List[HeaderBlock] = []
            while len(added_blocks) < num_blocks and len(heads) > 0:
                heads = sorted(heads, key=lambda b: b.height, reverse=True)
                max_block = heads[0]
                if max_block not in added_blocks:
                    added_blocks.append(max_block)
                heads.remove(max_block)
                prev: Optional[HeaderBlock] = await client.get_header(
                    max_block.prev_header_hash)
                if prev is not None:
                    heads.append(prev)

            latest_blocks_labels = []
            for i, b in enumerate(added_blocks):
                latest_blocks_labels.append(
                    f"{b.height}:{b.header_hash}"
                    f" {'LCA' if b.header_hash == lca_block.header_hash else ''}"
                    f" {'TIP' if b.header_hash in [h.header_hash for h in tips] else ''}"
                )
            for i in range(len(latest_blocks_labels)):
                if i < 2:
                    print(latest_blocks_labels[i])
                elif i == 2:
                    print(
                        latest_blocks_labels[i],
                        "\n",
                        "                                -----",
                    )
                else:
                    print("", latest_blocks_labels[i])
            # if called together with connections, leave a blank line
            if args.connections:
                print("")
        if args.connections:
            connections = await client.get_connections()
            print("Connections")
            print(
                "Type      IP                                      Ports      NodeID        Last Connect"
                + "       MiB Up|Dwn")
            for con in connections:
                last_connect_tuple = struct_time(
                    localtime(con["last_message_time"]))
                # last_connect = time.ctime(con['last_message_time'])
                last_connect = time.strftime("%b %d %T", last_connect_tuple)
                mb_down = con["bytes_read"] / 1024
                mb_up = con["bytes_written"] / 1024
                # print (last_connect)
                con_str = (
                    f"{NodeType(con['type']).name:9} {con['peer_host']:39} "
                    f"{con['peer_port']:5}/{con['peer_server_port']:<5}"
                    f"{con['node_id'].hex()[:10]}... "
                    f"{last_connect}  "
                    f"{mb_down:7.1f}|{mb_up:<7.1f}")
                print(con_str)
            # if called together with state, leave a blank line
            if args.state:
                print("")
        if args.exit_node:
            node_stop = await client.stop_node()
            print(node_stop, "Node stopped.")
        if args.add_connection:
            if ":" not in args.add_connection:
                print(
                    "Enter a valid IP and port in the following format: 10.5.4.3:8000"
                )
            else:
                ip, port = (
                    ":".join(args.add_connection.split(":")[:-1]),
                    args.add_connection.split(":")[-1],
                )
            print(f"Connecting to {ip}, {port}")
            try:
                await client.open_connection(ip, int(port))
            except Exception:
                # TODO: catch right exception
                print(f"Failed to connect to {ip}:{port}")
        if args.remove_connection:
            result_txt = ""
            if len(args.remove_connection) != 10:
                result_txt = "Invalid NodeID"
            else:
                connections = await client.get_connections()
                for con in connections:
                    if args.remove_connection == con["node_id"].hex()[:10]:
                        print("Attempting to disconnect", "NodeID",
                              args.remove_connection)
                        try:
                            await client.close_connection(con["node_id"])
                        except Exception:
                            result_txt = (
                                f"Failed to disconnect NodeID {args.remove_connection}"
                            )
                        else:
                            result_txt = f"NodeID {args.remove_connection}... {NodeType(con['type']).name} "
                            f"{con['peer_host']} disconnected."
                    elif result_txt == "":
                        result_txt = f"NodeID {args.remove_connection}... not found."
            print(result_txt)
        if args.block_header_hash_by_height != "":
            block_header = await client.get_header_by_height(
                args.block_header_hash_by_height)
            if block_header is not None:
                block_header_string = str(block_header.get_hash())
                print(
                    f"Header hash of block {args.block_header_hash_by_height}: {block_header_string}"
                )
            else:
                print("Block height", args.block_header_hash_by_height,
                      "not found.")
        if args.block_by_header_hash != "":
            block = await client.get_block(
                hexstr_to_bytes(args.block_by_header_hash))
            # Would like to have a verbose flag for this
            if block is not None:
                prev_block_header_hash = block.header.data.prev_header_hash
                prev_block_header = await client.get_block(
                    prev_block_header_hash)
                block_time = struct_time(localtime(
                    block.header.data.timestamp))
                block_time_string = time.strftime("%a %b %d %Y %T %Z",
                                                  block_time)
                if block.header.data.aggregated_signature is None:
                    aggregated_signature = block.header.data.aggregated_signature
                else:
                    aggregated_signature = block.header.data.aggregated_signature
                print("Block", block.header.data.height, ":")
                print(
                    f"Header Hash            0x{args.block_by_header_hash}\n"
                    f"Timestamp              {block_time_string}\n"
                    f"Height                 {block.header.data.height}\n"
                    f"Weight                 {block.header.data.weight}\n"
                    f"Previous Block         0x{block.header.data.prev_header_hash}\n"
                    f"Cost                   {block.header.data.cost}\n"
                    f"Difficulty             {block.header.data.weight-prev_block_header.header.data.weight}\n"
                    f"Total VDF Iterations   {block.header.data.total_iters}\n"
                    f"Block VDF Iterations   {block.proof_of_time.number_of_iterations}\n"
                    f"PoTime Witness Type    {block.proof_of_time.witness_type}\n"
                    f"PoSpace 'k' Size       {block.proof_of_space.size}\n"
                    f"Plot Public Key        0x{block.proof_of_space.plot_public_key}\n"
                    f"Pool Public Key        0x{block.proof_of_space.pool_public_key}\n"
                    f"Tx Filter Hash         {b'block.transactions_filter'.hex()}\n"
                    f"Tx Generator Hash      {block.transactions_generator}\n"
                    f"Coinbase Amount        {block.get_coinbase().amount/1000000000000}\n"
                    f"Coinbase Puzzle Hash   0x{block.get_coinbase().puzzle_hash}\n"
                    f"Fees Amount            {block.get_fees_coin().amount/1000000000000}\n"
                    f"Fees Puzzle Hash       0x{block.get_fees_coin().puzzle_hash}\n"
                    f"Aggregated Signature   {aggregated_signature}")
            else:
                print("Block with header hash", args.block_by_header_hash,
                      "not found.")

        if args.wallet_balances:
            if "wallet_rpc_port" not in args or args.wallet_rpc_port is None:
                wallet_rpc_port = config["wallet"]["rpc_port"]
            else:
                wallet_rpc_port = args.wallet_rpc_port
            wallet_client = await WalletRpcClient.create(
                self_hostname, wallet_rpc_port)
            get_keys_response = await wallet_client.get_keys()
            if ("public_key_fingerprints" not in get_keys_response
                    or len(get_keys_response["public_key_fingerprints"]) == 0):
                print("Error, no keys loaded")
                wallet_client.close()
                await wallet_client.await_closed()
                client.close()
                await client.await_closed()
                return
            fingerprints = get_keys_response["public_key_fingerprints"]
            fingerprint = None
            if len(fingerprints) == 1:
                fingerprint = fingerprints[0][0]
                log_in_response = await wallet_client.log_in(fingerprint)
            else:
                print("Choose wallet key:")
                for i, fp in enumerate(fingerprints):
                    print(f"{i+1}) {fp[0]}")
                val = None
                while val is None:
                    val = input("Enter a number to pick or q to quit: ")
                    if val == "q":
                        return
                    if not val.isdigit():
                        val = None
                    else:
                        index = int(val) - 1
                        if index >= len(fingerprints):
                            print("Invalid value")
                            val = None
                            continue
                        else:
                            fingerprint = fingerprints[index][0]
                log_in_response = await wallet_client.log_in(fingerprint)

            if log_in_response["success"] is False:
                if log_in_response["error"] == "not_initialized":
                    use_cloud = True
                    if "backup_path" in log_in_response:
                        path = log_in_response["backup_path"]
                        print(
                            f"Backup file from backup.chia.net downloaded and written to: {path}"
                        )
                        val = input(
                            "Do you want to use this file to restore from backup? (Y/N) "
                        )
                        if val.lower() == "y":
                            log_in_response = await wallet_client.log_in_and_restore(
                                fingerprint, path)
                        else:
                            use_cloud = False

                    if "backup_path" not in log_in_response or use_cloud is False:
                        if use_cloud is True:
                            val = input(
                                "No online backup file found, \n Press S to skip restore from backup"
                                " \n Press F to use your own backup file: ")
                        else:
                            val = input(
                                "Cloud backup declined, \n Press S to skip restore from backup"
                                " \n Press F to use your own backup file: ")

                        if val.lower() == "s":
                            log_in_response = await wallet_client.log_in_and_skip(
                                fingerprint)
                        elif val.lower() == "f":
                            val = input(
                                "Please provide the full path to your backup file: "
                            )
                            log_in_response = await wallet_client.log_in_and_restore(
                                fingerprint, val)

            if "success" not in log_in_response or log_in_response[
                    "success"] is False:
                if "error" in log_in_response:
                    error = log_in_response["error"]
                    print(f"Error: {log_in_response[error]}")

            summaries_response = await wallet_client.get_wallet_summaries()
            if "wallet_summaries" not in summaries_response:
                print("Wallet summary cannot be displayed")
            else:
                print("Balances")
                for wallet_id, summary in summaries_response[
                        "wallet_summaries"].items():
                    balances_response = await wallet_client.get_wallet_balance(
                        wallet_id)
                    if "wallet_balance" not in balances_response:
                        print("Balances cannot be displayed")
                        continue
                    balances = balances_response["wallet_balance"]
                    typ = WalletType(int(summary["type"])).name
                    if "name" in summary:
                        print(
                            f"Wallet ID {wallet_id} type {typ} {summary['name']}"
                        )
                        print(
                            f"   -Confirmed: {balances['confirmed_wallet_balance']/units['colouredcoin']}"
                        )
                        print(
                            f"   -Unconfirmed: {balances['unconfirmed_wallet_balance']/units['colouredcoin']}"
                        )
                        print(
                            f"   -Spendable: {balances['spendable_balance']/units['colouredcoin']}"
                        )
                        print(
                            f"   -Frozen: {balances['frozen_balance']/units['colouredcoin']}"
                        )
                        print(
                            f"   -Pending change: {balances['pending_change']/units['colouredcoin']}"
                        )
                    else:
                        print(f"Wallet ID {wallet_id} type {typ}")
                        print(
                            f"   -Confirmed: {balances['confirmed_wallet_balance']/units['chia']} TXCH"
                        )
                        print(
                            f"   -Unconfirmed: {balances['unconfirmed_wallet_balance']/units['chia']} TXCH"
                        )
                        print(
                            f"   -Spendable: {balances['spendable_balance']/units['chia']} TXCH"
                        )
                        print(
                            f"   -Frozen: {balances['frozen_balance']/units['chia']} TXCH"
                        )
                        print(
                            f"   -Pending change: {balances['pending_change']/units['chia']} TXCH"
                        )
            wallet_client.close()
            await wallet_client.await_closed()

    except Exception as e:
        if isinstance(e, aiohttp.client_exceptions.ClientConnectorError):
            print(
                f"Connection error. Check if full node is running at {args.rpc_port}"
            )
        else:
            print(f"Exception from 'show' {e}")

    client.close()
    await client.await_closed()