Browse Source

big refactoring: command line options and electrum.conf options override settings in wallet file.

283
thomasv 12 years ago
parent
commit
5444f55e6b
  1. 63
      electrum
  2. 3
      lib/__init__.py
  3. 10
      lib/gui.py
  4. 46
      lib/gui_lite.py
  5. 81
      lib/gui_qt.py
  6. 110
      lib/interface.py
  7. 226
      lib/simple_config.py
  8. 199
      lib/wallet.py
  9. 4
      scripts/blocks
  10. 4
      scripts/get_history
  11. 4
      scripts/merchant.py
  12. 4
      scripts/peers
  13. 4
      scripts/watch_address

63
electrum

@ -18,7 +18,6 @@
import re import re
import sys import sys
# import argparse
import optparse import optparse
try: try:
@ -37,9 +36,9 @@ except ImportError:
sys.exit("Error: AES does not seem to be installed. Try 'sudo pip install slowaes'") sys.exit("Error: AES does not seem to be installed. Try 'sudo pip install slowaes'")
try: try:
from lib import Wallet, WalletSynchronizer, format_satoshis, mnemonic, prompt_password, parse_proxy_options, SimpleConfig from lib import Wallet, WalletSynchronizer, format_satoshis, mnemonic, prompt_password, SimpleConfig, pick_random_server
except ImportError: except ImportError:
from electrum import Wallet, WalletSynchronizer, format_satoshis, mnemonic, prompt_password, parse_proxy_options, SimpleConfig from electrum import Wallet, WalletSynchronizer, format_satoshis, mnemonic, prompt_password, SimpleConfig, pick_random_server
from decimal import Decimal from decimal import Decimal
@ -95,33 +94,39 @@ options:\n --fee, -f: set transaction fee\n --fromaddr, -s: send from address
offline_commands = [ 'password', 'mktx', 'label', 'contacts', 'help', 'validateaddress', 'signmessage', 'verifymessage', 'eval', 'create', 'addresses', 'import', 'seed','deseed','reseed','freeze','unfreeze','prioritize','unprioritize'] offline_commands = [ 'password', 'mktx',
'label', 'contacts',
'help', 'validateaddress',
'signmessage', 'verifymessage',
'eval', 'create', 'addresses',
'import', 'seed',
'deseed','reseed',
'freeze','unfreeze',
'prioritize','unprioritize']
protected_commands = ['payto', 'password', 'mktx', 'seed', 'import','signmessage' ] protected_commands = ['payto', 'password', 'mktx', 'seed', 'import','signmessage' ]
if __name__ == '__main__': if __name__ == '__main__':
# Load simple config class
simple_config = SimpleConfig()
usage = "usage: %prog [options] command\nCommands: "+ (', '.join(known_commands)) usage = "usage: %prog [options] command\nCommands: "+ (', '.join(known_commands))
parser = optparse.OptionParser(prog=usage) parser = optparse.OptionParser(prog=usage)
parser.add_option("-g", "--gui", dest="gui", default=simple_config.config["gui"], help="gui") parser.add_option("-g", "--gui", dest="gui", help="gui")
parser.add_option("-w", "--wallet", dest="wallet_path", help="wallet path (default: electrum.dat)") parser.add_option("-w", "--wallet", dest="wallet_path", help="wallet path (default: electrum.dat)")
parser.add_option("-o", "--offline", action="store_true", dest="offline", default=False, help="remain offline") parser.add_option("-o", "--offline", action="store_true", dest="offline", default=False, help="remain offline")
parser.add_option("-a", "--all", action="store_true", dest="show_all", default=False, help="show all addresses") parser.add_option("-a", "--all", action="store_true", dest="show_all", default=False, help="show all addresses")
parser.add_option("-b", "--balance", action="store_true", dest="show_balance", default=False, help="show the balance at listed addresses") parser.add_option("-b", "--balance", action="store_true", dest="show_balance", default=False, help="show the balance at listed addresses")
parser.add_option("-k", "--keys",action="store_true", dest="show_keys",default=False, help="show the private keys of listed addresses") parser.add_option("-k", "--keys",action="store_true", dest="show_keys",default=False, help="show the private keys of listed addresses")
parser.add_option("-f", "--fee", dest="tx_fee", default="0.005", help="set tx fee") parser.add_option("-f", "--fee", dest="tx_fee", default="0.005", help="set tx fee")
parser.add_option("-s", "--fromaddr", dest="from_addr", default=None, help="set source address for payto/mktx. if it isn't in the wallet, it will ask for the private key unless supplied in the format public_key:private_key. It's not saved in the wallet.") parser.add_option("-F", "--fromaddr", dest="from_addr", default=None, help="set source address for payto/mktx. if it isn't in the wallet, it will ask for the private key unless supplied in the format public_key:private_key. It's not saved in the wallet.")
parser.add_option("-c", "--changeaddr", dest="change_addr", default=None, help="set the change address for payto/mktx. default is a spare address, or the source address if it's not in the wallet") parser.add_option("-c", "--changeaddr", dest="change_addr", default=None, help="set the change address for payto/mktx. default is a spare address, or the source address if it's not in the wallet")
parser.add_option("-s", "--server", dest="server", default=None, help="set server host:port:protocol, where protocol is t or h")
parser.add_option("-p", "--proxy", dest="proxy", default=None, help="set proxy [type:]host[:port], where type is socks4,socks5 or http") parser.add_option("-p", "--proxy", dest="proxy", default=None, help="set proxy [type:]host[:port], where type is socks4,socks5 or http")
options, args = parser.parse_args() options, args = parser.parse_args()
proxy = parse_proxy_options(options.proxy) if options.proxy else simple_config.config["proxy"] # config is an object passed to the various constructors (wallet, interface, gui)
wallet = Wallet() config = SimpleConfig(options)
wallet.set_path(options.wallet_path) wallet = Wallet(config)
wallet.read()
if len(args)==0: if len(args)==0:
url = None url = None
@ -136,31 +141,31 @@ if __name__ == '__main__':
#this entire if/else block is just concerned with importing the #this entire if/else block is just concerned with importing the
#right GUI toolkit based the GUI command line option given #right GUI toolkit based the GUI command line option given
if cmd == 'gui': if cmd == 'gui':
pref_gui = config.get('gui','qt')
if options.gui=='gtk': if pref_gui == 'gtk':
try: try:
import lib.gui as gui import lib.gui as gui
except ImportError: except ImportError:
import electrum.gui as gui import electrum.gui as gui
elif options.gui=='qt': elif pref_gui == 'qt':
try: try:
import lib.gui_qt as gui import lib.gui_qt as gui
except ImportError: except ImportError:
import electrum.gui_qt as gui import electrum.gui_qt as gui
elif options.gui == 'lite': elif pref_gui == 'lite':
try: try:
import lib.gui_lite as gui import lib.gui_lite as gui
except ImportError: except ImportError:
import electrum.gui_lite as gui import electrum.gui_lite as gui
else: else:
sys.exit("Error: Unknown GUI: " + options.gui) sys.exit("Error: Unknown GUI: " + pref_gui )
gui = gui.ElectrumGui(wallet) gui = gui.ElectrumGui(wallet, config)
interface = WalletSynchronizer(wallet, True, gui.server_list_changed, proxy) interface = WalletSynchronizer(wallet, config, True, gui.server_list_changed)
interface.start() interface.start()
try: try:
found = wallet.file_exists found = config.wallet_file_exists
if not found: if not found:
found = gui.restore_or_create() found = gui.restore_or_create()
except SystemExit, e: except SystemExit, e:
@ -180,17 +185,19 @@ if __name__ == '__main__':
if cmd not in known_commands: if cmd not in known_commands:
cmd = 'help' cmd = 'help'
if not wallet.file_exists and cmd not in ['help','create','restore']: if not config.wallet_file_exists and cmd not in ['help','create','restore']:
print "Error: Wallet file not found." print "Error: Wallet file not found."
print "Type 'electrum create' to create a new wallet, or provide a path to a wallet with the -w option" print "Type 'electrum create' to create a new wallet, or provide a path to a wallet with the -w option"
sys.exit(0) sys.exit(0)
if cmd in ['create', 'restore']: if cmd in ['create', 'restore']:
if wallet.file_exists: if config.wallet_file_exists:
sys.exit("Error: Remove the existing wallet first!") sys.exit("Error: Remove the existing wallet first!")
password = prompt_password("Password (hit return if you do not wish to encrypt your wallet):") password = prompt_password("Password (hit return if you do not wish to encrypt your wallet):")
w_host, w_port, w_protocol = wallet.server.split(':') server = config.get('server')
if not server: server = pick_random_server()
w_host, w_port, w_protocol = server.split(':')
host = raw_input("server (default:%s):"%w_host) host = raw_input("server (default:%s):"%w_host)
port = raw_input("port (default:%s):"%w_port) port = raw_input("port (default:%s):"%w_port)
protocol = raw_input("protocol [t=tcp;h=http;n=native] (default:%s):"%w_protocol) protocol = raw_input("protocol [t=tcp;h=http;n=native] (default:%s):"%w_protocol)
@ -199,7 +206,7 @@ if __name__ == '__main__':
if host: w_host = host if host: w_host = host
if port: w_port = port if port: w_port = port
if protocol: w_protocol = protocol if protocol: w_protocol = protocol
wallet.server = w_host + ':' + w_port + ':' +w_protocol wallet.config.set_key('server', w_host + ':' + w_port + ':' +w_protocol)
if fee: wallet.fee = float(fee) if fee: wallet.fee = float(fee)
if gap: wallet.gap_limit = int(gap) if gap: wallet.gap_limit = int(gap)
@ -216,7 +223,7 @@ if __name__ == '__main__':
wallet.seed = str(seed) wallet.seed = str(seed)
wallet.init_mpk( wallet.seed ) wallet.init_mpk( wallet.seed )
if not options.offline: if not options.offline:
WalletSynchronizer(wallet, proxy=proxy).start() WalletSynchronizer(wallet, config).start()
print "Recovering wallet..." print "Recovering wallet..."
wallet.up_to_date_event.clear() wallet.up_to_date_event.clear()
wallet.up_to_date = False wallet.up_to_date = False
@ -239,7 +246,7 @@ if __name__ == '__main__':
print "Please keep it in a safe place; if you lose it, you will not be able to restore your wallet." print "Please keep it in a safe place; if you lose it, you will not be able to restore your wallet."
print "Equivalently, your wallet seed can be stored and recovered with the following mnemonic code:" print "Equivalently, your wallet seed can be stored and recovered with the following mnemonic code:"
print "\""+' '.join(mnemonic.mn_encode(wallet.seed))+"\"" print "\""+' '.join(mnemonic.mn_encode(wallet.seed))+"\""
print "Wallet saved in '%s'"%wallet.path print "Wallet saved in '%s'"%wallet.config.path
if password: if password:
wallet.update_password(wallet.seed, None, password) wallet.update_password(wallet.seed, None, password)
@ -259,7 +266,7 @@ if __name__ == '__main__':
# open session # open session
if cmd not in offline_commands and not options.offline: if cmd not in offline_commands and not options.offline:
WalletSynchronizer(wallet, proxy=proxy).start() WalletSynchronizer(wallet, config).start()
wallet.update() wallet.update()
wallet.save() wallet.save()

3
lib/__init__.py

@ -1,4 +1,3 @@
from wallet import Wallet, format_satoshis, prompt_password from wallet import Wallet, format_satoshis, prompt_password
from interface import WalletSynchronizer, parse_proxy_options from interface import WalletSynchronizer, Interface, pick_random_server
from interface import TcpStratumInterface
from simple_config import SimpleConfig from simple_config import SimpleConfig

10
lib/gui.py

@ -558,12 +558,13 @@ class ElectrumWindow:
def show_message(self, msg): def show_message(self, msg):
show_message(msg, self.window) show_message(msg, self.window)
def __init__(self, wallet): def __init__(self, wallet, config):
self.config = config
self.wallet = wallet self.wallet = wallet
self.funds_error = False # True if not enough funds self.funds_error = False # True if not enough funds
self.window = MyWindow(gtk.WINDOW_TOPLEVEL) self.window = MyWindow(gtk.WINDOW_TOPLEVEL)
title = 'Electrum ' + self.wallet.electrum_version + ' - ' + self.wallet.path title = 'Electrum ' + self.wallet.electrum_version + ' - ' + self.config.path
if not self.wallet.seed: title += ' [seedless]' if not self.wallet.seed: title += ' [seedless]'
self.window.set_title(title) self.window.set_title(title)
self.window.connect("destroy", gtk.main_quit) self.window.connect("destroy", gtk.main_quit)
@ -1298,11 +1299,12 @@ class ElectrumWindow:
class ElectrumGui(): class ElectrumGui():
def __init__(self, wallet): def __init__(self, wallet, config):
self.wallet = wallet self.wallet = wallet
self.config = config
def main(self, url=None): def main(self, url=None):
ew = ElectrumWindow(self.wallet) ew = ElectrumWindow(self.wallet, self.config)
if url: ew.set_url(url) if url: ew.set_url(url)
gtk.main() gtk.main()

46
lib/gui_lite.py

@ -13,17 +13,13 @@ except ImportError:
qtVersion = qVersion() qtVersion = qVersion()
if not(int(qtVersion[0]) >= 4 and int(qtVersion[2]) >= 7): if not(int(qtVersion[0]) >= 4 and int(qtVersion[2]) >= 7):
app = QApplication(sys.argv) app = QApplication(sys.argv)
QMessageBox.warning(None,"Could not start Lite GUI.", "Electrum was unable to load the 'Lite GUI' because it needs Qt version >= 4.7.\nElectrum was set to use the 'Qt' GUI") QMessageBox.warning(None,"Could not start Lite GUI.", "Electrum was unable to load the 'Lite GUI' because it needs Qt version >= 4.7.\nPlease use the 'Qt' GUI")
from simple_config import SimpleConfig
cfg = SimpleConfig()
cfg.set_key("gui", "qt",True)
sys.exit(0) sys.exit(0)
from decimal import Decimal as D from decimal import Decimal as D
from interface import DEFAULT_SERVERS from interface import DEFAULT_SERVERS
from simple_config import SimpleConfig
from util import get_resource_path as rsrc from util import get_resource_path as rsrc
from i18n import _ from i18n import _
import decimal import decimal
@ -61,10 +57,11 @@ def resize_line_edit_width(line_edit, text_input):
class ElectrumGui(QObject): class ElectrumGui(QObject):
def __init__(self, wallet): def __init__(self, wallet, config):
super(QObject, self).__init__() super(QObject, self).__init__()
self.wallet = wallet self.wallet = wallet
self.config = config
self.app = QApplication(sys.argv) self.app = QApplication(sys.argv)
def main(self, url): def main(self, url):
@ -76,7 +73,7 @@ class ElectrumGui(QObject):
old_path = QDir.currentPath() old_path = QDir.currentPath()
actuator.load_theme() actuator.load_theme()
self.mini = MiniWindow(actuator, self.expand) self.mini = MiniWindow(actuator, self.expand, self.config)
driver = MiniDriver(self.wallet, self.mini) driver = MiniDriver(self.wallet, self.mini)
# Reset path back to original value now that loading the GUI # Reset path back to original value now that loading the GUI
@ -88,12 +85,10 @@ class ElectrumGui(QObject):
timer = Timer() timer = Timer()
timer.start() timer.start()
self.expert = gui_qt.ElectrumWindow(self.wallet) self.expert = gui_qt.ElectrumWindow(self.wallet, self.config)
self.expert.app = self.app self.expert.app = self.app
self.expert.connect_slots(timer) self.expert.connect_slots(timer)
self.expert.update_wallet() self.expert.update_wallet()
self.app.exec_() self.app.exec_()
def server_list_changed(self): def server_list_changed(self):
@ -124,10 +119,11 @@ class ElectrumGui(QObject):
class MiniWindow(QDialog): class MiniWindow(QDialog):
def __init__(self, actuator, expand_callback): def __init__(self, actuator, expand_callback, config):
super(MiniWindow, self).__init__() super(MiniWindow, self).__init__()
self.actuator = actuator self.actuator = actuator
self.config = config
self.btc_balance = None self.btc_balance = None
self.quote_currencies = ["EUR", "USD", "GBP"] self.quote_currencies = ["EUR", "USD", "GBP"]
@ -259,11 +255,12 @@ class MiniWindow(QDialog):
close_shortcut = QShortcut(QKeySequence("Ctrl+W"), self) close_shortcut = QShortcut(QKeySequence("Ctrl+W"), self)
close_shortcut.activated.connect(self.close) close_shortcut.activated.connect(self.close)
self.cfg = SimpleConfig() g = self.config.get("winpos-lite",[4, 25, 351, 149])
g = self.cfg.config["winpos-lite"]
self.setGeometry(g[0], g[1], g[2], g[3]) self.setGeometry(g[0], g[1], g[2], g[3])
show_history.setChecked(self.cfg.config["history"])
self.show_history(self.cfg.config["history"]) show_hist = self.config.get("gui_show_history",False)
show_history.setChecked(show_hist)
self.show_history(show_hist)
self.setWindowIcon(QIcon(":electrum.png")) self.setWindowIcon(QIcon(":electrum.png"))
self.setWindowTitle("Electrum") self.setWindowTitle("Electrum")
@ -282,9 +279,8 @@ class MiniWindow(QDialog):
def closeEvent(self, event): def closeEvent(self, event):
g = self.geometry() g = self.geometry()
self.cfg.set_key("winpos-lite", [g.left(),g.top(),g.width(),g.height()]) self.config.set_key("winpos-lite", [g.left(),g.top(),g.width(),g.height()],True)
self.cfg.set_key("history", self.history_list.isVisible()) self.config.set_key("history", self.history_list.isVisible(),True)
self.cfg.save_config()
super(MiniWindow, self).closeEvent(event) super(MiniWindow, self).closeEvent(event)
qApp.quit() qApp.quit()
@ -563,7 +559,7 @@ class MiniActuator:
def __init__(self, wallet): def __init__(self, wallet):
"""Retrieve the gui theme used in previous session.""" """Retrieve the gui theme used in previous session."""
self.wallet = wallet self.wallet = wallet
self.theme_name = self.wallet.theme self.theme_name = self.wallet.config.get('litegui_theme','Cleanlook')
self.themes = util.load_theme_paths() self.themes = util.load_theme_paths()
def load_theme(self): def load_theme(self):
@ -587,13 +583,14 @@ class MiniActuator:
def change_theme(self, theme_name): def change_theme(self, theme_name):
"""Change theme.""" """Change theme."""
self.wallet.theme = self.theme_name = theme_name self.theme_name = theme_name
self.wallet.config.set_key('litegui_theme',theme_name)
self.load_theme() self.load_theme()
def set_configured_currency(self, set_quote_currency): def set_configured_currency(self, set_quote_currency):
"""Set the inital fiat currency conversion country (USD/EUR/GBP) in """Set the inital fiat currency conversion country (USD/EUR/GBP) in
the GUI to what it was set to in the wallet.""" the GUI to what it was set to in the wallet."""
currency = self.wallet.conversion_currency currency = self.wallet.config.get('conversion_currency')
# currency can be none when Electrum is used for the first # currency can be none when Electrum is used for the first
# time and no setting has been created yet. # time and no setting has been created yet.
if currency is not None: if currency is not None:
@ -601,7 +598,7 @@ class MiniActuator:
def set_config_currency(self, conversion_currency): def set_config_currency(self, conversion_currency):
"""Change the wallet fiat currency country.""" """Change the wallet fiat currency country."""
self.wallet.conversion_currency = conversion_currency self.wallet.config.set_key('conversion_currency',conversion_currency,True)
def set_servers_gui_stuff(self, servers_menu, servers_group): def set_servers_gui_stuff(self, servers_menu, servers_group):
self.servers_menu = servers_menu self.servers_menu = servers_menu
@ -620,7 +617,7 @@ class MiniActuator:
print "Servers loaded." print "Servers loaded."
self.servers_list = interface.servers self.servers_list = interface.servers
server_names = [details[0] for details in self.servers_list] server_names = [details[0] for details in self.servers_list]
current_server = self.wallet.server.split(":")[0] current_server = interface.server.split(":")[0]
for server_name in server_names: for server_name in server_names:
server_action = self.servers_menu.addAction(server_name) server_action = self.servers_menu.addAction(server_name)
server_action.setCheckable(True) server_action.setCheckable(True)
@ -661,8 +658,7 @@ class MiniActuator:
server_line = "%s:%s:%s" % (server_name, port, protocol) server_line = "%s:%s:%s" % (server_name, port, protocol)
# Should this have exception handling? # Should this have exception handling?
self.cfg = SimpleConfig() self.wallet.set_server(server_line, self.config.get(["proxy"]))
self.wallet.set_server(server_line, self.cfg.config["proxy"])
def copy_address(self, receive_popup): def copy_address(self, receive_popup):
"""Copy the wallet addresses into the client.""" """Copy the wallet addresses into the client."""

81
lib/gui_qt.py

@ -37,9 +37,7 @@ except:
sys.exit("Error: Could not import icons_rc.py, please generate it with: 'pyrcc4 icons.qrc -o lib/icons_rc.py'") sys.exit("Error: Could not import icons_rc.py, please generate it with: 'pyrcc4 icons.qrc -o lib/icons_rc.py'")
from wallet import format_satoshis from wallet import format_satoshis
from simple_config import SimpleConfig
import bmp, mnemonic, pyqrnative, qrscanner import bmp, mnemonic, pyqrnative, qrscanner
from simple_config import SimpleConfig
from decimal import Decimal from decimal import Decimal
@ -185,11 +183,14 @@ def ok_cancel_buttons(dialog):
class ElectrumWindow(QMainWindow): class ElectrumWindow(QMainWindow):
def __init__(self, wallet): def __init__(self, wallet, config):
QMainWindow.__init__(self) QMainWindow.__init__(self)
self.wallet = wallet self.wallet = wallet
self.config = config
self.wallet.register_callback(self.update_callback) self.wallet.register_callback(self.update_callback)
self.detailed_view = config.get('qt_detailed_view', False)
self.funds_error = False self.funds_error = False
self.completions = QStringListModel() self.completions = QStringListModel()
@ -204,10 +205,10 @@ class ElectrumWindow(QMainWindow):
tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.setCentralWidget(tabs) self.setCentralWidget(tabs)
self.create_status_bar() self.create_status_bar()
cfg = SimpleConfig()
g = cfg.config["winpos-qt"] g = self.config.get("winpos-qt",[100, 100, 840, 400])
self.setGeometry(g[0], g[1], g[2], g[3]) self.setGeometry(g[0], g[1], g[2], g[3])
title = 'Electrum ' + self.wallet.electrum_version + ' - ' + self.wallet.path title = 'Electrum ' + self.wallet.electrum_version + ' - ' + self.config.path
if not self.wallet.seed: title += ' [seedless]' if not self.wallet.seed: title += ' [seedless]'
self.setWindowTitle( title ) self.setWindowTitle( title )
@ -696,10 +697,12 @@ class ElectrumWindow(QMainWindow):
return w return w
def details_button_text(self): def details_button_text(self):
return _('Hide details') if self.wallet.gui_detailed_view else _('Show details') return _('Hide details') if self.detailed_view else _('Show details')
def toggle_detailed_view(self): def toggle_detailed_view(self):
self.wallet.gui_detailed_view = not self.wallet.gui_detailed_view self.detailed_view = not self.detailed_view
self.config.set_key('qt_detailed_view', self.detailed_view, True)
self.details_button.setText(self.details_button_text()) self.details_button.setText(self.details_button_text())
self.wallet.save() self.wallet.save()
self.update_receive_tab() self.update_receive_tab()
@ -731,11 +734,11 @@ class ElectrumWindow(QMainWindow):
menu.addAction(_("Copy to Clipboard"), lambda: self.app.clipboard().setText(addr)) menu.addAction(_("Copy to Clipboard"), lambda: self.app.clipboard().setText(addr))
menu.addAction(_("View QR code"),lambda: self.show_address_qrcode(addr)) menu.addAction(_("View QR code"),lambda: self.show_address_qrcode(addr))
menu.addAction(_("Edit label"), lambda: self.edit_label(True)) menu.addAction(_("Edit label"), lambda: self.edit_label(True))
if self.wallet.gui_detailed_view:
t = _("Unfreeze") if addr in self.wallet.frozen_addresses else _("Freeze") t = _("Unfreeze") if addr in self.wallet.frozen_addresses else _("Freeze")
menu.addAction(t, lambda: self.toggle_freeze(addr)) menu.addAction(t, lambda: self.toggle_freeze(addr))
t = _("Unprioritize") if addr in self.wallet.prioritized_addresses else _("Prioritize") t = _("Unprioritize") if addr in self.wallet.prioritized_addresses else _("Prioritize")
menu.addAction(t, lambda: self.toggle_priority(addr)) menu.addAction(t, lambda: self.toggle_priority(addr))
menu.exec_(self.receive_list.viewport().mapToGlobal(position)) menu.exec_(self.receive_list.viewport().mapToGlobal(position))
@ -790,9 +793,9 @@ class ElectrumWindow(QMainWindow):
def update_receive_tab(self): def update_receive_tab(self):
l = self.receive_list l = self.receive_list
l.clear() l.clear()
l.setColumnHidden(0,not self.wallet.gui_detailed_view) l.setColumnHidden(0,not self.detailed_view)
l.setColumnHidden(3,not self.wallet.gui_detailed_view) l.setColumnHidden(3,not self.detailed_view)
l.setColumnHidden(4,not self.wallet.gui_detailed_view) l.setColumnHidden(4,not self.detailed_view)
l.setColumnWidth(0, 50) l.setColumnWidth(0, 50)
l.setColumnWidth(1, 310) l.setColumnWidth(1, 310)
l.setColumnWidth(2, 250) l.setColumnWidth(2, 250)
@ -803,7 +806,7 @@ class ElectrumWindow(QMainWindow):
is_red = False is_red = False
for address in self.wallet.all_addresses(): for address in self.wallet.all_addresses():
if self.wallet.is_change(address) and not self.wallet.gui_detailed_view: if self.wallet.is_change(address) and not self.detailed_view:
continue continue
label = self.wallet.labels.get(address,'') label = self.wallet.labels.get(address,'')
@ -855,7 +858,7 @@ class ElectrumWindow(QMainWindow):
l = self.contacts_list l = self.contacts_list
l.clear() l.clear()
l.setColumnHidden(2, not self.wallet.gui_detailed_view) l.setColumnHidden(2, not self.detailed_view)
l.setColumnWidth(0, 350) l.setColumnWidth(0, 350)
l.setColumnWidth(1, 330) l.setColumnWidth(1, 330)
l.setColumnWidth(2, 100) l.setColumnWidth(2, 100)
@ -1247,9 +1250,8 @@ class ElectrumWindow(QMainWindow):
gap_e.textChanged.connect(lambda: numbify(nz_e,True)) gap_e.textChanged.connect(lambda: numbify(nz_e,True))
gui = QComboBox() gui = QComboBox()
gui.addItems(['Lite', 'Qt']) gui.addItems(['Lite', 'Qt', 'Gtk'])
cfg = SimpleConfig() gui.setCurrentIndex(gui.findText(self.config.get("gui","lite").capitalize()))
gui.setCurrentIndex(gui.findText(cfg.config["gui"].capitalize()))
grid.addWidget(QLabel(_('Default GUI') + ':'), 7, 0) grid.addWidget(QLabel(_('Default GUI') + ':'), 7, 0)
grid.addWidget(gui, 7, 1) grid.addWidget(gui, 7, 1)
grid.addWidget(HelpButton(_('Select which GUI mode to use at start up. ')), 7, 2) grid.addWidget(HelpButton(_('Select which GUI mode to use at start up. ')), 7, 2)
@ -1298,9 +1300,7 @@ class ElectrumWindow(QMainWindow):
else: else:
QMessageBox.warning(self, _('Error'), _('Invalid value'), _('OK')) QMessageBox.warning(self, _('Error'), _('Invalid value'), _('OK'))
cfg = SimpleConfig() self.config.set_key("gui", str(gui.currentText()).lower(), True)
cfg.set_key("gui", str(gui.currentText()).lower())
cfg.save_config()
@ -1312,7 +1312,7 @@ class ElectrumWindow(QMainWindow):
status = _("Connected to")+" %s:%d\n%d blocks"%(interface.host, interface.port, wallet.blocks) status = _("Connected to")+" %s:%d\n%d blocks"%(interface.host, interface.port, wallet.blocks)
else: else:
status = _("Not connected") status = _("Not connected")
server = wallet.server server = interface.server
else: else:
import random import random
status = _("Please choose a server.") status = _("Please choose a server.")
@ -1458,37 +1458,28 @@ class ElectrumWindow(QMainWindow):
if not d.exec_(): return if not d.exec_(): return
server = unicode( host_line.text() ) server = unicode( host_line.text() )
try: if proxy_mode.currentText() != 'NONE':
if proxy_mode.currentText() != 'NONE': proxy = { u'mode':unicode(proxy_mode.currentText()).lower(), u'host':unicode(proxy_host.text()), u'port':unicode(proxy_port.text()) }
proxy = { u'mode':unicode(proxy_mode.currentText()).lower(), u'host':unicode(proxy_host.text()), u'port':unicode(proxy_port.text()) } else:
else: proxy = None
proxy = None
cfg = SimpleConfig() wallet.config.set_key("proxy", proxy, True)
cfg.set_key("proxy", proxy, True) wallet.config.set_key("server", server, True)
wallet.set_server(server, proxy) interface.set_server(server, proxy)
except Exception as err:
QMessageBox.information(None, _('Error'), str(err), _('OK'))
if parent == None:
sys.exit(1)
else:
return
return True return True
def closeEvent(self, event): def closeEvent(self, event):
cfg = SimpleConfig()
g = self.geometry() g = self.geometry()
cfg.set_key("winpos-qt", [g.left(),g.top(),g.width(),g.height()]) self.config.set_key("winpos-qt", [g.left(),g.top(),g.width(),g.height()], True)
cfg.save_config()
event.accept() event.accept()
class ElectrumGui: class ElectrumGui:
def __init__(self, wallet, app=None): def __init__(self, wallet, config, app=None):
self.wallet = wallet self.wallet = wallet
self.config = config
if app is None: if app is None:
self.app = QApplication(sys.argv) self.app = QApplication(sys.argv)
@ -1563,7 +1554,7 @@ class ElectrumGui:
def main(self,url): def main(self,url):
s = Timer() s = Timer()
s.start() s.start()
w = ElectrumWindow(self.wallet) w = ElectrumWindow(self.wallet, self.config)
if url: w.set_url(url) if url: w.set_url(url)
w.app = self.app w.app = self.app
w.connect_slots(s) w.connect_slots(s)

110
lib/interface.py

@ -22,7 +22,7 @@ import threading, traceback, sys, time, json, Queue
from version import ELECTRUM_VERSION from version import ELECTRUM_VERSION
from util import print_error from util import print_error
from simple_config import SimpleConfig
DEFAULT_TIMEOUT = 5 DEFAULT_TIMEOUT = 5
DEFAULT_SERVERS = [ 'electrum.novit.ro:50001:t', DEFAULT_SERVERS = [ 'electrum.novit.ro:50001:t',
@ -30,23 +30,10 @@ DEFAULT_SERVERS = [ 'electrum.novit.ro:50001:t',
proxy_modes = ['socks4', 'socks5', 'http'] proxy_modes = ['socks4', 'socks5', 'http']
def replace_keys(obj, old_key, new_key): def pick_random_server():
if isinstance(obj, dict): print "using random server"
if old_key in obj: return random.choice( DEFAULT_SERVERS )
obj[new_key] = obj[old_key]
del obj[old_key]
for elem in obj.itervalues():
replace_keys(elem, old_key, new_key)
elif isinstance(obj, list):
for elem in obj:
replace_keys(elem, old_key, new_key)
def old_to_new(d):
replace_keys(d, 'blk_hash', 'block_hash')
replace_keys(d, 'pos', 'index')
replace_keys(d, 'nTime', 'timestamp')
replace_keys(d, 'is_in', 'is_input')
replace_keys(d, 'raw_scriptPubKey', 'raw_output_script')
def parse_proxy_options(s): def parse_proxy_options(s):
if s.lower() == 'none': return None if s.lower() == 'none': return None
@ -65,7 +52,11 @@ def parse_proxy_options(s):
proxy["port"] = "8080" if proxy["mode"] == "http" else "1080" proxy["port"] = "8080" if proxy["mode"] == "http" else "1080"
return proxy return proxy
class Interface(threading.Thread):
class InterfaceAncestor(threading.Thread):
def __init__(self, host, port, proxy=None): def __init__(self, host, port, proxy=None):
threading.Thread.__init__(self) threading.Thread.__init__(self)
self.daemon = True self.daemon = True
@ -134,11 +125,11 @@ class Interface(threading.Thread):
class PollingInterface(Interface): class PollingInterface(InterfaceAncestor):
""" non-persistent connection. synchronous calls""" """ non-persistent connection. synchronous calls"""
def __init__(self, host, port, proxy=None): def __init__(self, host, port, proxy=None):
Interface.__init__(self, host, port, proxy) InterfaceAncestor.__init__(self, host, port, proxy)
self.session_id = None self.session_id = None
def get_history(self, address): def get_history(self, address):
@ -146,14 +137,6 @@ class PollingInterface(Interface):
def poll(self): def poll(self):
pass pass
#if is_new or wallet.remote_url:
# self.was_updated = True
# is_new = wallet.synchronize()
# wallet.update_tx_history()
# wallet.save()
# return is_new
#else:
# return False
def run(self): def run(self):
self.is_connected = True self.is_connected = True
@ -249,11 +232,11 @@ class HttpStratumInterface(PollingInterface):
class TcpStratumInterface(Interface): class TcpStratumInterface(InterfaceAncestor):
"""json-rpc over persistent TCP connection, asynchronous""" """json-rpc over persistent TCP connection, asynchronous"""
def __init__(self, host, port, proxy=None): def __init__(self, host, port, proxy=None):
Interface.__init__(self, host, port, proxy) InterfaceAncestor.__init__(self, host, port, proxy)
def init_socket(self): def init_socket(self):
global proxy_modes global proxy_modes
@ -328,38 +311,63 @@ class TcpStratumInterface(Interface):
class Interface(TcpStratumInterface, HttpStratumInterface):
def __init__(self, config):
class WalletSynchronizer(threading.Thread):
def __init__(self, wallet, loop=False, servers_loaded_callback=None, proxy=None):
threading.Thread.__init__(self)
self.daemon = True
self.wallet = wallet
self.loop = loop
self.proxy = proxy
self.init_interface()
self.servers_loaded_callback = servers_loaded_callback
def init_interface(self):
try: try:
host, port, protocol = self.wallet.server.split(':') s = config.get('server')
host, port, protocol = s.split(':')
port = int(port) port = int(port)
except: except:
self.wallet.pick_random_server() s = pick_random_server()
host, port, protocol = self.wallet.server.split(':') host, port, protocol = s.split(':')
port = int(port) port = int(port)
proxy = config.get('proxy')
self.server = host + ':%d:%s'%(port, protocol)
#print protocol, host, port #print protocol, host, port
if protocol == 't': if protocol == 't':
InterfaceClass = TcpStratumInterface TcpStratumInterface.__init__(self, host, port, proxy)
elif protocol == 'h': elif protocol == 'h':
InterfaceClass = HttpStratumInterface HttpStratumInterface.__init__(self, host, port, proxy)
else: else:
print_error("Error: Unknown protocol") print_error("Error: Unknown protocol")
InterfaceClass = TcpStratumInterface TcpStratumInterface.__init__(self, host, port, proxy)
def set_server(self, server, proxy=None):
# raise an error if the format isnt correct
a,b,c = server.split(':')
b = int(b)
assert c in ['t', 'h']
# set the server
if server != self.server or proxy != self.proxy:
print "changing server:", server, proxy
self.server = server
self.proxy = proxy
self.is_connected = False # this exits the polling loop
self.poke()
class WalletSynchronizer(threading.Thread):
self.interface = InterfaceClass(host, port, self.proxy) def __init__(self, wallet, config, loop=False, servers_loaded_callback=None):
threading.Thread.__init__(self)
self.daemon = True
self.wallet = wallet
self.loop = loop
self.config = config
self.init_interface()
self.servers_loaded_callback = servers_loaded_callback
def init_interface(self):
self.interface = Interface(self.config)
self.wallet.interface = self.interface self.wallet.interface = self.interface
def handle_response(self, r): def handle_response(self, r):

226
lib/simple_config.py

@ -1,66 +1,176 @@
import json import json, ast
import os import os, ast
from util import user_dir from util import user_dir
from version import ELECTRUM_VERSION, SEED_VERSION
from interface import parse_proxy_options
# old stuff.. should be removed at some point
def replace_keys(obj, old_key, new_key):
if isinstance(obj, dict):
if old_key in obj:
obj[new_key] = obj[old_key]
del obj[old_key]
for elem in obj.itervalues():
replace_keys(elem, old_key, new_key)
elif isinstance(obj, list):
for elem in obj:
replace_keys(elem, old_key, new_key)
def old_to_new(d):
replace_keys(d, 'blk_hash', 'block_hash')
replace_keys(d, 'pos', 'index')
replace_keys(d, 'nTime', 'timestamp')
replace_keys(d, 'is_in', 'is_input')
replace_keys(d, 'raw_scriptPubKey', 'raw_output_script')
class SimpleConfig: class SimpleConfig:
default_options = { def __init__(self, options):
"gui": "lite",
"proxy": None, self.wallet_config = {}
"winpos-qt": [100, 100, 840, 400], self.read_wallet_config(options.wallet_path)
"winpos-lite": [4, 25, 351, 149],
"history": False self.common_config = {}
} self.read_common_config()
def __init__(self): self.options_config = {}
# Find electrum data folder
self.config_folder = user_dir() if options.server: self.options_config['server'] = options.server
# Read the file if options.proxy: self.options_config['proxy'] = parse_proxy_options(options.proxy)
if os.path.exists(self.config_file_path()): if options.gui: self.options_config['gui'] = options.gui
self.load_config()
def set_key(self, key, value, save = False):
# find where a setting comes from and save it there
if self.options_config.get(key):
return
elif self.wallet_config.get(key):
self.wallet_config[key] = value
if save: self.save_wallet_config()
elif self.common_config.get(key):
self.common_config[key] = value
if save: self.save_common_config()
else:
# add key to wallet config
self.wallet_config[key] = value
if save: self.save_wallet_config()
def get(self, key, default=None):
# 1. command-line options always override everything
if self.options_config.has_key(key):
# print "found", key, "in options"
out = self.options_config.get(key)
# 2. configuration file overrides wallet file
elif self.common_config.has_key(key):
out = self.common_config.get(key)
else: else:
self.config = self.default_options out = self.wallet_config.get(key)
# Make config directory if it does not yet exist.
if not os.path.exists(self.config_folder): if out is None and default is not None:
os.mkdir(self.config_folder) out = default
self.save_config() return out
# This is a friendly fallback to the old style default proxy options
if(self.config.get("proxy") is not None and self.config["proxy"]["mode"] == "none"): def is_modifiable(self, key):
self.set_key("proxy", None, True) if self.options_config.has_key(key) or self.common_config.has_key(key):
return False
def set_key(self, key, value, save = True):
self.config[key] = value
if save == True:
self.save_config()
def save_config(self):
if not os.path.exists(self.config_folder):
os.mkdir(self.config_folder)
f = open(self.config_file_path(), "w+")
f.write(json.dumps(self.config))
def load_config(self):
f = open(self.config_file_path(), "r")
file_contents = f.read()
if file_contents:
user_config = json.loads(file_contents)
for i in user_config:
self.config[i] = user_config[i]
else: else:
self.config = self.default_options return True
self.save_config()
def config_file_path(self): def read_common_config(self):
return "%s" % (self.config_folder + "/config.json") for name in [ os.path.join( user_dir(), 'electrum.conf') , '/etc/electrum.conf']:
if os.path.exists(name):
def __init__(self): from interface import parse_proxy_options
# Find electrum data folder try:
self.config_folder = user_dir() import ConfigParser
self.config = self.default_options except:
# Read the file print "cannot parse electrum.conf. please install ConfigParser"
if os.path.exists(self.config_file_path()): return
self.load_config()
self.save_config() p = ConfigParser.ConfigParser()
p.read(name)
try:
self.common_config['server'] = p.get('interface','server')
except:
pass
try:
self.common_config['proxy'] = parse_proxy_options(p.get('interface','proxy'))
except:
pass
break
def init_path(self, wallet_path):
"""Set the path of the wallet."""
if wallet_path is not None:
self.path = wallet_path
return
# Look for wallet file in the default data directory.
# Keeps backwards compatibility.
wallet_dir = user_dir()
# Make wallet directory if it does not yet exist.
if not os.path.exists(wallet_dir):
os.mkdir(wallet_dir)
self.path = os.path.join(wallet_dir, "electrum.dat")
def save_common_config(self):
s = repr(self.common_config)
# todo: decide what to do
print "not saving settings in common config:", s
def read_wallet_config(self, path):
"""Read the contents of the wallet file."""
self.wallet_file_exists = False
self.init_path(path)
try:
with open(self.path, "r") as f:
data = f.read()
except IOError:
return
try:
d = ast.literal_eval( data ) #parse raw data from reading wallet file
old_to_new(d)
except:
raise IOError("Cannot read wallet file.")
self.wallet_config = d
self.wallet_file_exists = True
def set_interface(self, interface):
pass
def set_gui(self, gui):
pass
def save(self):
self.save_wallet_config()
def save_wallet_config(self):
s = repr(self.wallet_config)
f = open(self.path,"w")
f.write( s )
f.close()
import stat
os.chmod(self.path,stat.S_IREAD | stat.S_IWRITE)

199
lib/wallet.py

@ -273,49 +273,40 @@ def format_satoshis(x, is_diff=False, num_zeros = 0):
from version import ELECTRUM_VERSION, SEED_VERSION from version import ELECTRUM_VERSION, SEED_VERSION
from interface import DEFAULT_SERVERS
class Wallet: class Wallet:
def __init__(self): def __init__(self, config={}):
self.config = config
self.electrum_version = ELECTRUM_VERSION self.electrum_version = ELECTRUM_VERSION
self.seed_version = SEED_VERSION
self.update_callbacks = [] self.update_callbacks = []
self.gap_limit = 5 # configuration
self.use_change = True
self.fee = 100000
self.num_zeros = 0
self.master_public_key = ''
self.conversion_currency = None
self.theme = "Cleanlook"
# saved fields # saved fields
self.use_encryption = False self.seed_version = config.get('seed_version', SEED_VERSION)
self.addresses = [] # receiving addresses visible for user self.gap_limit = config.get('gap_limit', 5)
self.change_addresses = [] # addresses used as change self.use_change = config.get('use_change',True)
self.seed = '' # encrypted self.fee = int(config.get('fee',100000))
self.history = {} self.num_zeros = int(config.get('num_zeros',0))
self.labels = {} # labels for addresses and transactions self.master_public_key = config.get('master_public_key','').decode('hex')
self.aliases = {} # aliases for addresses self.use_encryption = config.get('use_encryption', False)
self.authorities = {} # trusted addresses self.addresses = config.get('addresses', []) # receiving addresses visible for user
self.frozen_addresses = [] self.change_addresses = config.get('change_addresses', []) # addresses used as change
self.prioritized_addresses = [] self.seed = config.get('seed', '') # encrypted
self.gui_detailed_view = False self.history = config.get('history',{})
self.labels = config.get('labels',{}) # labels for addresses and transactions
self.receipts = {} # signed URIs self.aliases = config.get('aliases', {}) # aliases for addresses
self.receipt = None # next receipt self.authorities = config.get('authorities', {}) # trusted addresses
self.addressbook = [] # outgoing addresses, for payments self.frozen_addresses = config.get('frozen_addresses',[])
self.debug_server = False # write server communication debug info to stdout self.prioritized_addresses = config.get('prioritized_addresses',[])
self.receipts = config.get('receipts',{}) # signed URIs
self.addressbook = config.get('contacts', []) # outgoing addresses, for payments
self.imported_keys = config.get('imported_keys',{})
# not saved # not saved
self.receipt = None # next receipt
self.tx_history = {} self.tx_history = {}
self.imported_keys = {}
self.was_updated = True self.was_updated = True
self.blocks = -1 self.blocks = -1
self.banner = '' self.banner = ''
@ -329,7 +320,10 @@ class Wallet:
self.lock = threading.Lock() self.lock = threading.Lock()
self.tx_event = threading.Event() self.tx_event = threading.Event()
self.pick_random_server() self.update_tx_history()
if self.seed_version != SEED_VERSION:
raise ValueError("This wallet seed is deprecated. Please run upgrade.py for a diagnostic.")
def register_callback(self, update_callback): def register_callback(self, update_callback):
with self.lock: with self.lock:
@ -340,38 +334,9 @@ class Wallet:
callbacks = self.update_callbacks[:] callbacks = self.update_callbacks[:]
[update() for update in callbacks] [update() for update in callbacks]
def pick_random_server(self):
self.server = random.choice( DEFAULT_SERVERS ) # random choice when the wallet is created
def is_up_to_date(self): def is_up_to_date(self):
return self.interface.responses.empty() and not self.interface.unanswered_requests return self.interface.responses.empty() and not self.interface.unanswered_requests
def set_server(self, server, proxy=None):
# raise an error if the format isnt correct
a,b,c = server.split(':')
b = int(b)
assert c in ['t', 'h', 'n']
# set the server
if server != self.server or proxy != self.interface.proxy:
self.server = server
self.save()
self.interface.proxy = proxy
self.interface.is_connected = False # this exits the polling loop
self.interface.poke()
def set_path(self, wallet_path):
"""Set the path of the wallet."""
if wallet_path is not None:
self.path = wallet_path
return
# Look for wallet file in the default data directory.
# Keeps backwards compatibility.
wallet_dir = user_dir()
# Make wallet directory if it does not yet exist.
if not os.path.exists(wallet_dir):
os.mkdir(wallet_dir)
self.path = os.path.join(wallet_dir, "electrum.dat")
def import_key(self, keypair, password): def import_key(self, keypair, password):
address, key = keypair.split(':') address, key = keypair.split(':')
@ -390,6 +355,7 @@ class Wallet:
raise BaseException('Address does not match private key') raise BaseException('Address does not match private key')
self.imported_keys[address] = self.pw_encode( key, password ) self.imported_keys[address] = self.pw_encode( key, password )
def new_seed(self, password): def new_seed(self, password):
seed = "%032x"%ecdsa.util.randrange( pow(2,128) ) seed = "%032x"%ecdsa.util.randrange( pow(2,128) )
#self.init_mpk(seed) #self.init_mpk(seed)
@ -630,91 +596,6 @@ class Wallet:
self.update_tx_labels() self.update_tx_labels()
def save(self):
# TODO: Need special config storage class. Should not be mixed
# up with the wallet.
# Settings should maybe be stored in a flat ini file.
s = {
'seed_version': self.seed_version,
'use_encryption': self.use_encryption,
'use_change': self.use_change,
'master_public_key': self.master_public_key.encode('hex'),
'fee': self.fee,
'server': self.server,
'seed': self.seed,
'addresses': self.addresses,
'change_addresses': self.change_addresses,
'history': self.history,
'labels': self.labels,
'contacts': self.addressbook,
'imported_keys': self.imported_keys,
'aliases': self.aliases,
'authorities': self.authorities,
'receipts': self.receipts,
'num_zeros': self.num_zeros,
'frozen_addresses': self.frozen_addresses,
'prioritized_addresses': self.prioritized_addresses,
'gui_detailed_view': self.gui_detailed_view,
'gap_limit': self.gap_limit,
'debug_server': self.debug_server,
'conversion_currency': self.conversion_currency,
'theme': self.theme
}
f = open(self.path,"w")
f.write( repr(s) )
f.close()
import stat
os.chmod(self.path,stat.S_IREAD | stat.S_IWRITE)
def read(self):
"""Read the contents of the wallet file."""
import interface
self.file_exists = False
try:
with open(self.path, "r") as f:
data = f.read()
except IOError:
return
try:
d = ast.literal_eval( data ) #parse raw data from reading wallet file
interface.old_to_new(d)
self.seed_version = d.get('seed_version')
self.master_public_key = d.get('master_public_key').decode('hex')
self.use_encryption = d.get('use_encryption')
self.use_change = bool(d.get('use_change', True))
self.fee = int(d.get('fee'))
self.seed = d.get('seed')
self.server = d.get('server')
self.addresses = d.get('addresses')
self.change_addresses = d.get('change_addresses')
self.history = d.get('history')
self.labels = d.get('labels')
self.addressbook = d.get('contacts')
self.imported_keys = d.get('imported_keys', {})
self.aliases = d.get('aliases', {})
self.authorities = d.get('authorities', {})
self.receipts = d.get('receipts', {})
self.num_zeros = d.get('num_zeros', 0)
self.frozen_addresses = d.get('frozen_addresses', [])
self.prioritized_addresses = d.get('prioritized_addresses', [])
self.gui_detailed_view = d.get('gui_detailed_view', False)
self.gap_limit = d.get('gap_limit', 5)
self.debug_server = d.get('debug_server', False)
self.conversion_currency = d.get('conversion_currency', 'USD')
self.theme = d.get('theme', 'Cleanlook')
except:
raise IOError("Cannot read wallet file.")
self.update_tx_history()
if self.seed_version != SEED_VERSION:
raise ValueError("This wallet seed is deprecated. Please run upgrade.py for a diagnostic.")
self.file_exists = True
def get_address_flags(self, addr): def get_address_flags(self, addr):
flags = "C" if self.is_change(addr) else "I" if addr in self.imported_keys.keys() else "-" flags = "C" if self.is_change(addr) else "I" if addr in self.imported_keys.keys() else "-"
flags += "F" if addr in self.frozen_addresses else "P" if addr in self.prioritized_addresses else "-" flags += "F" if addr in self.frozen_addresses else "P" if addr in self.prioritized_addresses else "-"
@ -1134,3 +1015,29 @@ class Wallet:
return True return True
else: else:
return False return False
def save(self):
s = {
'seed_version': self.seed_version,
'use_encryption': self.use_encryption,
'use_change': self.use_change,
'master_public_key': self.master_public_key.encode('hex'),
'fee': self.fee,
'seed': self.seed,
'addresses': self.addresses,
'change_addresses': self.change_addresses,
'history': self.history,
'labels': self.labels,
'contacts': self.addressbook,
'imported_keys': self.imported_keys,
'aliases': self.aliases,
'authorities': self.authorities,
'receipts': self.receipts,
'num_zeros': self.num_zeros,
'frozen_addresses': self.frozen_addresses,
'prioritized_addresses': self.prioritized_addresses,
'gap_limit': self.gap_limit,
}
for k, v in s.items():
self.config.set_key(k,v)
self.config.save()

4
scripts/blocks

@ -1,8 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
from electrum import TcpStratumInterface from electrum import Interface
i = TcpStratumInterface('electrum.novit.ro', 50001) i = Interface({'server':'electrum.novit.ro:50001:t'})
i.init_socket() i.init_socket()
i.start() i.start()
i.send([('blockchain.numblocks.subscribe',[])]) i.send([('blockchain.numblocks.subscribe',[])])

4
scripts/get_history

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
import sys import sys
from electrum import TcpStratumInterface from electrum import Interface
try: try:
addr = sys.argv[1] addr = sys.argv[1]
@ -9,7 +9,7 @@ except:
print "usage: get_history <bitcoin_address>" print "usage: get_history <bitcoin_address>"
sys.exit(1) sys.exit(1)
i = TcpStratumInterface('electrum.novit.ro', 50001) i = Interface({'server':'electrum.novit.ro:50001:t'})
i.init_socket() i.init_socket()
i.start() i.start()
i.send([('blockchain.address.get_history',[addr])]) i.send([('blockchain.address.get_history',[addr])])

4
scripts/merchant.py

@ -21,7 +21,7 @@ import time, thread, sys, socket, os
import urllib2,json import urllib2,json
import MySQLdb as mdb import MySQLdb as mdb
import Queue import Queue
from electrum import Wallet, TcpStratumInterface from electrum import Wallet, Interface
import ConfigParser import ConfigParser
config = ConfigParser.ConfigParser() config = ConfigParser.ConfigParser()
@ -157,7 +157,7 @@ if __name__ == '__main__':
print "using database", db_name print "using database", db_name
conn = mdb.connect(db_instance, db_user, db_password, db_name); conn = mdb.connect(db_instance, db_user, db_password, db_name);
i = TcpStratumInterface(electrum_server, 50001) i = Interface({'server':"%s:%d:t"%(electrum_server, 50001)})
i.init_socket() i.init_socket()
i.start() i.start()

4
scripts/peers

@ -1,8 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
from electrum import TcpStratumInterface from electrum import Interface
i = TcpStratumInterface('electrum.novit.ro', 50001) i = Interface({'server':'electrum.novit.ro:50001:t'})
i.init_socket() i.init_socket()
i.start() i.start()
i.send([('server.peers.subscribe',[])]) i.send([('server.peers.subscribe',[])])

4
scripts/watch_address

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
import sys import sys
from electrum import TcpStratumInterface from electrum import Interface
try: try:
addr = sys.argv[1] addr = sys.argv[1]
@ -9,7 +9,7 @@ except:
print "usage: watch_address <bitcoin_address>" print "usage: watch_address <bitcoin_address>"
sys.exit(1) sys.exit(1)
i = TcpStratumInterface('electrum.novit.ro', 50001) i = Interface({'server':'electrum.novit.ro:50001:t'})
i.init_socket() i.init_socket()
i.start() i.start()
i.send([('blockchain.address.subscribe',[addr])]) i.send([('blockchain.address.subscribe',[addr])])

Loading…
Cancel
Save