def __init__(self, parent): MyTreeWidget.__init__(self, parent, self.create_menu, [_('Name'), _('Address')], 0, [0]) self.setSelectionMode(QAbstractItemView.ExtendedSelection) self.setSortingEnabled(True)
from electrum_stratis.i18n import _ fullname = 'Plot History' description = _("Ability to plot transaction history in graphical mode.") requires = [('matplotlib', 'matplotlib')] available_for = ['qt']
def request_trezor_init_settings(self, wizard, method, device): vbox = QVBoxLayout() next_enabled = True label = QLabel(_("Enter a label to name your device:")) name = QLineEdit() hl = QHBoxLayout() hl.addWidget(label) hl.addWidget(name) hl.addStretch(1) vbox.addLayout(hl) def clean_text(widget): text = unicode(widget.toPlainText()).strip() return ' '.join(text.split()) if method in [TIM_NEW, TIM_RECOVER]: gb = QGroupBox() hbox1 = QHBoxLayout() gb.setLayout(hbox1) # KeepKey recovery doesn't need a word count if method == TIM_NEW or self.device == 'TREZOR': vbox.addWidget(gb) gb.setTitle(_("Select your seed length:")) bg = QButtonGroup() for i, count in enumerate([12, 18, 24]): rb = QRadioButton(gb) rb.setText(_("%d words") % count) bg.addButton(rb) bg.setId(rb, i) hbox1.addWidget(rb) rb.setChecked(True) cb_pin = QCheckBox(_('Enable PIN protection')) cb_pin.setChecked(True) else: text = QTextEdit() text.setMaximumHeight(60) if method == TIM_MNEMONIC: msg = _("Enter your BIP39 mnemonic:") else: msg = _("Enter the master private key beginning with xprv:") def set_enabled(): wizard.next_button.setEnabled( Wallet.is_xprv(clean_text(text))) text.textChanged.connect(set_enabled) next_enabled = False vbox.addWidget(QLabel(msg)) vbox.addWidget(text) pin = QLineEdit() pin.setValidator(QRegExpValidator(QRegExp('[1-9]{0,10}'))) pin.setMaximumWidth(100) hbox_pin = QHBoxLayout() hbox_pin.addWidget(QLabel(_("Enter your PIN (digits 1-9):"))) hbox_pin.addWidget(pin) hbox_pin.addStretch(1) if method in [TIM_NEW, TIM_RECOVER]: vbox.addWidget(WWLabel(RECOMMEND_PIN)) vbox.addWidget(cb_pin) else: vbox.addLayout(hbox_pin) passphrase_msg = WWLabel(PASSPHRASE_HELP_SHORT) passphrase_warning = WWLabel(PASSPHRASE_NOT_PIN) passphrase_warning.setStyleSheet("color: red") cb_phrase = QCheckBox(_('Enable passphrases')) cb_phrase.setChecked(False) vbox.addWidget(passphrase_msg) vbox.addWidget(passphrase_warning) vbox.addWidget(cb_phrase) wizard.set_main_layout(vbox, next_enabled=next_enabled) if method in [TIM_NEW, TIM_RECOVER]: item = bg.checkedId() pin = cb_pin.isChecked() else: item = ' '.join(str(clean_text(text)).split()) pin = str(pin.text()) return (item, unicode(name.text()), pin, cb_phrase.isChecked())
from electrum_stratis.i18n import _ fullname = 'Ledger Wallet' description = 'Provides support for Ledger hardware wallet' requires = [('btchip', 'github.com/ledgerhq/btchip-python')] registers_keystore = ('hardware', 'ledger', _("Ledger wallet")) available_for = ['qt', 'cmdline']
def transaction_dialog(self, d): d.cosigner_send_button = b = QPushButton(_("Send to cosigner")) b.clicked.connect(lambda: self.do_send(d.tx)) d.buttons.insert(0, b) self.transaction_dialog_update(d)
def __init__(self, wallet, msg, kind, OK_button): self.wallet = wallet self.pw = QLineEdit() self.pw.setEchoMode(2) self.new_pw = QLineEdit() self.new_pw.setEchoMode(2) self.conf_pw = QLineEdit() self.conf_pw.setEchoMode(2) self.kind = kind self.OK_button = OK_button vbox = QVBoxLayout() label = QLabel(msg + "\n") label.setWordWrap(True) grid = QGridLayout() grid.setSpacing(8) grid.setColumnMinimumWidth(0, 150) grid.setColumnMinimumWidth(1, 100) grid.setColumnStretch(1, 1) if kind == PW_PASSPHRASE: vbox.addWidget(label) msgs = [_('Passphrase:'), _('Confirm Passphrase:')] else: logo_grid = QGridLayout() logo_grid.setSpacing(8) logo_grid.setColumnMinimumWidth(0, 70) logo_grid.setColumnStretch(1, 1) logo = QLabel() logo.setAlignment(Qt.AlignCenter) logo_grid.addWidget(logo, 0, 0) logo_grid.addWidget(label, 0, 1, 1, 2) vbox.addLayout(logo_grid) m1 = _('New Password:'******'Password:'******'Confirm Password:'******'Current Password:')), 0, 0) grid.addWidget(self.pw, 0, 1) lockfile = ":icons/lock.png" else: lockfile = ":icons/unlock.png" logo.setPixmap(QPixmap(lockfile).scaledToWidth(36)) grid.addWidget(QLabel(msgs[0]), 1, 0) grid.addWidget(self.new_pw, 1, 1) grid.addWidget(QLabel(msgs[1]), 2, 0) grid.addWidget(self.conf_pw, 2, 1) vbox.addLayout(grid) # Password Strength Label if kind != PW_PASSPHRASE: self.pw_strength = QLabel() grid.addWidget(self.pw_strength, 3, 0, 1, 2) self.new_pw.textChanged.connect(self.pw_changed) def enable_OK(): OK_button.setEnabled(self.new_pw.text() == self.conf_pw.text()) self.new_pw.textChanged.connect(enable_OK) self.conf_pw.textChanged.connect(enable_OK) self.vbox = vbox
def settings_widget(self, window): return EnterButton(_('Settings'), partial(self.settings_dialog, window))
def __init__(self, handler, data): '''Ask user for 2nd factor authentication. Support text, security card and paired mobile methods. Use last method from settings, but support new pairing and downgrade. ''' QDialog.__init__(self, handler.top_level_window()) self.handler = handler self.txdata = data self.idxs = self.txdata[ 'keycardData'] if self.txdata['confirmationType'] > 1 else '' self.setMinimumWidth(600) self.setWindowTitle(_("Ledger Wallet Authentication")) self.cfg = copy.deepcopy(self.handler.win.wallet.get_keystore().cfg) self.dongle = self.handler.win.wallet.get_keystore().get_client( ).dongle self.ws = None self.pin = '' self.devmode = self.getDevice2FAMode() if self.devmode == 0x11 or self.txdata['confirmationType'] == 1: self.cfg['mode'] = 0 vbox = QVBoxLayout() self.setLayout(vbox) def on_change_mode(idx): if idx < 2 and self.ws: self.ws.stop() self.ws = None self.cfg[ 'mode'] = 0 if self.devmode == 0x11 else idx if idx > 0 else 1 if self.cfg['mode'] > 1 and self.cfg['pair'] and not self.ws: self.req_validation() if self.cfg['mode'] > 0: self.handler.win.wallet.get_keystore().cfg = self.cfg self.handler.win.wallet.save_keystore() self.update_dlg() def add_pairing(): self.do_pairing() def return_pin(): self.pin = self.pintxt.text( ) if self.txdata['confirmationType'] == 1 else self.cardtxt.text() if self.cfg['mode'] == 1: self.pin = ''.join(chr(int(str(i), 16)) for i in self.pin) self.accept() self.modebox = QWidget() modelayout = QHBoxLayout() self.modebox.setLayout(modelayout) modelayout.addWidget(QLabel(_("Method:"))) self.modes = QComboBox() modelayout.addWidget(self.modes, 2) self.addPair = QPushButton(_("Pair")) self.addPair.setMaximumWidth(60) modelayout.addWidget(self.addPair) modelayout.addStretch(1) self.modebox.setMaximumHeight(50) vbox.addWidget(self.modebox) self.populate_modes() self.modes.currentIndexChanged.connect(on_change_mode) self.addPair.clicked.connect(add_pairing) self.helpmsg = QTextEdit() self.helpmsg.setStyleSheet( "QTextEdit { background-color: lightgray; }") self.helpmsg.setReadOnly(True) vbox.addWidget(self.helpmsg) self.pinbox = QWidget() pinlayout = QHBoxLayout() self.pinbox.setLayout(pinlayout) self.pintxt = QLineEdit() self.pintxt.setEchoMode(2) self.pintxt.setMaxLength(4) self.pintxt.returnPressed.connect(return_pin) pinlayout.addWidget(QLabel(_("Enter PIN:"))) pinlayout.addWidget(self.pintxt) pinlayout.addWidget(QLabel(_("NOT DEVICE PIN - see above"))) pinlayout.addStretch(1) self.pinbox.setVisible(self.cfg['mode'] == 0) vbox.addWidget(self.pinbox) self.cardbox = QWidget() card = QVBoxLayout() self.cardbox.setLayout(card) self.addrtext = QTextEdit() self.addrtext.setStyleSheet( "QTextEdit { color:blue; background-color:lightgray; padding:15px 10px; border:none; font-size:20pt; }" ) self.addrtext.setReadOnly(True) self.addrtext.setMaximumHeight(120) card.addWidget(self.addrtext) def pin_changed(s): if len(s) < len(self.idxs): i = self.idxs[len(s)] addr = self.txdata['address'] addr = addr[:i] + '<u><b>' + addr[i:i + 1] + '</u></b>' + addr[i + 1:] self.addrtext.setHtml(str(addr)) else: self.addrtext.setHtml(_("Press Enter")) pin_changed('') cardpin = QHBoxLayout() cardpin.addWidget(QLabel(_("Enter PIN:"))) self.cardtxt = QLineEdit() self.cardtxt.setEchoMode(2) self.cardtxt.setMaxLength(len(self.idxs)) self.cardtxt.textChanged.connect(pin_changed) self.cardtxt.returnPressed.connect(return_pin) cardpin.addWidget(self.cardtxt) cardpin.addWidget(QLabel(_("NOT DEVICE PIN - see above"))) cardpin.addStretch(1) card.addLayout(cardpin) self.cardbox.setVisible(self.cfg['mode'] == 1) vbox.addWidget(self.cardbox) self.pairbox = QWidget() pairlayout = QVBoxLayout() self.pairbox.setLayout(pairlayout) pairhelp = QTextEdit(helpTxt[5]) pairhelp.setStyleSheet("QTextEdit { background-color: lightgray; }") pairhelp.setReadOnly(True) pairlayout.addWidget(pairhelp, 1) self.pairqr = QRCodeWidget() pairlayout.addWidget(self.pairqr, 4) self.pairbox.setVisible(False) vbox.addWidget(self.pairbox) self.update_dlg() if self.cfg['mode'] > 1 and not self.ws: self.req_validation()
from electrum_stratis.i18n import _ fullname = 'TREZOR Wallet' description = _('Provides support for TREZOR hardware wallet') requires = [('trezorlib', 'github.com/trezor/python-trezor')] registers_keystore = ('hardware', 'trezor', _("TREZOR wallet")) available_for = ['qt', 'cmdline']
def on_n(n): n_label.setText(_('From %d cosigners') % n) cw.set_n(n) m_edit.setMaximum(n)
QLabel, SIGNAL) import PyQt4.QtCore as QtCore from electrum_stratis.i18n import _ from electrum_gui.qt.util import * from electrum_stratis.util import print_msg import os, hashlib, websocket, threading, logging, json, copy from electrum_gui.qt.qrcodewidget import QRCodeWidget, QRDialog from btchip.btchip import * DEBUG = False helpTxt = [_("Your Ledger Wallet wants tell you a one-time PIN code.<br><br>" \ "For best security you should unplug your device, open a text editor on another computer, " \ "put your cursor into it, and plug your device into that computer. " \ "It will output a summary of the transaction being signed and a one-time PIN.<br><br>" \ "Verify the transaction summary and type the PIN code here.<br><br>" \ "Before pressing enter, plug the device back into this computer.<br>" ), _("Verify the address below.<br>Type the character from your security card corresponding to the <u><b>BOLD</b></u> character."), _("Waiting for authentication on your mobile phone"), _("Transaction accepted by mobile phone. Waiting for confirmation."), _("Click Pair button to begin pairing a mobile phone."), _("Scan this QR code with your LedgerWallet phone app to pair it with this Ledger device.<br>" "To complete pairing you will need your security card to answer a challenge." ) ] class LedgerAuthDialog(QDialog): def __init__(self, handler, data): '''Ask user for 2nd factor authentication. Support text, security card and paired mobile methods. Use last method from settings, but support new pairing and downgrade.
def on_m(m): m_label.setText(_('Require %d signatures') % m) cw.set_m(m)
from electrum_stratis.wallet import Wallet from electrum_stratis.util import UserCancelled from electrum_stratis.base_wizard import BaseWizard from electrum_stratis.i18n import _ from seed_dialog import SeedLayout, KeysLayout from network_dialog import NetworkChoiceLayout from util import * from password_dialog import PasswordLayout, PW_NEW class GoBack(Exception): pass MSG_GENERATING_WAIT = _( "Electrum is generating your addresses, please wait...") MSG_ENTER_ANYTHING = _("Please enter a seed phrase, a master key, a list of " "Stratis addresses, or a list of private keys") MSG_ENTER_SEED_OR_MPK = _( "Please enter a seed phrase or a master key (xpub or xprv):") MSG_COSIGNER = _("Please enter the master public key of cosigner #%d:") MSG_ENTER_PASSWORD = _("Choose a password to encrypt your wallet keys.") + '\n'\ + _("Leave this field empty if you want to disable encryption.") MSG_RESTORE_PASSPHRASE = \ _("Please enter your seed derivation passphrase. " "Note: this is NOT your encryption password. " "Leave this field empty if you did not use one or are unsure.") class CosignWidget(QWidget): size = 120
from electrum_stratis.i18n import _ fullname = _('Audio MODEM') description = _('Provides support for air-gapped transaction signing.') requires = [('amodem', 'http://github.com/romanz/amodem/')] available_for = ['qt']
def __init__(self, tx, parent, desc, prompt_if_unsaved): '''Transactions in the wallet will show their description. Pass desc to give a description for txs not yet in the wallet. ''' # We want to be a top-level window QDialog.__init__(self, parent=None) # Take a copy; it might get updated in the main window by # e.g. the FX plugin. If this happens during or after a long # sign operation the signatures are lost. self.tx = copy.deepcopy(tx) self.tx.deserialize() self.main_window = parent self.wallet = parent.wallet self.prompt_if_unsaved = prompt_if_unsaved self.saved = False self.desc = desc self.setMinimumWidth(660) self.setWindowTitle(_("Transaction")) vbox = QVBoxLayout() self.setLayout(vbox) vbox.addWidget(QLabel(_("Transaction ID:"))) self.tx_hash_e = ButtonsLineEdit() qr_show = lambda: parent.show_qrcode( str(self.tx_hash_e.text()), 'Transaction ID', parent=self) self.tx_hash_e.addButton(":icons/qrcode.png", qr_show, _("Show as QR code")) self.tx_hash_e.setReadOnly(True) vbox.addWidget(self.tx_hash_e) self.tx_desc = QLabel() vbox.addWidget(self.tx_desc) self.status_label = QLabel() vbox.addWidget(self.status_label) self.date_label = QLabel() vbox.addWidget(self.date_label) self.amount_label = QLabel() vbox.addWidget(self.amount_label) self.fee_label = QLabel() vbox.addWidget(self.fee_label) self.add_io(vbox) vbox.addStretch(1) self.sign_button = b = QPushButton(_("Sign")) b.clicked.connect(self.sign) self.broadcast_button = b = QPushButton(_("Broadcast")) b.clicked.connect(self.do_broadcast) self.save_button = b = QPushButton(_("Save")) b.clicked.connect(self.save) self.cancel_button = b = QPushButton(_("Close")) b.clicked.connect(self.close) b.setDefault(True) self.qr_button = b = QPushButton() b.setIcon(QIcon(":icons/qrcode.png")) b.clicked.connect(self.show_qr) self.copy_button = CopyButton(lambda: str(self.tx), parent.app) # Action buttons self.buttons = [ self.sign_button, self.broadcast_button, self.cancel_button ] # Transaction sharing buttons self.sharing_buttons = [ self.copy_button, self.qr_button, self.save_button ] run_hook('transaction_dialog', self) hbox = QHBoxLayout() hbox.addLayout(Buttons(*self.sharing_buttons)) hbox.addStretch(1) hbox.addLayout(Buttons(*self.buttons)) vbox.addLayout(hbox) self.update()
from electrum_stratis.i18n import _ fullname = _('LabelSync') description = ' '.join([ _("Save your wallet labels on a remote server, and synchronize them across multiple devices where you use Electrum." ), _("Labels, transactions IDs and addresses are encrypted before they are sent to the remote server." ) ]) available_for = ['qt', 'kivy']
class PasswordLayout(object): titles = [_("Enter Password"), _("Change Password"), _("Enter Passphrase")] def __init__(self, wallet, msg, kind, OK_button): self.wallet = wallet self.pw = QLineEdit() self.pw.setEchoMode(2) self.new_pw = QLineEdit() self.new_pw.setEchoMode(2) self.conf_pw = QLineEdit() self.conf_pw.setEchoMode(2) self.kind = kind self.OK_button = OK_button vbox = QVBoxLayout() label = QLabel(msg + "\n") label.setWordWrap(True) grid = QGridLayout() grid.setSpacing(8) grid.setColumnMinimumWidth(0, 150) grid.setColumnMinimumWidth(1, 100) grid.setColumnStretch(1, 1) if kind == PW_PASSPHRASE: vbox.addWidget(label) msgs = [_('Passphrase:'), _('Confirm Passphrase:')] else: logo_grid = QGridLayout() logo_grid.setSpacing(8) logo_grid.setColumnMinimumWidth(0, 70) logo_grid.setColumnStretch(1, 1) logo = QLabel() logo.setAlignment(Qt.AlignCenter) logo_grid.addWidget(logo, 0, 0) logo_grid.addWidget(label, 0, 1, 1, 2) vbox.addLayout(logo_grid) m1 = _('New Password:'******'Password:'******'Confirm Password:'******'Current Password:')), 0, 0) grid.addWidget(self.pw, 0, 1) lockfile = ":icons/lock.png" else: lockfile = ":icons/unlock.png" logo.setPixmap(QPixmap(lockfile).scaledToWidth(36)) grid.addWidget(QLabel(msgs[0]), 1, 0) grid.addWidget(self.new_pw, 1, 1) grid.addWidget(QLabel(msgs[1]), 2, 0) grid.addWidget(self.conf_pw, 2, 1) vbox.addLayout(grid) # Password Strength Label if kind != PW_PASSPHRASE: self.pw_strength = QLabel() grid.addWidget(self.pw_strength, 3, 0, 1, 2) self.new_pw.textChanged.connect(self.pw_changed) def enable_OK(): OK_button.setEnabled(self.new_pw.text() == self.conf_pw.text()) self.new_pw.textChanged.connect(enable_OK) self.conf_pw.textChanged.connect(enable_OK) self.vbox = vbox def title(self): return self.titles[self.kind] def layout(self): return self.vbox def pw_changed(self): password = self.new_pw.text() if password: colors = { "Weak": "Red", "Medium": "Blue", "Strong": "Green", "Very Strong": "Green" } strength = check_password_strength(password) label = (_("Password Strength") + ": " + "<font color=" + colors[strength] + ">" + strength + "</font>") else: label = "" self.pw_strength.setText(label) def old_password(self): if self.kind == PW_CHANGE: return unicode(self.pw.text()) or None return None def new_password(self): pw = unicode(self.new_pw.text()) # Empty passphrases are fine and returned empty. if pw == "" and self.kind != PW_PASSPHRASE: pw = None return pw
from electrum_stratis.i18n import _ fullname = _("Exchange rates") description = _("Exchange rates and currency conversion tools.") available_for = ['qt', 'kivy']
from electrum_stratis.i18n import _ fullname = 'Virtual Keyboard' description = '%s\n%s' % ( _("Add an optional virtual keyboard to the password dialog."), _("Warning: do not use this if it makes you pick a weaker password.")) available_for = ['qt']
def print_qr(): p = QPixmap.grabWindow(qrw.winId()) p.save(filename, 'png') self.show_message(_("QR code saved to file") + " " + filename)
def done_processing(self, dialog, result): dialog.show_message(_("Your labels have been synchronised."))
def copy_to_clipboard(): p = QPixmap.grabWindow(qrw.winId()) p.save(filename, 'png') QApplication.clipboard().setImage(QImage(filename)) self.show_message(_("QR code copied to clipboard"))
from electrum_stratis.i18n import _ fullname = _('Cosigner Pool') description = ' '.join([ _("This plugin facilitates the use of multi-signatures wallets."), _("It sends and receives partially signed transactions from/to your cosigner wallet." ), _("Transactions are encrypted and stored on a remote server.") ]) #requires_wallet_type = ['2of2', '2of3'] available_for = ['qt']
def history_tab_headers(self, headers): if self.show_history(): headers.extend([ '%s ' % self.ccy + _('Amount'), '%s ' % self.ccy + _('Balance') ])
def __init__(self, network, config, wizard=False): self.network = network self.config = config self.protocol = None self.servers = network.get_servers() host, port, protocol, proxy_config, auto_connect = network.get_parameters() if not proxy_config: proxy_config = { "mode":"none", "host":"localhost", "port":"9050"} if not wizard: n = len(network.get_interfaces()) if n: status = _("Blockchain") + ": " + "%d "%(network.get_local_height()) + _("blocks") + ".\n" + _("Getting block headers from %d nodes.")%n else: status = _("Not connected") if network.is_connected(): status += "\n" + _("Server") + ": %s"%(host) else: status += "\n" + _("Disconnected from server") else: status = _("Please choose a server.") + "\n" + _("Press 'Next' if you are offline.") vbox = QVBoxLayout() hbox = QHBoxLayout() l = QLabel() l.setPixmap(QPixmap(":icons/network.png")) hbox.addStretch(10) hbox.addWidget(l) hbox.addWidget(QLabel(status)) hbox.addStretch(50) msg = _("Electrum sends your wallet addresses to a single server, in order to receive your transaction history.") + "\n\n" \ + _("In addition, Electrum connects to several nodes in order to download block headers and find out the longest blockchain.") + " " \ + _("This blockchain is used to verify the transactions sent by the address server.") hbox.addWidget(HelpButton(msg)) vbox.addLayout(hbox) vbox.addSpacing(15) # grid layout grid = QGridLayout() grid.setSpacing(8) vbox.addLayout(grid) # server self.server_host = QLineEdit() self.server_host.setFixedWidth(200) self.server_port = QLineEdit() self.server_port.setFixedWidth(60) grid.addWidget(QLabel(_('Server') + ':'), 0, 0) grid.addWidget(self.server_host, 0, 1, 1, 2) grid.addWidget(self.server_port, 0, 3) # use SSL self.ssl_cb = QCheckBox(_('Use SSL')) self.ssl_cb.setChecked(auto_connect) grid.addWidget(self.ssl_cb, 3, 1, 1, 3) self.ssl_cb.stateChanged.connect(self.change_protocol) # auto connect self.autoconnect_cb = QCheckBox(_('Select server automatically')) self.autoconnect_cb.setChecked(auto_connect) grid.addWidget(self.autoconnect_cb, 1, 1, 1, 3) self.autoconnect_cb.setEnabled(self.config.is_modifiable('auto_connect')) msg = _("If auto-connect is enabled, Electrum will always use a server that is on the longest blockchain.") + "\n" \ + _("If it is disabled, Electrum will warn you if your server is lagging.") self.autoconnect_cb.setToolTip(msg) label = _('Active Servers') if network.is_connected() else _('Default Servers') self.servers_list_widget = QTreeWidget() self.servers_list_widget.setHeaderLabels( [ label, _('Limit') ] ) self.servers_list_widget.setMaximumHeight(150) self.servers_list_widget.setColumnWidth(0, 240) self.change_server(host, protocol) self.set_protocol(protocol) self.servers_list_widget.connect(self.servers_list_widget, SIGNAL('currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)'), lambda x,y: self.server_changed(x)) grid.addWidget(self.servers_list_widget, 2, 1, 1, 3) def enable_set_server(): if config.is_modifiable('server'): enabled = not self.autoconnect_cb.isChecked() self.server_host.setEnabled(enabled) self.server_port.setEnabled(enabled) self.servers_list_widget.setEnabled(enabled) else: for w in [self.autoconnect_cb, self.server_host, self.server_port, self.ssl_cb, self.servers_list_widget]: w.setEnabled(False) self.autoconnect_cb.clicked.connect(enable_set_server) enable_set_server() # proxy setting self.proxy_mode = QComboBox() self.proxy_host = QLineEdit() self.proxy_host.setFixedWidth(200) self.proxy_port = QLineEdit() self.proxy_port.setFixedWidth(60) self.proxy_mode.addItems(['NONE', 'SOCKS4', 'SOCKS5', 'HTTP']) def check_for_disable(index = False): if self.config.is_modifiable('proxy'): if self.proxy_mode.currentText() != 'NONE': self.proxy_host.setEnabled(True) self.proxy_port.setEnabled(True) else: self.proxy_host.setEnabled(False) self.proxy_port.setEnabled(False) else: for w in [self.proxy_host, self.proxy_port, self.proxy_mode]: w.setEnabled(False) check_for_disable() self.proxy_mode.connect(self.proxy_mode, SIGNAL('currentIndexChanged(int)'), check_for_disable) self.proxy_mode.setCurrentIndex(self.proxy_mode.findText(str(proxy_config.get("mode").upper()))) self.proxy_host.setText(proxy_config.get("host")) self.proxy_port.setText(proxy_config.get("port")) grid.addWidget(QLabel(_('Proxy') + ':'), 4, 0) grid.addWidget(self.proxy_mode, 4, 1) grid.addWidget(self.proxy_host, 4, 2) grid.addWidget(self.proxy_port, 4, 3) self.layout_ = vbox
def update(self): desc = self.desc base_unit = self.main_window.base_unit() format_amount = self.main_window.format_amount tx_hash, status, label, can_broadcast, can_rbf, amount, fee, height, conf, timestamp, exp_n = self.wallet.get_tx_info( self.tx) self.broadcast_button.setEnabled(can_broadcast) self.sign_button.setEnabled(self.wallet.can_sign(self.tx)) self.tx_hash_e.setText(tx_hash or _('Unknown')) if desc is None: self.tx_desc.hide() else: self.tx_desc.setText(_("Description") + ': ' + desc) self.tx_desc.show() self.status_label.setText(_('Status:') + ' ' + status) if timestamp: time_str = datetime.datetime.fromtimestamp(timestamp).isoformat( ' ')[:-3] self.date_label.setText(_("Date: %s") % time_str) self.date_label.show() elif exp_n: text = '%d blocks' % (exp_n) if exp_n > 0 else _( 'unknown (low fee)') self.date_label.setText( _('Expected confirmation time') + ': ' + text) self.date_label.show() else: self.date_label.hide() if amount is None: amount_str = _("Transaction unrelated to your wallet") elif amount > 0: amount_str = _("Amount received:" ) + ' %s' % format_amount(amount) + ' ' + base_unit else: amount_str = _("Amount sent:" ) + ' %s' % format_amount(-amount) + ' ' + base_unit fee_str = _("Transaction fee") + ': %s' % (format_amount( fee) + ' ' + base_unit if fee is not None else _('unknown')) if fee is not None: size = self.tx.estimated_size() fee_str += ' ( %d bytes @ %s ' % ( size, format_amount(fee * 1000 / size) ) + base_unit + '/kB, %.0d sat/byte )' % (fee / size) self.amount_label.setText(amount_str) self.fee_label.setText(fee_str) run_hook('transaction_dialog_update', self)
import threading from PyQt4.Qt import Qt from PyQt4.Qt import QGridLayout, QInputDialog, QPushButton from PyQt4.Qt import QVBoxLayout, QLabel, SIGNAL from electrum_stratis_gui.qt.util import * from .plugin import TIM_NEW, TIM_RECOVER, TIM_MNEMONIC from ..hw_wallet.qt import QtHandlerBase, QtPluginBase from electrum_stratis.i18n import _ from electrum_stratis.plugins import hook, DeviceMgr from electrum_stratis.util import PrintError, UserCancelled from electrum_stratis.wallet import Wallet, Standard_Wallet PASSPHRASE_HELP_SHORT = _( "Passphrases allow you to access new wallets, each " "hidden behind a particular case-sensitive passphrase.") PASSPHRASE_HELP = PASSPHRASE_HELP_SHORT + " " + _( "You need to create a separate Electrum wallet for each passphrase " "you use as they each generate different addresses. Changing " "your passphrase does not lose other wallets, each is still " "accessible behind its own passphrase.") RECOMMEND_PIN = _( "You should enable PIN protection. Your PIN is the only protection " "for your stratiss if your device is lost or stolen.") PASSPHRASE_NOT_PIN = _( "If you forget a passphrase you will be unable to access any " "stratiss in the wallet behind it. A passphrase is not a PIN. " "Only change this if you are sure you understand it.") CHARACTER_RECOVERY = ( "Use the recovery cipher shown on your device to input your seed words. "
def add_io(self, vbox): if self.tx.locktime > 0: vbox.addWidget(QLabel("LockTime: %d\n" % self.tx.locktime)) vbox.addWidget(QLabel(_("Inputs") + ' (%d)' % len(self.tx.inputs()))) ext = QTextCharFormat() rec = QTextCharFormat() rec.setBackground(QBrush(QColor("lightgreen"))) rec.setToolTip(_("Wallet receive address")) chg = QTextCharFormat() chg.setBackground(QBrush(QColor("yellow"))) chg.setToolTip(_("Wallet change address")) def text_format(addr): if self.wallet.is_mine(addr): return chg if self.wallet.is_change(addr) else rec return ext def format_amount(amt): return self.main_window.format_amount(amt, whitespaces=True) i_text = QTextEdit() i_text.setFont(QFont(MONOSPACE_FONT)) i_text.setReadOnly(True) i_text.setMaximumHeight(100) cursor = i_text.textCursor() for x in self.tx.inputs(): if x.get('is_coinbase'): cursor.insertText('coinbase') else: prevout_hash = x.get('prevout_hash') prevout_n = x.get('prevout_n') cursor.insertText(prevout_hash[0:8] + '...', ext) cursor.insertText(prevout_hash[-8:] + ":%-4d " % prevout_n, ext) addr = x.get('address') if addr == "(pubkey)": _addr = self.wallet.find_pay_to_pubkey_address( prevout_hash, prevout_n) if _addr: addr = _addr if addr is None: addr = _('unknown') cursor.insertText(addr, text_format(addr)) if x.get('value'): cursor.insertText(format_amount(x['value']), ext) cursor.insertBlock() vbox.addWidget(i_text) vbox.addWidget(QLabel(_("Outputs") + ' (%d)' % len(self.tx.outputs()))) o_text = QTextEdit() o_text.setFont(QFont(MONOSPACE_FONT)) o_text.setReadOnly(True) o_text.setMaximumHeight(100) cursor = o_text.textCursor() for addr, v in self.tx.get_outputs(): cursor.insertText(addr, text_format(addr)) if v is not None: cursor.insertText('\t', ext) cursor.insertText(format_amount(v), ext) cursor.insertBlock() vbox.addWidget(o_text)
def __init__(self, window, plugin, keystore, device_id): title = _("%s Settings") % plugin.device super(SettingsDialog, self).__init__(window, title) self.setMaximumWidth(540) devmgr = plugin.device_manager() config = devmgr.config handler = keystore.handler thread = keystore.thread hs_rows, hs_cols = (64, 128) def invoke_client(method, *args, **kw_args): unpair_after = kw_args.pop('unpair_after', False) def task(): client = devmgr.client_by_id(device_id) if not client: raise RuntimeError("Device not connected") if method: getattr(client, method)(*args, **kw_args) if unpair_after: devmgr.unpair_id(device_id) return client.features thread.add(task, on_success=update) def update(features): self.features = features set_label_enabled() bl_hash = features.bootloader_hash.encode('hex') bl_hash = "\n".join([bl_hash[:32], bl_hash[32:]]) noyes = [_("No"), _("Yes")] endis = [_("Enable Passphrases"), _("Disable Passphrases")] disen = [_("Disabled"), _("Enabled")] setchange = [_("Set a PIN"), _("Change PIN")] version = "%d.%d.%d" % (features.major_version, features.minor_version, features.patch_version) coins = ", ".join(coin.coin_name for coin in features.coins) device_label.setText(features.label) pin_set_label.setText(noyes[features.pin_protection]) passphrases_label.setText(disen[features.passphrase_protection]) bl_hash_label.setText(bl_hash) label_edit.setText(features.label) device_id_label.setText(features.device_id) initialized_label.setText(noyes[features.initialized]) version_label.setText(version) coins_label.setText(coins) clear_pin_button.setVisible(features.pin_protection) clear_pin_warning.setVisible(features.pin_protection) pin_button.setText(setchange[features.pin_protection]) pin_msg.setVisible(not features.pin_protection) passphrase_button.setText(endis[features.passphrase_protection]) language_label.setText(features.language) def set_label_enabled(): label_apply.setEnabled(label_edit.text() != self.features.label) def rename(): invoke_client('change_label', unicode(label_edit.text())) def toggle_passphrase(): title = _("Confirm Toggle Passphrase Protection") currently_enabled = self.features.passphrase_protection if currently_enabled: msg = _("After disabling passphrases, you can only pair this " "Electrum wallet if it had an empty passphrase. " "If its passphrase was not empty, you will need to " "create a new wallet with the install wizard. You " "can use this wallet again at any time by re-enabling " "passphrases and entering its passphrase.") else: msg = _("Your current Electrum wallet can only be used with " "an empty passphrase. You must create a separate " "wallet with the install wizard for other passphrases " "as each one generates a new set of addresses.") msg += "\n\n" + _("Are you sure you want to proceed?") if not self.question(msg, title=title): return invoke_client('toggle_passphrase', unpair_after=currently_enabled) def change_homescreen(): from PIL import Image # FIXME dialog = QFileDialog(self, _("Choose Homescreen")) filename = dialog.getOpenFileName() if filename: im = Image.open(str(filename)) if im.size != (hs_cols, hs_rows): raise Exception('Image must be 64 x 128 pixels') im = im.convert('1') pix = im.load() img = '' for j in range(hs_rows): for i in range(hs_cols): img += '1' if pix[i, j] else '0' img = ''.join( chr(int(img[i:i + 8], 2)) for i in range(0, len(img), 8)) invoke_client('change_homescreen', img) def clear_homescreen(): invoke_client('change_homescreen', '\x00') def set_pin(): invoke_client('set_pin', remove=False) def clear_pin(): invoke_client('set_pin', remove=True) def wipe_device(): if wallet and sum(wallet.get_balance()): title = _("Confirm Device Wipe") msg = _("Are you SURE you want to wipe the device?\n" "Your wallet still has stratiss in it!") if not self.question( msg, title=title, icon=QMessageBox.Critical): return invoke_client('wipe_device', unpair_after=True) def slider_moved(): mins = timeout_slider.sliderPosition() timeout_minutes.setText(_("%2d minutes") % mins) def slider_released(): config.set_session_timeout(timeout_slider.sliderPosition() * 60) # Information tab info_tab = QWidget() info_layout = QVBoxLayout(info_tab) info_glayout = QGridLayout() info_glayout.setColumnStretch(2, 1) device_label = QLabel() pin_set_label = QLabel() passphrases_label = QLabel() version_label = QLabel() device_id_label = QLabel() bl_hash_label = QLabel() bl_hash_label.setWordWrap(True) coins_label = QLabel() coins_label.setWordWrap(True) language_label = QLabel() initialized_label = QLabel() rows = [ (_("Device Label"), device_label), (_("PIN set"), pin_set_label), (_("Passphrases"), passphrases_label), (_("Firmware Version"), version_label), (_("Device ID"), device_id_label), (_("Bootloader Hash"), bl_hash_label), (_("Supported Coins"), coins_label), (_("Language"), language_label), (_("Initialized"), initialized_label), ] for row_num, (label, widget) in enumerate(rows): info_glayout.addWidget(QLabel(label), row_num, 0) info_glayout.addWidget(widget, row_num, 1) info_layout.addLayout(info_glayout) # Settings tab settings_tab = QWidget() settings_layout = QVBoxLayout(settings_tab) settings_glayout = QGridLayout() # Settings tab - Label label_msg = QLabel( _("Name this %s. If you have mutiple devices " "their labels help distinguish them.") % plugin.device) label_msg.setWordWrap(True) label_label = QLabel(_("Device Label")) label_edit = QLineEdit() label_edit.setMinimumWidth(150) label_edit.setMaxLength(plugin.MAX_LABEL_LEN) label_apply = QPushButton(_("Apply")) label_apply.clicked.connect(rename) label_edit.textChanged.connect(set_label_enabled) settings_glayout.addWidget(label_label, 0, 0) settings_glayout.addWidget(label_edit, 0, 1, 1, 2) settings_glayout.addWidget(label_apply, 0, 3) settings_glayout.addWidget(label_msg, 1, 1, 1, -1) # Settings tab - PIN pin_label = QLabel(_("PIN Protection")) pin_button = QPushButton() pin_button.clicked.connect(set_pin) settings_glayout.addWidget(pin_label, 2, 0) settings_glayout.addWidget(pin_button, 2, 1) pin_msg = QLabel( _("PIN protection is strongly recommended. " "A PIN is your only protection against someone " "stealing your stratiss if they obtain physical " "access to your %s.") % plugin.device) pin_msg.setWordWrap(True) pin_msg.setStyleSheet("color: red") settings_glayout.addWidget(pin_msg, 3, 1, 1, -1) # Settings tab - Homescreen if plugin.device != 'KeepKey': # Not yet supported by KK firmware homescreen_layout = QHBoxLayout() homescreen_label = QLabel(_("Homescreen")) homescreen_change_button = QPushButton(_("Change...")) homescreen_clear_button = QPushButton(_("Reset")) homescreen_change_button.clicked.connect(change_homescreen) homescreen_clear_button.clicked.connect(clear_homescreen) homescreen_msg = QLabel( _("You can set the homescreen on your " "device to personalize it. You must " "choose a %d x %d monochrome black and " "white image.") % (hs_rows, hs_cols)) homescreen_msg.setWordWrap(True) settings_glayout.addWidget(homescreen_label, 4, 0) settings_glayout.addWidget(homescreen_change_button, 4, 1) settings_glayout.addWidget(homescreen_clear_button, 4, 2) settings_glayout.addWidget(homescreen_msg, 5, 1, 1, -1) # Settings tab - Session Timeout timeout_label = QLabel(_("Session Timeout")) timeout_minutes = QLabel() timeout_slider = QSlider(Qt.Horizontal) timeout_slider.setRange(1, 60) timeout_slider.setSingleStep(1) timeout_slider.setTickInterval(5) timeout_slider.setTickPosition(QSlider.TicksBelow) timeout_slider.setTracking(True) timeout_msg = QLabel( _("Clear the session after the specified period " "of inactivity. Once a session has timed out, " "your PIN and passphrase (if enabled) must be " "re-entered to use the device.")) timeout_msg.setWordWrap(True) timeout_slider.setSliderPosition(config.get_session_timeout() // 60) slider_moved() timeout_slider.valueChanged.connect(slider_moved) timeout_slider.sliderReleased.connect(slider_released) settings_glayout.addWidget(timeout_label, 6, 0) settings_glayout.addWidget(timeout_slider, 6, 1, 1, 3) settings_glayout.addWidget(timeout_minutes, 6, 4) settings_glayout.addWidget(timeout_msg, 7, 1, 1, -1) settings_layout.addLayout(settings_glayout) settings_layout.addStretch(1) # Advanced tab advanced_tab = QWidget() advanced_layout = QVBoxLayout(advanced_tab) advanced_glayout = QGridLayout() # Advanced tab - clear PIN clear_pin_button = QPushButton(_("Disable PIN")) clear_pin_button.clicked.connect(clear_pin) clear_pin_warning = QLabel( _("If you disable your PIN, anyone with physical access to your " "%s device can spend your stratiss.") % plugin.device) clear_pin_warning.setWordWrap(True) clear_pin_warning.setStyleSheet("color: red") advanced_glayout.addWidget(clear_pin_button, 0, 2) advanced_glayout.addWidget(clear_pin_warning, 1, 0, 1, 5) # Advanced tab - toggle passphrase protection passphrase_button = QPushButton() passphrase_button.clicked.connect(toggle_passphrase) passphrase_msg = WWLabel(PASSPHRASE_HELP) passphrase_warning = WWLabel(PASSPHRASE_NOT_PIN) passphrase_warning.setStyleSheet("color: red") advanced_glayout.addWidget(passphrase_button, 3, 2) advanced_glayout.addWidget(passphrase_msg, 4, 0, 1, 5) advanced_glayout.addWidget(passphrase_warning, 5, 0, 1, 5) # Advanced tab - wipe device wipe_device_button = QPushButton(_("Wipe Device")) wipe_device_button.clicked.connect(wipe_device) wipe_device_msg = QLabel( _("Wipe the device, removing all data from it. The firmware " "is left unchanged.")) wipe_device_msg.setWordWrap(True) wipe_device_warning = QLabel( _("Only wipe a device if you have the recovery seed written down " "and the device wallet(s) are empty, otherwise the stratiss " "will be lost forever.")) wipe_device_warning.setWordWrap(True) wipe_device_warning.setStyleSheet("color: red") advanced_glayout.addWidget(wipe_device_button, 6, 2) advanced_glayout.addWidget(wipe_device_msg, 7, 0, 1, 5) advanced_glayout.addWidget(wipe_device_warning, 8, 0, 1, 5) advanced_layout.addLayout(advanced_glayout) advanced_layout.addStretch(1) tabs = QTabWidget(self) tabs.addTab(info_tab, _("Information")) tabs.addTab(settings_tab, _("Settings")) tabs.addTab(advanced_tab, _("Advanced")) dialog_vbox = QVBoxLayout(self) dialog_vbox.addWidget(tabs) dialog_vbox.addLayout(Buttons(CloseButton(self))) # Update information invoke_client(None)
def slider_moved(): mins = timeout_slider.sliderPosition() timeout_minutes.setText(_("%2d minutes") % mins)