diff --git a/apps/amm/src/AmmUiBackend.cpp b/apps/amm/src/AmmUiBackend.cpp index b7f3497..93e167d 100644 --- a/apps/amm/src/AmmUiBackend.cpp +++ b/apps/amm/src/AmmUiBackend.cpp @@ -113,7 +113,7 @@ QString AmmUiBackend::getBalance(QString accountIdHex, bool isPublic) return m_walletController->balance(accountIdHex, isPublic); } -void AmmUiBackend::refreshNewPositionContext(QVariantMap request) +QVariantMap AmmUiBackend::refreshNewPositionContext(QVariantMap request) { const bool refreshWalletAccounts = request.take(QStringLiteral("refreshWalletAccounts")).toBool(); @@ -125,11 +125,14 @@ void AmmUiBackend::refreshNewPositionContext(QVariantMap request) request = m_newPositionHints; } if (!walletStateReady()) { - setNewPositionContext(loadingContext()); - return; + const QVariantMap context = loadingContext(); + setNewPositionContext(context); + return context; } - setNewPositionContext(m_logos->amm_module.newPositionContext( - request, isWalletOpen(), refreshWalletAccounts)); + const QVariantMap context = m_logos->amm_module.newPositionContext( + request, isWalletOpen(), refreshWalletAccounts); + setNewPositionContext(context); + return context; } void AmmUiBackend::syncWalletState() diff --git a/apps/amm/src/AmmUiBackend.h b/apps/amm/src/AmmUiBackend.h index 72561d8..bc87166 100644 --- a/apps/amm/src/AmmUiBackend.h +++ b/apps/amm/src/AmmUiBackend.h @@ -46,7 +46,7 @@ public slots: void refreshAccounts() override; void refreshBalances() override; QString getBalance(QString accountIdHex, bool isPublic) override; - void refreshNewPositionContext(QVariantMap request) override; + QVariantMap refreshNewPositionContext(QVariantMap request) override; // Return the new wallet's BIP39 mnemonic (empty string on failure) so the // UI can force a one-time seed-phrase backup step. QString createNewDefault(QString password) override; diff --git a/apps/amm/src/AmmUiBackend.rep b/apps/amm/src/AmmUiBackend.rep index d428331..3959e90 100644 --- a/apps/amm/src/AmmUiBackend.rep +++ b/apps/amm/src/AmmUiBackend.rep @@ -30,7 +30,8 @@ class AmmUiBackend // The QVariant payloads are stable maps/lists so the UI never assembles AMM // transactions or duplicates quote state. PROP(QVariantMap newPositionContext READONLY) - SLOT(void refreshNewPositionContext(QVariantMap request)) + // Return the published context so the QML refresh watcher always settles. + SLOT(QVariantMap refreshNewPositionContext(QVariantMap request)) // Wallet lifecycle. createNewDefault() is the happy path: it creates a // fresh wallet at the canonical walletHome with no path picking. createNew() diff --git a/apps/amm/tests/qml/tst_LiquidityPage.qml b/apps/amm/tests/qml/tst_LiquidityPage.qml index 60b0fd5..f72befc 100644 --- a/apps/amm/tests/qml/tst_LiquidityPage.qml +++ b/apps/amm/tests/qml/tst_LiquidityPage.qml @@ -15,11 +15,17 @@ TestCase { QtObject { property bool walletStateReady: false + property int contextRefreshCalls: 0 property var newPositionContext: ({ "status": "ready", "tokens": [], "feeTiers": [] }) + + function refreshNewPositionContext(request) { + ++contextRefreshCalls + return newPositionContext + } } } @@ -49,6 +55,18 @@ TestCase { verify(form.width <= page.width - 32) } + Component { + id: runtimeComponent + + QtObject { + function watch(value, succeeded, failed) { + if (value === undefined) + return + succeeded(value) + } + } + } + Component { id: pageComponent @@ -87,6 +105,32 @@ TestCase { compare(page.flow.contextHints(true).refreshWalletAccounts, true) } + function test_refreshPositionCompletesAndReenablesTokenSelection() { + var backend = createTemporaryObject(backendComponent, testCase, { + "walletStateReady": true + }) + var runtime = createTemporaryObject(runtimeComponent, testCase) + var page = createTemporaryObject(pageComponent, testCase, { + "backend": backend, + "runtime": runtime + }) + verify(backend) + verify(runtime) + verify(page) + + var refreshButton = findChild(page, "refreshPositionButton") + var tokenAInput = findChild(page, "tokenAAmountInput") + verify(refreshButton) + verify(tokenAInput) + + refreshButton.clicked() + + tryCompare(backend, "contextRefreshCalls", 1) + tryCompare(page.flow, "contextLoading", false) + compare(refreshButton.enabled, true) + compare(tokenAInput.tokenSelectionEnabled, true) + } + function test_staleContextCompletionCannotFinishNewerRefresh() { var backend = createTemporaryObject(backendComponent, testCase, { "walletStateReady": true