mirror of
https://github.com/logos-blockchain/lez-programs.git
synced 2026-08-25 22:21:16 +00:00
Add portable Basecamp packaging and an inspector-driven end-to-end flow.
1322 lines
62 KiB
QML
1322 lines
62 KiB
QML
pragma ComponentBehavior: Bound
|
|
|
|
import QtQuick 2.15
|
|
import QtQuick.Controls.Basic
|
|
import QtQuick.Layouts 1.15
|
|
|
|
Item {
|
|
id: root
|
|
|
|
objectName: "tokenManagePage"
|
|
|
|
property var store: null
|
|
property var backend: null
|
|
property var runtime: null
|
|
property string query: ""
|
|
property string typeFilter: "all"
|
|
property string selectedId: ""
|
|
property bool loading: false
|
|
property string loadError: ""
|
|
property int refreshSerial: 0
|
|
|
|
readonly property var definitions: store ? store.allDefinitions : []
|
|
readonly property var filteredDefinitions: root.filterDefinitions()
|
|
readonly property var selectedDefinition: store && selectedId.length > 0 ? store.findDefinition(selectedId) : null
|
|
readonly property bool hasSelection: selectedDefinition !== null
|
|
readonly property bool selectedIsFungible: hasSelection && selectedDefinition.type === "fungible"
|
|
readonly property bool selectedIsNft: hasSelection && selectedDefinition.type === "nonFungible"
|
|
|
|
function filterDefinitions() {
|
|
var matches = store ? store.visibleDefinitions(query) : [];
|
|
if (typeFilter === "all")
|
|
return matches;
|
|
|
|
var typed = [];
|
|
for (var index = 0; index < matches.length; ++index) {
|
|
if (matches[index].type === typeFilter)
|
|
typed.push(matches[index]);
|
|
}
|
|
return typed;
|
|
}
|
|
|
|
function ensureSelection() {
|
|
if (!store)
|
|
return;
|
|
|
|
var matches = filteredDefinitions;
|
|
if (matches.length === 0) {
|
|
selectedId = "";
|
|
return;
|
|
}
|
|
|
|
for (var index = 0; index < matches.length; ++index) {
|
|
if (matches[index].id === selectedId)
|
|
return;
|
|
}
|
|
|
|
if (selectedId.length === 0 && typeFilter === "all" && query.length === 0) {
|
|
var featured = store.findDefinition("3sG2zN3fAXBvs9mdgFHFiJFSFiwiYyaR5HUA3gZZTSXt");
|
|
if (featured) {
|
|
selectedId = featured.id;
|
|
return;
|
|
}
|
|
}
|
|
|
|
selectedId = matches[0].id;
|
|
}
|
|
|
|
function valueOrDash(value) {
|
|
if (value === null || value === undefined || value === "")
|
|
return "—";
|
|
return String(value);
|
|
}
|
|
|
|
function sourceLabel(definition) {
|
|
if (!definition)
|
|
return "";
|
|
if (definition.source === "pending")
|
|
return qsTr("Pending transaction");
|
|
if (definition.source === "network")
|
|
return qsTr("Network");
|
|
if (definition.source === "draft")
|
|
return qsTr("Draft");
|
|
return qsTr("Example");
|
|
}
|
|
|
|
function authorityTitle(definition) {
|
|
if (!definition)
|
|
return "—";
|
|
if (definition.type === "nonFungible")
|
|
return qsTr("Master holding");
|
|
if (definition.authorityMode === "external")
|
|
return qsTr("External authority");
|
|
if (definition.authorityMode === "self")
|
|
return qsTr("Self authority");
|
|
if (definition.authorityMode === "renounced")
|
|
return qsTr("Authority revoked");
|
|
return qsTr("Fixed supply");
|
|
}
|
|
|
|
function authorityDescription(definition) {
|
|
if (!definition)
|
|
return "";
|
|
if (definition.type === "nonFungible")
|
|
return qsTr("Printing is controlled by the NFT master holding, not a definition authority.");
|
|
if (definition.authorityMode === "external")
|
|
return qsTr("A separate account can sign future fungible mints.");
|
|
if (definition.authorityMode === "self")
|
|
return qsTr("The definition account is the mint authority.");
|
|
if (definition.authorityMode === "renounced")
|
|
return qsTr("No mint authority is stored; the supply cannot be increased.");
|
|
return qsTr("No mint authority is stored; the supply cannot be increased.");
|
|
}
|
|
|
|
function refreshLiveDefinitions() {
|
|
if (!root.store)
|
|
return;
|
|
|
|
if (!root.backend || !root.backend.isWalletOpen || !root.runtime) {
|
|
root.loading = false;
|
|
root.loadError = "";
|
|
if (root.store.clearLiveDefinitions)
|
|
root.store.clearLiveDefinitions();
|
|
root.ensureSelection();
|
|
return;
|
|
}
|
|
|
|
var requestSerial = ++root.refreshSerial;
|
|
root.loading = true;
|
|
root.loadError = "";
|
|
root.runtime.watch(root.backend.walletDefinitions(), function(definitions) {
|
|
if (requestSerial !== root.refreshSerial)
|
|
return;
|
|
root.loading = false;
|
|
root.store.setLiveDefinitions(definitions || []);
|
|
root.ensureSelection();
|
|
}, function(error) {
|
|
if (requestSerial !== root.refreshSerial)
|
|
return;
|
|
root.loading = false;
|
|
root.loadError = qsTr("Token accounts could not be read: %1").arg(error);
|
|
root.store.clearLiveDefinitions();
|
|
root.ensureSelection();
|
|
});
|
|
}
|
|
|
|
onVisibleChanged: {
|
|
if (visible)
|
|
root.refreshLiveDefinitions();
|
|
}
|
|
onBackendChanged: root.refreshLiveDefinitions()
|
|
onRuntimeChanged: root.refreshLiveDefinitions()
|
|
Component.onCompleted: {
|
|
root.ensureSelection();
|
|
root.refreshLiveDefinitions();
|
|
}
|
|
onStoreChanged: root.ensureSelection()
|
|
onFilteredDefinitionsChanged: root.ensureSelection()
|
|
|
|
Connections {
|
|
target: root.backend
|
|
ignoreUnknownSignals: true
|
|
function onIsWalletOpenChanged() { root.refreshLiveDefinitions() }
|
|
}
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
color: "#151515"
|
|
}
|
|
|
|
Flickable {
|
|
id: scroll
|
|
|
|
anchors.fill: parent
|
|
clip: true
|
|
contentWidth: width
|
|
contentHeight: content.implicitHeight + 32
|
|
flickableDirection: Flickable.VerticalFlick
|
|
|
|
ScrollBar.vertical: ScrollBar {
|
|
id: verticalScrollBar
|
|
|
|
parent: scroll.parent
|
|
anchors.top: scroll.top
|
|
anchors.right: scroll.right
|
|
anchors.bottom: scroll.bottom
|
|
anchors.topMargin: 4
|
|
anchors.rightMargin: 4
|
|
anchors.bottomMargin: 4
|
|
policy: scroll.contentHeight > scroll.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
|
|
active: true
|
|
visible: policy === ScrollBar.AlwaysOn
|
|
width: 12
|
|
z: 10
|
|
|
|
background: Rectangle {
|
|
radius: 6
|
|
color: "#292929"
|
|
}
|
|
|
|
contentItem: Rectangle {
|
|
implicitWidth: 8
|
|
implicitHeight: 32
|
|
radius: 4
|
|
color: verticalScrollBar.pressed ? "#F26A21" : "#9A8C81"
|
|
opacity: 1
|
|
}
|
|
}
|
|
|
|
ColumnLayout {
|
|
id: content
|
|
|
|
width: Math.max(240, Math.min(scroll.width - 32, 1440))
|
|
x: Math.max(16, (scroll.width - width) / 2)
|
|
y: 24
|
|
spacing: 18
|
|
|
|
ColumnLayout {
|
|
id: pageHeader
|
|
|
|
Layout.fillWidth: true
|
|
spacing: 5
|
|
|
|
ColumnLayout {
|
|
Layout.fillWidth: true
|
|
Layout.minimumWidth: 0
|
|
spacing: 5
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
Layout.minimumWidth: 0
|
|
color: "#E7E1D8"
|
|
font.pixelSize: 28
|
|
font.weight: Font.DemiBold
|
|
wrapMode: Text.Wrap
|
|
text: qsTr("Inspect token definitions")
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
Layout.minimumWidth: 0
|
|
color: "#A9A098"
|
|
font.pixelSize: 14
|
|
wrapMode: Text.Wrap
|
|
text: qsTr("View deployed token definitions and account state.")
|
|
}
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
spacing: 8
|
|
|
|
Text {
|
|
objectName: "tokenManageStatus"
|
|
Layout.fillWidth: true
|
|
color: root.loadError.length > 0 ? "#F08A76" : "#8E8780"
|
|
font.pixelSize: 12
|
|
elide: Text.ElideRight
|
|
text: root.loadError.length > 0 ? root.loadError : root.loading ? qsTr("Reading wallet token accounts…") : root.backend && root.backend.isWalletOpen ? qsTr("Live wallet view") : qsTr("Connect wallet to inspect live assets")
|
|
}
|
|
|
|
Button {
|
|
id: refreshDefinitionsButton
|
|
|
|
objectName: "tokenRefreshButton"
|
|
|
|
Layout.preferredWidth: 86
|
|
Layout.preferredHeight: 32
|
|
enabled: root.backend !== null && root.backend.isWalletOpen && !root.loading
|
|
text: root.loading ? qsTr("Reading…") : qsTr("Refresh")
|
|
Accessible.name: qsTr("Refresh live token definitions")
|
|
onClicked: root.refreshLiveDefinitions()
|
|
|
|
contentItem: Text {
|
|
color: parent.enabled ? "#F2D8C7" : "#8E8780"
|
|
font.pixelSize: 12
|
|
horizontalAlignment: Text.AlignHCenter
|
|
verticalAlignment: Text.AlignVCenter
|
|
text: refreshDefinitionsButton.text
|
|
}
|
|
|
|
background: Rectangle {
|
|
radius: 7
|
|
color: parent.enabled ? "#211914" : "#282522"
|
|
border.color: parent.enabled ? "#49301F" : "#3C3833"
|
|
border.width: 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
GridLayout {
|
|
id: workbench
|
|
|
|
readonly property int columnCount: content.width >= 1180 ? 2 : 1
|
|
|
|
Layout.fillWidth: true
|
|
Layout.minimumWidth: 0
|
|
columns: columnCount
|
|
columnSpacing: 14
|
|
rowSpacing: 14
|
|
|
|
Rectangle {
|
|
id: indexPanel
|
|
|
|
Layout.alignment: Qt.AlignTop
|
|
Layout.fillWidth: true
|
|
Layout.minimumWidth: 0
|
|
Layout.preferredWidth: workbench.columnCount === 2 ? 390 : 0
|
|
Layout.maximumWidth: workbench.columnCount === 2 ? 430 : 1440
|
|
implicitHeight: indexContent.implicitHeight + 32
|
|
radius: 16
|
|
color: "#1B1B1B"
|
|
border.color: "#303030"
|
|
border.width: 1
|
|
|
|
ColumnLayout {
|
|
id: indexContent
|
|
|
|
anchors.fill: parent
|
|
anchors.margins: 16
|
|
spacing: 12
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
|
|
Text {
|
|
color: "#E7E1D8"
|
|
font.pixelSize: 18
|
|
font.weight: Font.DemiBold
|
|
text: qsTr("Definition index")
|
|
}
|
|
|
|
Item {
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
Text {
|
|
color: "#8E8780"
|
|
font.pixelSize: 12
|
|
text: qsTr("%1 shown").arg(root.filteredDefinitions.length)
|
|
}
|
|
}
|
|
|
|
TextField {
|
|
id: searchField
|
|
|
|
objectName: "tokenSearchField"
|
|
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 42
|
|
Accessible.name: qsTr("Search token definitions")
|
|
color: "#E7E1D8"
|
|
font.pixelSize: 14
|
|
placeholderText: qsTr("Search name or definition account")
|
|
placeholderTextColor: "#8E8780"
|
|
selectByMouse: true
|
|
onTextChanged: root.query = text
|
|
|
|
background: Rectangle {
|
|
radius: 7
|
|
color: "#101010"
|
|
border.color: searchField.activeFocus ? "#F26A21" : "#343434"
|
|
border.width: 1
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
spacing: 7
|
|
|
|
Button {
|
|
id: allFilterButton
|
|
|
|
objectName: "tokenAllFilterButton"
|
|
|
|
Layout.preferredHeight: 30
|
|
activeFocusOnTab: true
|
|
Accessible.name: qsTr("Show all token definitions")
|
|
text: qsTr("All")
|
|
onClicked: root.typeFilter = "all"
|
|
|
|
contentItem: Text {
|
|
color: root.typeFilter === "all" ? "#F2D8C7" : "#A9A098"
|
|
font.pixelSize: 12
|
|
horizontalAlignment: Text.AlignHCenter
|
|
verticalAlignment: Text.AlignVCenter
|
|
text: allFilterButton.text
|
|
}
|
|
|
|
background: Rectangle {
|
|
radius: 6
|
|
color: root.typeFilter === "all" ? "#211914" : "#101010"
|
|
border.color: allFilterButton.activeFocus ? "#FFB26B" : root.typeFilter === "all" ? "#F26A21" : "#343434"
|
|
border.width: allFilterButton.activeFocus ? 2 : 1
|
|
}
|
|
}
|
|
|
|
Button {
|
|
id: fungibleFilterButton
|
|
|
|
objectName: "tokenFungibleFilterButton"
|
|
|
|
Layout.preferredHeight: 30
|
|
activeFocusOnTab: true
|
|
Accessible.name: qsTr("Show fungible definitions")
|
|
text: qsTr("Fungible")
|
|
onClicked: root.typeFilter = "fungible"
|
|
|
|
contentItem: Text {
|
|
color: root.typeFilter === "fungible" ? "#F2D8C7" : "#A9A098"
|
|
font.pixelSize: 12
|
|
horizontalAlignment: Text.AlignHCenter
|
|
verticalAlignment: Text.AlignVCenter
|
|
text: fungibleFilterButton.text
|
|
}
|
|
|
|
background: Rectangle {
|
|
radius: 6
|
|
color: root.typeFilter === "fungible" ? "#211914" : "#101010"
|
|
border.color: fungibleFilterButton.activeFocus ? "#FFB26B" : root.typeFilter === "fungible" ? "#F26A21" : "#343434"
|
|
border.width: fungibleFilterButton.activeFocus ? 2 : 1
|
|
}
|
|
}
|
|
|
|
Button {
|
|
id: nftFilterButton
|
|
|
|
objectName: "tokenNftFilterButton"
|
|
|
|
Layout.preferredHeight: 30
|
|
activeFocusOnTab: true
|
|
Accessible.name: qsTr("Show non-fungible definitions")
|
|
text: qsTr("NFT")
|
|
onClicked: root.typeFilter = "nonFungible"
|
|
|
|
contentItem: Text {
|
|
color: root.typeFilter === "nonFungible" ? "#BFD8F4" : "#A9A098"
|
|
font.pixelSize: 12
|
|
horizontalAlignment: Text.AlignHCenter
|
|
verticalAlignment: Text.AlignVCenter
|
|
text: nftFilterButton.text
|
|
}
|
|
|
|
background: Rectangle {
|
|
radius: 6
|
|
color: root.typeFilter === "nonFungible" ? "#182534" : "#101010"
|
|
border.color: nftFilterButton.activeFocus ? "#FFB26B" : root.typeFilter === "nonFungible" ? "#40607A" : "#343434"
|
|
border.width: nftFilterButton.activeFocus ? 2 : 1
|
|
}
|
|
}
|
|
|
|
Item {
|
|
Layout.fillWidth: true
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 1
|
|
color: "#303030"
|
|
}
|
|
|
|
Column {
|
|
id: definitionList
|
|
|
|
Layout.fillWidth: true
|
|
spacing: 7
|
|
|
|
Repeater {
|
|
model: root.filteredDefinitions
|
|
|
|
delegate: Rectangle {
|
|
id: definitionRow
|
|
|
|
objectName: "tokenDefinitionRow"
|
|
|
|
required property var modelData
|
|
|
|
width: definitionList.width
|
|
height: 70
|
|
radius: 9
|
|
color: root.selectedId === definitionRow.modelData.id ? (definitionRow.modelData.type === "fungible" ? "#211914" : "#182534") : rowPointer.containsMouse ? "#222222" : "#101010"
|
|
border.color: root.selectedId === definitionRow.modelData.id || definitionRow.activeFocus ? (definitionRow.modelData.type === "fungible" ? "#F26A21" : "#40607A") : "#343434"
|
|
border.width: 1
|
|
activeFocusOnTab: true
|
|
Accessible.name: qsTr("Inspect %1 definition").arg(definitionRow.modelData.name)
|
|
Accessible.role: Accessible.Button
|
|
Accessible.onPressAction: definitionRow.inspectDefinition()
|
|
|
|
function inspectDefinition() {
|
|
root.selectedId = definitionRow.modelData.id;
|
|
}
|
|
|
|
Keys.onReturnPressed: definitionRow.inspectDefinition()
|
|
Keys.onSpacePressed: definitionRow.inspectDefinition()
|
|
|
|
MouseArea {
|
|
id: rowPointer
|
|
|
|
anchors.fill: parent
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
onClicked: definitionRow.inspectDefinition()
|
|
}
|
|
|
|
RowLayout {
|
|
anchors.fill: parent
|
|
anchors.margins: 11
|
|
spacing: 10
|
|
|
|
Rectangle {
|
|
Layout.preferredHeight: 30
|
|
Layout.preferredWidth: rowKind.implicitWidth + 14
|
|
radius: 15
|
|
color: definitionRow.modelData.type === "fungible" ? "#2D211A" : "#182534"
|
|
border.color: definitionRow.modelData.type === "fungible" ? "#6A4329" : "#40607A"
|
|
border.width: 1
|
|
|
|
Text {
|
|
id: rowKind
|
|
|
|
anchors.centerIn: parent
|
|
color: definitionRow.modelData.type === "fungible" ? "#F2D8C7" : "#BFD8F4"
|
|
font.pixelSize: 11
|
|
font.weight: Font.DemiBold
|
|
text: definitionRow.modelData.type === "fungible" ? qsTr("FT") : qsTr("NFT")
|
|
}
|
|
}
|
|
|
|
ColumnLayout {
|
|
Layout.fillWidth: true
|
|
spacing: 2
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
color: "#E7E1D8"
|
|
elide: Text.ElideRight
|
|
font.pixelSize: 14
|
|
font.weight: Font.DemiBold
|
|
text: definitionRow.modelData.name
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
color: "#8E8780"
|
|
elide: Text.ElideMiddle
|
|
font.family: "monospace"
|
|
font.pixelSize: 11
|
|
text: root.store ? root.store.shortAddress(definitionRow.modelData.definitionId) : definitionRow.modelData.definitionId
|
|
}
|
|
}
|
|
|
|
Text {
|
|
color: definitionRow.modelData.source === "pending" || definitionRow.modelData.source === "draft" ? "#78C88D" : "#A9A098"
|
|
font.pixelSize: 11
|
|
text: root.sourceLabel(definitionRow.modelData)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Text {
|
|
width: parent.width
|
|
visible: root.filteredDefinitions.length === 0
|
|
color: "#A9A098"
|
|
font.pixelSize: 13
|
|
horizontalAlignment: Text.AlignHCenter
|
|
text: qsTr("No definition matches this search.")
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
id: detailPanel
|
|
|
|
Layout.alignment: Qt.AlignTop
|
|
Layout.fillWidth: true
|
|
Layout.minimumWidth: 0
|
|
Layout.preferredWidth: workbench.columnCount === 2 ? 850 : 0
|
|
Layout.maximumWidth: 1440
|
|
implicitHeight: detailContent.implicitHeight + 32
|
|
radius: 16
|
|
color: "#1B1B1B"
|
|
border.color: "#303030"
|
|
border.width: 1
|
|
|
|
ColumnLayout {
|
|
id: detailContent
|
|
|
|
anchors.fill: parent
|
|
anchors.margins: 16
|
|
spacing: 14
|
|
|
|
Item {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: root.hasSelection ? headline.implicitHeight : emptyState.implicitHeight
|
|
|
|
RowLayout {
|
|
id: headline
|
|
|
|
anchors.fill: parent
|
|
visible: root.hasSelection
|
|
spacing: 10
|
|
|
|
Rectangle {
|
|
Layout.alignment: Qt.AlignTop
|
|
Layout.preferredHeight: 30
|
|
Layout.preferredWidth: selectedKind.implicitWidth + 16
|
|
radius: 15
|
|
color: root.selectedIsFungible ? "#2D211A" : "#182534"
|
|
border.color: root.selectedIsFungible ? "#6A4329" : "#40607A"
|
|
border.width: 1
|
|
|
|
Text {
|
|
id: selectedKind
|
|
|
|
anchors.centerIn: parent
|
|
color: root.selectedIsFungible ? "#F2D8C7" : "#BFD8F4"
|
|
font.pixelSize: 12
|
|
font.weight: Font.DemiBold
|
|
text: root.selectedIsFungible ? qsTr("Fungible") : qsTr("NFT collection")
|
|
}
|
|
}
|
|
|
|
ColumnLayout {
|
|
Layout.fillWidth: true
|
|
spacing: 3
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
color: "#E7E1D8"
|
|
elide: Text.ElideRight
|
|
font.pixelSize: 22
|
|
font.weight: Font.DemiBold
|
|
text: root.hasSelection ? root.selectedDefinition.name : ""
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
color: root.hasSelection && (root.selectedDefinition.source === "pending" || root.selectedDefinition.source === "draft") ? "#78C88D" : "#A9A098"
|
|
font.pixelSize: 12
|
|
text: root.hasSelection ? root.sourceLabel(root.selectedDefinition) : ""
|
|
}
|
|
}
|
|
}
|
|
|
|
Text {
|
|
id: emptyState
|
|
|
|
anchors.fill: parent
|
|
visible: !root.hasSelection
|
|
color: "#A9A098"
|
|
font.pixelSize: 15
|
|
horizontalAlignment: Text.AlignHCenter
|
|
verticalAlignment: Text.AlignVCenter
|
|
text: qsTr("Choose a definition from the index to inspect it.")
|
|
}
|
|
}
|
|
|
|
GridLayout {
|
|
id: summaryGrid
|
|
|
|
Layout.fillWidth: true
|
|
visible: root.hasSelection
|
|
Layout.preferredHeight: visible ? implicitHeight : 0
|
|
columns: detailContent.width >= 800 ? 3 : detailContent.width >= 500 ? 2 : 1
|
|
columnSpacing: 9
|
|
rowSpacing: 9
|
|
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 80
|
|
radius: 10
|
|
color: "#101010"
|
|
border.color: "#343434"
|
|
border.width: 1
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
anchors.margins: 11
|
|
spacing: 3
|
|
|
|
Text {
|
|
color: "#8E8780"
|
|
font.pixelSize: 11
|
|
text: qsTr("Stored definition")
|
|
}
|
|
|
|
Text {
|
|
color: "#E7E1D8"
|
|
font.pixelSize: 15
|
|
font.weight: Font.DemiBold
|
|
text: root.selectedIsFungible ? qsTr("Fungible token") : qsTr("Non-fungible token")
|
|
}
|
|
|
|
Text {
|
|
color: "#A9A098"
|
|
font.pixelSize: 11
|
|
text: root.selectedIsFungible ? qsTr("total_supply") : qsTr("printable_supply")
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 80
|
|
radius: 10
|
|
color: "#101010"
|
|
border.color: "#343434"
|
|
border.width: 1
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
anchors.margins: 11
|
|
spacing: 3
|
|
|
|
Text {
|
|
color: "#8E8780"
|
|
font.pixelSize: 11
|
|
text: root.selectedIsFungible ? qsTr("Current raw supply") : qsTr("Printable supply")
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
color: "#E7E1D8"
|
|
elide: Text.ElideMiddle
|
|
font.family: "monospace"
|
|
font.pixelSize: 14
|
|
font.weight: Font.DemiBold
|
|
text: !root.hasSelection ? "" : root.selectedIsFungible ? root.valueOrDash(root.selectedDefinition.rawSupply) : root.valueOrDash(root.selectedDefinition.printableCopies)
|
|
}
|
|
|
|
Text {
|
|
color: "#A9A098"
|
|
font.pixelSize: 11
|
|
text: root.selectedIsFungible ? qsTr("raw u128") : qsTr("master starts at this balance")
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 80
|
|
radius: 10
|
|
color: "#101010"
|
|
border.color: "#343434"
|
|
border.width: 1
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
anchors.margins: 11
|
|
spacing: 3
|
|
|
|
Text {
|
|
color: "#8E8780"
|
|
font.pixelSize: 11
|
|
text: root.selectedIsNft ? qsTr("Control") : qsTr("Mint authority")
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
color: root.hasSelection && root.selectedDefinition.authorityMode === "renounced" ? "#78C88D" : "#E7E1D8"
|
|
elide: Text.ElideRight
|
|
font.pixelSize: 15
|
|
font.weight: Font.DemiBold
|
|
text: root.authorityTitle(root.selectedDefinition)
|
|
}
|
|
|
|
Text {
|
|
color: "#A9A098"
|
|
font.pixelSize: 11
|
|
text: root.hasSelection && root.selectedDefinition.metadataStandard ? qsTr("%1 metadata").arg(root.selectedDefinition.metadataStandard) : qsTr("No metadata linked")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
visible: root.hasSelection
|
|
Layout.preferredHeight: visible ? definitionRecord.implicitHeight + 26 : 0
|
|
radius: 10
|
|
color: "#101010"
|
|
border.color: "#343434"
|
|
border.width: 1
|
|
|
|
ColumnLayout {
|
|
id: definitionRecord
|
|
|
|
anchors.fill: parent
|
|
anchors.margins: 13
|
|
spacing: 8
|
|
|
|
Text {
|
|
color: "#E7E1D8"
|
|
font.pixelSize: 16
|
|
font.weight: Font.DemiBold
|
|
text: qsTr("Definition record")
|
|
}
|
|
|
|
Text {
|
|
color: "#8E8780"
|
|
font.pixelSize: 11
|
|
text: qsTr("DEFINITION ACCOUNT")
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
color: "#E7E1D8"
|
|
elide: Text.ElideMiddle
|
|
font.family: "monospace"
|
|
font.pixelSize: 13
|
|
text: root.hasSelection ? root.selectedDefinition.definitionId : ""
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
visible: root.hasSelection && !!root.selectedDefinition.definitionHex
|
|
Layout.preferredHeight: visible ? implicitHeight : 0
|
|
color: "#8E8780"
|
|
elide: Text.ElideMiddle
|
|
font.family: "monospace"
|
|
font.pixelSize: 11
|
|
text: root.hasSelection ? qsTr("hex %1").arg(root.selectedDefinition.definitionHex) : ""
|
|
}
|
|
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 1
|
|
color: "#303030"
|
|
}
|
|
|
|
GridLayout {
|
|
Layout.fillWidth: true
|
|
columns: detailContent.width >= 720 ? 2 : 1
|
|
columnSpacing: 16
|
|
rowSpacing: 7
|
|
|
|
ColumnLayout {
|
|
Layout.fillWidth: true
|
|
visible: root.selectedIsFungible
|
|
Layout.preferredHeight: visible ? implicitHeight : 0
|
|
spacing: 3
|
|
|
|
Text {
|
|
color: "#8E8780"
|
|
font.pixelSize: 11
|
|
text: qsTr("DISPLAYED SUPPLY")
|
|
}
|
|
|
|
Text {
|
|
color: "#E7E1D8"
|
|
font.pixelSize: 15
|
|
font.weight: Font.Medium
|
|
text: root.hasSelection ? root.valueOrDash(root.selectedDefinition.displaySupply) : ""
|
|
}
|
|
|
|
Text {
|
|
color: "#A9A098"
|
|
font.pixelSize: 12
|
|
text: root.hasSelection ? qsTr("UI inference: %1 decimal places; not stored in this definition.").arg(root.valueOrDash(root.selectedDefinition.inferredDecimals)) : ""
|
|
}
|
|
}
|
|
|
|
ColumnLayout {
|
|
Layout.fillWidth: true
|
|
visible: root.selectedIsNft
|
|
Layout.preferredHeight: visible ? implicitHeight : 0
|
|
spacing: 3
|
|
|
|
Text {
|
|
color: "#8E8780"
|
|
font.pixelSize: 11
|
|
text: qsTr("NFT CREATION PATH")
|
|
}
|
|
|
|
Text {
|
|
color: "#E7E1D8"
|
|
font.family: "monospace"
|
|
font.pixelSize: 14
|
|
font.weight: Font.Medium
|
|
text: root.hasSelection ? root.selectedDefinition.instruction : ""
|
|
}
|
|
|
|
Text {
|
|
color: "#A9A098"
|
|
font.pixelSize: 12
|
|
text: qsTr("NFT creation always links metadata and creates one master holding.")
|
|
}
|
|
}
|
|
|
|
ColumnLayout {
|
|
Layout.fillWidth: true
|
|
spacing: 3
|
|
|
|
Text {
|
|
color: "#8E8780"
|
|
font.pixelSize: 11
|
|
text: qsTr("CREATION INSTRUCTION")
|
|
}
|
|
|
|
Text {
|
|
color: "#F2D8C7"
|
|
font.family: "monospace"
|
|
font.pixelSize: 14
|
|
font.weight: Font.Medium
|
|
text: root.hasSelection ? root.selectedDefinition.instruction : ""
|
|
}
|
|
|
|
Text {
|
|
color: "#A9A098"
|
|
font.pixelSize: 12
|
|
text: root.selectedIsFungible && root.selectedDefinition.metadataId ? qsTr("Metadata-backed fungible creation.") : root.selectedIsFungible ? qsTr("Plain fungible creation.") : qsTr("Typed metadata creation is required.")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
visible: root.hasSelection
|
|
Layout.preferredHeight: visible ? authorityRecord.implicitHeight + 26 : 0
|
|
radius: 10
|
|
color: root.selectedIsNft ? "#181D25" : "#101010"
|
|
border.color: root.selectedIsNft ? "#31435D" : "#343434"
|
|
border.width: 1
|
|
|
|
ColumnLayout {
|
|
id: authorityRecord
|
|
|
|
anchors.fill: parent
|
|
anchors.margins: 13
|
|
spacing: 8
|
|
|
|
Text {
|
|
color: "#E7E1D8"
|
|
font.pixelSize: 16
|
|
font.weight: Font.DemiBold
|
|
text: root.selectedIsNft ? qsTr("Master holding and print control") : qsTr("Mint authority")
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
color: "#A9A098"
|
|
font.pixelSize: 13
|
|
wrapMode: Text.Wrap
|
|
text: root.hasSelection ? root.authorityDescription(root.selectedDefinition) : ""
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
visible: root.hasSelection && root.selectedIsFungible && !!root.selectedDefinition.authority
|
|
Layout.preferredHeight: visible ? implicitHeight : 0
|
|
color: "#E7E1D8"
|
|
elide: Text.ElideMiddle
|
|
font.family: "monospace"
|
|
font.pixelSize: 13
|
|
text: root.hasSelection ? root.selectedDefinition.authority : ""
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
visible: root.hasSelection && root.selectedIsFungible && !!root.selectedDefinition.authorityLabel
|
|
Layout.preferredHeight: visible ? implicitHeight : 0
|
|
color: "#A9A098"
|
|
font.pixelSize: 12
|
|
text: root.hasSelection ? String(root.selectedDefinition.authorityLabel || "") : ""
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
visible: root.hasSelection && root.selectedIsFungible && root.selectedDefinition.authorityMode === "renounced"
|
|
Layout.preferredHeight: visible ? implicitHeight : 0
|
|
color: "#78C88D"
|
|
font.pixelSize: 12
|
|
wrapMode: Text.Wrap
|
|
text: root.hasSelection ? qsTr("Initial self authority: %1").arg(root.selectedDefinition.initialAuthority) : ""
|
|
}
|
|
|
|
GridLayout {
|
|
Layout.fillWidth: true
|
|
visible: root.selectedIsNft
|
|
Layout.preferredHeight: visible ? implicitHeight : 0
|
|
columns: detailContent.width >= 720 ? 2 : 1
|
|
columnSpacing: 16
|
|
rowSpacing: 9
|
|
|
|
ColumnLayout {
|
|
Layout.fillWidth: true
|
|
spacing: 3
|
|
|
|
Text {
|
|
color: "#8E8780"
|
|
font.pixelSize: 11
|
|
text: qsTr("MASTER HOLDING")
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
color: "#E7E1D8"
|
|
elide: Text.ElideMiddle
|
|
font.family: "monospace"
|
|
font.pixelSize: 13
|
|
text: root.hasSelection ? root.valueOrDash(root.selectedDefinition.masterHolding) : ""
|
|
}
|
|
}
|
|
|
|
ColumnLayout {
|
|
Layout.fillWidth: true
|
|
spacing: 3
|
|
|
|
Text {
|
|
color: "#8E8780"
|
|
font.pixelSize: 11
|
|
text: qsTr("CURRENT MASTER PRINT BALANCE")
|
|
}
|
|
|
|
Text {
|
|
color: "#BFD8F4"
|
|
font.pixelSize: 15
|
|
font.weight: Font.Medium
|
|
text: root.hasSelection && root.selectedDefinition.holding ? root.valueOrDash(root.selectedDefinition.holding.printBalance) : "—"
|
|
}
|
|
}
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
visible: root.selectedIsNft
|
|
Layout.preferredHeight: visible ? implicitHeight : 0
|
|
color: "#BFD8F4"
|
|
font.pixelSize: 12
|
|
wrapMode: Text.Wrap
|
|
text: qsTr("A print requires master balance greater than 1 and leaves one master unit reserved. Printed copies do not restore print capacity when burned.")
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
visible: root.hasSelection
|
|
Layout.preferredHeight: visible ? holdingsRecord.implicitHeight + 26 : 0
|
|
radius: 10
|
|
color: "#101010"
|
|
border.color: "#343434"
|
|
border.width: 1
|
|
|
|
ColumnLayout {
|
|
id: holdingsRecord
|
|
|
|
anchors.fill: parent
|
|
anchors.margins: 13
|
|
spacing: 9
|
|
|
|
Text {
|
|
color: "#E7E1D8"
|
|
font.pixelSize: 16
|
|
font.weight: Font.DemiBold
|
|
text: root.selectedIsNft ? qsTr("Observed NFT holdings") : qsTr("Observed token holdings")
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
color: "#A9A098"
|
|
font.pixelSize: 12
|
|
wrapMode: Text.Wrap
|
|
text: root.hasSelection && root.selectedDefinition.source === "pending" ? qsTr("Transaction accepted; refresh after the account state is indexed.") : qsTr("Balances and ownership reflect the selected network state.")
|
|
}
|
|
|
|
Column {
|
|
id: holdingList
|
|
|
|
Layout.fillWidth: true
|
|
spacing: 7
|
|
visible: root.hasSelection && root.selectedDefinition.holdings && root.selectedDefinition.holdings.length > 0
|
|
|
|
Repeater {
|
|
model: root.hasSelection && root.selectedDefinition.holdings ? root.selectedDefinition.holdings : []
|
|
|
|
delegate: Rectangle {
|
|
id: holdingRow
|
|
|
|
required property var modelData
|
|
|
|
width: holdingList.width
|
|
height: 62
|
|
radius: 8
|
|
color: holdingRow.modelData.role === "nftMaster" ? "#181D25" : "#181818"
|
|
border.color: holdingRow.modelData.role === "nftMaster" ? "#31435D" : "#303030"
|
|
border.width: 1
|
|
|
|
RowLayout {
|
|
anchors.fill: parent
|
|
anchors.margins: 10
|
|
spacing: 10
|
|
|
|
ColumnLayout {
|
|
Layout.fillWidth: true
|
|
spacing: 2
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
color: "#E7E1D8"
|
|
elide: Text.ElideMiddle
|
|
font.family: "monospace"
|
|
font.pixelSize: 12
|
|
text: holdingRow.modelData.id
|
|
}
|
|
|
|
Text {
|
|
color: "#A9A098"
|
|
font.pixelSize: 11
|
|
text: holdingRow.modelData.role === "nftMaster" ? qsTr("NFT master holding") : holdingRow.modelData.role === "nftPrintedCopy" ? (holdingRow.modelData.owned ? qsTr("Printed copy · owned") : qsTr("Printed copy · unowned")) : qsTr("%1 · %2").arg(holdingRow.modelData.wallet).arg(holdingRow.modelData.role)
|
|
}
|
|
}
|
|
|
|
ColumnLayout {
|
|
Layout.alignment: Qt.AlignRight
|
|
spacing: 2
|
|
|
|
Text {
|
|
color: holdingRow.modelData.printBalance !== undefined ? "#BFD8F4" : "#E7E1D8"
|
|
font.family: "monospace"
|
|
font.pixelSize: 12
|
|
font.weight: Font.Medium
|
|
text: holdingRow.modelData.printBalance !== undefined ? root.valueOrDash(holdingRow.modelData.printBalance) : holdingRow.modelData.rawBalance !== undefined ? root.valueOrDash(holdingRow.modelData.rawBalance) : ""
|
|
}
|
|
|
|
Text {
|
|
visible: holdingRow.modelData.displayBalance !== undefined || holdingRow.modelData.printBalance !== undefined
|
|
color: "#8E8780"
|
|
font.pixelSize: 11
|
|
text: holdingRow.modelData.printBalance !== undefined ? qsTr("print balance") : root.valueOrDash(holdingRow.modelData.displayBalance)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
visible: root.hasSelection && (!root.selectedDefinition.holdings || root.selectedDefinition.holdings.length === 0)
|
|
Layout.preferredHeight: visible ? implicitHeight : 0
|
|
color: "#E7E1D8"
|
|
elide: Text.ElideMiddle
|
|
font.family: "monospace"
|
|
font.pixelSize: 13
|
|
text: root.hasSelection ? root.valueOrDash(root.selectedDefinition.holdingId) : ""
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
visible: root.hasSelection && !!root.selectedDefinition.metadataId
|
|
Layout.preferredHeight: visible ? metadataRecord.implicitHeight + 26 : 0
|
|
radius: 10
|
|
color: "#101010"
|
|
border.color: "#343434"
|
|
border.width: 1
|
|
|
|
ColumnLayout {
|
|
id: metadataRecord
|
|
|
|
anchors.fill: parent
|
|
anchors.margins: 13
|
|
spacing: 8
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
|
|
Text {
|
|
color: "#E7E1D8"
|
|
font.pixelSize: 16
|
|
font.weight: Font.DemiBold
|
|
text: qsTr("Linked metadata")
|
|
}
|
|
|
|
Item {
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
Rectangle {
|
|
Layout.preferredHeight: 23
|
|
Layout.preferredWidth: metadataStandard.implicitWidth + 14
|
|
radius: 12
|
|
color: "#211914"
|
|
border.color: "#49301F"
|
|
border.width: 1
|
|
|
|
Text {
|
|
id: metadataStandard
|
|
|
|
anchors.centerIn: parent
|
|
color: "#F2D8C7"
|
|
font.pixelSize: 11
|
|
font.weight: Font.DemiBold
|
|
text: root.hasSelection ? root.valueOrDash(root.selectedDefinition.metadataStandard) : ""
|
|
}
|
|
}
|
|
}
|
|
|
|
Text {
|
|
color: "#8E8780"
|
|
font.pixelSize: 11
|
|
text: qsTr("METADATA ACCOUNT")
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
color: "#E7E1D8"
|
|
elide: Text.ElideMiddle
|
|
font.family: "monospace"
|
|
font.pixelSize: 13
|
|
text: root.hasSelection ? root.valueOrDash(root.selectedDefinition.metadataId) : ""
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
visible: root.hasSelection && !!root.selectedDefinition.description
|
|
Layout.preferredHeight: visible ? implicitHeight : 0
|
|
color: "#A9A098"
|
|
font.pixelSize: 13
|
|
wrapMode: Text.Wrap
|
|
text: root.hasSelection ? (root.selectedDefinition.description || "") : ""
|
|
}
|
|
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 1
|
|
color: "#303030"
|
|
}
|
|
|
|
Text {
|
|
color: "#8E8780"
|
|
font.pixelSize: 11
|
|
text: qsTr("URI")
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
color: "#E7E1D8"
|
|
font.family: "monospace"
|
|
font.pixelSize: 11
|
|
wrapMode: Text.WrapAnywhere
|
|
text: root.hasSelection ? root.valueOrDash(root.selectedDefinition.metadataUri) : ""
|
|
}
|
|
|
|
Text {
|
|
color: "#8E8780"
|
|
font.pixelSize: 11
|
|
text: qsTr("CREATORS")
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
color: "#E7E1D8"
|
|
font.pixelSize: 13
|
|
wrapMode: Text.WrapAnywhere
|
|
text: root.hasSelection ? root.valueOrDash(root.selectedDefinition.creators) : ""
|
|
}
|
|
|
|
Text {
|
|
color: "#A9A098"
|
|
font.pixelSize: 12
|
|
text: qsTr("Stored primary_sale_date starts at 0. The token program does not validate URI content or metadata schema.")
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
visible: root.hasSelection && !root.selectedDefinition.metadataId
|
|
Layout.preferredHeight: visible ? metadataAbsent.implicitHeight + 22 : 0
|
|
radius: 9
|
|
color: "#181818"
|
|
border.color: "#303030"
|
|
border.width: 1
|
|
|
|
Text {
|
|
id: metadataAbsent
|
|
|
|
anchors.fill: parent
|
|
anchors.margins: 11
|
|
color: "#A9A098"
|
|
font.pixelSize: 12
|
|
wrapMode: Text.Wrap
|
|
text: qsTr("No metadata account is linked to this definition. Metadata is optional for fungibles and required for non-fungible definitions.")
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
visible: root.hasSelection
|
|
Layout.preferredHeight: visible ? contractNotice.implicitHeight + 22 : 0
|
|
radius: 9
|
|
color: "#211914"
|
|
border.color: "#49301F"
|
|
border.width: 1
|
|
|
|
Text {
|
|
id: contractNotice
|
|
|
|
anchors.fill: parent
|
|
anchors.margins: 11
|
|
color: "#F2D8C7"
|
|
font.pixelSize: 12
|
|
wrapMode: Text.Wrap
|
|
text: root.selectedIsFungible ? qsTr("The Token Program stores raw supply and optional authority/metadata links. Decimals, symbol, image, royalties, collection, and mutable metadata are not definition settings.") : qsTr("The Token Program stores the NFT name, printable supply, and required metadata link. It has no NFT mint authority or configurable royalty, collection, image, or mutable-metadata setting.")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|