Merge pull request #12 from logos-blockchain/fix/privateToOwned

fix: transfer_private_owned
This commit is contained in:
Khushboo-dev-cpp 2026-03-07 16:33:02 +00:00 committed by GitHub
commit c510f89cf9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 189 additions and 90 deletions

View File

@ -146,6 +146,7 @@ void LEZWalletBackend::refreshBalances()
const bool isPub = m_accountModel->data(idx, LEZWalletAccountModel::IsPublicRole).toBool();
m_accountModel->setBalanceByAddress(addr, getBalance(addr, isPub));
}
saveWallet();
}
void LEZWalletBackend::fetchAndUpdateBlockHeights()
@ -272,6 +273,19 @@ QString LEZWalletBackend::transferPrivate(
return result.isValid() ? result.toString() : QStringLiteral("Error: Call failed.");
}
QString LEZWalletBackend::transferPrivateOwned(
const QString& fromHex,
const QString& toHex,
const QString& amountLe16Hex)
{
if (!m_walletClient) return QStringLiteral("Error: Module not initialized.");
const QString amountHex = amountToLe16Hex(amountLe16Hex);
if (amountHex.isEmpty()) return QStringLiteral("Error: Invalid amount.");
QVariant result = m_walletClient->invokeRemoteMethod(
WALLET_MODULE_NAME, "transfer_private_owned", fromHex, toHex.trimmed(), amountHex);
return result.isValid() ? result.toString() : QStringLiteral("Error: Call failed.");
}
bool LEZWalletBackend::createNew(
const QString& configPath,
const QString& storagePath,

View File

@ -53,6 +53,10 @@ public:
const QString& fromHex,
const QString& toHex,
const QString& amountLe16Hex);
Q_INVOKABLE QString transferPrivateOwned(
const QString& fromHex,
const QString& toHex,
const QString& amountLe16Hex);
Q_INVOKABLE bool createNew(
const QString& configPath,
const QString& storagePath,

View File

@ -109,14 +109,9 @@ Rectangle {
}
backend.refreshBalances()
}
onTransferRequested: function(isPublic, fromId, toAddress, amount) {
if (!backend) {
console.warning("backend is null")
return
}
var raw = isPublic
? backend.transferPublic(fromId, toAddress, amount)
: backend.transferPrivate(fromId, toAddress, amount)
onTransferPublicRequested: (fromId, toAddress, amount) => {
if (!backend) return
var raw = backend.transferPublic(fromId, toAddress, amount)
var msg = raw || ""
var isError = false
try {
@ -128,8 +123,45 @@ Rectangle {
isError = true
}
} catch (e) {
if (msg.length > 0)
if (msg.length > 0) isError = true
}
dashboardView.transferResult = msg
dashboardView.transferResultIsError = isError
}
onTransferPrivateRequested: (fromId, toKeysJsonOrAddress, amount) => {
if (!backend) return
var raw = backend.transferPrivate(fromId, toKeysJsonOrAddress, amount)
var msg = raw || ""
var isError = false
try {
var obj = JSON.parse(raw)
if (obj.success) {
msg = obj.tx_hash ? qsTr("Success. Tx: %1").arg(obj.tx_hash) : qsTr("Success.")
} else if (obj.error) {
msg = ffiErrors.format(obj.error)
isError = true
}
} catch (e) {
if (msg.length > 0) isError = true
}
dashboardView.transferResult = msg
dashboardView.transferResultIsError = isError
}
onTransferPrivateOwnedRequested: (fromId, toAccountId, amount) => {
if (!backend) return
var raw = backend.transferPrivateOwned(fromId, toAccountId, amount)
var msg = raw || ""
var isError = false
try {
var obj = JSON.parse(raw)
if (obj.success) {
msg = obj.tx_hash ? qsTr("Success. Tx: %1").arg(obj.tx_hash) : qsTr("Success.")
} else if (obj.error) {
msg = ffiErrors.format(obj.error)
isError = true
}
} catch (e) {
if (msg.length > 0) isError = true
}
dashboardView.transferResult = msg
dashboardView.transferResultIsError = isError

View File

@ -0,0 +1,81 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Logos.Theme
import Logos.Controls
ComboBox {
id: root
leftPadding: 12
rightPadding: 12
implicitHeight: 40
textRole: "name"
valueRole: "address"
background: Rectangle {
radius: Theme.spacing.radiusSmall
color: Theme.palette.backgroundSecondary
border.width: 1
border.color: root.popup.visible ? Theme.palette.overlayOrange : Theme.palette.backgroundElevated
}
indicator: LogosText {
id: indicatorText
text: "▼"
font.pixelSize: Theme.typography.secondaryText
color: Theme.palette.textSecondary
x: root.width - width - 12
y: (root.height - height) / 2
visible: root.count > 0
}
contentItem: Item {
implicitWidth: 120
width: root.width - indicatorText.width - 12
TextInput {
id: comboContentInput
anchors.fill: parent
readOnly: true
selectByMouse: true
font.pixelSize: Theme.typography.secondaryText
color: Theme.palette.text
text: root.displayText
verticalAlignment: Text.AlignVCenter
clip: true
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
onClicked: root.popup.visible ? root.popup.close() : root.popup.open()
}
}
delegate: AccountDelegate {
width: root.popup ? (root.popup.width - root.popup.leftPadding - root.popup.rightPadding) : 368
highlighted: root.highlightedIndex === index
}
popup: Popup {
y: root.height - 1
width: 400
height: Math.min(contentItem.implicitHeight + 8, 300)
padding: Theme.spacing.small
contentItem: ListView {
clip: true
implicitHeight: contentHeight
model: root.popup.visible ? root.delegateModel : null
ScrollIndicator.vertical: ScrollIndicator { }
highlightFollowsCurrentItem: false
}
background: Rectangle {
color: Theme.palette.backgroundTertiary
border.width: 1
border.color: Theme.palette.backgroundElevated
radius: Theme.spacing.radiusSmall
}
}
}

View File

@ -17,7 +17,9 @@ Rectangle {
signal createPublicAccountRequested()
signal createPrivateAccountRequested()
signal fetchBalancesRequested()
signal transferRequested(bool isPublic, string fromAccountId, string toAddress, string amount)
signal transferPublicRequested(string fromAccountId, string toAddress, string amount)
signal transferPrivateRequested(string fromAccountId, string toKeysJsonOrAddress, string amount)
signal transferPrivateOwnedRequested(string fromAccountId, string toAccountId, string amount)
signal copyRequested(string copyText)
color: Theme.palette.background
@ -47,9 +49,9 @@ Rectangle {
transferResult: root.transferResult
transferResultIsError: root.transferResultIsError
onTransferRequested: function(isPublic, fromId, toAddress, amount) {
root.transferRequested(isPublic, fromId, toAddress, amount)
}
onTransferPublicRequested: (fromId, toAddress, amount) => root.transferPublicRequested(fromId, toAddress, amount)
onTransferPrivateRequested: (fromId, toKeysJsonOrAddress, amount) => root.transferPrivateRequested(fromId, toKeysJsonOrAddress, amount)
onTransferPrivateOwnedRequested: (fromId, toAccountId, amount) => root.transferPrivateOwnedRequested(fromId, toAccountId, amount)
onCopyRequested: (copyText) => root.copyRequested(copyText)
}
}

View File

@ -15,16 +15,23 @@ Rectangle {
property string transferResult: ""
property bool transferResultIsError: false
// --- Public API: signals out ---
signal transferRequested(bool isPublic, string fromAccountId, string toAddress, string amount)
// --- Public API: signals out (match backend: transfer_public, transfer_private, transfer_private_owned) ---
signal transferPublicRequested(string fromAccountId, string toAddress, string amount)
signal transferPrivateRequested(string fromAccountId, string toKeysJsonOrAddress, string amount)
signal transferPrivateOwnedRequested(string fromAccountId, string toAccountId, string amount)
signal copyRequested(string copyText)
readonly property int fromFilterCount: fromAccountModel ? fromAccountModel.count : 0
QtObject {
id: d
readonly property bool sendEnabled: toField && amountField && manualFromField
&& toField.text.length > 0 && amountField.text.length > 0
property bool useOwnedAccountForTo: false
readonly property bool isPrivateTab: transferTypeBar.currentIndex === 1
readonly property bool toAddressValid: isPrivateTab && useOwnedAccountForTo
? (fromFilterCount > 0 && toCombo.currentIndex >= 0)
: (toField && toField.text.trim().length > 0)
readonly property bool sendEnabled: amountField && manualFromField
&& amountField.text.length > 0 && d.toAddressValid
&& ((fromFilterCount > 0 && fromCombo.currentIndex >= 0)
|| (fromFilterCount === 0 && manualFromField.text.trim().length > 0))
}
@ -82,81 +89,11 @@ Rectangle {
visible: fromFilterCount === 0
}
ComboBox {
AccountComboBox {
id: fromCombo
Layout.fillWidth: true
leftPadding: 12
rightPadding: 12
implicitHeight: 40
model: fromAccountModel
textRole: "name"
valueRole: "address"
visible: fromFilterCount > 0
background: Rectangle {
radius: Theme.spacing.radiusSmall
color: Theme.palette.backgroundSecondary
border.width: 1
border.color: fromCombo.popup.visible ? Theme.palette.overlayOrange : Theme.palette.backgroundElevated
}
indicator: LogosText {
id: indicatorText
text: "▼"
font.pixelSize: Theme.typography.secondaryText
color: Theme.palette.textSecondary
x: fromCombo.width - width - 12
y: (fromCombo.height - height) / 2
visible: fromCombo.count > 0
}
contentItem: Item {
implicitWidth: 120
width: fromCombo.width - indicatorText.width - 12
TextInput {
id: fromComboContentInput
anchors.fill: parent
readOnly: true
selectByMouse: true
font.pixelSize: Theme.typography.secondaryText
color: Theme.palette.text
text: fromCombo.displayText
verticalAlignment: Text.AlignVCenter
clip: true
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
onClicked: fromCombo.popup.visible ? fromCombo.popup.close() : fromCombo.popup.open()
}
}
delegate: AccountDelegate {
width: fromCombo.popup.width - fromCombo.popup.leftPadding - fromCombo.popup.rightPadding
highlighted: fromCombo.highlightedIndex === index
}
popup: Popup {
y: fromCombo.height - 1
width: 400
height: Math.min(contentItem.implicitHeight + 8, 300)
padding: Theme.spacing.small
contentItem: ListView {
clip: true
implicitHeight: contentHeight
model: fromCombo.popup.visible ? fromCombo.delegateModel : null
ScrollIndicator.vertical: ScrollIndicator { }
highlightFollowsCurrentItem: false
}
background: Rectangle {
color: Theme.palette.backgroundTertiary
border.width: 1
border.color: Theme.palette.backgroundElevated
radius: Theme.spacing.radiusSmall
}
}
}
}
@ -171,10 +108,28 @@ Rectangle {
color: Theme.palette.textSecondary
}
CheckBox {
id: useOwnedToCheck
visible: d.isPrivateTab
checked: d.useOwnedAccountForTo
onCheckedChanged: d.useOwnedAccountForTo = checked
text: qsTr("Use owned account")
font.pixelSize: Theme.typography.secondaryText
palette.text: Theme.palette.text
}
LogosTextField {
id: toField
Layout.fillWidth: true
placeholderText: qsTr("Recipient public key")
visible: !d.isPrivateTab || !d.useOwnedAccountForTo
}
AccountComboBox {
id: toCombo
Layout.fillWidth: true
model: fromAccountModel
visible: d.isPrivateTab && d.useOwnedAccountForTo && fromFilterCount > 0
}
}
@ -206,8 +161,18 @@ Rectangle {
var fromId = fromFilterCount > 0 && fromCombo.currentIndex >= 0
? (fromCombo.currentValue ?? "")
: manualFromField.text.trim()
if (fromId.length > 0)
root.transferRequested(transferTypeBar.currentIndex === 0, fromId, toField.text.trim(), amountField.text.trim())
var toAddress = d.useOwnedAccountForTo && toCombo.currentIndex >= 0
? (toCombo.currentValue ?? "")
: toField.text.trim()
var amount = amountField.text.trim()
if (fromId.length > 0 && toAddress.length > 0 && amount.length > 0) {
if (transferTypeBar.currentIndex === 0)
root.transferPublicRequested(fromId, toAddress, amount)
else if (d.useOwnedAccountForTo)
root.transferPrivateOwnedRequested(fromId, toAddress, amount)
else
root.transferPrivateRequested(fromId, toAddress, amount)
}
}
}

View File

@ -1,6 +1,7 @@
<RCC>
<qresource prefix="/lezwallet">
<file>qml/ExecutionZoneWalletView.qml</file>
<file>qml/controls/AccountComboBox.qml</file>
<file>qml/controls/AccountDelegate.qml</file>
<file>qml/popups/CreateAccountDialog.qml</file>
<file>qml/views/qmldir</file>