1
0

support for payment requests in the gui

This commit is contained in:
ThomasV
2014-05-07 15:26:38 +02:00
parent 2642b7e126
commit 87fa402c34
4 changed files with 139 additions and 98 deletions

View File

@@ -150,21 +150,38 @@ class ElectrumGui:
def set_url(self, url):
from electrum import util
from decimal import Decimal
try:
address, amount, label, message, url = util.parse_url(url)
address, amount, label, message, request_url, url = util.parse_url(url)
except Exception:
QMessageBox.warning(self.main_window, _('Error'), _('Invalid bitcoin URL'), _('OK'))
return
try:
if amount and self.main_window.base_unit() == 'mBTC':
amount = str( 1000* Decimal(amount))
elif amount:
amount = str(Decimal(amount))
except Exception:
amount = "0.0"
QMessageBox.warning(self.main_window, _('Error'), _('Invalid Amount'), _('OK'))
if amount:
try:
if self.main_window.base_unit() == 'mBTC':
amount = str( 1000* Decimal(amount))
else:
amount = str(Decimal(amount))
except Exception:
amount = "0.0"
QMessageBox.warning(self.main_window, _('Error'), _('Invalid Amount'), _('OK'))
if request_url:
try:
from electrum import paymentrequest
except:
print "cannot import paymentrequest"
return
def payment_request():
pr = paymentrequest.PaymentRequest(request_url)
if pr.verify() or 1:
self.main_window.payment_request = pr
self.main_window.emit(SIGNAL('payment_request_ok'))
else:
self.main_window.emit(SIGNAL('payment_request_failed'))
threading.Thread(target=payment_request).start()
self.main_window.set_send(address, amount, label, message)
if self.lite_window:

View File

@@ -120,6 +120,7 @@ class ElectrumWindow(QMainWindow):
set_language(config.get('language'))
self.funds_error = False
self.payment_request = None
self.completions = QStringListModel()
self.tabs = tabs = QTabWidget(self)
@@ -155,6 +156,7 @@ class ElectrumWindow(QMainWindow):
self.connect(self, QtCore.SIGNAL('transaction_signal'), lambda: self.notify_transactions() )
self.connect(self, QtCore.SIGNAL('send_tx2'), self.send_tx2)
self.connect(self, QtCore.SIGNAL('send_tx3'), self.send_tx3)
self.connect(self, QtCore.SIGNAL('payment_request_ok'), self.payment_request_ok)
self.history_list.setFocus(True)
@@ -203,7 +205,7 @@ class ElectrumWindow(QMainWindow):
self.password_menu.setEnabled(not self.wallet.is_watching_only())
self.seed_menu.setEnabled(self.wallet.has_seed())
self.mpk_menu.setEnabled(self.wallet.is_deterministic())
self.import_menu.setEnabled(self.wallet.can_create_accounts() or not self.wallet.is_deterministic())
self.import_menu.setEnabled(self.wallet.can_import())
self.update_lock_icon()
self.update_buttons_on_seed()
@@ -767,24 +769,31 @@ class ElectrumWindow(QMainWindow):
def do_send(self):
label = unicode( self.message_e.text() )
r = unicode( self.payto_e.text() )
r = r.strip()
# label or alias, with address in brackets
m = re.match('(.*?)\s*\<([1-9A-HJ-NP-Za-km-z]{26,})\>', r)
to_address = m.group(2) if m else r
if self.payment_request:
outputs = self.payment_request.outputs
amount = self.payment_request.get_amount()
if not is_valid(to_address):
QMessageBox.warning(self, _('Error'), _('Invalid Bitcoin Address') + ':\n' + to_address, _('OK'))
return
else:
r = unicode( self.payto_e.text() )
r = r.strip()
# label or alias, with address in brackets
m = re.match('(.*?)\s*\<([1-9A-HJ-NP-Za-km-z]{26,})\>', r)
to_address = m.group(2) if m else r
if not is_valid(to_address):
QMessageBox.warning(self, _('Error'), _('Invalid Bitcoin Address') + ':\n' + to_address, _('OK'))
return
try:
amount = self.read_amount(unicode( self.amount_e.text()))
except Exception:
QMessageBox.warning(self, _('Error'), _('Invalid Amount'), _('OK'))
return
outputs = [(to_address, amount)]
try:
amount = self.read_amount(unicode( self.amount_e.text()))
except Exception:
QMessageBox.warning(self, _('Error'), _('Invalid Amount'), _('OK'))
return
try:
fee = self.read_amount(unicode( self.fee_e.text()))
except Exception:
@@ -801,7 +810,7 @@ class ElectrumWindow(QMainWindow):
if not self.question(_("The fee for this transaction seems unusually high.\nAre you really sure you want to pay %(fee)s in fees?")%{ 'fee' : self.format_amount(fee) + ' '+ self.base_unit()}):
return
self.send_tx(to_address, amount, fee, label)
self.send_tx(outputs, fee, label)
def waiting_dialog(self, message):
@@ -815,11 +824,10 @@ class ElectrumWindow(QMainWindow):
@protected
def send_tx(self, to_address, amount, fee, label, password):
def send_tx(self, outputs, fee, label, password):
# first, create an unsigned tx
domain = self.get_payment_sources()
outputs = [(to_address, amount)]
try:
tx = self.wallet.make_unsigned_transaction(outputs, fee, None, domain)
tx.error = None
@@ -842,9 +850,6 @@ class ElectrumWindow(QMainWindow):
self.tx_wait_dialog = self.waiting_dialog('Signing..')
threading.Thread(target=sign_thread).start()
# add recipient to addressbook
if to_address not in self.wallet.addressbook and not self.wallet.is_mine(to_address):
self.wallet.addressbook.append(to_address)
def send_tx2(self):
@@ -866,28 +871,36 @@ class ElectrumWindow(QMainWindow):
self.show_transaction(tx)
return
# broadcast the tx
def broadcast_thread():
if self.payment_request:
refund_address = self.wallet.addresses()[0]
self.payment_request.send_ack(str(tx), refund_address)
self.payment_request = None
# note: BIP 70 recommends not broadcasting the tx to the network and letting the merchant do that
self.tx_broadcast_result = self.wallet.sendtx(tx)
self.emit(SIGNAL('send_tx3'))
self.tx_broadcast_dialog = self.waiting_dialog('Broadcasting..')
threading.Thread(target=broadcast_thread).start()
def send_tx3(self):
self.tx_broadcast_dialog.accept()
status, msg = self.tx_broadcast_result
if status:
QMessageBox.information(self, '', _('Payment sent.') + '\n' + msg, _('OK'))
self.do_clear()
self.update_contacts_tab()
else:
QMessageBox.warning(self, _('Error'), msg, _('OK'))
def payment_request_ok(self):
self.payto_e.setText(self.payment_request.domain)
self.payto_e.setReadOnly(True)
self.amount_e.setText(self.format_amount(self.payment_request.get_amount()))
self.amount_e.setReadOnly(True)
def set_send(self, address, amount, label, message):