1 from electrum.util import print_error
2 from electrum_gui.i18n import _
6 from urlparse import urlparse, parse_qs
10 sys.exit("Error: Could not import PyQt4 on Linux systems, you may try 'sudo apt-get install python-qt4'")
12 from PyQt4.QtGui import *
13 from PyQt4.QtCore import *
14 import PyQt4.QtCore as QtCore
15 import PyQt4.QtGui as QtGui
17 target_host = 'labelectrum.herokuapp.com'
25 return config.get("plugin_label_api_key")
28 """If you want to give this a spin create a account at the target_host url and put it in your user dir config
29 file with the label_api_key."""
34 if config.get('plugin_label_enabled'):
35 gui.set_hook('create_settings_tab', add_settings_tab)
36 gui.set_hook('close_settings_dialog', close_settings_dialog)
41 cloud_wallet = CloudWallet(gui.wallet)
42 gui.set_hook('set_label', set_label)
44 cloud_wallet.full_pull()
48 return hashlib.sha256(str(config.get("master_public_key"))).digest().encode('hex')
50 def set_label(item,label, changed):
54 print "Label changed! Item: %s Label: %s label" % ( item, label)
56 hashed = hashlib.sha256(item).digest().encode('hex')
57 bundle = {"label": {"external_id": hashed, "text": label}}
58 params = json.dumps(bundle)
59 connection = httplib.HTTPConnection(target_host)
60 connection.request("POST", ("/api/wallets/%s/labels.json?auth_token=%s" % (wallet_id(), auth_token())), params, {'Content-Type': 'application/json'})
62 response = connection.getresponse()
63 if response.reason == httplib.responses[httplib.NOT_FOUND]:
65 response = json.loads(response.read())
67 def close_settings_dialog(gui):
70 # When you enable the plugin for the first time this won't exist.
72 if hasattr(gui, 'auth_token_edit'):
73 config.set_key("plugin_label_api_key", str(gui.auth_token_edit.text()))
75 QMessageBox.information(None, _("Cloud plugin loaded"), _("Please open the settings again to configure the label-cloud plugin."))
77 def add_settings_tab(gui, tabs):
78 def check_for_api_key(api_key):
80 if api_key and len(api_key) > 12:
81 config.set_key("plugin_label_api_key", str(gui.auth_token_edit.text()))
82 upload.setEnabled(True)
83 download.setEnabled(True)
85 upload.setEnabled(False)
86 download.setEnabled(False)
89 layout = QGridLayout(cloud_tab)
90 layout.addWidget(QLabel("API Key: "),0,0)
92 # TODO: I need to add it to the Electrum GUI here so I can retrieve it later when the settings dialog is closed, is there a better way to do this?
93 gui.auth_token_edit = QLineEdit(auth_token())
94 gui.auth_token_edit.textChanged.connect(check_for_api_key)
96 layout.addWidget(gui.auth_token_edit, 0,1,1,2)
97 layout.addWidget(QLabel("Label cloud options: "),1,0)
99 upload = QPushButton("Force upload")
100 upload.clicked.connect(lambda: full_push(gui.wallet))
101 layout.addWidget(upload, 1,1)
103 download = QPushButton("Force download")
104 download.clicked.connect(lambda: full_pull(gui.wallet))
105 layout.addWidget(download, 1,2)
107 gui.cloud_tab = cloud_tab
108 check_for_api_key(auth_token())
110 tabs.addTab(cloud_tab, "Label cloud")
112 def full_push(wallet):
113 cloud_wallet = CloudWallet(wallet)
114 cloud_wallet.full_push()
115 QMessageBox.information(None, _("Labels synced"), _("Your labels have been uploaded."))
117 def full_pull(wallet):
118 cloud_wallet = CloudWallet(wallet)
119 cloud_wallet.full_pull(True)
120 QMessageBox.information(None, _("Labels synced"), _("Your labels have been synced, please restart Electrum for the changes to take effect."))
126 return 'Label sync', "Syncs your labels with 'the cloud'. Labels are not encrypted, transactions and addresses are however. This code might increase the load of your wallet with a few micoseconds as it will sync labels on each startup."
129 return config.get('plugin_label_enabled') is True
136 gui.unset_hook('create_settings_tab', add_settings_tab)
137 gui.unset_hook('close_settings_dialog', close_settings_dialog)
139 config.set_key('plugin_label_enabled', enabled, True)
145 # This can probably be refactored into plain top level methods instead of a class
147 def __init__(self, wallet):
148 self.labels = wallet.labels
149 self.transactions = wallet.transactions
152 for k, account in wallet.accounts.items():
153 for address in account[0]:
154 addresses.append(address)
156 self.addresses = addresses
158 def full_pull(self, force = False):
160 connection = httplib.HTTPConnection(target_host)
161 connection.request("GET", ("/api/wallets/%s/labels.json?auth_token=%s" % (wallet_id(), auth_token())),"", {'Content-Type': 'application/json'})
162 response = connection.getresponse()
163 if response.reason == httplib.responses[httplib.NOT_FOUND]:
166 response = json.loads(response.read())
167 except ValueError as e:
170 if "error" in response:
171 QMessageBox.warning(None, _("Error"),_("Could not sync labels: %s" % response["error"]))
174 for label in response:
175 for key in self.addresses:
176 target_hashed = hashlib.sha256(key).digest().encode('hex')
177 if label["external_id"] == target_hashed:
178 if force or not self.labels.get(key):
179 self.labels[key] = label["text"]
180 for key, value in self.transactions.iteritems():
181 target_hashed = hashlib.sha256(key).digest().encode('hex')
182 if label["external_id"] == target_hashed:
183 if force or not self.labels.get(key):
184 self.labels[key] = label["text"]
189 bundle = {"labels": {}}
190 for key, value in self.labels.iteritems():
191 hashed = hashlib.sha256(key).digest().encode('hex')
192 bundle["labels"][hashed] = value
194 params = json.dumps(bundle)
195 connection = httplib.HTTPConnection(target_host)
196 connection.request("POST", ("/api/wallets/%s/labels/batch.json?auth_token=%s" % (wallet_id(), auth_token())), params, {'Content-Type': 'application/json'})
198 response = connection.getresponse()
199 if response.reason == httplib.responses[httplib.NOT_FOUND]:
202 response = json.loads(response.read())
203 except ValueError as e:
206 if "error" in response:
207 QMessageBox.warning(None, _("Error"),_("Could not sync labels: %s" % response["error"]))