Skip to content

Commit

Permalink
Add sign_transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
moisses89 committed Oct 20, 2023
1 parent 689a69f commit 869b410
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 25 deletions.
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
colorama==0.4.6
ledgereth==0.9.0
packaging>=23.1
prompt_toolkit==3.0.39
pyfiglet==1.0.0
pygments==2.16.1
requests==2.31.0
safe-eth-py==6.0.0b2
ledgereth==0.7.3
safe-eth-py==6.0.0b3
tabulate==0.9.0
web3==6.10.0
14 changes: 12 additions & 2 deletions safe_cli/operators/hw_accounts/ledger_account.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import warnings

from eth_account.datastructures import SignedTransaction
from eth_account.signers.base import BaseAccount
from hexbytes import HexBytes
from ledgerblue import Dongle
from ledgereth import create_transaction, sign_typed_data_draft
from web3 import Web3
from web3.types import TxParams


Expand Down Expand Up @@ -73,7 +76,7 @@ def signTransaction(self, transaction_dict):
)
pass

def sign_transaction(self, tx: TxParams):
def sign_transaction(self, tx: TxParams) -> SignedTransaction:
signed = create_transaction(
destination=tx["to"],
amount=tx["value"],
Expand All @@ -86,7 +89,14 @@ def sign_transaction(self, tx: TxParams):
sender_path=self.path,
dongle=self.dongle,
)
return signed
raw_transaction = signed.raw_transaction()
return SignedTransaction(
HexBytes(raw_transaction),
Web3.keccak(HexBytes(raw_transaction)),
signed.sender_r,
signed.sender_s,
signed.y_parity,
)

def __bytes__(self):
return self.key
48 changes: 29 additions & 19 deletions safe_cli/operators/safe_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from hexbytes import HexBytes
from ledgereth import get_account_by_path
from ledgereth.comms import init_dongle
from ledgereth.exceptions import LedgerNotFound
from ledgereth.exceptions import LedgerAppNotOpened, LedgerLocked, LedgerNotFound
from packaging import version as semantic_version
from prompt_toolkit import HTML, print_formatted_text
from web3 import Web3
Expand All @@ -33,12 +33,12 @@

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 (
get_default_fallback_handler_address,
get_safe_contract_address,
get_safe_l2_contract_address,
)
from safe_cli.operators.hw_accounts.ledger_account import LedgerAccount
from safe_cli.utils import get_erc_20_list, yes_or_no_question


Expand Down Expand Up @@ -307,28 +307,38 @@ def load_cli_owners(self, keys: List[str]):
def load_ledger_cli_owners(self):
try:
dongle = init_dongle()
# 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.from_wei(balance, "ether")} ether'
f"Ledger account cannot be defined as sender"
)
)
# TODO add ledger as sender
break
except LedgerNotFound:
print_formatted_text(
HTML("<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'
f"Ledger account cannot be defined as sender"
)
)
# TODO add ledger as sender
break
except LedgerAppNotOpened:
print_formatted_text(
HTML("<ansired>Ensure open ethereum app on your ledger</ansired>")
)
return
except LedgerLocked:
print_formatted_text(
HTML("<ansired>Ensure open ethereum app on your ledger</ansired>")
)
return

def unload_cli_owners(self, owners: List[str]):
accounts_to_remove: Set[Account] = set()
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"pyfiglet>=0.8",
"pygments>=2",
"requests>=2",
"safe-eth-py>=6",
"safe-eth-py==6.0.0b3",
"tabulate>=0.8",
],
packages=setuptools.find_packages(),
Expand Down
2 changes: 1 addition & 1 deletion tests/test_safe_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def test_load_cli_owner(self, get_contract_mock: MagicMock):
@mock.patch("safe_cli.operators.safe_operator.get_account_by_path")
def test_load_ledger_cli_owner(self, mock_get_account_by_path: MagicMock):
owner_address = Account.create().address
safe_address = self.deploy_test_safe(owners=[owner_address]).safe_address
safe_address = self.deploy_test_safe(owners=[owner_address]).address
safe_operator = SafeOperator(safe_address, self.ethereum_node_url)
safe_operator.load_ledger_cli_owners()
self.assertEqual(len(safe_operator.accounts), 0)
Expand Down

0 comments on commit 869b410

Please sign in to comment.