Skip to content

Commit

Permalink
Add load_ledger_cli_owners function
Browse files Browse the repository at this point in the history
  • Loading branch information
moisses89 committed Feb 11, 2023
1 parent 9806de1 commit 1cf9a8f
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 4 deletions.
Empty file.
4 changes: 2 additions & 2 deletions safe_cli/operators/hw_accounts/ledger_account.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import warnings

from eth_account.signers.base import BaseAccount
from gnosis.eth.eip712 import eip712_encode
from ledgerblue import Dongle
from ledgereth import sign_typed_data_draft, create_transaction
from web3.types import TxParams


class LedgerAccount(BaseAccount):
def __init__(self, path, address, dongle):
def __init__(self, path, address, dongle: Dongle):
"""
Initialize a new ledger account (no private key)
Expand Down
35 changes: 33 additions & 2 deletions safe_cli/operators/safe_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
from eth_account.signers.local import LocalAccount
from eth_utils import ValidationError
from hexbytes import HexBytes
from ledgereth import get_account_by_path
from ledgereth.comms import init_dongle
from ledgereth.exceptions import LedgerNotFound
from packaging import version as semantic_version
from prompt_toolkit import HTML, print_formatted_text
from web3 import Web3
Expand All @@ -28,6 +31,7 @@
from safe_cli.api.relay_service_api import RelayServiceApi
from safe_cli.api.transaction_service_api import TransactionServiceApi
from safe_cli.ethereum_hd_wallet import get_account_from_words
from safe_cli.operators.hw_accounts.ledger_account import LedgerAccount
from safe_cli.safe_addresses import LAST_DEFAULT_CALLBACK_HANDLER, LAST_SAFE_CONTRACT
from safe_cli.utils import get_erc_20_list, yes_or_no_question

Expand Down Expand Up @@ -190,8 +194,8 @@ def __init__(self, address: str, node_url: str):
self.safe_contract_1_1_0 = get_safe_V1_1_1_contract(
self.ethereum_client.w3, address=self.address
)
self.accounts: Set[LocalAccount] = set()
self.default_sender: Optional[LocalAccount] = None
self.accounts: Set[LocalAccount | LedgerAccount] = set()
self.default_sender: Optional[LocalAccount] | LedgerAccount = None
self.executed_transactions: List[str] = []
self._safe_cli_info: Optional[SafeCliInfo] = None # Cache for SafeCliInfo
self.require_all_signatures = (
Expand Down Expand Up @@ -277,6 +281,33 @@ def load_cli_owners(self, keys: List[str]):
except ValueError:
print_formatted_text(HTML(f"<ansired>Cannot load key={key}</ansired>"))

def load_ledger_cli_owners(self):
try:
dongle = init_dongle()
except LedgerNotFound:
print_formatted_text(HTML(f"<ansired>Unable to find Ledger device</ansired>"))
return
# Search between 10 first accounts
for index in range(10):
path = f"44'/60'/{index}'/0/0"
account = get_account_by_path(path, dongle=dongle)
if account.address in self.safe_cli_info.owners:
sender = LedgerAccount(account.path, account.address, dongle)
self.accounts.add(sender)
balance = self.ethereum_client.get_balance(account.address)
print_formatted_text(
HTML(
f"Loaded account <b>{account.address}</b> "
f'with balance={Web3.fromWei(balance, "ether")} ether'
)
)
if not self.default_sender and balance > 0:
print_formatted_text(
HTML(f"Set account <b>{account.address}</b> as default sender of txs")
)
self.default_sender = sender
break

def unload_cli_owners(self, owners: List[str]):
accounts_to_remove: Set[Account] = set()
for owner in owners:
Expand Down
7 changes: 7 additions & 0 deletions safe_cli/prompt_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@ def load_cli_owners_from_words(args):
def load_cli_owners(args):
safe_operator.load_cli_owners(args.keys)

@safe_exception
def load_ledger_cli_owners(args):
safe_operator.load_ledger_cli_owners()

@safe_exception
def unload_cli_owners(args):
safe_operator.unload_cli_owners(args.addresses)
Expand Down Expand Up @@ -334,6 +338,9 @@ def remove_delegate(args):
parser_load_cli_owners.add_argument("keys", type=str, nargs="+")
parser_load_cli_owners.set_defaults(func=load_cli_owners)

parser_load_ledger_cli_owners = subparsers.add_parser("load_ledger_cli_owners")
parser_load_ledger_cli_owners.set_defaults(func=load_ledger_cli_owners)

parser_unload_cli_owners = subparsers.add_parser("unload_cli_owners")
parser_unload_cli_owners.add_argument(
"addresses", type=check_ethereum_address, nargs="+"
Expand Down
5 changes: 5 additions & 0 deletions safe_cli/safe_completer_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"history": "(read-only)",
"info": "(read-only)",
"load_cli_owners": "<account-private-key> [<account-private-key>...]",
"load_ledger_cli_owners": "",
"load_cli_owners_from_words": "<word_1> <word_2> ... <word_12>",
"refresh": "",
"remove_delegate": "<address> <signer-address>",
Expand Down Expand Up @@ -156,6 +157,10 @@
"Command <b>load_cli_owners</b> will try to load a new owner via "
"<u>&lt;account-private-key&gt;</u>."
),
"load_ledger_cli_owners": HTML(
"Command <b>load_cli_owners</b> will try to load a new owner via "
"<u>&lt;account-private-key&gt;</u>."
),
"load_cli_owners_from_words": HTML(
"Command <b>load_cli_owners_from_words</b> will try to load owners via"
"<u>seed_words</u>. Only relevant accounts(owners) will be loaded"
Expand Down

0 comments on commit 1cf9a8f

Please sign in to comment.