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
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])
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
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})" )
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
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" )
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))
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()