From 6dbe2477e584f64ad8dab5ad345ac62c7f0d5fee Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 20 Jun 2026 17:27:27 +0200 Subject: [PATCH] Add cryptarchia info block --- src/BlockchainBackend.cpp | 9 ++ src/BlockchainBackend.h | 1 + src/BlockchainBackend.rep | 1 + src/qml/BlockchainView.qml | 36 +++++++ src/qml/views/CryptarchiaInfoView.qml | 143 ++++++++++++++++++++++++++ src/qml/views/qmldir | 1 + 6 files changed, 191 insertions(+) create mode 100644 src/qml/views/CryptarchiaInfoView.qml diff --git a/src/BlockchainBackend.cpp b/src/BlockchainBackend.cpp index 89d9da2..31c2d96 100644 --- a/src/BlockchainBackend.cpp +++ b/src/BlockchainBackend.cpp @@ -210,6 +210,15 @@ QVariantMap BlockchainBackend::claimLeaderRewards() BLOCKCHAIN_MODULE_NAME, "leader_claim"))); } +QVariantMap BlockchainBackend::getCryptarchiaInfo() +{ + if (!m_blockchainClient) + return result::toVariantMap(result::err(QStringLiteral("Module not initialized."))); + + return result::toVariantMap(result::toLogosResult(m_blockchainClient->invokeRemoteMethod( + BLOCKCHAIN_MODULE_NAME, QStringLiteral("get_cryptarchia_info")))); +} + void BlockchainBackend::startBlockchain() { if (!m_blockchainClient) { diff --git a/src/BlockchainBackend.h b/src/BlockchainBackend.h index 5936c4f..52d8472 100644 --- a/src/BlockchainBackend.h +++ b/src/BlockchainBackend.h @@ -45,6 +45,7 @@ public slots: QVariantMap getBalance(QString addressHex) override; QVariantMap transferFunds(QString fromKeyHex, QString toKeyHex, QString amountStr) override; QVariantMap claimLeaderRewards() override; + QVariantMap getCryptarchiaInfo() override; QVariantMap generateConfig(QString outputPath, QStringList initialPeers, int netPort, int blendPort, QString httpAddr, QString externalAddress, bool noPublicIpCheck, int deploymentMode, diff --git a/src/BlockchainBackend.rep b/src/BlockchainBackend.rep index 817ba80..983e2a1 100644 --- a/src/BlockchainBackend.rep +++ b/src/BlockchainBackend.rep @@ -15,6 +15,7 @@ class BlockchainBackend SLOT(QVariantMap getBalance(QString addressHex)) SLOT(QVariantMap transferFunds(QString fromKeyHex, QString toKeyHex, QString amountStr)) SLOT(QVariantMap claimLeaderRewards()) + SLOT(QVariantMap getCryptarchiaInfo()) SLOT(QVariantMap generateConfig(QString outputPath, QStringList initialPeers, int netPort, int blendPort, QString httpAddr, QString externalAddress, bool noPublicIpCheck, int deploymentMode, QString deploymentConfigPath, QString statePath)) SLOT(QVariantMap getNotes(QString walletAddressHex, QString optionalTipHex)) SLOT(QVariantMap channelDepositWithNotes(QString channelIdHex, QStringList inputNoteIdHexes, QString metadataBase58, QString changePublicKeyHex, QStringList fundingPublicKeyHexes, QString maxTxFee, QString optionalTipHex)) diff --git a/src/qml/BlockchainView.qml b/src/qml/BlockchainView.qml index 5e4f924..eb0107d 100644 --- a/src/qml/BlockchainView.qml +++ b/src/qml/BlockchainView.qml @@ -57,6 +57,34 @@ Rectangle { visible: false } + // Live Cryptarchia consensus state, polled while the node runs. + property string cryptarchiaInfoJson: "" + property string cryptarchiaInfoError: "" + + Timer { + id: cryptarchiaTimer + interval: 2000 + repeat: true + triggeredOnStart: true + running: root.ready && root.backend + && root.backend.status === BlockchainBackend.Running + onTriggered: { + if (!root.backend) return + logos.watch( + root.backend.getCryptarchiaInfo(), + function(result) { + if (result.success) { + root.cryptarchiaInfoJson = result.value + root.cryptarchiaInfoError = "" + } else { + root.cryptarchiaInfoError = _d.errorText(result.error) + } + }, + function(error) { root.cryptarchiaInfoError = _d.errorText(error) } + ) + } + } + QtObject { id: _d function errorText(message) { @@ -238,6 +266,14 @@ Rectangle { onChangeConfigRequested: _d.currentPage = 0 } + CryptarchiaInfoView { + Layout.fillWidth: true + visible: opPage.nodeRunning + infoJson: root.cryptarchiaInfoJson + errorText: root.cryptarchiaInfoError + onCopyToClipboard: (text) => root.copyText(text) + } + Item { Layout.preferredHeight: Theme.spacing.small } diff --git a/src/qml/views/CryptarchiaInfoView.qml b/src/qml/views/CryptarchiaInfoView.qml new file mode 100644 index 0000000..c8df818 --- /dev/null +++ b/src/qml/views/CryptarchiaInfoView.qml @@ -0,0 +1,143 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +import Logos.Theme +import Logos.Controls + +import "../controls" + +// Live Cryptarchia consensus state, polled from get_cryptarchia_info. +// The result `value` is a JSON string; parsed defensively (nested under +// "cryptarchia_info" or flat, mode as string or numeric enum). +Rectangle { + id: root + + property string infoJson: "" + property string errorText: "" + + signal copyToClipboard(string text) + + readonly property var info: parse(infoJson) + + function parse(s) { + try { return s && s.length > 0 ? JSON.parse(s) : null } catch (e) { return null } + } + + function field(key) { + if (!info) return undefined + if (info.cryptarchia_info && info.cryptarchia_info[key] !== undefined) + return info.cryptarchia_info[key] + return info[key] + } + + function num(key) { + var v = field(key) + return (v === undefined || v === null) ? qsTr("—") : String(v) + } + + function hash(key) { + var v = field(key) + return (v === undefined || v === null) ? "" : String(v) + } + + // mode lives at the top level (ChainServiceMode); accept string or the + // c-binding numeric enum (0 Bootstrapping / 1 Online / 2 NotStarted). + function modeText() { + var m = info ? info.mode : undefined + if (m === undefined || m === null) return qsTr("—") + if (typeof m === "number") { + switch (m) { + case 0: return qsTr("Bootstrapping") + case 1: return qsTr("Online") + case 2: return qsTr("Not Started") + default: return String(m) + } + } + return String(m) + } + + function modeColor() { + var t = modeText() + if (t === qsTr("Online")) return Theme.palette.success + if (t === qsTr("Bootstrapping")) return Theme.palette.warning + return Theme.palette.textSecondary + } + + implicitHeight: contentCol.implicitHeight + 2 * Theme.spacing.large + color: Theme.palette.backgroundTertiary + radius: Theme.spacing.radiusLarge + border.color: Theme.palette.border + border.width: 1 + + ColumnLayout { + id: contentCol + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + anchors.margins: Theme.spacing.large + spacing: Theme.spacing.small + + RowLayout { + Layout.fillWidth: true + spacing: Theme.spacing.small + LogosText { + text: qsTr("Consensus") + font.pixelSize: Theme.typography.secondaryText + font.bold: true + } + Item { Layout.fillWidth: true } + LogosText { + text: root.modeText() + color: root.modeColor() + font.pixelSize: Theme.typography.secondaryText + font.bold: true + } + } + + LogosText { + Layout.fillWidth: true + visible: root.errorText.length > 0 + text: root.errorText + color: Theme.palette.error + font.pixelSize: Theme.typography.secondaryText + wrapMode: Text.WordWrap + } + + RowLayout { + Layout.fillWidth: true + visible: root.errorText.length === 0 + spacing: Theme.spacing.large + LogosText { + text: qsTr("Slot: %1").arg(root.num("slot")) + font.pixelSize: Theme.typography.secondaryText + color: Theme.palette.textSecondary + } + LogosText { + text: qsTr("Height: %1").arg(root.num("height")) + font.pixelSize: Theme.typography.secondaryText + color: Theme.palette.textSecondary + } + LogosText { + visible: root.field("lib_slot") !== undefined + text: qsTr("LIB slot: %1").arg(root.num("lib_slot")) + font.pixelSize: Theme.typography.secondaryText + color: Theme.palette.textSecondary + } + Item { Layout.fillWidth: true } + } + + HashRow { + visible: root.errorText.length === 0 + label: qsTr("Tip") + value: root.hash("tip") + onCopyRequested: (t) => root.copyToClipboard(t) + } + HashRow { + visible: root.errorText.length === 0 + label: qsTr("LIB") + value: root.hash("lib") + onCopyRequested: (t) => root.copyToClipboard(t) + } + } +} diff --git a/src/qml/views/qmldir b/src/qml/views/qmldir index 34b0946..1324617 100644 --- a/src/qml/views/qmldir +++ b/src/qml/views/qmldir @@ -1,6 +1,7 @@ module views StatusConfigView 1.0 StatusConfigView.qml BlocksView 1.0 BlocksView.qml +CryptarchiaInfoView 1.0 CryptarchiaInfoView.qml AccountsView 1.0 AccountsView.qml TransferView 1.0 TransferView.qml LeaderRewardsView 1.0 LeaderRewardsView.qml