def passphrase_dialog(self, msg, confirm): # If confirm is true, require the user to enter the passphrase twice parent = self.top_level_window() d = WindowModalDialog(parent, _("Enter Passphrase")) if confirm: OK_button = OkButton(d) playout = PasswordLayout(msg=msg, kind=PW_PASSPHRASE, OK_button=OK_button) vbox = QVBoxLayout() vbox.addLayout(playout.layout()) vbox.addLayout(Buttons(CancelButton(d), OK_button)) d.setLayout(vbox) passphrase = playout.new_password() if d.exec_() else None else: pw = PasswordLineEdit() pw.setMinimumWidth(200) vbox = QVBoxLayout() vbox.addWidget(WWLabel(msg)) vbox.addWidget(pw) vbox.addLayout(Buttons(CancelButton(d), OkButton(d))) d.setLayout(vbox) passphrase = pw.text() if d.exec_() else None self.passphrase = passphrase self.done.set()
def __init__(self, handler, data, *, client: 'Ledger_Client'): '''Ask user for 2nd factor authentication. Support text and security card methods. Use last method from settings, but support 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(650) self.setWindowTitle(_("Ledger Wallet Authentication")) self.cfg = copy.deepcopy(self.handler.win.wallet.get_keystore().cfg) self.dongle = client.dongleObject.dongle 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): self.cfg[ 'mode'] = 0 if self.devmode == 0x11 else idx if idx > 0 else 1 if self.cfg['mode'] > 0: self.handler.win.wallet.get_keystore().cfg = self.cfg self.handler.win.wallet.save_keystore() self.update_dlg() 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) modelayout.addStretch(1) self.modebox.setMaximumHeight(50) vbox.addWidget(self.modebox) self.populate_modes() self.modes.currentIndexChanged.connect(on_change_mode) self.helpmsg = QTextEdit() self.helpmsg.setStyleSheet( "QTextEdit { color:black; background-color: lightgray; }") self.helpmsg.setReadOnly(True) vbox.addWidget(self.helpmsg) self.pinbox = QWidget() pinlayout = QHBoxLayout() self.pinbox.setLayout(pinlayout) self.pintxt = PasswordLineEdit() 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; font-family: "Courier New", monospace; } ''') self.addrtext.setReadOnly(True) self.addrtext.setMaximumHeight(130) card.addWidget(self.addrtext) def pin_changed(s): if len(s) < len(self.idxs): i = self.idxs[len(s)] addr = self.txdata['address'] if not constants.net.TESTNET: text = addr[:i] + '<u><b>' + addr[ i:i + 1] + '</u></b>' + addr[i + 1:] else: # pin needs to be created from mainnet address addr_mainnet = bitcoin.script_to_address( bitcoin.address_to_script(addr), net=constants.QtumMainnet) addr_mainnet = addr_mainnet[:i] + '<u><b>' + addr_mainnet[ i:i + 1] + '</u></b>' + addr_mainnet[i + 1:] text = str(addr) + '\n' + str(addr_mainnet) self.addrtext.setHtml(str(text)) else: self.addrtext.setHtml(_("Press Enter")) pin_changed('') cardpin = QHBoxLayout() cardpin.addWidget(QLabel(_("Enter PIN:"))) self.cardtxt = PasswordLineEdit() 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.update_dlg()
def passphrase_dialog(self, msg, confirm): # If confirm is true, require the user to enter the passphrase twice parent = self.top_level_window() d = WindowModalDialog(parent, _('Enter Passphrase')) OK_button = OkButton(d, _('Enter Passphrase')) OnDevice_button = QPushButton(_('Enter Passphrase on Device')) new_pw = PasswordLineEdit() conf_pw = PasswordLineEdit() 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) vbox.addWidget(label) grid.addWidget(QLabel(_('Passphrase:')), 0, 0) grid.addWidget(new_pw, 0, 1) if confirm: grid.addWidget(QLabel(_('Confirm Passphrase:')), 1, 0) grid.addWidget(conf_pw, 1, 1) vbox.addLayout(grid) def enable_OK(): if not confirm: ok = True else: ok = new_pw.text() == conf_pw.text() OK_button.setEnabled(ok) new_pw.textChanged.connect(enable_OK) conf_pw.textChanged.connect(enable_OK) vbox.addWidget(OK_button) if self.passphrase_on_device: vbox.addWidget(OnDevice_button) d.setLayout(vbox) self.passphrase = None def ok_clicked(): self.passphrase = new_pw.text() def on_device_clicked(): self.passphrase = PASSPHRASE_ON_DEVICE OK_button.clicked.connect(ok_clicked) OnDevice_button.clicked.connect(on_device_clicked) OnDevice_button.clicked.connect(d.accept) d.exec_() self.done.set()
def __init__(self, *, window: 'ElectrumWindow', txs, password, is_sweep): WindowModalDialog.__init__(self, window, _('BitPost Transactions Preview')) self.setMinimumSize(800, 600) self.main_window = window self.txs = txs self.password_required = self.main_window.wallet.has_keystore_encryption( ) and not is_sweep self.is_send = False vbox = QVBoxLayout() self.setLayout(vbox) lbox = QListWidget() items = [] for tx in txs: inputs = tx.inputs() outputs = tx.outputs() fee = tx.get_fee() fiat = False text = "fee: {}".format(fee) if self.main_window.fx and self.main_window.fx.is_enabled(): fiat = Exchange(self.main_window.fx) text += fiat.str_exchange(fee) text += "\t\tvbyte: {}\n".format(tx.estimated_size()) tmp = "fee/vbyte: {}".format(round(fee / tx.estimated_size(), 2)) if fiat: tmp += fiat.str_exchange(fee / tx.estimated_size()) text += tmp if len(tmp) > 22: tab = "\t" else: tab = "\t\t" text += "{}total size: {}\n".format(tab, tx.estimated_total_size()) text += "INPUTS:\n" for i in inputs: text += "{}:{} = {}".format(i.prevout.txid.hex(), i.prevout.out_idx, i.value_sats()) if fiat: text += fiat.str_exchange(i.value_sats()) text += "\n" text += "OUTPUTS:\n" for o in outputs: text += "{} = {}".format(o.address, o.value) if fiat: text += fiat.str_exchange(o.value) text += "\n" items.append(text) lbox.addItems(items) vbox.addWidget(lbox) self.send_button = QPushButton(_('Send')) self.send_button.clicked.connect(self.on_send) self.send_button.setDefault(True) self.pw_label = QLabel(_('Password')) self.pw_label.setVisible(self.password_required) self.pw = PasswordLineEdit(password) self.pw.setVisible(self.password_required) vbox.addLayout( Buttons(CancelButton(self), self.pw_label, self.pw, self.send_button))
def build_gui(self): vbox = QVBoxLayout() self.setLayout(vbox) grid = QGridLayout() vbox.addLayout(grid) self.amount_label = QLabel('') grid.addWidget(QLabel(_("Target for confirmation")), 0, 0) self.qtarget = QDateTimeEdit(QDateTime.currentDateTime().addSecs( int(self.main_window.config.get('bitpost_target_interval')) * 60)) grid.addWidget(self.qtarget, 0, 1) self.asap_check = QCheckBox("ASAP") self.asap_check.clicked.connect(self.toggle_target) grid.addWidget(self.asap_check, 0, 2) grid.addWidget(QLabel(_("Maximum Fee")), 2, 0) self.max_fees = QLineEdit( str(self.main_window.config.get('bitpost_max_fee'))) self.max_fees.textChanged.connect(self.change_max_fees) grid.addWidget(self.max_fees, 2, 1) self.fee_combo = QComboBox() fee_combo_values = get_fee_units( self.main_window, self.main_window.config.get('bitpost_max_fee_unit')) self.fee_combo.addItems(fee_combo_values) grid.addWidget(self.fee_combo, 2, 2) self.schedule_check = QCheckBox(_("Schedule transaction")) self.schedule_check.clicked.connect(self.toggle_delay) grid.addWidget(self.schedule_check, 3, 0, 1, -1) self.qdelay = QDateTimeEdit(QDateTime.currentDateTime()) grid.addWidget(self.qdelay, 4, 0) sp_retain = QSizePolicy(self.qdelay.sizePolicy()) sp_retain.setRetainSizeWhenHidden(True) self.qdelay.setSizePolicy(sp_retain) self.qdelay.setVisible(False) self.message_label = QLabel(self.default_message()) grid.addWidget(self.message_label, 9, 0, 1, -1) self.pw_label = QLabel(_('Password')) self.pw_label.setVisible(self.password_required) self.pw = PasswordLineEdit() self.pw.setVisible(self.password_required) grid.addWidget(self.pw_label, 11, 0) grid.addWidget(self.pw, 11, 1, 1, -1) self.send_button = QPushButton(_('Send')) self.send_button.clicked.connect(self.on_send) self.send_button.setDefault(True) self.preview_button = QPushButton(_('Preview')) self.preview_button.clicked.connect(self.on_preview) self.preview_button.setDefault(True) vbox.addLayout( Buttons(CancelButton(self), self.preview_button, self.send_button)) # set default to ASAP checked self.asap_check.setChecked(True) self.toggle_target() self.update() self.is_send = False
class ConfirmTxDialog(WindowModalDialog): # set fee and return password (after pw check) def __init__(self, *, window: 'ElectrumWindow', inputs, outputs, output_value: Union[int, str], is_sweep: bool): WindowModalDialog.__init__(self, window, _("BitPost Confirm Transaction")) self.main_window = window self.inputs = inputs self.outputs = outputs self.output_value = output_value self.delay = None self.target = None self.txs = [] self.config = window.config self.wallet = window.wallet self.not_enough_funds = False self.no_dynfee_estimates = False self.needs_update = False self.is_sweep = is_sweep self.password_required = self.wallet.has_keystore_encryption( ) and not is_sweep self.num_txs = int(window.config.get('bitpost_num_txs')) self.imax_fees = 0 self.imax_size = 0 self.build_gui() def build_gui(self): vbox = QVBoxLayout() self.setLayout(vbox) grid = QGridLayout() vbox.addLayout(grid) self.amount_label = QLabel('') grid.addWidget(QLabel(_("Target for confirmation")), 0, 0) self.qtarget = QDateTimeEdit(QDateTime.currentDateTime().addSecs( int(self.main_window.config.get('bitpost_target_interval')) * 60)) grid.addWidget(self.qtarget, 0, 1) self.asap_check = QCheckBox("ASAP") self.asap_check.clicked.connect(self.toggle_target) grid.addWidget(self.asap_check, 0, 2) grid.addWidget(QLabel(_("Maximum Fee")), 2, 0) self.max_fees = QLineEdit( str(self.main_window.config.get('bitpost_max_fee'))) self.max_fees.textChanged.connect(self.change_max_fees) grid.addWidget(self.max_fees, 2, 1) self.fee_combo = QComboBox() fee_combo_values = get_fee_units( self.main_window, self.main_window.config.get('bitpost_max_fee_unit')) self.fee_combo.addItems(fee_combo_values) grid.addWidget(self.fee_combo, 2, 2) self.schedule_check = QCheckBox(_("Schedule transaction")) self.schedule_check.clicked.connect(self.toggle_delay) grid.addWidget(self.schedule_check, 3, 0, 1, -1) self.qdelay = QDateTimeEdit(QDateTime.currentDateTime()) grid.addWidget(self.qdelay, 4, 0) sp_retain = QSizePolicy(self.qdelay.sizePolicy()) sp_retain.setRetainSizeWhenHidden(True) self.qdelay.setSizePolicy(sp_retain) self.qdelay.setVisible(False) self.message_label = QLabel(self.default_message()) grid.addWidget(self.message_label, 9, 0, 1, -1) self.pw_label = QLabel(_('Password')) self.pw_label.setVisible(self.password_required) self.pw = PasswordLineEdit() self.pw.setVisible(self.password_required) grid.addWidget(self.pw_label, 11, 0) grid.addWidget(self.pw, 11, 1, 1, -1) self.send_button = QPushButton(_('Send')) self.send_button.clicked.connect(self.on_send) self.send_button.setDefault(True) self.preview_button = QPushButton(_('Preview')) self.preview_button.clicked.connect(self.on_preview) self.preview_button.setDefault(True) vbox.addLayout( Buttons(CancelButton(self), self.preview_button, self.send_button)) # set default to ASAP checked self.asap_check.setChecked(True) self.toggle_target() self.update() self.is_send = False def toggle_target(self): if self.asap_check.isChecked(): self.qtarget.setEnabled(False) self.qdelay.setEnabled(False) self.schedule_check.setEnabled(False) else: self.qtarget.setEnabled(True) self.qdelay.setEnabled(True) self.schedule_check.setEnabled(True) def toggle_delay(self): if self.schedule_check.isChecked(): self.qdelay.setVisible(True) else: self.qdelay.setVisible(False) def change_max_fees(self): pass def default_message(self): return _('Enter your password to proceed' ) if self.password_required else _('Click Send to proceed') def on_preview(self): password = self.pw.text() or None BlockingWaitingDialog(self.main_window, _("Preparing transaction..."), self.prepare_txs) if len(self.txs) <= 0: return d = PreviewTxsDialog(window=self.main_window, txs=self.txs, password=password, is_sweep=self.is_sweep) cancelled, is_send, password = d.run() if cancelled: return if is_send: self.pw.setText(password) self.send() def run(self): cancelled = not self.exec_() password = self.pw.text() or None return cancelled, self.is_send, password, self.txs, self.target, self.delay, self.imax_fees, self.imax_size def send(self): password = self.pw.text() or None if self.password_required: if password is None: self.main_window.show_error(_("Password required"), parent=self) return try: self.wallet.check_password(password) except Exception as e: self.main_window.show_error(str(e), parent=self) return self.is_send = True self.target = self.qtarget.dateTime().toPyDateTime().timestamp() if self.asap_check.isChecked(): self.target = round(datetime.now().timestamp() + 20 * 60) if self.schedule_check.isChecked(): self.delay = self.qdelay.dateTime().toPyDateTime() else: self.delay = self.main_window.config.get('bitpost_delay', 0) if self.target < self.delay: self.main_window.show_error( _("Target should be greater than delay")) return self.is_send = True if self.is_send: self.accept() else: print("ERROR: is_send is false") def on_send(self): BlockingWaitingDialog(self.main_window, _("Preparing transaction..."), self.prepare_txs) if len(self.txs) <= 0: return self.send() def get_feerates(self, estimated_size): if self.config.get('testnet'): testnet = True else: testnet = False bitpost_interface = BitpostInterface(testnet=testnet) max_feerate = self.calculate_max_feerate(estimated_size, self.fee_combo.currentText()) return bitpost_interface.get_feerates(max_feerate, size=self.num_txs) def calculate_max_feerate(self, estimated_size, fee_unit): raw_max_fee = float(self.max_fees.text()) if fee_unit == 'sats/byte': return raw_max_fee elif fee_unit == 'sats': return raw_max_fee / estimated_size else: max_sats = 100_000_000 * raw_max_fee / float( self.main_window.fx.exchange_rate()) return max_sats / estimated_size def prepare_txs(self): try: print('prepare txs') self.prepare_txs_by_bumping_fee() except CannotBumpFee as ex: print("cannot bump fee", ex) self.prepare_txs_manually() except Exception as e: print(e) def prepare_txs_manually(self): print('prepare tx manually') max_fee = int( 200 * self.calculate_max_feerate(200, self.fee_combo.currentText())) highest_fee_tx = self.make_tx(max_fee) self.imax_size = est_size = highest_fee_tx.estimated_size() self.imax_fees = max_fee = int( est_size * self.calculate_max_feerate(est_size, self.fee_combo.currentText())) can_be_change = lambda o: self.main_window.wallet.is_change( o.address) and self.main_window.wallet.is_mine(o.address) change_index = max([ i for i in range(len(highest_fee_tx.outputs())) if can_be_change(highest_fee_tx.outputs()[i]) ]) max_feerate = ( highest_fee_tx.input_value() - highest_fee_tx.output_value()) / highest_fee_tx.estimated_size() feerates = self.get_feerates(max_feerate) highest_fee_tx.set_rbf(True) self.txs = [] for fee in feerates: tx = self.main_window.wallet.make_unsigned_transaction( coins=highest_fee_tx.inputs(), outputs=highest_fee_tx.outputs()) new_change = highest_fee_tx.outputs()[change_index].value + int( abs(max_feerate - fee) * highest_fee_tx.estimated_size()) tx.outputs()[change_index].value = new_change self.txs.append(tx) self.not_enough_funds = False self.no_dynfee_estimates = False def prepare_txs_by_bumping_fee(self): try: base_tx = self.make_tx(0) est_size = base_tx.estimated_size() feerates = self.get_feerates(est_size) base_tx.set_rbf(True) base_tx.serialize_to_network() for fee in feerates: tx = self.bump_fee(base_tx, fee) tx.set_rbf(True) self.txs.append(tx) self.imax_fees = max(self.imax_fees, tx.get_fee()) self.imax_size = max(self.imax_size, tx.estimated_size()) self.not_enough_funds = False self.no_dynfee_estimates = False except NotEnoughFunds: self.not_enough_funds = True self.txs = [] print("not enought funds") return except NoDynamicFeeEstimates: self.no_dynfee_estimates = True self.txs = [] print("no dynamic fee estimation") try: self.txs = [self.make_tx(0)] except BaseException: return except InternalAddressCorruption as e: self.txs = [] self.main_window.show_error(str(e)) print("Internal address corruption") return except BitpostDownException: self.main_window.show_error(_("Fee Rates Service Not Available"), parent=self) self.is_send = False print("bitpost down") return except Exception as e: self.txs = [] print("Exception", e) self.main_window.show_error(_("Exception: " + str(e)), parent=self.main_window) return def bump_fee(self, tx, new_fee): inputs = tx.inputs() coco = [] for c in self.inputs: if c not in inputs: coco.append(c) try: self.main_window.logger.debug(str(new_fee) + "bump fee method 1") tx_out = self.main_window.wallet._bump_fee_through_coinchooser( tx=tx, new_fee_rate=new_fee, coins=coco) except Exception as ex: if all( self.main_window.wallet.is_mine(o.address) for o in list(tx.outputs())): raise ex self.window.show_error( _("Not enought funds, please add more inputs or reduce max fee" )) raise NotEnoughFunds return tx_out def make_tx(self, fee_est): tx = self.main_window.wallet.make_unsigned_transaction( coins=self.inputs, outputs=self.outputs, fee=fee_est, is_sweep=self.is_sweep) return tx
class LedgerAuthDialog(QDialog): def __init__(self, handler, data): '''Ask user for 2nd factor authentication. Support text and security card methods. Use last method from settings, but support 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(650) 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.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): self.cfg['mode'] = 0 if self.devmode == 0x11 else idx if idx > 0 else 1 if self.cfg['mode'] > 0: self.handler.win.wallet.get_keystore().cfg = self.cfg self.handler.win.wallet.save_keystore() self.update_dlg() 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) modelayout.addStretch(1) self.modebox.setMaximumHeight(50) vbox.addWidget(self.modebox) self.populate_modes() self.modes.currentIndexChanged.connect(on_change_mode) self.helpmsg = QTextEdit() self.helpmsg.setStyleSheet("QTextEdit { color:black; background-color: lightgray; }") self.helpmsg.setReadOnly(True) vbox.addWidget(self.helpmsg) self.pinbox = QWidget() pinlayout = QHBoxLayout() self.pinbox.setLayout(pinlayout) self.pintxt = PasswordLineEdit() 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; font-family: "Courier New", monospace; } ''') self.addrtext.setReadOnly(True) self.addrtext.setMaximumHeight(130) card.addWidget(self.addrtext) def pin_changed(s): if len(s) < len(self.idxs): i = self.idxs[len(s)] addr = self.txdata['address'] if not constants.net.TESTNET: text = addr[:i] + '<u><b>' + addr[i:i+1] + '</u></b>' + addr[i+1:] else: # pin needs to be created from mainnet address addr_mainnet = bitcoin.script_to_address(bitcoin.address_to_script(addr), net=constants.BitcoinMainnet) addr_mainnet = addr_mainnet[:i] + '<u><b>' + addr_mainnet[i:i+1] + '</u></b>' + addr_mainnet[i+1:] text = str(addr) + '\n' + str(addr_mainnet) self.addrtext.setHtml(str(text)) else: self.addrtext.setHtml(_("Press Enter")) pin_changed('') cardpin = QHBoxLayout() cardpin.addWidget(QLabel(_("Enter PIN:"))) self.cardtxt = PasswordLineEdit() 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.update_dlg() def populate_modes(self): self.modes.blockSignals(True) self.modes.clear() self.modes.addItem(_("Summary Text PIN (requires dongle replugging)") if self.txdata['confirmationType'] == 1 else _("Summary Text PIN is Disabled")) if self.txdata['confirmationType'] > 1: self.modes.addItem(_("Security Card Challenge")) self.modes.blockSignals(False) def update_dlg(self): self.modes.setCurrentIndex(self.cfg['mode']) self.modebox.setVisible(True) self.helpmsg.setText(helpTxt[self.cfg['mode']]) self.helpmsg.setMinimumHeight(180 if self.txdata['confirmationType'] == 1 else 100) self.helpmsg.setVisible(True) self.pinbox.setVisible(self.cfg['mode'] == 0) self.cardbox.setVisible(self.cfg['mode'] == 1) self.pintxt.setFocus(True) if self.cfg['mode'] == 0 else self.cardtxt.setFocus(True) self.setMaximumHeight(400) def getDevice2FAMode(self): apdu = [0xe0, 0x24, 0x01, 0x00, 0x00, 0x01] # get 2fa mode try: mode = self.dongle.exchange( bytearray(apdu) ) return mode except BTChipException as e: _logger.debug('Device getMode Failed') return 0x11