From 26b19ad6bb20419a5d5b4bad77daedfb6fcb7856 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Sun, 29 Apr 2012 18:33:01 +0200 Subject: [PATCH 01/12] version 0.44. fix jsonrpc stratum, deprecate native protocol --- client/interface.py | 124 +++++++++++--------------------------------- client/version.py | 2 +- 2 files changed, 32 insertions(+), 94 deletions(-) diff --git a/client/interface.py b/client/interface.py index bdba222d..21ea5a83 100644 --- a/client/interface.py +++ b/client/interface.py @@ -49,25 +49,41 @@ class Interface(threading.Thread): #json self.message_id = 0 self.responses = Queue.Queue() + self.methods = {} def poke(self): # push a fake response so that the getting thread exits its loop self.responses.put(None) def queue_json_response(self, c): - #print repr(c) + + #print "<--",c msg_id = c.get('id') - result = c.get('result') error = c.get('error') - params = c.get('params',[]) - method = c.get('method',None) - if not method: - return if error: - print "received error:", c, method, params + print "received error:", c + return + + if msg_id is not None: + method, params = self.methods.pop(msg_id) + result = c.get('result') else: - self.responses.put({'method':method, 'params':params, 'result':result}) + # notification + method = c.get('method') + params = c.get('params') + + if method == 'blockchain.numblocks.subscribe': + result = params[0] + params = [] + + elif method == 'blockchain.address.subscribe': + addr = params[0] + result = params[1] + params = [addr] + + self.responses.put({'method':method, 'params':params, 'result':result}) + def subscribe(self, addresses): @@ -148,71 +164,6 @@ class PollingInterface(Interface): -class NativeInterface(PollingInterface): - - def start_session(self, addresses, version): - self.send([('session.new', [ version, addresses ])] ) - self.send([('server.peers.subscribe',[])]) - - def poll(self): - self.send([('session.poll', [])]) - - def send(self, messages): - import time - cmds = {'session.new':'new_session', - 'server.peers.subscribe':'peers', - 'session.poll':'poll', - 'blockchain.transaction.broadcast':'tx', - 'blockchain.address.get_history':'h', - 'blockchain.address.subscribe':'address.subscribe' - } - - for m in messages: - method, params = m - cmd = cmds[method] - - if cmd == 'poll': - params = self.session_id - - if cmd == 'address.subscribe': - params = [ self.session_id ] + params - - if cmd in ['h', 'tx']: - str_params = params[0] - elif type(params) != type(''): - str_params = repr( params ) - else: - str_params = params - t1 = time.time() - request = repr ( (cmd, str_params) ) + "#" - s = socket.socket( socket.AF_INET, socket.SOCK_STREAM) - s.settimeout(DEFAULT_TIMEOUT) - s.connect(( self.host, self.port) ) - s.send( request ) - out = '' - while 1: - msg = s.recv(1024) - if msg: out += msg - else: break - s.close() - self.rtime = time.time() - t1 - self.is_connected = True - - if cmd == 'h': - out = old_to_new(out) - - if cmd in ['peers','h','poll']: - out = ast.literal_eval( out ) - - if out == '': - out = None - - if cmd == 'new_session': - self.session_id, msg = ast.literal_eval( out ) - self.responses.put({'method':'server.banner', 'params':[], 'result':msg}) - else: - self.responses.put({'method':method, 'params':params, 'result':out}) - @@ -235,6 +186,7 @@ class HttpStratumInterface(PollingInterface): method, params = m if type(params) != type([]): params = [params] data.append( { 'method':method, 'id':self.message_id, 'params':params } ) + self.methods[self.message_id] = method, params self.message_id += 1 if data: @@ -324,6 +276,8 @@ class TcpStratumInterface(Interface): for m in messages: method, params = m request = json.dumps( { 'id':self.message_id, 'method':method, 'params':params } ) + self.methods[self.message_id] = method, params + #print "-->",request self.message_id += 1 out += request + '\n' self.s.send( out ) @@ -357,16 +311,6 @@ class WalletSynchronizer(threading.Thread): self.wallet.banner = result self.wallet.was_updated = True - elif method == 'session.poll': - # native poll - blocks, changed_addresses = result - if blocks == -1: raise BaseException("session not found") - self.wallet.blocks = int(blocks) - if changed_addresses: - self.wallet.was_updated = True - for addr, status in changed_addresses.items(): - self.wallet.receive_status_callback(addr, status) - elif method == 'server.peers.subscribe': servers = [] for item in result: @@ -375,18 +319,14 @@ class WalletSynchronizer(threading.Thread): ports = [] if len(item)>2: for v in item[2]: - if re.match("[thn]\d+",v): + if re.match("[th]\d+",v): ports.append((v[0],v[1:])) - #if not s: - # s.append(host+":50000:n") - #else: - # s.append(host+":50000:n") if ports: servers.append( (host, ports) ) self.interface.servers = servers elif method == 'blockchain.address.subscribe': - addr = params[-1] + addr = params[0] self.wallet.receive_status_callback(addr, result) elif method == 'blockchain.address.get_history': @@ -418,15 +358,13 @@ class WalletSynchronizer(threading.Thread): port = int(port) #print protocol, host, port - if protocol == 'n': - InterfaceClass = NativeInterface - elif protocol == 't': + if protocol == 't': InterfaceClass = TcpStratumInterface elif protocol == 'h': InterfaceClass = HttpStratumInterface else: print "unknown protocol" - InterfaceClass = NativeInterface + InterfaceClass = TcpStratumInterface self.interface = InterfaceClass(host, port) self.wallet.interface = self.interface diff --git a/client/version.py b/client/version.py index a4b24de2..68897c9e 100644 --- a/client/version.py +++ b/client/version.py @@ -1,2 +1,2 @@ -ELECTRUM_VERSION = "0.43d" +ELECTRUM_VERSION = "0.44" SEED_VERSION = 4 # bump this everytime the seed generation is modified From b3fd4a28325ac6077640e0af5ab713f566d0370b Mon Sep 17 00:00:00 2001 From: genjix Date: Sun, 29 Apr 2012 17:49:41 +0100 Subject: [PATCH 02/12] mv client/* . && rm -fr client --- client/LICENCE => LICENCE | 0 client/MANIFEST.in => MANIFEST.in | 0 client/README => README | 0 client/RELEASE-NOTES => RELEASE-NOTES | 0 client/blocks => blocks | 0 client/bmp.py => bmp.py | 0 {client/docs => docs}/android.html | 0 client/electrum => electrum | 0 client/electrum4a.py => electrum4a.py | 0 .../electrum_text_320.png => electrum_text_320.png | Bin client/gui.py => gui.py | 0 client/gui_qt.py => gui_qt.py | 0 client/icons.qrc => icons.qrc | 0 {client/icons => icons}/confirmed.png | Bin {client/icons => icons}/lock.png | Bin {client/icons => icons}/lock.svg | 0 {client/icons => icons}/network.png | Bin {client/icons => icons}/preferences.png | Bin {client/icons => icons}/seed.png | Bin {client/icons => icons}/status_connected.png | Bin {client/icons => icons}/status_disconnected.png | Bin {client/icons => icons}/status_disconnected.svg | 0 {client/icons => icons}/status_waiting.png | Bin {client/icons => icons}/status_waiting.svg | 0 {client/icons => icons}/unconfirmed.png | Bin {client/icons => icons}/unconfirmed.svg | 0 client/interface.py => interface.py | 0 client/mnemonic.py => mnemonic.py | 0 client/msqr.py => msqr.py | 0 client/peers => peers | 0 client/pyqrnative.py => pyqrnative.py | 0 client/remote.php => remote.php | 0 client/remote_wallet.py => remote_wallet.py | 0 client/ripemd.py => ripemd.py | 0 client/setup.py => setup.py | 0 client/upgrade.py => upgrade.py | 0 client/version.py => version.py | 0 client/wallet.py => wallet.py | 0 38 files changed, 0 insertions(+), 0 deletions(-) rename client/LICENCE => LICENCE (100%) rename client/MANIFEST.in => MANIFEST.in (100%) rename client/README => README (100%) rename client/RELEASE-NOTES => RELEASE-NOTES (100%) rename client/blocks => blocks (100%) rename client/bmp.py => bmp.py (100%) rename {client/docs => docs}/android.html (100%) rename client/electrum => electrum (100%) rename client/electrum4a.py => electrum4a.py (100%) rename client/electrum_text_320.png => electrum_text_320.png (100%) rename client/gui.py => gui.py (100%) rename client/gui_qt.py => gui_qt.py (100%) rename client/icons.qrc => icons.qrc (100%) rename {client/icons => icons}/confirmed.png (100%) rename {client/icons => icons}/lock.png (100%) rename {client/icons => icons}/lock.svg (100%) rename {client/icons => icons}/network.png (100%) rename {client/icons => icons}/preferences.png (100%) rename {client/icons => icons}/seed.png (100%) rename {client/icons => icons}/status_connected.png (100%) rename {client/icons => icons}/status_disconnected.png (100%) rename {client/icons => icons}/status_disconnected.svg (100%) rename {client/icons => icons}/status_waiting.png (100%) rename {client/icons => icons}/status_waiting.svg (100%) rename {client/icons => icons}/unconfirmed.png (100%) rename {client/icons => icons}/unconfirmed.svg (100%) rename client/interface.py => interface.py (100%) rename client/mnemonic.py => mnemonic.py (100%) rename client/msqr.py => msqr.py (100%) rename client/peers => peers (100%) rename client/pyqrnative.py => pyqrnative.py (100%) rename client/remote.php => remote.php (100%) rename client/remote_wallet.py => remote_wallet.py (100%) rename client/ripemd.py => ripemd.py (100%) rename client/setup.py => setup.py (100%) rename client/upgrade.py => upgrade.py (100%) rename client/version.py => version.py (100%) rename client/wallet.py => wallet.py (100%) diff --git a/client/LICENCE b/LICENCE similarity index 100% rename from client/LICENCE rename to LICENCE diff --git a/client/MANIFEST.in b/MANIFEST.in similarity index 100% rename from client/MANIFEST.in rename to MANIFEST.in diff --git a/client/README b/README similarity index 100% rename from client/README rename to README diff --git a/client/RELEASE-NOTES b/RELEASE-NOTES similarity index 100% rename from client/RELEASE-NOTES rename to RELEASE-NOTES diff --git a/client/blocks b/blocks similarity index 100% rename from client/blocks rename to blocks diff --git a/client/bmp.py b/bmp.py similarity index 100% rename from client/bmp.py rename to bmp.py diff --git a/client/docs/android.html b/docs/android.html similarity index 100% rename from client/docs/android.html rename to docs/android.html diff --git a/client/electrum b/electrum similarity index 100% rename from client/electrum rename to electrum diff --git a/client/electrum4a.py b/electrum4a.py similarity index 100% rename from client/electrum4a.py rename to electrum4a.py diff --git a/client/electrum_text_320.png b/electrum_text_320.png similarity index 100% rename from client/electrum_text_320.png rename to electrum_text_320.png diff --git a/client/gui.py b/gui.py similarity index 100% rename from client/gui.py rename to gui.py diff --git a/client/gui_qt.py b/gui_qt.py similarity index 100% rename from client/gui_qt.py rename to gui_qt.py diff --git a/client/icons.qrc b/icons.qrc similarity index 100% rename from client/icons.qrc rename to icons.qrc diff --git a/client/icons/confirmed.png b/icons/confirmed.png similarity index 100% rename from client/icons/confirmed.png rename to icons/confirmed.png diff --git a/client/icons/lock.png b/icons/lock.png similarity index 100% rename from client/icons/lock.png rename to icons/lock.png diff --git a/client/icons/lock.svg b/icons/lock.svg similarity index 100% rename from client/icons/lock.svg rename to icons/lock.svg diff --git a/client/icons/network.png b/icons/network.png similarity index 100% rename from client/icons/network.png rename to icons/network.png diff --git a/client/icons/preferences.png b/icons/preferences.png similarity index 100% rename from client/icons/preferences.png rename to icons/preferences.png diff --git a/client/icons/seed.png b/icons/seed.png similarity index 100% rename from client/icons/seed.png rename to icons/seed.png diff --git a/client/icons/status_connected.png b/icons/status_connected.png similarity index 100% rename from client/icons/status_connected.png rename to icons/status_connected.png diff --git a/client/icons/status_disconnected.png b/icons/status_disconnected.png similarity index 100% rename from client/icons/status_disconnected.png rename to icons/status_disconnected.png diff --git a/client/icons/status_disconnected.svg b/icons/status_disconnected.svg similarity index 100% rename from client/icons/status_disconnected.svg rename to icons/status_disconnected.svg diff --git a/client/icons/status_waiting.png b/icons/status_waiting.png similarity index 100% rename from client/icons/status_waiting.png rename to icons/status_waiting.png diff --git a/client/icons/status_waiting.svg b/icons/status_waiting.svg similarity index 100% rename from client/icons/status_waiting.svg rename to icons/status_waiting.svg diff --git a/client/icons/unconfirmed.png b/icons/unconfirmed.png similarity index 100% rename from client/icons/unconfirmed.png rename to icons/unconfirmed.png diff --git a/client/icons/unconfirmed.svg b/icons/unconfirmed.svg similarity index 100% rename from client/icons/unconfirmed.svg rename to icons/unconfirmed.svg diff --git a/client/interface.py b/interface.py similarity index 100% rename from client/interface.py rename to interface.py diff --git a/client/mnemonic.py b/mnemonic.py similarity index 100% rename from client/mnemonic.py rename to mnemonic.py diff --git a/client/msqr.py b/msqr.py similarity index 100% rename from client/msqr.py rename to msqr.py diff --git a/client/peers b/peers similarity index 100% rename from client/peers rename to peers diff --git a/client/pyqrnative.py b/pyqrnative.py similarity index 100% rename from client/pyqrnative.py rename to pyqrnative.py diff --git a/client/remote.php b/remote.php similarity index 100% rename from client/remote.php rename to remote.php diff --git a/client/remote_wallet.py b/remote_wallet.py similarity index 100% rename from client/remote_wallet.py rename to remote_wallet.py diff --git a/client/ripemd.py b/ripemd.py similarity index 100% rename from client/ripemd.py rename to ripemd.py diff --git a/client/setup.py b/setup.py similarity index 100% rename from client/setup.py rename to setup.py diff --git a/client/upgrade.py b/upgrade.py similarity index 100% rename from client/upgrade.py rename to upgrade.py diff --git a/client/version.py b/version.py similarity index 100% rename from client/version.py rename to version.py diff --git a/client/wallet.py b/wallet.py similarity index 100% rename from client/wallet.py rename to wallet.py From 235e3756c5f02bff3a1534f611447bee45cdae7e Mon Sep 17 00:00:00 2001 From: ThomasV Date: Mon, 30 Apr 2012 11:48:02 +0200 Subject: [PATCH 03/12] fix: is_input --- electrum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/electrum b/electrum index 011d56f2..e7f378d6 100755 --- a/electrum +++ b/electrum @@ -288,7 +288,7 @@ if __name__ == '__main__': h = wallet.history.get(addr,[]) ni = no = 0 for item in h: - if item['is_in']: ni += 1 + if item['is_input']: ni += 1 else: no += 1 b = "%d %d %s"%(no, ni, str(Decimal(wallet.get_addr_balance(addr)[0])/100000000)) else: b='' From 3a0381bc0638df596b99a8379af60800d54946a9 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Mon, 30 Apr 2012 11:48:19 +0200 Subject: [PATCH 04/12] watch_address --- watch_address | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100755 watch_address diff --git a/watch_address b/watch_address new file mode 100755 index 00000000..d6146f89 --- /dev/null +++ b/watch_address @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +import interface, sys +try: + addr = sys.argv[1] +except: + print "usage: watch_address " + +i = interface.TcpStratumInterface('ecdsa.org', 50001) +i.start() +i.send([('blockchain.address.subscribe',[addr])]) + +while True: + r = i.responses.get(True, 100000000000) + method = r.get('method') + if method == 'blockchain.address.subscribe': + i.send([('blockchain.address.get_history',[addr])]) + elif method == 'blockchain.address.get_history': + confirmed = unconfirmed = 0 + h = r.get('result') + if not h: + continue + for item in h: + v = item['value'] + if item['height']: + confirmed += v + else: + uunconfirmed += v + print (confirmed+unconfirmed)/1.e8 + + From 86e867ae3048dc3d55e1a446e9bacc10d207ae0d Mon Sep 17 00:00:00 2001 From: ThomasV Date: Tue, 1 May 2012 10:55:10 +0200 Subject: [PATCH 05/12] assert address is in wallet (use watch_address if it is not) --- wallet.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/wallet.py b/wallet.py index d30bea71..d4be6852 100644 --- a/wallet.py +++ b/wallet.py @@ -609,11 +609,8 @@ class Wallet: def get_addr_balance(self, addr): - if self.is_mine(addr): - h = self.history.get(addr) - else: - h = self.interface.retrieve_history(addr) - if not h: return 0,0 + assert self.is_mine(addr) + h = self.history.get(addr,[]) c = u = 0 for item in h: v = item['value'] From 0ed56990219a68b83d4e5d21dd0796fb5797b105 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Tue, 1 May 2012 11:02:42 +0200 Subject: [PATCH 06/12] fix: display balance of unused addresses --- watch_address | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/watch_address b/watch_address index d6146f89..9d7b3816 100755 --- a/watch_address +++ b/watch_address @@ -18,7 +18,7 @@ while True: elif method == 'blockchain.address.get_history': confirmed = unconfirmed = 0 h = r.get('result') - if not h: + if h is None: continue for item in h: v = item['value'] From 50e5f910a768abf905891abd44155c256526dfc4 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Tue, 1 May 2012 14:57:37 +0200 Subject: [PATCH 07/12] remove native protocol from gui --- gui.py | 6 ------ gui_qt.py | 5 ----- 2 files changed, 11 deletions(-) diff --git a/gui.py b/gui.py index 77acdd1c..1703ddf3 100644 --- a/gui.py +++ b/gui.py @@ -328,9 +328,6 @@ def run_network_dialog( wallet, parent ): radio2 = gtk.RadioButton(radio1, "http") p_box.pack_start(radio2, True, True, 0) radio2.show() - radio3 = gtk.RadioButton(radio1, "native") - p_box.pack_start(radio3, True, True, 0) - radio3.show() def current_line(): return unicode(host_entry.get_text()).split(':') @@ -340,8 +337,6 @@ def run_network_dialog( wallet, parent ): radio1.set_active(1) elif protocol == 'h': radio2.set_active(1) - elif protocol == 'n': - radio3.set_active(1) def set_protocol(protocol): host = current_line()[0] @@ -354,7 +349,6 @@ def run_network_dialog( wallet, parent ): radio1.connect("toggled", lambda x,y:set_protocol('t'), "radio button 1") radio2.connect("toggled", lambda x,y:set_protocol('h'), "radio button 1") - radio3.connect("toggled", lambda x,y:set_protocol('n'), "radio button 1") server_list = gtk.ListStore(str) for host in plist.keys(): diff --git a/gui_qt.py b/gui_qt.py index 2620ac0e..9f47da50 100644 --- a/gui_qt.py +++ b/gui_qt.py @@ -895,7 +895,6 @@ class ElectrumWindow(QMainWindow): buttonGroup = QGroupBox("protocol") radio1 = QRadioButton("tcp", buttonGroup) radio2 = QRadioButton("http", buttonGroup) - radio3 = QRadioButton("native", buttonGroup) def current_line(): return unicode(host_line.text()).split(':') @@ -905,8 +904,6 @@ class ElectrumWindow(QMainWindow): radio1.setChecked(1) elif protocol == 'h': radio2.setChecked(1) - elif protocol == 'n': - radio3.setChecked(1) def set_protocol(protocol): host = current_line()[0] @@ -919,14 +916,12 @@ class ElectrumWindow(QMainWindow): radio1.clicked.connect(lambda x: set_protocol('t') ) radio2.clicked.connect(lambda x: set_protocol('h') ) - radio3.clicked.connect(lambda x: set_protocol('n') ) set_button(current_line()[2]) hbox.addWidget(QLabel('Protocol:')) hbox.addWidget(radio1) hbox.addWidget(radio2) - hbox.addWidget(radio3) vbox.addLayout(hbox) From 9050a413815cc430e2f6cece49639f652deb5d54 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Tue, 1 May 2012 17:06:14 +0200 Subject: [PATCH 08/12] more QR code capabilities: encode amount, save to file --- bmp.py | 16 +++++++++++ electrum4a.py | 52 +++++++++++++++++----------------- gui_qt.py | 78 +++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 110 insertions(+), 36 deletions(-) diff --git a/bmp.py b/bmp.py index bfdd165b..b4bd4102 100644 --- a/bmp.py +++ b/bmp.py @@ -193,7 +193,23 @@ class BitMap(object): f.close() +def save_qrcode(qr, filename): + bitmap = BitMap( 35*8, 35*8 ) + #print len(bitmap.bitarray) + bitmap.bitarray = [] + k = 33 + for r in range(35): + tmparray = [ 0 ] * 35*8 + if 0 < r < 34: + for c in range(k): + if qr.isDark(r-1, c): + tmparray[ (1+c)*8:(2+c)*8] = [1]*8 + + for i in range(8): + bitmap.bitarray.append( tmparray[:] ) + + bitmap.saveFile( filename ) diff --git a/electrum4a.py b/electrum4a.py index f2477644..1698cc96 100755 --- a/electrum4a.py +++ b/electrum4a.py @@ -26,7 +26,7 @@ from wallet import format_satoshis from decimal import Decimal import mnemonic -import datetime +import datetime, re @@ -606,6 +606,10 @@ def main_loop(): elif out == "receive": global receive_addr receive_addr = select_from_addresses() + amount = modal_input('Amount', 'Amount you want receive. ', '', "numberDecimal") + if amount: + receive_addr = 'bitcoin:%s?amount=%s'%(receive_addr, amount) + if not receive_addr: out = None @@ -656,9 +660,16 @@ def payto_loop(): code = droid.scanBarcode() r = code.result if r: - addr = r['extras']['SCAN_RESULT'] - if addr: - droid.fullSetProperty("recipient","text",addr) + data = r['extras']['SCAN_RESULT'] + if data: + if re.match('^bitcoin:', data): + payto, amount, label, _, _, _, _ = wallet.parse_url(data, None, None) + droid.fullSetProperty("recipient", "text",payto) + droid.fullSetProperty("amount", "text", amount) + droid.fullSetProperty("label", "text", label) + else: + droid.fullSetProperty("recipient", "text", data) + elif event["name"] in menu_commands: out = event["name"] @@ -923,29 +934,16 @@ def make_bitmap(addr): # fixme: this is highly inefficient droid.dialogCreateSpinnerProgress("please wait") droid.dialogShow() - import pyqrnative, bmp - qr = pyqrnative.QRCode(4, pyqrnative.QRErrorCorrectLevel.H) - qr.addData(addr) - qr.make() - k = qr.getModuleCount() - bitmap = bmp.BitMap( 35*8, 35*8 ) - print len(bitmap.bitarray) - bitmap.bitarray = [] - assert k == 33 - - for r in range(35): - tmparray = [ 0 ] * 35*8 - - if 0 < r < 34: - for c in range(k): - if qr.isDark(r-1, c): - tmparray[ (1+c)*8:(2+c)*8] = [1]*8 - - for i in range(8): - bitmap.bitarray.append( tmparray[:] ) - - bitmap.saveFile( "/sdcard/sl4a/qrcode.bmp" ) - droid.dialogDismiss() + try: + import pyqrnative, bmp + qr = pyqrnative.QRCode(4, pyqrnative.QRErrorCorrectLevel.L) + qr.addData(addr) + qr.make() + k = qr.getModuleCount() + assert k == 33 + bmp.save_qrcode(qr,"/sdcard/sl4a/qrcode.bmp") + finally: + droid.dialogDismiss() diff --git a/gui_qt.py b/gui_qt.py index 9f47da50..6206612c 100644 --- a/gui_qt.py +++ b/gui_qt.py @@ -96,11 +96,14 @@ class StatusBarButton(QPushButton): class QRCodeWidget(QWidget): def __init__(self, addr): - import pyqrnative super(QRCodeWidget, self).__init__() - self.addr = addr self.setGeometry(300, 300, 350, 350) - self.qr = pyqrnative.QRCode(4, pyqrnative.QRErrorCorrectLevel.H) + self.set_addr(addr) + + def set_addr(self, addr): + import pyqrnative + self.addr = addr + self.qr = pyqrnative.QRCode(4, pyqrnative.QRErrorCorrectLevel.L) self.qr.addData(addr) self.qr.make() @@ -524,7 +527,7 @@ class ElectrumWindow(QMainWindow): addr = unicode( i.text(0) ) return addr - qrButton = EnterButton("QR",lambda: ElectrumWindow.showqrcode(get_addr(l))) + qrButton = EnterButton("QR",lambda: self.show_address_qrcode(get_addr(l))) def copy2clipboard(addr): self.app.clipboard().setText(addr) @@ -657,18 +660,75 @@ class ElectrumWindow(QMainWindow): + ' '.join(mnemonic.mn_encode(seed)) + "\"" QMessageBox.information(parent, 'Seed', msg, 'OK') - ElectrumWindow.showqrcode(seed) + ElectrumWindow.show_seed_qrcode(seed) @staticmethod - def showqrcode(address): + def show_seed_qrcode(seed): + if not seed: return + d = QDialog(None) + d.setModal(1) + d.setWindowTitle(seed) + d.setMinimumSize(270, 300) + vbox = QVBoxLayout() + vbox.addWidget(QRCodeWidget(seed)) + hbox = QHBoxLayout() + hbox.addStretch(1) + b = QPushButton("OK") + hbox.addWidget(b) + b.clicked.connect(d.accept) + + vbox.addLayout(hbox) + d.setLayout(vbox) + d.exec_() + + def show_address_qrcode(self,address): if not address: return d = QDialog(None) d.setModal(1) d.setWindowTitle(address) - d.setMinimumSize(270, 300) + d.setMinimumSize(270, 350) vbox = QVBoxLayout() - vbox.addWidget(QRCodeWidget(address)) - vbox.addLayout(ok_cancel_buttons(d)) + qrw = QRCodeWidget(address) + vbox.addWidget(qrw) + + hbox = QHBoxLayout() + amount_e = QLineEdit() + hbox.addWidget(QLabel('Amount')) + hbox.addWidget(amount_e) + vbox.addLayout(hbox) + + #hbox = QHBoxLayout() + #label_e = QLineEdit() + #hbox.addWidget(QLabel('Label')) + #hbox.addWidget(label_e) + #vbox.addLayout(hbox) + + def amount_changed(): + amount = numbify(amount_e) + #label = str( label_e.getText() ) + if amount is not None: + qrw.set_addr('bitcoin:%s?amount=%s'%(address,str( Decimal(amount) /100000000))) + else: + qrw.set_addr( address ) + qrw.repaint() + + def do_save(): + import bmp + bmp.save_qrcode(qrw.qr, "qrcode.bmp") + self.show_message("QR code saved to file 'qrcode.bmp'") + + amount_e.textChanged.connect( amount_changed ) + + hbox = QHBoxLayout() + hbox.addStretch(1) + b = QPushButton("Save") + b.clicked.connect(do_save) + hbox.addWidget(b) + b = QPushButton("Close") + hbox.addWidget(b) + b.clicked.connect(d.accept) + + vbox.addLayout(hbox) d.setLayout(vbox) d.exec_() From 973e5af9259b3d2754fba79bd65361220b29dc9f Mon Sep 17 00:00:00 2001 From: ThomasV Date: Tue, 1 May 2012 17:15:27 +0200 Subject: [PATCH 09/12] do not show seed qr code during wallet creation --- gui_qt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui_qt.py b/gui_qt.py index 6206612c..9a8b28f4 100644 --- a/gui_qt.py +++ b/gui_qt.py @@ -660,7 +660,7 @@ class ElectrumWindow(QMainWindow): + ' '.join(mnemonic.mn_encode(seed)) + "\"" QMessageBox.information(parent, 'Seed', msg, 'OK') - ElectrumWindow.show_seed_qrcode(seed) + if parent: ElectrumWindow.show_seed_qrcode(seed) @staticmethod def show_seed_qrcode(seed): From c2a1015abae036d0103536c94a085af9da0a123d Mon Sep 17 00:00:00 2001 From: ThomasV Date: Tue, 1 May 2012 17:23:36 +0200 Subject: [PATCH 10/12] fix: do not ask amount if the action is cancelled --- electrum4a.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/electrum4a.py b/electrum4a.py index 1698cc96..513267b2 100755 --- a/electrum4a.py +++ b/electrum4a.py @@ -606,9 +606,10 @@ def main_loop(): elif out == "receive": global receive_addr receive_addr = select_from_addresses() - amount = modal_input('Amount', 'Amount you want receive. ', '', "numberDecimal") - if amount: - receive_addr = 'bitcoin:%s?amount=%s'%(receive_addr, amount) + if receive_addr: + amount = modal_input('Amount', 'Amount you want receive. ', '', "numberDecimal") + if amount: + receive_addr = 'bitcoin:%s?amount=%s'%(receive_addr, amount) if not receive_addr: out = None From 543262e29ee34b5d4cedd344beadba3de653ab8c Mon Sep 17 00:00:00 2001 From: ThomasV Date: Tue, 1 May 2012 21:37:35 +0200 Subject: [PATCH 11/12] fix:typo --- watch_address | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/watch_address b/watch_address index 9d7b3816..162c5a6d 100755 --- a/watch_address +++ b/watch_address @@ -25,7 +25,7 @@ while True: if item['height']: confirmed += v else: - uunconfirmed += v + unconfirmed += v print (confirmed+unconfirmed)/1.e8 From b8fa306bd81a4f994037dac1ebf3430429f11b62 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Tue, 1 May 2012 21:40:30 +0200 Subject: [PATCH 12/12] version 0.45 --- version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.py b/version.py index 68897c9e..ee1f00c2 100644 --- a/version.py +++ b/version.py @@ -1,2 +1,2 @@ -ELECTRUM_VERSION = "0.44" +ELECTRUM_VERSION = "0.45" SEED_VERSION = 4 # bump this everytime the seed generation is modified