Skip to content

fix(ui): improve platform address validation consistency across UI screens#592

Merged
QuantumExplorer merged 7 commits into
dashpay:v1.0-devfrom
thepastaclaw:fix/platform-address-validation-consistency
Feb 17, 2026
Merged

fix(ui): improve platform address validation consistency across UI screens#592
QuantumExplorer merged 7 commits into
dashpay:v1.0-devfrom
thepastaclaw:fix/platform-address-validation-consistency

Conversation

@thepastaclaw
Copy link
Copy Markdown
Collaborator

@thepastaclaw thepastaclaw commented Feb 17, 2026

Summary

After PR #575 introduced DIP-18 HRP support (evo1.../tevo1... Bech32m platform addresses), several UI screens had stale hint text or inconsistent address validation. This PR fixes 4 issues to make the UI consistent with the backend.

Reported by @lklimek — the platform address validation in input fields had improper validation where the backend checked properly but the frontend did not.

Changes (4 commits)

1. fix(ui): correct platform address hint text in transfer screen

File: src/ui/identities/transfer_screen.rs

  • Changed hint text from "Enter Platform address (y...)" to "Enter Platform address (evo1.../tevo1...)"
  • The validate_platform_address() already handled both formats correctly; only the hint was stale

2. fix(ui): add network-aware hint text and platform address detection in withdraw screen

File: src/ui/identities/withdraw_screen.rs

  • Added network-aware hint text: "Enter Core address (X.../7...) or Platform address (evo1.../tevo1...)"
  • Added platform address prefix detection (evo1/tevo1) to auto-switch the is_platform_transfer toggle
  • Previously only detected legacy y-prefix addresses as platform transfers

3. fix(ui): use network-aware hint text in wallet send dialog

File: src/ui/wallet/send_screen.rs

  • Added network-aware hint text showing both Core and Platform address prefixes
  • Mainnet: "Enter Core (X.../7...) or Platform (evo1...) address"
  • Testnet: "Enter Core (y.../8...) or Platform (tevo1...) address"

4. fix(ui): add inline address validation to wallet send dialog

File: src/ui/wallet/send_screen.rs

  • Added real-time address validation that checks if the entered address is a valid Core or Platform address
  • Shows validation error message when input is non-empty but invalid
  • Uses both Address::from_str() and PlatformAddress::from_bech32m_string() for comprehensive validation

Testing

  • Verified compilation with cargo check
  • Changes are UI-only (hint text + validation display), no backend logic changes

Breaking Changes

None.

Summary by CodeRabbit

  • New Features

    • Address inputs now show network-specific hint text and provide inline address error feedback.
    • Lightweight platform-address detection added to improve UI validation experience.
  • Bug Fixes

    • Validation updated to recognize dash/tdash Bech32m platform addresses and reject them where Core addresses are required.
    • Retained fallback parsing for legacy formats and clarified error wording to "Invalid Core address".
  • Documentation

    • User-facing docs and hints updated to reference dash/tdash Bech32m HRP per DIP-18.

thepastaclaw and others added 4 commits February 17, 2026 09:33
The hint text showed "y..." which is a Core address prefix. Platform
addresses use evo1.../tevo1... (Bech32m format per DIP-18).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…n withdraw screen

The withdraw screen only supports Core addresses but had no hint text
and showed a generic "Invalid address" for platform addresses. Now shows
network-appropriate Core address hints and a specific error message when
a user enters an evo1.../tevo1... platform address.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The send dialog hint text showed "y..." which is only valid for
testnet/devnet. Now shows network-appropriate Core address prefixes
(X.../7... for mainnet, y.../8... for testnet).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The send dialog had no frontend address validation — invalid addresses
only errored at the backend level. Now validates on input change using
Address parsing with inline error display, and detects platform addresses
(evo1.../tevo1...) with a specific unsupported format message.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread src/ui/identities/transfer_screen.rs Outdated
ui.add(
egui::TextEdit::singleline(&mut self.platform_address_input)
.hint_text("Enter Platform address (y...)")
.hint_text("Enter Platform address (evo1.../tevo1...)")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we use dash/tdash right? not evo/tevo

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right — fixing all evo/tevo references to dash/tdash per DIP-18. Also adding a shared is_platform_address() helper that uses the SDK's PLATFORM_HRP_MAINNET/PLATFORM_HRP_TESTNET constants + the 1 separator instead of hardcoding prefixes. Force push incoming.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right — the SDK uses dash/tdash as the HRP (from DIP-18), so addresses are dash1.../tdash1.... I copied the stale evo1/tevo1 from the existing codebase. Fixing now.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 17, 2026

📝 Walkthrough

Walkthrough

UI and docs updated to adopt DIP-18 naming and detection for Platform Bech32m addresses (dash1/tdash1). Added a lightweight is_platform_address_string helper, made address input hints network-aware, trim-and-validate inputs, reject platform Bech32m where Core (base58) addresses are required, and surface clearer error text.

Changes

Cohort / File(s) Summary
Platform detection helper
src/ui/helpers.rs
Added pub fn is_platform_address_string(&str) -> bool — lightweight, case-insensitive HRP check for dash/tdash Bech32m-like strings (no full validation).
Identity screens
src/ui/identities/transfer_screen.rs, src/ui/identities/withdraw_screen.rs
Hint text updated to dash1.../tdash1...; input replaced with network-aware TextEdit in withdraw; trimming and platform-address (Bech32m) detection added; platform inputs rejected with explicit error; Core-address parsing preserved.
Wallet send UI & dialogs
src/ui/wallets/wallets_screen/dialogs.rs, src/ui/wallets/send_screen.rs, src/ui/wallets/wallets_screen/address_table.rs, src/ui/wallets/account_summary.rs
Introduced Network usage and address_error: Option<String> in SendDialogState; recipient hints are network-aware; validation trims input, uses is_platform_address_string(...) to detect/reject platform Bech32m, falls back to Core address parsing and shows "Invalid Core address"; updated doc/example strings to dash/tdash HRP.
Address tools screen
src/ui/tools/address_balance_screen.rs
UI label and hint text changed to reference dash1.../tdash1...; no control-flow changes.
Database & model docs
src/database/wallet.rs, src/model/wallet/mod.rs
Documentation comments adjusted to reference dash/tdash Bech32m HRP per DIP-18 (no behavioral/code changes).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I hopped through strings and trimmed each end,
Spotted dash1 tails and gave them a mend,
I taught the UI when to say "That's wrong",
Core addresses hum their steady song,
Hooray — the ledger hops along!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main objective: improving platform address validation consistency across UI screens, which aligns with the core changes throughout multiple UI files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/ui/identities/transfer_screen.rs (1)

248-253: Consider making the platform address hint network-aware for consistency.

The other screens in this PR (withdraw_screen.rs, dialogs.rs) branch on self.app_context.network == Network::Dash to show network-specific hints. This screen shows both evo1.../tevo1... regardless of network, which is slightly inconsistent and can confuse users (e.g., showing tevo1... on mainnet).

Suggested network-aware hint
-                    .hint_text("Enter Platform address (evo1.../tevo1...)")
+                    .hint_text(if self.app_context.network == dash_sdk::dashcore_rpc::dashcore::Network::Dash {
+                        "Enter Platform address (evo1...)"
+                    } else {
+                        "Enter Platform address (tevo1...)"
+                    })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/identities/transfer_screen.rs` around lines 248 - 253, Update the
platform address hint to be network-aware: in the UI code that builds the
TextEdit for self.platform_address_input (the block where
egui::TextEdit::singleline is used), check self.app_context.network (the same
enum used elsewhere like Network::Dash in withdraw_screen.rs and dialogs.rs) and
set the hint_text accordingly (e.g., "Enter Platform address (evo1...)" for Dash
vs "Enter Platform address (tevo1...)" for other networks). Modify only the hint
text construction so it mirrors the branching pattern used in
withdraw_screen.rs/dialogs.rs, referencing self.app_context.network and
Network::Dash to choose the correct hint.
src/ui/wallets/wallets_screen/dialogs.rs (1)

222-233: Send button is not disabled when address_error is present.

The withdraw screen (line 576) gates its button with !has_address_error, but here the Send button remains clickable even when the inline validation shows an error. Consider disabling the button for consistency:

Suggested fix
+                let has_address_error = self.send_dialog.address_error.is_some();
                 ui.horizontal(|ui| {
-                    if ui.button("Send").clicked() {
+                    if ui.add_enabled(!has_address_error, egui::Button::new("Send")).clicked() {
                         match self.prepare_send_action() {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/wallets/wallets_screen/dialogs.rs` around lines 222 - 233, The Send
button is still clickable even when there's an inline address validation error;
update the UI to disable the Send button when send_dialog has an address_error
(mirror the withdraw screen's gating). Wrap the button in an enabled/disabled
container (e.g., use ui.add_enabled(...) or equivalent) checking
!self.send_dialog.address_error.is_some() (or a has_address_error helper) so the
existing click/prepare_send_action() path only runs when no address error; refer
to send_dialog, prepare_send_action, and the Send button block to apply the
change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/ui/identities/withdraw_screen.rs`:
- Around line 160-181: The validation currently trims input into the local
variable trimmed but still calls Address::from_str(&self.withdrawal_address),
causing valid addresses with surrounding whitespace to fail; update the
validation in the response.changed() branch to call Address::from_str(trimmed)
(and on success clear self.withdrawal_address_error, on error set it to "Invalid
Core address") and ensure any other checks (e.g., starts_with("evo1") / "tevo1")
continue to use trimmed so all validation uses the trimmed string.

---

Nitpick comments:
In `@src/ui/identities/transfer_screen.rs`:
- Around line 248-253: Update the platform address hint to be network-aware: in
the UI code that builds the TextEdit for self.platform_address_input (the block
where egui::TextEdit::singleline is used), check self.app_context.network (the
same enum used elsewhere like Network::Dash in withdraw_screen.rs and
dialogs.rs) and set the hint_text accordingly (e.g., "Enter Platform address
(evo1...)" for Dash vs "Enter Platform address (tevo1...)" for other networks).
Modify only the hint text construction so it mirrors the branching pattern used
in withdraw_screen.rs/dialogs.rs, referencing self.app_context.network and
Network::Dash to choose the correct hint.

In `@src/ui/wallets/wallets_screen/dialogs.rs`:
- Around line 222-233: The Send button is still clickable even when there's an
inline address validation error; update the UI to disable the Send button when
send_dialog has an address_error (mirror the withdraw screen's gating). Wrap the
button in an enabled/disabled container (e.g., use ui.add_enabled(...) or
equivalent) checking !self.send_dialog.address_error.is_some() (or a
has_address_error helper) so the existing click/prepare_send_action() path only
runs when no address error; refer to send_dialog, prepare_send_action, and the
Send button block to apply the change.

Comment thread src/ui/identities/withdraw_screen.rs
…tevo prefixes

- Add is_platform_address_string() helper using SDK's PLATFORM_HRP_MAINNET/TESTNET constants
- Replace all hardcoded starts_with("evo1")/starts_with("tevo1") checks with the helper
- Update all UI hint text, error messages, and doc comments to reference dash1.../tdash1...
- The '1' is the bech32 separator, not part of the HRP — detection now properly uses HRP + separator

Addresses review feedback on PR dashpay#592.
@thepastaclaw thepastaclaw force-pushed the fix/platform-address-validation-consistency branch from 80e8d1e to f9d1859 Compare February 17, 2026 15:56
- Use trimmed input for Address::from_str in withdraw_screen (bug fix)
- Make transfer_screen hint text network-aware (dash1 vs tdash1)
- Disable Send button when address validation error is present
Copy link
Copy Markdown
Contributor

@thephez thephez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partially tested ACK (identity create worked)

@thepastaclaw
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 17, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@PastaPastaPasta
Copy link
Copy Markdown
Member

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 17, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/ui/helpers.rs (2)

1-17: Run clippy and fmt before finalizing.

Please run cargo clippy and cargo +nightly fmt to conform with the repo’s Rust workflow checks.

As per coding guidelines: **/*.rs: Always run cargo clippy and cargo +nightly fmt when finalizing work.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/helpers.rs` around lines 1 - 17, Run the repository Rust linters and
formatter on your changes: execute cargo clippy and cargo +nightly fmt, then fix
any warnings/errors reported (especially in the is_platform_address_string
function and any use of PLATFORM_HRP_MAINNET / PLATFORM_HRP_TESTNET) so code
conforms to project style and clippy suggestions before finalizing the PR.

4-17: Add a tiny inline test for the new helper.

This is small but easy to lock down with a couple of prefix/negative cases.

💡 Suggested inline test
+#[cfg(test)]
+mod tests {
+    use super::is_platform_address_string;
+
+    #[test]
+    fn detects_platform_hrp_prefixes() {
+        assert!(is_platform_address_string("dash1qqqq"));
+        assert!(is_platform_address_string("tdash1qqqq"));
+        assert!(!is_platform_address_string("evo1qqqq"));
+        assert!(!is_platform_address_string("XyZ123"));
+    }
+}

As per coding guidelines: src/**/*.rs: Unit tests should be inline in source files using #[test] attribute; UI integration tests in tests/kittest/; E2E tests in tests/e2e/.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/helpers.rs` around lines 4 - 17, Add an inline unit test for
is_platform_address_string by creating a #[cfg(test)] mod tests in the same file
and a #[test] fn (e.g., test_is_platform_address_string) that asserts true for
strings built from PLATFORM_HRP_MAINNET and PLATFORM_HRP_TESTNET followed by '1'
and some payload (e.g., format!("{}1{}", PLATFORM_HRP_MAINNET, "abcd")), and
asserts false for negative cases like wrong HRP (e.g., "x1abcd"), missing
separator (e.g., format!("{}abcd", PLATFORM_HRP_MAINNET)), and other invalid
prefixes; reference the function is_platform_address_string and the constants
PLATFORM_HRP_MAINNET and PLATFORM_HRP_TESTNET in the test to lock behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/ui/helpers.rs`:
- Around line 1-17: Run the repository Rust linters and formatter on your
changes: execute cargo clippy and cargo +nightly fmt, then fix any
warnings/errors reported (especially in the is_platform_address_string function
and any use of PLATFORM_HRP_MAINNET / PLATFORM_HRP_TESTNET) so code conforms to
project style and clippy suggestions before finalizing the PR.
- Around line 4-17: Add an inline unit test for is_platform_address_string by
creating a #[cfg(test)] mod tests in the same file and a #[test] fn (e.g.,
test_is_platform_address_string) that asserts true for strings built from
PLATFORM_HRP_MAINNET and PLATFORM_HRP_TESTNET followed by '1' and some payload
(e.g., format!("{}1{}", PLATFORM_HRP_MAINNET, "abcd")), and asserts false for
negative cases like wrong HRP (e.g., "x1abcd"), missing separator (e.g.,
format!("{}abcd", PLATFORM_HRP_MAINNET)), and other invalid prefixes; reference
the function is_platform_address_string and the constants PLATFORM_HRP_MAINNET
and PLATFORM_HRP_TESTNET in the test to lock behavior.

@QuantumExplorer QuantumExplorer merged commit 8b733da into dashpay:v1.0-dev Feb 17, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants