From 1d1db9ba4e582270e516c29484e3b500ef69262e Mon Sep 17 00:00:00 2001 From: Ricardo Guilherme Schmidt <3esmit@gmail.com> Date: Fri, 17 Jul 2026 19:48:50 -0300 Subject: [PATCH] fix(amm): reload changed sequencer configuration --- apps/amm/src/AmmUiBackend.cpp | 5 +- apps/amm/src/AmmUiBackend.h | 1 - apps/amm/src/SequencerClient.cpp | 56 ++++++++++--------- apps/amm/tests/cpp/NewPositionRuntimeTest.cpp | 36 ++++++++++++ 4 files changed, 67 insertions(+), 31 deletions(-) diff --git a/apps/amm/src/AmmUiBackend.cpp b/apps/amm/src/AmmUiBackend.cpp index f2f5a12..5def81a 100644 --- a/apps/amm/src/AmmUiBackend.cpp +++ b/apps/amm/src/AmmUiBackend.cpp @@ -217,10 +217,7 @@ void AmmUiBackend::syncWalletState() setSequencerAddr(state.sequencerAddress); setSequencerReachable(state.sequencerReachable); - if (m_sequencerConfigPath != state.configPath || !m_sequencer->isConfigured()) { - m_sequencerConfigPath = state.configPath; - m_sequencer->configure(state.configPath); - } + m_sequencer->configure(state.configPath); const bool addressChanged = previousAddress != state.sequencerAddress; if (addressChanged) { diff --git a/apps/amm/src/AmmUiBackend.h b/apps/amm/src/AmmUiBackend.h index 7eabb89..c5bf160 100644 --- a/apps/amm/src/AmmUiBackend.h +++ b/apps/amm/src/AmmUiBackend.h @@ -78,7 +78,6 @@ private: ActiveNetwork m_network; QVariantMap m_newPositionHints; - QString m_sequencerConfigPath; bool m_identityProbeInFlight = false; quint64 m_contextGeneration = 0; struct PendingTransaction { diff --git a/apps/amm/src/SequencerClient.cpp b/apps/amm/src/SequencerClient.cpp index 14cd3e0..40254fe 100644 --- a/apps/amm/src/SequencerClient.cpp +++ b/apps/amm/src/SequencerClient.cpp @@ -82,36 +82,40 @@ SequencerClient::SequencerClient(AmmClient* client, QObject* parent) bool SequencerClient::configure(const QString& configPath) { + QUrl endpoint; + QByteArray authorization; + QFile file(configPath); + bool valid = file.open(QIODevice::ReadOnly); + if (valid) { + const QJsonDocument document = QJsonDocument::fromJson(file.readAll()); + const QJsonObject config = document.object(); + endpoint = QUrl(config.value(QStringLiteral("sequencer_addr")).toString()); + const QString scheme = endpoint.scheme().toLower(); + valid = document.isObject() && endpoint.isValid() && !endpoint.host().isEmpty() + && (scheme == QStringLiteral("http") || scheme == QStringLiteral("https")); + if (valid) { + const QJsonObject basicAuth = config.value(QStringLiteral("basic_auth")).toObject(); + const QString username = basicAuth.value(QStringLiteral("username")).toString(); + const QString password = basicAuth.value(QStringLiteral("password")).toString(); + if (!username.isEmpty()) { + authorization = QByteArrayLiteral("Basic ") + + (username + QLatin1Char(':') + password).toUtf8().toBase64(); + } + } + } + if (!valid) { + endpoint = QUrl(); + authorization.clear(); + } + if (endpoint == m_endpoint && authorization == m_authorization) + return valid; + ++m_generation; cancelPendingReads(); clear(); - QFile file(configPath); - if (!file.open(QIODevice::ReadOnly)) { - m_endpoint = QUrl(); - m_authorization.clear(); - return false; - } - const QJsonDocument document = QJsonDocument::fromJson(file.readAll()); - const QJsonObject config = document.object(); - const QUrl endpoint(config.value(QStringLiteral("sequencer_addr")).toString()); - const QString scheme = endpoint.scheme().toLower(); - if (!document.isObject() || !endpoint.isValid() || endpoint.host().isEmpty() - || (scheme != QStringLiteral("http") && scheme != QStringLiteral("https"))) { - m_endpoint = QUrl(); - m_authorization.clear(); - return false; - } - m_endpoint = endpoint; - m_authorization.clear(); - const QJsonObject basicAuth = config.value(QStringLiteral("basic_auth")).toObject(); - const QString username = basicAuth.value(QStringLiteral("username")).toString(); - const QString password = basicAuth.value(QStringLiteral("password")).toString(); - if (!username.isEmpty()) { - m_authorization = QByteArrayLiteral("Basic ") - + (username + QLatin1Char(':') + password).toUtf8().toBase64(); - } - return true; + m_authorization = authorization; + return valid; } void SequencerClient::readAccounts(const QStringList& accountIds, diff --git a/apps/amm/tests/cpp/NewPositionRuntimeTest.cpp b/apps/amm/tests/cpp/NewPositionRuntimeTest.cpp index a212ed0..9b92657 100644 --- a/apps/amm/tests/cpp/NewPositionRuntimeTest.cpp +++ b/apps/amm/tests/cpp/NewPositionRuntimeTest.cpp @@ -445,5 +445,41 @@ int main(int argc, char** argv) "holding read should recover from the sequencer")) return 1; + const int requestsBeforeUnchangedConfig = server.requestCount(); + if (!expect(sequencer.configure(sequencerConfig.fileName()), + "unchanged sequencer config should remain valid")) + return 1; + QVector unchangedConfigRead; + if (!expect(waitForAccounts(sequencer, { holding.address }, false, + &unchangedConfigRead), + "cached read after unchanged config should complete")) + return 1; + if (!expect(server.requestCount() == requestsBeforeUnchangedConfig, + "unchanged config should preserve the account cache")) + return 1; + + LocalRpcServer replacementServer; + if (!expect(replacementServer.listen(), + "replacement sequencer should listen")) + return 1; + if (!expect(sequencerConfig.resize(0) && sequencerConfig.seek(0), + "sequencer config should rewind")) + return 1; + sequencerConfig.write(QJsonDocument(QJsonObject { + { QStringLiteral("sequencer_addr"), replacementServer.endpoint() }, + }).toJson(QJsonDocument::Compact)); + sequencerConfig.flush(); + if (!expect(sequencer.configure(sequencerConfig.fileName()), + "same-path endpoint update should configure")) + return 1; + QVector replacementRead; + if (!expect(waitForAccounts(sequencer, { holding.address }, false, + &replacementRead), + "same-path endpoint read should complete")) + return 1; + if (!expect(replacementServer.requestCount() == 1, + "same-path endpoint update should clear cache and use new sequencer")) + return 1; + return 0; }