def create_status_bar(self, parent): b = StatusBarButton(read_QIcon('revealer.png'), "Revealer " + _("secret backup utility"), partial(self.setup_dialog, parent)) parent.addPermanentWidget(b)
def show_critical(self, msg, parent=None, title=None): return self.msg_box(QMessageBox.Critical, parent, title or _('Critical Error'), msg)
def addCopyButton(self, app): self.app = app self.addButton(":icons/copy.png", self.on_copy, _("Copy to clipboard"))
def __init__(self, dialog, label=None): QPushButton.__init__(self, label or _("OK")) self.clicked.connect(dialog.accept) self.setDefault(True)
def show_warning(self, msg, parent=None, title=None): return self.msg_box(QMessageBox.Warning, parent, title or _('Warning'), msg)
else: MONOSPACE_FONT = 'monospace' dialogs = [] from electrum_xzc.paymentrequest import PR_UNPAID, PR_PAID, PR_EXPIRED pr_icons = { PR_UNPAID:":icons/unpaid.png", PR_PAID:":icons/confirmed.png", PR_EXPIRED:":icons/expired.png" } pr_tooltips = { PR_UNPAID:_('Pending'), PR_PAID:_('Paid'), PR_EXPIRED:_('Expired') } expiration_values = [ (_('1 hour'), 60*60), (_('1 day'), 24*60*60), (_('1 week'), 7*24*60*60), (_('Never'), None) ] class Timer(QThread): stopped = False timer_signal = pyqtSignal()
def __init__(self, text_getter, app): QPushButton.__init__(self, _("Copy")) self.clicked.connect(lambda: app.clipboard().setText(text_getter()))
def decrypt_message(self, sequence, message, password): raise RuntimeError( _('Encryption and decryption are not implemented by %s') % self.device)
from electrum_xzc.i18n import _ fullname = 'KeepKey' description = _('Provides support for KeepKey hardware wallet') requires = [('keepkeylib', 'github.com/keepkey/python-keepkey')] registers_keystore = ('hardware', 'keepkey', _("KeepKey wallet")) available_for = ['qt', 'cmdline']
def change_label(self, label): with self.run_flow(_("Confirm the new label on your {} device")): trezorlib.device.apply_settings(self.client, label=label)
def change_homescreen(self, homescreen): with self.run_flow( _("Confirm on your {} device to change your home screen")): trezorlib.device.apply_settings(self.client, homescreen=homescreen)
from electrum_xzc.i18n import _ from electrum_xzc.util import UserCancelled, UserFacingException from electrum_xzc.keystore import bip39_normalize_passphrase from electrum_xzc.bip32 import BIP32Node, convert_bip32_path_to_list_of_uint32 as parse_path from electrum_xzc.logging import Logger from electrum_xzc.plugins.hw_wallet.plugin import OutdatedHwFirmwareException from trezorlib.client import TrezorClient from trezorlib.exceptions import TrezorFailure, Cancelled, OutdatedFirmwareError from trezorlib.messages import WordRequestType, FailureType, RecoveryDeviceType import trezorlib.btc import trezorlib.device MESSAGES = { 3: _("Confirm the transaction output on your {} device"), 4: _("Confirm internal entropy on your {} device to begin"), 5: _("Write down the seed word shown on your {}"), 6: _("Confirm on your {} that you want to wipe it clean"), 7: _("Confirm on your {} device the message to sign"), 8: _("Confirm the total amount spent and the transaction fee on your {} device" ), 10: _("Confirm wallet address on your {} device"), 14: _("Choose on your {} device where to enter your passphrase"),
def setup_dialog(self, window): self.wallet = window.parent().wallet self.update_wallet_name(self.wallet) self.user_input = False self.d = WindowModalDialog(window, "Setup Dialog") self.d.setMinimumWidth(500) self.d.setMinimumHeight(210) self.d.setMaximumHeight(320) self.d.setContentsMargins(11, 11, 1, 1) self.hbox = QHBoxLayout(self.d) vbox = QVBoxLayout() logo = QLabel() self.hbox.addWidget(logo) logo.setPixmap(QPixmap(icon_path('revealer.png'))) logo.setAlignment(Qt.AlignLeft) self.hbox.addSpacing(16) vbox.addWidget( WWLabel( "<b>" + _("Revealer Secret Backup Plugin") + "</b><br>" + _("To encrypt your backup, first we need to load some noise.") + "<br/>")) vbox.addSpacing(7) bcreate = QPushButton(_("Create a new Revealer")) bcreate.setMaximumWidth(181) bcreate.setDefault(True) vbox.addWidget(bcreate, Qt.AlignCenter) self.load_noise = ScanQRTextEdit() self.load_noise.setTabChangesFocus(True) self.load_noise.textChanged.connect(self.on_edit) self.load_noise.setMaximumHeight(33) self.hbox.addLayout(vbox) vbox.addWidget( WWLabel( _("or type an existing revealer code below and click 'next':")) ) vbox.addWidget(self.load_noise) vbox.addSpacing(3) self.next_button = QPushButton(_("Next"), self.d) self.next_button.setEnabled(False) vbox.addLayout(Buttons(self.next_button)) self.next_button.clicked.connect(self.d.close) self.next_button.clicked.connect( partial(self.cypherseed_dialog, window)) vbox.addWidget( QLabel("<b>" + _("Warning") + "</b>: " + _( "Each revealer should be used only once." ) + "<br>" + _( "more information at <a href=\"https://revealer.cc/faq\">https://revealer.cc/faq</a>" ))) def mk_digital(): try: self.make_digital(self.d) except Exception: self.logger.exception('') else: self.cypherseed_dialog(window) bcreate.clicked.connect(mk_digital) return bool(self.d.exec_())
def settings_widget(self, window): return EnterButton(_('Printer Calibration'), partial(self.calibration_dialog, window))
def sign_message(self, sequence, message, password): sig = None try: message = message.encode('utf8') inputPath = self.get_derivation() + "/%d/%d" % sequence msg_hash = Hash(msg_magic(message)) inputHash = to_hexstr(msg_hash) hasharray = [] hasharray.append({'hash': inputHash, 'keypath': inputPath}) hasharray = json.dumps(hasharray) msg = b'{"sign":{"meta":"sign message", "data":%s}}' % hasharray.encode( 'utf8') dbb_client = self.plugin.get_client(self) if not dbb_client.is_paired(): raise Exception("Could not sign message.") reply = dbb_client.hid_send_encrypt(msg) self.handler.show_message(_("Signing message ...\r\n\r\n" \ "To continue, touch the Digital Bitbox's blinking light for 3 seconds.\r\n\r\n" \ "To cancel, briefly touch the blinking light or wait for the timeout.")) reply = dbb_client.hid_send_encrypt( msg ) # Send twice, first returns an echo for smart verification (not implemented) self.handler.finished() if 'error' in reply: raise Exception(reply['error']['message']) if 'sign' not in reply: raise Exception("Could not sign message.") if 'recid' in reply['sign'][0]: # firmware > v2.1.1 sig = bytes([27 + int(reply['sign'][0]['recid'], 16) + 4 ]) + binascii.unhexlify(reply['sign'][0]['sig']) pk, compressed = pubkey_from_signature(sig, msg_hash) pk = point_to_ser(pk.pubkey.point, compressed) addr = public_key_to_p2pkh(pk) if verify_message(addr, sig, message) is False: raise Exception("Could not sign message") elif 'pubkey' in reply['sign'][0]: # firmware <= v2.1.1 for i in range(4): sig = bytes([27 + i + 4]) + binascii.unhexlify( reply['sign'][0]['sig']) try: addr = public_key_to_p2pkh( binascii.unhexlify(reply['sign'][0]['pubkey'])) if verify_message(addr, sig, message): break except Exception: continue else: raise Exception("Could not sign message") except BaseException as e: self.give_error(e) return sig
class WalletMNsModel(QAbstractTableModel): '''Model for wallet DIP3 masternodes.''' ALIAS = 0 STATE = 1 KEYS = 2 SERVICE = 3 PROTX_HASH = 4 TOTAL_FIELDS = 5 filterColumns = [ALIAS, SERVICE, PROTX_HASH] STATE_LOADING = 'Loading' STATE_UNREGISTERED = 'Unregistered' STATE_VALID = 'Valid' STATE_BANNED = 'PoSe Banned' STATE_REMOVED = 'Removed' STATES_TXT = { STATE_LOADING: _('Loading'), STATE_UNREGISTERED: _('Unregistered'), STATE_VALID: _('Valid'), STATE_BANNED: _('PoSe Banned'), STATE_REMOVED: _('Removed'), } def __init__(self, manager, mn_list, gui, row_h): super(WalletMNsModel, self).__init__() self.gui = gui self.manager = manager self.mn_list = mn_list sz = row_h - 10 mode = Qt.SmoothTransformation imgfile = icon_path('dip3_unregistered.png') self.icon_unregistered = QPixmap(imgfile).scaledToWidth(sz, mode=mode) imgfile = icon_path('dip3_valid.png') self.icon_valid = QPixmap(imgfile).scaledToWidth(sz, mode=mode) imgfile = icon_path('dip3_banned.png') self.icon_banned = QPixmap(imgfile).scaledToWidth(sz, mode=mode) imgfile = icon_path('dip3_removed.png') self.icon_removed = QPixmap(imgfile).scaledToWidth(sz, mode=mode) imgfile = icon_path('dip3_own_op.png') self.icon_own_op = QPixmap(imgfile).scaledToWidth(sz, mode=mode) imgfile = icon_path('dip3_own.png') self.icon_own = QPixmap(imgfile).scaledToWidth(sz, mode=mode) imgfile = icon_path('dip3_op.png') self.icon_op = QPixmap(imgfile).scaledToWidth(sz, mode=mode) headers = [ { Qt.DisplayRole: _('Alias') }, { Qt.DisplayRole: _('State') }, { Qt.DisplayRole: _('Keys') }, { Qt.DisplayRole: _('Service') }, { Qt.DisplayRole: _('ProRegTx hash') }, ] for d in headers: d[Qt.EditRole] = d[Qt.DisplayRole] self.headers = headers self.mns = [] self.mns_states = {} self.row_count = 0 def reload_data(self): self.beginResetModel() self.mns = sorted(self.manager.mns.values(), key=lambda x: x.alias) protx_mns = { h: mn.as_dict() for h, mn in self.mn_list.protx_mns.items() } for mn in self.mns: h = mn.protx_hash if not h: self.mns_states[mn.alias] = self.STATE_UNREGISTERED continue if not self.mn_list or self.mn_list.protx_loading: self.mns_states[mn.alias] = self.STATE_LOADING continue protx_mn = protx_mns.get(h) if protx_mn: if protx_mn['isValid']: self.mns_states[mn.alias] = self.STATE_VALID else: self.mns_states[mn.alias] = self.STATE_BANNED else: conf = self.manager.wallet.get_tx_height(h).conf if conf > 0: self.mns_states[mn.alias] = self.STATE_REMOVED else: self.mns_states[mn.alias] = self.STATE_UNREGISTERED self.row_count = len(self.mns) self.endResetModel() def columnCount(self, parent=QModelIndex()): return self.TOTAL_FIELDS def rowCount(self, parent=QModelIndex()): return self.row_count def headerData(self, section, orientation, role=Qt.DisplayRole): if role not in [Qt.DisplayRole]: return None if orientation != Qt.Horizontal: return None dataItem = self.headers[section] data = dataItem.get(role) if dataItem else None return QVariant(data) def data(self, index, role=Qt.DisplayRole): data = None if not index.isValid(): return None mn = self.mns[index.row()] i = index.column() if i == self.ALIAS and role in (Qt.DisplayRole, Qt.EditRole): data = mn.alias elif i == self.STATE: if role == Qt.DecorationRole: state = self.mns_states.get(mn.alias) if state in [self.STATE_UNREGISTERED, self.STATE_LOADING]: data = self.icon_unregistered elif state == self.STATE_VALID: data = self.icon_valid elif state == self.STATE_BANNED: data = self.icon_banned elif state == self.STATE_REMOVED: data = self.icon_removed else: data = None elif role == Qt.ToolTipRole: data = self.STATES_TXT.get(self.mns_states.get(mn.alias), 'Unknown') elif i == self.KEYS: if role == Qt.DecorationRole: if mn.is_owned and mn.is_operated: data = self.icon_own_op elif mn.is_owned and not mn.is_operated: data = self.icon_own elif not mn.is_owned and mn.is_operated: data = self.icon_op else: data = None elif role == Qt.ToolTipRole: if mn.is_owned and mn.is_operated: data = _('Owner and Operator private keys') elif mn.is_owned and not mn.is_operated: data = _('Owner key') elif not mn.is_owned and mn.is_operated: data = _('Operator privete key') else: data = None elif i == self.SERVICE and role == Qt.DisplayRole: data = str(mn.service) elif i == self.PROTX_HASH and role == Qt.DisplayRole: data = mn.protx_hash return QVariant(data) def reload_alias(self, alias): idx = self.match(self.index(0, 0), Qt.DisplayRole, alias, 1, Qt.MatchExactly) if not idx: return idx = idx[0] last_col_idx = idx.sibling(idx.row(), self.TOTAL_FIELDS - 1) self.mns = sorted(self.manager.mns.values(), key=lambda x: x.alias) mn = self.manager.mns[alias] if mn and not mn.protx_hash: self.mns_states[alias] = self.STATE_UNREGISTERED self.dataChanged.emit(idx, last_col_idx) def setData(self, idx, value, role): if role != Qt.EditRole: return False new_alias = value.strip() alias = self.data(idx, Qt.DisplayRole).value() if new_alias == alias: return False try: self.manager.rename_mn(alias, new_alias) self.mns_states[new_alias] = self.mns_states[alias] del self.mns_states[alias] self.layoutAboutToBeChanged.emit() self.mns = sorted(self.manager.mns.values(), key=lambda x: x.alias) new_row = [ e[0] for e in enumerate(self.mns) if e[1].alias == new_alias ][0] new_idx = idx.sibling(new_row, 0) self.layoutChanged.emit() self.dataChanged.emit(new_idx, new_idx) except ProTxManagerExc as e: self.gui.show_error(str(e)) return False return True def flags(self, idx): col = idx.column() if col != WalletMNsModel.ALIAS: return super(WalletMNsModel, self).flags(idx) else: return super(WalletMNsModel, self).flags(idx) | Qt.ItemIsEditable
def sign_transaction(self, tx, password): if tx.is_complete(): return try: p2pkhTransaction = True derivations = self.get_tx_derivations(tx) inputhasharray = [] hasharray = [] pubkeyarray = [] # Build hasharray from inputs for i, txin in enumerate(tx.inputs()): if txin['type'] == 'coinbase': self.give_error( "Coinbase not supported") # should never happen if txin['type'] != 'p2pkh': p2pkhTransaction = False for x_pubkey in txin['x_pubkeys']: if x_pubkey in derivations: index = derivations.get(x_pubkey) inputPath = "%s/%d/%d" % (self.get_derivation(), index[0], index[1]) inputHash = Hash( binascii.unhexlify(tx.serialize_preimage(i))) hasharray_i = { 'hash': to_hexstr(inputHash), 'keypath': inputPath } hasharray.append(hasharray_i) inputhasharray.append(inputHash) break else: self.give_error("No matching x_key for sign_transaction" ) # should never happen # Build pubkeyarray from outputs for _type, address, amount in tx.outputs(): assert _type == TYPE_ADDRESS info = tx.output_info.get(address) if info is not None: index, xpubs, m = info changePath = self.get_derivation() + "/%d/%d" % index changePubkey = self.derive_pubkey(index[0], index[1]) pubkeyarray_i = { 'pubkey': changePubkey, 'keypath': changePath } pubkeyarray.append(pubkeyarray_i) # Special serialization of the unsigned transaction for # the mobile verification app. # At the moment, verification only works for p2pkh transactions. if p2pkhTransaction: class CustomTXSerialization(Transaction): @classmethod def input_script(self, txin, estimate_size=False): if txin['type'] == 'p2pkh': return Transaction.get_preimage_script(txin) if txin['type'] == 'p2sh': # Multisig verification has partial support, but is disabled. This is the # expected serialization though, so we leave it here until we activate it. return '00' + push_script( Transaction.get_preimage_script(txin)) raise Exception("unsupported type %s" % txin['type']) tx_dbb_serialized = CustomTXSerialization( tx.serialize()).serialize() else: # We only need this for the signing echo / verification. tx_dbb_serialized = None # Build sign command dbb_signatures = [] steps = math.ceil(1.0 * len(hasharray) / self.maxInputs) for step in range(int(steps)): hashes = hasharray[step * self.maxInputs:(step + 1) * self.maxInputs] msg = { "sign": { "data": hashes, "checkpub": pubkeyarray, }, } if tx_dbb_serialized is not None: msg["sign"]["meta"] = to_hexstr(Hash(tx_dbb_serialized)) msg = json.dumps(msg).encode('ascii') dbb_client = self.plugin.get_client(self) if not dbb_client.is_paired(): raise Exception("Could not sign transaction.") reply = dbb_client.hid_send_encrypt(msg) if 'error' in reply: raise Exception(reply['error']['message']) if 'echo' not in reply: raise Exception("Could not sign transaction.") if self.plugin.is_mobile_paired( ) and tx_dbb_serialized is not None: reply['tx'] = tx_dbb_serialized self.plugin.comserver_post_notification(reply) if steps > 1: self.handler.show_message(_("Signing large transaction. Please be patient ...\r\n\r\n" \ "To continue, touch the Digital Bitbox's blinking light for 3 seconds. " \ "(Touch " + str(step + 1) + " of " + str(int(steps)) + ")\r\n\r\n" \ "To cancel, briefly touch the blinking light or wait for the timeout.\r\n\r\n")) else: self.handler.show_message(_("Signing transaction ...\r\n\r\n" \ "To continue, touch the Digital Bitbox's blinking light for 3 seconds.\r\n\r\n" \ "To cancel, briefly touch the blinking light or wait for the timeout.")) # Send twice, first returns an echo for smart verification reply = dbb_client.hid_send_encrypt(msg) self.handler.finished() if 'error' in reply: if reply["error"].get('code') in (600, 601): # aborted via LED short touch or timeout raise UserCancelled() raise Exception(reply['error']['message']) if 'sign' not in reply: raise Exception("Could not sign transaction.") dbb_signatures.extend(reply['sign']) # Fill signatures if len(dbb_signatures) != len(tx.inputs()): raise Exception("Incorrect number of transactions signed." ) # Should never occur for i, txin in enumerate(tx.inputs()): num = txin['num_sig'] for pubkey in txin['pubkeys']: signatures = list(filter(None, txin['signatures'])) if len(signatures) == num: break # txin is complete ii = txin['pubkeys'].index(pubkey) signed = dbb_signatures[i] if 'recid' in signed: # firmware > v2.1.1 recid = int(signed['recid'], 16) s = binascii.unhexlify(signed['sig']) h = inputhasharray[i] pk = MyVerifyingKey.from_signature(s, recid, h, curve=SECP256k1) pk = to_hexstr(point_to_ser(pk.pubkey.point, True)) elif 'pubkey' in signed: # firmware <= v2.1.1 pk = signed['pubkey'] if pk != pubkey: continue sig_r = int(signed['sig'][:64], 16) sig_s = int(signed['sig'][64:], 16) sig = sigencode_der(sig_r, sig_s, generator_secp256k1.order()) txin['signatures'][ii] = to_hexstr(sig) + '01' tx._inputs[i] = txin except UserCancelled: raise except BaseException as e: self.give_error(e, True) else: print_error("Transaction is_complete", tx.is_complete()) tx.raw = tx.serialize()
def create_reg_menu(self, position): menu = QMenu() h = self.reg_cur_protx menu.addAction(_('Details'), lambda: Dip3MNInfoDialog(self, protx_hash=h).show()) menu.exec_(self.reg_view.viewport().mapToGlobal(position))
def __init__(self, dialog): QPushButton.__init__(self, _("Close")) self.clicked.connect(dialog.close) self.setDefault(True)
def create_wallet_mn_tab(self): w = QWidget() hw = QWidget() self.w_label = QLabel(self.wallet_label()) self.w_add_btn = QPushButton(_('Add / Import')) self.w_file_btn = QPushButton(_('File')) self.w_del_btn = QPushButton(_('Remove')) self.w_up_params_btn = QPushButton(_('Update Params')) self.w_up_coll_btn = QPushButton(_('Change Collateral')) self.w_protx_btn = QPushButton(_('Register')) self.w_up_srv_btn = QPushButton(_('Update Service')) self.w_up_reg_btn = QPushButton(_('Update Registrar')) self.w_add_btn.clicked.connect(self.on_add_masternode) self.w_file_btn.clicked.connect(self.on_file) self.w_del_btn.clicked.connect(self.on_del_masternode) self.w_up_params_btn.clicked.connect(self.on_update_params) self.w_up_coll_btn.clicked.connect(self.on_update_collateral) self.w_protx_btn.clicked.connect(self.on_make_pro_reg_tx) self.w_up_srv_btn.clicked.connect(self.on_make_pro_up_srv_tx) self.w_up_reg_btn.clicked.connect(self.on_make_pro_up_reg_tx) self.w_view = QTableView() self.w_view.setContextMenuPolicy(Qt.CustomContextMenu) self.w_view.customContextMenuRequested.connect(self.create_wallet_menu) self.w_hheader = QHeaderView(Qt.Horizontal, self.w_view) self.w_hheader.setSectionResizeMode(QHeaderView.ResizeToContents) self.w_hheader.setStretchLastSection(True) self.w_view.setHorizontalHeader(self.w_hheader) self.w_view.verticalHeader().hide() self.w_view.setSelectionMode(QAbstractItemView.SingleSelection) self.w_view.setSelectionBehavior(QAbstractItemView.SelectRows) self.w_view.doubleClicked.connect(self.w_mn_dbl_clicked) row_h = self.w_view.verticalHeader().defaultSectionSize() self.w_hheader.setMinimumSectionSize(row_h) src_model = WalletMNsModel(self.manager, self.mn_list, self.gui, row_h) src_model.dataChanged.connect(self.w_data_changed) self.w_model = Dip3FilterProxyModel() self.w_model.setSourceModel(src_model) self.w_view.setModel(self.w_model) sel_model = self.w_view.selectionModel() sel_model.selectionChanged.connect(self.on_wallet_selection_changed) self.w_model.modelReset.connect(self.on_wallet_model_reset) hbox = QHBoxLayout() vbox = QVBoxLayout() hbox.setContentsMargins(0, 0, 0, 0) hbox.addWidget(self.w_label) hbox.addStretch(1) hbox.addWidget(self.w_del_btn) hbox.addWidget(self.w_up_params_btn) hbox.addWidget(self.w_up_coll_btn) hbox.addWidget(self.w_protx_btn) hbox.addWidget(self.w_up_reg_btn) hbox.addWidget(self.w_up_srv_btn) hbox.addWidget(self.w_file_btn) hbox.addWidget(self.w_add_btn) hw.setLayout(hbox) vbox.addWidget(hw) vbox.addWidget(self.w_view) w.setLayout(vbox) self.addTab(w, read_QIcon('tab_dip3.png'), _('Wallet MNs')) if not self.mn_list.protx_loading: self.w_model.reload_data() return w
def __init__(self, text_getter, app, dialog): QPushButton.__init__(self, _("Copy and Close")) self.clicked.connect(lambda: app.clipboard().setText(text_getter())) self.clicked.connect(dialog.close) self.setDefault(True)
def __init__(self, parent, protx_hash=None, alias=None): ''' Show information about registred Masternodes with given prot_hash, or Masternodes in manager with given alias. ''' super(Dip3MNInfoDialog, self).__init__(parent) self.setMinimumSize(950, 450) self.setWindowIcon(read_QIcon('electrum-dash.png')) self.parent = parent self.gui = parent.gui self.manager = parent.manager self.mn_list = parent.mn_list self.diff_updated.connect(self.on_diff_updated) self.info_updated.connect(self.on_info_updated) if alias: self.mn = self.manager.mns.get(alias) else: self.mn = None if self.mn: self.protx_hash = self.mn.protx_hash self.setWindowTitle(_('%s Dip3 Masternode Info') % alias) elif protx_hash: self.protx_hash = protx_hash self.setWindowTitle( _('%s... Dip3 Masternode Info') % protx_hash[:32]) if self.mn_list and self.protx_hash: mn_list = self.mn_list sml_entry = mn_list.protx_mns.get(self.protx_hash, {}) self.diff_info = sml_entry.as_dict() if sml_entry else {} self.mn_list.register_callback(self.on_mn_list_diff_updated, ['mn-list-diff-updated']) self.mn_list.register_callback(self.on_mn_list_info_updated, ['mn-list-info-updated']) self.info = mn_list.protx_info.get(self.protx_hash, {}) if not self.info and self.gui.network.is_connected(): self.gui.network.run_from_another_thread( self.gui.network.request_protx_info(self.protx_hash)) else: self.diff_info = {} self.info = {} layout = QGridLayout() self.setLayout(layout) self.tabs = QTabWidget(self) self.close_btn = b = QPushButton(_('Close')) b.setDefault(True) b.clicked.connect(self.close) layout.addWidget(self.tabs, 0, 0, 1, -1) layout.setColumnStretch(0, 1) layout.addWidget(b, 1, 1) if self.mn: self.mn_tab = QWidget() self.mn_label = QLabel(_('Wallet Masternode: %s') % self.mn.alias) self.mn_view = QTextEdit() self.mn_view.setReadOnly(True) self.mn_view.setText(pformat(self.mn.as_dict())) mn_vbox = QVBoxLayout() mn_vbox.addWidget(self.mn_label) mn_vbox.addWidget(self.mn_view) self.mn_tab.setLayout(mn_vbox) self.tabs.addTab(self.mn_tab, _('Wallet')) if self.protx_hash: self.diff_info_tab = QWidget() self.diff_info_view = QTextEdit() self.diff_info_view.setReadOnly(True) self.diff_info_view.setText(pformat(self.diff_info)) diff_info_vbox = QVBoxLayout() diff_info_vbox.addWidget(self.diff_info_view) self.diff_info_tab.setLayout(diff_info_vbox) self.tabs.addTab(self.diff_info_tab, _('protx.diff data (merkle ' 'root verified)')) self.info_tab = QWidget() self.info_view = QTextEdit() self.info_view.setReadOnly(True) self.info_view.setText(pformat(self.info)) info_vbox = QVBoxLayout() info_vbox.addWidget(self.info_view) self.info_tab.setLayout(info_vbox) self.tabs.addTab(self.info_tab, _('protx.info data (unverified)'))
def __init__(self, dialog, label=None): QPushButton.__init__(self, label or _("Cancel")) self.clicked.connect(dialog.reject)
from electrum_xzc.i18n import _ fullname = 'Coldcard Wallet' description = 'Provides support for the Coldcard hardware wallet from Coinkite' requires = [('ckcc-protocol', 'github.com/Coldcard/ckcc-protocol')] registers_keystore = ('hardware', 'coldcard', _("Coldcard Wallet")) available_for = ['qt', 'cmdline']
def show_error(self, msg, parent=None): return self.msg_box(QMessageBox.Warning, parent, _('Error'), msg)
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 show_message(self, msg, parent=None, title=None): return self.msg_box(QMessageBox.Information, parent, title or _('Information'), msg)
def decrypt_message(self, pubkey, message, password): raise RuntimeError( _('Encryption and decryption are currently not supported for %s') % self.device)
def on_copy(self): self.app.clipboard().setText(self.text()) QToolTip.showText(QCursor.pos(), _("Text copied to clipboard"), self)
def seed_img(self, is_seed=True): if is_seed: try: cseed = self.get_seed() except UserCancelled: return except InvalidPassword as e: self.d.show_error(str(e)) return if not cseed: self.d.show_message(_("This wallet has no seed")) return txt = cseed.upper() else: txt = self.txt.upper() img = QImage(self.SIZE[0], self.SIZE[1], QImage.Format_Mono) bitmap = QBitmap.fromImage(img, Qt.MonoOnly) bitmap.fill(Qt.white) painter = QPainter() painter.begin(bitmap) QFontDatabase.addApplicationFont( os.path.join(os.path.dirname(__file__), 'SourceSansPro-Bold.otf')) if len(txt) < 102: fontsize = 15 linespace = 15 max_letters = 17 max_lines = 6 max_words = 3 else: fontsize = 12 linespace = 10 max_letters = 21 max_lines = 9 max_words = int(max_letters / 4) font = QFont('Source Sans Pro', fontsize, QFont.Bold) font.setLetterSpacing(QFont.PercentageSpacing, 100) font.setPixelSize(fontsize) painter.setFont(font) seed_array = txt.split(' ') for n in range(max_lines): nwords = max_words temp_seed = seed_array[:nwords] while len(' '.join(map(str, temp_seed))) > max_letters: nwords = nwords - 1 temp_seed = seed_array[:nwords] painter.drawText( QRect(0, linespace * n, self.SIZE[0], self.SIZE[1]), Qt.AlignHCenter, ' '.join(map(str, temp_seed))) del seed_array[:nwords] painter.end() img = bitmap.toImage() if (self.rawnoise == False): self.make_rawnoise() self.make_cypherseed(img, self.rawnoise, False, is_seed) return img