From b2b2708e8162820993409c637a2dad6a31efe88d Mon Sep 17 00:00:00 2001 From: PastaClaw Date: Sun, 15 Mar 2026 11:36:36 -0500 Subject: [PATCH 1/2] fix(ui): improve auth key error message and suppress on startup auto-select MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Better error message: Include the identity alias/DPNS name and ID in the error, so users with multiple identities can identify which one lacks a signing key. Before: Identity doesn't have an authentication key for signing document transitions After: Identity 'my-evonode' (7xK3...) doesn't have an authentication key for signing document transitions 2. Suppress banner on auto-select: The ContactRequests and QRCodeGenerator screens auto-select the first identity during construction. If that identity lacks a document signing key (e.g., evonode identities), the error was shown immediately before the user did anything. Now these screens silently set wallet to None on auto-select — the error only appears when the user explicitly selects an identity that lacks the key. Closes #743 --- src/ui/dashpay/contact_requests.rs | 7 +++---- src/ui/dashpay/qr_code_generator.rs | 7 +++---- src/ui/identities/mod.rs | 13 +++++++++++-- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/ui/dashpay/contact_requests.rs b/src/ui/dashpay/contact_requests.rs index c26de21f4..a86bed5bd 100644 --- a/src/ui/dashpay/contact_requests.rs +++ b/src/ui/dashpay/contact_requests.rs @@ -103,11 +103,10 @@ impl ContactRequests { .id() .to_string(dash_sdk::dpp::platform_value::string_encoding::Encoding::Base58); - // Get wallet for the selected identity + // Get wallet for the selected identity (don't show error on auto-select; + // some identities like evonodes may lack document signing keys) new_self.selected_wallet = - get_selected_wallet(&identities[0], Some(&app_context), None) - .or_show_error(app_context.egui_ctx()) - .unwrap_or(None); + get_selected_wallet(&identities[0], Some(&app_context), None).unwrap_or(None); // Load requests from database for this identity new_self.load_requests_from_database(); diff --git a/src/ui/dashpay/qr_code_generator.rs b/src/ui/dashpay/qr_code_generator.rs index 412c690f8..1e71046f6 100644 --- a/src/ui/dashpay/qr_code_generator.rs +++ b/src/ui/dashpay/qr_code_generator.rs @@ -77,11 +77,10 @@ impl QRCodeGeneratorScreen { new_self.selected_identity_string = identities[0].identity.id().to_string(Encoding::Base58); - // Get wallet for the selected identity + // Get wallet for the selected identity (don't show error on auto-select; + // some identities like evonodes may lack document signing keys) new_self.selected_wallet = - get_selected_wallet(&identities[0], Some(&app_context), None) - .or_show_error(app_context.egui_ctx()) - .unwrap_or(None); + get_selected_wallet(&identities[0], Some(&app_context), None).unwrap_or(None); } new_self diff --git a/src/ui/identities/mod.rs b/src/ui/identities/mod.rs index d582aa176..165a5f034 100644 --- a/src/ui/identities/mod.rs +++ b/src/ui/identities/mod.rs @@ -78,8 +78,17 @@ pub fn get_selected_wallet( qualified_identity .document_signing_key(&preorder_document_type) .ok_or_else(|| { - "Identity doesn't have an authentication key for signing document transitions" - .to_string() + use dash_sdk::dpp::identity::accessors::IdentityGettersV0; + let identity_label = qualified_identity + .alias + .as_deref() + .or_else(|| qualified_identity.dpns_names.first().map(|n| n.name.as_str())) + .unwrap_or("unknown"); + format!( + "Identity '{}' ({}) doesn't have an authentication key for signing document transitions", + identity_label, + qualified_identity.identity.id() + ) })? } else { // Fallback: directly use the provided selected key. From a6bd8f37f075e2ff55d2a3e7a595ef589804c861 Mon Sep 17 00:00:00 2001 From: PastaClaw Date: Sun, 15 Mar 2026 16:34:20 -0500 Subject: [PATCH 2/2] fix: remove quotes from identity label and use empty string for unknown Per lklimek's review: remove single quotes around identity label in error message, and use empty string instead of 'unknown' when no alias/DPNS name is available. --- src/ui/dashpay/contact_requests.rs | 17 +++++++++++++---- src/ui/dashpay/qr_code_generator.rs | 17 +++++++++++++---- src/ui/identities/mod.rs | 29 +++++++++++++++++++++++++---- 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/src/ui/dashpay/contact_requests.rs b/src/ui/dashpay/contact_requests.rs index a86bed5bd..627d233d0 100644 --- a/src/ui/dashpay/contact_requests.rs +++ b/src/ui/dashpay/contact_requests.rs @@ -12,8 +12,8 @@ use crate::ui::components::wallet_unlock_popup::{ WalletUnlockPopup, WalletUnlockResult, try_open_wallet_no_password, wallet_needs_unlock, }; use crate::ui::components::{MessageBanner, ResultBannerExt}; -use crate::ui::identities::get_selected_wallet; use crate::ui::identities::keys::add_key_screen::AddKeyScreen; +use crate::ui::identities::{get_selected_wallet, is_missing_document_signing_key_error}; use crate::ui::theme::DashColors; use crate::ui::{MessageType, Screen, ScreenLike, ScreenType}; use dash_sdk::dpp::document::DocumentV0Getters; @@ -103,10 +103,19 @@ impl ContactRequests { .id() .to_string(dash_sdk::dpp::platform_value::string_encoding::Encoding::Base58); - // Get wallet for the selected identity (don't show error on auto-select; - // some identities like evonodes may lack document signing keys) + // Get wallet for the selected identity. Suppress the expected + // "missing document-signing key" error on auto-select (some + // identities, e.g. evonodes, legitimately lack one); surface + // anything else so we don't silently hide real failures. new_self.selected_wallet = - get_selected_wallet(&identities[0], Some(&app_context), None).unwrap_or(None); + match get_selected_wallet(&identities[0], Some(&app_context), None) { + Ok(wallet) => wallet, + Err(e) if is_missing_document_signing_key_error(&e) => None, + Err(e) => { + MessageBanner::set_global(app_context.egui_ctx(), &e, MessageType::Error); + None + } + }; // Load requests from database for this identity new_self.load_requests_from_database(); diff --git a/src/ui/dashpay/qr_code_generator.rs b/src/ui/dashpay/qr_code_generator.rs index 1e71046f6..04f650920 100644 --- a/src/ui/dashpay/qr_code_generator.rs +++ b/src/ui/dashpay/qr_code_generator.rs @@ -15,7 +15,7 @@ use crate::ui::components::wallet_unlock_popup::{ use crate::ui::components::{MessageBanner, ResultBannerExt}; use crate::ui::dashpay::dashpay_screen::DashPaySubscreen; use crate::ui::identities::funding_common::generate_qr_code_image; -use crate::ui::identities::get_selected_wallet; +use crate::ui::identities::{get_selected_wallet, is_missing_document_signing_key_error}; use crate::ui::theme::DashColors; use crate::ui::{MessageType, RootScreenType, ScreenLike}; use eframe::epaint::TextureHandle; @@ -77,10 +77,19 @@ impl QRCodeGeneratorScreen { new_self.selected_identity_string = identities[0].identity.id().to_string(Encoding::Base58); - // Get wallet for the selected identity (don't show error on auto-select; - // some identities like evonodes may lack document signing keys) + // Get wallet for the selected identity. Suppress the expected + // "missing document-signing key" error on auto-select (some + // identities, e.g. evonodes, legitimately lack one); surface + // anything else so we don't silently hide real failures. new_self.selected_wallet = - get_selected_wallet(&identities[0], Some(&app_context), None).unwrap_or(None); + match get_selected_wallet(&identities[0], Some(&app_context), None) { + Ok(wallet) => wallet, + Err(e) if is_missing_document_signing_key_error(&e) => None, + Err(e) => { + MessageBanner::set_global(app_context.egui_ctx(), &e, MessageType::Error); + None + } + }; } new_self diff --git a/src/ui/identities/mod.rs b/src/ui/identities/mod.rs index 165a5f034..a199b90c5 100644 --- a/src/ui/identities/mod.rs +++ b/src/ui/identities/mod.rs @@ -28,6 +28,20 @@ pub mod top_up_identity_screen; pub mod transfer_screen; pub mod withdraw_screen; +/// Substring used to identify the "missing document-signing key" error returned +/// by [`get_selected_wallet`] when an identity has no key suitable for signing +/// document state transitions. Callsites that auto-select an identity (e.g. +/// DashPay startup) use this to suppress the expected case while still +/// surfacing unrelated errors. +const MISSING_DOCUMENT_SIGNING_KEY_MARKER: &str = + "doesn't have an authentication key for signing document transitions"; + +/// Returns `true` if the given error string is the expected +/// "identity has no document-signing key" error from [`get_selected_wallet`]. +pub fn is_missing_document_signing_key_error(error: &str) -> bool { + error.contains(MISSING_DOCUMENT_SIGNING_KEY_MARKER) +} + /// Retrieves the appropriate wallet (if any) associated with the given identity. /// /// # Description @@ -79,15 +93,22 @@ pub fn get_selected_wallet( .document_signing_key(&preorder_document_type) .ok_or_else(|| { use dash_sdk::dpp::identity::accessors::IdentityGettersV0; + use dash_sdk::dpp::platform_value::string_encoding::Encoding; let identity_label = qualified_identity .alias .as_deref() - .or_else(|| qualified_identity.dpns_names.first().map(|n| n.name.as_str())) - .unwrap_or("unknown"); + .or_else(|| { + qualified_identity + .dpns_names + .first() + .map(|n| n.name.as_str()) + }) + .unwrap_or(""); format!( - "Identity '{}' ({}) doesn't have an authentication key for signing document transitions", + "Identity {} ({}) {}", identity_label, - qualified_identity.identity.id() + qualified_identity.identity.id().to_string(Encoding::Base58), + MISSING_DOCUMENT_SIGNING_KEY_MARKER, ) })? } else {