From 9e26854ea2137a0fdde448254a126ee924926895 Mon Sep 17 00:00:00 2001 From: Ty Lauriente Date: Mon, 3 Aug 2026 23:16:08 -0700 Subject: [PATCH] wizard: add Trezor Safe 7 support The Trezor Safe 7 speaks the Trezor Host Protocol v2 rather than the legacy v1 wire protocol. With THP implemented in the wallet, the GUI needs three things to drive it. A pairing dialog for the THP CodeEntry step: on the first pairing the device displays a six-digit code and the host has to echo it back. The dialog collects it, accepts the spacing and dashes a paste brings with it, and reports a rejected code in place so the user can try again instead of dead-ending the wizard. The Safe 7 as a selectable model in the create-wallet-from-device wizard, with its own image. Classification of Trezor connect and open failures, so the loading screen can offer a retry hint when the device is merely off, locked or not yet paired, rather than the "check application logs" error that every failure produces today. Cancelling, on the device or in the dialog, now ends the wizard quietly instead of as an error, which is what the second argument to walletCreatedFromDevice carries. C++17 is set unconditionally rather than only for DEV_MODE checkouts, because the monero revision carrying THP requires it. That hunk stands on its own and can be dropped if it would rather go in with the submodule bump. No submodule bump is included here. The matching monero change is a separate pull request, and moving the pointer before that merges would pin the GUI to a personal fork. --- CMakeLists.txt | 7 +- components/DevicePairingCodeDialog.qml | 232 +++++++++++++++++++++++++ components/ProcessingSplash.qml | 103 ++++++++++- images/trezor7.png | Bin 0 -> 97637 bytes main.qml | 175 ++++++++++++++++++- qml.qrc | 2 + src/CMakeLists.txt | 2 + src/libwalletqt/PairingCodeHelper.cpp | 65 +++++++ src/libwalletqt/PairingCodeHelper.h | 79 +++++++++ src/libwalletqt/Wallet.cpp | 18 ++ src/libwalletqt/Wallet.h | 27 ++- src/libwalletqt/WalletListenerImpl.cpp | 13 ++ src/libwalletqt/WalletListenerImpl.h | 8 +- src/libwalletqt/WalletManager.cpp | 41 ++++- src/libwalletqt/WalletManager.h | 9 +- wizard/WizardController.qml | 75 +++++++- wizard/WizardCreateDevice1.qml | 7 +- 17 files changed, 840 insertions(+), 23 deletions(-) create mode 100644 components/DevicePairingCodeDialog.qml create mode 100644 images/trezor7.png create mode 100644 src/libwalletqt/PairingCodeHelper.cpp create mode 100644 src/libwalletqt/PairingCodeHelper.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7507e80c57..185a74a9df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,12 +19,7 @@ option(WITH_UPDATER "Regularly check for new updates" ON) option(DEV_MODE "Checkout latest monero master on build" OFF) cmake_dependent_option(QML_TESTS "Build QML tests" ON "NOT STATIC;NOT ANDROID;NOT IOS" OFF) -if(DEV_MODE) - # DEV_MODE checks out the monero submodule to master, which requires C++17. - set(CMAKE_CXX_STANDARD 17) -else() - set(CMAKE_CXX_STANDARD 14) -endif() +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_SOURCE_DIR}/cmake") diff --git a/components/DevicePairingCodeDialog.qml b/components/DevicePairingCodeDialog.qml new file mode 100644 index 0000000000..0fd77f7c72 --- /dev/null +++ b/components/DevicePairingCodeDialog.qml @@ -0,0 +1,232 @@ +// Copyright (c) 2026, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import QtQuick 2.9 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.1 + +import "../components" as MoneroComponents + +// Modal that prompts the user for the 6-digit pairing code shown on a +// Trezor Safe 7 during the THP CodeEntry pairing flow. +FocusScope { + id: root + visible: false + + // onAcceptedCallback is invoked with the entered code (string of 6 + // ASCII digits). onRejectedCallback is invoked when the user cancels. + // Both are cleared once one of them has fired. + property var onAcceptedCallback + property var onRejectedCallback + + // Message shown above the input, set by the caller when a previous + // code was rejected by the device. + property string errorText + + function open() { + // Same modal behaviour as PasswordDialog: a wallet pool thread + // is blocked waiting for the code, so the UI behind the dialog + // must not accept input (e.g. starting a second wallet open + // would hang forever on the same device). + leftPanel.enabled = false; + middlePanel.enabled = false; + wizard.enabled = false; + titleBar.state = "essentials"; + root.visible = true; + codeInput.text = ""; + codeInput.forceActiveFocus(); + } + + function close() { + leftPanel.enabled = true; + middlePanel.enabled = true; + wizard.enabled = !wizard.deviceWalletCreationInProgress; + if (rootItem.state == "wizard") { + titleBar.state = "essentials"; + } else { + titleBar.state = "default"; + } + root.visible = false; + root.errorText = ""; + } + + function onOk() { + if (codeInput.text.length !== 6) { + return; + } + var entered = codeInput.text; + var callback = root.onAcceptedCallback; + root.onAcceptedCallback = null; + root.onRejectedCallback = null; + root.close(); + if (callback) { + callback(entered); + } + } + + function onCancel() { + if (!root.visible) { + return; + } + var callback = root.onRejectedCallback; + root.onAcceptedCallback = null; + root.onRejectedCallback = null; + root.close(); + if (callback) { + callback(); + } + } + + Keys.enabled: root.visible + Keys.onEscapePressed: root.onCancel() + + ColumnLayout { + id: mainLayout + spacing: 10 + anchors.fill: parent + anchors.margins: 35 + + ColumnLayout { + id: column + + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + Layout.maximumWidth: 480 + + Label { + Layout.fillWidth: true + text: qsTr("Trezor Safe 7 - pair this computer") + translationManager.emptyString + font.pixelSize: 18 + font.family: MoneroComponents.Style.fontBold.name + font.bold: true + color: MoneroComponents.Style.defaultFontColor + } + + Label { + Layout.fillWidth: true + Layout.topMargin: 12 + text: qsTr("Your Trezor is showing a 6-digit code on its screen. " + + "Type that exact code here to confirm this computer is allowed to talk to it. " + + "After this one-time pairing, the computer is remembered and you won't be asked again.") + translationManager.emptyString + font.pixelSize: 14 + font.family: MoneroComponents.Style.fontLight.name + color: MoneroComponents.Style.defaultFontColor + wrapMode: Text.WordWrap + } + + Label { + id: errorTextLabel + visible: text !== "" + text: root.errorText + Layout.fillWidth: true + Layout.topMargin: 12 + font.pixelSize: 14 + font.family: MoneroComponents.Style.fontLight.name + color: MoneroComponents.Style.errorColor + wrapMode: Text.WordWrap + } + + MoneroComponents.Input { + id: codeInput + focus: true + Layout.topMargin: 16 + Layout.fillWidth: true + horizontalAlignment: TextInput.AlignHCenter + verticalAlignment: TextInput.AlignVCenter + font.family: MoneroComponents.Style.fontBold.name + font.pixelSize: 32 + font.letterSpacing: 6 + bottomPadding: 12 + leftPadding: 10 + topPadding: 12 + color: MoneroComponents.Style.defaultFontColor + selectionColor: MoneroComponents.Style.textSelectionColor + selectedTextColor: MoneroComponents.Style.textSelectedColor + inputMethodHints: Qt.ImhDigitsOnly + + // js replacement for `RegExpValidator { regExp: /[0-9]{0,6}/ }`, + // which rejects a paste outright: a code copied as + // "12 34 56" or "123-456" would insert nothing at all. + onTextChanged: { + var digits = codeInput.text.replace(/[^0-9]/g, "").substring(0, 6); + if (digits !== codeInput.text) { + codeInput.text = digits; + codeInput.cursorPosition = digits.length; + } + } + + background: Rectangle { + radius: 2 + border.color: MoneroComponents.Style.inputBorderColorActive + border.width: 1 + color: MoneroComponents.Style.blackTheme ? "black" : "#A9FFFFFF" + } + + Keys.enabled: root.visible + Keys.onEnterPressed: root.onOk() + Keys.onReturnPressed: root.onOk() + Keys.onEscapePressed: root.onCancel() + } + + Label { + Layout.fillWidth: true + Layout.topMargin: 8 + text: qsTr("Tip: nobody, not even a fake Trezor, can guess this code. " + + "If you mistype it, pairing starts over and the device shows a fresh code.") + translationManager.emptyString + font.pixelSize: 12 + font.italic: true + font.family: MoneroComponents.Style.fontLight.name + color: MoneroComponents.Style.dimmedFontColor + wrapMode: Text.WordWrap + } + + RowLayout { + spacing: 16 + Layout.topMargin: 16 + Layout.alignment: Qt.AlignRight + + MoneroComponents.StandardButton { + primary: false + small: true + width: 120 + fontSize: 14 + text: qsTr("Cancel") + translationManager.emptyString + onClicked: root.onCancel() + } + MoneroComponents.StandardButton { + small: true + width: 120 + fontSize: 14 + text: qsTr("Confirm") + translationManager.emptyString + enabled: codeInput.text.length === 6 + onClicked: root.onOk() + } + } + } + } +} diff --git a/components/ProcessingSplash.qml b/components/ProcessingSplash.qml index 469cc1fad8..ada8738411 100644 --- a/components/ProcessingSplash.qml +++ b/components/ProcessingSplash.qml @@ -43,23 +43,74 @@ Rectangle { border.width: 1 z: 11 property alias messageText: messageTitle.text + property alias subMessageText: messageSub.text + + // Optional Retry / Cancel row, shown instead of leaving the user + // stuck on a splash they can't dismiss. To use it, set + // retryCallback and cancelCallback, set showActionButtons, then + // call show(). Leaving retryCallback null hides Retry. + property bool showActionButtons: false + property var retryCallback: null + property var cancelCallback: null width: 100 height: 50 + focus: visible && showActionButtons + Keys.onPressed: { + if (!root.showActionButtons) return; + if (event.key === Qt.Key_Escape) { + root.fireCancel(); + event.accepted = true; + } else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { + if (cancelButton.activeFocus || !retryButton.visible) { + root.fireCancel(); + } else { + root.fireRetry(); + } + event.accepted = true; + } + } + function show() { root.visible = true; + if (root.showActionButtons) { + if (retryButton.visible) { + retryButton.forceActiveFocus(); + } else { + cancelButton.forceActiveFocus(); + } + } } function close() { root.visible = false; + root.showActionButtons = false; + root.retryCallback = null; + root.cancelCallback = null; + } + + function fireRetry() { + var cb = root.retryCallback; + root.close(); + if (cb) cb(); + } + + function fireCancel() { + var cb = root.cancelCallback; + root.close(); + if (cb) cb(); } ColumnLayout { id: rootLayout - anchors.centerIn: parent - + // Anchor to the splash sides so a wrapping sub-message stays + // inside the box; anchors.centerIn leaves the layout width + // unconstrained and long messages spill outside. + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter anchors.leftMargin: 30 anchors.rightMargin: 30 @@ -79,7 +130,9 @@ Rectangle { } BusyIndicator { - running: parent.visible + // Nothing is in progress while the action row waits for + // the user, so the spinner stops. + running: parent.visible && !root.showActionButtons anchors.centerIn: imgLogo style: BusyIndicatorStyle { indicator: Image { @@ -108,5 +161,49 @@ Rectangle { themeTransition: false color: MoneroComponents.Style.defaultFontColor } + + MoneroComponents.TextPlain { + id: messageSub + text: "" + visible: text.length > 0 + font.pixelSize: 15 + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter + Layout.fillWidth: true + Layout.leftMargin: 10 + Layout.rightMargin: 10 + themeTransition: false + color: MoneroComponents.Style.dimmedFontColor + } + + RowLayout { + id: actionRow + visible: root.showActionButtons + spacing: 16 + Layout.alignment: Qt.AlignHCenter + Layout.topMargin: 4 + + MoneroComponents.StandardButton { + id: cancelButton + primary: !retryButton.visible + small: false + text: qsTr("Cancel") + translationManager.emptyString + onClicked: root.fireCancel() + KeyNavigation.tab: retryButton.visible ? retryButton : cancelButton + KeyNavigation.backtab: retryButton.visible ? retryButton : cancelButton + } + + MoneroComponents.StandardButton { + id: retryButton + visible: root.retryCallback !== null + primary: true + small: false + text: qsTr("Try again") + translationManager.emptyString + onClicked: root.fireRetry() + KeyNavigation.tab: cancelButton + KeyNavigation.backtab: cancelButton + } + } } } diff --git a/images/trezor7.png b/images/trezor7.png new file mode 100644 index 0000000000000000000000000000000000000000..e5cdbcff65b6b2aa36cf964ca8b1d3fdebafec4a GIT binary patch literal 97637 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 wallet pairing code needed: "); + devicePairingCodeDialog.onAcceptedCallback = function(code) { + handler.onPairingCodeEntered(code, false); + appWindow.onWalletOpening(); + } + devicePairingCodeDialog.onRejectedCallback = function() { + handler.onPairingCodeEntered("", true); + appWindow.onWalletOpening(); + } + devicePairingCodeDialog.open(); + } + function onWalletUpdate(stoppedBackgroundSync) { if (!currentWallet) return; @@ -1026,6 +1134,11 @@ ApplicationWindow { transaction.setFilename(path); } appWindow.showProcessingSplash(qsTr("Sending transaction ...")); + // Signing on a hardware wallet takes one tap per input, which can + // run to tens of seconds with no other sign of progress. + if (currentWallet && currentWallet.isHwBacked()) { + splash.subMessageText = qsTr("Confirm each transaction step on your hardware wallet. Each input requires a tap on the device.") + translationManager.emptyString; + } currentWallet.commitTransactionAsync(transaction); } @@ -1165,8 +1278,15 @@ ApplicationWindow { function showProcessingSplash(message) { console.log("Displaying processing splash") + // Drop any stale Retry/Cancel state so a regular splash never + // renders the action row of a previous error. + splash.showActionButtons = false; + splash.retryCallback = null; + splash.cancelCallback = null; if (typeof message != 'undefined') { splash.messageText = message + // Callers that want a subtitle assign it after this call. + splash.subMessageText = "" } leftPanel.enabled = false; @@ -1177,6 +1297,7 @@ ApplicationWindow { function hideProcessingSplash() { console.log("Hiding processing splash") + splash.subMessageText = ""; splash.close(); if (!passwordDialog.visible) { @@ -1186,6 +1307,32 @@ ApplicationWindow { } } + // Surface a retry-recoverable failure on the splash with a Retry / + // Cancel button row instead of bouncing the user back to the + // password dialog, so retrying after reconnecting the device does + // not require re-typing the wallet password. + // + // The splash is modal, so cancelling has to put the panels back. + // That happens here rather than in each caller's cancel callback: + // a caller that forgot would leave the app permanently disabled. + function showRetryableTrezorErrorSplash(title, subMessage, retryCallback, cancelCallback) { + splash.messageText = title; + splash.subMessageText = subMessage; + splash.retryCallback = retryCallback; + splash.cancelCallback = function() { + hideProcessingSplash(); + if (cancelCallback) { + cancelCallback(); + } + }; + splash.showActionButtons = true; + + leftPanel.enabled = false; + middlePanel.enabled = false; + titleBar.enabled = false; + splash.show(); + } + // close wallet and show wizard function showWizard(){ walletInitialized = false; @@ -1391,6 +1538,7 @@ ApplicationWindow { walletManager.deviceButtonPressed.connect(onDeviceButtonPressed); walletManager.checkUpdatesComplete.connect(onWalletCheckUpdatesComplete); walletManager.walletPassphraseNeeded.connect(onWalletPassphraseNeededManager); + walletManager.walletPairingCodeNeeded.connect(onWalletPairingCodeNeededManager); IPC.uriHandler.connect(onUriHandler); if(typeof daemonManager != "undefined") { @@ -1803,6 +1951,13 @@ ApplicationWindow { anchors.fill: parent } + DevicePairingCodeDialog { + id: devicePairingCodeDialog + visible: false + z: parent.z + 1 + anchors.fill: parent + } + InputDialog { id: inputDialog visible: false @@ -1832,7 +1987,10 @@ ApplicationWindow { ProcessingSplash { id: splash width: appWindow.width / 2 - height: appWindow.height / 2.66 + // The Retry/Cancel row needs more room than a plain splash. + height: showActionButtons + ? appWindow.height / 1.9 + : appWindow.height / 2.66 x: (appWindow.width - width) / 2 y: (appWindow.height - height) / 2 messageText: qsTr("Please wait...") + translationManager.emptyString @@ -1947,7 +2105,7 @@ ApplicationWindow { source: blurredArea radius: 64 visible: passwordDialog.visible || inputDialog.visible || splash.visible || updateDialog.visible || - devicePassphraseDialog.visible || txConfirmationPopup.visible || successfulTxPopup.visible || + devicePassphraseDialog.visible || devicePairingCodeDialog.visible || txConfirmationPopup.visible || successfulTxPopup.visible || remoteNodeDialog.visible } @@ -2155,10 +2313,13 @@ ApplicationWindow { visible: false property alias text: statusMessageText.text anchors.bottom: parent.bottom - width: statusMessageText.contentWidth + 20 + // Cap the width so a long message wraps inside the toast instead + // of spilling off the right edge, and grow the height to match. + width: Math.min(statusMessageText.implicitWidth + 20, + Math.max(appWindow.width - 80, 320)) + height: statusMessageText.paintedHeight + 20 anchors.horizontalCenter: parent.horizontalCenter color: MoneroComponents.Style.blackTheme ? "black" : "white" - height: 40 MoneroComponents.TextPlain { id: statusMessageText anchors.fill: parent @@ -2166,6 +2327,8 @@ ApplicationWindow { font.pixelSize: 14 color: MoneroComponents.Style.defaultFontColor themeTransition: false + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignHCenter } } @@ -2218,6 +2381,10 @@ ApplicationWindow { } + // An unanswered pairing prompt holds a wallet pool thread, which + // would then never finish. Cancel it so the thread unwinds. + devicePairingCodeDialog.onCancel(); + // If daemon is running - prompt user before exiting if(daemonManager == undefined || persistentSettings.useRemoteNode) { closeAccepted(); diff --git a/qml.qrc b/qml.qrc index 9223423dc8..599ab41029 100644 --- a/qml.qrc +++ b/qml.qrc @@ -111,6 +111,7 @@ components/ProgressBar.qml components/StandardDialog.qml components/DevicePassphraseDialog.qml + components/DevicePairingCodeDialog.qml pages/Sign.qml components/DaemonManagerDialog.qml version.js @@ -286,6 +287,7 @@ images/ledgerFlex.png images/trezor3.png images/trezor5.png + images/trezor7.png images/trezorT.png images/trezorT@2x.png qtquickcontrols2.conf diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bcbda89cfe..9942b02782 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,6 +14,7 @@ file(GLOB SOURCE_FILES "libwalletqt/WalletListenerImpl.cpp" "libwalletqt/Wallet.cpp" "libwalletqt/PassphraseHelper.cpp" + "libwalletqt/PairingCodeHelper.cpp" "libwalletqt/PendingTransaction.cpp" "libwalletqt/TransactionHistory.cpp" "libwalletqt/TransactionInfo.cpp" @@ -25,6 +26,7 @@ file(GLOB SOURCE_FILES "libwalletqt/WalletManager.h" "libwalletqt/Wallet.h" "libwalletqt/PassphraseHelper.h" + "libwalletqt/PairingCodeHelper.h" "libwalletqt/PendingTransaction.h" "libwalletqt/TransactionHistory.h" "libwalletqt/TransactionInfo.h" diff --git a/src/libwalletqt/PairingCodeHelper.cpp b/src/libwalletqt/PairingCodeHelper.cpp new file mode 100644 index 0000000000..a6dfa3edad --- /dev/null +++ b/src/libwalletqt/PairingCodeHelper.cpp @@ -0,0 +1,65 @@ +// Copyright (c) 2026, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "PairingCodeHelper.h" +#include +#include + +Monero::optional PairingCodeHelper::onDevicePairingCodeRequest() +{ + qDebug() << __FUNCTION__; + QMutexLocker locker(&m_mutex); + m_abort = false; + m_answered = false; + m_code.clear(); + + if (m_prompter != nullptr) { + m_prompter->onWalletPairingCodeNeeded(); + } + + while (!m_answered) { + m_cond.wait(&m_mutex); + } + + if (m_abort) { + return Monero::optional(std::string{}); + } + auto result = m_code.toStdString(); + m_code.clear(); + return Monero::optional(result); +} + +void PairingCodeHelper::onPairingCodeEntered(const QString &code, bool entry_abort) +{ + qDebug() << __FUNCTION__; + QMutexLocker locker(&m_mutex); + m_code = code; + m_abort = entry_abort; + m_answered = true; + m_cond.wakeAll(); +} diff --git a/src/libwalletqt/PairingCodeHelper.h b/src/libwalletqt/PairingCodeHelper.h new file mode 100644 index 0000000000..d9aca2f70d --- /dev/null +++ b/src/libwalletqt/PairingCodeHelper.h @@ -0,0 +1,79 @@ +// Copyright (c) 2026, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef MONERO_GUI_PAIRINGCODEHELPER_H +#define MONERO_GUI_PAIRINGCODEHELPER_H + +#include +#include +#include +#include +#include + +/** + * THP CodeEntry pairing code helper. The wallet's worker thread blocks + * inside onDevicePairingCodeRequest waiting for the user to type the + * 6-digit code shown on the Trezor. The QML side displays a modal, + * collects the code, and calls onPairingCodeEntered to wake the worker. + * + * Mirrors the existing PassphraseHelper pattern. + */ +class PairingCodePrompter { +public: + virtual void onWalletPairingCodeNeeded() = 0; + virtual ~PairingCodePrompter() = default; +}; + +class PairingCodeReceiver { +public: + virtual void onPairingCodeEntered(const QString &code, bool entry_abort) = 0; + virtual ~PairingCodeReceiver() = default; +}; + +class PairingCodeHelper { +public: + PairingCodeHelper(PairingCodePrompter *prompter = nullptr): m_prompter(prompter) {} + PairingCodeHelper(const PairingCodeHelper &h): PairingCodeHelper(h.m_prompter) {} + + // Blocks until onPairingCodeEntered is called. Returns the code as + // a UTF-8 string (ASCII digits in practice). Returns an empty + // string on user cancel. + Monero::optional onDevicePairingCodeRequest(); + + void onPairingCodeEntered(const QString &code, bool entry_abort); + +private: + PairingCodePrompter *m_prompter; + QWaitCondition m_cond; + QMutex m_mutex; + QString m_code; + bool m_abort = false; + bool m_answered = false; +}; + +#endif // MONERO_GUI_PAIRINGCODEHELPER_H diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp index 64f968707b..9fbab619c3 100644 --- a/src/libwalletqt/Wallet.cpp +++ b/src/libwalletqt/Wallet.cpp @@ -92,6 +92,11 @@ Wallet::Status Wallet::status() const return static_cast(m_walletImpl->status()); } +Wallet::TrezorError Wallet::trezorError() const +{ + return static_cast(m_walletImpl->trezorError()); +} + NetworkType::Type Wallet::nettype() const { return static_cast(m_walletImpl->nettype()); @@ -1173,6 +1178,19 @@ void Wallet::onPassphraseEntered(const QString &passphrase, bool enter_on_device } } +void Wallet::onWalletPairingCodeNeeded() +{ + emit this->walletPairingCodeNeeded(); +} + +void Wallet::onPairingCodeEntered(const QString &code, bool entry_abort) +{ + if (m_walletListener != nullptr) + { + m_walletListener->onPairingCodeEntered(code, entry_abort); + } +} + Wallet::Wallet(Monero::Wallet *w, QObject *parent) : QObject(parent) , m_walletImpl(w) diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h index 1cac75a505..14b1ee9d97 100644 --- a/src/libwalletqt/Wallet.h +++ b/src/libwalletqt/Wallet.h @@ -43,6 +43,7 @@ #include "PendingTransaction.h" // we need to have an access to the PendingTransaction::Priority enum here; #include "UnsignedTransaction.h" #include "NetworkType.h" +#include "PairingCodeHelper.h" #include "PassphraseHelper.h" #include "WalletListenerImpl.h" @@ -61,7 +62,7 @@ class SubaddressModel; class SubaddressAccount; class SubaddressAccountModel; -class Wallet : public QObject, public PassprasePrompter +class Wallet : public QObject, public PassprasePrompter, public PairingCodePrompter { Q_OBJECT Q_PROPERTY(bool disconnected READ disconnected NOTIFY disconnectedChanged) @@ -69,6 +70,7 @@ class Wallet : public QObject, public PassprasePrompter Q_PROPERTY(QString seed READ getSeed) Q_PROPERTY(QString seedLanguage READ getSeedLanguage) Q_PROPERTY(Status status READ status) + Q_PROPERTY(TrezorError trezorError READ trezorError) Q_PROPERTY(NetworkType::Type nettype READ nettype) // Q_PROPERTY(ConnectionStatus connected READ connected) Q_PROPERTY(quint32 currentSubaddressAccount READ currentSubaddressAccount NOTIFY currentSubaddressAccountChanged) @@ -120,6 +122,21 @@ class Wallet : public QObject, public PassprasePrompter Q_ENUM(BackgroundSyncType) + //! Category of the Trezor failure behind the last open or create, so + //! QML can offer the recovery that fits without matching the English + //! text of an error. + enum TrezorError { + TrezorError_None = Monero::Wallet::TrezorError_None, + TrezorError_Unreachable = Monero::Wallet::TrezorError_Unreachable, + TrezorError_Cancelled = Monero::Wallet::TrezorError_Cancelled, + TrezorError_Protocol = Monero::Wallet::TrezorError_Protocol, + TrezorError_Other = Monero::Wallet::TrezorError_Other, + TrezorError_FirmwareUnsupported = Monero::Wallet::TrezorError_FirmwareUnsupported, + TrezorError_PairingRejected = Monero::Wallet::TrezorError_PairingRejected + }; + + Q_ENUM(TrezorError) + //! returns mnemonic seed QString getSeed() const; @@ -132,6 +149,9 @@ class Wallet : public QObject, public PassprasePrompter //! returns last operation's status Status status() const; + //! returns the category of the Trezor failure behind the last status + TrezorError trezorError() const; + //! returns network type of the wallet. NetworkType::Type nettype() const; @@ -374,6 +394,10 @@ class Wallet : public QObject, public PassprasePrompter Q_INVOKABLE void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort=false); virtual void onWalletPassphraseNeeded(bool on_device) override; + // THP CodeEntry pairing code entry for Trezor Safe 7 + Q_INVOKABLE void onPairingCodeEntered(const QString &code, bool entry_abort=false); + virtual void onWalletPairingCodeNeeded() override; + // TODO: setListenter() when it implemented in API signals: // emitted on every event happened with wallet @@ -397,6 +421,7 @@ class Wallet : public QObject, public PassprasePrompter void deviceButtonRequest(quint64 buttonCode); void deviceButtonPressed(); void walletPassphraseNeeded(bool onDevice); + void walletPairingCodeNeeded(); void transactionCommitted(bool status, PendingTransaction *t, const QStringList& txid); void heightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight) const; void deviceShowAddressShowed(); diff --git a/src/libwalletqt/WalletListenerImpl.cpp b/src/libwalletqt/WalletListenerImpl.cpp index d2ccc24442..db1dd96162 100644 --- a/src/libwalletqt/WalletListenerImpl.cpp +++ b/src/libwalletqt/WalletListenerImpl.cpp @@ -32,6 +32,7 @@ WalletListenerImpl::WalletListenerImpl(Wallet * w) : m_wallet(w) , m_phelper(w) + , m_pchelper(w) { } @@ -95,3 +96,15 @@ Monero::optional WalletListenerImpl::onDevicePassphraseRequest(bool qDebug() << __FUNCTION__; return m_phelper.onDevicePassphraseRequest(on_device); } + +Monero::optional WalletListenerImpl::onDevicePairingCodeRequest() +{ + qDebug() << __FUNCTION__; + return m_pchelper.onDevicePairingCodeRequest(); +} + +void WalletListenerImpl::onPairingCodeEntered(const QString &code, bool entry_abort) +{ + qDebug() << __FUNCTION__; + m_pchelper.onPairingCodeEntered(code, entry_abort); +} diff --git a/src/libwalletqt/WalletListenerImpl.h b/src/libwalletqt/WalletListenerImpl.h index 46f38fdf32..b6720b787e 100644 --- a/src/libwalletqt/WalletListenerImpl.h +++ b/src/libwalletqt/WalletListenerImpl.h @@ -30,11 +30,12 @@ #define MONERO_GUI_WALLETLISTENERIMPL_H #include "wallet/api/wallet2_api.h" +#include "PairingCodeHelper.h" #include "PassphraseHelper.h" class Wallet; -class WalletListenerImpl : public Monero::WalletListener, public PassphraseReceiver +class WalletListenerImpl : public Monero::WalletListener, public PassphraseReceiver, public PairingCodeReceiver { public: WalletListenerImpl(Wallet * w); @@ -60,9 +61,14 @@ class WalletListenerImpl : public Monero::WalletListener, public PassphraseRecei virtual Monero::optional onDevicePassphraseRequest(bool & on_device) override; + virtual Monero::optional onDevicePairingCodeRequest() override; + + virtual void onPairingCodeEntered(const QString &code, bool entry_abort) override; + private: Wallet * m_wallet; PassphraseHelper m_phelper; + PairingCodeHelper m_pchelper; }; #endif //MONERO_GUI_WALLETLISTENERIMPL_H diff --git a/src/libwalletqt/WalletManager.cpp b/src/libwalletqt/WalletManager.cpp index 73046afa1f..8699f2bc30 100644 --- a/src/libwalletqt/WalletManager.cpp +++ b/src/libwalletqt/WalletManager.cpp @@ -46,10 +46,10 @@ #include "qt/updater.h" #include "qt/ScopeGuard.h" -class WalletPassphraseListenerImpl : public Monero::WalletListener, public PassphraseReceiver +class WalletPassphraseListenerImpl : public Monero::WalletListener, public PassphraseReceiver, public PairingCodeReceiver { public: - WalletPassphraseListenerImpl(WalletManager * mgr): m_mgr(mgr), m_phelper(mgr) {} + WalletPassphraseListenerImpl(WalletManager * mgr): m_mgr(mgr), m_phelper(mgr), m_pchelper(mgr) {} virtual void moneySpent(const std::string &txId, uint64_t amount) override { (void)txId; (void)amount; }; virtual void moneyReceived(const std::string &txId, uint64_t amount) override { (void)txId; (void)amount; }; @@ -70,6 +70,18 @@ class WalletPassphraseListenerImpl : public Monero::WalletListener, public Pass return m_phelper.onDevicePassphraseRequest(on_device); } + virtual void onPairingCodeEntered(const QString &code, bool entry_abort) override + { + qDebug() << __FUNCTION__; + m_pchelper.onPairingCodeEntered(code, entry_abort); + } + + virtual Monero::optional onDevicePairingCodeRequest() override + { + qDebug() << __FUNCTION__; + return m_pchelper.onDevicePairingCodeRequest(); + } + virtual void onDeviceButtonRequest(uint64_t code) override { qDebug() << __FUNCTION__; @@ -85,6 +97,7 @@ class WalletPassphraseListenerImpl : public Monero::WalletListener, public Pass private: WalletManager * m_mgr; PassphraseHelper m_phelper; + PairingCodeHelper m_pchelper; }; Wallet *WalletManager::createWallet(const QString &path, const QString &password, @@ -108,9 +121,14 @@ Wallet *WalletManager::openWallet(const QString &path, const QString &password, m_mutex_passphraseReceiver.lock(); m_passphraseReceiver = &tmpListener; m_mutex_passphraseReceiver.unlock(); + m_mutex_pairingCodeReceiver.lock(); + m_pairingCodeReceiver = &tmpListener; + m_mutex_pairingCodeReceiver.unlock(); const auto cleanup = sg::make_scope_guard([this]() noexcept { QMutexLocker passphrase_locker(&m_mutex_passphraseReceiver); this->m_passphraseReceiver = nullptr; + QMutexLocker pairing_locker(&m_mutex_pairingCodeReceiver); + this->m_pairingCodeReceiver = nullptr; }); if (m_currentWallet) { @@ -178,9 +196,14 @@ Wallet *WalletManager::createWalletFromDevice(const QString &path, const QString m_mutex_passphraseReceiver.lock(); m_passphraseReceiver = &tmpListener; m_mutex_passphraseReceiver.unlock(); + m_mutex_pairingCodeReceiver.lock(); + m_pairingCodeReceiver = &tmpListener; + m_mutex_pairingCodeReceiver.unlock(); const auto cleanup = sg::make_scope_guard([this]() noexcept { QMutexLocker passphrase_locker(&m_mutex_passphraseReceiver); this->m_passphraseReceiver = nullptr; + QMutexLocker pairing_locker(&m_mutex_pairingCodeReceiver); + this->m_pairingCodeReceiver = nullptr; }); if (m_currentWallet) { @@ -589,6 +612,20 @@ void WalletManager::onPassphraseEntered(const QString &passphrase, bool enter_on } } +void WalletManager::onWalletPairingCodeNeeded() +{ + emit this->walletPairingCodeNeeded(); +} + +void WalletManager::onPairingCodeEntered(const QString &code, bool entry_abort) +{ + QMutexLocker locker(&m_mutex_pairingCodeReceiver); + if (m_pairingCodeReceiver != nullptr) + { + m_pairingCodeReceiver->onPairingCodeEntered(code, entry_abort); + } +} + QString WalletManager::proxyAddress() const { QMutexLocker locker(&m_proxyMutex); diff --git a/src/libwalletqt/WalletManager.h b/src/libwalletqt/WalletManager.h index 649a9f9289..3b4362f592 100644 --- a/src/libwalletqt/WalletManager.h +++ b/src/libwalletqt/WalletManager.h @@ -38,6 +38,7 @@ #include #include "qt/FutureScheduler.h" #include "NetworkType.h" +#include "PairingCodeHelper.h" #include "PassphraseHelper.h" class Wallet; @@ -45,7 +46,7 @@ namespace Monero { struct WalletManager; } -class WalletManager : public QObject, public PassprasePrompter +class WalletManager : public QObject, public PassprasePrompter, public PairingCodePrompter { Q_OBJECT Q_PROPERTY(bool connected READ connected) @@ -195,6 +196,9 @@ class WalletManager : public QObject, public PassprasePrompter Q_INVOKABLE void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort=false); virtual void onWalletPassphraseNeeded(bool on_device) override; + Q_INVOKABLE void onPairingCodeEntered(const QString &code, bool entry_abort=false); + virtual void onWalletPairingCodeNeeded() override; + QString proxyAddress() const; void setProxyAddress(QString address); @@ -203,6 +207,7 @@ class WalletManager : public QObject, public PassprasePrompter void walletOpened(Wallet * wallet); void walletCreated(Wallet * wallet); void walletPassphraseNeeded(bool onDevice); + void walletPairingCodeNeeded(); void deviceButtonRequest(quint64 buttonCode); void deviceButtonPressed(); void checkUpdatesComplete( @@ -226,6 +231,8 @@ public slots: QPointer m_currentWallet; PassphraseReceiver * m_passphraseReceiver; QMutex m_mutex_passphraseReceiver; + PairingCodeReceiver * m_pairingCodeReceiver = nullptr; + QMutex m_mutex_pairingCodeReceiver; QString m_proxyAddress; mutable QMutex m_proxyMutex; FutureScheduler m_scheduler; diff --git a/wizard/WizardController.qml b/wizard/WizardController.qml index 6e722d893c..d3af259927 100644 --- a/wizard/WizardController.qml +++ b/wizard/WizardController.qml @@ -35,6 +35,7 @@ import QtQuick.Controls.Styles 1.4 import QtQuick.Layouts 1.2 import QtQuick.Dialogs 1.2 import moneroComponents.Wallet 1.0 +import moneroComponents.WalletManager 1.0 import "../js/Wizard.js" as Wizard import "../js/Windows.js" as Windows @@ -48,7 +49,7 @@ Rectangle { anchors.fill: parent signal useMoneroClicked() - signal walletCreatedFromDevice(bool success) + signal walletCreatedFromDevice(bool success, bool cancelled) function restart(generatingNewSeed) { // Clear up any state, including `m_wallet`, which @@ -425,6 +426,7 @@ Rectangle { function disconnect(){ walletManager.walletCreated.disconnect(onWalletCreated); walletManager.walletPassphraseNeeded.disconnect(onWalletPassphraseNeeded); + walletManager.walletPairingCodeNeeded.disconnect(onWalletPairingCodeNeeded); walletManager.deviceButtonRequest.disconnect(onDeviceButtonRequest); walletManager.deviceButtonPressed.disconnect(onDeviceButtonPressed); } @@ -432,6 +434,7 @@ Rectangle { function connect(){ walletManager.walletCreated.connect(onWalletCreated); walletManager.walletPassphraseNeeded.connect(onWalletPassphraseNeeded); + walletManager.walletPairingCodeNeeded.connect(onWalletPairingCodeNeeded); walletManager.deviceButtonRequest.connect(onDeviceButtonRequest); walletManager.deviceButtonPressed.connect(onDeviceButtonPressed); } @@ -456,6 +459,9 @@ Rectangle { var kdfRounds = persistentSettings.kdfRounds; var restoreHeight = wizardController.walletOptionsRestoreHeight; var subaddressLookahead = wizardController.walletOptionsSubaddressLookahead; + // Device descriptor. The segment before the first ':' selects the + // device class, always "Trezor" here; an empty transport path + // matches every USB transport and the first one wins. var deviceName = wizardController.walletOptionsDeviceName; connect(); @@ -470,6 +476,7 @@ Rectangle { wizardController.enabled = true; splash.close() + var cancelled = false; var success = wallet.status === Wallet.Status_Ok; if (success) { wizardController.m_wallet = wallet; @@ -479,13 +486,59 @@ Rectangle { wizardController.walletOptionsRestoreHeight = wizardController.m_wallet.walletCreationHeight; } } else { + // The wallet-create path hits the same Trezor error + // categories as wallet-open. The raw errorString is worth + // logging but is wallet2-internal phrasing that does not + // tell the user what to do. console.log(wallet.errorString) - appWindow.showStatusMessage(qsTr(wallet.errorString), 5); + var es = wallet.errorString || ""; + var trezorError = wallet.trezorError; + if (trezorError === Wallet.TrezorError_Unreachable) { + // Retry re-fires createWalletFromDevice with the same + // wizard options; they all persist on wizardController. + walletManager.closeWallet(); + // Unwire the handlers first, otherwise the retry path's + // connect() double-binds onWalletCreated. + disconnect(); + appWindow.showRetryableTrezorErrorSplash( + qsTr("Couldn't reach your Trezor") + + translationManager.emptyString, + qsTr("Make sure your Trezor is connected and unlocked, then try again.") + + translationManager.emptyString, + function() { wizardController.createWalletFromDevice(); }, + function() { walletCreatedFromDevice(false, true); }); + return; + } else if (trezorError === Wallet.TrezorError_PairingRejected) { + // The device rejected the pairing code the user just + // typed. Starting over makes it show a fresh code, and + // the pairing dialog re-prompts carrying the message. + walletManager.closeWallet(); + disconnect(); + devicePairingCodeDialog.errorText = + qsTr("That code did not match. Check the code on your device and try again.") + + translationManager.emptyString; + wizardController.createWalletFromDevice(); + return; + } else if (trezorError === Wallet.TrezorError_Cancelled) { + appWindow.showStatusMessage( + qsTr("Wallet creation cancelled.") + translationManager.emptyString, + 5); + cancelled = true; + } else if (trezorError === Wallet.TrezorError_FirmwareUnsupported) { + // Nothing to retry: the device needs different firmware + // before it can hold a Monero wallet. + appWindow.showStatusMessage( + qsTr("This Trezor runs firmware that has no Monero support, such as the bitcoin-only build. Install the standard firmware with Trezor Suite, then try again.") + + translationManager.emptyString, + 10); + } else { + appWindow.showStatusMessage(qsTr(wallet.errorString), 5); + } walletManager.closeWallet(); } disconnect(); - walletCreatedFromDevice(success); + walletCreatedFromDevice(success, cancelled); } function onWalletPassphraseNeeded(on_device){ @@ -508,6 +561,22 @@ Rectangle { devicePassphraseDialog.open(on_device) } + function onWalletPairingCodeNeeded(){ + splash.close() + + console.log(">>> wallet pairing code needed: "); + devicePairingCodeDialog.onAcceptedCallback = function(code) { + walletManager.onPairingCodeEntered(code, false); + creatingWalletDeviceSplash(); + } + devicePairingCodeDialog.onRejectedCallback = function() { + walletManager.onPairingCodeEntered("", true); + creatingWalletDeviceSplash(); + } + + devicePairingCodeDialog.open() + } + function onDeviceButtonRequest(code){ deviceAttentionSplash(); } diff --git a/wizard/WizardCreateDevice1.qml b/wizard/WizardCreateDevice1.qml index 268091c3e2..3a70382f80 100644 --- a/wizard/WizardCreateDevice1.qml +++ b/wizard/WizardCreateDevice1.qml @@ -61,6 +61,7 @@ Rectangle { ListElement { column1: "Trezor Model T"; column2: "Trezor";} ListElement { column1: "Trezor Safe 3"; column2: "Trezor";} ListElement { column1: "Trezor Safe 5"; column2: "Trezor";} + ListElement { column1: "Trezor Safe 7"; column2: "Trezor";} } ColumnLayout { @@ -174,6 +175,8 @@ Rectangle { return "qrc:///images/trezor3.png"; } else if (trezorType == "Trezor Safe 5") { return "qrc:///images/trezor5.png"; + } else if (trezorType == "Trezor Safe 7") { + return "qrc:///images/trezor7.png"; } } else if (hardwareWalletType == "Ledger") { if (ledgerType == "Ledger Nano S") { @@ -297,11 +300,11 @@ Rectangle { } } - function onCreateWalletFromDeviceCompleted(written){ + function onCreateWalletFromDeviceCompleted(written, cancelled){ hideProcessingSplash(); if(written){ wizardStateView.state = "wizardCreateWallet3"; - } else { + } else if(!cancelled){ errorMsg.text = qsTr("Error writing wallet from hardware device. Check application logs.") + translationManager.emptyString; } wizardController.walletCreatedFromDevice.disconnect(onCreateWalletFromDeviceCompleted);