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:
2026-06-05 10:36:00 -05:00
parent e6b91ca661
commit 2daea67a1e
5 changed files with 76 additions and 1 deletions

View File

@@ -4718,6 +4718,30 @@ void testLitePerAddressBalances()
EXPECT_NEAR(state.t_addresses[0].balance, 0.5, 1e-9); // 50000000
}
// M3: new-address generation via the controller (backend "new" zs/R) returns the address.
void testLiteWalletControllerNewAddress()
{
using namespace dragonx::wallet;
const auto caps = makeWalletCapabilities(WalletBuildKind::Lite, /*embeddedDaemon*/ false, /*liteBackendLinked*/ true);
const auto conn = defaultLiteConnectionSettings();
LiteWalletController controller(caps, conn, LiteClientBridge::fromApi(dragonx::test::makeFakeLiteApi()));
EXPECT_TRUE(controller.createWallet(LiteWalletCreateRequest{}).walletReady);
const auto z = controller.newAddress(/*shielded*/ true);
EXPECT_TRUE(z.ok);
EXPECT_TRUE(z.address.rfind("zs1", 0) == 0);
const auto t = controller.newAddress(/*shielded*/ false);
EXPECT_TRUE(t.ok);
EXPECT_TRUE(t.address.rfind("R1", 0) == 0);
// No wallet open -> error, no address.
LiteWalletController idle(caps, conn, LiteClientBridge::fromApi(dragonx::test::makeFakeLiteApi()));
const auto none = idle.newAddress(true);
EXPECT_FALSE(none.ok);
}
// Gateway hardening: one command's parse failure must not abort the whole refresh — the
// other commands still populate the bundle (graceful degradation against real-shape drift).
void testLiteWalletGatewayRefreshSkipsFailedCommand()
@@ -4841,6 +4865,7 @@ int main()
testLiteChainNameMigration();
testLiteRefreshModelAppliesToWalletState();
testLitePerAddressBalances();
testLiteWalletControllerNewAddress();
testLiteSyncStatusParserRealShapes();
testLiteWalletControllerRefreshPopulatesState();
testLiteWalletGatewayRefreshSkipsFailedCommand();