feat(lite): M3 — new-address generation + sync-indicator confirmation
- LiteWalletController::newAddress(shielded) runs the backend "new" command ("zs"/"R" ->
do_new_address), parses the ["addr"] response, and returns the new address; the next
refresh lists it. Fast (local derivation), safe on the UI thread.
- fake_lite_backend returns ["zs1fakenew"]/["R1fakenew"] for "new" by args.
- testLiteWalletControllerNewAddress covers shielded/transparent + no-wallet error.
Also confirmed (no code needed): the sync-progress indicator already works for lite —
balance_tab reads state.sync.* which M2b-3 populates. Per-address balances landed in M2.
Remaining M3 is pure UI wiring (receive_tab button -> newAddress, loading/empty states),
which isn't verifiable without a GUI session.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <sodium.h>
|
||||
|
||||
namespace dragonx {
|
||||
@@ -202,6 +203,35 @@ std::optional<LiteWalletAppRefreshModel> LiteWalletController::refreshModel()
|
||||
return mapped.model;
|
||||
}
|
||||
|
||||
LiteNewAddressResult LiteWalletController::newAddress(bool shielded)
|
||||
{
|
||||
LiteNewAddressResult out;
|
||||
if (!walletOpen_.load() || !bridge_) {
|
||||
out.error = "no wallet is open";
|
||||
return out;
|
||||
}
|
||||
// Backend address-type tokens: "zs" (shielded) / "R" (transparent) (do_new_address).
|
||||
const auto result = bridge_->execute("new", shielded ? "zs" : "R");
|
||||
if (!result.ok) {
|
||||
out.error = result.error.empty() ? "new address generation failed" : result.error;
|
||||
return out;
|
||||
}
|
||||
// Response is a JSON array with the new address, e.g. ["zs1..."].
|
||||
try {
|
||||
const auto parsed = nlohmann::json::parse(result.value);
|
||||
if (parsed.is_array() && !parsed.empty() && parsed[0].is_string()) {
|
||||
out.address = parsed[0].get<std::string>();
|
||||
} else if (parsed.is_string()) {
|
||||
out.address = parsed.get<std::string>();
|
||||
}
|
||||
} catch (...) {
|
||||
// fall through to the error below
|
||||
}
|
||||
out.ok = !out.address.empty();
|
||||
if (!out.ok) out.error = "could not parse new address response";
|
||||
return out;
|
||||
}
|
||||
|
||||
bool LiteWalletController::refreshWalletState(dragonx::WalletState& state)
|
||||
{
|
||||
auto model = refreshModel();
|
||||
|
||||
@@ -53,6 +53,12 @@ struct LiteWalletControllerOptions {
|
||||
bool allowBridgeCalls = true;
|
||||
};
|
||||
|
||||
struct LiteNewAddressResult {
|
||||
bool ok = false;
|
||||
std::string address;
|
||||
std::string error;
|
||||
};
|
||||
|
||||
class LiteWalletController {
|
||||
public:
|
||||
LiteWalletController(WalletCapabilities capabilities,
|
||||
@@ -92,6 +98,10 @@ public:
|
||||
// op produces a ready wallet; safe to call once.
|
||||
void startSync();
|
||||
|
||||
// Generate a new address (shielded if true, else transparent) via the backend. Fast (local
|
||||
// key derivation), safe to call on the UI thread; the next refresh lists the new address.
|
||||
LiteNewAddressResult newAddress(bool shielded);
|
||||
|
||||
// Poll sync status + fetch balance/addresses/transactions, and apply the result into the
|
||||
// app's WalletState. Returns true if state was updated. Safe no-op when no wallet is open.
|
||||
// Synchronous (blocks on the backend); used by tests and as the worker's unit of work.
|
||||
|
||||
Reference in New Issue
Block a user