feat: reuse signtxModal and show success and failure
This commit is contained in:
parent
56d6ece3e9
commit
0c1156b33c
|
@ -122,12 +122,19 @@ QtObject:
|
||||||
# TODO make this async
|
# TODO make this async
|
||||||
let response = status.wallet.sendTransaction(fromAddress, to, value, selectedGasLimit, selectedGasPrice, password, success)
|
let response = status.wallet.sendTransaction(fromAddress, to, value, selectedGasLimit, selectedGasPrice, password, success)
|
||||||
debug "Response", response, success
|
debug "Response", response, success
|
||||||
|
let errorMessage = if not success:
|
||||||
|
if response == "":
|
||||||
|
"web3-response-error"
|
||||||
|
else:
|
||||||
|
response
|
||||||
|
else:
|
||||||
|
""
|
||||||
|
|
||||||
return $ %* {
|
return $ %* {
|
||||||
"type": ResponseTypes.Web3SendAsyncCallback,
|
"type": ResponseTypes.Web3SendAsyncCallback,
|
||||||
"messageId": data.messageId,
|
"messageId": data.messageId,
|
||||||
# TODO do we get an error code?
|
"error": errorMessage,
|
||||||
"error": (if response == "" or not success: newJString("web3-response-error") else: newJNull()),
|
"result": if (success): response else: ""
|
||||||
"result": response
|
|
||||||
}
|
}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error "Error sending the transaction", msg = e.msg
|
error "Error sending the transaction", msg = e.msg
|
||||||
|
@ -135,7 +142,6 @@ QtObject:
|
||||||
"type": ResponseTypes.Web3SendAsyncCallback,
|
"type": ResponseTypes.Web3SendAsyncCallback,
|
||||||
"messageId": data.messageId,
|
"messageId": data.messageId,
|
||||||
"error": {
|
"error": {
|
||||||
# TODO where does the code come from?
|
|
||||||
"code": 4100,
|
"code": 4100,
|
||||||
"message": e.msg
|
"message": e.msg
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import QtQuick.Controls.Styles 1.0
|
||||||
import QtQuick.Dialogs 1.2
|
import QtQuick.Dialogs 1.2
|
||||||
import "../../../shared"
|
import "../../../shared"
|
||||||
import "../../../imports"
|
import "../../../imports"
|
||||||
|
import "../Chat/ChatColumn/ChatComponents"
|
||||||
|
|
||||||
// Code based on https://code.qt.io/cgit/qt/qtwebengine.git/tree/examples/webengine/quicknanobrowser/BrowserWindow.qml?h=5.15
|
// Code based on https://code.qt.io/cgit/qt/qtwebengine.git/tree/examples/webengine/quicknanobrowser/BrowserWindow.qml?h=5.15
|
||||||
// Licensed under BSD
|
// Licensed under BSD
|
||||||
|
@ -121,9 +122,16 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO we'll need a new dialog at one point because this one is not using the same call, but it's good for now
|
||||||
|
property Component sendTransactionModalComponent: SignTransactionModal {}
|
||||||
|
|
||||||
property Component sendTransactionModalComponent: SendTransactionModal {}
|
property MessageDialog sendingError: MessageDialog {
|
||||||
|
id: sendingError
|
||||||
|
//% "Error sending the transaction"
|
||||||
|
title: qsTrId("error-sending-the-transaction")
|
||||||
|
icon: StandardIcon.Critical
|
||||||
|
standardButtons: StandardButton.Ok
|
||||||
|
}
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: provider
|
id: provider
|
||||||
|
@ -157,7 +165,72 @@ Item {
|
||||||
} else if (request.type === Constants.web3SendAsyncReadOnly &&
|
} else if (request.type === Constants.web3SendAsyncReadOnly &&
|
||||||
request.payload.method === "eth_sendTransaction") {
|
request.payload.method === "eth_sendTransaction") {
|
||||||
const sendDialog = sendTransactionModalComponent.createObject(browserWindow);
|
const sendDialog = sendTransactionModalComponent.createObject(browserWindow);
|
||||||
sendDialog.request = request;
|
|
||||||
|
walletModel.setFocusedAccountByAddress(request.payload.params[0].from)
|
||||||
|
var acc = walletModel.focusedAccount
|
||||||
|
sendDialog.selectedAccount = {
|
||||||
|
name: acc.name,
|
||||||
|
address: request.payload.params[0].from,
|
||||||
|
iconColor: acc.iconColor,
|
||||||
|
assets: acc.assets
|
||||||
|
}
|
||||||
|
sendDialog.selectedRecipient = {
|
||||||
|
address: request.payload.params[0].to,
|
||||||
|
identicon: chatsModel.generateIdenticon(request.payload.params[0].to),
|
||||||
|
name: chatsModel.activeChannel.name,
|
||||||
|
type: RecipientSelector.Type.Address
|
||||||
|
};
|
||||||
|
// TODO get this from data
|
||||||
|
sendDialog.selectedAsset = {
|
||||||
|
name: "ETH",
|
||||||
|
symbol: "ETH",
|
||||||
|
address: Constants.zeroAddress
|
||||||
|
};
|
||||||
|
const value = utilsModel.wei2Token(request.payload.params[0].value, 18)
|
||||||
|
sendDialog.selectedAmount = value
|
||||||
|
// TODO calculate that
|
||||||
|
sendDialog.selectedFiatAmount = "42";
|
||||||
|
|
||||||
|
// TODO change sendTransaction function to the postMessage one
|
||||||
|
sendDialog.sendTransaction = function (selectedGasLimit, selectedGasPrice, enteredPassword) {
|
||||||
|
console.log('OK', selectedGasLimit, selectedGasPrice, enteredPassword)
|
||||||
|
request.payload.selectedGasLimit = selectedGasLimit
|
||||||
|
request.payload.selectedGasPrice = selectedGasPrice
|
||||||
|
request.payload.password = enteredPassword
|
||||||
|
request.payload.params[0].value = value
|
||||||
|
|
||||||
|
const response = web3Provider.postMessage(JSON.stringify(request))
|
||||||
|
provider.web3Response(response)
|
||||||
|
|
||||||
|
let responseObj
|
||||||
|
try {
|
||||||
|
responseObj = JSON.parse(response)
|
||||||
|
|
||||||
|
if (responseObj.error) {
|
||||||
|
throw new Error(responseObj.error)
|
||||||
|
}
|
||||||
|
|
||||||
|
//% "Transaction pending..."
|
||||||
|
toastMessage.title = qsTrId("ens-transaction-pending")
|
||||||
|
toastMessage.source = "../../img/loading.svg"
|
||||||
|
toastMessage.iconColor = Style.current.primary
|
||||||
|
toastMessage.iconRotates = true
|
||||||
|
toastMessage.link = `${walletModel.etherscanLink}/${responseOnj.result}`
|
||||||
|
toastMessage.open()
|
||||||
|
} catch (e) {
|
||||||
|
if (e.message.includes("could not decrypt key with given password")){
|
||||||
|
//% "Wrong password"
|
||||||
|
sendDialog.transactionSigner.validationError = qsTrId("wrong-password")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sendingError.text = e.message
|
||||||
|
return sendingError.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
sendDialog.close()
|
||||||
|
sendDialog.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
sendDialog.open();
|
sendDialog.open();
|
||||||
walletModel.getGasPricePredictions()
|
walletModel.getGasPricePredictions()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,187 +0,0 @@
|
||||||
import QtQuick 2.13
|
|
||||||
import "../../../shared"
|
|
||||||
import "../../../imports"
|
|
||||||
|
|
||||||
ModalPopup {
|
|
||||||
id: popup
|
|
||||||
|
|
||||||
property var request: ({
|
|
||||||
"type": "web3-send-async-read-only",
|
|
||||||
"messageId": 13,
|
|
||||||
"payload": {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": 19,
|
|
||||||
"method": "eth_sendTransaction",
|
|
||||||
"params": [{
|
|
||||||
"to": "0x2127edab5d08b1e11adf7ae4bae16c2b33fdf74a",
|
|
||||||
"value": "0x9184e72a000",
|
|
||||||
"from": "0x2dcb8515ea98701614919cb82d30876780936a76"
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
"hostname": "ciqhsxa6udhk6tho3smjn4kloo5tb2ly4scv5yrbxgsx6wutijucqdq.infura.status.im",
|
|
||||||
"title": "DAPP"
|
|
||||||
})
|
|
||||||
property string fromAccount: request.payload.params[0].from
|
|
||||||
property string toAccount: request.payload.params[0].to
|
|
||||||
property string value: {
|
|
||||||
// TODO get decimals
|
|
||||||
let val = utilsModel.wei2Token(request.payload.params[0].value, 18)
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
|
|
||||||
function postMessage(isAllowed) {
|
|
||||||
request.isAllowed = isAllowed;
|
|
||||||
provider.web3Response(web3Provider.postMessage(JSON.stringify(request)));
|
|
||||||
}
|
|
||||||
|
|
||||||
onClosed: {
|
|
||||||
popup.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
title: qsTr("Confirm transaction")
|
|
||||||
height: 600
|
|
||||||
|
|
||||||
property string passwordValidationError: ""
|
|
||||||
property bool loading: false
|
|
||||||
|
|
||||||
function validate() {
|
|
||||||
if (passwordInput.text === "") {
|
|
||||||
//% "You need to enter a password"
|
|
||||||
passwordValidationError = qsTrId("you-need-to-enter-a-password")
|
|
||||||
} else if (passwordInput.text.length < 4) {
|
|
||||||
//% "Password needs to be 4 characters or more"
|
|
||||||
passwordValidationError = qsTrId("password-needs-to-be-4-characters-or-more")
|
|
||||||
} else {
|
|
||||||
passwordValidationError = ""
|
|
||||||
}
|
|
||||||
return passwordValidationError === ""
|
|
||||||
}
|
|
||||||
|
|
||||||
onOpened: {
|
|
||||||
passwordInput.text = ""
|
|
||||||
passwordInput.forceActiveFocus(Qt.MouseFocusReason)
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
spacing: Style.current.smallPadding
|
|
||||||
width: parent.width
|
|
||||||
|
|
||||||
TextWithLabel {
|
|
||||||
label: qsTr("From")
|
|
||||||
text: fromAccount
|
|
||||||
}
|
|
||||||
|
|
||||||
TextWithLabel {
|
|
||||||
label: qsTr("To")
|
|
||||||
text: toAccount
|
|
||||||
}
|
|
||||||
|
|
||||||
TextWithLabel {
|
|
||||||
label: qsTr("Value")
|
|
||||||
text: popup.value
|
|
||||||
}
|
|
||||||
|
|
||||||
Input {
|
|
||||||
id: passwordInput
|
|
||||||
//% "Enter your password…"
|
|
||||||
placeholderText: qsTrId("enter-your-password…")
|
|
||||||
//% "Password"
|
|
||||||
label: qsTrId("password")
|
|
||||||
textField.echoMode: TextInput.Password
|
|
||||||
validationError: popup.passwordValidationError
|
|
||||||
}
|
|
||||||
|
|
||||||
GasSelector {
|
|
||||||
id: gasSelector
|
|
||||||
slowestGasPrice: parseFloat(walletModel.safeLowGasPrice)
|
|
||||||
fastestGasPrice: parseFloat(walletModel.fastestGasPrice)
|
|
||||||
getGasEthValue: walletModel.getGasEthValue
|
|
||||||
getFiatValue: walletModel.getFiatValue
|
|
||||||
defaultCurrency: walletModel.defaultCurrency
|
|
||||||
width: parent.width
|
|
||||||
reset: function() {
|
|
||||||
slowestGasPrice = Qt.binding(function(){ return parseFloat(walletModel.safeLowGasPrice) })
|
|
||||||
fastestGasPrice = Qt.binding(function(){ return parseFloat(walletModel.fastestGasPrice) })
|
|
||||||
}
|
|
||||||
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
|
|
||||||
if (!(fromAccount &&
|
|
||||||
toAccount &&
|
|
||||||
// TODO support asset
|
|
||||||
// txtAmount.selectedAsset && txtAmount.selectedAsset.address &&
|
|
||||||
popup.value)) return
|
|
||||||
|
|
||||||
let gasEstimate = JSON.parse(walletModel.estimateGas(
|
|
||||||
fromAccount,
|
|
||||||
toAccount,
|
|
||||||
// TODO support other assets
|
|
||||||
Constants.zeroAddress,
|
|
||||||
popup.value))
|
|
||||||
|
|
||||||
if (!gasEstimate.success) {
|
|
||||||
//% "Error estimating gas: %1"
|
|
||||||
console.warn(qsTrId("error-estimating-gas---1").arg(gasEstimate.error.message))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
selectedGasLimit = gasEstimate.result
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// TODO find where to get the assets
|
|
||||||
// GasValidator {
|
|
||||||
// id: gasValidator
|
|
||||||
// selectedAccount: request.payload.params[0].from
|
|
||||||
// selectedAmount: parseFloat(txtAmount.selectedAmount)
|
|
||||||
// selectedAsset: txtAmount.selectedAsset
|
|
||||||
// selectedGasEthValue: gasSelector.selectedGasEthValue
|
|
||||||
// reset: function() {
|
|
||||||
// selectedAccount = Qt.binding(function() { return selectFromAccount.selectedAccount })
|
|
||||||
// selectedAmount = Qt.binding(function() { return parseFloat(txtAmount.selectedAmount) })
|
|
||||||
// selectedAsset = Qt.binding(function() { return txtAmount.selectedAsset })
|
|
||||||
// selectedGasEthValue = Qt.binding(function() { return gasSelector.selectedGasEthValue })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
footer: Item {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
StyledButton {
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: Style.current.padding
|
|
||||||
label: qsTr("Cancel")
|
|
||||||
disabled: loading
|
|
||||||
onClicked: {
|
|
||||||
// Do we need to send back an error?
|
|
||||||
popup.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledButton {
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: Style.current.padding
|
|
||||||
label: loading ?
|
|
||||||
//% "Loading..."
|
|
||||||
qsTrId("loading") :
|
|
||||||
qsTr("Confirm")
|
|
||||||
|
|
||||||
disabled: loading || passwordInput.text === ""
|
|
||||||
|
|
||||||
onClicked : {
|
|
||||||
loading = true
|
|
||||||
if (!validate()) {
|
|
||||||
return loading = false
|
|
||||||
}
|
|
||||||
|
|
||||||
request.payload.selectedGasLimit = gasSelector.selectedGasLimit
|
|
||||||
request.payload.selectedGasPrice = gasSelector.selectedGasPrice
|
|
||||||
request.payload.password = passwordInput.text
|
|
||||||
request.payload.params[0].value = popup.value
|
|
||||||
provider.web3Response(web3Provider.postMessage(JSON.stringify(request)));
|
|
||||||
loading = false
|
|
||||||
|
|
||||||
popup.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -13,6 +13,31 @@ ModalPopup {
|
||||||
property var selectedAmount
|
property var selectedAmount
|
||||||
property var selectedFiatAmount
|
property var selectedFiatAmount
|
||||||
|
|
||||||
|
property alias transactionSigner: transactionSigner
|
||||||
|
|
||||||
|
property var sendTransaction: function(selectedGasLimit, selectedGasPrice, enteredPassword) {
|
||||||
|
let responseStr = walletModel.sendTransaction(root.selectedAccount.address,
|
||||||
|
root.selectedRecipient.address,
|
||||||
|
root.selectedAsset.address,
|
||||||
|
root.selectedAmount,
|
||||||
|
selectedGasLimit,
|
||||||
|
selectedGasPrice,
|
||||||
|
enteredPassword)
|
||||||
|
|
||||||
|
let response = JSON.parse(responseStr)
|
||||||
|
|
||||||
|
if (response.error) {
|
||||||
|
if (response.result.includes("could not decrypt key with given password")){
|
||||||
|
//% "Wrong password"
|
||||||
|
transactionSigner.validationError = qsTrId("wrong-password")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sendingError.text = response.result
|
||||||
|
return sendingError.open()
|
||||||
|
}
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
//% "Send"
|
//% "Send"
|
||||||
|
@ -31,28 +56,6 @@ ModalPopup {
|
||||||
stack.reset()
|
stack.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendTransaction() {
|
|
||||||
let responseStr = walletModel.sendTransaction(root.selectedAccount.address,
|
|
||||||
root.selectedRecipient.address,
|
|
||||||
root.selectedAsset.address,
|
|
||||||
root.selectedAmount,
|
|
||||||
gasSelector.selectedGasLimit,
|
|
||||||
gasSelector.selectedGasPrice,
|
|
||||||
transactionSigner.enteredPassword)
|
|
||||||
let response = JSON.parse(responseStr)
|
|
||||||
|
|
||||||
if (response.error) {
|
|
||||||
if (response.result.includes("could not decrypt key with given password")){
|
|
||||||
//% "Wrong password"
|
|
||||||
transactionSigner.validationError = qsTrId("wrong-password")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sendingError.text = response.result
|
|
||||||
return sendingError.open()
|
|
||||||
}
|
|
||||||
root.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
TransactionStackView {
|
TransactionStackView {
|
||||||
id: stack
|
id: stack
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -206,7 +209,9 @@ ModalPopup {
|
||||||
const validity = stack.currentGroup.validate()
|
const validity = stack.currentGroup.validate()
|
||||||
if (validity.isValid && !validity.isPending) {
|
if (validity.isValid && !validity.isPending) {
|
||||||
if (stack.isLastGroup) {
|
if (stack.isLastGroup) {
|
||||||
return root.sendTransaction()
|
return root.sendTransaction(gasSelector.selectedGasLimit,
|
||||||
|
gasSelector.selectedGasPrice,
|
||||||
|
transactionSigner.enteredPassword)
|
||||||
}
|
}
|
||||||
stack.next()
|
stack.next()
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,6 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||||
!isEmpty(target.path): INSTALLS += target
|
!isEmpty(target.path): INSTALLS += target
|
||||||
|
|
||||||
DISTFILES += \
|
DISTFILES += \
|
||||||
app/AppLayouts/Browser/SendTransactionModal.qml \
|
|
||||||
app/AppLayouts/Chat/ChatColumn/ChatComponents/ChatCommandButton.qml \
|
app/AppLayouts/Chat/ChatColumn/ChatComponents/ChatCommandButton.qml \
|
||||||
app/AppLayouts/Chat/ChatColumn/ChatComponents/ChatCommandModal.qml \
|
app/AppLayouts/Chat/ChatColumn/ChatComponents/ChatCommandModal.qml \
|
||||||
app/AppLayouts/Chat/ChatColumn/ChatComponents/ChatCommandsPopup.qml \
|
app/AppLayouts/Chat/ChatColumn/ChatComponents/ChatCommandsPopup.qml \
|
||||||
|
|
Loading…
Reference in New Issue