support for payment requests in the gui
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user