diff --git a/README.md b/README.md index f9ea6cec..e3d8d38a 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,22 @@ BTCLI accepts a few environment variables that can alter how it works: - DISK_CACHE (default 0, also settable in config): If set to 1 (or set in config), will use disk caching for various safe-cachable substrate calls (such as block number to block hash mapping), which can speed up subsequent calls. - BTCLI_CONFIG_PATH (default `~/.bittensor/config.yml`): This will set the config file location, creating if it does not exist. + - BTCLI_DEBUG_FILE (default `~/.bittensor/debug.txt`): The file stores the most recent's command's debug log. + +--- + +## Debugging +BTCLI will store a debug log for every command run. This file is overwritten for each new command run. The default location +of this file is `~/.bittensor/debug.txt` and can be set with the `BTCLI_DEBUG_FILE` env var (see above section). + +The debug log will **NOT** contain any sensitive data (private keys), and is intended to be sent to the developers +for debugging. This file contains basic information about the command being run, the config, and the back and forth of requests and responses +to and from the chain. + +If you encounter an issue, and would like to save the file somewhere it won't be overwritten, run `btcli --debug`, +and set the save file location. We recommend doing this first before anything, and then starting your debugging with +us on our [Discord](https://discord.gg/bittensor), or by opening an issue on [GitHub](https://github.com/opentensor/btcli/issues/new) +(where you can also upload your debug file). --- diff --git a/bittensor_cli/cli.py b/bittensor_cli/cli.py index 2044bae7..6e4559c6 100755 --- a/bittensor_cli/cli.py +++ b/bittensor_cli/cli.py @@ -4,6 +4,7 @@ import curses import importlib import json +import logging import os.path import re import ssl @@ -86,6 +87,7 @@ class GitError(Exception): pass +logger = logging.getLogger("btcli") _epilog = "Made with [bold red]:heart:[/bold red] by The Openτensor Foundaτion" np.set_printoptions(precision=8, suppress=True, floatmode="fixed") @@ -599,6 +601,28 @@ def commands_callback(value: bool): if value: cli = CLIManager() console.print(cli.generate_command_tree()) + + +def debug_callback(value: bool): + if value: + save_file_loc_ = Prompt.ask( + "Enter the file location to save the debug log for the previous command.", + default="~/.bittensor/debug-export", + ).strip() + save_file_loc = os.path.expanduser(save_file_loc_) + try: + with ( + open(save_file_loc, "w+") as save_file, + open( + os.getenv("BTCLI_DEBUG_FILE") + or os.path.expanduser(defaults.config.debug_file_path), + "r", + ) as current_file, + ): + save_file.write(current_file.read()) + console.print(f"Saved debug log to {save_file_loc}") + except FileNotFoundError: + print_error(f"The filepath '{save_file_loc}' does not exist.") raise typer.Exit() @@ -672,6 +696,9 @@ def __init__(self): self.config_path = os.getenv("BTCLI_CONFIG_PATH") or os.path.expanduser( defaults.config.path ) + self.debug_file_path = os.getenv("BTCLI_DEBUG_FILE") or os.path.expanduser( + defaults.config.debug_file_path + ) self.app = typer.Typer( rich_markup_mode="rich", @@ -1194,6 +1221,14 @@ def main_callback( "--commands", callback=commands_callback, help="Show BTCLI commands" ), ] = None, + debug_log: Annotated[ + Optional[bool], + typer.Option( + "--debug", + callback=debug_callback, + help="Saves the debug log from the last used command", + ), + ] = None, ): """ Command line interface (CLI) for Bittensor. Uses the values in the configuration file. These values can be @@ -1228,6 +1263,27 @@ def main_callback( for k, v in config.items(): if k in self.config.keys(): self.config[k] = v + if self.config.get("use_cache", False): + with open(self.debug_file_path, "w+") as f: + f.write( + f"BTCLI {__version__}\n" + f"Async-Substrate-Interface: {importlib.metadata.version('async-substrate-interface')}\n" + f"Bittensor-Wallet: {importlib.metadata.version('bittensor-wallet')}\n" + f"Command: {' '.join(sys.argv)}\n" + f"Config: {self.config}\n" + f"Python: {sys.version}\n" + f"System: {sys.platform}\n\n" + ) + asi_logger = logging.getLogger("async_substrate_interface") + asi_logger.setLevel(logging.DEBUG) + logger.setLevel(logging.DEBUG) + formatter = logging.Formatter( + "%(asctime)s - %(levelname)s - %(name)s - %(module)s:%(lineno)d - %(message)s" + ) + handler = logging.FileHandler(self.debug_file_path) + handler.setFormatter(formatter) + asi_logger.addHandler(handler) + logger.addHandler(handler) def verbosity_handler( self, quiet: bool, verbose: bool, json_output: bool = False @@ -1427,6 +1483,7 @@ def set_config( for arg, val in args.items(): if val is not None: + logger.debug(f"Config: setting {arg} to {val}") self.config[arg] = val with open(self.config_path, "w") as f: safe_dump(self.config, f) @@ -1492,6 +1549,7 @@ def del_config( for arg in args.keys(): if self.config.get(arg) is not None: if Confirm.ask(f"Do you want to clear the {arg__(arg)} config?"): + logger.debug(f"Config: clearing {arg}.") self.config[arg] = None console.print(f"Cleared {arg__(arg)} config and set to 'None'.") else: @@ -1507,6 +1565,7 @@ def del_config( f" [bold cyan]({self.config.get(arg)})[/bold cyan] config?" ): self.config[arg] = None + logger.debug(f"Config: clearing {arg}.") console.print( f"Cleared {arg__(arg)} config and set to 'None'." ) @@ -1604,26 +1663,31 @@ def ask_safe_staking( bool: Safe staking setting """ if safe_staking is not None: + enabled = "enabled" if safe_staking else "disabled" console.print( - f"[dim][blue]Safe staking[/blue]: [bold cyan]{'enabled' if safe_staking else 'disabled'}[/bold cyan]." + f"[dim][blue]Safe staking[/blue]: [bold cyan]{enabled}[/bold cyan]." ) + logger.debug(f"Safe staking {enabled}") return safe_staking elif self.config.get("safe_staking") is not None: safe_staking = self.config["safe_staking"] + enabled = "enabled" if safe_staking else "disabled" console.print( - f"[dim][blue]Safe staking[/blue]: [bold cyan]{'enabled' if safe_staking else 'disabled'}[/bold cyan] (from config)." + f"[dim][blue]Safe staking[/blue]: [bold cyan]{enabled}[/bold cyan] (from config)." ) + logger.debug(f"Safe staking {enabled}") return safe_staking else: safe_staking = True console.print( "[dim][blue]Safe staking[/blue]: " - + f"[bold cyan]{'enabled' if safe_staking else 'disabled'}[/bold cyan] " - + "by default. Set this using " - + "[dark_sea_green3 italic]`btcli config set`[/dark_sea_green3 italic] " - + "or " - + "[dark_sea_green3 italic]`--safe/--unsafe`[/dark_sea_green3 italic] flag[/dim]" + f"[bold cyan]enabled[/bold cyan] " + "by default. Set this using " + "[dark_sea_green3 italic]`btcli config set`[/dark_sea_green3 italic] " + "or " + "[dark_sea_green3 italic]`--safe/--unsafe`[/dark_sea_green3 italic] flag[/dim]" ) + logger.debug(f"Safe staking enabled.") return safe_staking def ask_partial_stake( @@ -1640,25 +1704,31 @@ def ask_partial_stake( bool: Partial stake setting """ if allow_partial_stake is not None: + partial_staking = "enabled" if allow_partial_stake else "disabled" console.print( - f"[dim][blue]Partial staking[/blue]: [bold cyan]{'enabled' if allow_partial_stake else 'disabled'}[/bold cyan]." + f"[dim][blue]Partial staking[/blue]: [bold cyan]{partial_staking}[/bold cyan]." ) + logger.debug(f"Partial staking {partial_staking}") return allow_partial_stake elif self.config.get("allow_partial_stake") is not None: config_partial = self.config["allow_partial_stake"] + partial_staking = "enabled" if allow_partial_stake else "disabled" console.print( - f"[dim][blue]Partial staking[/blue]: [bold cyan]{'enabled' if config_partial else 'disabled'}[/bold cyan] (from config)." + f"[dim][blue]Partial staking[/blue]: [bold cyan]{partial_staking}[/bold cyan] (from config)." ) + logger.debug(f"Partial staking {partial_staking}") return config_partial else: + partial_staking = "enabled" if allow_partial_stake else "disabled" console.print( "[dim][blue]Partial staking[/blue]: " - + f"[bold cyan]{'enabled' if allow_partial_stake else 'disabled'}[/bold cyan] " - + "by default. Set this using " - + "[dark_sea_green3 italic]`btcli config set`[/dark_sea_green3 italic] " - + "or " - + "[dark_sea_green3 italic]`--partial/--no-partial`[/dark_sea_green3 italic] flag[/dim]" + f"[bold cyan]{partial_staking}[/bold cyan] " + "by default. Set this using " + "[dark_sea_green3 italic]`btcli config set`[/dark_sea_green3 italic] " + "or " + "[dark_sea_green3 italic]`--partial/--no-partial`[/dark_sea_green3 italic] flag[/dim]" ) + logger.debug(f"Partial staking {partial_staking}") return False def wallet_ask( @@ -1731,6 +1801,7 @@ def wallet_ask( if wallet_path: wallet_path = os.path.expanduser(wallet_path) wallet = Wallet(name=wallet_name, path=wallet_path, hotkey=wallet_hotkey) + logger.debug(f"Using wallet {wallet}") # Validate the wallet if required if validate == WV.WALLET or validate == WV.WALLET_AND_HOTKEY: @@ -1886,6 +1957,15 @@ def wallet_overview( str, "Hotkeys names must be a comma-separated list, e.g., `--exclude-hotkeys hk1,hk2`.", ) + logger.debug( + "args:\n" + f"all_wallets: {all_wallets}\n" + f"sort_by: {sort_by}\n" + f"sort_order: {sort_order}\n" + f"include_hotkeys: {include_hotkeys}\n" + f"exclude_hotkeys: {exclude_hotkeys}\n" + f"netuids: {netuids}\n" + ) return self._run_command( wallets.overview( @@ -1975,6 +2055,15 @@ def wallet_transfer( amount = 0 elif not amount: amount = FloatPrompt.ask("Enter amount (in TAO) to transfer.") + logger.debug( + "args:\n" + f"destination: {destination_ss58_address}\n" + f"amount: {amount}\n" + f"transfer_all: {transfer_all}\n" + f"allow_death: {allow_death}\n" + f"period: {period}\n" + f"prompt: {prompt}\n" + ) return self._run_command( wallets.transfer( wallet=wallet, @@ -2044,6 +2133,13 @@ def wallet_swap_hotkey( ask_for=[WO.NAME, WO.PATH, WO.HOTKEY], validate=WV.WALLET_AND_HOTKEY, ) + logger.debug( + "args:\n" + f"original_wallet: {original_wallet}\n" + f"new_wallet: {new_wallet}\n" + f"netuid: {netuid}\n" + f"prompt: {prompt}\n" + ) self.initialize_chain(network) return self._run_command( wallets.swap_hotkey( @@ -2207,6 +2303,17 @@ def wallet_faucet( ask_for=[WO.NAME, WO.PATH], validate=WV.WALLET, ) + logger.debug( + "args:\n" + f"network {network}\n" + f"threads_per_block {threads_per_block}\n" + f"update_interval {update_interval}\n" + f"processors {processors}\n" + f"use_cuda {use_cuda}\n" + f"dev_id {dev_id}\n" + f"output_in_place {output_in_place}\n" + f"max_successes {max_successes}\n" + ) return self._run_command( wallets.faucet( wallet, @@ -2274,6 +2381,7 @@ def wallet_regen_coldkey( mnemonic, seed, json_path, json_password = get_creation_data( mnemonic, seed, json_path, json_password ) + # logger.debug should NOT be used here, it's simply too risky return self._run_command( wallets.regen_coldkey( wallet, @@ -2343,6 +2451,7 @@ def wallet_regen_coldkey_pub( ): rich.print("[red]Error: Invalid SS58 address or public key![/red]") return + # do not logger.debug any creation cmds return self._run_command( wallets.regen_coldkey_pub( wallet, ss58_address, public_key_hex, overwrite, json_output @@ -2395,6 +2504,7 @@ def wallet_regen_hotkey( mnemonic, seed, json_path, json_password = get_creation_data( mnemonic, seed, json_path, json_password ) + # do not logger.debug any creation cmds return self._run_command( wallets.regen_hotkey( wallet, @@ -2464,6 +2574,7 @@ def wallet_regen_hotkey_pub( ): rich.print("[red]Error: Invalid SS58 address or public key![/red]") return False + # do not logger.debug any creation cmds return self._run_command( wallets.regen_hotkey_pub( wallet, ss58_address, public_key_hex, overwrite, json_output @@ -2528,6 +2639,7 @@ def wallet_new_hotkey( ) if not uri: n_words = get_n_words(n_words) + # do not logger.debug any creation cmds return self._run_command( wallets.new_hotkey( wallet, n_words, use_password, uri, overwrite, json_output @@ -2594,7 +2706,13 @@ def wallet_associate_hotkey( f"hotkey [blue]{wallet_hotkey}[/blue] " f"[{COLORS.GENERAL.HK}]({hotkey_ss58})[/{COLORS.GENERAL.HK}]" ) - + logger.debug( + "args:\n" + f"network {network}\n" + f"hotkey_ss58 {hotkey_ss58}\n" + f"hotkey_display {hotkey_display}\n" + f"prompt {prompt}\n" + ) return self._run_command( wallets.associate_hotkey( wallet, @@ -2742,7 +2860,8 @@ def wallet_check_ck_swap( if not scheduled_block: block_input = Prompt.ask( - "[blue]Enter the block number[/blue] where the swap was scheduled [dim](optional, press enter to skip)[/dim]", + "[blue]Enter the block number[/blue] where the swap was scheduled " + "[dim](optional, press enter to skip)[/dim]", default="", ) if block_input: @@ -2751,7 +2870,12 @@ def wallet_check_ck_swap( except ValueError: print_error("Invalid block number") raise typer.Exit() - + logger.debug( + "args:\n" + f"scheduled_block {scheduled_block}\n" + f"ss58_address {ss58_address}\n" + f"network {network}\n" + ) return self._run_command( wallets.check_swap_status(self.subtensor, ss58_address, scheduled_block) ) @@ -2808,6 +2932,7 @@ def wallet_create_wallet( ) if not uri: n_words = get_n_words(n_words) + # do not logger.debug any creation commands return self._run_command( wallets.wallet_create( wallet, n_words, use_password, uri, overwrite, json_output @@ -2916,6 +3041,12 @@ def wallet_balance( ask_for=ask_for, validate=validate, ) + logger.debug( + "args:\n" + f"all_balances {all_balances}\n" + f"ss58_addresses {ss58_addresses}\n" + f"network {network}" + ) subtensor = self.initialize_chain(network) return self._run_command( wallets.wallet_balance( @@ -3066,6 +3197,7 @@ def wallet_set_id( additional, github_repo, ) + logger.debug(f"args:\nidentity {identity}\nnetwork {network}\n") return self._run_command( wallets.set_id( @@ -3327,7 +3459,12 @@ def wallet_swap_coldkey( f"[dark_sea_green3]{new_wallet}[/dark_sea_green3]\n" ) new_wallet_coldkey_ss58 = new_wallet.coldkeypub.ss58_address - + logger.debug( + "args:\n" + f"network {network}\n" + f"new_coldkey_ss58 {new_wallet_coldkey_ss58}\n" + f"force_swap {force_swap}" + ) return self._run_command( wallets.schedule_coldkey_swap( wallet=wallet, @@ -3399,7 +3536,13 @@ def stake_list( wallet = self.wallet_ask( wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH] ) - + logger.debug( + "args:\n" + f"coldkey_ss58 {coldkey_ss58}\n" + f"network {network}\n" + f"live: {live}\n" + f"no_prompt: {no_prompt}\n" + ) return self._run_command( list_stake.stake_list( wallet, @@ -3648,6 +3791,7 @@ def stake_add( ), exit_early=False, ) + logger.debug(f"Free balance: {free_balance}") if free_balance == Balance.from_tao(0): print_error("You dont have any balance to stake.") return @@ -3668,7 +3812,21 @@ def stake_add( f"You dont have enough balance to stake. Current free Balance: {free_balance}." ) raise typer.Exit() - + logger.debug( + "args:\n" + f"network: {network}\n" + f"netuids: {netuids}\n" + f"stake_all: {stake_all}\n" + f"amount: {amount}\n" + f"prompt: {prompt}\n" + f"all_hotkeys: {all_hotkeys}\n" + f"include_hotkeys: {include_hotkeys}\n" + f"exclude_hotkeys: {exclude_hotkeys}\n" + f"safe_staking: {safe_staking}\n" + f"rate_tolerance: {rate_tolerance}\n" + f"allow_partial_stake: {allow_partial_stake}\n" + f"period: {period}\n" + ) return self._run_command( add_stake.stake_add( wallet, @@ -3936,6 +4094,17 @@ def stake_remove( ask_for=[WO.NAME, WO.PATH, WO.HOTKEY], validate=WV.WALLET_AND_HOTKEY, ) + logger.debug( + "args:\n" + f"network: {network}\n" + f"hotkey_ss58_address: {hotkey_ss58_address}\n" + f"unstake_all: {unstake_all}\n" + f"unstake_all_alpha: {unstake_all_alpha}\n" + f"all_hotkeys: {all_hotkeys}\n" + f"include_hotkeys: {include_hotkeys}\n" + f"exclude_hotkeys: {exclude_hotkeys}\n" + f"era: {period}" + ) return self._run_command( remove_stake.unstake_all( wallet=wallet, @@ -3986,6 +4155,22 @@ def stake_remove( } ) return False + logger.debug( + "args:\n" + f"network: {network}\n" + f"hotkey_ss58_address: {hotkey_ss58_address}\n" + f"all_hotkeys: {all_hotkeys}\n" + f"include_hotkeys: {include_hotkeys}\n" + f"exclude_hotkeys: {exclude_hotkeys}\n" + f"amount: {amount}\n" + f"prompt: {prompt}\n" + f"interactive: {interactive}\n" + f"netuid: {netuid}\n" + f"safe_staking: {safe_staking}\n" + f"rate_tolerance: {rate_tolerance}\n" + f"allow_partial_stake: {allow_partial_stake}\n" + f"era: {period}" + ) return self._run_command( remove_stake.unstake( @@ -4150,7 +4335,19 @@ def stake_move( destination_netuid = IntPrompt.ask( "Enter the [blue]destination subnet[/blue] (netuid) to move stake to" ) - + logger.debug( + "args:\n" + f"network: {network}\n" + f"origin_netuid: {origin_netuid}\n" + f"origin_hotkey: {origin_hotkey}\n" + f"destination_hotkey: {destination_hotkey}\n" + f"destination_netuid: {destination_netuid}\n" + f"amount: {amount}\n" + f"stake_all: {stake_all}\n" + f"era: {period}\n" + f"interactive_selection: {interactive_selection}\n" + f"prompt: {prompt}\n" + ) result = self._run_command( move_stake.move_stake( subtensor=self.initialize_chain(network), @@ -4315,7 +4512,18 @@ def stake_transfer( dest_netuid = IntPrompt.ask( "Enter the [blue]destination subnet[/blue] (netuid)" ) - + logger.debug( + "args:\n" + f"network: {network}\n" + f"origin_hotkey: {origin_hotkey}\n" + f"origin_netuid: {origin_netuid}\n" + f"dest_netuid: {dest_netuid}\n" + f"dest_hotkey: {origin_hotkey}\n" + f"dest_coldkey_ss58: {dest_ss58}\n" + f"amount: {amount}\n" + f"era: {period}\n" + f"stake_all: {stake_all}" + ) result = self._run_command( move_stake.transfer_stake( wallet=wallet, @@ -4423,7 +4631,19 @@ def stake_swap( ) if not amount and not swap_all: amount = FloatPrompt.ask("Enter the [blue]amount[/blue] to swap") - + logger.debug( + "args:\n" + f"network: {network}\n" + f"origin_netuid: {origin_netuid}\n" + f"dest_netuid: {dest_netuid}\n" + f"amount: {amount}\n" + f"swap_all: {swap_all}\n" + f"era: {period}\n" + f"interactive_selection: {interactive_selection}\n" + f"prompt: {prompt}\n" + f"wait_for_inclusion: {wait_for_inclusion}\n" + f"wait_for_finalization: {wait_for_finalization}\n" + ) result = self._run_command( move_stake.swap_stake( wallet=wallet, @@ -4572,6 +4792,15 @@ def stake_set_children( ask_for=[WO.NAME, WO.HOTKEY], validate=WV.WALLET_AND_HOTKEY, ) + logger.debug( + "args:\n" + f"network: {network}\n" + f"netuid: {netuid}\n" + f"children: {children}\n" + f"proportions: {proportions}\n" + f"wait_for_inclusion: {wait_for_inclusion}\n" + f"wait_for_finalization: {wait_for_finalization}\n" + ) return self._run_command( children_hotkeys.set_children( wallet=wallet, @@ -4637,6 +4866,13 @@ def stake_revoke_children( netuid = IntPrompt.ask( "Enter netuid (leave blank for all)", default=None, show_default=True ) + logger.debug( + "args:\n" + f"network: {network}\n" + f"netuid: {netuid}\n" + f"wait_for_inclusion: {wait_for_inclusion}\n" + f"wait_for_finalization: {wait_for_finalization}\n" + ) return self._run_command( children_hotkeys.revoke_children( wallet, @@ -4715,6 +4951,14 @@ def stake_childkey_take( netuid = IntPrompt.ask( "Enter netuid (leave blank for all)", default=None, show_default=True ) + logger.debug( + "args:\n" + f"network: {network}\n" + f"netuid: {netuid}\n" + f"take: {take}\n" + f"wait_for_inclusion: {wait_for_inclusion}\n" + f"wait_for_finalization: {wait_for_finalization}\n" + ) results: list[tuple[Optional[int], bool]] = self._run_command( children_hotkeys.childkey_take( wallet=wallet, @@ -4846,6 +5090,13 @@ def sudo_set( wallet = self.wallet_ask( wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH] ) + logger.debug( + "args:\n" + f"network: {network}\n" + f"netuid: {netuid}\n" + f"param_name: {param_name}\n" + f"param_value: {param_value}" + ) result, err_msg = self._run_command( sudo.sudo_set_hyperparameter( wallet, @@ -4966,6 +5217,7 @@ def sudo_senate_vote( ask_for=[WO.NAME, WO.PATH, WO.HOTKEY], validate=WV.WALLET_AND_HOTKEY, ) + logger.debug(f"args:\nnetwork: {network}\nproposal: {proposal}\nvote: {vote}\n") return self._run_command( sudo.senate_vote( wallet, self.initialize_chain(network), proposal, vote, prompt @@ -5018,7 +5270,7 @@ def sudo_set_take( f"Take value must be between {min_value} and {max_value}. Provided value: {take}" ) raise typer.Exit() - + logger.debug(f"args:\nnetwork: {network}\ntake: {take}") result = self._run_command( sudo.set_take(wallet, self.initialize_chain(network), take) ) @@ -5359,6 +5611,7 @@ def subnets_create( logo_url=logo_url, additional=additional_info, ) + logger.debug(f"args:\nnetwork: {network}\nidentity: {identity}\n") self._run_command( subnets.create( wallet, self.initialize_chain(network), identity, json_output, prompt @@ -5420,6 +5673,7 @@ def subnets_start( ], validate=WV.WALLET, ) + logger.debug(f"args:\nnetwork: {network}\nnetuid: {netuid}\n") return self._run_command( subnets.start_subnet( wallet, @@ -5535,7 +5789,9 @@ def subnets_set_identity( logo_url=logo_url, additional=additional_info, ) - + logger.debug( + f"args:\nnetwork: {network}\nnetuid: {netuid}\nidentity: {identity}" + ) success = self._run_command( subnets.set_identity( wallet, self.initialize_chain(network), netuid, identity, prompt @@ -5673,6 +5929,7 @@ def subnets_register( ask_for=[WO.NAME, WO.HOTKEY], validate=WV.WALLET_AND_HOTKEY, ) + logger.debug(f"args:\nnetwork: {network}\nnetuid: {netuid}\nperiod: {period}\n") return self._run_command( subnets.register( wallet, @@ -5870,7 +6127,6 @@ def weights_reveal( ask_for=[WO.NAME, WO.PATH, WO.HOTKEY], validate=WV.WALLET_AND_HOTKEY, ) - return self._run_command( weights_cmds.reveal_weights( self.initialize_chain(network), @@ -6116,7 +6372,14 @@ def liquidity_add( if price_low >= price_high: err_console.print("The low price must be lower than the high price.") return False - + logger.debug( + f"args:\n" + f"hotkey: {hotkey}\n" + f"netuid: {netuid}\n" + f"liquidity: {liquidity_}\n" + f"price_low: {price_low}\n" + f"price_high: {price_high}\n" + ) return self._run_command( liquidity.add_liquidity( subtensor=self.initialize_chain(network), @@ -6217,6 +6480,14 @@ def liquidity_remove( validate=WV.WALLET, return_wallet_and_hotkey=True, ) + logger.debug( + f"args:\n" + f"network: {network}\n" + f"hotkey: {hotkey}\n" + f"netuid: {netuid}\n" + f"position_id: {position_id}\n" + f"all_liquidity_ids: {all_liquidity_ids}\n" + ) return self._run_command( liquidity.remove_liquidity( subtensor=self.initialize_chain(network), @@ -6281,6 +6552,14 @@ def liquidity_modify( f"[blue]{position_id}[/blue] (can be positive or negative)", negative_allowed=True, ) + logger.debug( + f"args:\n" + f"network: {network}\n" + f"hotkey: {hotkey}\n" + f"netuid: {netuid}\n" + f"position_id: {position_id}\n" + f"liquidity_delta: {liquidity_delta}" + ) return self._run_command( liquidity.modify_liquidity( diff --git a/bittensor_cli/src/__init__.py b/bittensor_cli/src/__init__.py index afabc424..ef9493ca 100644 --- a/bittensor_cli/src/__init__.py +++ b/bittensor_cli/src/__init__.py @@ -88,6 +88,7 @@ class Defaults: class config: base_path = "~/.bittensor" path = "~/.bittensor/config.yml" + debug_file_path = "~/.bittensor/debug.txt" dictionary = { "network": None, "wallet_path": None, diff --git a/bittensor_cli/src/commands/stake/remove.py b/bittensor_cli/src/commands/stake/remove.py index 67f0109f..3a37b8cb 100644 --- a/bittensor_cli/src/commands/stake/remove.py +++ b/bittensor_cli/src/commands/stake/remove.py @@ -361,6 +361,7 @@ async def unstake( ) if json_output: json_console.print(json.dumps(successes)) + return True async def unstake_all( diff --git a/bittensor_cli/src/commands/wallets.py b/bittensor_cli/src/commands/wallets.py index ff37a50e..b45a5d0e 100644 --- a/bittensor_cli/src/commands/wallets.py +++ b/bittensor_cli/src/commands/wallets.py @@ -1836,7 +1836,7 @@ async def check_coldkey_swap(wallet: Wallet, subtensor: SubtensorInterface): async def sign( - wallet: Wallet, message: str, use_hotkey: str, json_output: bool = False + wallet: Wallet, message: str, use_hotkey: bool, json_output: bool = False ): """Sign a message using the provided wallet or hotkey.""" diff --git a/pyproject.toml b/pyproject.toml index 767047b3..5a47f2b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ scripts = { btcli = "bittensor_cli.cli:main" } requires-python = ">=3.9,<3.14" dependencies = [ "wheel", - "async-substrate-interface>=1.4.2", + "async-substrate-interface>=1.5.2", "aiohttp~=3.10.2", "backoff~=2.2.1", "GitPython>=3.0.0",