feat(lite): make the Console tab interactive (run backend commands)
The lite backend's litelib_execute() is the same command interface as silentdragonxlite-cli (balance, info, height, list, notes, addresses, sync, syncstatus, new, send, shield, encrypt, …), so the lite Console can be a real interactive console — like the full-node RPC console — instead of a read-only diagnostics log. Controller: add an async arbitrary-command runner mirroring the broadcast pattern — runConsoleCommand() splits "<command> [args]" (the first token is the command, the remainder is passed as the single arg string litelib_execute expects, since it does NOT whitespace-split), runs the bridge call on a detached thread that captures the shared bridge (never `this`), and delivers the result to a main-thread slot drained by takeConsoleResult(). Results are NEVER routed through LiteDiagnostics (seed/export can return secrets). Console tab: a command input (Enter to run, Up/Down history via the shared console_input_model helpers) over a unified scroll buffer that interleaves the automatic diagnostics events with user command I/O, colour-coded, with the live status header preserved. The input is disabled while a command runs. Two backend footguns are intercepted at the UI layer before forwarding: `clear` (the backend command WIPES wallet tx history — re-bound to clearing the view, what the user expects) and `quit`/`exit` (would only save; the embedded backend must stay running with the app). Test: runConsoleCommand drives the fake backend (info -> raw response; "new zs" -> exercises the command/arg split; blank line rejected). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -3638,6 +3638,49 @@ void testLiteWalletControllerOpenFailover()
|
||||
dragonx::test::g_liteFakeWarmupServerSubstr.clear();
|
||||
}
|
||||
|
||||
// Interactive console: runConsoleCommand() forwards an arbitrary backend command on a background
|
||||
// thread and delivers the raw response to a main-thread slot drained by takeConsoleResult().
|
||||
void testLiteWalletControllerConsoleCommand()
|
||||
{
|
||||
using namespace dragonx::wallet;
|
||||
const auto liteCaps = makeWalletCapabilities(WalletBuildKind::Lite, false, true);
|
||||
LiteConnectionSettings conn;
|
||||
conn.chainName = "main";
|
||||
conn.servers = { LiteServerEndpoint{"https://good.example", "Good", true} };
|
||||
|
||||
dragonx::test::resetLiteFakeCounters();
|
||||
LiteWalletController controller(liteCaps, conn,
|
||||
LiteClientBridge::fromApi(dragonx::test::makeFakeLiteApi()));
|
||||
|
||||
const auto drainConsole = [&](LiteConsoleResult& res) {
|
||||
for (int i = 0; i < 400 && !controller.takeConsoleResult(res); ++i)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
};
|
||||
|
||||
// A single-token command (no args) returns the backend's raw response.
|
||||
{
|
||||
EXPECT_TRUE(controller.runConsoleCommand("info"));
|
||||
LiteConsoleResult res;
|
||||
drainConsole(res);
|
||||
EXPECT_TRUE(res.ok);
|
||||
EXPECT_EQ(res.command, std::string("info"));
|
||||
EXPECT_TRUE(res.response.find("sdxl-fake") != std::string::npos);
|
||||
}
|
||||
|
||||
// "<command> <args>" splits into the command token + the remainder as the single arg string
|
||||
// (new zs -> the shielded-address path of the fake backend).
|
||||
{
|
||||
EXPECT_TRUE(controller.runConsoleCommand("new zs"));
|
||||
LiteConsoleResult res;
|
||||
drainConsole(res);
|
||||
EXPECT_TRUE(res.ok);
|
||||
EXPECT_TRUE(res.response.find("zs1fakenew") != std::string::npos);
|
||||
}
|
||||
|
||||
// A blank line is rejected (nothing to run).
|
||||
EXPECT_FALSE(controller.runConsoleCommand(" "));
|
||||
}
|
||||
|
||||
// Async FULL lifecycle (Settings-page create/open/restore WITH passphrase/restore params) also
|
||||
// fails over: the request runs off the UI thread against the preferred server, then the other
|
||||
// usable defaults, finalized by pumpLifecycleResult() on the main thread.
|
||||
@@ -4596,6 +4639,7 @@ int main()
|
||||
testLiteWalletControllerLifecycle();
|
||||
testLiteWalletControllerOpenFailover();
|
||||
testLiteWalletControllerAsyncLifecycleFailover();
|
||||
testLiteWalletControllerConsoleCommand();
|
||||
testLiteWalletControllerM4();
|
||||
testLiteWalletControllerM5Persistence();
|
||||
testLiteWalletControllerEncryption();
|
||||
|
||||
Reference in New Issue
Block a user