mirror of
https://github.com/logos-blockchain/logos-execution-zone-wallet-ui.git
synced 2026-05-08 05:39:24 +00:00
Merge pull request #12 from logos-blockchain/fix/privateToOwned
fix: transfer_private_owned
This commit is contained in:
commit
c510f89cf9
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
81
src/qml/controls/AccountComboBox.qml
Normal file
81
src/qml/controls/AccountComboBox.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user