def test_list_wallets(self): """ test list_wallets """ # remove any wallets we might have created in other tests temp_dir = tempfile.gettempdir() for f in os.listdir(temp_dir): if f.startswith(KEYFILE_PREFIX) and f.endswith(KEYFILE_POSTFIX): os.remove(os.path.join(temp_dir, f)) # there should be no wallets self.assertEqual(list_wallets(), []) # make one wallet private_key = "0x8da4ef21b864d2cc526dbdb2a120bd2874c36c9d0a1fb7f8c63d7f7a8b41de8f" # noqa: mock password = "******" import_and_save_wallet(password, private_key) self.assertEqual(len(list_wallets()), 1) # reimporting an existing wallet should not change the count import_and_save_wallet(password, private_key) self.assertEqual(len(list_wallets()), 1) # make a second wallet private_key2 = "0xaaaaaf21b864d2cc526dbdb2a120bd2874c36c9d0a1fb7f8c63d7f7a8b41eeee" # noqa: mock password2 = "topsecrettopsecret" import_and_save_wallet(password2, private_key2) self.assertEqual(len(list_wallets()), 2)
async def single_prompt(cvar: ConfigVar): if cvar.required or single_key: if cvar.key == "strategy_file_path": val = await self._import_or_create_strategy_config() elif cvar.key == "wallet": wallets = list_wallets() if len(wallets) > 0: val = await self._unlock_wallet() else: val = await self._create_or_import_wallet() logging.getLogger("hummingbot.public_eth_address").info( val) else: val = await self.app.prompt(prompt=cvar.prompt, is_password=cvar.is_secure) if not cvar.validate(val): self.app.log("%s is not a valid %s value" % (val, cvar.key)) val = await single_prompt(cvar) else: val = cvar.value if val is None or (isinstance(val, string_types) and len(val) == 0): val = cvar.default return val
async def _unlock_wallet(self): choice = await self.app.prompt( prompt= "Would you like to unlock your previously saved wallet? (y/n) >>> " ) if choice.lower() in {"y", "yes"}: wallets = list_wallets() self.app.log("Existing wallets:") self.list(obj="wallets") if len(wallets) == 1: public_key = wallets[0] else: public_key = await self.app.prompt( prompt="Which wallet would you like to import ? >>> ") password = await self.app.prompt(prompt="Enter your password >>> ", is_password=True) try: acct = unlock_wallet(public_key=public_key, password=password) self.app.log("Wallet %s unlocked" % (acct.address, )) self.acct = acct return self.acct.address except Exception as e: self.app.log("Cannot unlock wallet. Please try again.") result = await self._unlock_wallet() return result else: value = await self._create_or_import_wallet() return value
async def prompt_single_variable( self, # type: HummingbotApplication cvar: ConfigVar, requirement_overwrite: bool = False) -> Any: """ Prompt a single variable in the input pane, validates and returns the user input :param cvar: the config var to be prompted :param requirement_overwrite: Set to true when a config var is forced to be prompted, even if it is not required by default setting :return: a validated user input or the variable's default value """ if cvar.required or requirement_overwrite: if cvar.key == "strategy_file_path": val = await self._import_or_create_strategy_config() elif cvar.key == "wallet": wallets = list_wallets() if len(wallets) > 0: val = await self._unlock_wallet() else: val = await self._create_or_import_wallet() logging.getLogger("hummingbot.public_eth_address").info(val) else: val = await self.app.prompt(prompt=cvar.prompt, is_password=cvar.is_secure) if not cvar.validate(val): self._notify("%s is not a valid %s value" % (val, cvar.key)) val = await self.prompt_single_variable( cvar, requirement_overwrite) else: val = cvar.value if val is None or (isinstance(val, string_types) and len(val) == 0): val = cvar.default return val
async def _unlock_wallet( self, # type: HummingbotApplication ): """ Special handler function that helps the user unlock an existing wallet, or redirect user to create a new wallet. """ choice = await self.app.prompt( prompt= "Would you like to unlock your previously saved wallet? (y/n) >>> " ) if choice.lower() in {"y", "yes"}: wallets = list_wallets() self._notify("Existing wallets:") self.list(obj="wallets") if len(wallets) == 1: public_key = wallets[0] else: public_key = await self.app.prompt( prompt="Which wallet would you like to import ? >>> ") password = await self.app.prompt(prompt="Enter your password >>> ", is_password=True) try: acct = unlock_wallet(public_key=public_key, password=password) self._notify("Wallet %s unlocked" % (acct.address, )) self.acct = acct return self.acct.address except Exception: self._notify("Cannot unlock wallet. Please try again.") result = await self._unlock_wallet() return result else: value = await self._create_or_import_wallet() return value
def list_wallet(self, # type: HummingbotApplication ): wallets = list_wallets() if len(wallets) == 0: self._notify('Wallet not available. Please configure your wallet (Enter "config wallet")') else: self._notify('\n'.join(wallets))
def test_register(self): random_email: str = "".join(random.choice(string.ascii_lowercase[:12]) for i in range(7)) + "@hummingbot.io" random_eth_address: str = list_wallets()[0] try: [results] = self.run_parallel(self.bounty.register(email=random_email, eth_address=random_eth_address)) self.assertEqual(results["participation_status"], "valid") except Exception as e: self.assertTrue("email/ethereum_address is already registered" in str(e))
def decrypt_all(cls): cls._secure_configs.clear() cls._private_keys.clear() cls._decryption_done.clear() encrypted_files = list_encrypted_file_paths() for file in encrypted_files: cls.decrypt_file(file) wallets = list_wallets() for wallet in wallets: cls.unlock_wallet(wallet) cls._decryption_done.set()
async def _unlock_wallet( self, # type: HummingbotApplication ): """ Special handler function that helps the user unlock an existing wallet, or redirect user to create a new wallet. """ choice = await self.app.prompt( prompt= "Would you like to unlock your previously saved wallet? (y/n) >>> " ) if choice.lower() in {"y", "yes"}: wallets = list_wallets() self._notify("Existing wallets:") self.list(obj="wallets") if len(wallets) == 1: public_key = wallets[0] else: public_key = await self.app.prompt( prompt="Which wallet would you like to import ? >>> ") password = in_memory_config_map["password"].value try: acct = unlock_wallet(public_key=public_key, password=password) self._notify("Wallet %s unlocked" % (acct.address, )) self.acct = acct return self.acct.address except ValueError as err: if str(err) != "MAC mismatch": raise err self._notify("The wallet was locked by a different password.") old_password = await self.app.prompt( prompt="Please enter the password >>> ", is_password=True) try: acct = unlock_wallet(public_key=public_key, password=old_password) self._notify("Wallet %s unlocked" % (acct.address, )) save_wallet(acct, password) self._notify( f"Wallet {acct.address} is now saved with your main password." ) self.acct = acct return self.acct.address except ValueError as err: if str(err) != "MAC mismatch": raise err self._notify("Cannot unlock wallet. Please try again.") return await self._unlock_wallet() else: value = await self._create_or_import_wallet() return value
async def _one_password_config( self, # type: HummingbotApplication ): """ Special handler function to handle one password unlocking all secure conf variable and wallets - let a user creates a new password if there is no existing encrypted_files or key_files. - verify the entered password is valid by trying to unlock files. """ encrypted_files = list_encrypted_file_paths() wallets = list_wallets() password_valid = False err_msg = "Invalid password, please try again." if not encrypted_files and not wallets: password = await self.app.prompt( prompt="Enter your new password >>> ", is_password=True) re_password = await self.app.prompt( prompt="Please reenter your password >>> ", is_password=True) if password == re_password: password_valid = True else: err_msg = "Passwords entered do not match, please try again." else: password = await self.app.prompt(prompt="Enter your password >>> ", is_password=True) if encrypted_files: try: decrypt_file(encrypted_files[0], password) password_valid = True except ValueError as err: if str(err) != "MAC mismatch": raise err else: for wallet in wallets: try: unlock_wallet(public_key=wallet, password=password) password_valid = True break except ValueError as err: if str(err) != "MAC mismatch": raise err if password_valid: return password else: self._notify(err_msg) return await self._one_password_config()
async def prompt_single_variable( self, # type: HummingbotApplication cvar: ConfigVar, requirement_overwrite: bool = False) -> Any: """ Prompt a single variable in the input pane, validates and returns the user input :param cvar: the config var to be prompted :param requirement_overwrite: Set to true when a config var is forced to be prompted, even if it is not required by default setting :return: a validated user input or the variable's default value """ if cvar.required or requirement_overwrite: if cvar.key == "password": return await self._one_password_config() if cvar.key == "strategy_file_path": val = await self._import_or_create_strategy_config() elif cvar.key == "wallet": wallets = list_wallets() if len(wallets) > 0: val = await self._unlock_wallet() else: val = await self._create_or_import_wallet() else: if cvar.value is None: self.app.set_text(parse_cvar_default_value_prompt(cvar)) val = await self.app.prompt(prompt=cvar.prompt, is_password=cvar.is_secure) if not cvar.validate(val): # If the user inputs an empty string, use the default val_is_empty = val is None or (isinstance(val, str) and len(val) == 0) if cvar.default is not None and val_is_empty: val = cvar.default else: self._notify("%s is not a valid %s value" % (val, cvar.key)) val = await self.prompt_single_variable( cvar, requirement_overwrite) else: val = cvar.value if val is None or (isinstance(val, str) and len(val) == 0): val = cvar.default return val
def login(cls, password): encrypted_files = list_encrypted_file_paths() wallets = list_wallets() if encrypted_files: try: decrypt_file(encrypted_files[0], password) except ValueError as err: if str(err) == "MAC mismatch": return False raise err elif wallets: try: unlock_wallet(wallets[0], password) except ValueError as err: if str(err) == "MAC mismatch": return False raise err Security.password = password coro = AsyncCallScheduler.shared_instance().call_async(cls.decrypt_all, timeout_seconds=30) safe_ensure_future(coro) return True
def any_wallets(): return len(list_wallets()) > 0
def new_password_required(): encrypted_files = list_encrypted_file_paths() wallets = list_wallets() return len(encrypted_files) == 0 and len(wallets) == 0
def _wallet_address_completer(self): return WordCompleter(list_wallets(), ignore_case=True)
def list(self, obj: str): if obj == "wallets": wallets = list_wallets() if len(wallets) == 0: self.app.log( 'Wallet not available. Please configure your wallet (Enter "config wallet")' ) else: self.app.log('\n'.join(wallets)) elif obj == "exchanges": if len(EXCHANGES) == 0: self.app.log("No exchanges available") else: self.app.log('\n'.join(EXCHANGES)) elif obj == "configs": columns: List[str] = ["Key", "Current Value"] global_cvs: List[ConfigVar] = list( in_memory_config_map.values()) + list( global_config_map.values()) global_data: List[List[str, Any]] = [[ cv.key, len(str(cv.value)) * "*" if cv.is_secure else str(cv.value) ] for cv in global_cvs] global_df: pd.DataFrame = pd.DataFrame(data=global_data, columns=columns) self.app.log("\nglobal configs:") self.app.log(str(global_df)) strategy = in_memory_config_map.get("strategy").value if strategy: strategy_cvs: List[ConfigVar] = get_strategy_config_map( strategy).values() strategy_data: List[List[str, Any]] = [[ cv.key, len(str(cv.value)) * "*" if cv.is_secure else str(cv.value) ] for cv in strategy_cvs] strategy_df: pd.DataFrame = pd.DataFrame(data=strategy_data, columns=columns) self.app.log(f"\n{strategy} strategy configs:") self.app.log(str(strategy_df)) self.app.log("\n") elif obj == "trades": lines = [] if self.strategy is None: self.app.log("No strategy available, cannot show past trades.") else: if len(self.strategy.trades) > 0: df = Trade.to_pandas(self.strategy.trades) df_lines = str(df).split("\n") lines.extend(["", " Past trades:"] + [" " + line for line in df_lines]) else: lines.extend([" No past trades."]) self.app.log("\n".join(lines)) else: self.help("list")