2026-02-20 14:20:39 +01:00
|
|
|
import QtQuick
|
|
|
|
|
import QtQuick.Controls
|
|
|
|
|
import QtQuick.Layouts
|
|
|
|
|
|
|
|
|
|
import LEZWalletBackend
|
|
|
|
|
import Logos.Theme
|
|
|
|
|
import Logos.Controls
|
2026-02-20 18:10:59 +01:00
|
|
|
import "views"
|
2026-02-20 14:20:39 +01:00
|
|
|
|
|
|
|
|
Rectangle {
|
|
|
|
|
id: root
|
|
|
|
|
|
2026-02-23 18:09:06 +01:00
|
|
|
// Map wallet FFI error codes to user-facing strings. Matches lssa/wallet-ffi WalletFfiError enum.
|
|
|
|
|
QtObject {
|
|
|
|
|
id: ffiErrors
|
|
|
|
|
readonly property var codeToMessage: ({
|
|
|
|
|
0: qsTr("Success"),
|
|
|
|
|
1: qsTr("Invalid argument (null pointer)"),
|
|
|
|
|
2: qsTr("Invalid UTF-8 string"),
|
|
|
|
|
3: qsTr("Wallet not initialized"),
|
|
|
|
|
4: qsTr("Configuration error"),
|
|
|
|
|
5: qsTr("Storage or persistence error"),
|
|
|
|
|
6: qsTr("Network or RPC error"),
|
|
|
|
|
7: qsTr("Account not found"),
|
|
|
|
|
8: qsTr("Key not found for account"),
|
|
|
|
|
9: qsTr("Insufficient funds"),
|
|
|
|
|
10: qsTr("Invalid account ID format"),
|
|
|
|
|
11: qsTr("Runtime error"),
|
|
|
|
|
12: qsTr("Password required but not provided"),
|
|
|
|
|
13: qsTr("Block synchronization error"),
|
|
|
|
|
14: qsTr("Serialization error"),
|
|
|
|
|
15: qsTr("Invalid type conversion"),
|
|
|
|
|
16: qsTr("Invalid key value"),
|
|
|
|
|
99: qsTr("Internal error")
|
|
|
|
|
})
|
|
|
|
|
function format(errorMessage) {
|
|
|
|
|
if (!errorMessage || typeof errorMessage !== "string")
|
|
|
|
|
return errorMessage || ""
|
|
|
|
|
var match = errorMessage.match(/wallet FFI error (\d+)/)
|
|
|
|
|
if (match) {
|
|
|
|
|
var code = match[1]
|
|
|
|
|
var msg = codeToMessage[code]
|
|
|
|
|
if (msg)
|
|
|
|
|
return msg
|
|
|
|
|
return qsTr("Wallet error (code %1)").arg(code)
|
|
|
|
|
}
|
|
|
|
|
return errorMessage
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QtObject {
|
|
|
|
|
id: d
|
|
|
|
|
readonly property bool isWalletOpen: backend && backend.isWalletOpen
|
|
|
|
|
onIsWalletOpenChanged: {
|
|
|
|
|
if(isWalletOpen) {
|
|
|
|
|
stackView.push(mainView)
|
|
|
|
|
} else {
|
|
|
|
|
stackView.push(onboardingView)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-20 14:20:39 +01:00
|
|
|
color: Theme.palette.background
|
|
|
|
|
|
2026-02-20 18:10:59 +01:00
|
|
|
StackView {
|
2026-02-23 18:09:06 +01:00
|
|
|
id: stackView
|
2026-02-20 14:20:39 +01:00
|
|
|
anchors.fill: parent
|
|
|
|
|
|
2026-02-20 18:10:59 +01:00
|
|
|
Component {
|
|
|
|
|
id: onboardingView
|
|
|
|
|
OnboardingView {
|
2026-02-23 18:09:06 +01:00
|
|
|
storePath: backend.storagePath
|
|
|
|
|
configPath: backend.configPath
|
2026-02-20 18:10:59 +01:00
|
|
|
onCreateWallet: function(configPath, storagePath, password) {
|
|
|
|
|
if (!backend || !backend.createNew(configPath, storagePath, password))
|
|
|
|
|
createError = qsTr("Failed to create wallet. Check paths and try again.")
|
2026-02-20 14:20:39 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-20 18:10:59 +01:00
|
|
|
Component {
|
|
|
|
|
id: mainView
|
2026-02-22 02:03:13 +05:30
|
|
|
DashboardView {
|
|
|
|
|
id: dashboardView
|
|
|
|
|
accountModel: backend ? backend.accountModel : null
|
|
|
|
|
|
|
|
|
|
onCreatePublicAccountRequested: {
|
|
|
|
|
if (!backend) {
|
|
|
|
|
console.warning("backend is null")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
backend.createAccountPublic()
|
|
|
|
|
}
|
|
|
|
|
onCreatePrivateAccountRequested: {
|
|
|
|
|
if (!backend) {
|
|
|
|
|
console.warning("backend is null")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
backend.createAccountPrivate()
|
|
|
|
|
}
|
|
|
|
|
onFetchBalancesRequested: {
|
|
|
|
|
if (!backend) {
|
|
|
|
|
console.warning("backend is null")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
backend.refreshBalances()
|
|
|
|
|
}
|
|
|
|
|
onTransferRequested: function(isPublic, fromId, toAddress, amount) {
|
|
|
|
|
if (!backend) {
|
|
|
|
|
console.warning("backend is null")
|
|
|
|
|
return
|
|
|
|
|
}
|
2026-02-23 18:09:06 +01:00
|
|
|
var raw = isPublic
|
2026-02-22 02:03:13 +05:30
|
|
|
? backend.transferPublic(fromId, toAddress, amount)
|
|
|
|
|
: backend.transferPrivate(fromId, toAddress, amount)
|
2026-02-23 18:09:06 +01:00
|
|
|
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
|
2026-02-20 14:20:39 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|