fix: 1:1 chat command transactions "intrinsic gas too low"

I noticed that the 1:1 chat commands were not able to send token transactions due to "intrinsic gas too low" error. I quickly realised there there were a few components missing, which have been fixed.

*feat: update the 1:1 chat commands transaction modal to allow editing of the from account and network fee*

The TransactionStackGroup was updated slightly to allow manual control of back/next actions.

Fixes #870.

*fix: Create distinct modal transaction actions*

Previously, adding `Connection`s for the  `walletModel.transactionWasSent` signal in different dialogs would cause the signal to be handled in the wrong dialog. The solution was to pass a `uuid` from the requesting dialog, and include the `uuid` in the response, so that only requests that were requested from the dialog would be handled.

*fix: update 1:1 translations*
All the translations were not being translated for me. I noticed that they did not exist in the `.ts` translation files either.
This commit is contained in:
emizzle 2020-10-07 13:47:21 +11:00 committed by Pascal Precht
parent 0a13940742
commit 423882df89
No known key found for this signature in database
GPG Key ID: 0EE28D8D6FD85D7D
13 changed files with 252 additions and 127 deletions

View File

@ -280,18 +280,18 @@ QtObject:
proc transactionSent(self: WalletView, txResult: string) {.slot.} = proc transactionSent(self: WalletView, txResult: string) {.slot.} =
self.transactionWasSent(txResult) self.transactionWasSent(txResult)
proc sendTransaction*(self: WalletView, from_addr: string, to: string, assetAddress: string, value: string, gas: string, gasPrice: string, password: string) {.slot.} = proc sendTransaction*(self: WalletView, from_addr: string, to: string, assetAddress: string, value: string, gas: string, gasPrice: string, password: string, uuid: string) {.slot.} =
let wallet = self.status.wallet let wallet = self.status.wallet
if assetAddress != ZERO_ADDRESS and not assetAddress.isEmptyOrWhitespace: if assetAddress != ZERO_ADDRESS and not assetAddress.isEmptyOrWhitespace:
spawnAndSend(self, "transactionSent") do: spawnAndSend(self, "transactionSent") do:
var success: bool var success: bool
let response = wallet.sendTokenTransaction(from_addr, to, assetAddress, value, gas, gasPrice, password, success) let response = wallet.sendTokenTransaction(from_addr, to, assetAddress, value, gas, gasPrice, password, success)
$(%* { "result": %response, "success": %success }) $(%* { "result": %response, "success": %success, "uuid": %uuid })
else: else:
spawnAndSend(self, "transactionSent") do: spawnAndSend(self, "transactionSent") do:
var success: bool var success: bool
let response = wallet.sendTransaction(from_addr, to, value, gas, gasPrice, password, success) let response = wallet.sendTransaction(from_addr, to, value, gas, gasPrice, password, success)
$(%* { "result": %response, "success": %success }) $(%* { "result": %response, "success": %success, "uuid": %uuid })
proc getDefaultAccount*(self: WalletView): string {.slot.} = proc getDefaultAccount*(self: WalletView): string {.slot.} =
self.currentAccount.address self.currentAccount.address

View File

@ -44,7 +44,11 @@ ModalPopup {
currency: walletModel.defaultCurrency currency: walletModel.defaultCurrency
width: stack.width width: stack.width
//% "From account" //% "From account"
label: qsTrId("from-account") label: {
return root.isRequested ?
qsTr("Receive on account") :
qsTrId("from-account")
}
reset: function() { reset: function() {
accounts = Qt.binding(function() { return walletModel.accounts }) accounts = Qt.binding(function() { return walletModel.accounts })
selectedAccount = Qt.binding(function() { return walletModel.currentAccount }) selectedAccount = Qt.binding(function() { return walletModel.currentAccount })
@ -54,13 +58,13 @@ ModalPopup {
id: separator id: separator
anchors.top: selectFromAccount.bottom anchors.top: selectFromAccount.bottom
anchors.topMargin: 19 anchors.topMargin: 19
icon.rotation: root.isRequested ? -90 : 90
} }
RecipientSelector { RecipientSelector {
id: selectRecipient id: selectRecipient
accounts: walletModel.accounts accounts: walletModel.accounts
contacts: profileModel.addedContacts contacts: profileModel.addedContacts
//% "Recipient" label: qsTr("From")
label: qsTrId("recipient")
readOnly: true readOnly: true
anchors.top: separator.bottom anchors.top: separator.bottom
anchors.topMargin: 10 anchors.topMargin: 10
@ -114,6 +118,7 @@ ModalPopup {
SVGImage { SVGImage {
width: 16 width: 16
height: 16 height: 16
visible: warningText.visible
source: "../../../../img/warning.svg" source: "../../../../img/warning.svg"
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: warningText.top anchors.bottom: warningText.top
@ -122,6 +127,7 @@ ModalPopup {
StyledText { StyledText {
id: warningText id: warningText
visible: !root.isRequested
//% "You need to request the recipients address first.\nAssets wont be sent yet." //% "You need to request the recipients address first.\nAssets wont be sent yet."
text: qsTrId("you-need-to-request-the-recipient-s-address-first--nassets-won-t-be-sent-yet-") text: qsTrId("you-need-to-request-the-recipient-s-address-first--nassets-won-t-be-sent-yet-")
color: Style.current.danger color: Style.current.danger
@ -139,29 +145,14 @@ ModalPopup {
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
StyledButton { StatusRoundButton {
id: btnBack id: btnBack
anchors.left: parent.left anchors.left: parent.left
width: 44
height: 44
visible: !stack.isFirstGroup visible: !stack.isFirstGroup
label: "" icon.name: "arrow-right"
background: Rectangle { icon.width: 20
anchors.fill: parent icon.height: 16
border.width: 0 rotation: 180
radius: width / 2
color: btnBack.hovered ? Qt.darker(btnBack.btnColor, 1.1) : btnBack.btnColor
SVGImage {
width: 20.42
height: 15.75
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
fillMode: Image.PreserveAspectFit
source: "../../../../img/arrow-right.svg"
rotation: 180
}
}
onClicked: { onClicked: {
stack.back() stack.back()
} }

View File

@ -24,7 +24,8 @@ ModalPopup {
root.selectedAmount, root.selectedAmount,
selectedGasLimit, selectedGasLimit,
selectedGasPrice, selectedGasPrice,
enteredPassword) enteredPassword,
stack.uuid)
let response = JSON.parse(responseStr) let response = JSON.parse(responseStr)
@ -67,13 +68,14 @@ ModalPopup {
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Style.current.padding anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding anchors.rightMargin: Style.current.padding
initialItem: groupPreview
isLastGroup: stack.currentGroup === groupSignTx
onGroupActivated: { onGroupActivated: {
root.title = group.headerText root.title = group.headerText
btnNext.text = group.footerText btnNext.text = group.footerText
} }
TransactionFormGroup { TransactionFormGroup {
id: group1 id: groupSelectAcct
//% "Send"
headerText: { headerText: {
if(trxData.startsWith("0x095ea7b3")){ if(trxData.startsWith("0x095ea7b3")){
const approveData = JSON.parse(walletModel.decodeTokenApproval(selectedRecipient.address, trxData)) const approveData = JSON.parse(walletModel.decodeTokenApproval(selectedRecipient.address, trxData))
@ -82,9 +84,54 @@ ModalPopup {
} }
return qsTrId("command-button-send"); return qsTrId("command-button-send");
} }
footerText: qsTr("Continue")
showNextBtn: false
onBackClicked: function() {
if(validate()) {
stack.pop()
}
}
AccountSelector {
id: selectFromAccount
accounts: walletModel.accounts
selectedAccount: root.selectedAccount
currency: walletModel.defaultCurrency
width: stack.width
//% "Choose account"
label: qsTrId("choose-account")
showBalanceForAssetSymbol: root.selectedAsset.symbol
minRequiredAssetBalance: parseFloat(root.selectedAmount)
reset: function() {
accounts = Qt.binding(function() { return walletModel.accounts })
selectedAccount = Qt.binding(function() { return root.selectedAccount })
showBalanceForAssetSymbol = Qt.binding(function() { return root.selectedAsset.symbol })
minRequiredAssetBalance = Qt.binding(function() { return parseFloat(root.selectedAmount) })
}
onSelectedAccountChanged: if (isValid) { gasSelector.estimateGas() }
}
RecipientSelector {
id: selectRecipient
visible: false
accounts: walletModel.accounts
contacts: profileModel.addedContacts
selectedRecipient: root.selectedRecipient
readOnly: true
reset: function() {
accounts = Qt.binding(function() { return walletModel.accounts })
contacts = Qt.binding(function() { return profileModel.addedContacts })
selectedRecipient = Qt.binding(function() { return root.selectedRecipient })
}
}
}
TransactionFormGroup {
id: groupSelectGas
headerText: qsTr("Network fee")
//% "Preview" //% "Preview"
footerText: qsTrId("preview") footerText: qsTrId("preview")
showNextBtn: false
onBackClicked: function() {
stack.pop()
}
GasSelector { GasSelector {
id: gasSelector id: gasSelector
anchors.topMargin: Style.current.bigPadding anchors.topMargin: Style.current.bigPadding
@ -98,17 +145,19 @@ ModalPopup {
slowestGasPrice = Qt.binding(function(){ return parseFloat(walletModel.safeLowGasPrice) }) slowestGasPrice = Qt.binding(function(){ return parseFloat(walletModel.safeLowGasPrice) })
fastestGasPrice = Qt.binding(function(){ return parseFloat(walletModel.fastestGasPrice) }) fastestGasPrice = Qt.binding(function(){ return parseFloat(walletModel.fastestGasPrice) })
} }
function estimateGas() { property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
console.log("CALLING ESTIMATE GAS") if (!(selectFromAccount.selectedAccount && selectFromAccount.selectedAccount.address &&
if (!(root.selectedAccount && root.selectedAccount.address && selectRecipient.selectedRecipient && selectRecipient.selectedRecipient.address &&
root.selectedRecipient && root.selectedRecipient.address &&
root.selectedAsset && root.selectedAsset.address && root.selectedAsset && root.selectedAsset.address &&
root.selectedAmount)) return root.selectedAmount)) {
selectedGasLimit = 250000
return
}
let gasEstimate = JSON.parse(walletModel.estimateGas( let gasEstimate = JSON.parse(walletModel.estimateGas(
root.selectedAccount.address, selectFromAccount.selectedAccount.address,
root.selectedRecipient.address, selectRecipient.selectedRecipient.address,
root.selectedAsset.address, root.selectedAsset.address,
root.selectedAmount, root.selectedAmount,
trxData)) trxData))
@ -119,7 +168,7 @@ ModalPopup {
return return
} }
selectedGasLimit = gasEstimate.result selectedGasLimit = gasEstimate.result
} })
} }
GasValidator { GasValidator {
id: gasValidator id: gasValidator
@ -130,16 +179,24 @@ ModalPopup {
selectedAsset: root.selectedAsset selectedAsset: root.selectedAsset
selectedGasEthValue: gasSelector.selectedGasEthValue selectedGasEthValue: gasSelector.selectedGasEthValue
reset: function() { reset: function() {
selectedAccount = Qt.binding(function() { return root.selectedAccount })
selectedAmount = Qt.binding(function() { return parseFloat(root.selectedAmount) })
selectedAsset = Qt.binding(function() { return root.selectedAsset })
selectedGasEthValue = Qt.binding(function() { return gasSelector.selectedGasEthValue }) selectedGasEthValue = Qt.binding(function() { return gasSelector.selectedGasEthValue })
} }
} }
} }
TransactionFormGroup { TransactionFormGroup {
id: group2 id: groupPreview
//% "Transaction preview" //% "Transaction preview"
headerText: qsTrId("transaction-preview") headerText: qsTrId("transaction-preview")
//% "Sign with password" //% "Sign with password"
footerText: qsTrId("sign-with-password") footerText: qsTrId("sign-with-password")
showBackBtn: false
onNextClicked: function() {
stack.push(groupSignTx, StackView.Immediate)
}
TransactionPreview { TransactionPreview {
id: pvwTransaction id: pvwTransaction
@ -155,6 +212,7 @@ ModalPopup {
amount: { "value": root.selectedAmount, "fiatValue": root.selectedFiatAmount } amount: { "value": root.selectedAmount, "fiatValue": root.selectedFiatAmount }
currency: walletModel.defaultCurrency currency: walletModel.defaultCurrency
reset: function() { reset: function() {
fromAccount = Qt.binding(function() { return root.selectedAccount })
gas = Qt.binding(function() { gas = Qt.binding(function() {
return { return {
"value": gasSelector.selectedGasEthValue, "value": gasSelector.selectedGasEthValue,
@ -162,15 +220,23 @@ ModalPopup {
"fiatValue": gasSelector.selectedGasFiatValue "fiatValue": gasSelector.selectedGasFiatValue
} }
}) })
toAccount = Qt.binding(function() { return root.selectedRecipient })
asset = Qt.binding(function() { return root.selectedAsset })
amount = Qt.binding(function() { return { "value": root.selectedAmount, "fiatValue": root.selectedFiatAmount } })
} }
onFromClicked: stack.push(groupSelectAcct, StackView.Immediate)
onGasClicked: stack.push(groupSelectGas, StackView.Immediate)
} }
} }
TransactionFormGroup { TransactionFormGroup {
id: group3 id: groupSignTx
//% "Sign with password" //% "Sign with password"
headerText: qsTrId("sign-with-password") headerText: qsTrId("sign-with-password")
//% "Send %1 %2" //% "Send %1 %2"
footerText: qsTrId("send--1--2").arg(root.selectedAmount).arg(!!root.selectedAsset ? root.selectedAsset.symbol : "") footerText: qsTrId("send--1--2").arg(root.selectedAmount).arg(!!root.selectedAsset ? root.selectedAsset.symbol : "")
onBackClicked: function() {
stack.pop()
}
TransactionSigner { TransactionSigner {
id: transactionSigner id: transactionSigner
@ -187,30 +253,19 @@ ModalPopup {
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
StyledButton { StatusRoundButton {
id: btnBack id: btnBack
anchors.left: parent.left anchors.left: parent.left
width: 44 icon.name: "arrow-right"
height: 44 icon.width: 20
visible: !stack.isFirstGroup icon.height: 16
label: "" rotation: 180
background: Rectangle { visible: stack.currentGroup.showBackBtn
anchors.fill: parent enabled: stack.currentGroup.isValid || stack.isLastGroup
border.width: 0
radius: width / 2
color: btnBack.hovered ? Qt.darker(btnBack.btnColor, 1.1) : btnBack.btnColor
SVGImage {
width: 20.42
height: 15.75
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
fillMode: Image.PreserveAspectFit
source: "../../../../img/arrow-right.svg"
rotation: 180
}
}
onClicked: { onClicked: {
if (typeof stack.currentGroup.onBackClicked === "function") {
return stack.currentGroup.onBackClicked()
}
stack.back() stack.back()
} }
} }
@ -220,6 +275,7 @@ ModalPopup {
//% "Next" //% "Next"
text: qsTrId("next") text: qsTrId("next")
enabled: stack.currentGroup.isValid && !stack.currentGroup.isPending enabled: stack.currentGroup.isValid && !stack.currentGroup.isPending
visible: stack.currentGroup.showNextBtn
onClicked: { onClicked: {
const validity = stack.currentGroup.validate() const validity = stack.currentGroup.validate()
if (validity.isValid && !validity.isPending) { if (validity.isValid && !validity.isPending) {
@ -228,10 +284,47 @@ ModalPopup {
gasSelector.selectedGasPrice, gasSelector.selectedGasPrice,
transactionSigner.enteredPassword) transactionSigner.enteredPassword)
} }
if (typeof stack.currentGroup.onNextClicked === "function") {
return stack.currentGroup.onNextClicked()
}
stack.next() stack.next()
} }
} }
} }
Connections {
target: walletModel
onTransactionWasSent: {
try {
let response = JSON.parse(txResult)
if (response.uuid !== stack.uuid) return
stack.currentGroup.isPending = false
if (!response.success) {
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()
}
//% "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}/${response.result}`
toastMessage.open()
root.close()
} catch (e) {
console.error('Error parsing the response', e)
}
}
}
} }
} }

View File

@ -14,8 +14,7 @@ Item {
StyledText { StyledText {
id: signText id: signText
color: Style.current.blue color: Style.current.blue
//% "Sign and send" text: qsTr("Sign and send")
text: qsTrId("sign-and-send")
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
font.weight: Font.Medium font.weight: Font.Medium

View File

@ -55,26 +55,18 @@ Rectangle {
} }
text: { text: {
switch (root.state) { switch (root.state) {
//% "Pending" case Constants.pending: return qsTr("Pending")
case Constants.pending: return qsTrId("pending") case Constants.confirmed: return qsTr("Confirmed")
//% "Confirmed" case Constants.unknown: return qsTr("Unknown token")
case Constants.confirmed: return qsTrId("status-confirmed") case Constants.addressRequested: return qsTr("Address requested")
//% "Unknown token" case Constants.transactionRequested: return qsTr("Waiting to accept")
case Constants.unknown: return qsTrId("unknown-token") case Constants.addressReceived: return (!root.outgoing ?
//% "Address requested" qsTr("Address shared") :
case Constants.addressRequested: return qsTrId("address-requested") qsTr("Address received"))
//% "Waiting to accept"
case Constants.transactionRequested: return qsTrId("waiting-to-accept")
//% "Address shared"
//% "Address received"
case Constants.addressReceived: return (!root.outgoing ? qsTrId("address-shared") : qsTrId("address-received"))
case Constants.transactionDeclined: case Constants.transactionDeclined:
//% "Transaction declined" case Constants.declined: return qsTr("Transaction declined")
case Constants.declined: return qsTrId("transaction-declined") case Constants.failure: return qsTr("failure")
//% "Failure" default: return qsTr("Unknown state")
case Constants.failure: return qsTrId("failure")
//% "Unknown state"
default: return qsTrId("unknown-state")
} }
} }
font.weight: Font.Medium font.weight: Font.Medium

View File

@ -81,7 +81,7 @@ ModalPopup {
showBalanceForAssetSymbol = Qt.binding(function() { return root.asset.symbol }) showBalanceForAssetSymbol = Qt.binding(function() { return root.asset.symbol })
minRequiredAssetBalance = Qt.binding(function() { return root.ensPrice }) minRequiredAssetBalance = Qt.binding(function() { return root.ensPrice })
} }
onSelectedAccountChanged: gasSelector.estimateGas() onSelectedAccountChanged: if (isValid) { gasSelector.estimateGas() }
} }
RecipientSelector { RecipientSelector {
id: selectRecipient id: selectRecipient
@ -90,7 +90,7 @@ ModalPopup {
contacts: profileModel.addedContacts contacts: profileModel.addedContacts
selectedRecipient: { "address": utilsModel.ensRegisterAddress, "type": RecipientSelector.Type.Address } selectedRecipient: { "address": utilsModel.ensRegisterAddress, "type": RecipientSelector.Type.Address }
readOnly: true readOnly: true
onSelectedRecipientChanged: gasSelector.estimateGas() onSelectedRecipientChanged: if (isValid) { gasSelector.estimateGas() }
} }
GasSelector { GasSelector {
id: gasSelector id: gasSelector

View File

@ -85,7 +85,7 @@ ModalPopup {
showBalanceForAssetSymbol = Qt.binding(function() { return "ETH" }) showBalanceForAssetSymbol = Qt.binding(function() { return "ETH" })
minRequiredAssetBalance = Qt.binding(function() { return 0 }) minRequiredAssetBalance = Qt.binding(function() { return 0 })
} }
onSelectedAccountChanged: gasSelector.estimateGas() onSelectedAccountChanged: if (isValid) { gasSelector.estimateGas() }
} }
RecipientSelector { RecipientSelector {
id: selectRecipient id: selectRecipient
@ -94,7 +94,7 @@ ModalPopup {
contacts: profileModel.addedContacts contacts: profileModel.addedContacts
selectedRecipient: { "address": utilsModel.ensRegisterAddress, "type": RecipientSelector.Type.Address } selectedRecipient: { "address": utilsModel.ensRegisterAddress, "type": RecipientSelector.Type.Address }
readOnly: true readOnly: true
onSelectedRecipientChanged: gasSelector.estimateGas() onSelectedRecipientChanged: if (isValid) { gasSelector.estimateGas() }
} }
GasSelector { GasSelector {
id: gasSelector id: gasSelector

View File

@ -35,7 +35,8 @@ ModalPopup {
txtAmount.selectedAmount, txtAmount.selectedAmount,
gasSelector.selectedGasLimit, gasSelector.selectedGasLimit,
gasSelector.selectedGasPrice, gasSelector.selectedGasPrice,
transactionSigner.enteredPassword) transactionSigner.enteredPassword,
stack.uuid)
} }
TransactionStackView { TransactionStackView {
@ -66,7 +67,7 @@ ModalPopup {
accounts = Qt.binding(function() { return walletModel.accounts }) accounts = Qt.binding(function() { return walletModel.accounts })
selectedAccount = Qt.binding(function() { return walletModel.currentAccount }) selectedAccount = Qt.binding(function() { return walletModel.currentAccount })
} }
onSelectedAccountChanged: gasSelector.estimateGas() onSelectedAccountChanged: if (isValid) { gasSelector.estimateGas() }
} }
SeparatorWithIcon { SeparatorWithIcon {
id: separator id: separator
@ -87,7 +88,7 @@ ModalPopup {
contacts = Qt.binding(function() { return profileModel.addedContacts }) contacts = Qt.binding(function() { return profileModel.addedContacts })
selectedRecipient = {} selectedRecipient = {}
} }
onSelectedRecipientChanged: gasSelector.estimateGas() onSelectedRecipientChanged: if (isValid) { gasSelector.estimateGas() }
} }
} }
TransactionFormGroup { TransactionFormGroup {
@ -107,8 +108,8 @@ ModalPopup {
reset: function() { reset: function() {
selectedAccount = Qt.binding(function() { return selectFromAccount.selectedAccount }) selectedAccount = Qt.binding(function() { return selectFromAccount.selectedAccount })
} }
onSelectedAssetChanged: gasSelector.estimateGas() onSelectedAssetChanged: if (isValid) { gasSelector.estimateGas() }
onSelectedAmountChanged: gasSelector.estimateGas() onSelectedAmountChanged: if (isValid) { gasSelector.estimateGas() }
} }
GasSelector { GasSelector {
id: gasSelector id: gasSelector
@ -225,30 +226,14 @@ ModalPopup {
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
StyledButton { StatusRoundButton {
id: btnBack id: btnBack
anchors.left: parent.left anchors.left: parent.left
width: 44
height: 44
visible: !stack.isFirstGroup visible: !stack.isFirstGroup
label: "" icon.name: "arrow-right"
background: Rectangle { icon.width: 20
anchors.fill: parent icon.height: 16
border.width: 0 rotation: 180
radius: width / 2
color: btnBack.disabled ? Style.current.grey :
btnBack.hovered ? Qt.darker(btnBack.btnColor, 1.1) : btnBack.btnColor
SVGImage {
width: 20.42
height: 15.75
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
fillMode: Image.PreserveAspectFit
source: "../../img/arrow-right.svg"
rotation: 180
}
}
onClicked: { onClicked: {
stack.back() stack.back()
} }
@ -275,9 +260,12 @@ ModalPopup {
target: walletModel target: walletModel
onTransactionWasSent: { onTransactionWasSent: {
try { try {
stack.currentGroup.isPending = false
let response = JSON.parse(txResult) let response = JSON.parse(txResult)
if (response.uuid !== stack.uuid) return
stack.currentGroup.isPending = false
if (!response.success) { if (!response.success) {
if (response.result.includes("could not decrypt key with given password")){ if (response.result.includes("could not decrypt key with given password")){
//% "Wrong password" //% "Wrong password"

View File

@ -167,4 +167,8 @@ QtObject {
let wordCount = countWords(text); let wordCount = countWords(text);
return qsTr("%1%2 words").arg(getTick(wordCount)).arg(wordCount.toString()); return qsTr("%1%2 words").arg(getTick(wordCount)).arg(wordCount.toString());
} }
function uuid() {
return Date.now().toString(36) + Math.random().toString(36).substr(2, 5)
}
} }

View File

@ -6,4 +6,8 @@ FormGroup {
id: root id: root
property string headerText property string headerText
property string footerText property string footerText
property bool showBackBtn: true
property bool showNextBtn: true
property var onBackClicked
property var onNextClicked
} }

View File

@ -15,6 +15,8 @@ Item {
property var gas property var gas
height: content.height height: content.height
property var reset: function() {} property var reset: function() {}
signal fromClicked
signal gasClicked
function resetInternal() { function resetInternal() {
fromAccount = undefined fromAccount = undefined
@ -53,15 +55,39 @@ Item {
id: imgFromWallet id: imgFromWallet
sourceSize.height: 18 sourceSize.height: 18
sourceSize.width: 18 sourceSize.width: 18
anchors.right: parent.right anchors.right: fromArrow.visible ? fromArrow.left : parent.right
anchors.rightMargin: fromArrow.visible ? Style.current.padding : 0
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit
source: "../app/img/walletIcon.svg" source: "../app/img/walletIcon.svg"
ColorOverlay {
anchors.fill: parent
source: parent
color: root.fromAccount ? root.fromAccount.iconColor : Style.current.blue
}
} }
ColorOverlay { SVGImage {
anchors.fill: imgFromWallet id: fromArrow
source: imgFromWallet width: 13
color: root.fromAccount ? root.fromAccount.iconColor : Style.current.blue visible: typeof root.fromClicked === "function"
anchors.right: parent.right
anchors.rightMargin: 7
anchors.verticalCenter: parent.verticalCenter
fillMode: Image.PreserveAspectFit
source: "../app/img/caret.svg"
rotation: 270
ColorOverlay {
anchors.fill: parent
visible: parent.visible
source: parent
color: Style.current.secondaryText
}
}
MouseArea {
anchors.fill: parent
visible: fromArrow.visible
cursorShape: Qt.PointingHandCursor
onClicked: root.fromClicked()
} }
} }
} }
@ -316,6 +342,7 @@ Item {
id: itmNetworkFee id: itmNetworkFee
//% "Network fee" //% "Network fee"
label: qsTrId("network-fee") label: qsTrId("network-fee")
visible: !!root.gas
value: Item { value: Item {
id: networkFeeRoot id: networkFeeRoot
anchors.fill: parent anchors.fill: parent
@ -362,11 +389,35 @@ Item {
height: 22 height: 22
text: root.currency.toUpperCase() text: root.currency.toUpperCase()
color: Style.current.secondaryText color: Style.current.secondaryText
anchors.right: parent.right anchors.right: gasArrow.visible ? gasArrow.left : parent.right
anchors.rightMargin: gasArrow.visible ? Style.current.padding : 0
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
} }
SVGImage {
id: gasArrow
width: 13
visible: typeof root.gasClicked === "function"
anchors.right: parent.right
anchors.rightMargin: 7
anchors.verticalCenter: parent.verticalCenter
fillMode: Image.PreserveAspectFit
source: "../app/img/caret.svg"
rotation: 270
ColorOverlay {
anchors.fill: parent
visible: parent.visible
source: parent
color: Style.current.secondaryText
}
}
MouseArea {
anchors.fill: parent
visible: gasArrow.visible
cursorShape: Qt.PointingHandCursor
onClicked: root.gasClicked()
}
} }
} }
} }

View File

@ -10,13 +10,14 @@ StackView {
property bool isFirstGroup: currentIdx === 0 property bool isFirstGroup: currentIdx === 0
signal groupActivated(Item group) signal groupActivated(Item group)
property alias currentGroup: root.currentItem property alias currentGroup: root.currentItem
readonly property string uuid: Utils.uuid()
property var next: function() { property var next: function() {
if (groups && groups.length <= currentIdx + 1) { if (groups && groups.length <= currentIdx + 1) {
return return
} }
const group = groups[++currentIdx] const group = groups[++currentIdx]
this.push(group, StackView.Immediate) this.push(group, StackView.Immediate)
} }
property var back: function() { property var back: function() {
if (currentIdx <= 0) { if (currentIdx <= 0) {

View File

@ -85,7 +85,7 @@ ModalPopup {
showBalanceForAssetSymbol = Qt.binding(function() { return root.asset.symbol }) showBalanceForAssetSymbol = Qt.binding(function() { return root.asset.symbol })
minRequiredAssetBalance = Qt.binding(function() { return root.packPrice }) minRequiredAssetBalance = Qt.binding(function() { return root.packPrice })
} }
onSelectedAccountChanged: gasSelector.estimateGas() onSelectedAccountChanged: if (isValid) { gasSelector.estimateGas() }
} }
RecipientSelector { RecipientSelector {
id: selectRecipient id: selectRecipient
@ -94,7 +94,7 @@ ModalPopup {
contacts: profileModel.addedContacts contacts: profileModel.addedContacts
selectedRecipient: { "address": utilsModel.stickerMarketAddress, "type": RecipientSelector.Type.Address } selectedRecipient: { "address": utilsModel.stickerMarketAddress, "type": RecipientSelector.Type.Address }
readOnly: true readOnly: true
onSelectedRecipientChanged: gasSelector.estimateGas() onSelectedRecipientChanged: if (isValid) { gasSelector.estimateGas() }
} }
GasSelector { GasSelector {
id: gasSelector id: gasSelector
@ -196,11 +196,13 @@ ModalPopup {
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
StyledButton { StatusRoundButton {
id: btnBack id: btnBack
anchors.left: parent.left anchors.left: parent.left
//% "Back" icon.name: "arrow-right"
label: qsTrId("back") icon.width: 20
icon.height: 16
rotation: 180
onClicked: { onClicked: {
if (stack.isFirstGroup) { if (stack.isFirstGroup) {
return root.close() return root.close()