1 from electrum.util import print_error
5 from urlparse import urlparse, parse_qs
9 sys.exit("Error: Could not import PyQt4 on Linux systems, you may try 'sudo apt-get install python-qt4'")
11 from PyQt4.QtGui import *
12 from PyQt4.QtCore import *
13 import PyQt4.QtCore as QtCore
14 import PyQt4.QtGui as QtGui
16 target_host = 'labelectrum.herokuapp.com'
19 """If you want to give this a spin create a account at the target_host url and put it in your user dir config
20 file with the label_api_key."""
23 auth_token = gui.config.get("label_api_key")
27 cloud_wallet = CloudWallet(gui.wallet)
28 gui.set_hook('create_settings_tab', add_settings_tab)
29 gui.set_hook('label_changed', label_changed)
30 cloud_wallet.full_pull()
32 def wallet_id(wallet):
33 return hashlib.sha256(str(wallet.get_master_public_key())).digest().encode('hex')
35 def label_changed(gui,item,label):
36 print "Label changed! Item: %s Label: %s label" % ( item, label)
37 global auth_token, target_host
38 hashed = hashlib.sha256(item).digest().encode('hex')
39 bundle = {"label": {"external_id": hashed, "text": label}}
40 params = json.dumps(bundle)
41 connection = httplib.HTTPConnection(target_host)
42 wallet = wallet_id(gui.wallet)
43 connection.request("POST", ("/api/wallets/%s/labels.json?auth_token=%s" % (wallet, auth_token)), params, {'Content-Type': 'application/json'})
45 response = connection.getresponse()
46 if response.reason == httplib.responses[httplib.NOT_FOUND]:
48 response = json.loads(response.read())
50 def add_settings_tab(gui, tabs):
52 layout = QGridLayout(cloud_tab)
53 layout.addWidget(QLabel("API Key: "),0,0)
54 layout.addWidget(QLineEdit(auth_token), 0,2)
56 layout.addWidget(QLabel("Label sync options: "),1,0)
58 upload = QPushButton("Force upload")
59 upload.clicked.connect(lambda: full_push(gui.wallet))
60 layout.addWidget(upload, 1,1)
62 download = QPushButton("Force download")
63 download.clicked.connect(lambda: full_pull(gui.wallet))
64 layout.addWidget(download, 1,2)
66 tabs.addTab(cloud_tab, "Label cloud")
68 def full_push(wallet):
69 cloud_wallet = CloudWallet(wallet)
70 cloud_wallet.full_push()
73 def full_pull(wallet):
74 cloud_wallet = CloudWallet(wallet)
75 cloud_wallet.full_pull(True)
76 print "Labels pulled, please restart your client"
82 return 'Label sync', "Syncs your labels with LabElectrum. 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."
90 # This can probably be refactored into plain top level methods instead of a class
92 def __init__(self, wallet):
93 self.mpk = hashlib.sha256(str(wallet.get_master_public_key())).digest().encode('hex')
94 self.labels = wallet.labels
95 self.transactions = wallet.transactions
98 for k, account in wallet.accounts.items():
99 for address in account[0]:
100 addresses.append(address)
102 self.addresses = addresses
105 def full_pull(self, force = False):
106 global target_host, auth_token
107 connection = httplib.HTTPConnection(target_host)
108 connection.request("GET", ("/api/wallets/%s/labels.json?auth_token=%s" % (self.mpk, auth_token)),"", {'Content-Type': 'application/json'})
109 response = connection.getresponse()
110 if response.reason == httplib.responses[httplib.NOT_FOUND]:
113 response = json.loads(response.read())
114 except ValueError as e:
117 for label in response:
118 for key in self.addresses:
119 target_hashed = hashlib.sha256(key).digest().encode('hex')
120 if label["external_id"] == target_hashed:
121 if force or not self.labels.get(key):
122 self.labels[key] = label["text"]
123 for key, value in self.transactions.iteritems():
124 target_hashed = hashlib.sha256(key).digest().encode('hex')
125 if label["external_id"] == target_hashed:
126 if force or not self.labels.get(key):
127 self.labels[key] = label["text"]
130 global target_host, auth_token
132 bundle = {"labels": {}}
133 for key, value in self.labels.iteritems():
134 hashed = hashlib.sha256(key).digest().encode('hex')
135 bundle["labels"][hashed] = value
137 params = json.dumps(bundle)
138 connection = httplib.HTTPConnection(target_host)
139 connection.request("POST", ("/api/wallets/%s/labels/batch.json?auth_token=%s" % (self.mpk, auth_token)), params, {'Content-Type': 'application/json'})
141 response = connection.getresponse()
142 if response.reason == httplib.responses[httplib.NOT_FOUND]:
144 response = json.loads(response.read())