Skip to content

Commit

Permalink
chore: upgrade ape (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey authored Oct 1, 2021
1 parent b1e766d commit 1d7694e
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 90 deletions.
75 changes: 26 additions & 49 deletions ape_ledger/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@

import click
from ape import accounts
from ape.exceptions import AliasAlreadyInUseError
from ape.utils import Abort, notify
from ape.cli import (
ape_cli_context,
existing_alias_argument,
non_existing_alias_argument,
skip_confirmation_option,
)
from eth_account import Account
from eth_account.messages import encode_defunct

from ape_ledger.accounts import LedgerAccount
from ape_ledger.choices import AddressPromptChoice
from ape_ledger.client import connect_to_ethereum_app
from ape_ledger.exceptions import AliasNotExistsError
from ape_ledger.hdpath import HDBasePath


Expand All @@ -22,44 +25,15 @@ def cli():
"""


skip_confirmation_option = click.option(
"-y",
"--yes",
"skip_confirmation",
default=False,
is_flag=True,
help="Don't ask for confirmation when removing the account",
)


def _require_non_existing_alias(arg):
if arg in accounts.aliases:
raise AliasAlreadyInUseError(arg)
return arg


def _require_existing_alias(arg):
if arg not in accounts.aliases:
raise AliasNotExistsError(arg)
return arg


existing_alias_argument = click.argument(
"alias", callback=lambda ctx, param, arg: _require_existing_alias(arg)
)
non_existing_alias_argument = click.argument(
"alias", callback=lambda ctx, param, arg: _require_non_existing_alias(arg)
)


@cli.command("list")
def _list():
@ape_cli_context()
def _list(cli_ctx):
"""List the Ledger accounts in your ape configuration"""

ledger_accounts = _get_ledger_accounts()

if len(ledger_accounts) == 0:
notify("WARNING", "No accounts found.")
cli_ctx.logger.warning("No accounts found.")
return

num_accounts = len(accounts)
Expand All @@ -78,6 +52,7 @@ def _get_ledger_accounts() -> List[LedgerAccount]:


@cli.command()
@ape_cli_context()
@non_existing_alias_argument
@click.option(
"--hd-path",
Expand All @@ -88,55 +63,57 @@ def _get_ledger_accounts() -> List[LedgerAccount]:
),
callback=lambda ctx, param, arg: HDBasePath(arg),
)
def add(alias, hd_path):
def add(cli_ctx, alias, hd_path):
"""Add a account from your Ledger hardware wallet"""

app = connect_to_ethereum_app(hd_path)
choices = AddressPromptChoice(app)
address, account_hd_path = choices.get_user_selected_account()
container = accounts.containers.get("ledger")
container.save_account(alias, address, str(account_hd_path))
notify("SUCCESS", f"Account '{address}' successfully added with alias '{alias}'.")
cli_ctx.logger.success(f"Account '{address}' successfully added with alias '{alias}'.")


@cli.command()
@existing_alias_argument
def delete(alias):
@ape_cli_context()
@existing_alias_argument(account_type=LedgerAccount)
def delete(cli_ctx, alias):
"""Remove a Ledger account from your ape configuration"""

container = accounts.containers.get("ledger")
container.delete_account(alias)
notify("SUCCESS", f"Account '{alias}' has been removed")
cli_ctx.logger.success(f"Account '{alias}' has been removed")


@cli.command()
@skip_confirmation_option
def delete_all(skip_confirmation):
@ape_cli_context()
@skip_confirmation_option("Don't ask for confirmation when removing all accounts")
def delete_all(cli_ctx, skip_confirmation):
"""Remove all Ledger accounts from your ape configuration"""

container = accounts.containers.get("ledger")
ledger_accounts = _get_ledger_accounts()
if len(ledger_accounts) == 0:
notify("WARNING", "No accounts found.")
cli_ctx.logger.warning("No accounts found.")
return

user_agrees = skip_confirmation or click.confirm("Remove all Ledger accounts from ape?")
if not user_agrees:
notify("INFO", "No account were removed.")
cli_ctx.logger.info("No account were removed.")
return

for account in ledger_accounts:
container.delete_account(account.alias)
notify("SUCCESS", f"Account '{account.alias}' has been removed")
cli_ctx.logger.success(f"Account '{account.alias}' has been removed")


@cli.command(short_help="Sign a message with your Ledger device")
@ape_cli_context()
@click.argument("alias")
@click.argument("message", default="Hello World!")
def sign_message(alias, message):
def sign_message(cli_ctx, alias, message):
if alias not in accounts.aliases:
notify("ERROR", f"Account with alias '{alias}' does not exist")
return
cli_ctx.abort(f"Account with alias '{alias}' does not exist")

eip191message = encode_defunct(text=message)
account = accounts.load(alias)
Expand All @@ -146,7 +123,7 @@ def sign_message(alias, message):
# Verify signature
signer = Account.recover_message(eip191message, signature=signature_bytes)
if signer != account.address:
raise Abort(f"Signer resolves incorrectly, got {signer}, expected {account.address}.")
cli_ctx.abort(f"Signer resolves incorrectly, got {signer}, expected {account.address}.")

# Message signed successfully
output_signature = signature.encode_vrs().hex()
Expand Down
30 changes: 1 addition & 29 deletions ape_ledger/choices.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,13 @@
from typing import Any, Optional, Tuple

import click
from ape.cli import PromptChoice
from click import Context, Parameter

from ape_ledger.client import LedgerEthereumAppClient
from ape_ledger.hdpath import HDAccountPath, HDBasePath


class PromptChoice(click.ParamType):
"""
A choice option or argument from user selection.
"""

def __init__(self, choices):
self.choices = choices
self.choice_index = None

def print_choices(self):
choices = dict(enumerate(self.choices, 1))
for choice in choices:
click.echo(f"{choice}. {choices[choice]}")
click.echo()

def convert(
self, value: Any, param: Optional["Parameter"], ctx: Optional["Context"]
) -> Optional[str]:
try:
self.choice_index = int(value) - 1
if self.choice_index < 0:
self.fail("Invalid choice", param=param)

choice = self.choices[self.choice_index]
return choice
except Exception:
self.fail("Invalid choice", param=param)


class AddressPromptChoice(PromptChoice):
"""
A class for handling prompting the user for an address selection.
Expand Down
9 changes: 0 additions & 9 deletions ape_ledger/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,6 @@ class LedgerSigningError(LedgerAccountException):
"""


class AliasNotExistsError(LedgerAccountException):
"""
An error raised when an account with the given alias does not exist.
"""

def __init__(self, alias):
super().__init__(f"The account with alias '{alias}' does not exist")


class LedgerUsbError(LedgerAccountException):
def __init__(self, message, status=0):
self.status = status
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
install_requires=[
"click>=8.0.0",
"hidapi==0.10.1",
"eth-ape==0.1.0a23",
"eth-ape>=0.1.0a24",
"eth-account==0.5.5",
"eth-typing>=2.2.2",
"eth-utils>=1.10.0",
Expand Down
4 changes: 2 additions & 2 deletions tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,5 +121,5 @@ def test_delete(runner, existing_account):

def test_delete_account_not_exists(runner):
result = runner.invoke(cli, ["ledger", "delete", TEST_ALIAS])
assert result.exit_code == 1
assert f"ERROR: The account with alias '{TEST_ALIAS}' does not exist" in result.output
assert result.exit_code == 2
assert f"'{TEST_ALIAS}' is not one of" in result.output

0 comments on commit 1d7694e

Please sign in to comment.