def test_account_selection(click_runner, mocker, mock_testerchain, mock_worklock_agent, test_registry_source_manager): accounts = list(mock_testerchain.client.accounts) index = random.choice(range(len(accounts))) the_chosen_one = accounts[index] # I spy mock_select = mocker.spy(worklock_command, 'select_client_account') command = ('cancel-bid', '--provider', MOCK_PROVIDER_URI, '--network', TEMPORARY_DOMAIN) user_input = '\n'.join((str(index), INSECURE_DEVELOPMENT_PASSWORD, YES)) result = click_runner.invoke(worklock, command, input=user_input, catch_exceptions=False) assert result.exit_code == 0 # Check call mock_select.assert_called_once() # Check output assert GENERIC_SELECT_ACCOUNT in result.output assert SELECTED_ACCOUNT.format( choice=index, chosen_account=the_chosen_one) in result.output assert COLLECT_ETH_PASSWORD.format( checksum_address=the_chosen_one) in result.output
def select_client_account(emitter, provider_uri: str = None, signer: Signer = None, signer_uri: str = None, wallet: Wallet = None, prompt: str = None, default: int = 0, registry=None, show_eth_balance: bool = False, show_nu_balance: bool = False, show_staking: bool = False, network: str = None, poa: bool = None) -> str: """ Interactively select an ethereum wallet account from a table of nucypher account metadata. Note: Showing ETH and/or NU balances, causes an eager blockchain connection. """ if wallet and (provider_uri or signer_uri or signer): raise ValueError( "If a wallet is provided, don't provide a signer, provider URI, or signer URI." ) # We use Wallet internally as an account management abstraction if not wallet: if signer and signer_uri: raise ValueError('Pass either signer or signer_uri but not both.') if not provider_uri and not signer_uri: raise ValueError( "At least a provider URI or signer URI is necessary to select an account" ) if provider_uri: # Lazy connect the blockchain interface if not BlockchainInterfaceFactory.is_interface_initialized( provider_uri=provider_uri): BlockchainInterfaceFactory.initialize_interface( provider_uri=provider_uri, poa=poa, emitter=emitter) if signer_uri: testnet = network != NetworksInventory.MAINNET signer = Signer.from_signer_uri(signer_uri, testnet=testnet) wallet = Wallet(provider_uri=provider_uri, signer=signer) # Display accounts info if show_nu_balance or show_staking: # Lazy registry fetching if not registry: if not network: raise ValueError("Pass network name or registry; Got neither.") registry = InMemoryContractRegistry.from_latest_publication( network=network) wallet_accounts = wallet.accounts enumerated_accounts = dict(enumerate(wallet_accounts)) if len(enumerated_accounts) < 1: emitter.echo(NO_ETH_ACCOUNTS, color='red', bold=True) raise click.Abort() # Display account info headers = ['Account'] if show_staking: headers.append('Staking') if show_eth_balance: headers.append('ETH') if show_nu_balance: headers.append('NU') rows = list() for index, account in enumerated_accounts.items(): row = [account] if show_staking: staker = Staker(is_me=True, checksum_address=account, registry=registry) staker.refresh_stakes() is_staking = 'Yes' if bool(staker.stakes) else 'No' row.append(is_staking) if show_eth_balance: ether_balance = Web3.fromWei(wallet.eth_balance(account), 'ether') row.append(f'{ether_balance} ETH') if show_nu_balance: token_balance = NU.from_nunits( wallet.token_balance(account, registry)) row.append(token_balance) rows.append(row) emitter.echo(tabulate(rows, headers=headers, showindex='always')) # Prompt the user for selection, and return prompt = prompt or GENERIC_SELECT_ACCOUNT account_range = click.IntRange(min=0, max=len(enumerated_accounts) - 1) choice = click.prompt(prompt, type=account_range, default=default) chosen_account = enumerated_accounts[choice] emitter.echo(SELECTED_ACCOUNT.format(choice=choice, chosen_account=chosen_account), color='blue') return chosen_account
def select_client_account(emitter, eth_provider_uri: str = None, signer: Signer = None, signer_uri: str = None, prompt: str = None, default: int = 0, registry: BaseContractRegistry = None, show_eth_balance: bool = False, show_nu_balance: bool = False, show_staking: bool = False, network: str = None, poa: bool = None) -> str: """ Interactively select an ethereum wallet account from a table of nucypher account metadata. Note: Showing ETH and/or NU balances, causes an eager blockchain connection. """ if signer and signer_uri: raise ValueError('Pass either signer or signer_uri but not both.') if not any((eth_provider_uri, signer_uri, signer)): raise ValueError( "At least a provider URI, signer URI or signer must be provided to select an account" ) if eth_provider_uri: # Connect to the blockchain in order to select an account if not BlockchainInterfaceFactory.is_interface_initialized( eth_provider_uri=eth_provider_uri): BlockchainInterfaceFactory.initialize_interface( eth_provider_uri=eth_provider_uri, poa=poa, emitter=emitter) if not signer_uri: signer_uri = eth_provider_uri blockchain = BlockchainInterfaceFactory.get_interface( eth_provider_uri=eth_provider_uri) if signer_uri and not signer: testnet = network != NetworksInventory.MAINNET signer = Signer.from_signer_uri(signer_uri, testnet=testnet) # Display accounts info if show_nu_balance or show_staking: # Lazy registry fetching if not registry: if not network: raise ValueError("Pass network name or registry; Got neither.") registry = InMemoryContractRegistry.from_latest_publication( network=network) enumerated_accounts = dict(enumerate(signer.accounts)) if len(enumerated_accounts) < 1: emitter.echo(NO_ETH_ACCOUNTS, color='red', bold=True) raise click.Abort() elif len(enumerated_accounts) == 1: # There are no choices if there is only one available address. return enumerated_accounts[0] # Display account info headers = ['Account'] if show_staking: headers.append('Staking') if show_eth_balance: headers.append('ETH') if show_nu_balance: headers.append('NU') rows = list() for index, account in enumerated_accounts.items(): row = [account] if show_staking: staker = Staker(domain=network, checksum_address=account, registry=registry) staker.refresh_stakes() is_staking = 'Yes' if bool(staker.stakes) else 'No' row.append(is_staking) if show_eth_balance: ether_balance = Web3.fromWei( blockchain.client.get_balance(account), 'ether') row.append(f'{ether_balance} ETH') if show_nu_balance: token_agent = ContractAgency.get_agent(NucypherTokenAgent, registry=registry) token_balance = NU.from_units( token_agent.get_balance(account, registry)) row.append(token_balance) rows.append(row) emitter.echo(tabulate(rows, headers=headers, showindex='always')) # Prompt the user for selection, and return prompt = prompt or GENERIC_SELECT_ACCOUNT account_range = click.IntRange(min=0, max=len(enumerated_accounts) - 1) choice = click.prompt(prompt, type=account_range, default=default) chosen_account = enumerated_accounts[choice] emitter.echo(SELECTED_ACCOUNT.format(choice=choice, chosen_account=chosen_account), color='blue') return chosen_account