tWork in progress on Label syncing - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit e8b97e5326df188422529ccd12a0ff64bea1c3d0 DIR parent 18bcf5b206664e3a9d2392ba54c349423eb9456b HTML Author: Maran <maran.hidskes@gmail.com> Date: Sun, 10 Mar 2013 17:04:00 +0100 Work in progress on Label syncing Diffstat: M gui/gui_classic.py | 12 +++++++++++- M icons.qrc | 1 + A plugins/labels.py | 118 +++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+), 1 deletion(-) --- DIR diff --git a/gui/gui_classic.py b/gui/gui_classic.py t@@ -273,6 +273,8 @@ class ElectrumWindow(QMainWindow): self.config = config self.init_plugins() + self.create_status_bar() + self.wallet.interface.register_callback('updated', lambda: self.emit(QtCore.SIGNAL('update_wallet'))) self.wallet.interface.register_callback('banner', lambda: self.emit(QtCore.SIGNAL('banner_signal'))) self.wallet.interface.register_callback('disconnected', lambda: self.emit(QtCore.SIGNAL('update_status'))) t@@ -295,7 +297,6 @@ class ElectrumWindow(QMainWindow): tabs.setMinimumSize(600, 400) tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setCentralWidget(tabs) - self.create_status_bar() g = self.config.get("winpos-qt",[100, 100, 840, 400]) self.setGeometry(g[0], g[1], g[2], g[3]) t@@ -520,6 +521,9 @@ class ElectrumWindow(QMainWindow): text = unicode( item.text(2) ) if text: self.wallet.labels[tx_hash] = text + # Label changed + self.run_hook('label_changed',(self, str(tx_hash), text)) + item.setForeground(2, QBrush(QColor('black'))) else: if s: self.wallet.labels.pop(tx_hash) t@@ -562,6 +566,7 @@ class ElectrumWindow(QMainWindow): if old_addr != addr: self.wallet.labels[addr] = text changed = True + self.run_hook('label_changed',(self, addr, text)) else: print_error("Error: This is one of your aliases") label = self.wallet.labels.get(addr,'') t@@ -1195,6 +1200,8 @@ class ElectrumWindow(QMainWindow): self.status_button = StatusBarButton( QIcon(":icons/status_disconnected.png"), _("Network"), lambda: self.network_dialog(self.wallet, self) ) sb.addPermanentWidget( self.status_button ) + self.run_hook('create_status_bar', (sb,)) + self.setStatusBar(sb) def go_lite(self): t@@ -1866,6 +1873,7 @@ class ElectrumWindow(QMainWindow): vbox = QVBoxLayout() tabs = QTabWidget(self) + self.settings_tab = tabs vbox.addWidget(tabs) tab1 = QWidget() t@@ -2040,6 +2048,8 @@ class ElectrumWindow(QMainWindow): traceback.print_exc(file=sys.stdout) grid_plugins.setRowStretch(i+1,1) + self.run_hook('create_settings_tab', (self,tabs,)) + vbox.addLayout(ok_cancel_buttons(d)) d.setLayout(vbox) DIR diff --git a/icons.qrc b/icons.qrc t@@ -16,5 +16,6 @@ <file>icons/switchgui.png</file> <file>icons/unconfirmed.png</file> <file>icons/network.png</file> + <file>icons/cloud.png</file> </qresource> </RCC> DIR diff --git a/plugins/labels.py b/plugins/labels.py t@@ -0,0 +1,118 @@ +from electrum.util import print_error +import httplib, urllib +import hashlib +import json +from urlparse import urlparse, parse_qs +try: + import PyQt4 +except: + sys.exit("Error: Could not import PyQt4 on Linux systems, you may try 'sudo apt-get install python-qt4'") + +from PyQt4.QtGui import * +from PyQt4.QtCore import * +import PyQt4.QtCore as QtCore +import PyQt4.QtGui as QtGui + +target_host = 'localhost:3000' +auth_token = 'jEnsNBb5fAR5rYSBNYnR' + +def init(gui): + cloud_wallet = CloudWallet(gui.wallet) + gui.set_hook('create_settings_tab', add_settings_tab) + gui.set_hook('label_changed', label_changed) + cloud_wallet.full_pull() + +def wallet_id(wallet): + return hashlib.sha256(str(wallet.get_master_public_key())).digest().encode('hex') + + +def label_changed(gui,item,label): + print "Label changed! Item: %s Label: %s label" % ( item, label) + global auth_token, target_host + hashed = hashlib.sha256(item).digest().encode('hex') + bundle = {"label": {"external_id": hashed, "text": label}} + params = json.dumps(bundle) + connection = httplib.HTTPConnection(target_host) + connection.request("POST", ("/api/wallets/%s/labels.json?auth_token=%s" % (wallet_id(gui.wallet), auth_token)), params, {'Content-Type': 'application/json'}) + + response = connection.getresponse() + if response.reason == httplib.responses[httplib.NOT_FOUND]: + return + response = json.loads(response.read()) + +def add_settings_tab(gui, tabs): + cloud_tab = QWidget() + layout = QGridLayout(cloud_tab) + layout.addWidget(QLabel("API Key: "),0,0) + layout.addWidget(QLineEdit(), 0,2) + + layout.addWidget(QLabel("Label sync options: "),1,0) + layout.addWidget(QPushButton("Force upload"), 1,1) + layout.addWidget(QPushButton("Force download"), 1,2) + + tabs.addTab(cloud_tab, "Label cloud") + +def show(): + print 'showing' + +def get_info(): + return 'Label sync', "Syncs your labels with LabElectrum. Labels are not encrypted, transactions and addresses are however." + +def is_enabled(): + return True + +def toggle(gui): + return is_enabled() + + +class CloudWallet(): + def __init__(self, wallet): + self.mpk = hashlib.sha256(str(wallet.get_master_public_key())).digest().encode('hex') + self.labels = wallet.labels + self.transactions = wallet.transactions + + addresses = [] + for k, account in wallet.accounts.items(): + for address in account[0]: + addresses.append(address) + + self.addresses = addresses + + + def full_pull(self): + global target_host, auth_token + connection = httplib.HTTPConnection(target_host) + connection.request("GET", ("/api/wallets/%s/labels.json?auth_token=%s" % (self.mpk, auth_token)),"", {'Content-Type': 'application/json'}) + response = connection.getresponse() + if response.reason == httplib.responses[httplib.NOT_FOUND]: + return + + response = json.loads(response.read()) + for label in response: + for key in self.addresses: + target_hashed = hashlib.sha256(key).digest().encode('hex') + if label["external_id"] == target_hashed: + if not self.labels.get(key): + self.labels[key] = label["text"] + for key, value in self.transactions.iteritems(): + target_hashed = hashlib.sha256(key).digest().encode('hex') + if label["external_id"] == target_hashed: + if not self.labels.get(key): + self.labels[key] = label["text"] + + def full_push(self): + global target_host, auth_token + + bundle = {"labels": {}} + for key, value in self.labels.iteritems(): + hashed = hashlib.sha256(key).digest().encode('hex') + bundle["labels"][hashed] = value + + params = json.dumps(bundle) + connection = httplib.HTTPConnection(target_host) + connection.request("POST", ("/api/wallets/%s/labels/batch.json?auth_token=%s" % (self.mpk, auth_token)), params, {'Content-Type': 'application/json'}) + + response = connection.getresponse() + if response.reason == httplib.responses[httplib.NOT_FOUND]: + return + response = json.loads(response.read())