|
|
@ -7,7 +7,7 @@ import electrum |
|
|
|
from electrum.bitcoin import EncodeBase58Check, DecodeBase58Check, TYPE_ADDRESS |
|
|
|
from electrum.i18n import _ |
|
|
|
from electrum.plugins import BasePlugin, hook |
|
|
|
from ..hw_wallet import BIP32_HW_Wallet |
|
|
|
from electrum.keystore import Hardware_KeyStore |
|
|
|
from ..hw_wallet import HW_PluginBase |
|
|
|
from electrum.util import format_satoshis_plain, print_error |
|
|
|
|
|
|
@ -26,12 +26,12 @@ except ImportError: |
|
|
|
BTCHIP = False |
|
|
|
|
|
|
|
|
|
|
|
class BTChipWallet(BIP32_HW_Wallet): |
|
|
|
class Ledger_KeyStore(Hardware_KeyStore): |
|
|
|
wallet_type = 'btchip' |
|
|
|
device = 'Ledger' |
|
|
|
|
|
|
|
def __init__(self, storage): |
|
|
|
BIP32_HW_Wallet.__init__(self, storage) |
|
|
|
def __init__(self): |
|
|
|
Hardware_KeyStore.__init__(self) |
|
|
|
# Errors and other user interaction is done through the wallet's |
|
|
|
# handler. The handler is per-window and preserved across |
|
|
|
# device reconnects |
|
|
@ -39,6 +39,18 @@ class BTChipWallet(BIP32_HW_Wallet): |
|
|
|
self.force_watching_only = False |
|
|
|
self.device_checked = False |
|
|
|
self.signing = False |
|
|
|
self.client = None |
|
|
|
|
|
|
|
def get_derivation(self): |
|
|
|
return "m/44'/0'/%d'"%self.account_id |
|
|
|
|
|
|
|
def load(self, storage, name): |
|
|
|
self.xpub = storage.get('master_public_keys', {}).get(name) |
|
|
|
self.account_id = int(storage.get('account_id')) |
|
|
|
|
|
|
|
def init_xpub(self): |
|
|
|
client = self.get_client() |
|
|
|
self.xpub = self.get_public_key(self.get_derivation()) |
|
|
|
|
|
|
|
def give_error(self, message, clear_client = False): |
|
|
|
print_error(message) |
|
|
@ -47,7 +59,7 @@ class BTChipWallet(BIP32_HW_Wallet): |
|
|
|
else: |
|
|
|
self.signing = False |
|
|
|
if clear_client: |
|
|
|
self.plugin.client = None |
|
|
|
self.client = None |
|
|
|
self.device_checked = False |
|
|
|
raise Exception(message) |
|
|
|
|
|
|
@ -271,7 +283,7 @@ class BTChipWallet(BIP32_HW_Wallet): |
|
|
|
self.signing = False |
|
|
|
|
|
|
|
def check_proper_device(self): |
|
|
|
pubKey = DecodeBase58Check(self.master_public_keys["x/0'"])[45:] |
|
|
|
pubKey = DecodeBase58Check(self.xpub)[45:] |
|
|
|
if not self.device_checked: |
|
|
|
self.handler.show_message("Checking device") |
|
|
|
try: |
|
|
@ -306,24 +318,7 @@ class BTChipWallet(BIP32_HW_Wallet): |
|
|
|
return False, None, None |
|
|
|
return True, response, response |
|
|
|
|
|
|
|
|
|
|
|
class LedgerPlugin(HW_PluginBase): |
|
|
|
libraries_available = BTCHIP |
|
|
|
wallet_class = BTChipWallet |
|
|
|
|
|
|
|
def __init__(self, parent, config, name): |
|
|
|
HW_PluginBase.__init__(self, parent, config, name) |
|
|
|
# FIXME shouldn't be a plugin member. Then this constructor can go. |
|
|
|
self.client = None |
|
|
|
|
|
|
|
def btchip_is_connected(self, wallet): |
|
|
|
try: |
|
|
|
wallet.get_client().getFirmwareVersion() |
|
|
|
except: |
|
|
|
return False |
|
|
|
return True |
|
|
|
|
|
|
|
def get_client(self, wallet, force_pair=True, noPin=False): |
|
|
|
def get_client(self, force_pair=True, noPin=False): |
|
|
|
aborted = False |
|
|
|
client = self.client |
|
|
|
if not client or client.bad: |
|
|
@ -388,8 +383,21 @@ class LedgerPlugin(HW_PluginBase): |
|
|
|
else: |
|
|
|
raise e |
|
|
|
client.bad = False |
|
|
|
wallet.device_checked = False |
|
|
|
wallet.proper_device = False |
|
|
|
self.device_checked = False |
|
|
|
self.proper_device = False |
|
|
|
self.client = client |
|
|
|
|
|
|
|
return self.client |
|
|
|
|
|
|
|
|
|
|
|
class LedgerPlugin(HW_PluginBase): |
|
|
|
libraries_available = BTCHIP |
|
|
|
keystore_class = Ledger_KeyStore |
|
|
|
|
|
|
|
def btchip_is_connected(self, keystore): |
|
|
|
try: |
|
|
|
keystore.get_client().getFirmwareVersion() |
|
|
|
except Exception as e: |
|
|
|
self.print_error("get_client", str(e)) |
|
|
|
return False |
|
|
|
return True |
|
|
|