def _start_wizard_to_select_or_create_wallet( self, path) -> Optional[Abstract_Wallet]: wizard = InstallWizard(self.config, self.app, self.plugins) run_notification = False try: path, storage = wizard.select_storage(path, self.daemon.get_wallet) # storage is None if file does not exist if storage is None: wizard.path = path # needed by trustedcoin plugin wizard.run('new') storage = wizard.create_storage(path) run_notification = True else: wizard.run_upgrades(storage) except (UserCancelled, GoBack): return except WalletAlreadyOpenInMemory as e: return e.wallet finally: wizard.terminate() # return if wallet creation is not complete if storage is None or storage.get_action(): return wallet = Wallet(storage, config=self.config) if run_notification: self.add_email_notification(wallet) wallet.start_network(self.daemon.network) self.daemon.add_wallet(wallet) return wallet
def _start_wizard_to_select_or_create_wallet( self, path) -> Optional[Abstract_Wallet]: wizard = InstallWizard(self.config, self.app, self.plugins) try: path, storage = wizard.select_storage(path, self.daemon.get_wallet) # storage is None if file does not exist if storage is None: wizard.path = path # needed by trustedcoin plugin wizard.run('new') storage = wizard.create_storage(path) else: wizard.run_upgrades(storage) except (UserCancelled, GoBack): return except WalletAlreadyOpenInMemory as e: return e.wallet except (WalletFileException, BitcoinException) as e: self.logger.exception('') QMessageBox.warning(None, _('Error'), _('Cannot load wallet') + ' (2):\n' + str(e)) return finally: wizard.terminate() # return if wallet creation is not complete if storage is None or storage.get_action(): return wallet = Wallet(storage) wallet.start_network(self.daemon.network) self.daemon.add_wallet(wallet) return wallet
class ElectrumGui: def __init__(self, config, network): self.network = network self.config = config storage = WalletStorage(self.config.get_wallet_path()) if not storage.file_exists: raise BaseException("Wallet not found") self.wallet = Wallet(storage) self.cmd_runner = Commands(self.config, self.wallet, self.network) host = config.get('rpchost', 'localhost') port = config.get('rpcport', 7777) self.server = SimpleJSONRPCServer((host, port), requestHandler=RequestHandler) self.server.socket.settimeout(1) for cmdname in known_commands: self.server.register_function(getattr(self.cmd_runner, cmdname), cmdname) def main(self, url): self.wallet.start_threads(self.network) while True: try: self.server.handle_request() except socket.timeout: continue except: break self.wallet.stop_threads()
def __init__(self, config, daemon, plugins): self.config = config network = daemon.network storage = WalletStorage(config.get_wallet_path()) if not storage.file_exists: print "Wallet not found. try 'electrum create'" exit() self.done = 0 self.last_balance = "" set_verbosity(False) self.str_recipient = "" self.str_description = "" self.str_amount = "" self.str_fee = "" self.wallet = Wallet(storage) self.wallet.start_threads(network) self.contacts = StoreDict(self.config, 'contacts') network.register_callback(self.on_network, ['updated', 'banner']) self.commands = [_("[h] - displays this help text"), \ _("[i] - display transaction history"), \ _("[o] - enter payment order"), \ _("[p] - print stored payment order"), \ _("[s] - send stored payment order"), \ _("[r] - show own receipt addresses"), \ _("[c] - display contacts"), \ _("[b] - print server banner"), \ _("[q] - quit") ] self.num_commands = len(self.commands)
def init_storage_from_path(self, path): self.storage = WalletStorage(path) self.basename = self.storage.basename() if not self.storage.file_exists(): self.require_password = False self.message = _('Press Next to create') elif self.storage.is_encrypted(): if not self.storage.is_encrypted_with_user_pw(): raise Exception( "Kivy GUI does not support this type of encrypted wallet files." ) self.pw_check = self.storage.check_password if self.app.password and self.check_password(self.app.password): self.pw = self.app.password # must be set so that it is returned in callback self.require_password = False self.message = _('Press Next to open') else: self.require_password = True self.message = self.enter_pw_message else: # it is a bit wasteful load the wallet here and load it again in main_window, # but that is fine, because we are progressively enforcing storage encryption. db = WalletDB(self.storage.read(), manual_upgrades=False) wallet = Wallet(db, self.storage, config=self.app.electrum_config) self.require_password = wallet.has_password() self.pw_check = wallet.check_password self.message = self.enter_pw_message if self.require_password else _( 'Wallet not encrypted')
class ElectrumGui: def __init__(self, config, network, plugins): self.network = network self.config = config storage = WalletStorage(self.config.get_wallet_path()) if not storage.file_exists: raise BaseException("Wallet not found") self.wallet = Wallet(storage) self.cmd_runner = Commands(self.config, self.wallet, self.network) host = config.get('rpchost', 'localhost') port = config.get('rpcport', 7777) self.server = SimpleJSONRPCServer((host, port), requestHandler=RequestHandler) self.server.socket.settimeout(1) for cmdname in known_commands: self.server.register_function(getattr(self.cmd_runner, cmdname), cmdname) def main(self): self.wallet.start_threads(self.network) while True: try: self.server.handle_request() except socket.timeout: continue except: break self.wallet.stop_threads()
def _start_wizard_to_select_or_create_wallet(self, path) -> Optional[Abstract_Wallet]: wizard = InstallWizard(self.config, self.app, self.plugins) try: path, storage = wizard.select_storage(path, self.daemon.get_wallet) # storage is None if file does not exist if storage is None: wizard.path = path # needed by trustedcoin plugin wizard.run('new') storage = wizard.create_storage(path) else: wizard.run_upgrades(storage) except (UserCancelled, GoBack): return except WalletAlreadyOpenInMemory as e: return e.wallet except (WalletFileException, BitcoinException) as e: traceback.print_exc(file=sys.stderr) QMessageBox.warning(None, _('Error'), _('Cannot load wallet') + ' (2):\n' + str(e)) return finally: wizard.terminate() # return if wallet creation is not complete if storage is None or storage.get_action(): return wallet = Wallet(storage) wallet.start_network(self.daemon.network) self.daemon.add_wallet(wallet) return wallet
def _start_wizard_to_select_or_create_wallet(self, path) -> Optional[Abstract_Wallet]: wizard = InstallWizard(self.config, self.app, self.plugins, gui_object=self) try: path, storage = wizard.select_storage(path, self.daemon.get_wallet) # storage is None if file does not exist if storage is None: wizard.path = path # needed by trustedcoin plugin wizard.run('new') storage, db = wizard.create_storage(path) else: db = WalletDB(storage.read(), manual_upgrades=False) wizard.run_upgrades(storage, db) except (UserCancelled, GoBack): return except WalletAlreadyOpenInMemory as e: return e.wallet finally: wizard.terminate() # return if wallet creation is not complete if storage is None or db.get_action(): return wallet = Wallet(db, storage, config=self.config) wallet.start_network(self.daemon.network) self.daemon.add_wallet(wallet) return wallet
def __init__(self, config, daemon, plugins): self.config = config self.network = daemon.network storage = WalletStorage(config.get_wallet_path()) if not storage.file_exists(): print("Wallet not found. try 'electrum create'") exit() if storage.is_encrypted(): password = getpass.getpass('Password:'******'') self.encoding = locale.getpreferredencoding() self.stdscr = curses.initscr() curses.noecho() curses.cbreak() curses.start_color() curses.use_default_colors() curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE) curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_CYAN) curses.init_pair(3, curses.COLOR_BLACK, curses.COLOR_WHITE) self.stdscr.keypad(1) self.stdscr.border(0) self.maxy, self.maxx = self.stdscr.getmaxyx() self.set_cursor(0) self.w = curses.newwin(10, 50, 5, 5) console_stderr_handler.setLevel(logging.CRITICAL) self.tab = 0 self.pos = 0 self.popup_pos = 0 self.str_recipient = "" self.str_description = "" self.str_asset = "" self.str_amount = "" self.str_fee = "" self.history = None if self.network: self.network.register_callback( self.update, ['wallet_updated', 'network_updated']) self.tab_names = [ _("History"), _("Send"), _("Receive"), _("Addresses"), _("Contacts"), _("Banner"), _("Assets"), _("Send Assets") ] self.num_tabs = len(self.tab_names)
def __init__(self, *, config: 'SimpleConfig', daemon: 'Daemon', plugins: 'Plugins'): BaseElectrumGui.__init__(self, config=config, daemon=daemon, plugins=plugins) self.network = daemon.network storage = WalletStorage(config.get_wallet_path()) if not storage.file_exists(): print("Wallet not found. try 'electrum create'") exit() if storage.is_encrypted(): password = getpass.getpass('Password:'******'') self.encoding = locale.getpreferredencoding() self.stdscr = curses.initscr() curses.noecho() curses.cbreak() curses.start_color() curses.use_default_colors() curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE) curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_CYAN) curses.init_pair(3, curses.COLOR_BLACK, curses.COLOR_WHITE) self.stdscr.keypad(1) self.stdscr.border(0) self.maxy, self.maxx = self.stdscr.getmaxyx() self.set_cursor(0) self.w = curses.newwin(10, 50, 5, 5) self.tab = 0 self.pos = 0 self.popup_pos = 0 self.str_recipient = "" self.str_description = "" self.str_amount = "" self.str_fee = "" self.history = None self.txid = [] self.register_callbacks() self.tab_names = [ _("History"), _("Send"), _("Receive"), _("Addresses"), _("Contacts"), _("Banner") ] self.num_tabs = len(self.tab_names)
def create_wallet(self, text, password): if self.wallet_type == 'standard': self.wallet = Wallet.from_text(text, password, self.storage) self.run('create_addresses') elif self.wallet_type == 'multisig': self.storage.put('wallet_type', self.multisig_type) self.wallet = Multisig_Wallet(self.storage) self.wallet.add_cosigner('x1/', text, password) self.run('show_xpub_and_add_cosigners', (Wallet.is_xpub(text), password,))
def on_wizard_complete(self, wizard, storage): if storage: wallet = Wallet(storage) wallet.start_network(self.daemon.network) self.daemon.add_wallet(wallet) self.load_wallet(wallet) elif not self.wallet: # wizard did not return a wallet; and there is no wallet open atm # try to open last saved wallet (potentially start wizard again) self.load_wallet_by_name(self.electrum_config.get_wallet_path(), ask_if_wizard=True)
def make_address_electrum(mnemonic: str, second: str, num: int = 0, script: str = 'p2wpkh', path: str = 'wallet.db', remove: bool = True): if electrum is None: raise ImportError( 'Unable to import electrum. Follow README instructions.') if len(second) < MIN_LEN_PASSWORD: raise ValueError( f'Password too short {len(second)} < {MIN_LEN_PASSWORD}') script_types = ('p2pkh', 'p2wpkh', 'p2wpkh-p2sh') if script not in script_types: raise ValueError(f'Script {script} must be noe of {script_types}') if os.path.exists(path): os.unlink(path) language = 'english' seed = Mnemonic(language).to_seed(mnemonic).hex() derivation = None if script == 'p2wpkh': derivation = "m/84'/0'/0'" elif script == 'p2wpkh-p2sh': derivation = "m/49'/0'/0'" elif script == 'p2pkh': script = 'standard' derivation = "m/44'/0'/0'" ks = keystore.from_bip39_seed(mnemonic, second, derivation, xtype=script) db = WalletDB('', manual_upgrades=False) db.put('keystore', ks.dump()) db.put('wallet_type', 'standard') storage = WalletStorage(path) wallet = Wallet(db, storage, config=SimpleConfig()) if not storage.file_exists(): wallet.update_password(old_pw=None, new_pw=second, encrypt_storage=True) wallet.synchronize() wallet.save_db() addr = wallet.get_receiving_addresses()[num] wif = wallet.export_private_key(addr, password=second) if remove: os.unlink(path) return AddressResult(address=addr, wif=wif, num=num)
def __init__(self, name, config): """ Initializes new electrum wallet instance @param name: Name of the wallet @param config: Configuration dictionary e.g { 'server': 'localhost:7777:s', 'rpc_user': '******', 'rpc_pass_': 'pass', 'electrum_path': '/opt/var/data/electrum', 'seed': '....', 'fee': 10000, 'testnet': 1 } """ self._name = name self._config = config self._config['testnet'] = bool(self._config['testnet']) if self._config['testnet'] is True: constants.set_testnet() self._config['verbos'] = False self._electrum_config = SimpleConfig(self._config) self._wallet_path = os.path.join(self._electrum_config.path, 'wallets', self._name) self._storage = WalletStorage(path=self._wallet_path) if not self._storage.file_exists(): self._electrum_config.set_key('default_wallet_path', self._wallet_path) k = keystore.from_seed(self._config['seed'], self._config['passphrase'], False) k.update_password(None, self._config['password']) self._storage.put('keystore', k.dump()) self._storage.put('wallet_type', 'standard') self._storage.put('use_encryption', bool(self._config['password'])) self._storage.write() self._wallet = Wallet(self._storage) # self._server = daemon.get_server(self._electrum_config) self._network = Network(self._electrum_config) self._network.start() self._wallet.start_threads(self._network) self._wallet.synchronize() self._wallet.wait_until_synchronized() self._wallet.stop_threads() self._wallet.storage.write() else: self._network = None self._wallet = self._wallet = Wallet(self._storage) self._commands = Commands(config=self._electrum_config, wallet=self._wallet, network=self._network) self._init_commands()
def run_and_get_wallet(self): # Show network dialog if config does not exist if self.network: if self.config.get('auto_connect') is None: self.choose_server(self.network) path = self.storage.path if self.storage.requires_split(): self.hide() msg = _( "The wallet '%s' contains multiple accounts, which are no longer supported in Electrum 2.7.\n\n" "Do you want to split your wallet into multiple files?" % path) if not self.question(msg): return file_list = '\n'.join(self.storage.split_accounts()) msg = _('Your accounts have been moved to' ) + ':\n' + file_list + '\n\n' + _( 'Do you want to delete the old file') + ':\n' + path if self.question(msg): os.remove(path) self.show_warning(_('The file was removed')) return if self.storage.requires_upgrade(): self.hide() msg = _( "The format of your wallet '%s' must be upgraded for Electrum. This change will not be backward compatible" % path) if not self.question(msg): return self.storage.upgrade() self.show_warning(_('Your wallet was upgraded successfully')) self.wallet = Wallet(self.storage) self.terminate() return self.wallet action = self.storage.get_action() if action and action != 'new': self.hide() msg = _("The file '%s' contains an incompletely created wallet.\n" "Do you want to complete its creation now?") % path if not self.question(msg): if self.question(_("Do you want to delete '%s'?") % path): os.remove(path) self.show_warning(_('The file was removed')) return self.show() if action: # self.wallet is set in run self.run(action) return self.wallet
def __init__(self, config, network): self.network = network self.config = config storage = WalletStorage(self.config.get_wallet_path()) if not storage.file_exists: raise BaseException("Wallet not found") self.wallet = Wallet(storage) self.cmd_runner = Commands(self.config, self.wallet, self.network) host = config.get('rpchost', 'localhost') port = config.get('rpcport', 7777) self.server = SimpleJSONRPCServer((host, port), requestHandler=RequestHandler) self.server.socket.settimeout(1) for cmdname in known_commands: self.server.register_function(getattr(self.cmd_runner, cmdname), cmdname)
def __init__(self, config, network, daemon, plugins): self.network = network self.config = config storage = WalletStorage(config.get_wallet_path()) if not storage.file_exists: print "Wallet not found. try 'electrum create'" exit() self.done = 0 self.last_balance = "" set_verbosity(False) self.str_recipient = "" self.str_description = "" self.str_amount = "" self.str_fee = "" self.wallet = Wallet(storage) self.wallet.start_threads(network) self.contacts = StoreDict(self.config, "contacts") network.register_callback(self.on_network, ["updated", "banner"]) self.commands = [ _("[h] - displays this help text"), _("[i] - display transaction history"), _("[o] - enter payment order"), _("[p] - print stored payment order"), _("[s] - send stored payment order"), _("[r] - show own receipt addresses"), _("[c] - display contacts"), _("[b] - print server banner"), _("[q] - quit"), ] self.num_commands = len(self.commands)
def get_action(self): if self.storage.file_exists: self.wallet = Wallet(self.storage) action = self.wallet.get_action() else: action = 'new' return action
def run_and_get_wallet(self): path = self.storage.path if self.storage.requires_split(): self.hide() msg = _("The wallet '{}' contains multiple accounts, which are no longer supported since Electrum 2.7.\n\n" "Do you want to split your wallet into multiple files?").format(path) if not self.question(msg): return file_list = '\n'.join(self.storage.split_accounts()) msg = _('Your accounts have been moved to') + ':\n' + file_list + '\n\n'+ _('Do you want to delete the old file') + ':\n' + path if self.question(msg): os.remove(path) self.show_warning(_('The file was removed')) return action = self.storage.get_action() if action and action not in ('new', 'upgrade_storage'): self.hide() msg = _("The file '{}' contains an incompletely created wallet.\n" "Do you want to complete its creation now?").format(path) if not self.question(msg): if self.question(_("Do you want to delete '{}'?").format(path)): os.remove(path) self.show_warning(_('The file was removed')) return self.show() if action: # self.wallet is set in run self.run(action) return self.wallet self.wallet = Wallet(self.storage) return self.wallet
def load_wallet(xpub): if xpub in wallets: return wallets[xpub] config = SimpleConfig() command_runner = Commands(config, wallet=None, network=network) # get wallet on disk wallet_dir = os.path.dirname(config.get_wallet_path()) wallet_path = os.path.join(wallet_dir, xpub) if not os.path.exists(wallet_path): config.set_key('wallet_path', wallet_path) command_runner.restore(xpub) storage = WalletStorage(wallet_path) wallet = Wallet(storage) wallet.start_network(network) command_runner.wallet = wallet wallets[xpub] = command_runner return command_runner
def run_offline_command(config, config_options, plugins): print(config) print(config_options) print(plugins) cmdname = config.get('cmd') cmd = known_commands[cmdname] print(cmd.__dict__) password = config_options.get('password') if cmd.requires_wallet: storage = WalletStorage(config.get_wallet_path()) if storage.is_encrypted(): if storage.is_encrypted_with_hw_device(): password = get_password_for_hw_device_encrypted_storage( plugins) config_options['password'] = password storage.decrypt(password) wallet = Wallet(storage) else: wallet = None # check password if cmd.requires_password and wallet.has_password(): try: wallet.check_password(password) except InvalidPassword: print_msg("Error: This password does not decode this wallet.") sys.exit(1) if cmd.requires_network: print_msg("Warning: running command offline") # arguments passed to function args = [config.get(x) for x in cmd.params] # decode json arguments if cmdname not in ('setconfig', ): args = list(map(json_decode, args)) # options kwargs = {} for x in cmd.options: kwargs[x] = (config_options.get(x) if x in ['password', 'new_password'] else config.get(x)) cmd_runner = Commands(config, wallet, None) func = getattr(cmd_runner, cmd.name) result = func(*args, **kwargs) # save wallet if wallet: wallet.storage.write() return result
def confirm_seed(self, seed): assert Wallet.is_seed(seed) msg = _( 'Please retype your seed phrase, to confirm that you properly saved it' ) self.restore_seed_dialog(run_prev=self.create_seed, run_next=self.enter_pin, test=lambda x: x == seed, message=msg)
def start(self): self.logger.info("start") user_config = { "auto_connect": False, "oneserver": True, "server": "localhost:" + str(self.electrumx.tcp_port) + ":t", "request_initial_sync": False, "lightning_listen": "127.0.0.1:" + str(self.port), } config = simple_config.SimpleConfig( user_config, read_user_dir_function=lambda: self.directory) constants.set_regtest() self.actual = Daemon(config) assert self.actual.network.asyncio_loop.is_running() wallet_path = self.actual.cmd_runner.create(segwit=True)['path'] storage = WalletStorage(wallet_path) wallet = Wallet(storage) wallet.start_network(self.actual.network) self.actual.add_wallet(wallet)
def create_wallet(self, text, password): if self.wallet_type == 'standard': self.wallet = Wallet.from_text(text, password, self.storage) self.run('create_addresses') elif self.wallet_type == 'multisig': self.storage.put('wallet_type', self.multisig_type) self.wallet = Multisig_Wallet(self.storage) self.wallet.add_seed(text, password) self.wallet.create_master_keys(password) self.run_wallet()
def create_wallet(self, text, password): if self.wallet_type == 'standard': self.wallet = Wallet.from_text(text, password, self.storage) self.run('create_addresses') elif self.wallet_type == 'multisig': self.storage.put('wallet_type', self.multisig_type) self.wallet = Multisig_Wallet(self.storage) self.wallet.add_cosigner('x1/', text, password) self.stack = [] self.run('show_xpub_and_add_cosigners', (password,))
def load_wallet(self, path, password): # wizard will be launched if we return if path in self.wallets: wallet = self.wallets[path] return wallet storage = WalletStorage(path, manual_upgrades=True) if not storage.file_exists(): return if storage.is_encrypted(): if not password: return storage.decrypt(password) if storage.requires_split(): return if storage.get_action(): return wallet = Wallet(storage) wallet.start_threads(self.network) self.wallets[path] = wallet return wallet
def __init__(self, config, network): self.network = network self.config = config storage = WalletStorage(config) if not storage.file_exists: print "Wallet not found. try 'electrum create'" exit() self.done = 0 self.last_balance = "" set_verbosity(False) self.str_recipient = "" self.str_description = "" self.str_amount = "" self.str_fee = "" self.wallet = Wallet(storage) self.wallet.start_threads(network) self.wallet.network.register_callback('updated', self.updated) self.wallet.network.register_callback('connected', self.connected) self.wallet.network.register_callback('disconnected', self.disconnected) self.wallet.network.register_callback('disconnecting', self.disconnecting) self.wallet.network.register_callback('peers', self.peers) self.wallet.network.register_callback('banner', self.print_banner) self.commands = [_("[h] - displays this help text"), \ _("[i] - display transaction history"), \ _("[o] - enter payment order"), \ _("[p] - print stored payment order"), \ _("[s] - send stored payment order"), \ _("[r] - show own receipt addresses"), \ _("[c] - display contacts"), \ _("[b] - print server banner"), \ _("[q] - quit") ] self.num_commands = len(self.commands)
def __init__(self, config, daemon, plugins): self.config = config self.network = daemon.network storage = WalletStorage(config.get_wallet_path()) if not storage.file_exists(): print("Wallet not found. try 'electrum create'") exit() if storage.is_encrypted(): password = getpass.getpass('Password:'******'') self.encoding = locale.getpreferredencoding() self.stdscr = curses.initscr() curses.noecho() curses.cbreak() curses.start_color() curses.use_default_colors() curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE) curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_CYAN) curses.init_pair(3, curses.COLOR_BLACK, curses.COLOR_WHITE) self.stdscr.keypad(1) self.stdscr.border(0) self.maxy, self.maxx = self.stdscr.getmaxyx() self.set_cursor(0) self.w = curses.newwin(10, 50, 5, 5) set_verbosity(False) self.tab = 0 self.pos = 0 self.popup_pos = 0 self.str_recipient = "" self.str_description = "" self.str_amount = "" self.str_fee = "" self.history = None if self.network: self.network.register_callback(self.update, ['wallet_updated', 'network_updated']) self.tab_names = [_("History"), _("Send"), _("Receive"), _("Addresses"), _("Contacts"), _("Banner")] self.num_tabs = len(self.tab_names)
def new(self): name = os.path.basename(self.storage.path) title = _("Welcome to the Electrum installation wizard.") message = '\n'.join([ _("The wallet '%s' does not exist.") % name, _("What kind of wallet do you want to create?") ]) wallet_kinds = [ ('standard', _("Standard wallet")), ('twofactor', _("Wallet with two-factor authentication")), ('multisig', _("Multi-signature wallet")), ('hardware', _("Hardware wallet")), ] registered_kinds = Wallet.categories() choices = [pair for pair in wallet_kinds if pair[0] in registered_kinds] self.choice_dialog(title = title, message=message, choices=choices, run_next=self.on_wallet_type)
def on_restore_pw(self, wizard, seed, password): # FIXME # wallet.add_seed(seed, password) storage = wizard.storage words = seed.split() n = len(words) / 2 keystore1 = keystore.xprv_from_seed(' '.join(words[0:n]), password) keystore2 = keystore.xprv_from_seed(' '.join(words[n:]), password) keystore1.save(storage, 'x1/') keystore2.save(storage, 'x2/') long_user_id, short_id = get_user_id(storage) xpub3 = make_xpub(signing_xpub, long_user_id) keystore3 = keystore.from_xpub(xpub3) keystore3.save(storage, 'x3/') wizard.wallet = Wallet(storage) wizard.create_addresses()
def run_and_get_wallet(self): # Show network dialog if config does not exist if self.network: if self.config.get('auto_connect') is None: self.choose_server(self.network) path = self.storage.path if self.storage.requires_split(): self.hide() msg = _("The wallet '%s' contains multiple accounts, which are no longer supported in Electrum 2.7.\n\n" "Do you want to split your wallet into multiple files?"%path) if not self.question(msg): return file_list = '\n'.join(self.storage.split_accounts()) msg = _('Your accounts have been moved to:\n %s.\n\nDo you want to delete the old file:\n%s' % (file_list, path)) if self.question(msg): os.remove(path) self.show_warning(_('The file was removed')) return if self.storage.requires_upgrade(): self.hide() msg = _("The format of your wallet '%s' must be upgraded for Electrum. This change will not be backward compatible"%path) if not self.question(msg): return self.storage.upgrade() self.show_warning(_('Your wallet was upgraded successfully')) self.wallet = Wallet(self.storage) self.terminate() return self.wallet action = self.storage.get_action() if action and action != 'new': self.hide() msg = _("The file '%s' contains an incompletely created wallet.\n" "Do you want to complete its creation now?") % path if not self.question(msg): if self.question(_("Do you want to delete '%s'?") % path): os.remove(path) self.show_warning(_('The file was removed')) return self.show() if action: # self.wallet is set in run self.run(action) return self.wallet
def create_remote_key(self, wizard): email = self.accept_terms_of_use(wizard) mpk = wizard.storage.get('master_public_keys') xpub1 = mpk["x1/"] xpub2 = mpk["x2/"] # Generate third key deterministically. long_user_id, short_id = get_user_id(wizard.storage) xpub3 = make_xpub(signing_xpub, long_user_id) # secret must be sent by the server try: r = server.create(xpub1, xpub2, email) except socket.error: wizard.show_message('Server not reachable, aborting') return except TrustedCoinException as e: if e.status_code == 409: r = None else: raise e if r is None: otp_secret = None else: otp_secret = r.get('otp_secret') if not otp_secret: wizard.show_message(_('Error')) return _xpub3 = r['xpubkey_cosigner'] _id = r['id'] try: assert _id == short_id, ("user id error", _id, short_id) assert xpub3 == _xpub3, ("xpub3 error", xpub3, _xpub3) except Exception as e: wizard.show_message(str(e)) return if not self.setup_google_auth(wizard, short_id, otp_secret): wizard.show_message("otp error") return keystore3 = keystore.from_xpub(xpub3) keystore3.save(wizard.storage, 'x3/') wizard.storage.put('use_trustedcoin', True) wizard.storage.write() wizard.wallet = Wallet(wizard.storage) wizard.run('create_addresses')
def __init__(self, config, network): self.network = network self.config = config storage = WalletStorage(config) if not storage.file_exists: print "Wallet not found. try 'electrum create'" exit() self.done = 0 self.last_balance = "" set_verbosity(False) self.str_recipient = "" self.str_description = "" self.str_amount = "" self.str_fee = "" self.wallet = Wallet(storage) self.wallet.start_threads(network) self.contacts = StoreDict(self.config, 'contacts') self.wallet.network.register_callback('updated', self.updated) self.wallet.network.register_callback('connected', self.connected) self.wallet.network.register_callback('disconnected', self.disconnected) self.wallet.network.register_callback('disconnecting', self.disconnecting) self.wallet.network.register_callback('peers', self.peers) self.wallet.network.register_callback('banner', self.print_banner) self.commands = [_("[h] - displays this help text"), \ _("[i] - display transaction history"), \ _("[o] - enter payment order"), \ _("[p] - print stored payment order"), \ _("[s] - send stored payment order"), \ _("[r] - show own receipt addresses"), \ _("[c] - display contacts"), \ _("[b] - print server banner"), \ _("[q] - quit") ] self.num_commands = len(self.commands)
class ElectrumGui: def __init__(self, config, daemon, plugins): self.config = config self.network = daemon.network storage = WalletStorage(config.get_wallet_path()) if not storage.file_exists(): print("Wallet not found. try 'electrum create'") exit() if storage.is_encrypted(): password = getpass.getpass('Password:'******'') self.encoding = locale.getpreferredencoding() self.stdscr = curses.initscr() curses.noecho() curses.cbreak() curses.start_color() curses.use_default_colors() curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE) curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_CYAN) curses.init_pair(3, curses.COLOR_BLACK, curses.COLOR_WHITE) self.stdscr.keypad(1) self.stdscr.border(0) self.maxy, self.maxx = self.stdscr.getmaxyx() self.set_cursor(0) self.w = curses.newwin(10, 50, 5, 5) set_verbosity(False) self.tab = 0 self.pos = 0 self.popup_pos = 0 self.str_recipient = "" self.str_description = "" self.str_amount = "" self.str_fee = "" self.history = None if self.network: self.network.register_callback(self.update, ['wallet_updated', 'network_updated']) self.tab_names = [_("History"), _("Send"), _("Receive"), _("Addresses"), _("Contacts"), _("Banner")] self.num_tabs = len(self.tab_names) def set_cursor(self, x): try: curses.curs_set(x) except Exception: pass def restore_or_create(self): pass def verify_seed(self): pass def get_string(self, y, x): self.set_cursor(1) curses.echo() self.stdscr.addstr( y, x, " "*20, curses.A_REVERSE) s = self.stdscr.getstr(y,x) curses.noecho() self.set_cursor(0) return s def update(self, event): self.update_history() if self.tab == 0: self.print_history() self.refresh() def print_history(self): width = [20, 40, 14, 14] delta = (self.maxx - sum(width) - 4)/3 format_str = "%"+"%d"%width[0]+"s"+"%"+"%d"%(width[1]+delta)+"s"+"%"+"%d"%(width[2]+delta)+"s"+"%"+"%d"%(width[3]+delta)+"s" if self.history is None: self.update_history() self.print_list(self.history[::-1], format_str%( _("Date"), _("Description"), _("Amount"), _("Balance"))) def update_history(self): width = [20, 40, 14, 14] delta = (self.maxx - sum(width) - 4)/3 format_str = "%"+"%d"%width[0]+"s"+"%"+"%d"%(width[1]+delta)+"s"+"%"+"%d"%(width[2]+delta)+"s"+"%"+"%d"%(width[3]+delta)+"s" b = 0 self.history = [] for tx_hash, tx_mined_status, value, balance in self.wallet.get_history(): if tx_mined_status.conf: timestamp = tx_mined_status.timestamp try: time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3] except Exception: time_str = "------" else: time_str = 'unconfirmed' label = self.wallet.get_label(tx_hash) if len(label) > 40: label = label[0:37] + '...' self.history.append( format_str%( time_str, label, format_satoshis(value, whitespaces=True), format_satoshis(balance, whitespaces=True) ) ) def print_balance(self): if not self.network: msg = _("Offline") elif self.network.is_connected(): if not self.wallet.up_to_date: msg = _("Synchronizing...") else: c, u, x = self.wallet.get_balance() msg = _("Balance")+": %f "%(Decimal(c) / COIN) if u: msg += " [%f unconfirmed]"%(Decimal(u) / COIN) if x: msg += " [%f unmatured]"%(Decimal(x) / COIN) else: msg = _("Not connected") self.stdscr.addstr( self.maxy -1, 3, msg) for i in range(self.num_tabs): self.stdscr.addstr( 0, 2 + 2*i + len(''.join(self.tab_names[0:i])), ' '+self.tab_names[i]+' ', curses.A_BOLD if self.tab == i else 0) self.stdscr.addstr(self.maxy -1, self.maxx-30, ' '.join([_("Settings"), _("Network"), _("Quit")])) def print_receive(self): addr = self.wallet.get_receiving_address() self.stdscr.addstr(2, 1, "Address: "+addr) self.print_qr(addr) def print_contacts(self): messages = map(lambda x: "%20s %45s "%(x[0], x[1][1]), self.contacts.items()) self.print_list(messages, "%19s %15s "%("Key", "Value")) def print_addresses(self): fmt = "%-35s %-30s" messages = map(lambda addr: fmt % (addr, self.wallet.labels.get(addr,"")), self.wallet.get_addresses()) self.print_list(messages, fmt % ("Address", "Label")) def print_edit_line(self, y, label, text, index, size): text += " "*(size - len(text) ) self.stdscr.addstr( y, 2, label) self.stdscr.addstr( y, 15, text, curses.A_REVERSE if self.pos%6==index else curses.color_pair(1)) def print_send_tab(self): self.stdscr.clear() self.print_edit_line(3, _("Pay to"), self.str_recipient, 0, 40) self.print_edit_line(5, _("Description"), self.str_description, 1, 40) self.print_edit_line(7, _("Amount"), self.str_amount, 2, 15) self.print_edit_line(9, _("Fee"), self.str_fee, 3, 15) self.stdscr.addstr( 12, 15, _("[Send]"), curses.A_REVERSE if self.pos%6==4 else curses.color_pair(2)) self.stdscr.addstr( 12, 25, _("[Clear]"), curses.A_REVERSE if self.pos%6==5 else curses.color_pair(2)) self.maxpos = 6 def print_banner(self): if self.network and self.network.banner: banner = self.network.banner banner = banner.replace('\r', '') self.print_list(banner.split('\n')) def print_qr(self, data): import qrcode try: from StringIO import StringIO except ImportError: from io import StringIO s = StringIO() self.qr = qrcode.QRCode() self.qr.add_data(data) self.qr.print_ascii(out=s, invert=False) msg = s.getvalue() lines = msg.split('\n') try: for i, l in enumerate(lines): l = l.encode("utf-8") self.stdscr.addstr(i+5, 5, l, curses.color_pair(3)) except curses.error: m = 'error. screen too small?' m = m.encode(self.encoding) self.stdscr.addstr(5, 1, m, 0) def print_list(self, lst, firstline = None): lst = list(lst) self.maxpos = len(lst) if not self.maxpos: return if firstline: firstline += " "*(self.maxx -2 - len(firstline)) self.stdscr.addstr( 1, 1, firstline ) for i in range(self.maxy-4): msg = lst[i] if i < len(lst) else "" msg += " "*(self.maxx - 2 - len(msg)) m = msg[0:self.maxx - 2] m = m.encode(self.encoding) self.stdscr.addstr( i+2, 1, m, curses.A_REVERSE if i == (self.pos % self.maxpos) else 0) def refresh(self): if self.tab == -1: return self.stdscr.border(0) self.print_balance() self.stdscr.refresh() def main_command(self): c = self.stdscr.getch() print(c) cc = curses.unctrl(c).decode() if c == curses.KEY_RIGHT: self.tab = (self.tab + 1)%self.num_tabs elif c == curses.KEY_LEFT: self.tab = (self.tab - 1)%self.num_tabs elif c == curses.KEY_DOWN: self.pos +=1 elif c == curses.KEY_UP: self.pos -= 1 elif c == 9: self.pos +=1 # tab elif cc in ['^W', '^C', '^X', '^Q']: self.tab = -1 elif cc in ['^N']: self.network_dialog() elif cc == '^S': self.settings_dialog() else: return c if self.pos<0: self.pos=0 if self.pos>=self.maxpos: self.pos=self.maxpos - 1 def run_tab(self, i, print_func, exec_func): while self.tab == i: self.stdscr.clear() print_func() self.refresh() c = self.main_command() if c: exec_func(c) def run_history_tab(self, c): if c == 10: out = self.run_popup('',["blah","foo"]) def edit_str(self, target, c, is_num=False): # detect backspace cc = curses.unctrl(c).decode() if c in [8, 127, 263] and target: target = target[:-1] elif not is_num or cc in '0123456789.': target += cc return target def run_send_tab(self, c): if self.pos%6 == 0: self.str_recipient = self.edit_str(self.str_recipient, c) if self.pos%6 == 1: self.str_description = self.edit_str(self.str_description, c) if self.pos%6 == 2: self.str_amount = self.edit_str(self.str_amount, c, True) elif self.pos%6 == 3: self.str_fee = self.edit_str(self.str_fee, c, True) elif self.pos%6==4: if c == 10: self.do_send() elif self.pos%6==5: if c == 10: self.do_clear() def run_receive_tab(self, c): if c == 10: out = self.run_popup('Address', ["Edit label", "Freeze", "Prioritize"]) def run_contacts_tab(self, c): if c == 10 and self.contacts: out = self.run_popup('Address', ["Copy", "Pay to", "Edit label", "Delete"]).get('button') key = list(self.contacts.keys())[self.pos%len(self.contacts.keys())] if out == "Pay to": self.tab = 1 self.str_recipient = key self.pos = 2 elif out == "Edit label": s = self.get_string(6 + self.pos, 18) if s: self.wallet.labels[key] = s def run_banner_tab(self, c): self.show_message(repr(c)) pass def main(self): tty.setraw(sys.stdin) try: while self.tab != -1: self.run_tab(0, self.print_history, self.run_history_tab) self.run_tab(1, self.print_send_tab, self.run_send_tab) self.run_tab(2, self.print_receive, self.run_receive_tab) self.run_tab(3, self.print_addresses, self.run_banner_tab) self.run_tab(4, self.print_contacts, self.run_contacts_tab) self.run_tab(5, self.print_banner, self.run_banner_tab) except curses.error as e: raise Exception("Error with curses. Is your screen too small?") from e finally: tty.setcbreak(sys.stdin) curses.nocbreak() self.stdscr.keypad(0) curses.echo() curses.endwin() def do_clear(self): self.str_amount = '' self.str_recipient = '' self.str_fee = '' self.str_description = '' def do_send(self): if not is_address(self.str_recipient): self.show_message(_('Invalid Bitcoin address')) return try: amount = int(Decimal(self.str_amount) * COIN) except Exception: self.show_message(_('Invalid Amount')) return try: fee = int(Decimal(self.str_fee) * COIN) except Exception: self.show_message(_('Invalid Fee')) return if self.wallet.has_password(): password = self.password_dialog() if not password: return else: password = None try: tx = self.wallet.mktx([TxOutput(TYPE_ADDRESS, self.str_recipient, amount)], password, self.config, fee) except Exception as e: self.show_message(str(e)) return if self.str_description: self.wallet.labels[tx.txid()] = self.str_description self.show_message(_("Please wait..."), getchar=False) try: self.network.run_from_another_thread(self.network.broadcast_transaction(tx)) except Exception as e: self.show_message(repr(e)) else: self.show_message(_('Payment sent.')) self.do_clear() #self.update_contacts_tab() def show_message(self, message, getchar = True): w = self.w w.clear() w.border(0) for i, line in enumerate(message.split('\n')): w.addstr(2+i,2,line) w.refresh() if getchar: c = self.stdscr.getch() def run_popup(self, title, items): return self.run_dialog(title, list(map(lambda x: {'type':'button','label':x}, items)), interval=1, y_pos = self.pos+3) def network_dialog(self): if not self.network: return net_params = self.network.get_parameters() host, port, protocol = net_params.host, net_params.port, net_params.protocol proxy_config, auto_connect = net_params.proxy, net_params.auto_connect srv = 'auto-connect' if auto_connect else self.network.default_server out = self.run_dialog('Network', [ {'label':'server', 'type':'str', 'value':srv}, {'label':'proxy', 'type':'str', 'value':self.config.get('proxy', '')}, ], buttons = 1) if out: if out.get('server'): server = out.get('server') auto_connect = server == 'auto-connect' if not auto_connect: try: host, port, protocol = deserialize_server(server) except Exception: self.show_message("Error:" + server + "\nIn doubt, type \"auto-connect\"") return False if out.get('server') or out.get('proxy'): proxy = electrum.network.deserialize_proxy(out.get('proxy')) if out.get('proxy') else proxy_config net_params = NetworkParameters(host, port, protocol, proxy, auto_connect) self.network.run_from_another_thread(self.network.set_parameters(net_params)) def settings_dialog(self): fee = str(Decimal(self.config.fee_per_kb()) / COIN) out = self.run_dialog('Settings', [ {'label':'Default fee', 'type':'satoshis', 'value': fee } ], buttons = 1) if out: if out.get('Default fee'): fee = int(Decimal(out['Default fee']) * COIN) self.config.set_key('fee_per_kb', fee, True) def password_dialog(self): out = self.run_dialog('Password', [ {'label':'Password', 'type':'password', 'value':''} ], buttons = 1) return out.get('Password') def run_dialog(self, title, items, interval=2, buttons=None, y_pos=3): self.popup_pos = 0 self.w = curses.newwin( 5 + len(list(items))*interval + (2 if buttons else 0), 50, y_pos, 5) w = self.w out = {} while True: w.clear() w.border(0) w.addstr( 0, 2, title) num = len(list(items)) numpos = num if buttons: numpos += 2 for i in range(num): item = items[i] label = item.get('label') if item.get('type') == 'list': value = item.get('value','') elif item.get('type') == 'satoshis': value = item.get('value','') elif item.get('type') == 'str': value = item.get('value','') elif item.get('type') == 'password': value = '*'*len(item.get('value','')) else: value = '' if value is None: value = '' if len(value)<20: value += ' '*(20-len(value)) if 'value' in item: w.addstr( 2+interval*i, 2, label) w.addstr( 2+interval*i, 15, value, curses.A_REVERSE if self.popup_pos%numpos==i else curses.color_pair(1) ) else: w.addstr( 2+interval*i, 2, label, curses.A_REVERSE if self.popup_pos%numpos==i else 0) if buttons: w.addstr( 5+interval*i, 10, "[ ok ]", curses.A_REVERSE if self.popup_pos%numpos==(numpos-2) else curses.color_pair(2)) w.addstr( 5+interval*i, 25, "[cancel]", curses.A_REVERSE if self.popup_pos%numpos==(numpos-1) else curses.color_pair(2)) w.refresh() c = self.stdscr.getch() if c in [ord('q'), 27]: break elif c in [curses.KEY_LEFT, curses.KEY_UP]: self.popup_pos -= 1 elif c in [curses.KEY_RIGHT, curses.KEY_DOWN]: self.popup_pos +=1 else: i = self.popup_pos%numpos if buttons and c==10: if i == numpos-2: return out elif i == numpos -1: return {} item = items[i] _type = item.get('type') if _type == 'str': item['value'] = self.edit_str(item['value'], c) out[item.get('label')] = item.get('value') elif _type == 'password': item['value'] = self.edit_str(item['value'], c) out[item.get('label')] = item ['value'] elif _type == 'satoshis': item['value'] = self.edit_str(item['value'], c, True) out[item.get('label')] = item.get('value') elif _type == 'list': choices = item.get('choices') try: j = choices.index(item.get('value')) except Exception: j = 0 new_choice = choices[(j + 1)% len(choices)] item['value'] = new_choice out[item.get('label')] = item.get('value') elif _type == 'button': out['button'] = item.get('label') break return out
def confirm_seed(self, seed): assert Wallet.is_seed(seed) msg = _('Please retype your seed phrase, to confirm that you properly saved it') self.restore_seed_dialog(run_prev=self.create_seed, run_next=self.enter_pin, test=lambda x: x==seed, message=msg)
def set_enabled(): OK_button.setEnabled(Wallet.is_xprv(self.get_seed_text(text)))
def restore_hardware_wallet(self): self.storage.put('wallet_type', self.wallet_type) self.wallet = Wallet(self.storage) self.wallet.plugin.on_restore_wallet(self.wallet, self) self.terminate()
def restore_2fa(self): self.storage.put('wallet_type', '2fa') self.wallet = Wallet(self.storage) self.wallet.plugin.on_restore_wallet(self.wallet, self)
config = SimpleConfig({"testnet": True}) # to use ~/.electrum/testnet as datadir constants.set_testnet() # to set testnet magic bytes daemon = Daemon(config, listen_jsonrpc=False) network = daemon.network assert network.asyncio_loop.is_running() # get wallet on disk wallet_dir = os.path.dirname(config.get_wallet_path()) wallet_path = os.path.join(wallet_dir, "test_wallet") if not os.path.exists(wallet_path): create_new_wallet(path=wallet_path, segwit=True) # open wallet storage = WalletStorage(wallet_path) wallet = Wallet(storage) wallet.start_network(network) # you can use ~CLI commands by accessing command_runner command_runner = Commands(config, wallet=None, network=network) command_runner.wallet = wallet print("balance", command_runner.getbalance()) print("addr", command_runner.getunusedaddress()) print("gettx", command_runner.gettransaction("bd3a700b2822e10a034d110c11a596ee7481732533eb6aca7f9ca02911c70a4f")) # but you might as well interact with the underlying methods directly print("balance", wallet.get_balance()) print("addr", wallet.get_unused_address()) print("gettx", network.run_from_another_thread(network.get_transaction("bd3a700b2822e10a034d110c11a596ee7481732533eb6aca7f9ca02911c70a4f")))
class ElectrumGui: def __init__(self, config, network, daemon, plugins): self.network = network self.config = config storage = WalletStorage(config.get_wallet_path()) if not storage.file_exists: print "Wallet not found. try 'electrum create'" exit() self.done = 0 self.last_balance = "" set_verbosity(False) self.str_recipient = "" self.str_description = "" self.str_amount = "" self.str_fee = "" self.wallet = Wallet(storage) self.wallet.start_threads(network) self.contacts = StoreDict(self.config, "contacts") network.register_callback(self.on_network, ["updated", "banner"]) self.commands = [ _("[h] - displays this help text"), _("[i] - display transaction history"), _("[o] - enter payment order"), _("[p] - print stored payment order"), _("[s] - send stored payment order"), _("[r] - show own receipt addresses"), _("[c] - display contacts"), _("[b] - print server banner"), _("[q] - quit"), ] self.num_commands = len(self.commands) def on_network(self, event, *args): if event == "updated": self.updated() elif event == "banner": self.print_banner() def main_command(self): self.print_balance() c = raw_input("enter command: ") if c == "h": self.print_commands() elif c == "i": self.print_history() elif c == "o": self.enter_order() elif c == "p": self.print_order() elif c == "s": self.send_order() elif c == "r": self.print_addresses() elif c == "c": self.print_contacts() elif c == "b": self.print_banner() elif c == "n": self.network_dialog() elif c == "e": self.settings_dialog() elif c == "q": self.done = 1 else: self.print_commands() def updated(self): s = self.get_balance() if s != self.last_balance: print (s) self.last_balance = s return True def print_commands(self): self.print_list(self.commands, "Available commands") def print_history(self): width = [20, 40, 14, 14] delta = (80 - sum(width) - 4) / 3 format_str = ( "%" + "%d" % width[0] + "s" + "%" + "%d" % (width[1] + delta) + "s" + "%" + "%d" % (width[2] + delta) + "s" + "%" + "%d" % (width[3] + delta) + "s" ) b = 0 messages = [] for item in self.wallet.get_history(): tx_hash, confirmations, value, timestamp, balance = item if confirmations: try: time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(" ")[:-3] except Exception: time_str = "unknown" else: time_str = "pending" label = self.wallet.get_label(tx_hash) messages.append( format_str % ( time_str, label, format_satoshis(value, whitespaces=True), format_satoshis(balance, whitespaces=True), ) ) self.print_list(messages[::-1], format_str % (_("Date"), _("Description"), _("Amount"), _("Balance"))) def print_balance(self): print (self.get_balance()) def get_balance(self): if self.wallet.network.is_connected(): if not self.wallet.up_to_date: msg = _("Synchronizing...") else: c, u, x = self.wallet.get_balance() msg = _("Balance") + ": %f " % (Decimal(c) / COIN) if u: msg += " [%f unconfirmed]" % (Decimal(u) / COIN) if x: msg += " [%f unmatured]" % (Decimal(x) / COIN) else: msg = _("Not connected") return msg def print_contacts(self): messages = map(lambda x: "%20s %45s " % (x[0], x[1][1]), self.contacts.items()) self.print_list(messages, "%19s %25s " % ("Key", "Value")) def print_addresses(self): messages = map( lambda addr: "%30s %30s " % (addr, self.wallet.labels.get(addr, "")), self.wallet.addresses() ) self.print_list(messages, "%19s %25s " % ("Address", "Label")) def print_order(self): print ( "send order to " + self.str_recipient + ", amount: " + self.str_amount + "\nfee: " + self.str_fee + ", desc: " + self.str_description ) def enter_order(self): self.str_recipient = raw_input("Pay to: ") self.str_description = raw_input("Description : ") self.str_amount = raw_input("Amount: ") self.str_fee = raw_input("Fee: ") def send_order(self): self.do_send() def print_banner(self): for i, x in enumerate(self.wallet.network.banner.split("\n")): print (x) def print_list(self, list, firstline): self.maxpos = len(list) if not self.maxpos: return print (firstline) for i in range(self.maxpos): msg = list[i] if i < len(list) else "" print (msg) def main(self): while self.done == 0: self.main_command() def do_send(self): if not is_valid(self.str_recipient): print (_("Invalid Bitcoin address")) return try: amount = int(Decimal(self.str_amount) * COIN) except Exception: print (_("Invalid Amount")) return try: fee = int(Decimal(self.str_fee) * COIN) except Exception: print (_("Invalid Fee")) return if self.wallet.use_encryption: password = self.password_dialog() if not password: return else: password = None c = "" while c != "y": c = raw_input("ok to send (y/n)?") if c == "n": return try: tx = self.wallet.mktx([(TYPE_ADDRESS, self.str_recipient, amount)], password, self.config, fee) except Exception as e: print (str(e)) return if self.str_description: self.wallet.labels[tx.hash()] = self.str_description h = self.wallet.send_tx(tx) print (_("Please wait...")) self.wallet.tx_event.wait() status, msg = self.wallet.receive_tx(h, tx) if status: print (_("Payment sent.")) # self.do_clear() # self.update_contacts_tab() else: print (_("Error")) def network_dialog(self): print ("use 'electrum setconfig server/proxy' to change your network settings") return True def settings_dialog(self): print ("use 'electrum setconfig' to change your settings") return True def password_dialog(self): return getpass.getpass() # XXX unused def run_receive_tab(self, c): # if c == 10: # out = self.run_popup('Address', ["Edit label", "Freeze", "Prioritize"]) return def run_contacts_tab(self, c): pass
def confirm_seed(self, seed): assert Wallet.is_seed(seed) title = _('Confirm Seed') msg = _('Please retype your seed phrase, to confirm that you properly saved it') self.enter_seed_dialog(run_next=self.add_password, title=title, message=msg, is_valid=lambda x: x==seed)
def confirm_seed(self, seed): assert Wallet.is_seed(seed) self.confirm_seed_dialog(run_next=self.add_password, is_valid=lambda x: x==seed)
def _sanity_check_upgraded_db(self, db): self.assertFalse(db.requires_split()) self.assertFalse(db.requires_upgrade()) w = Wallet(db, None, config=self.config)
class InstallWizard(QDialog, MessageBoxMixin, BaseWizard): def __init__(self, config, app, plugins, network, storage): BaseWizard.__init__(self, config, network, storage) QDialog.__init__(self, None) self.setWindowTitle('Electrum - ' + _('Install Wizard')) self.app = app self.config = config # Set for base base class self.plugins = plugins self.language_for_seed = config.get('language') self.setMinimumSize(530, 370) self.setMaximumSize(530, 370) self.connect(self, QtCore.SIGNAL('accept'), self.accept) self.title = QLabel() self.main_widget = QWidget() self.back_button = QPushButton(_("Back"), self) self.next_button = QPushButton(_("Next"), self) self.next_button.setDefault(True) self.logo = QLabel() self.please_wait = QLabel(_("Please wait...")) self.please_wait.setAlignment(Qt.AlignCenter) self.icon_filename = None self.loop = QEventLoop() self.rejected.connect(lambda: self.loop.exit(0)) self.back_button.clicked.connect(lambda: self.loop.exit(1)) self.next_button.clicked.connect(lambda: self.loop.exit(2)) outer_vbox = QVBoxLayout(self) inner_vbox = QVBoxLayout() inner_vbox = QVBoxLayout() inner_vbox.addWidget(self.title) inner_vbox.addWidget(self.main_widget) inner_vbox.addStretch(1) inner_vbox.addWidget(self.please_wait) inner_vbox.addStretch(1) icon_vbox = QVBoxLayout() icon_vbox.addWidget(self.logo) icon_vbox.addStretch(1) hbox = QHBoxLayout() hbox.addLayout(icon_vbox) hbox.addSpacing(5) hbox.addLayout(inner_vbox) hbox.setStretchFactor(inner_vbox, 1) outer_vbox.addLayout(hbox) outer_vbox.addLayout(Buttons(self.back_button, self.next_button)) self.set_icon(':icons/electrum.png') self.show() self.raise_() self.refresh_gui() # Need for QT on MacOSX. Lame. def run_and_get_wallet(self): # Show network dialog if config does not exist if self.network: if self.config.get('auto_connect') is None: self.choose_server(self.network) path = self.storage.path if self.storage.requires_split(): self.hide() msg = _("The wallet '%s' contains multiple accounts, which are no longer supported in Electrum 2.7.\n\n" "Do you want to split your wallet into multiple files?"%path) if not self.question(msg): return file_list = '\n'.join(self.storage.split_accounts()) msg = _('Your accounts have been moved to:\n %s.\n\nDo you want to delete the old file:\n%s' % (file_list, path)) if self.question(msg): os.remove(path) self.show_warning(_('The file was removed')) return if self.storage.requires_upgrade(): self.hide() msg = _("The format of your wallet '%s' must be upgraded for Electrum. This change will not be backward compatible"%path) if not self.question(msg): return self.storage.upgrade() self.show_warning(_('Your wallet was upgraded successfully')) self.wallet = Wallet(self.storage) self.terminate() return self.wallet action = self.storage.get_action() if action and action != 'new': self.hide() msg = _("The file '%s' contains an incompletely created wallet.\n" "Do you want to complete its creation now?") % path if not self.question(msg): if self.question(_("Do you want to delete '%s'?") % path): os.remove(path) self.show_warning(_('The file was removed')) return self.show() if action: # self.wallet is set in run self.run(action) return self.wallet def finished(self): '''Ensure the dialog is closed.''' self.accept() self.refresh_gui() def on_error(self, exc_info): if not isinstance(exc_info[1], UserCancelled): traceback.print_exception(*exc_info) self.show_error(str(exc_info[1])) def set_icon(self, filename): prior_filename, self.icon_filename = self.icon_filename, filename self.logo.setPixmap(QPixmap(filename).scaledToWidth(60)) return prior_filename def set_main_layout(self, layout, title=None, raise_on_cancel=True, next_enabled=True): self.title.setText("<b>%s</b>"%title if title else "") self.title.setVisible(bool(title)) # Get rid of any prior layout by assigning it to a temporary widget prior_layout = self.main_widget.layout() if prior_layout: QWidget().setLayout(prior_layout) self.main_widget.setLayout(layout) self.back_button.setEnabled(True) self.next_button.setEnabled(next_enabled) self.main_widget.setVisible(True) self.please_wait.setVisible(False) result = self.loop.exec_() if not result and raise_on_cancel: raise UserCancelled if result == 1: raise GoBack self.title.setVisible(False) self.back_button.setEnabled(False) self.next_button.setEnabled(False) self.main_widget.setVisible(False) self.please_wait.setVisible(True) self.refresh_gui() return result def refresh_gui(self): # For some reason, to refresh the GUI this needs to be called twice self.app.processEvents() self.app.processEvents() def remove_from_recently_open(self, filename): self.config.remove_from_recently_open(filename) def text_input(self, title, message, is_valid): slayout = SeedInputLayout(title=message) def sanitized_seed(): return clean_text(slayout.seed_edit()) def set_enabled(): self.next_button.setEnabled(is_valid(sanitized_seed())) slayout.seed_edit().textChanged.connect(set_enabled) self.set_main_layout(slayout.layout(), title, next_enabled=False) seed = sanitized_seed() return seed @wizard_dialog def restore_keys_dialog(self, title, message, is_valid, run_next): return self.text_input(title, message, is_valid) @wizard_dialog def add_cosigner_dialog(self, run_next, index, is_valid): title = _("Add Cosigner") + " %d"%index message = ' '.join([ _('Please enter the master public key of your cosigner.'), _('Enter their seed or master private key if you want to be able to sign for them.') ]) return self.text_input(title, message, is_valid) @wizard_dialog def restore_seed_dialog(self, run_next, is_valid): title = _('Enter Seed') message = _('Please enter your seed phrase in order to restore your wallet.') return self.text_input(title, message, is_valid) @wizard_dialog def confirm_seed_dialog(self, run_next, is_valid): self.app.clipboard().clear() title = _('Confirm Seed') message = ' '.join([ _('Your seed is important!'), _('To make sure that you have properly saved your seed, please retype it here.') ]) return self.text_input(title, message, is_valid) @wizard_dialog def show_seed_dialog(self, run_next, seed_text): slayout = SeedWarningLayout(seed_text) self.set_main_layout(slayout.layout()) return seed_text def pw_layout(self, msg, kind): playout = PasswordLayout(None, msg, kind, self.next_button) self.set_main_layout(playout.layout()) return playout.new_password() @wizard_dialog def request_passphrase(self, device_text, run_next): """When restoring a wallet, request the passphrase that was used for the wallet on the given device and confirm it. Should return a unicode string.""" phrase = self.pw_layout(MSG_RESTORE_PASSPHRASE % device_text, PW_PASSPHRASE) if phrase is None: raise UserCancelled return phrase @wizard_dialog def request_password(self, run_next): """Request the user enter a new password and confirm it. Return the password or None for no password.""" return self.pw_layout(MSG_ENTER_PASSWORD, PW_NEW) def show_restore(self, wallet, network): # FIXME: these messages are shown after the install wizard is # finished and the window closed. On MacOSX they appear parented # with a re-appeared ghost install wizard window... if network: def task(): wallet.wait_until_synchronized() if wallet.is_found(): msg = _("Recovery successful") else: msg = _("No transactions found for this seed") self.emit(QtCore.SIGNAL('synchronized'), msg) self.connect(self, QtCore.SIGNAL('synchronized'), self.show_message) t = threading.Thread(target = task) t.daemon = True t.start() else: msg = _("This wallet was restored offline. It may " "contain more addresses than displayed.") self.show_message(msg) @wizard_dialog def confirm_dialog(self, msg, run_next): self.confirm(msg) def confirm(self, msg): vbox = QVBoxLayout() vbox.addWidget(WWLabel(msg)) self.set_main_layout(vbox) @wizard_dialog def action_dialog(self, action, run_next): self.run(action) def terminate(self): self.wallet.start_threads(self.network) self.emit(QtCore.SIGNAL('accept')) def waiting_dialog(self, task, msg): self.please_wait.setText(MSG_GENERATING_WAIT) self.refresh_gui() t = threading.Thread(target = task) t.start() @wizard_dialog def choice_dialog(self, title, message, choices, run_next): c_values = map(lambda x: x[0], choices) c_titles = map(lambda x: x[1], choices) clayout = ChoicesLayout(message, c_titles) vbox = QVBoxLayout() vbox.addLayout(clayout.layout()) self.set_main_layout(vbox, title) action = c_values[clayout.selected_index()] return action @wizard_dialog def show_xpub_dialog(self, xpub, run_next): msg = ' '.join([ _("Here is your master public key."), _("Please share it with your cosigners.") ]) vbox = QVBoxLayout() layout = SeedDisplayLayout(xpub, title=msg, sid='hot') vbox.addLayout(layout.layout()) self.set_main_layout(vbox, _('Master Public Key')) return None def choose_server(self, network): title = _("Electrum communicates with remote servers to get " "information about your transactions and addresses. The " "servers all fulfil the same purpose only differing in " "hardware. In most cases you simply want to let Electrum " "pick one at random. However if you prefer feel free to " "select a server manually.") choices = [_("Auto connect"), _("Select server manually")] choices_title = _("How do you want to connect to a server? ") clayout = ChoicesLayout(choices_title, choices) self.set_main_layout(clayout.layout(), title) auto_connect = True if clayout.selected_index() == 1: nlayout = NetworkChoiceLayout(network, self.config, wizard=True) if self.set_main_layout(nlayout.layout(), raise_on_cancel=False): nlayout.accept() auto_connect = False self.config.set_key('auto_connect', auto_connect, True) network.auto_connect = auto_connect @wizard_dialog def multisig_dialog(self, run_next): cw = CosignWidget(2, 2) m_edit = QSlider(Qt.Horizontal, self) n_edit = QSlider(Qt.Horizontal, self) n_edit.setMinimum(2) n_edit.setMaximum(15) m_edit.setMinimum(1) m_edit.setMaximum(2) n_edit.setValue(2) m_edit.setValue(2) n_label = QLabel() m_label = QLabel() grid = QGridLayout() grid.addWidget(n_label, 0, 0) grid.addWidget(n_edit, 0, 1) grid.addWidget(m_label, 1, 0) grid.addWidget(m_edit, 1, 1) def on_m(m): m_label.setText(_('Require %d signatures')%m) cw.set_m(m) def on_n(n): n_label.setText(_('From %d cosigners')%n) cw.set_n(n) m_edit.setMaximum(n) n_edit.valueChanged.connect(on_n) m_edit.valueChanged.connect(on_m) on_n(2) on_m(2) vbox = QVBoxLayout() vbox.addWidget(cw) vbox.addWidget(WWLabel(_("Choose the number of signatures needed to unlock funds in your wallet:"))) vbox.addLayout(grid) self.set_main_layout(vbox, _("Multi-Signature Wallet")) m = int(m_edit.value()) n = int(n_edit.value()) return (m, n)
# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import os from electrum.wallet import Wallet, Multisig_Wallet, WalletStorage from i18n import _ is_any_key = lambda x: Wallet.is_old_mpk(x) or Wallet.is_xprv(x) or Wallet.is_xpub(x) or Wallet.is_address(x) or Wallet.is_private_key(x) is_private_key = lambda x: Wallet.is_xprv(x) or Wallet.is_private_key(x) is_bip32_key = lambda x: Wallet.is_xprv(x) or Wallet.is_xpub(x) class BaseWizard(object): def __init__(self, config, network, path): super(BaseWizard, self).__init__() self.config = config self.network = network self.storage = WalletStorage(path) self.wallet = None self.stack = [] def run(self, *args):
def set_enabled(): wizard.next_button.setEnabled(Wallet.is_xprv(clean_text(text)))
def set_enabled(): wizard.next_button.setEnabled( Wallet.is_xprv(clean_text(text)))
def set_enabled(): OK_button.setEnabled(Wallet.is_xprv(clean_text(text)))