diff --git a/src/app_service/service/transaction/service.nim b/src/app_service/service/transaction/service.nim index 7a2bc06648..bf0ee5bdbf 100644 --- a/src/app_service/service/transaction/service.nim +++ b/src/app_service/service/transaction/service.nim @@ -206,6 +206,14 @@ QtObject: error "error: ", errDescription return + proc extractRpcErrorMessage(self: Service, errorMessage: string): string = + var startIndex = errorMessage.find("message:") + if startIndex < 0: + return errorMessage + startIndex += 8 + let endIndex = errorMessage.rfind("]") + return errorMessage[startIndex..endIndex-1] + proc getPendingTransactionsForType*(self: Service, transactionType: PendingTransactionTypeDto): seq[TransactionDto] = let allPendingTransactions = self.getPendingTransactions() return allPendingTransactions.filter(x => x.typeValue == $transactionType) @@ -449,7 +457,7 @@ QtObject: toTokenSymbol, totalAmountToReceive.toString(10), uuid, routes, response) except Exception as e: self.sendTransactionSentSignal(sendType, from_addr, to_addr, tokenSymbol, "", - toTokenSymbol, "", uuid, @[], RpcResponse[JsonNode](), fmt"Error sending token transfer transaction: {e.msg}") + toTokenSymbol, "", uuid, @[], RpcResponse[JsonNode](), self.extractRpcErrorMessage(e.msg)) proc mustIgnoreApprovalRequests(sendType: SendType): bool = # Swap requires approvals to be done in advance in a separate Tx @@ -564,7 +572,7 @@ QtObject: except Exception as e: self.sendTransactionSentSignal(sendType, mtCommand.fromAddress, mtCommand.toAddress, assetKey, "", toAssetKey, "", - uuid, @[], RpcResponse[JsonNode](), fmt"Error sending token transfer transaction: {e.msg}") + uuid, @[], RpcResponse[JsonNode](), self.extractRpcErrorMessage(e.msg)) proc transfer*( self: Service, @@ -619,7 +627,7 @@ QtObject: sendType, tokenName, isOwnerToken, slippagePercentage) except Exception as e: - self.sendTransactionSentSignal(sendType, fromAddr, toAddr, assetKey, "", toAssetKey, "", uuid, @[], RpcResponse[JsonNode](), fmt"Error sending token transfer transaction: {e.msg}") + self.sendTransactionSentSignal(sendType, fromAddr, toAddr, assetKey, "", toAssetKey, "", uuid, @[], RpcResponse[JsonNode](), self.extractRpcErrorMessage(e.msg)) proc proceedWithTransactionsSignatures*(self: Service, fromAddr: string, toAddr: string, fromTokenKey: string, toTokenKey: string, uuid: string, signatures: TransactionsSignatures, diff --git a/storybook/pages/SendModalPage.qml b/storybook/pages/SendModalPage.qml index 6dfdef505a..10b65901fb 100644 --- a/storybook/pages/SendModalPage.qml +++ b/storybook/pages/SendModalPage.qml @@ -211,6 +211,13 @@ SplitView { preSelectedHoldingID: loader.preSelectedHoldingID preSelectedHoldingType: loader.preSelectedHoldingType showCustomRoutingMode: ctrlShowCustomMode.checked + generateUuid: () => { return "12345" } + sendTransaction: () => { + if (!showSendErrorCheckBox.checked) + return + + txStore.walletSectionSendInst.transactionSent(1, "0x123", generateUuid(), "Send error, please ignore") + } } Component.onCompleted: loader.active = true } @@ -353,6 +360,12 @@ SplitView { checked: true } + CheckBox { + id: showSendErrorCheckBox + text: "Show send error" + checked: false + } + CheckBox { id: showCommunityAssetsCheckBox text: "Show community assets when sending tokens" diff --git a/ui/imports/shared/popups/send/SendModal.qml b/ui/imports/shared/popups/send/SendModal.qml index 16851d5612..efd9744fd9 100644 --- a/ui/imports/shared/popups/send/SendModal.qml +++ b/ui/imports/shared/popups/send/SendModal.qml @@ -1,7 +1,6 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 -import QtQuick.Dialogs 1.3 import QtGraphicalEffects 1.0 import SortFilterProxyModel 0.2 @@ -65,13 +64,6 @@ StatusDialog { property int loginType property bool showCustomRoutingMode - property MessageDialog sendingError: MessageDialog { - id: sendingError - title: qsTr("Error sending the transaction") - icon: StandardIcon.Critical - standardButtons: StandardButton.Ok - } - // In case selected address is incorrect take first account from the list readonly property alias selectedAccount: selectedSenderAccountEntry.item @@ -90,6 +82,8 @@ StatusDialog { } }) + property var generateUuid: () => { return Utils.uuid() } + QtObject { id: d @@ -140,7 +134,9 @@ StatusDialog { property string routerError: "" property string routerErrorDetails: "" - readonly property string uuid: Utils.uuid() + property string sendError: "" + + readonly property string uuid: popup.generateUuid() property bool isPendingTx: false property string totalTimeEstimate property double totalFeesInFiat @@ -153,6 +149,7 @@ StatusDialog { readonly property bool isSelectedHoldingValidAsset: !!selectedHolding && selectedHoldingType === Constants.TokenType.ERC20 onSelectedHoldingChanged: { + d.sendError = "" if (!selectedHolding) { return } @@ -315,6 +312,7 @@ StatusDialog { } selectedAddress: popup.preSelectedAccountAddress onCurrentAccountAddressChanged: { + d.sendError = "" store.setSenderAccount(currentAccountAddress) if (d.isSelectedHoldingValidAsset) { @@ -536,7 +534,10 @@ StatusDialog { formatBalance: amount => d.currencyStore.formatCurrencyAmount( amount, selectedSymbol) - onAmountChanged: popup.recalculateRoutesAndFees() + onAmountChanged: { + d.sendError = "" + popup.recalculateRoutesAndFees() + } } // Horizontal spacer @@ -582,7 +583,10 @@ StatusDialog { interactive: popup.interactive selectedAsset: d.selectedHolding onIsLoading: popup.isLoading = true - onRecalculateRoutesAndFees: popup.recalculateRoutesAndFees() + onRecalculateRoutesAndFees: { + d.sendError = "" + popup.recalculateRoutesAndFees() + } onAddressTextChanged: store.setSelectedRecipient(addressText) } } @@ -641,6 +645,11 @@ StatusDialog { visible: recipientInputLoader.ready && (amountToSend.ready || d.isCollectiblesTransfer) + onVisibleChanged: { + if (!visible) + d.sendError = "" + } + objectName: "sendModalScroll" Behavior on implicitHeight { @@ -660,7 +669,10 @@ StatusDialog { minSendCryptoDecimals: amountToSend.minSendCryptoDecimals minReceiveCryptoDecimals: amountToSend.minReceiveCryptoDecimals selectedAsset: d.selectedHolding - onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees() + onReCalculateSuggestedRoute: { + d.sendError = "" + popup.recalculateRoutesAndFees() + } errorType: d.errorType isLoading: popup.isLoading isBridgeTx: d.isBridgeTx @@ -675,6 +687,47 @@ StatusDialog { routerErrorDetails: d.routerErrorDetails } } + + Rectangle { + Layout.fillWidth: true + Layout.topMargin: Style.current.bigPadding + Layout.leftMargin: Style.current.xlPadding + Layout.rightMargin: Style.current.xlPadding + Layout.bottomMargin: Style.current.xlPadding + implicitHeight: sendErrorColumn.height + Style.current.padding + color: Theme.palette.dangerColor3 + radius: 8 + border.width: 1 + border.color: Theme.palette.dangerColor2 + + visible: !!d.sendError + + ColumnLayout { + id: sendErrorColumn + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.leftMargin: Style.current.padding + anchors.rightMargin: Style.current.padding + spacing: Style.current.padding + + StatusBaseText { + Layout.fillWidth: true + Layout.topMargin: Style.current.padding + font.pixelSize: Style.current.secondaryTextFontSize + font.bold: true + wrapMode: Text.WrapAnywhere + text: qsTr("Error sending the transaction") + } + + StatusBaseText { + Layout.fillWidth: true + font.pixelSize: Style.current.tertiaryTextFontSize + wrapMode: Text.WrapAnywhere + text: d.sendError + } + } + } } footer: TransactionModalFooter { @@ -687,7 +740,10 @@ StatusDialog { pending: d.isPendingTx || popup.isLoading visible: recipientInputLoader.ready && (amountToSend.ready || d.isCollectiblesTransfer) && !d.errorMode && !d.routerError - onNextButtonClicked: popup.sendTransaction() + onNextButtonClicked: { + d.sendError = "" + popup.sendTransaction() + } } Connections { @@ -715,10 +771,7 @@ StatusDialog { networkSelector.suggestedToNetworksList = txRoutes.toNetworksRouteModel popup.isLoading = false } - } - Connections { - target: popup.store.walletSectionSendInst function onTransactionSent(chainId: int, txHash: string, uuid: string, error: string) { d.isPendingTx = false if (uuid !== d.uuid) return @@ -726,8 +779,8 @@ StatusDialog { if (error.includes(Constants.walletSection.authenticationCanceled)) { return } - sendingError.text = error - return sendingError.open() + d.sendError = error + return } popup.close() }