Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: align ledger and trezor repos from pr feedback #14

Merged
merged 4 commits into from
Jan 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 26 additions & 9 deletions ape_ledger/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
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 LedgerSigningError
from ape_ledger.hdpath import HDBasePath


@click.group(short_help="Manage Ledger accounts")
def cli():
"""
Command-line helper for managing Ledger hardware device accounts.
You can add accounts using the `add` command.
"""


Expand Down Expand Up @@ -57,8 +57,8 @@ def _get_ledger_accounts() -> List[LedgerAccount]:
@click.option(
"--hd-path",
help=(
f"The Ethereum account derivation path prefix. "
f"Defaults to {HDBasePath.DEFAULT} where {{x}} is the account ID. "
"The Ethereum account derivation path prefix. "
"Defaults to m/44'/60'/{x}'/0/0 where {{x}} is the account ID. "
"Exclude {x} to append the account ID to the end of the base path."
),
callback=lambda ctx, param, arg: HDBasePath(arg),
Expand All @@ -82,7 +82,7 @@ def delete(cli_ctx, alias):

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


@cli.command()
Expand All @@ -104,16 +104,17 @@ def delete_all(cli_ctx, skip_confirmation):

for account in ledger_accounts:
container.delete_account(account.alias)
cli_ctx.logger.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(cli_ctx, alias, message):

if alias not in accounts.aliases:
cli_ctx.abort(f"Account with alias '{alias}' does not exist")
cli_ctx.abort(f"Account with alias '{alias}' does not exist.")

eip191message = encode_defunct(text=message)
account = accounts.load(alias)
Expand All @@ -125,6 +126,22 @@ def sign_message(cli_ctx, alias, message):
if signer != account.address:
cli_ctx.abort(f"Signer resolves incorrectly, got {signer}, expected {account.address}.")

# Message signed successfully
output_signature = signature.encode_vrs().hex()
click.echo(output_signature)
# Message signed successfully, return signature
click.echo(signature.encode_vrs().hex())


@cli.command(short_help="Verify a message with your Trezor device")
@click.argument("message")
def verify_message(message, signature):

eip191message = encode_defunct(text=message)

try:
signer_address = Account.recover_message(eip191message, signature=signature)
except ValueError as exc:
message = "Message cannot be verified. Check the signature and try again."
raise LedgerSigningError(message) from exc

alias = accounts[signer_address].alias if signer_address in accounts else ""

click.echo(f"Signer: {signer_address} {alias}")
7 changes: 1 addition & 6 deletions ape_ledger/accounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,8 @@ def save_account(self, alias: str, address: str, hd_path: str):
def delete_account(self, alias: str):
path = self.data_folder.joinpath(f"{alias}.json")

try:
if path.exists():
path.unlink()
except FileNotFoundError:
# It is ok file is missing.
# NOTE: we are unable to use ``missing_ok`` parameter in `unlink()`
# because of python 3.7 compatibility
return


class LedgerAccount(AccountAPI):
Expand Down
4 changes: 2 additions & 2 deletions ape_ledger/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ def _to_vrs(reply: bytes) -> Tuple[int, bytes, bytes]:
where `v` is 1 byte, `r` is 32 bytes, and `s` is 32 bytes.
"""
if not reply:
raise LedgerUsbError("No data in reply")
raise LedgerUsbError("No data in reply.")

v = reply[0] # 1 byte
r = reply[1:33] # 32 bytes
Expand Down Expand Up @@ -429,7 +429,7 @@ def connect_to_device() -> LedgerUsbDeviceClient:

hid_path = _get_hid_device_path()
if hid_path is None:
raise LedgerUsbError("No Ledger USB device found")
raise LedgerUsbError("No Ledger USB device found.")

device = _get_device(hid_path)
return LedgerUsbDeviceClient(device)
Expand Down
6 changes: 3 additions & 3 deletions ape_ledger/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class LedgerSigningError(LedgerAccountException):


class LedgerUsbError(LedgerAccountException):
def __init__(self, message, status=0):
def __init__(self, message: str, status: int = 0):
self.status = status
super().__init__(message)

Expand All @@ -25,9 +25,9 @@ class LedgerTimeoutError(LedgerUsbError):
Raised when the Ledger client times-out waiting for a response from the device.
"""

def __init__(self, timeout):
def __init__(self, timeout: int):
message = (
f"Timeout waiting device response (timeout={timeout}).\n"
f"Make sure the Ledger device is not busy with another task."
"Make sure the Ledger device is not busy with another task."
)
super().__init__(message)
6 changes: 2 additions & 4 deletions ape_ledger/hdpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,8 @@ class HDBasePath(HDPath):
:class:`~ape_ledger.hdpath.HDAccountPath`.
"""

DEFAULT = "m/44'/60'/{x}'/0/0"

def __init__(self, base_path=DEFAULT):
base_path = base_path or self.DEFAULT
def __init__(self, base_path=None):
base_path = base_path or "m/44'/60'/{x}'/0/0"
base_path = base_path.rstrip("/")
base_path = base_path if "{x}" in base_path else f"{base_path}/{{x}}"
super().__init__(base_path)
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ markers = "fuzzing: Run Hypothesis fuzz test suite"
line_length = 100
force_grid_wrap = 0
include_trailing_comma = true
known_third_party = ["hypothesis"]
known_first_party = ["ape_ledger"]
known_third_party = ["ape", "click", "eip712", "eth_account", "eth_typing", "eth_utils", "hexbytes", "hid", "pytest", "rlp", "setuptools"]
known_first_party = ["ape_ledger", "conftest"]
multi_line_output = 3
use_parentheses = true
2 changes: 1 addition & 1 deletion tests/test_accounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
from pathlib import Path

import pytest
from conftest import TEST_ADDRESS, TEST_ALIAS, TEST_HD_PATH, assert_account
from eip712.messages import EIP712Message, EIP712Type
from eth_account.messages import SignableMessage

from ape_ledger.accounts import AccountContainer, LedgerAccount
from ape_ledger.exceptions import LedgerSigningError
from conftest import TEST_ADDRESS, TEST_ALIAS, TEST_HD_PATH, assert_account


class Person(EIP712Type):
Expand Down
3 changes: 1 addition & 2 deletions tests/test_choices.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from conftest import TEST_ADDRESS

from ape_ledger.choices import AddressPromptChoice
from conftest import TEST_ADDRESS


class TestAddressPromptChoice:
Expand Down
2 changes: 1 addition & 1 deletion tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
from ape import accounts
from ape._cli import cli
from ape.managers.accounts import AccountManager
from conftest import TEST_ADDRESS, TEST_HD_PATH, assert_account

from ape_ledger import LedgerAccount
from ape_ledger.hdpath import HDBasePath
from conftest import TEST_ADDRESS, TEST_HD_PATH, assert_account


def _get_container():
Expand Down