def get_passphrase(self, msg, confirm): import getpass print_stderr(msg) if self.passphrase_on_device and self.yes_no_question(_('Enter passphrase on device?')): return PASSPHRASE_ON_DEVICE else: return getpass.getpass('')
def OnShareURI() -> None: uri = self.generatePrURI() url = NSURL.URLWithString_(uri) utils.show_share_actions(vc=self, url=url, ipadAnchor=ipadAnchor, objectName=_("Request URI"))
def add_contact_slot(ign=None, but=but, item=item): # label, address, typ='address') -> str: new_contact = parent.set_contact(label=ca_string, address=info.address, typ='cashacct') if new_contact: msg = _( '<span style="white-space:nowrap"><b>{cash_account}</b> added to Contacts</span>' ).format(cash_account=ca_string_em) but.setDisabled(True) but.setToolTip(msg) all_cashacct_contacts.add(new_contact.name) else: msg = _("Error occurred adding to Contacts") QToolTip.showText(QCursor.pos(), msg, frame, QRect(), 5000)
def get_pin(self, code=None): if code == 2: msg = _("Enter a new PIN for your {}:") elif code == 3: msg = (_("Re-enter the new PIN for your {}.\n\n" "NOTE: the positions of the numbers have changed!")) else: msg = _("Enter your current {} PIN:") pin = self.handler.get_pin(msg.format(self.device)) if not pin: raise Cancelled if len(pin) > 9: self.handler.show_error( _('The PIN cannot be longer than 9 characters.')) raise Cancelled return pin
def new_cash_account_contact_dialog(self): ''' Context menu callback. Shows the "New Cash Account Contact" interface. ''' items = cashacctqt.lookup_cash_account_dialog( self.parent, self.wallet, title=_("New Cash Account Contact"), blurb=_("<br>Add anyone's Cash Account to your Contacts"), button_type=cashacctqt.InfoGroupBox.ButtonType.Radio) if items: info, min_chash, name = items[0] self.parent.set_contact(name, info.address.to_ui_string(), typ='cashacct') run_hook('update_contacts_tab', self)
def password_dialog(self, pw, grid, pos): vkb_button = QPushButton(_("+")) vkb_button.setFixedWidth(20) vkb_button.clicked.connect(lambda: self.toggle_vkb(grid, pw)) grid.addWidget(vkb_button, pos, 2) self.kb_pos = 2 self.vkb = None
def import_contacts(self): wallet_folder = self.parent.get_wallet_folder() filename, __ = QFileDialog.getOpenFileName(self.parent, "Select your wallet file", wallet_folder) if not filename: return try: num = self.parent.contacts.import_file(filename) self.parent.show_message( _("{} contacts successfully imported.").format(num)) except Exception as e: self.parent.show_error( _("Oregano was unable to import your contacts.") + "\n" + repr(e)) self.on_update()
def export_contacts(self): if self.parent.contacts.empty: self.parent.show_error(_("Your contact list is empty.")) return try: fileName = self.parent.getSaveFileName( _("Select file to save your contacts"), 'oregano-contacts.json', "*.json") if fileName: num = self.parent.contacts.export_file(fileName) self.parent.show_message( _("{} contacts exported to '{}'").format(num, fileName)) except Exception as e: self.parent.show_error( _("Oregano was unable to export your contacts.") + "\n" + repr(e))
def callback_WordRequest(self, msg): self.step += 1 msg = _("Step {}/24. Enter seed word as explained on " "your {}:").format(self.step, self.device) word = self.handler.get_word(msg) # Unfortunately the device can't handle self.proto.Cancel() return self.proto.WordAck(word=word)
def receive_menu(self, menu, addrs, wallet): if type(wallet) is not Standard_Wallet: return keystore = wallet.get_keystore() if type(keystore) is not self.keystore_class: return if not self.is_mobile_paired(): return if not keystore.is_p2pkh(): return if len(addrs) == 1: def show_address(): change, index = wallet.get_address_index(addrs[0]) keypath = '%s/%d/%d' % (keystore.derivation, change, index) xpub = self.get_client(keystore)._get_xpub(keypath) verify_request_payload = { "type": 'p2pkh', "echo": xpub['echo'], } self.comserver_post_notification(verify_request_payload) menu.addAction(_("Show on {}").format(self.device), show_address)
def callback_PinMatrixRequest(self, msg): if msg.type == 2: msg = _("Enter a new PIN for your {}:") elif msg.type == 3: msg = (_("Re-enter the new PIN for your {}.\n\n" "NOTE: the positions of the numbers have changed!")) else: msg = _("Enter your current {} PIN:") pin = self.handler.get_pin(msg.format(self.device)) if len(pin) > 9: self.handler.show_error( _('The PIN cannot be longer than 9 characters.')) pin = '' # to cancel below if not pin: return self.proto.Cancel() return self.proto.PinMatrixAck(pin=pin)
def item_changed(self, item): if item is None: return if not item.isSelected(): return addr = item.data(0, Qt.UserRole) req = self.wallet.receive_requests.get(addr) if not req: return expires = age(req['time'] + req['exp']) if req.get('exp') else _('Never') amount = req['amount'] opr = req.get('op_return') or req.get('op_return_raw') opr_is_raw = bool(req.get('op_return_raw')) message = self.wallet.labels.get(addr.to_storage_string(), '') self.parent.receive_address = addr self.parent.receive_address_e.setText(addr.to_full_ui_string()) self.parent.receive_message_e.setText(message) self.parent.receive_amount_e.setAmount(amount) self.parent.expires_combo.hide() self.parent.expires_label.show() self.parent.expires_label.setText(expires) self.parent.receive_opreturn_rawhex_cb.setChecked(opr_is_raw) self.parent.receive_opreturn_e.setText(opr or '') self.parent.save_request_button.setEnabled(False) self.parent.cash_account_e.set_cash_acct()
def create_output_by_address(): txoutputtype = TxOutputType() txoutputtype.amount = amount if _type == TYPE_SCRIPT: script = address.to_script() # We only support OP_RETURN with one constant push if (script[0] == 0x6a and amount == 0 and script[1] == len(script) - 2 and script[1] <= 75): txoutputtype.script_type = OutputScriptType.PAYTOOPRETURN txoutputtype.op_return_data = script[2:] else: raise Exception(_("Unsupported output script.")) elif _type == TYPE_ADDRESS: txoutputtype.script_type = OutputScriptType.PAYTOADDRESS addr_format = address.FMT_LEGACY if client.get_trezor_model() == 'T': if client.atleast_version(2, 0, 8): addr_format = address.FMT_UI elif client.atleast_version(2, 0, 7): addr_format = address.FMT_CASHADDR else: if client.atleast_version(1, 6, 2): addr_format = address.FMT_UI txoutputtype.address = address.to_full_string(addr_format) return txoutputtype
def check_libraries_available(self) -> bool: def version_str(t): return ".".join(str(i) for i in t) try: # this might raise ImportError or LibraryFoundButUnusable library_version = self.get_library_version() # if no exception so far, we might still raise LibraryFoundButUnusable if (library_version == 'unknown' or versiontuple(library_version) < self.minimum_library or hasattr(self, "maximum_library") and versiontuple(library_version) >= self.maximum_library): raise LibraryFoundButUnusable(library_version=library_version) except ImportError: return False except LibraryFoundButUnusable as e: library_version = e.library_version max_version_str = version_str(self.maximum_library) if hasattr( self, "maximum_library") else "inf" self.libraries_available_message = ( _("Library version for '{}' is incompatible.").format( self.name) + '\nInstalled: {}, Needed: {} <= x < {}'.format( library_version, version_str(self.minimum_library), max_version_str)) self.print_stderr(self.libraries_available_message) return False return True
def ShowIt() -> None: utils.show_share_actions( vc=self, img=self.qr.image, ipadAnchor=self.qr.convertRect_toView_( self.qr.bounds, self.view), objectName=_("Image"))
def create_client(self, device, handler): if device.product_key[1] == 2: transport = self._try_webusb(device) else: transport = self._try_hid(device) if not transport: self.print_error("cannot connect to device") return self.print_error("connected to device at {}".format(device.path)) client = self.client_class(transport, handler, self) # Try a ping for device sanity try: client.ping('t') except BaseException as e: self.print_error("ping failed {}".format(e)) return None if not client.atleast_version(*self.minimum_firmware): msg = (_('Outdated {} firmware for device labelled {}. Please ' 'download the updated firmware from {}').format( self.device, client.label(), self.firmware_URL)) self.print_error(msg) if handler: handler.show_error(msg) else: raise RuntimeError(msg) return None return client
def toggle_cashshuffle(self, window, *args): from .qt import Plugin if not Plugin.is_wallet_cashshuffle_compatible(window): window.show_warning( _("This wallet type cannot be used with CashShuffle."), parent=window) return plugins = window.gui_object.plugins p0 = self.plugin p = p0 or plugins.enable_internal_plugin("shuffle") if not p: raise RuntimeError("Could not find CashShuffle plugin") was_enabled = p.window_has_cashshuffle(window) if was_enabled and not p.warn_if_shuffle_disable_not_ok(window): # user at nag screen said "no", so abort self.update_cashshuffle_icon() return enable_flag = not was_enabled self._cash_shuffle_flag = 0 KillPopupLabel("CashShuffleError") if not p0: # plugin was not loaded -- so flag window as wanting cashshuffle and do init p.window_set_wants_cashshuffle(window, enable_flag) p.init_qt(window.gui_object) else: # plugin was already started -- just add the window to the plugin p.window_set_cashshuffle(window, enable_flag) self.update_cashshuffle_icon() window.statusBar().showMessage( self.cashshuffle_status_button.statusTip(), 3000) if enable_flag and window.config.get("show_utxo_tab") is None: window.toggle_tab( window.utxo_tab ) # toggle utxo tab to 'on' if user never specified it should be off.
def _on_camera_status_changed(self, status: QCamera.Status): if self._ok_done: # camera/scan is quitting, abort. return self.print_error('camera status changed to {}'.format(self._get_camera_status_name(status))) if status == QCamera.LoadedStatus: # Determine the optimal resolution and compute the crop rect camera_resolutions = self.camera.supportedViewfinderResolutions() try: resolution, was_ideal = self._get_resolution(camera_resolutions, self.SCAN_SIZE) except RuntimeError as e: self._error_message = str(e) self.reject() return self._set_resolution(resolution) # Set the camera resolution viewfinder_settings = QCameraViewfinderSettings() viewfinder_settings.setResolution(resolution) self.camera.setViewfinderSettings(viewfinder_settings) # Counter for the QR scanner frame number self.frame_id = 0 self.camera.start() self.lowres_label.setVisible(not was_ideal) # if they have a low res camera, show the warning label. elif status == QCamera.UnloadedStatus or status == QCamera.UnavailableStatus: self._error_message = _("Cannot start QR scanner, camera is unavailable.") self.reject() elif status == QCamera.ActiveStatus: self.open()
def __init__(self, text=None): _QrCodeTextEdit.__init__(self, text) self.setReadOnly(1) self.qr_button = self.addButton(self.get_qr_icon(), self.qr_show, _("Show as QR code")) run_hook('show_text_edit', self)
def settings_widget(self, window): while window and window_parent(window) and not isinstance(window_parent(window), ElectrumWindow): # MacOS fixup -- find window.parent() because we can end up with window.parent() not an ElectrumWindow window = window_parent(window) windowRef = Weak.ref(window) return EnterButton(_('Settings'), partial(self.settings_dialog, windowRef))
def show_qr(self): text = bfh(str(self.tx)) text = base_encode(text, base=43) try: self.main_window.show_qrcode(text, _('Transaction'), parent=self) except Exception as e: self.show_message(str(e))
def tableView_trailingSwipeActionsConfigurationForRowAtIndexPath_(self, tv, indexPath) -> ObjCInstance: ''' This method is called in iOS 11.0+ only .. so we only create this UISwipeActionsConfiguration ObjCClass here rather than in uikit_bindings.py ''' try: row = int(indexPath.row) # save param outside objcinstance object and into python for 'handler' closure section = int(indexPath.section) def handler(a : objc_id, v : objc_id, c : objc_id) -> None: result = False try: self.removeSpendFromAtIndex_(row) self.retain() utils.call_later(0.4, lambda: self.autorelease().spendFromWasDeleted()) result = True except: traceback.print_exc(file=sys.stderr) ObjCBlock(c)(bool(result)) # inform UIKit if we deleted it or not by calling the block handler callback action = UIContextualAction.contextualActionWithStyle_title_handler_(UIContextualActionStyleDestructive, _("Remove"), Block(handler)) action.image = UIImage.imageNamed_("trashcan_red.png") action.backgroundColor = utils.uicolor_custom('red') return UISwipeActionsConfiguration.configurationWithActions_([action]) except: utils.NSLog("Send.tableView_trailingSwipeActionsConfigurationForRowAtIndexPath_, got exception: %s", str(sys.exc_info()[1])) traceback.print_exc(file=sys.stderr) return None
def onSendBut_(self, sender) -> None: def SendReport() -> str: reportDict = _get_traceback_info(self) reportDict.update(_get_additional_info(self)) report = json.dumps(reportDict) #reportPretty = json.dumps(reportDict, indent=4) #utils.NSLog("Report contents: %s", reportPretty) response = requests.post(report_server, data=report) return response.text def onOk() -> None: self.presentingViewController.dismissViewControllerAnimated_completion_( True, None) def OnSuccess(response: str) -> None: utils.NSLog("Response from server: %s", response) response = response.strip() if len(response) > 255: response = response[:255] + "..." try: response = str( utils.nsattributedstring_from_html(response).string) except: pass parent().show_message(message=response, title=_("Report Sent"), vc=self, onOk=onOk) def OnError(exc) -> None: parent().show_error(message=str(exc[1]), vc=self) utils.WaitingDialog(self, _("Sending Report..."), SendReport, OnSuccess, OnError)
def DeleteChk() -> None: nonlocal tf, placeholder, prefill prefill = '' if tf: txt = str(tf.text).lower().strip() if txt == 'delete' or txt == delete_confirm_text: # support i18n try: os.remove(info.full_path) parent.set_wallet_use_touchid(info.name, None, clear_asked = True) # clear cached password if any parent.refresh_components('wallets') utils.show_notification(message = _("Wallet deleted successfully")) except: parent.show_error(vc = vc, message = str(sys.exc_info()[1])) else: parent.show_error(vc = vc, title = _("Not Deleted"), message = _("You didn't enter the text '{delete_confirm_text}' in the previous dialog. For your own safety, the wallet file was not deleted.").format(delete_confirm_text=delete_confirm_text)) Release()
def toggleDrawer(self) -> None: ''' Fancy tricky code below to create the "drawer opening" effect. Fades-in the WalletsDrawerVC view controller (which overlays on top of our view), while opening the drawer and animating the chevron. This creates the effect of the drawer opening and everything behind it fading darker. It's pretty smoothe. Potential glitches include the layout constraints in the modal not lining up perfectly with our view's drawer stub. But this has been tested and works on all extant iPhones & iPads in the simulator. ''' if not self.modalDrawerVC: NSBundle.mainBundle.loadNibNamed_owner_options_("WalletsDrawerVC", self, None) vc = self.modalDrawerVC # Note: self.modalDrawerVC weak ref auto-set by Nib loader if not vc: utils.NSLog("**** Warning: toggleDrawer could not find the requisite view controller in WalletsDrawerVC.nib!") return vc.amount.text = self.walletAmount.text #vc.units.attributedText = self.walletUnits.attributedText vc.units.text = self.walletUnits.text vc.name.text = self.walletName.text vc.addNewWalletLabel.text = _("Add new wallet") # set here again for i18n semiclear = vc.view.backgroundColor.copy() vc.view.backgroundColor = UIColor.clearColor def compl() -> None: vc.view.backgroundColorAnimationToColor_duration_reverses_completion_(semiclear.autorelease(), 0.2, False, None) vc.openAnimated_(True) self.presentViewController_animated_completion_(vc, False, compl) else: # NB: weak ref self.modalDrawerVC will be auto-cleared by obj-c runtime after it is dismissed utils.call_later(0.100, self.dismissViewControllerAnimated_completion_,True, None) self.modalDrawerVC.closeAnimated_(True)
def seeAllTxs() -> None: # Push a new viewcontroller that contains just a tableview.. we create another instance of this # class to manage the tableview and set it up properly. This should be fast as we are sharing tx history # data with the child instance via our "nspy_put" mechanism. vc = UIViewController.new().autorelease() vc.title = _("All Transactions") bb = UIBarButtonItem.new().autorelease() bb.title = _("Back") vc.navigationItem.backBarButtonItem = bb vc.view = UITableView.alloc().initWithFrame_style_( self.vc.view.frame, UITableViewStylePlain).autorelease() vc.view.separatorInset = UIEdgeInsetsZero helper = NewTxHistoryHelper(tv=vc.view, vc=self.vc, domain=_GetDomain(self)) self.vc.navigationController.pushViewController_animated_(vc, True)
def tableView_cellForRowAtIndexPath_(self, tv, indexPath) -> ObjCInstance: try: reqs = _GetReqs() identifier = "RequestListCell" if not self.didReg.containsObject_(tv.ptr.value): nib = UINib.nibWithNibName_bundle_(identifier, None) tv.registerNib_forCellReuseIdentifier_(nib, identifier) self.didReg.addObject_(tv.ptr.value) if not reqs or indexPath.row < 0 or indexPath.row >= len(reqs): raise Exception( 'Bad index path row -- wallet closed and reopened?') cell = tv.dequeueReusableCellWithIdentifier_(identifier) #ReqItem = namedtuple("ReqItem", "date addrStr signedBy message amountStr statusStr addr iconSign iconStatus") item = reqs[indexPath.row] cell.addressTit.setText_withKerning_(_('Address'), utils._kern) cell.statusTit.setText_withKerning_(_('Status'), utils._kern) cell.amountTit.setText_withKerning_(_('Amount'), utils._kern) if item.fiatStr: cell.amount.attributedText = utils.hackyFiatAmtAttrStr( item.amountStr.strip(), item.fiatStr.strip(), '', 2.5, cell.amountTit.textColor) else: cell.amount.text = item.amountStr.strip( ) if item.amountStr else '' cell.address.text = item.addrStr.strip() if item.addrStr else '' if item.dateStr: cell.date.attributedText = utils.makeFancyDateAttrString( item.dateStr.strip()) else: cell.date.text = '' if item.message: cell.desc.setText_withKerning_(item.message, utils._kern) else: cell.desc.text = '' cell.status.text = item.statusStr if item.statusStr else _( 'Unknown') cell.selectionStyle = UITableViewCellSelectionStyleNone if not self.vc or not self.vc.navigationController else UITableViewCellSelectionStyleDefault cell.chevron.setHidden_( cell.selectionStyle == UITableViewCellSelectionStyleNone) except: utils.NSLog("Exception in ReqTVD cellForRowAtIndexPath: %s", str(sys.exc_info()[1])) # this sometimes happens on app re-foregrounding.. so guard against it cell = UITableViewCell.alloc().initWithStyle_reuseIdentifier_( UITableViewCellStyleSubtitle, "Cell").autorelease() cell.selectionStyle = UITableViewCellSelectionStyleNone return cell
def transaction_dialog(self, d): window, state = self._find_window_and_state_for_wallet(d.wallet) if window and state: d.cosigner_send_button = b = QPushButton(_("Send to cosigner")) b.wallet_ref = Weak.ref(window.wallet) b.clicked.connect(lambda: Plugin.do_send_static(d)) d.buttons.insert(0, b) self.transaction_dialog_update(d)
def show_install_plugin_preview_dialog(self, file_path): plugin_manager = self.main_window.gui_object.plugins # We need to poll the file to see if it is valid. plugin_metadata, result_code = plugin_manager.get_metadata_from_external_plugin_zip_file( file_path) if plugin_metadata is not None: self.installWarningDialog = d = ExternalPluginsPreviewDialog( self, self.main_window, _("Plugin Preview"), plugin_path=file_path) d.exec_() else: self.show_error( INSTALL_ERROR_MESSAGES.get( result_code, _("Unexpected error %d") % result_code))
def _notok_synch(self, window, exc_info): # Runs in main thread cls = __class__ if window.isVisible() and not cls._warn_dlg_flg.get(window, False): # Guard against duplicate error dialogs (without this we may get error window spam when importing labels) cls._warn_dlg_flg[window] = True window.show_warning(_("LabelSync error:") + "\n\n" + str(exc_info[1]), rich_text=False) cls._warn_dlg_flg.pop(window, None)