Browse Source

Rename send_tx() to sign_tx()

Because it signs, and it doesn't send.
master
Neil Booth 11 years ago
parent
commit
15632adb40
  1. 6
      gui/qt/main_window.py
  2. 2
      gui/qt/transaction_dialog.py
  3. 89
      plugins/btchipwallet.py
  4. 42
      plugins/trustedcoin.py

6
gui/qt/main_window.py

@ -1137,18 +1137,18 @@ class ElectrumWindow(QMainWindow):
self.do_clear() self.do_clear()
else: else:
self.broadcast_transaction(tx, tx_desc) self.broadcast_transaction(tx, tx_desc)
self.send_tx(tx, sign_done) self.sign_tx(tx, sign_done)
@protected @protected
def send_tx(self, tx, callback, password): def sign_tx(self, tx, callback, password):
'''Sign the transaction in a separate thread. When done, calls '''Sign the transaction in a separate thread. When done, calls
the callback with a success code of True or False. the callback with a success code of True or False.
''' '''
self.send_button.setDisabled(True) self.send_button.setDisabled(True)
# call hook to see if plugin needs gui interaction # call hook to see if plugin needs gui interaction
run_hook('send_tx', tx) run_hook('sign_tx', tx)
# sign the tx # sign the tx
success = [False] # Array to work around python scoping success = [False] # Array to work around python scoping

2
gui/qt/transaction_dialog.py

@ -145,7 +145,7 @@ class TxDialog(QWidget):
self.prompt_if_unsaved = True self.prompt_if_unsaved = True
self.saved = False self.saved = False
self.update() self.update()
self.parent.send_tx(self.tx, sign_done) self.parent.sign_tx(self.tx, sign_done)
def save(self): def save(self):
name = 'signed_%s.txn' % (self.tx.hash()[0:8]) if self.tx.is_complete() else 'unsigned.txn' name = 'signed_%s.txn' % (self.tx.hash()[0:8]) if self.tx.is_complete() else 'unsigned.txn'

89
plugins/btchipwallet.py

@ -28,7 +28,7 @@ try:
from btchip.btchipFirmwareWizard import checkFirmware, updateFirmware from btchip.btchipFirmwareWizard import checkFirmware, updateFirmware
from btchip.btchipException import BTChipException from btchip.btchipException import BTChipException
BTCHIP = True BTCHIP = True
BTCHIP_DEBUG = False BTCHIP_DEBUG = False
except ImportError: except ImportError:
BTCHIP = False BTCHIP = False
@ -45,7 +45,7 @@ class Plugin(BasePlugin):
def _init(self): def _init(self):
return BTCHIP return BTCHIP
def is_available(self): def is_available(self):
if not self._is_available: if not self._is_available:
return False return False
if not self.wallet: if not self.wallet:
@ -82,7 +82,7 @@ class Plugin(BasePlugin):
else: else:
QMessageBox.information(self.window, _('Error'), _("BTChip device not detected.\nContinuing in watching-only mode."), _('OK')) QMessageBox.information(self.window, _('Error'), _("BTChip device not detected.\nContinuing in watching-only mode."), _('OK'))
self.wallet.force_watching_only = True self.wallet.force_watching_only = True
@hook @hook
def installwizard_restore(self, wizard, storage): def installwizard_restore(self, wizard, storage):
if storage.get('wallet_type') != 'btchip': if storage.get('wallet_type') != 'btchip':
@ -96,7 +96,7 @@ class Plugin(BasePlugin):
return wallet return wallet
@hook @hook
def send_tx(self, tx): def sign_tx(self, tx):
tx.error = None tx.error = None
try: try:
self.wallet.sign_transaction(tx, None) self.wallet.sign_transaction(tx, None)
@ -124,7 +124,7 @@ class BTChipWallet(BIP32_HD_Wallet):
if clear_client and self.client is not None: if clear_client and self.client is not None:
self.client.bad = True self.client.bad = True
self.device_checked = False self.device_checked = False
raise Exception(message) raise Exception(message)
def get_action(self): def get_action(self):
if not self.accounts: if not self.accounts:
@ -155,7 +155,7 @@ class BTChipWallet(BIP32_HD_Wallet):
d.setWaitImpl(DongleWaitQT(d)) d.setWaitImpl(DongleWaitQT(d))
self.client = btchip(d) self.client = btchip(d)
firmware = self.client.getFirmwareVersion()['version'].split(".") firmware = self.client.getFirmwareVersion()['version'].split(".")
if not checkFirmware(firmware): if not checkFirmware(firmware):
d.close() d.close()
try: try:
updateFirmware() updateFirmware()
@ -164,13 +164,13 @@ class BTChipWallet(BIP32_HD_Wallet):
raise e raise e
d = getDongle(BTCHIP_DEBUG) d = getDongle(BTCHIP_DEBUG)
d.setWaitImpl(DongleWaitQT(d)) d.setWaitImpl(DongleWaitQT(d))
self.client = btchip(d) self.client = btchip(d)
try: try:
self.client.getOperationMode() self.client.getOperationMode()
except BTChipException, e: except BTChipException, e:
if (e.sw == 0x6985): if (e.sw == 0x6985):
d.close() d.close()
dialog = StartBTChipPersoDialog() dialog = StartBTChipPersoDialog()
dialog.exec_() dialog.exec_()
# Then fetch the reference again as it was invalidated # Then fetch the reference again as it was invalidated
d = getDongle(BTCHIP_DEBUG) d = getDongle(BTCHIP_DEBUG)
@ -178,18 +178,18 @@ class BTChipWallet(BIP32_HD_Wallet):
self.client = btchip(d) self.client = btchip(d)
else: else:
raise e raise e
if not noPin: if not noPin:
# Immediately prompts for the PIN # Immediately prompts for the PIN
remaining_attempts = self.client.getVerifyPinRemainingAttempts() remaining_attempts = self.client.getVerifyPinRemainingAttempts()
if remaining_attempts <> 1: if remaining_attempts <> 1:
msg = "Enter your BTChip PIN - remaining attempts : " + str(remaining_attempts) msg = "Enter your BTChip PIN - remaining attempts : " + str(remaining_attempts)
else: else:
msg = "Enter your BTChip PIN - WARNING : LAST ATTEMPT. If the PIN is not correct, the dongle will be wiped." msg = "Enter your BTChip PIN - WARNING : LAST ATTEMPT. If the PIN is not correct, the dongle will be wiped."
confirmed, p, pin = self.password_dialog(msg) confirmed, p, pin = self.password_dialog(msg)
if not confirmed: if not confirmed:
aborted = True aborted = True
raise Exception('Aborted by user - please unplug the dongle and plug it again before retrying') raise Exception('Aborted by user - please unplug the dongle and plug it again before retrying')
pin = pin.encode() pin = pin.encode()
self.client.verifyPin(pin) self.client.verifyPin(pin)
except BTChipException, e: except BTChipException, e:
@ -197,18 +197,18 @@ class BTChipWallet(BIP32_HD_Wallet):
self.client.dongle.close() self.client.dongle.close()
except: except:
pass pass
self.client = None self.client = None
if (e.sw == 0x6faa): if (e.sw == 0x6faa):
raise Exception("Dongle is temporarily locked - please unplug it and replug it again") raise Exception("Dongle is temporarily locked - please unplug it and replug it again")
if ((e.sw & 0xFFF0) == 0x63c0): if ((e.sw & 0xFFF0) == 0x63c0):
raise Exception("Invalid PIN - please unplug the dongle and plug it again before retrying") raise Exception("Invalid PIN - please unplug the dongle and plug it again before retrying")
raise e raise e
except Exception, e: except Exception, e:
try: try:
self.client.dongle.close() self.client.dongle.close()
except: except:
pass pass
self.client = None self.client = None
if not aborted: if not aborted:
raise Exception("Could not connect to your BTChip dongle. Please verify access permissions, PIN, or unplug the dongle and plug it again") raise Exception("Could not connect to your BTChip dongle. Please verify access permissions, PIN, or unplug the dongle and plug it again")
else: else:
@ -234,20 +234,20 @@ class BTChipWallet(BIP32_HD_Wallet):
return [] return []
def get_public_key(self, bip32_path): def get_public_key(self, bip32_path):
# S-L-O-W - we don't handle the fingerprint directly, so compute it manually from the previous node # S-L-O-W - we don't handle the fingerprint directly, so compute it manually from the previous node
# This only happens once so it's bearable # This only happens once so it's bearable
self.get_client() # prompt for the PIN before displaying the dialog if necessary self.get_client() # prompt for the PIN before displaying the dialog if necessary
waitDialog.start("Computing master public key") waitDialog.start("Computing master public key")
try: try:
splitPath = bip32_path.split('/') splitPath = bip32_path.split('/')
fingerprint = 0 fingerprint = 0
if len(splitPath) > 1: if len(splitPath) > 1:
prevPath = "/".join(splitPath[0:len(splitPath) - 1]) prevPath = "/".join(splitPath[0:len(splitPath) - 1])
nodeData = self.get_client().getWalletPublicKey(prevPath) nodeData = self.get_client().getWalletPublicKey(prevPath)
publicKey = compress_public_key(nodeData['publicKey']) publicKey = compress_public_key(nodeData['publicKey'])
h = hashlib.new('ripemd160') h = hashlib.new('ripemd160')
h.update(hashlib.sha256(publicKey).digest()) h.update(hashlib.sha256(publicKey).digest())
fingerprint = unpack(">I", h.digest()[0:4])[0] fingerprint = unpack(">I", h.digest()[0:4])[0]
nodeData = self.get_client().getWalletPublicKey(bip32_path) nodeData = self.get_client().getWalletPublicKey(bip32_path)
publicKey = compress_public_key(nodeData['publicKey']) publicKey = compress_public_key(nodeData['publicKey'])
depth = len(splitPath) depth = len(splitPath)
@ -255,7 +255,7 @@ class BTChipWallet(BIP32_HD_Wallet):
if len(lastChild) == 1: if len(lastChild) == 1:
childnum = int(lastChild[0]) childnum = int(lastChild[0])
else: else:
childnum = 0x80000000 | int(lastChild[0]) childnum = 0x80000000 | int(lastChild[0])
xpub = "0488B21E".decode('hex') + chr(depth) + self.i4b(fingerprint) + self.i4b(childnum) + str(nodeData['chainCode']) + str(publicKey) xpub = "0488B21E".decode('hex') + chr(depth) + self.i4b(fingerprint) + self.i4b(childnum) + str(nodeData['chainCode']) + str(publicKey)
except Exception, e: except Exception, e:
self.give_error(e, True) self.give_error(e, True)
@ -270,7 +270,7 @@ class BTChipWallet(BIP32_HD_Wallet):
self.mpk = self.get_public_key("44'/0'") self.mpk = self.get_public_key("44'/0'")
return self.mpk return self.mpk
except Exception, e: except Exception, e:
self.give_error(e, True) self.give_error(e, True)
def i4b(self, x): def i4b(self, x):
return pack('>I', x) return pack('>I', x)
@ -287,13 +287,13 @@ class BTChipWallet(BIP32_HD_Wallet):
self.signing = True self.signing = True
self.get_client() # prompt for the PIN before displaying the dialog if necessary self.get_client() # prompt for the PIN before displaying the dialog if necessary
if not self.check_proper_device(): if not self.check_proper_device():
self.give_error('Wrong device or password') self.give_error('Wrong device or password')
address_path = self.address_id(address) address_path = self.address_id(address)
waitDialog.start("Signing Message ...") waitDialog.start("Signing Message ...")
try: try:
info = self.get_client().signMessagePrepare(address_path, message) info = self.get_client().signMessagePrepare(address_path, message)
pin = "" pin = ""
if info['confirmationNeeded']: if info['confirmationNeeded']:
# TODO : handle different confirmation types. For the time being only supports keyboard 2FA # TODO : handle different confirmation types. For the time being only supports keyboard 2FA
use2FA = True use2FA = True
confirmed, p, pin = self.password_dialog() confirmed, p, pin = self.password_dialog()
@ -307,8 +307,8 @@ class BTChipWallet(BIP32_HD_Wallet):
except BTChipException, e: except BTChipException, e:
if e.sw == 0x6a80: if e.sw == 0x6a80:
self.give_error("Unfortunately, this message cannot be signed by BTChip. Only alphanumerical messages shorter than 140 characters are supported. Please remove any extra characters (tab, carriage return) and retry.") self.give_error("Unfortunately, this message cannot be signed by BTChip. Only alphanumerical messages shorter than 140 characters are supported. Please remove any extra characters (tab, carriage return) and retry.")
else: else:
self.give_error(e, True) self.give_error(e, True)
except Exception, e: except Exception, e:
self.give_error(e, True) self.give_error(e, True)
finally: finally:
@ -332,22 +332,22 @@ class BTChipWallet(BIP32_HD_Wallet):
# And convert it # And convert it
return b64encode(chr(27 + 4 + (signature[0] & 0x01)) + r + s) return b64encode(chr(27 + 4 + (signature[0] & 0x01)) + r + s)
def sign_transaction(self, tx, password): def sign_transaction(self, tx, password):
if tx.is_complete(): if tx.is_complete():
return return
if tx.error: if tx.error:
raise BaseException(tx.error) raise BaseException(tx.error)
self.signing = True self.signing = True
inputs = [] inputs = []
inputsPaths = [] inputsPaths = []
pubKeys = [] pubKeys = []
trustedInputs = [] trustedInputs = []
redeemScripts = [] redeemScripts = []
signatures = [] signatures = []
preparedTrustedInputs = [] preparedTrustedInputs = []
changePath = "" changePath = ""
changeAmount = None changeAmount = None
output = None output = None
outputAmount = None outputAmount = None
@ -358,8 +358,8 @@ class BTChipWallet(BIP32_HD_Wallet):
for txinput in tx.inputs: for txinput in tx.inputs:
if ('is_coinbase' in txinput and txinput['is_coinbase']): if ('is_coinbase' in txinput and txinput['is_coinbase']):
self.give_error("Coinbase not supported") # should never happen self.give_error("Coinbase not supported") # should never happen
inputs.append([ self.transactions[txinput['prevout_hash']].raw, inputs.append([ self.transactions[txinput['prevout_hash']].raw,
txinput['prevout_n'] ]) txinput['prevout_n'] ])
address = txinput['address'] address = txinput['address']
inputsPaths.append(self.address_id(address)) inputsPaths.append(self.address_id(address))
pubKeys.append(self.get_public_keys(address)) pubKeys.append(self.get_public_keys(address))
@ -367,7 +367,7 @@ class BTChipWallet(BIP32_HD_Wallet):
# Recognize outputs - only one output and one change is authorized # Recognize outputs - only one output and one change is authorized
if len(tx.outputs) > 2: # should never happen if len(tx.outputs) > 2: # should never happen
self.give_error("Transaction with more than 2 outputs not supported") self.give_error("Transaction with more than 2 outputs not supported")
for type, address, amount in tx.outputs: for type, address, amount in tx.outputs:
assert type == 'address' assert type == 'address'
if self.is_change(address): if self.is_change(address):
changePath = self.address_id(address) changePath = self.address_id(address)
@ -386,7 +386,7 @@ class BTChipWallet(BIP32_HD_Wallet):
try: try:
# Get trusted inputs from the original transactions # Get trusted inputs from the original transactions
for utxo in inputs: for utxo in inputs:
txtmp = bitcoinTransaction(bytearray(utxo[0].decode('hex'))) txtmp = bitcoinTransaction(bytearray(utxo[0].decode('hex')))
trustedInputs.append(self.get_client().getTrustedInput(txtmp, utxo[1])) trustedInputs.append(self.get_client().getTrustedInput(txtmp, utxo[1]))
# TODO : Support P2SH later # TODO : Support P2SH later
redeemScripts.append(txtmp.outputs[utxo[1]].script) redeemScripts.append(txtmp.outputs[utxo[1]].script)
@ -394,13 +394,13 @@ class BTChipWallet(BIP32_HD_Wallet):
firstTransaction = True firstTransaction = True
inputIndex = 0 inputIndex = 0
while inputIndex < len(inputs): while inputIndex < len(inputs):
self.get_client().startUntrustedTransaction(firstTransaction, inputIndex, self.get_client().startUntrustedTransaction(firstTransaction, inputIndex,
trustedInputs, redeemScripts[inputIndex]) trustedInputs, redeemScripts[inputIndex])
outputData = self.get_client().finalizeInput(output, format_satoshis_plain(outputAmount), outputData = self.get_client().finalizeInput(output, format_satoshis_plain(outputAmount),
format_satoshis_plain(self.get_tx_fee(tx)), changePath, bytearray(rawTx.decode('hex'))) format_satoshis_plain(self.get_tx_fee(tx)), changePath, bytearray(rawTx.decode('hex')))
if firstTransaction: if firstTransaction:
transactionOutput = outputData['outputData'] transactionOutput = outputData['outputData']
if outputData['confirmationNeeded']: if outputData['confirmationNeeded']:
use2FA = True use2FA = True
# TODO : handle different confirmation types. For the time being only supports keyboard 2FA # TODO : handle different confirmation types. For the time being only supports keyboard 2FA
waitDialog.emit(SIGNAL('dongle_done')) waitDialog.emit(SIGNAL('dongle_done'))
@ -410,16 +410,16 @@ class BTChipWallet(BIP32_HD_Wallet):
msg = "Do not enter your device PIN here !\r\n\r\n" + \ msg = "Do not enter your device PIN here !\r\n\r\n" + \
"Your BTChip wants to talk to you and tell you a unique second factor code.\r\n" + \ "Your BTChip wants to talk to you and tell you a unique second factor code.\r\n" + \
"For this to work, please match the character between stars of the output address using your security card\r\n\r\n" + \ "For this to work, please match the character between stars of the output address using your security card\r\n\r\n" + \
"Output address : " "Output address : "
for index in range(len(output)): for index in range(len(output)):
if index == outputData['keycardData'][keycardIndex]: if index == outputData['keycardData'][keycardIndex]:
msg = msg + "*" + output[index] + "*" msg = msg + "*" + output[index] + "*"
else: else:
msg = msg + output[index] msg = msg + output[index]
msg = msg + "\r\n" msg = msg + "\r\n"
confirmed, p, pin = self.password_dialog(msg) confirmed, p, pin = self.password_dialog(msg)
if not confirmed: if not confirmed:
raise Exception('Aborted by user') raise Exception('Aborted by user')
try: try:
pin2 = pin2 + chr(int(pin[0], 16)) pin2 = pin2 + chr(int(pin[0], 16))
except: except:
@ -428,7 +428,7 @@ class BTChipWallet(BIP32_HD_Wallet):
else: else:
confirmed, p, pin = self.password_dialog() confirmed, p, pin = self.password_dialog()
if not confirmed: if not confirmed:
raise Exception('Aborted by user') raise Exception('Aborted by user')
pin = pin.encode() pin = pin.encode()
self.client.bad = True self.client.bad = True
self.device_checked = False self.device_checked = False
@ -452,7 +452,7 @@ class BTChipWallet(BIP32_HD_Wallet):
inputIndex = 0 inputIndex = 0
while inputIndex < len(inputs): while inputIndex < len(inputs):
# TODO : Support P2SH later # TODO : Support P2SH later
inputScript = get_regular_input_script(signatures[inputIndex], pubKeys[inputIndex][0].decode('hex')) inputScript = get_regular_input_script(signatures[inputIndex], pubKeys[inputIndex][0].decode('hex'))
preparedTrustedInputs.append([ trustedInputs[inputIndex]['value'], inputScript ]) preparedTrustedInputs.append([ trustedInputs[inputIndex]['value'], inputScript ])
inputIndex = inputIndex + 1 inputIndex = inputIndex + 1
updatedTransaction = format_transaction(transactionOutput, preparedTrustedInputs) updatedTransaction = format_transaction(transactionOutput, preparedTrustedInputs)
@ -525,4 +525,3 @@ if BTCHIP:
def waitFirstResponse(self, timeout): def waitFirstResponse(self, timeout):
return self.dongle.waitFirstResponse(timeout) return self.dongle.waitFirstResponse(timeout)

42
plugins/trustedcoin.py

@ -62,7 +62,7 @@ class TrustedCoinCosignerClient(object):
self.base_url = base_url self.base_url = base_url
self.debug = debug self.debug = debug
self.user_agent = user_agent self.user_agent = user_agent
def send_request(self, method, relative_url, data=None): def send_request(self, method, relative_url, data=None):
kwargs = {'headers': {}} kwargs = {'headers': {}}
if self.user_agent: if self.user_agent:
@ -85,12 +85,12 @@ class TrustedCoinCosignerClient(object):
r = response.json() r = response.json()
if 'message' in r: if 'message' in r:
message = r['message'] message = r['message']
raise TrustedCoinException(message, response.status_code) raise TrustedCoinException(message, response.status_code)
if response.headers.get('content-type') == 'application/json': if response.headers.get('content-type') == 'application/json':
return response.json() return response.json()
else: else:
return response.text return response.text
def get_terms_of_service(self, billing_plan='electrum-per-tx-otp'): def get_terms_of_service(self, billing_plan='electrum-per-tx-otp'):
""" """
Returns the TOS for the given billing plan as a plain/text unicode string. Returns the TOS for the given billing plan as a plain/text unicode string.
@ -98,13 +98,13 @@ class TrustedCoinCosignerClient(object):
""" """
payload = {'billing_plan': billing_plan} payload = {'billing_plan': billing_plan}
return self.send_request('get', 'tos', payload) return self.send_request('get', 'tos', payload)
def create(self, xpubkey1, xpubkey2, email, billing_plan='electrum-per-tx-otp'): def create(self, xpubkey1, xpubkey2, email, billing_plan='electrum-per-tx-otp'):
""" """
Creates a new cosigner resource. Creates a new cosigner resource.
:param xpubkey1: a bip32 extended public key (customarily the hot key) :param xpubkey1: a bip32 extended public key (customarily the hot key)
:param xpubkey2: a bip32 extended public key (customarily the cold key) :param xpubkey2: a bip32 extended public key (customarily the cold key)
:param email: a contact email :param email: a contact email
:param billing_plan: the billing plan for the cosigner :param billing_plan: the billing plan for the cosigner
""" """
payload = { payload = {
@ -114,7 +114,7 @@ class TrustedCoinCosignerClient(object):
'billing_plan': billing_plan, 'billing_plan': billing_plan,
} }
return self.send_request('post', 'cosigner', payload) return self.send_request('post', 'cosigner', payload)
def auth(self, id, otp): def auth(self, id, otp):
""" """
Attempt to authenticate for a particular cosigner. Attempt to authenticate for a particular cosigner.
@ -123,7 +123,7 @@ class TrustedCoinCosignerClient(object):
""" """
payload = {'otp': otp} payload = {'otp': otp}
return self.send_request('post', 'cosigner/%s/auth' % quote(id), payload) return self.send_request('post', 'cosigner/%s/auth' % quote(id), payload)
def get(self, id): def get(self, id):
""" """
Attempt to authenticate for a particular cosigner. Attempt to authenticate for a particular cosigner.
@ -131,7 +131,7 @@ class TrustedCoinCosignerClient(object):
:param otp: the one time password :param otp: the one time password
""" """
return self.send_request('get', 'cosigner/%s' % quote(id)) return self.send_request('get', 'cosigner/%s' % quote(id))
def sign(self, id, transaction, otp): def sign(self, id, transaction, otp):
""" """
Attempt to authenticate for a particular cosigner. Attempt to authenticate for a particular cosigner.
@ -157,7 +157,7 @@ class TrustedCoinCosignerClient(object):
'otp': otp, 'otp': otp,
'recipient': recipient, 'recipient': recipient,
'timestamp': int(time.time()), 'timestamp': int(time.time()),
} }
relative_url = 'cosigner/%s/transfer' % quote(id) relative_url = 'cosigner/%s/transfer' % quote(id)
full_url = urljoin(self.base_url, relative_url) full_url = urljoin(self.base_url, relative_url)
@ -282,7 +282,7 @@ class Plugin(BasePlugin):
wallet.add_cosigner_seed(' '.join(words[0:n]), 'x1/', password) wallet.add_cosigner_seed(' '.join(words[0:n]), 'x1/', password)
wallet.add_cosigner_xpub(' '.join(words[n:]), 'x2/') wallet.add_cosigner_xpub(' '.join(words[n:]), 'x2/')
msg = [ msg = [
_('Your wallet file is:') + " %s"%os.path.abspath(wallet.storage.path), _('Your wallet file is:') + " %s"%os.path.abspath(wallet.storage.path),
_('You need to be online in order to complete the creation of your wallet.'), _('You need to be online in order to complete the creation of your wallet.'),
_('If you generated your seed on an offline computer, click on "%s" to close this window, move your wallet file to an online computer and reopen it with Electrum.') % _('Close'), _('If you generated your seed on an offline computer, click on "%s" to close this window, move your wallet file to an online computer and reopen it with Electrum.') % _('Close'),
@ -350,14 +350,14 @@ class Plugin(BasePlugin):
def get_wizard_action(self, window, wallet, action): def get_wizard_action(self, window, wallet, action):
if hasattr(self, action): if hasattr(self, action):
return getattr(self, action) return getattr(self, action)
@hook @hook
def installwizard_restore(self, window, storage): def installwizard_restore(self, window, storage):
if storage.get('wallet_type') != '2fa': if storage.get('wallet_type') != '2fa':
return return
seed = window.enter_seed_dialog("Enter your seed", None, func=self.seed_func) seed = window.enter_seed_dialog("Enter your seed", None, func=self.seed_func)
if not seed: if not seed:
return return
wallet = Wallet_2fa(storage) wallet = Wallet_2fa(storage)
self.wallet = wallet self.wallet = wallet
@ -380,7 +380,7 @@ class Plugin(BasePlugin):
self.wallet = wallet self.wallet = wallet
self.window = window self.window = window
if wallet.storage.get('wallet_type') != '2fa': if wallet.storage.get('wallet_type') != '2fa':
raise raise
return return
@ -444,8 +444,8 @@ class Plugin(BasePlugin):
return False return False
@hook @hook
def send_tx(self, tx): def sign_tx(self, tx):
self.print_error("twofactor:send_tx") self.print_error("twofactor:sign_tx")
if self.wallet.storage.get('wallet_type') != '2fa': if self.wallet.storage.get('wallet_type') != '2fa':
return return
@ -514,7 +514,7 @@ class Plugin(BasePlugin):
self.print_error( "received answer", r) self.print_error( "received answer", r)
if not r: if not r:
return return
raw_tx = r.get('transaction') raw_tx = r.get('transaction')
tx.update(raw_tx) tx.update(raw_tx)
@ -534,7 +534,7 @@ class Plugin(BasePlugin):
grid.addWidget(pw, 1, 1) grid.addWidget(pw, 1, 1)
vbox.addLayout(grid) vbox.addLayout(grid)
vbox.addLayout(Buttons(CancelButton(d), OkButton(d))) vbox.addLayout(Buttons(CancelButton(d), OkButton(d)))
if not d.exec_(): if not d.exec_():
return return
return pw.get_amount() return pw.get_amount()
@ -562,7 +562,7 @@ class Plugin(BasePlugin):
+ _("For more information, visit") + " <a href=\"https://api.trustedcoin.com/#/electrum-help\">https://api.trustedcoin.com/#/electrum-help</a>" + _("For more information, visit") + " <a href=\"https://api.trustedcoin.com/#/electrum-help\">https://api.trustedcoin.com/#/electrum-help</a>"
label = QLabel(msg) label = QLabel(msg)
label.setOpenExternalLinks(1) label.setOpenExternalLinks(1)
hbox.addStretch(10) hbox.addStretch(10)
hbox.addWidget(logo) hbox.addWidget(logo)
hbox.addStretch(10) hbox.addStretch(10)
@ -656,7 +656,7 @@ class Plugin(BasePlugin):
tos = server.get_terms_of_service() tos = server.get_terms_of_service()
self.TOS = tos self.TOS = tos
window.emit(SIGNAL('twofactor:TOS')) window.emit(SIGNAL('twofactor:TOS'))
def on_result(): def on_result():
tos_e.setText(self.TOS) tos_e.setText(self.TOS)
@ -669,7 +669,7 @@ class Plugin(BasePlugin):
email_e.textChanged.connect(lambda: accept_button.setEnabled(re.match(regexp,email_e.text()) is not None)) email_e.textChanged.connect(lambda: accept_button.setEnabled(re.match(regexp,email_e.text()) is not None))
email_e.setFocus(True) email_e.setFocus(True)
if not window.exec_(): if not window.exec_():
return return
email = str(email_e.text()) email = str(email_e.text())

Loading…
Cancel
Save