2020-08-13 07:27:53 +00:00
import QtQuick 2.13
import QtQuick . Controls 2.13
import QtQuick . Layouts 1.13
2021-09-28 15:04:06 +00:00
import utils 1.0
2021-10-28 20:23:30 +00:00
import shared . panels 1.0
import shared . controls 1.0
import shared . controls . chat 1.0
2021-10-21 15:07:13 +00:00
import StatusQ . Controls 0.1
2022-07-01 11:24:32 +00:00
import StatusQ . Components 0.1
2021-10-21 15:07:13 +00:00
2020-08-13 07:27:53 +00:00
Item {
id: root
2021-05-21 20:19:03 +00:00
width: parent . width
2022-03-18 14:47:51 +00:00
height: visible ? Style . current . smallPadding + prioritytext . height +
( advancedMode ? advancedModeItemGroup.height : selectorButtons . height ) : 0
2021-05-21 20:19:03 +00:00
2022-05-19 08:53:57 +00:00
property var suggestedFees: ( {
eip1559Enabled: true
} )
2021-07-05 12:34:56 +00:00
property var getGasGweiValue: function ( ) { }
2020-08-13 07:27:53 +00:00
property var getGasEthValue: function ( ) { }
property var getFiatValue: function ( ) { }
2022-06-02 17:47:42 +00:00
property var getEstimatedTime: function ( ) { }
2020-08-13 07:27:53 +00:00
property string defaultCurrency: "USD"
property alias selectedGasPrice: inputGasPrice . text
property alias selectedGasLimit: inputGasLimit . text
2021-07-05 12:34:56 +00:00
property string defaultGasLimit: "0"
2022-03-18 14:47:51 +00:00
property string maxFiatFees: selectedGasFiatValue + root . defaultCurrency . toUpperCase ( )
2022-06-02 17:47:42 +00:00
property int estimatedTxTimeFlag: Constants . transactionEstimatedTime . unknown
2022-06-07 13:57:09 +00:00
property int chainId: 1
2021-07-05 12:34:56 +00:00
property alias selectedTipLimit: inputPerGasTipLimit . text
property alias selectedOverallLimit: inputGasPrice . text
2020-09-01 03:49:05 +00:00
property double selectedGasEthValue
property double selectedGasFiatValue
2022-04-04 11:26:30 +00:00
property string greaterThan0ErrorMessage: qsTr ( "Must be greater than 0" )
property string invalidInputErrorMessage: qsTr ( "This needs to be a number" )
property string noInputErrorMessage: qsTr ( "Please enter an amount" )
2020-08-20 04:45:29 +00:00
property bool isValid: true
2020-12-14 05:50:47 +00:00
readonly property string uuid: Utils . uuid ( )
2020-08-13 07:27:53 +00:00
2022-03-23 08:32:25 +00:00
property bool advancedMode: false
2021-07-05 12:34:56 +00:00
// TODO: change these values false once EIP1559 suggestions are revised
2022-07-17 14:55:57 +00:00
property double perGasTipLimitFloor: 1 // Matches status-mobile minimum-priority-fee
property double perGasTipLimitAverage: formatDec ( root . suggestedFees . maxPriorityFeePerGas , 2 ) // 1.5 // Matches status-mobile average-priority-fee
2021-07-05 12:34:56 +00:00
property bool showPriceLimitWarning : false
property bool showTipLimitWarning : false
function formatDec ( num , dec ) {
return Math . round ( ( num + Number . EPSILON ) * Math . pow ( 10 , dec ) ) / Math . pow ( 10 , dec )
}
2021-05-21 20:19:03 +00:00
2020-08-13 07:27:53 +00:00
function updateGasEthValue ( ) {
2020-08-13 08:24:51 +00:00
// causes error on application load without this null check
if ( ! inputGasPrice || ! inputGasLimit ) {
return
2022-05-19 08:53:57 +00:00
2020-08-13 08:24:51 +00:00
}
2022-06-02 17:47:42 +00:00
Qt . callLater ( function ( ) {
2022-06-07 13:57:09 +00:00
let ethValue = root . getGasEthValue ( inputGasPrice . text , inputGasLimit . text )
let fiatValue = root . getFiatValue ( ethValue , "ETH" , root . defaultCurrency )
selectedGasEthValue = ethValue
selectedGasFiatValue = fiatValue
2022-07-07 08:51:04 +00:00
root . estimatedTxTimeFlag = root . getEstimatedTime ( root . chainId , inputGasPrice . text )
2022-06-02 17:47:42 +00:00
} )
2020-08-13 07:27:53 +00:00
}
2021-07-05 12:34:56 +00:00
function appendError ( accum , error , nonBlocking = false ) {
return accum + ` < span class = "${nonBlocking ? " non - blocking " : " "}" > $ { error } . < / s p a n > `
}
function checkLimits ( ) {
2022-05-19 08:53:57 +00:00
if ( ! root . suggestedFees . eip1559Enabled ) return ;
2021-07-05 12:34:56 +00:00
let inputTipLimit = parseFloat ( inputPerGasTipLimit . text || "0.00" )
let inputOverallLimit = parseFloat ( inputGasPrice . text || "0.00" )
let gasLimit = parseInt ( inputGasLimit . text , 10 )
errorsText . text = "" ;
showPriceLimitWarning = false
showTipLimitWarning = false
let errorMsg = "" ;
2022-02-09 09:43:23 +00:00
2021-07-05 12:34:56 +00:00
if ( gasLimit < 21000 ) {
errorMsg = appendError ( errorMsg , qsTr ( "Min 21000 units" ) )
} else if ( gasLimit < parseInt ( defaultGasLimit ) ) {
errorMsg = appendError ( errorMsg , qsTr ( "Not enough gas" ) . arg ( perGasTipLimitAverage ) , true )
}
// Per-gas tip limit rules
if ( inputTipLimit < perGasTipLimitFloor ) {
errorMsg = appendError ( errorMsg , qsTr ( "Miners will currently not process transactions with a tip below %1 Gwei, the average is %2 Gwei" ) . arg ( perGasTipLimitFloor ) . arg ( perGasTipLimitAverage ) )
showTipLimitWarning = true
} else if ( inputTipLimit < perGasTipLimitAverage ) {
errorMsg = appendError ( errorMsg , qsTr ( "The average miner tip is %1 Gwei" ) . arg ( perGasTipLimitAverage ) , true )
}
errorsText . text = ` < style type = "text/css" > span { color: "#ff0000" } span . non - blocking { color: "#FE8F59" } < / s t y l e > $ { e r r o r M s g } `
}
2022-05-19 08:53:57 +00:00
function checkOptimal ( ) {
2022-07-01 11:24:32 +00:00
if ( ! optimalGasButton . checked ) {
optimalGasButton . toggle ( )
2022-05-19 08:53:57 +00:00
}
2021-07-05 12:34:56 +00:00
}
2021-05-25 14:58:53 +00:00
2021-05-21 20:19:03 +00:00
function validate ( ) {
// causes error on application load without a null check
2021-07-05 12:34:56 +00:00
if ( ! inputGasLimit || ! inputGasPrice || ! inputPerGasTipLimit ) {
2021-05-21 20:19:03 +00:00
return
}
2021-07-05 12:34:56 +00:00
2021-05-21 20:19:03 +00:00
inputGasLimit . validationError = ""
inputGasPrice . validationError = ""
2021-07-05 12:34:56 +00:00
inputPerGasTipLimit . validationError = ""
2021-05-21 20:19:03 +00:00
const noInputLimit = inputGasLimit . text === ""
const noInputPrice = inputGasPrice . text === ""
2021-07-05 12:34:56 +00:00
const noPerGasTip = inputPerGasTipLimit . text === ""
2021-05-21 20:19:03 +00:00
if ( noInputLimit ) {
inputGasLimit . validationError = root . noInputErrorMessage
}
2021-07-05 12:34:56 +00:00
2021-05-21 20:19:03 +00:00
if ( noInputPrice ) {
inputGasPrice . validationError = root . noInputErrorMessage
}
2021-07-05 12:34:56 +00:00
2022-05-19 08:53:57 +00:00
if ( root . suggestedFees . eip1559Enabled && noPerGasTip ) {
2021-07-05 12:34:56 +00:00
inputPerGasTipLimit . validationError = root . noInputErrorMessage
}
2021-05-21 20:19:03 +00:00
if ( isNaN ( inputGasLimit . text ) ) {
inputGasLimit . validationError = invalidInputErrorMessage
}
if ( isNaN ( inputGasPrice . text ) ) {
inputGasPrice . validationError = invalidInputErrorMessage
}
2021-07-05 12:34:56 +00:00
2022-05-19 08:53:57 +00:00
if ( root . suggestedFees . eip1559Enabled && isNaN ( inputPerGasTipLimit . text ) ) {
2021-07-05 12:34:56 +00:00
inputPerGasTipLimit . validationError = invalidInputErrorMessage
}
2021-05-21 20:19:03 +00:00
let inputLimit = parseFloat ( inputGasLimit . text || "0.00" )
let inputPrice = parseFloat ( inputGasPrice . text || "0.00" )
2021-07-05 12:34:56 +00:00
let inputTipLimit = parseFloat ( inputPerGasTipLimit . text || "0.00" )
if ( inputLimit <= 0.00 ) {
2021-05-21 20:19:03 +00:00
inputGasLimit . validationError = root . greaterThan0ErrorMessage
}
2021-07-05 12:34:56 +00:00
if ( inputPrice <= 0.00 ) {
2021-05-21 20:19:03 +00:00
inputGasPrice . validationError = root . greaterThan0ErrorMessage
}
2022-05-19 08:53:57 +00:00
if ( root . suggestedFees . eip1559Enabled && inputTipLimit <= 0.00 ) {
2021-07-05 12:34:56 +00:00
inputPerGasTipLimit . validationError = root . greaterThan0ErrorMessage
}
2022-06-07 13:57:09 +00:00
return inputGasLimit . validationError === "" && inputGasPrice . validationError === "" && ( ! root . suggestedFees . eip1559Enabled || ( root . suggestedFees . eip1559Enabled && inputPerGasTipLimit . validationError === "" ) )
2021-05-21 20:19:03 +00:00
}
2020-08-13 07:27:53 +00:00
StyledText {
2021-05-21 20:19:03 +00:00
id: prioritytext
2020-08-13 07:27:53 +00:00
anchors.top: parent . top
anchors.left: parent . left
2022-05-19 08:53:57 +00:00
text: root . suggestedFees . eip1559Enabled ? qsTr ( "Priority" ) : qsTr ( "Gas Price" )
2020-08-13 07:27:53 +00:00
font.weight: Font . Medium
font.pixelSize: 13
color: Style . current . textColor
2022-07-27 21:10:00 +00:00
visible: root . suggestedFees . eip1559Enabled && advancedMode
2020-08-13 07:27:53 +00:00
}
2021-07-05 12:34:56 +00:00
StyledText {
id: baseFeeText
2022-05-19 08:53:57 +00:00
visible: root . suggestedFees . eip1559Enabled && advancedMode
2021-07-05 12:34:56 +00:00
anchors.top: parent . top
anchors.left: prioritytext . right
anchors.leftMargin: Style . current . smallPadding
2022-03-23 08:32:25 +00:00
text: qsTr ( "Current base fee: %1 %2" ) . arg ( root . suggestedFees . baseFee ) . arg ( "Gwei" )
2021-07-05 12:34:56 +00:00
font.weight: Font . Medium
font.pixelSize: 13
color: Style . current . secondaryText
}
2022-07-01 11:24:32 +00:00
StatusButton {
2021-05-21 20:19:03 +00:00
anchors.verticalCenter: prioritytext . verticalCenter
2020-08-13 07:27:53 +00:00
anchors.right: parent . right
2022-07-27 21:10:00 +00:00
anchors.rightMargin: Style . current . bigPadding
2022-07-01 11:24:32 +00:00
height: 22
defaultTopPadding: 2
defaultBottomPadding: 2
size: StatusBaseButton . Size . Tiny
2022-05-19 08:53:57 +00:00
visible: root . suggestedFees . eip1559Enabled
2021-07-22 15:03:59 +00:00
text: advancedMode ?
2022-04-04 11:26:30 +00:00
qsTr ( "Use suggestions" ) :
qsTr ( "Use custom" )
2020-08-13 07:27:53 +00:00
font.pixelSize: 13
2021-05-21 20:19:03 +00:00
onClicked: advancedMode = ! advancedMode
2020-08-13 07:27:53 +00:00
}
2021-05-21 20:19:03 +00:00
Row {
id: selectorButtons
2022-05-19 08:53:57 +00:00
visible: root . suggestedFees . eip1559Enabled && ! advancedMode
2021-05-21 20:19:03 +00:00
anchors.top: prioritytext . bottom
anchors.topMargin: Style . current . halfPadding
spacing: 11
2020-08-13 07:27:53 +00:00
2021-05-21 20:19:03 +00:00
GasSelectorButton {
2022-05-19 08:53:57 +00:00
id: lowGasButton
2022-08-18 17:51:18 +00:00
objectName: "GasSelector_lowGasButton"
2022-07-01 11:24:32 +00:00
primaryText: qsTr ( "Low" )
2021-05-21 20:19:03 +00:00
gasLimit: inputGasLimit ? inputGasLimit.text : ""
getGasEthValue: root . getGasEthValue
getFiatValue: root . getFiatValue
defaultCurrency: root . defaultCurrency
2022-07-01 11:24:32 +00:00
price: {
if ( ! root . suggestedFees . eip1559Enabled ) return root . suggestedFees . gasPrice ;
return formatDec ( root . suggestedFees . maxFeePerGasL , 6 )
}
onCheckedChanged: {
if ( checked ) {
if ( root . suggestedFees . eip1559Enabled ) {
inputPerGasTipLimit . text = formatDec ( root . suggestedFees . maxPriorityFeePerGas , 2 ) ;
inputGasPrice . text = formatDec ( root . suggestedFees . maxFeePerGasL , 2 ) ;
} else {
inputGasPrice . text = price
}
root . updateGasEthValue ( )
root . checkLimits ( )
2021-07-05 12:34:56 +00:00
}
}
2020-08-13 07:27:53 +00:00
}
2022-07-01 11:24:32 +00:00
2021-05-21 20:19:03 +00:00
GasSelectorButton {
2021-05-25 14:58:53 +00:00
id: optimalGasButton
2022-08-18 17:51:18 +00:00
objectName: "GasSelector_optimalGasButton"
2022-07-01 11:24:32 +00:00
primaryText: qsTr ( "Optimal" )
2021-06-22 17:17:37 +00:00
price: {
2022-05-19 08:53:57 +00:00
if ( ! root . suggestedFees . eip1559Enabled ) {
2021-07-05 12:34:56 +00:00
// Setting the gas price field here because the binding didn't work
2022-05-19 08:53:57 +00:00
inputGasPrice . text = root . suggestedFees . gasPrice
return root . suggestedFees . gasPrice
2021-07-05 12:34:56 +00:00
}
2022-03-23 08:32:25 +00:00
return formatDec ( root . suggestedFees . maxFeePerGasM , 6 )
2021-06-22 17:17:37 +00:00
}
2021-05-21 20:19:03 +00:00
gasLimit: inputGasLimit ? inputGasLimit.text : ""
getGasEthValue: root . getGasEthValue
getFiatValue: root . getFiatValue
defaultCurrency: root . defaultCurrency
2022-07-01 11:24:32 +00:00
onCheckedChanged: {
if ( checked ) {
if ( root . suggestedFees . eip1559Enabled ) {
inputPerGasTipLimit . text = formatDec ( root . suggestedFees . maxPriorityFeePerGas , 2 ) ;
inputGasPrice . text = formatDec ( root . suggestedFees . maxFeePerGasM , 2 ) ;
} else {
inputGasPrice . text = root . suggestedFees . gasPrice
}
root . updateGasEthValue ( )
root . checkLimits ( )
2021-07-05 12:34:56 +00:00
}
}
2020-08-13 07:27:53 +00:00
}
2021-05-21 20:19:03 +00:00
GasSelectorButton {
2022-05-19 08:53:57 +00:00
id: highGasButton
2022-08-18 17:51:18 +00:00
objectName: "GasSelector_highGasButton"
2022-07-01 11:24:32 +00:00
primaryText: qsTr ( "High" )
2021-07-05 12:34:56 +00:00
price: {
2022-05-19 08:53:57 +00:00
if ( ! root . suggestedFees . eip1559Enabled ) return root . suggestedFees . gasPrice ;
2022-03-23 08:32:25 +00:00
return formatDec ( root . suggestedFees . maxFeePerGasH , 6 ) ;
2021-07-05 12:34:56 +00:00
}
2021-05-21 20:19:03 +00:00
gasLimit: inputGasLimit ? inputGasLimit.text : ""
getGasEthValue: root . getGasEthValue
getFiatValue: root . getFiatValue
defaultCurrency: root . defaultCurrency
2022-07-01 11:24:32 +00:00
onCheckedChanged: {
if ( checked ) {
if ( root . suggestedFees . eip1559Enabled ) {
inputPerGasTipLimit . text = formatDec ( root . suggestedFees . maxPriorityFeePerGas , 2 ) ;
inputGasPrice . text = formatDec ( root . suggestedFees . maxFeePerGasH , 2 ) ;
} else {
inputGasPrice . text = price
}
root . updateGasEthValue ( )
root . checkLimits ( )
2021-07-05 12:34:56 +00:00
}
}
2020-08-13 07:27:53 +00:00
}
}
2021-05-21 20:19:03 +00:00
Item {
id: advancedModeItemGroup
anchors.top: prioritytext . bottom
anchors.topMargin: 14
2022-05-19 08:53:57 +00:00
visible: ! root . suggestedFees . eip1559Enabled || root . advancedMode
2021-05-21 20:19:03 +00:00
width: parent . width
height: childrenRect . height
2020-08-20 04:45:29 +00:00
2021-05-21 20:19:03 +00:00
Input {
id: inputGasLimit
2022-04-04 11:26:30 +00:00
label: qsTr ( "Gas amount limit" )
2021-05-21 20:19:03 +00:00
text: "21000"
2021-07-05 12:34:56 +00:00
inputLabel.color: Style . current . secondaryText
2021-05-21 20:19:03 +00:00
customHeight: 56
anchors.top: parent . top
anchors.left: parent . left
2022-05-19 08:53:57 +00:00
anchors.right: root . suggestedFees . eip1559Enabled ? inputPerGasTipLimit.left : inputGasPrice . left
2021-05-21 20:19:03 +00:00
anchors.rightMargin: Style . current . padding
placeholderText: "21000"
2021-07-27 08:59:28 +00:00
validator: IntValidator {
bottom: 1
}
2021-05-21 20:19:03 +00:00
validationErrorAlignment: TextEdit . AlignRight
validationErrorTopMargin: 8
onTextChanged: {
if ( root . validate ( ) ) {
root . updateGasEthValue ( )
2021-07-05 12:34:56 +00:00
root . checkLimits ( )
}
}
}
Input {
id: inputPerGasTipLimit
label: qsTr ( "Per-gas tip limit" )
inputLabel.color: Style . current . secondaryText
anchors.top: parent . top
anchors.right: inputGasPrice . left
anchors.rightMargin: Style . current . padding
2022-05-19 08:53:57 +00:00
visible: root . suggestedFees . eip1559Enabled
2021-07-05 12:34:56 +00:00
width: 125
customHeight: 56
2022-03-23 08:32:25 +00:00
text: formatDec ( root . suggestedFees . maxPriorityFeePerGas , 2 ) ;
2021-07-05 12:34:56 +00:00
placeholderText: "20"
onTextChanged: {
if ( root . validate ( ) ) {
root . updateGasEthValue ( )
root . checkLimits ( )
2021-05-21 20:19:03 +00:00
}
2020-08-20 04:45:29 +00:00
}
}
2020-08-13 07:27:53 +00:00
2021-07-05 12:34:56 +00:00
StyledText {
color: Style . current . secondaryText
2022-04-04 11:26:30 +00:00
text: qsTr ( "Gwei" )
2022-05-19 08:53:57 +00:00
visible: root . suggestedFees . eip1559Enabled
2021-07-05 12:34:56 +00:00
anchors.top: parent . top
anchors.topMargin: 42
anchors.right: inputPerGasTipLimit . right
anchors.rightMargin: Style . current . padding
font.pixelSize: 15
}
2020-08-13 07:27:53 +00:00
Input {
2021-05-21 20:19:03 +00:00
id: inputGasPrice
2022-08-18 17:51:18 +00:00
textField.objectName: "gasPriceSelectorInput"
2022-04-04 11:26:30 +00:00
label: qsTr ( "Per-gas overall limit" )
2021-07-05 12:34:56 +00:00
inputLabel.color: Style . current . secondaryText
2021-05-21 20:19:03 +00:00
anchors.top: parent . top
anchors.right: parent . right
2021-07-05 12:34:56 +00:00
width: 125
2021-05-21 20:19:03 +00:00
customHeight: 56
placeholderText: "20"
onTextChanged: {
if ( root . validate ( ) ) {
root . updateGasEthValue ( )
2021-07-05 12:34:56 +00:00
root . checkLimits ( )
2021-05-21 20:19:03 +00:00
}
}
2020-08-13 07:27:53 +00:00
}
2021-05-21 20:19:03 +00:00
StyledText {
color: Style . current . secondaryText
2022-04-04 11:26:30 +00:00
text: qsTr ( "Gwei" )
2020-08-13 07:27:53 +00:00
anchors.top: parent . top
anchors.topMargin: 42
2021-05-21 20:19:03 +00:00
anchors.right: inputGasPrice . right
2020-08-13 07:27:53 +00:00
anchors.rightMargin: Style . current . padding
font.pixelSize: 15
}
2021-07-05 12:34:56 +00:00
StyledText {
id: errorsText
text: ""
width: parent . width - Style . current . padding
visible: text != ""
height: visible ? undefined : 0
anchors.top: inputGasLimit . bottom
anchors.topMargin: Style . current . smallPadding + 5
font.pixelSize: 13
textFormat: Text . RichText
color: Style . current . secondaryText
wrapMode: Text . WordWrap
}
2020-08-13 07:27:53 +00:00
StyledText {
2021-05-21 20:19:03 +00:00
id: maxPriorityFeeText
2021-07-05 12:34:56 +00:00
anchors.left: parent . left
2022-05-19 08:53:57 +00:00
visible: root . suggestedFees . eip1559Enabled
2021-07-05 12:34:56 +00:00
text: {
2022-02-09 09:43:23 +00:00
let v = selectedGasEthValue > 0.00009 ? selectedGasEthValue :
2021-07-05 12:34:56 +00:00
( selectedGasEthValue < 0.000001 ? "0.000000..." : selectedGasEthValue . toFixed ( 6 ) )
2022-04-04 11:26:30 +00:00
return qsTr ( "Maximum priority fee: %1 ETH" ) . arg ( v )
2021-07-05 12:34:56 +00:00
}
anchors.top: errorsText . bottom
anchors.topMargin: Style . current . smallPadding + 5
2020-08-13 07:27:53 +00:00
font.pixelSize: 13
2021-07-05 12:34:56 +00:00
color: Style . current . textColor
2021-05-21 20:19:03 +00:00
}
StyledText {
id: maxPriorityFeeFiatText
2022-03-18 14:47:51 +00:00
text: root . maxFiatFees
2022-05-19 08:53:57 +00:00
visible: root . suggestedFees . eip1559Enabled
2021-05-21 20:19:03 +00:00
anchors.verticalCenter: maxPriorityFeeText . verticalCenter
anchors.left: maxPriorityFeeText . right
anchors.leftMargin: 6
2020-08-13 07:27:53 +00:00
color: Style . current . secondaryText
2021-05-21 20:19:03 +00:00
anchors.topMargin: 19
font.pixelSize: 13
2020-08-13 07:27:53 +00:00
}
2021-05-21 20:19:03 +00:00
StyledText {
id: maxPriorityFeeDetailsText
2022-04-04 11:26:30 +00:00
text: qsTr ( "Maximum overall price for the transaction. If the block base fee exceeds this, it will be included in a following block with a lower base fee." )
2022-05-19 08:53:57 +00:00
visible: root . suggestedFees . eip1559Enabled
2021-05-21 20:19:03 +00:00
width: parent . width
anchors.top: maxPriorityFeeText . bottom
anchors.topMargin: Style . current . smallPadding
font.pixelSize: 13
color: Style . current . secondaryText
wrapMode: Text . WordWrap
2020-08-13 07:27:53 +00:00
}
}
}