Skip to content

backport: feat(wallet): add Mine Blocks dialog for Regtest/Devnet dev mode#638

Merged
lklimek merged 8 commits into
v1.0-devfrom
zk-extract/mine-blocks-dialog
Feb 24, 2026
Merged

backport: feat(wallet): add Mine Blocks dialog for Regtest/Devnet dev mode#638
lklimek merged 8 commits into
v1.0-devfrom
zk-extract/mine-blocks-dialog

Conversation

@lklimek
Copy link
Copy Markdown
Contributor

@lklimek lklimek commented Feb 24, 2026

Summary

  • Adds a "Mine" button to the wallet toolbar (visible only in developer mode on Regtest/Devnet with RPC backend)
  • New CoreTask::MineBlocks variant calls generate_to_address() and refreshes wallet balances
  • Dialog lets user pick a wallet address and specify block count

Test plan

Manual test scenarios: docs/ai-design/2026-02-24-mine-blocks-dialog/manual-test-scenarios.md

  • Mine button visible on Regtest + dev mode + RPC
  • Mine button hidden on Mainnet/Testnet/SPV/non-dev
  • Dialog: select address, enter block count, mine
  • Wallet balance updates after mining
  • Input validation (zero, negative, non-numeric rejected)
  • Cancel/close resets dialog state

🤖 Co-authored by Claudius the Magnificent AI Agent

Summary by CodeRabbit

  • New Features

    • Added a developer-only "Mine" button (Dev/Regtest/Devnet + RPC) that opens a Mine Blocks dialog to choose an address, enter block count, mine blocks, and auto-refresh balances with success feedback.
  • Tests

    • Added 24 manual test scenarios covering dialog visibility, address selection, input validation, mining flows, error cases, network/developer-mode switches, and balance refresh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@lklimek lklimek self-assigned this Feb 24, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 24, 2026

Warning

Rate limit exceeded

@lklimek has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 1 minutes and 5 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between dc3759d and 90cc2cd.

📒 Files selected for processing (3)
  • src/backend_task/core/mod.rs
  • src/backend_task/mod.rs
  • src/ui/wallets/wallets_screen/dialogs.rs
📝 Walkthrough

Walkthrough

Adds a dev-mode "Mine Blocks" feature: UI dialog for selecting a core address and block count, backend CoreTask::MineBlocks to generate blocks and refresh wallet balances, and documentation with 24 manual test scenarios.

Changes

Cohort / File(s) Summary
Documentation
docs/ai-design/2026-02-24-mine-blocks-dialog/manual-test-scenarios.md
New manual test scenarios (24 cases) describing Mine dialog visibility, interactions, address selection, block count validation, error paths, RPC failures, and network/mode edge cases.
Backend core task
src/backend_task/core/mod.rs
Added CoreTask::MineBlocks { block_count, address, wallet } handling: calls core client generate_to_address, computes mined count, triggers wallet refresh, returns MineBlocksSuccess.
Backend task results
src/backend_task/mod.rs
Added BackendTaskSuccessResult::MineBlocksSuccess(usize) variant to represent mining results.
UI — Dialog logic
src/ui/wallets/wallets_screen/dialogs.rs
Added MineDialogState and functions: open_mine_dialog, load_core_addresses_for_mine, render_mine_dialog — handles address loading, selection, block count input, validation, error display, and dispatching CoreTask::MineBlocks.
UI — Integration
src/ui/wallets/wallets_screen/mod.rs
Added mine_dialog: MineDialogState to WalletsBalancesScreen, initialized in constructors; shows a developer-only "Mine" button in dev RPC modes; invokes dialog rendering; handles MineBlocksSuccess to clear refreshing state and show success message.

Sequence Diagram

sequenceDiagram
    participant User
    participant UI as Mine Dialog (UI)
    participant Backend as AppContext / Backend Task
    participant Core as Core Client
    participant Wallet as Wallet

    User->>UI: Open Mine Dialog
    UI->>Wallet: Request core addresses & balances
    Wallet-->>UI: Return addresses
    User->>UI: Select address & enter block count
    UI->>Backend: Dispatch CoreTask::MineBlocks(block_count, address, wallet)
    Backend->>Core: generate_to_address(block_count, address)
    Core-->>Backend: Return mined blocks
    Backend->>Wallet: Refresh balances
    Wallet-->>Backend: Balances updated
    Backend-->>UI: MineBlocksSuccess(mined_count)
    UI->>User: Display success message
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I tunneled to a devnet light,
Clicked "Mine" and watched the blocks take flight,
Addresses chosen, counters set just right,
Balances bloom in morning bright,
Hooray—fresh coins for testing night! 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the primary change: adding a Mine Blocks dialog feature for Regtest/Devnet development mode, which aligns with all five files modified in the changeset.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch zk-extract/mine-blocks-dialog

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.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
lklimek and others added 2 commits February 24, 2026 18:30
The dialog stayed open (in a broken state) after clicking Mine or Cancel
because the local `open` variable was written back to `is_open` after the
dialog state had already been reset. Pass `is_open` directly to egui's
`.open()` and use a separate `close` flag for button-triggered dismissal.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@lklimek lklimek marked this pull request as ready for review February 24, 2026 17:44
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 (1)
src/backend_task/core/mod.rs (1)

284-306: Move generate_to_address into spawn_blocking to prevent blocking the async runtime.

The RPC call is synchronous and will block until all blocks are generated. For large block counts, this blocks a tokio worker thread. The codebase already uses spawn_blocking for other blocking RPC operations (wallet refresh, asset lock recovery); this should follow the same pattern.

♻️ Proposed adjustment
-                let mined = self
-                    .core_client
-                    .read()
-                    .expect("Core client lock was poisoned")
-                    .generate_to_address(block_count, &address)
-                    .map_err(|e| e.to_string())?;
+                let core_client = self.core_client.clone();
+                let address = address.clone();
+                let mined = tokio::task::spawn_blocking(move || {
+                    core_client
+                        .read()
+                        .expect("Core client lock was poisoned")
+                        .generate_to_address(block_count, &address)
+                })
+                .await
+                .map_err(|e| format!("Task join error: {}", e))?
+                .map_err(|e| e.to_string())?;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/backend_task/core/mod.rs` around lines 284 - 306, The synchronous RPC
call generate_to_address inside CoreTask::MineBlocks blocks the async runtime;
move the generate_to_address call into a tokio::task::spawn_blocking closure so
the blocking RPC runs off the async executor. Inside the closure acquire the
core_client read lock, call generate_to_address(block_count, &address), and
return the mined result (or its length) and any error; then await the
spawn_blocking result and map errors as before. After that, perform the wallet
refresh (calling ctx.refresh_wallet_info(wallet)) either in a subsequent
spawn_blocking or in the same blocking closure before returning, preserving the
existing error mappings and ultimately returning
BackendTaskSuccessResult::MineBlocksSuccess(mined_count).
🤖 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/backend_task/core/mod.rs`:
- Around line 284-306: The synchronous RPC call generate_to_address inside
CoreTask::MineBlocks blocks the async runtime; move the generate_to_address call
into a tokio::task::spawn_blocking closure so the blocking RPC runs off the
async executor. Inside the closure acquire the core_client read lock, call
generate_to_address(block_count, &address), and return the mined result (or its
length) and any error; then await the spawn_blocking result and map errors as
before. After that, perform the wallet refresh (calling
ctx.refresh_wallet_info(wallet)) either in a subsequent spawn_blocking or in the
same blocking closure before returning, preserving the existing error mappings
and ultimately returning
BackendTaskSuccessResult::MineBlocksSuccess(mined_count).

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 79e1479 and 29995bb.

📒 Files selected for processing (5)
  • docs/ai-design/2026-02-24-mine-blocks-dialog/manual-test-scenarios.md
  • src/backend_task/core/mod.rs
  • src/backend_task/mod.rs
  • src/ui/wallets/wallets_screen/dialogs.rs
  • src/ui/wallets/wallets_screen/mod.rs

@lklimek
Copy link
Copy Markdown
Contributor Author

lklimek commented Feb 24, 2026

🔍 Audit Report: PR #638 — Mine Blocks Dialog

Reviewed by: Claude Code with a 3-agent team:

  • code-reviewer (Opus) — backend logic, patterns, error handling
  • code-reviewer (Opus) — UI dialog patterns, egui conventions
  • security-engineer (Opus) — access control, input validation, OWASP

PR scope (from GitHub base): 5 files, +701 / -1 lines

Findings Summary

# Severity Location Finding
1 HIGH core/mod.rs:289-294 generate_to_address blocks async runtime — wrapped in spawn_blocking
2 HIGH core/mod.rs:291 .expect() on lock panics — replaced with .map_err()?
3 HIGH dialogs.rs:1409 No upper bound on block count — capped at 1000
4 MEDIUM core/mod.rs:284 No backend-side network guard (OWASP A01)
5 MEDIUM dialogs.rs:1376 Error display inconsistent with Send dialog
6 MEDIUM dialogs.rs:1368 Text input accepts non-numeric chars
7 MEDIUM dialogs.rs:1237 Dialog opens with error when no wallet selected
8 LOW dialogs.rs:1429 assume_checked() bypasses network validation
9 LOW mod.rs:268 MineBlocksSuccess(usize) vs block_count: u64
10 LOW dialogs.rs:1333 &addr[..12] fragile on non-ASCII
11 LOW dialogs.rs:1310 Close pattern differs from other dialogs

✅ = Fixed in follow-up commit

Pre-existing / Outside-Diff Issues

These are in the v1.0-dev base, not introduced by this PR:

Finding Location Note
UTXOs not removed when register_addresses is None asset_lock_transaction.rs:433 API invites misuse; not a live bug today
Implicit 1 duff/byte fee rate undocumented asset_lock_transaction.rs:50 Named constant recommended
Duplicated balance computation mod.rs:1855-1879 Extract shared helper
configure-local.sh single-quote quoting bug scripts/configure-local.sh:46 Password may include literal quotes

Positive Observations

  • ✅ UI access control gating is thorough (network + dev mode + RPC backend)
  • ✅ Excellent test coverage for calculate_asset_lock_fee including regression tests
  • ✅ Clean reload_utxos simplification with Result<bool, String> return
  • ✅ Well-designed atomic select-then-remove UTXO pattern with &mut self enforcement
  • refresh_wallet_info after mining correctly in spawn_blocking

🤖 Reviewed by Claudius the Magnificent AI Agent

lklimek and others added 2 commits February 24, 2026 18:57
- Wrap `generate_to_address` in `spawn_blocking` to avoid blocking
  the async runtime thread (HIGH)
- Replace `.expect()` on core client lock with `.map_err()?` for
  graceful error handling instead of panic (HIGH)
- Cap block count at 1000 to prevent resource exhaustion on the
  Core node (HIGH)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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 (4)
src/ui/wallets/wallets_screen/dialogs.rs (3)

1374-1377: Error display is inconsistent with the send dialog's styled error frame.

The send dialog renders errors inside a colored Frame with a "Dismiss" button (lines 206–223). The mine dialog just renders a plain colored label. If unifying error presentation across dialogs is desirable, the same Frame-with-dismiss pattern can be reused here.

🤖 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 1374 - 1377, The mine
dialog currently shows errors as a plain colored label (self.mine_dialog.error);
change it to match the send dialog's styled error Frame-with-"Dismiss" button
pattern by rendering the error inside the same Frame (using the same
color/styling helpers like DashColors::error_color(dark_mode)), include a
"Dismiss" button identical to the send dialog's behavior, and wire the button to
clear the error (e.g., set self.mine_dialog.error = None or call the same
dismiss helper used by the send dialog) so the UI and dismissal behavior are
consistent across dialogs.

1236-1241: Dialog opens in an error state when no wallet is selected.

When selected_wallet is None, the dialog opens immediately showing "Select a wallet first". Since the Mine button is gated by dev mode + RPC + Regtest/Devnet network, a wallet should always be selected by the time this dialog is reachable. If the intent is a defensive guard, consider not opening the dialog at all and instead surfacing the message through a MessageBanner or tooltip so the dialog stays closed until a wallet is selected.

🤖 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 1236 - 1241, The
open_mine_dialog currently opens the dialog and sets mine_dialog.error when
selected_wallet is None; change this so the dialog is not opened in that case:
in open_mine_dialog, if self.selected_wallet is None, do not set
mine_dialog.is_open or mine_dialog.error but instead surface the feedback via
the existing MessageBanner/tooltip mechanism (or set a banner state like
self.message_banner = Some("Select a wallet first")) so the dialog remains
closed until a wallet is selected; update references to selected_wallet,
mine_dialog.error, and mine_dialog.is_open in open_mine_dialog accordingly.

1253-1293: Extract a shared helper to eliminate near-identical address-loading logic.

load_core_addresses_for_mine is a near-verbatim copy of load_core_addresses_for_receive (lines 1132–1175). The only differences are which dialog fields receive the results. A helper that returns the loaded addresses can serve both:

fn load_bip44_external_addresses(
    &self,
    wallet: &Arc<RwLock<Wallet>>,
) -> Result<Vec<(String, u64)>, String> {
    let wallet_guard = wallet.read().map_err(|e| e.to_string())?;
    let network = self.app_context.network;
    let addresses: Vec<(String, u64)> = wallet_guard
        .watched_addresses
        .iter()
        .filter(|(path, _)| path.is_bip44_external(network))
        .map(|(_, info)| {
            let balance = wallet_guard
                .address_balances
                .get(&info.address)
                .copied()
                .unwrap_or(0);
            (info.address.to_string(), balance)
        })
        .collect();
    Ok(addresses)
}

Both load_core_addresses_for_* methods can then call this and handle the "empty → generate new" fallback independently.

There is also a minor inconsistency: load_core_addresses_for_receive explicitly calls self.receive_dialog.core_addresses.clear() on the generation-error path (line 1168), but load_core_addresses_for_mine omits the equivalent self.mine_dialog.core_addresses.clear() (line 1286). This is currently harmless since open_mine_dialog initialises the dialog with ..Default::default() before calling this function, but it should be made consistent.

🤖 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 1253 - 1293, Extract a
shared helper load_bip44_external_addresses(&self, wallet: &Arc<RwLock<Wallet>>)
-> Result<Vec<(String, u64)>, String> that acquires wallet.read(), filters
watched_addresses by path.is_bip44_external(self.app_context.network), maps to
(address.to_string(), balance) using address_balances, and returns the Vec or an
Err(String) on lock failure; then update both load_core_addresses_for_mine and
load_core_addresses_for_receive to call this helper and keep their individual
"if empty -> call generate_new_core_receive_address" fallback logic and dialog
assignments (leave generate_new_core_receive_address usage unchanged). Also make
the error path consistent by clearing self.mine_dialog.core_addresses on
generate_new_core_receive_address Err (matching receive_dialog behavior) and set
selected_address_index appropriately. Ensure references to
load_core_addresses_for_mine, load_core_addresses_for_receive,
load_bip44_external_addresses, generate_new_core_receive_address,
mine_dialog.core_addresses, receive_dialog.core_addresses, and mine_dialog.error
are used to locate and modify the code.
src/backend_task/core/mod.rs (1)

289-310: Add a network guard before dispatching generate_to_address.

The backend has no server-side check that the active network is Regtest or Devnet before calling generate_to_address. The UI enforces this at dispatch time, but if a MineBlocks task is ever constructed on the wrong network, the error surfaces only after the RPC round-trip. generate_to_address is a regtest-only command; adding an explicit guard here satisfies defense-in-depth and keeps the error message clear.

🛡️ Proposed guard
 CoreTask::MineBlocks {
     block_count,
     address,
     wallet,
 } => {
+    match self.network {
+        Network::Regtest | Network::Devnet => {}
+        net => {
+            return Err(format!(
+                "generate_to_address is only available on Regtest/Devnet, current network: {}",
+                net
+            ));
+        }
+    }
     let ctx = self.clone();

Rename the second ctx binding to avoid confusion.

The first ctx is moved into the initial spawn_blocking closure and consumed; the second let ctx = self.clone() at line 303 re-creates it for the wallet-refresh step. The reuse of the same name is correct but can be confusing when reading the diff.

♻️ Suggested rename
-    let ctx = self.clone();
-    tokio::task::spawn_blocking(move || ctx.refresh_wallet_info(wallet))
+    let refresh_ctx = self.clone();
+    tokio::task::spawn_blocking(move || refresh_ctx.refresh_wallet_info(wallet))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/backend_task/core/mod.rs` around lines 289 - 310, Before calling
generate_to_address, add an explicit guard that verifies the node is on Regtest
(or Devnet) and return a clear error if not; perform this check using the same
context used to access the RPC (e.g., via self or self.core_client.read()'s
network/state) so the regtest-only command is never dispatched on a public
network. After adding the network check, proceed to call generate_to_address
only when the guard passes. Also rename the second let ctx = self.clone() (used
before refresh_wallet_info) to a distinct name like ctx_refresh to avoid
shadowing/confusion with the earlier ctx moved into the first spawn_blocking
closure.
🤖 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/wallets/wallets_screen/dialogs.rs`:
- Around line 1436-1443: Replace the unsafe assume_checked() call with
require_network(...) to enforce the address network; specifically, when parsing
addr_str via addr_str.parse::<Address<NetworkUnchecked>>(), call
require_network(self.network) (or the appropriate Network value held by the
dialog/state) instead of assume_checked(), and if require_network returns an
Err, set self.mine_dialog.error = Some(format!("Invalid address: {}", err)) and
return — this makes the network invariant explicit and surfaces a clear error on
mismatch rather than silently accepting any network.

---

Nitpick comments:
In `@src/backend_task/core/mod.rs`:
- Around line 289-310: Before calling generate_to_address, add an explicit guard
that verifies the node is on Regtest (or Devnet) and return a clear error if
not; perform this check using the same context used to access the RPC (e.g., via
self or self.core_client.read()'s network/state) so the regtest-only command is
never dispatched on a public network. After adding the network check, proceed to
call generate_to_address only when the guard passes. Also rename the second let
ctx = self.clone() (used before refresh_wallet_info) to a distinct name like
ctx_refresh to avoid shadowing/confusion with the earlier ctx moved into the
first spawn_blocking closure.

In `@src/ui/wallets/wallets_screen/dialogs.rs`:
- Around line 1374-1377: The mine dialog currently shows errors as a plain
colored label (self.mine_dialog.error); change it to match the send dialog's
styled error Frame-with-"Dismiss" button pattern by rendering the error inside
the same Frame (using the same color/styling helpers like
DashColors::error_color(dark_mode)), include a "Dismiss" button identical to the
send dialog's behavior, and wire the button to clear the error (e.g., set
self.mine_dialog.error = None or call the same dismiss helper used by the send
dialog) so the UI and dismissal behavior are consistent across dialogs.
- Around line 1236-1241: The open_mine_dialog currently opens the dialog and
sets mine_dialog.error when selected_wallet is None; change this so the dialog
is not opened in that case: in open_mine_dialog, if self.selected_wallet is
None, do not set mine_dialog.is_open or mine_dialog.error but instead surface
the feedback via the existing MessageBanner/tooltip mechanism (or set a banner
state like self.message_banner = Some("Select a wallet first")) so the dialog
remains closed until a wallet is selected; update references to selected_wallet,
mine_dialog.error, and mine_dialog.is_open in open_mine_dialog accordingly.
- Around line 1253-1293: Extract a shared helper
load_bip44_external_addresses(&self, wallet: &Arc<RwLock<Wallet>>) ->
Result<Vec<(String, u64)>, String> that acquires wallet.read(), filters
watched_addresses by path.is_bip44_external(self.app_context.network), maps to
(address.to_string(), balance) using address_balances, and returns the Vec or an
Err(String) on lock failure; then update both load_core_addresses_for_mine and
load_core_addresses_for_receive to call this helper and keep their individual
"if empty -> call generate_new_core_receive_address" fallback logic and dialog
assignments (leave generate_new_core_receive_address usage unchanged). Also make
the error path consistent by clearing self.mine_dialog.core_addresses on
generate_new_core_receive_address Err (matching receive_dialog behavior) and set
selected_address_index appropriately. Ensure references to
load_core_addresses_for_mine, load_core_addresses_for_receive,
load_bip44_external_addresses, generate_new_core_receive_address,
mine_dialog.core_addresses, receive_dialog.core_addresses, and mine_dialog.error
are used to locate and modify the code.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 29995bb and dc3759d.

📒 Files selected for processing (2)
  • src/backend_task/core/mod.rs
  • src/ui/wallets/wallets_screen/dialogs.rs

Comment thread src/ui/wallets/wallets_screen/dialogs.rs Outdated
- Replace assume_checked() with require_network() for address
  validation (CodeRabbit #2)
- Use styled Frame-with-dismiss error display matching Send dialog
  pattern (CodeRabbit #3)
- Don't open dialog when no wallet selected; show MessageBanner
  instead (CodeRabbit #4)
- Extract shared load_bip44_external_addresses() helper to eliminate
  near-duplicate code between mine and receive dialogs (CodeRabbit #5)
- Add backend-side network guard (Regtest/Devnet) for defense-in-depth
  (CodeRabbit #6)
- Rename shadowed ctx binding to refresh_ctx for clarity (CodeRabbit #7)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread src/backend_task/core/mod.rs
Comment thread src/ui/wallets/wallets_screen/dialogs.rs Outdated
Comment thread src/ui/wallets/wallets_screen/dialogs.rs Outdated
Comment thread src/backend_task/mod.rs
Comment thread src/ui/wallets/wallets_screen/dialogs.rs Outdated
- Change MineBlocksSuccess(usize) to MineBlocksSuccess(u64) for
  type consistency with block_count parameter (Claudius #5)
- Align dialog close pattern with Send/Receive: use local `open`
  variable for egui X button, reset state inside closure for
  Cancel/Mine buttons (Claudius #6)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@lklimek lklimek merged commit cb837f3 into v1.0-dev Feb 24, 2026
4 checks passed
@lklimek lklimek deleted the zk-extract/mine-blocks-dialog branch February 24, 2026 18:41
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.

1 participant