Add cryptarchia info block

This commit is contained in:
Daniel 2026-06-20 17:27:27 +02:00
parent 0de0168f63
commit 6dbe2477e5
6 changed files with 191 additions and 0 deletions

View File

@ -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) {

View File

@ -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,

View File

@ -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))

View File

@ -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
}

View File

@ -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)
}
}
}

View File

@ -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