Skip to content
Merged
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

### Added

- **Automatic Platform node refresh during upgrades**: migrating a pre-1.0
installation now triggers a best-effort Mainnet or Testnet node refresh.
Failed attempts retry on later launches until fresh addresses are saved and
the app reconnects, so upgrading users do not need to find the manual action.

- **Search tags in the "Send to" field**: type `type:core`, `type:platform`,
`type:shielded`, or `wallet:<name>` to narrow the address suggestions
instead of scrolling through everything; plain words still search like
Expand Down
3 changes: 3 additions & 0 deletions docs/user-stories.md
Original file line number Diff line number Diff line change
Expand Up @@ -1261,6 +1261,9 @@ As a user, I want to fetch a fresh list of Platform (DAPI) node addresses from D
- "Refresh DAPI endpoints" action available on Mainnet and Testnet.
- Confirmation prompt before replacing an existing configured address set.
- New addresses are persisted to config and the SDK reinitialized without an app restart.
- A pre-1.0 migration triggers a silent, best-effort Mainnet or Testnet address
refresh; failures retry on later launches until addresses are saved, while
the manual action keeps its existing success message.

### NET-017: View live connection status (indicator and Platform endpoints) [Implemented]
**Persona:** Alex, Priya, Jordan
Expand Down
43 changes: 43 additions & 0 deletions src/backend_task/dapi_discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ use std::num::NonZeroUsize;
use std::str::FromStr;
use std::time::Duration;

use crate::backend_task::error::TaskError;
use crate::config::{CONFIG_PERSISTENCE_LOCK, Config};
use crate::context::AppContext;

/// Errors from DAPI address resolution and discovery.
#[derive(Debug, thiserror::Error)]
pub enum DapiDiscoveryError {
Expand Down Expand Up @@ -133,3 +137,42 @@ pub async fn discover_and_format(
let csv = urls.join(",");
Ok((count, csv))
}

/// Persist DAPI addresses and publish them to the active network configuration.
pub(crate) fn persist_dapi_addresses(
app_context: &AppContext,
addresses_csv: String,
) -> Result<(), TaskError> {
persist_dapi_addresses_inner(app_context, addresses_csv, || {})
}

fn persist_dapi_addresses_inner(
app_context: &AppContext,
addresses_csv: String,
before_save: impl FnOnce(),
) -> Result<(), TaskError> {
let _persistence_guard = CONFIG_PERSISTENCE_LOCK
.lock()
.unwrap_or_else(|poisoned| poisoned.into_inner());
let network = app_context.network();
let mut config = Config::load_from(app_context.data_dir())?;
Comment thread
lklimek marked this conversation as resolved.
Outdated
let mut network_config = config
.config_for_network(network)
.clone()
.unwrap_or_default();
network_config.dapi_addresses = Some(addresses_csv);
config.update_config_for_network(network, network_config.clone());
before_save();
config.save(app_context.data_dir())?;
Comment thread
lklimek marked this conversation as resolved.
Outdated
*app_context.config.write()? = network_config;
Ok(())
}

#[cfg(test)]
pub(crate) fn persist_dapi_addresses_with_hook(
app_context: &AppContext,
addresses_csv: String,
before_save: impl FnOnce(),
) -> Result<(), TaskError> {
persist_dapi_addresses_inner(app_context, addresses_csv, before_save)
}
12 changes: 8 additions & 4 deletions src/backend_task/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2125,13 +2125,17 @@ pub enum TaskError {
#[error("Could not connect to {network}. Check your network configuration and retry.")]
NetworkContextCreationFailed { network: Network },

/// A DAPI refresh completed after its network context was removed.
#[error(
"The node addresses could not be applied because the selected network changed. Select the network and retry."
)]
DapiConfigContextUnavailable { network: Network },

// ──────────────────────────────────────────────────────────────────────────
// Migration errors
// ──────────────────────────────────────────────────────────────────────────
/// Surfaced when wallet/identity/DashPay storage is being upgraded
/// from the legacy `data.db` and a task tried to touch it before
/// the migration finished. The user can retry once the migration
/// banner clears.
/// Surfaced while the legacy-data upgrade or its best-effort DAPI refresh
/// still owns the migration guard. The user can retry after a short wait.
#[error("The storage update is still running. Please wait a moment and try again.")]
WalletStorageNotReady,

Expand Down
Loading
Loading