This commit is contained in:
Richard Ramos 2021-07-05 08:34:56 -04:00 committed by Iuri Matias
parent daa0865885
commit 285f54dab6
25 changed files with 830 additions and 141 deletions

View File

@ -118,15 +118,17 @@ QtObject:
let estimateResult = Json.decode(estimateJson, tuple[estimate: int, uuid: string])
self.gasEstimateReturned(estimateResult.estimate, estimateResult.uuid)
proc buy*(self: StickersView, packId: int, address: string, price: string, gas: string, gasPrice: string, password: string): string {.slot.} =
proc buy*(self: StickersView, packId: int, address: string, price: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): string {.slot.} =
let eip1559Enabled = self.status.wallet.isEIP1559Enabled()
try:
validateTransactionInput(address, address, "", price, gas, gasPrice, "", "ok")
validateTransactionInput(address, address, "", price, gas, gasPrice, "", eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, "ok")
except Exception as e:
error "Error buying sticker pack", msg = e.msg
return ""
var success: bool
let response = self.status.stickers.buyPack(packId, address, price, gas, gasPrice, password, success)
let response = self.status.stickers.buyPack(packId, address, price, gas, gasPrice, eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, password, success)
# TODO:
# check if response["error"] is not null and handle the error

View File

@ -243,10 +243,11 @@ QtObject:
if not success:
result = 380000
proc registerENS*(self: EnsManager, username: string, address: string, gas: string, gasPrice: string, password: string): string {.slot.} =
proc registerENS*(self: EnsManager, username: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): string {.slot.} =
let eip1559Enabled = self.status.wallet.isEIP1559Enabled()
var success: bool
let pubKey = self.status.settings.getSetting[:string](Setting.PublicKey, "0x0")
let response = registerUsername(username, pubKey, address, gas, gasPrice, password, success)
let response = registerUsername(username, pubKey, address, gas, gasPrice, eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, password, success)
result = $(%* { "result": %response, "success": %success })
if success:
@ -282,10 +283,11 @@ QtObject:
if not success:
result = 80000
proc setPubKey(self: EnsManager, username: string, address: string, gas: string, gasPrice: string, password: string): string {.slot.} =
proc setPubKey*(self: EnsManager, username: string, address: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string): string {.slot.} =
let eip1559Enabled = self.status.wallet.isEIP1559Enabled()
var success: bool
let pubKey = self.status.settings.getSetting[:string](Setting.PublicKey, "0x0")
let response = setPubKey(username, pubKey, address, gas, gasPrice, password, success)
let response = setPubKey(username, pubKey, address, gas, gasPrice, eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, password, success)
result = $(%* { "result": %response, "success": %success })
if success:
self.transactionWasSent(response)

View File

@ -60,6 +60,8 @@ proc init*(self: WalletController) =
for acc in data.accounts:
self.status.wallet.updateAccount(acc)
self.status.wallet.checkPendingTransactions(acc, data.blockNumber)
discard self.status.wallet.isEIP1559Enabled(data.blockNumber)
self.status.wallet.setLatestBaseFee(data.baseFeePerGas)
self.view.updateView()
# TODO: show notification
@ -85,5 +87,9 @@ proc init*(self: WalletController) =
let tx = TransactionMinedArgs(e)
self.view.transactionCompleted(tx.success, tx.transactionHash, tx.revertReason)
proc checkPendingTransactions*(self: WalletController) =
self.status.wallet.checkPendingTransactions() # TODO: consider doing this in a threadpool task
proc onLogin*(self: WalletController) =
let blockInfo = getLatestBlock()
self.status.wallet.checkPendingTransactions(blockInfo[0]) # TODO: consider doing this in a threadpool task
discard self.status.wallet.isEIP1559Enabled(blockInfo[0])
self.status.wallet.setLatestBaseFee(blockInfo[1])

View File

@ -99,6 +99,8 @@ QtObject:
read = getDappBrowserView
proc updateView*(self: WalletView) =
self.transactionsView.triggerEIP1559Check()
self.balanceView.setTotalFiatBalance(self.status.wallet.getTotalFiatBalance())
self.balanceView.totalFiatBalanceChanged()

View File

@ -1,9 +1,10 @@
import atomics, strformat, strutils, sequtils, json, std/wrapnils, parseUtils, chronicles, web3/[ethtypes, conversions], stint
import NimQml, json, sequtils, chronicles, strutils, strformat, json
import NimQml, json, sequtils, chronicles, strutils, strformat, json, math
import
status/[status, wallet, utils],
status/types/[gas_prediction]
status/types/[gas_prediction],
status/libstatus/wallet as status_wallet
import ../../../../app_service/[main]
import ../../../../app_service/tasks/[qt, threadpool]
@ -17,7 +18,10 @@ type
const getGasPredictionsTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let
arg = decode[GasPredictionsTaskArg](argEncoded)
output = %getGasPricePredictions()
response = status_wallet.getGasPrice().parseJson
var output = "0"
if response.hasKey("result"):
output = $fromHex(Stuint[256], response["result"].getStr)
arg.finish(output)
proc getGasPredictions[T](self: T, slot: string) =
@ -35,10 +39,7 @@ QtObject:
type GasView* = ref object of QObject
status: Status
appService: AppService
safeLowGasPrice: string
standardGasPrice: string
fastGasPrice: string
fastestGasPrice: string
gasPrice: string
defaultGasLimit: string
proc setup(self: GasView) = self.QObject.setup
@ -48,10 +49,7 @@ QtObject:
new(result, delete)
result.status = status
result.appService = appService
result.safeLowGasPrice = "0"
result.standardGasPrice = "0"
result.fastGasPrice = "0"
result.fastestGasPrice = "0"
result.gasPrice = "0"
result.defaultGasLimit = "21000"
result.setup
@ -89,39 +87,69 @@ QtObject:
else:
result = $(%* { "result": "-1", "success": %success, "error": { "message": %response } })
proc gasPricePredictionsChanged*(self: GasView) {.signal.}
proc gasPriceChanged*(self: GasView) {.signal.}
proc getGasPricePredictions*(self: GasView) {.slot.} =
self.getGasPredictions("getGasPricePredictionsResult")
proc getGasPrice*(self: GasView) {.slot.} =
if not self.status.wallet.isEIP1559Enabled():
self.getGasPredictions("getGasPriceResult")
proc getGasPricePredictionsResult(self: GasView, gasPricePredictionsJson: string) {.slot.} =
let prediction = Json.decode(gasPricePredictionsJson, GasPricePrediction)
self.safeLowGasPrice = fmt"{prediction.safeLow:.3f}"
self.standardGasPrice = fmt"{prediction.standard:.3f}"
self.fastGasPrice = fmt"{prediction.fast:.3f}"
self.fastestGasPrice = fmt"{prediction.fastest:.3f}"
self.gasPricePredictionsChanged()
proc getGasPriceResult(self: GasView, gasPrice: string) {.slot.} =
let p = parseFloat(wei2gwei(gasPrice))
self.gasPrice = fmt"{p:.3f}"
self.gasPriceChanged()
proc safeLowGasPrice*(self: GasView): string {.slot.} = result = ?.self.safeLowGasPrice
QtProperty[string] safeLowGasPrice:
read = safeLowGasPrice
notify = gasPricePredictionsChanged
proc standardGasPrice*(self: GasView): string {.slot.} = result = ?.self.standardGasPrice
QtProperty[string] standardGasPrice:
read = standardGasPrice
notify = gasPricePredictionsChanged
proc fastGasPrice*(self: GasView): string {.slot.} = result = ?.self.fastGasPrice
QtProperty[string] fastGasPrice:
read = fastGasPrice
notify = gasPricePredictionsChanged
proc fastestGasPrice*(self: GasView): string {.slot.} = result = ?.self.fastestGasPrice
QtProperty[string] fastestGasPrice:
read = fastestGasPrice
notify = gasPricePredictionsChanged
proc gasPrice*(self: GasView): string {.slot.} = result = ?.self.gasPrice
QtProperty[string] gasPrice:
read = gasPrice
notify = gasPriceChanged
proc defaultGasLimit*(self: GasView): string {.slot.} = result = ?.self.defaultGasLimit
QtProperty[string] defaultGasLimit:
read = defaultGasLimit
proc maxPriorityFeePerGas*(self: GasView): string {.slot.} =
result = self.status.wallet.maxPriorityFeePerGas()
debug "Max priority fee per gas", value=result
proc suggestedFees*(self: GasView): string {.slot.} =
#[
0. priority tip always same, the value returned by eth_maxPriorityFeePerGas
1. slow fee 10th percentile base fee (last 100 blocks) + eth_maxPriorityFeePerGas
2. normal fee.
if 20th_percentile <= current_base_fee <= 80th_percentile then fee = current_base_fee + eth_maxPriorityFeePerGas.
if current_base_fee < 20th_percentile then fee = 20th_percentile + eth_maxPriorityFeePerGas
if current_base_fee > 80th_percentile then fee = 80th_percentile + eth_maxPriorityFeePerGas
The idea is to avoid setting too low base fee when price is in a dip and also to avoid overpaying on peak. Specific percentiles can be revisit later, it doesn't need to be symmetric because we are mostly interested in not getting stuck and overpaying might not be a huge issue here.
3. fast fee: current_base_fee + eth_maxPriorityFeePerGas
]#
let maxPriorityFeePerGas = self.status.wallet.maxPriorityFeePerGas().u256
let feeHistory = self.status.wallet.feeHistory(101)
let baseFee = self.status.wallet.getLatestBaseFee().u256
let gasPrice = self.status.wallet.getGasPrice().u256
let perc10 = feeHistory[ceil(10/100 * feeHistory.len.float).int - 1]
let perc20 = feeHistory[ceil(20/100 * feeHistory.len.float).int - 1]
let perc80 = feeHistory[ceil(80/100 * feeHistory.len.float).int - 1]
let maxFeePerGasM = if baseFee >= perc20 and baseFee <= perc80:
baseFee + maxPriorityFeePerGas
elif baseFee < perc20:
perc20 + maxPriorityFeePerGas
else:
perc80 + maxPriorityFeePerGas
result = $(%* {
"gasPrice": $gasPrice,
"baseFee": parseFloat(wei2gwei($baseFee)),
"maxPriorityFeePerGas": parseFloat(wei2gwei($maxPriorityFeePerGas)),
"maxFeePerGasL": parseFloat(wei2gwei($(perc10 + maxPriorityFeePerGas))),
"maxFeePerGasM": parseFloat(wei2gwei($(maxFeePerGasM))),
"maxFeePerGasH": parseFloat(wei2gwei($(baseFee + maxPriorityFeePerGas)))
})
QtProperty[string] maxPriorityFeePerGas:
read = maxPriorityFeePerGas
QtProperty[string] suggestedFees:
read = suggestedFees

View File

@ -24,6 +24,9 @@ type
value: string
gas: string
gasPrice: string
isEIP1559Enabled: bool
maxPriorityFeePerGas: string
maxFeePerGas: string
password: string
uuid: string
WatchTransactionTaskArg = ref object of QObjectTaskArg
@ -35,19 +38,20 @@ const sendTransactionTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
success: bool
response: string
if arg.assetAddress != ZERO_ADDRESS and not arg.assetAddress.isEmptyOrWhitespace:
response = wallet.sendTokenTransaction(arg.from_addr, arg.to, arg.assetAddress, arg.value, arg.gas, arg.gasPrice, arg.password, success)
response = wallet.sendTokenTransaction(arg.from_addr, arg.to, arg.assetAddress, arg.value, arg.gas, arg.gasPrice, arg.isEIP1559Enabled, arg.maxPriorityFeePerGas, arg.maxFeePerGas, arg.password, success)
else:
response = wallet.sendTransaction(arg.from_addr, arg.to, arg.value, arg.gas, arg.gasPrice, arg.password, success)
response = wallet.sendTransaction(arg.from_addr, arg.to, arg.value, arg.gas, arg.gasPrice, arg.isEIP1559Enabled, arg.maxPriorityFeePerGas, arg.maxFeePerGas, arg.password, success)
let output = %* { "result": %response, "success": %success, "uuid": %arg.uuid }
arg.finish(output)
proc sendTransaction[T](self: T, slot: string, from_addr: string, to: string, assetAddress: string, value: string, gas: string, gasPrice: string, password: string, uuid: string) =
proc sendTransaction[T](self: T, slot: string, from_addr: string, to: string, assetAddress: string, value: string, gas: string, gasPrice: string, isEIP1559Enabled: bool, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, uuid: string) =
let arg = SendTransactionTaskArg(
tptr: cast[ByteAddress](sendTransactionTask),
vptr: cast[ByteAddress](self.vptr),
slot: slot, from_addr: from_addr, to: to,
assetAddress: assetAddress, value: value, gas: gas,
gasPrice: gasPrice, password: password, uuid: uuid
gasPrice: gasPrice, password: password, uuid: uuid,
isEIP1559Enabled: isEIP1559Enabled, maxPriorityFeePerGas: maxPriorityFeePerGas, maxFeePerGas: maxFeePerGas
)
self.appService.threadpool.start(arg)
@ -110,23 +114,24 @@ QtObject:
if txHash != "":
self.watchTransaction("transactionWatchResultReceived", txHash)
proc sendTransaction*(self: TransactionsView, from_addr: string, to: string, assetAddress: string, value: string, gas: string, gasPrice: string, password: string, uuid: string) {.slot.} =
self.sendTransaction("transactionSent", from_addr, to, assetAddress, value, gas, gasPrice, password, uuid)
proc sendTransaction*(self: TransactionsView, from_addr: string, to: string, assetAddress: string, value: string, gas: string, gasPrice: string,eip1559Enabled: bool, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, uuid: string) {.slot.} =
self.sendTransaction("transactionSent", from_addr, to, assetAddress, value, gas, gasPrice, eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, password, uuid)
proc transferEth*(self: TransactionsView, from_addr: string, to_addr: string, value: string, gas: string, gasPrice: string, password: string, uuid: string): bool {.slot.} =
proc transferEth*(self: TransactionsView, from_addr: string, to_addr: string, value: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, uuid: string): bool {.slot.} =
try:
validateTransactionInput(from_addr, to_addr, "", value, gas, gasPrice, "", uuid)
self.sendTransaction("transactionSent", from_addr, to_addr, ZERO_ADDRESS, value, gas, gasPrice, password, uuid)
let eip1559Enabled = self.status.wallet.isEIP1559Enabled()
validateTransactionInput(from_addr, to_addr, "", value, gas, gasPrice, "", eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, uuid)
self.sendTransaction("transactionSent", from_addr, to_addr, ZERO_ADDRESS, value, gas, gasPrice, eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, password, uuid)
except Exception as e:
error "Error sending eth transfer transaction", msg = e.msg
return false
return true
proc transferTokens*(self: TransactionsView, from_addr: string, to_addr: string, assetAddress: string, value: string, gas: string, gasPrice: string, password: string, uuid: string): bool {.slot.} =
proc transferTokens*(self: TransactionsView, from_addr: string, to_addr: string, assetAddress: string, value: string, gas: string, gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string, uuid: string): bool {.slot.} =
try:
validateTransactionInput(from_addr, to_addr, assetAddress, value, gas, gasPrice, "", uuid)
self.sendTransaction("transactionSent", from_addr, to_addr, assetAddress, value, gas, gasPrice, password, uuid)
let eip1559Enabled = self.status.wallet.isEIP1559Enabled()
validateTransactionInput(from_addr, to_addr, assetAddress, value, gas, gasPrice, "", eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, uuid)
self.sendTransaction("transactionSent", from_addr, to_addr, assetAddress, value, gas, gasPrice, eip1559Enabled, maxPriorityFeePerGas, maxFeePerGas, password, uuid)
except Exception as e:
error "Error sending token transfer transaction", msg = e.msg
return false
@ -146,3 +151,26 @@ QtObject:
discard #TODO: Ask Simon if should we show an error popup indicating the trx wasn't mined in 10m or something
proc transactionCompleted*(self: TransactionsView, success: bool, txHash: string, revertReason: string = "") {.signal.}
proc triggerEIP1559Check*(self: TransactionsView) {.signal.}
proc isEIP1559Enabled(self: TransactionsView): bool {.slot.} =
return self.status.wallet.isEIP1559Enabled()
proc getLatestBaseFee(self: TransactionsView): string {.slot.} =
var baseFeeWei:string = self.status.wallet.getLatestBaseFee()
var baseFeeGwei:string = wei2Gwei(baseFeeWei)
var unit:string = "wei"
var amount = baseFeeWei
if parseFloat(baseFeeGwei) > 1:
unit = "gwei"
amount = baseFeeGwei
return $(%*{"gwei": baseFeeGwei, "amount": amount, "unit": unit})
QtProperty[bool] isEIP1559Enabled:
read = isEIP1559Enabled
notify = triggerEIP1559Check
QtProperty[string] latestBaseFee:
read = getLatestBaseFee
notify = triggerEIP1559Check

View File

@ -198,7 +198,8 @@ proc mainProc() =
utilsController.init()
browserController.init()
node.init()
wallet.checkPendingTransactions()
wallet.onLogin()
# this should be the last defer in the scope
defer:

View File

@ -77,7 +77,7 @@ Rectangle {
}
// 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: SignTransactionModal {}
property Component signMessageModalComponent: SignMessageModal {}
@ -190,9 +190,11 @@ property Component sendTransactionModalComponent: SignTransactionModal {}
});
// TODO change sendTransaction function to the postMessage one
sendDialog.sendTransaction = function (selectedGasLimit, selectedGasPrice, enteredPassword) {
sendDialog.sendTransaction = function (selectedGasLimit, selectedGasPrice, selectedTipLimit, selectedOverallLimit, enteredPassword) {
request.payload.selectedGasLimit = selectedGasLimit
request.payload.selectedGasPrice = selectedGasPrice
request.payload.selectedTipLimit = selectedTipLimit
request.payload.selectedOverallLimit = selectedOverallLimit
request.payload.password = enteredPassword
request.payload.params[0].value = value
@ -229,7 +231,7 @@ property Component sendTransactionModalComponent: SignTransactionModal {}
}
sendDialog.open();
walletModel.gasView.getGasPricePredictions()
walletModel.gasView.getGasPrice()
} else if (request.type === Constants.web3SendAsyncReadOnly && ["eth_sign", "personal_sign", "eth_signTypedData", "eth_signTypedData_v3"].indexOf(request.payload.method) > -1) {
const signDialog = signMessageModalComponent.createObject(browserWindow, {
request,
@ -516,6 +518,7 @@ property Component sendTransactionModalComponent: SignTransactionModal {}
anchors.top: parent.top
anchors.topMargin: browserHeader.height
focus: true
url: "https://dap.ps"
webChannel: channel
onLinkHovered: function(hoveredUrl) {
if (hoveredUrl === "")

View File

@ -498,7 +498,7 @@ Item {
SendModal {
id: sendTransactionWithEns
onOpened: {
walletModel.gasView.getGasPricePredictions()
walletModel.gasView.getGasPrice()
}
onClosed: {
txModalLoader.closed()
@ -622,8 +622,8 @@ Item {
Connections {
target: chatsModel.stickers
onTransactionWasSent: {
//% "Transaction pending"
toastMessage.title = qsTrId("transaction-pending")
//% "Transaction pending..."
toastMessage.title = qsTr("Transaction pending...")
toastMessage.source = "../../../img/loading.svg"
toastMessage.iconColor = Style.current.primary
toastMessage.iconRotates = true

View File

@ -5,6 +5,7 @@ import QtQuick.Dialogs 1.3
import "../../../../../imports"
import "../../../../../shared"
import "../../../../../shared/status"
import "../../../Wallet/"
ModalPopup {
property var selectedAccount
@ -18,7 +19,7 @@ ModalPopup {
property alias transactionSigner: transactionSigner
property var sendTransaction: function(selectedGasLimit, selectedGasPrice, enteredPassword) {
property var sendTransaction: function(selectedGasLimit, selectedGasPrice, selectedTipLimit, selectedOveralLimit, enteredPassword) {
let success = false
if(root.selectedAsset.address == Constants.zeroAddress){
success = walletModel.transactionsView.transferEth(
@ -26,7 +27,9 @@ ModalPopup {
selectRecipient.selectedRecipient.address,
root.selectedAmount,
selectedGasLimit,
selectedGasPrice,
gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
enteredPassword,
stack.uuid)
} else {
@ -36,7 +39,9 @@ ModalPopup {
root.selectedAsset.address,
root.selectedAmount,
selectedGasLimit,
selectedGasPrice,
gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
enteredPassword,
stack.uuid)
}
@ -52,7 +57,7 @@ ModalPopup {
//% "Send"
title: qsTrId("command-button-send")
height: 504
height: 540
property MessageDialog sendingError: MessageDialog {
id: sendingError
@ -60,7 +65,6 @@ ModalPopup {
title: qsTrId("error-sending-the-transaction")
icon: StandardIcon.Critical
standardButtons: StandardButton.Ok
onAccepted: root.close()
}
onClosed: {
@ -122,8 +126,7 @@ ModalPopup {
id: groupSelectGas
//% "Network fee"
headerText: qsTrId("network-fee")
//% "Preview"
footerText: qsTrId("preview")
footerText: qsTr("Continue")
showNextBtn: false
onBackClicked: function() {
stack.pop()
@ -131,8 +134,7 @@ ModalPopup {
GasSelector {
id: gasSelector
anchors.topMargin: Style.current.bigPadding
slowestGasPrice: parseFloat(walletModel.gasView.safeLowGasPrice)
fastestGasPrice: parseFloat(walletModel.gasView.fastestGasPrice)
gasPrice: parseFloat(walletModel.gasView.gasPrice)
getGasEthValue: walletModel.gasView.getGasEthValue
getFiatValue: walletModel.balanceView.getFiatValue
defaultCurrency: walletModel.balanceView.defaultCurrency
@ -144,6 +146,7 @@ ModalPopup {
root.selectedAsset && root.selectedAsset.address &&
root.selectedAmount)) {
selectedGasLimit = 250000
defaultGasLimit = selectedGasLimit
return
}
@ -164,6 +167,7 @@ ModalPopup {
return
}
selectedGasLimit = gasEstimate.result
defaultGasLimit = selectedGasLimit
})
}
GasValidator {
@ -267,6 +271,14 @@ ModalPopup {
stack.back()
}
}
Component {
id: transactionSettingsConfirmationPopupComponent
TransactionSettingsConfirmationPopup {
}
}
StatusButton {
id: btnNext
anchors.right: parent.right
@ -279,9 +291,33 @@ ModalPopup {
if (validity.isValid && !validity.isPending) {
if (stack.isLastGroup) {
return root.sendTransaction(gasSelector.selectedGasLimit,
gasSelector.selectedGasPrice,
gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
transactionSigner.enteredPassword)
}
if(gasSelector.eip1599Enabled && stack.currentGroup === groupSelectGas && gasSelector.advancedMode){
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
openPopup(transactionSettingsConfirmationPopupComponent, {
currentBaseFee: gasSelector.latestBaseFeeGwei,
currentMinimumTip: gasSelector.perGasTipLimitFloor,
currentAverageTip: gasSelector.perGasTipLimitAverage,
tipLimit: gasSelector.selectedTipLimit,
suggestedTipLimit: gasSelector.perGasTipLimitFloor, // TODO:
priceLimit: gasSelector.selectedOverallLimit,
suggestedPriceLimit: gasSelector.latestBaseFeeGwei + gasSelector.perGasTipLimitFloor,
showPriceLimitWarning: gasSelector.showPriceLimitWarning,
showTipLimitWarning: gasSelector.showTipLimitWarning,
onConfirm: function(){
stack.next();
}
})
return
}
}
if (typeof stack.currentGroup.onNextClicked === "function") {
return stack.currentGroup.onNextClicked()
}

View File

@ -89,7 +89,7 @@ Item {
id: signTxComponent
SignTransactionModal {
onOpened: {
walletModel.gasView.getGasPricePredictions()
walletModel.gasView.getGasPrice()
}
onClosed: {
destroy();

View File

@ -46,7 +46,7 @@ Item {
id: signTxComponent
SignTransactionModal {
onOpened: {
walletModel.gasView.getGasPricePredictions()
walletModel.gasView.getGasPrice()
}
onClosed: {
destroy();

View File

@ -51,7 +51,7 @@ Item {
id: transactionDialogComponent
StatusETHTransactionModal {
onOpened: {
walletModel.gasView.getGasPricePredictions()
walletModel.gasView.getGasPrice()
}
title: qsTr("Connect username with your pubkey")
onClosed: {

View File

@ -39,10 +39,12 @@ Item {
if (username === "" || !selectedAccount) return 380000;
return profileModel.ens.registerENSGasEstimate(username, selectedAccount.address)
}
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, password) {
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, tipLimit, overallLimit, password) {
return profileModel.ens.registerENS(username,
selectedAddress,
gasLimit,
tipLimit,
overallLimit,
gasPrice,
password)
}

View File

@ -34,7 +34,9 @@ ModalPopup {
selectRecipient.selectedRecipient.address,
txtAmount.selectedAmount,
gasSelector.selectedGasLimit,
gasSelector.selectedGasPrice,
gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
transactionSigner.enteredPassword,
stack.uuid)
} else {
@ -44,7 +46,9 @@ ModalPopup {
txtAmount.selectedAsset.address,
txtAmount.selectedAmount,
gasSelector.selectedGasLimit,
gasSelector.selectedGasPrice,
gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
transactionSigner.enteredPassword,
stack.uuid)
}
@ -53,7 +57,6 @@ ModalPopup {
//% "Invalid transaction parameters"
sendingError.text = qsTrId("invalid-transaction-parameters")
sendingError.open()
root.close()
}
}
@ -111,7 +114,7 @@ ModalPopup {
//% "Send"
headerText: qsTrId("command-button-send")
//% "Preview"
footerText: qsTrId("preview")
footerText: qsTr("Continue")
AssetAndAmountInput {
id: txtAmount
@ -127,11 +130,11 @@ ModalPopup {
id: gasSelector
anchors.top: txtAmount.bottom
anchors.topMargin: Style.current.bigPadding * 2
slowestGasPrice: parseFloat(walletModel.gasView.safeLowGasPrice)
fastestGasPrice: parseFloat(walletModel.gasView.fastestGasPrice)
gasPrice: parseFloat(walletModel.gasView.gasPrice)
getGasEthValue: walletModel.gasView.getGasEthValue
getFiatValue: walletModel.balanceView.getFiatValue
defaultCurrency: walletModel.balanceView.defaultCurrency
width: stack.width
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
if (!(selectFromAccount.selectedAccount && selectFromAccount.selectedAccount.address &&
@ -151,7 +154,9 @@ ModalPopup {
console.warn(qsTrId("error-estimating-gas---1").arg(gasEstimate.error.message))
return
}
selectedGasLimit = gasEstimate.result
defaultGasLimit = selectedGasLimit
})
}
GasValidator {
@ -222,6 +227,14 @@ ModalPopup {
stack.back()
}
}
Component {
id: transactionSettingsConfirmationPopupComponent
TransactionSettingsConfirmationPopup {
}
}
StatusButton {
id: btnNext
anchors.right: parent.right
@ -235,6 +248,27 @@ ModalPopup {
if (stack.isLastGroup) {
return root.sendTransaction()
}
if(gasSelector.eip1599Enabled && stack.currentGroup === group2 && gasSelector.advancedMode){
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
openPopup(transactionSettingsConfirmationPopupComponent, {
currentBaseFee: gasSelector.latestBaseFeeGwei,
currentMinimumTip: gasSelector.perGasTipLimitFloor,
currentAverageTip: gasSelector.perGasTipLimitAverage,
tipLimit: gasSelector.selectedTipLimit,
suggestedTipLimit: gasSelector.perGasTipLimitFloor,
priceLimit: gasSelector.selectedOverallLimit,
suggestedPriceLimit: gasSelector.latestBaseFeeGwei + gasSelector.perGasTipLimitFloor,
showPriceLimitWarning: gasSelector.showPriceLimitWarning,
showTipLimitWarning: gasSelector.showTipLimitWarning,
onConfirm: function(){
stack.next();
}
})
return
}
}
stack.next()
}
}

View File

@ -0,0 +1,258 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import "../../../imports"
import "../../../shared/status"
import "../../../shared"
ModalPopup {
id: popup
height: 300 + (showPriceLimitWarning ? 65 : 0) + (showTipLimitWarning ? 65 : 0)
width: 400
title: qsTr("Are you sure?")
property var onConfirm: function(){}
property double currentBaseFee: 0
property double currentMinimumTip: 0
property double currentAverageTip: 0
property double tipLimit: 0
property double suggestedTipLimit: 0
property double priceLimit: 0
property double suggestedPriceLimit: 0
property bool showPriceLimitWarning: false
property bool showTipLimitWarning: false
Column {
id: content
width: 450
height: parent.height
spacing: 10
StyledText {
anchors.left: parent.left
anchors.leftMargin: Style.current.smallPadding
text: qsTr("Your priority fee is below our suggested parameters.")
font.pixelSize: 13
wrapMode: Text.WordWrap
color: Style.current.secondaryText
}
Item {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.smallPadding
height: 20
StyledText {
text: qsTr("Current base fee")
font.pixelSize: 13
width: 190
anchors.left: parent.left
}
StyledText {
text: qsTr("%1 Gwei").arg(currentBaseFee)
font.pixelSize: 13
width: 190
anchors.right: parent.right
}
}
Item {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.smallPadding
height: 20
StyledText {
text: qsTr("Current minimum tip")
font.pixelSize: 13
width: 190
anchors.left: parent.left
}
StyledText {
text: qsTr("%1 Gwei").arg(currentMinimumTip)
font.pixelSize: 13
width: 190
anchors.right: parent.right
}
}
Item {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.smallPadding
height: 20
StyledText {
text: qsTr("Current average tip")
font.pixelSize: 13
width: 190
anchors.left: parent.left
}
StyledText {
text: qsTr("%1 Gwei").arg(currentAverageTip)
font.pixelSize: 13
width: 190
anchors.right: parent.right
}
}
Rectangle {
id: tipLimitRect
width: 368
visible: showTipLimitWarning
height: visible ? 70 : 0
radius: 8
color: Style.current.backgroundHoverLight
Column {
anchors.top: parent.top
anchors.topMargin: Style.current.smallPadding
anchors.left: parent.left
anchors.leftMargin: Style.current.smallPadding
height: 100
width: 450 - Style.current.smallPadding
spacing: 10
Item {
anchors.left: parent.left
anchors.right: parent.right
height: 20
StyledText {
text: qsTr("Your tip limit")
font.pixelSize: 13
width: 190
anchors.left: parent.left
color: Style.current.red
}
StyledText {
text: qsTr("%1 Gwei").arg(tipLimit)
font.pixelSize: 13
width: 190
anchors.right: parent.right
color: Style.current.red
}
}
Item {
anchors.left: parent.left
anchors.right: parent.right
height: 20
StyledText {
text: qsTr("Suggested minimum tip")
font.pixelSize: 13
width: 190
anchors.left: parent.left
}
StyledText {
text: qsTr("%1 Gwei").arg(suggestedTipLimit)
font.pixelSize: 13
width: 190
anchors.right: parent.right
}
}
}
}
Rectangle {
id: minPriceLimitRect
width: 368
visible: showPriceLimitWarning
height: visible ? 70 : 0
radius: 8
color: Style.current.backgroundHoverLight
Column {
anchors.top: parent.top
anchors.topMargin: Style.current.smallPadding
anchors.left: parent.left
anchors.leftMargin: Style.current.smallPadding
height: 100
width: 450 - Style.current.smallPadding
spacing: 10
Item {
anchors.left: parent.left
anchors.right: parent.right
height: 20
StyledText {
text: qsTr("Your price limit")
font.pixelSize: 13
width: 190
anchors.left: parent.left
color: Style.current.red
}
StyledText {
text: qsTr("%1 Gwei").arg(priceLimit)
font.pixelSize: 13
width: 190
anchors.right: parent.right
color: Style.current.red
}
}
Item {
anchors.left: parent.left
anchors.right: parent.right
height: 20
StyledText {
text: qsTr("Suggested minimum price limit")
font.pixelSize: 13
width: 190
anchors.left: parent.left
}
StyledText {
text: qsTr("%1 Gwei").arg(suggestedPriceLimit)
font.pixelSize: 13
width: 190
anchors.right: parent.right
}
}
}
}
}
footer: Item {
id: footerContainer
width: parent.width
StatusButton {
id: cancelButton
anchors.right: confirmButton.left
anchors.rightMargin: Style.current.smallPadding
text: qsTr("Change Limit")
anchors.bottom: parent.bottom
onClicked: popup.destroy()
}
StatusButton {
id: confirmButton
type: "warn"
anchors.right: parent.right
anchors.rightMargin: Style.current.smallPadding
text: qsTr("Continue anyway")
anchors.bottom: parent.bottom
onClicked: {
popup.onConfirm();
popup.destroy();
}
}
}
}

View File

@ -743,16 +743,15 @@ Item {
}
}
ToastMessage {
id: toastMessage
}
// Add SendModal here as it is used by the Wallet as well as the Browser
Loader {
id: sendModal
active: false
function open() {
this.active = true
this.item.open()
@ -763,7 +762,7 @@ Item {
}
sourceComponent: SendModal {
onOpened: {
walletModel.gasView.getGasPricePredictions()
walletModel.gasView.getGasPrice()
}
onClosed: {
sendModal.closed()

View File

@ -11,14 +11,30 @@ Item {
height: Style.current.smallPadding + prioritytext.height +
(advancedMode ? advancedModeItemGroup.height : selectorButtons.height)
property double slowestGasPrice: 0
property double fastestGasPrice: 100
property double stepSize: ((root.fastestGasPrice - root.slowestGasPrice) / 10).toFixed(1)
property double gasPrice: 0
property bool eip1599Enabled: walletModel.transactionsView.isEIP1559Enabled
property var suggestedFees: JSON.parse(walletModel.gasView.suggestedFees)
property var latestBaseFee: JSON.parse(walletModel.transactionsView.latestBaseFee)
property double latestBaseFeeGwei: {
if (!eip1599Enabled) return 0;
return parseFloat(latestBaseFee.gwei)
}
property var getGasGweiValue: function () {}
property var getGasEthValue: function () {}
property var getFiatValue: function () {}
property string defaultCurrency: "USD"
property alias selectedGasPrice: inputGasPrice.text
property alias selectedGasLimit: inputGasLimit.text
property string defaultGasLimit: "0"
property alias selectedTipLimit: inputPerGasTipLimit.text
property alias selectedOverallLimit: inputGasPrice.text
property double selectedGasEthValue
property double selectedGasFiatValue
//% "Must be greater than 0"
@ -30,13 +46,26 @@ Item {
property bool isValid: true
readonly property string uuid: Utils.uuid()
property bool advancedMode: false
property bool advancedMode: true // TODO: change to false once EIP1559 suggestions are revised
// TODO: change these values false once EIP1559 suggestions are revised
property double perGasTipLimitFloor: 1 // Matches status-react minimum-priority-fee
property double perGasTipLimitAverage: formatDec(suggestedFees.maxPriorityFeePerGas, 2) // 1.5 // Matches status-react average-priority-fee
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)
}
function updateGasEthValue() {
// causes error on application load without this null check
if (!inputGasPrice || !inputGasLimit) {
return
}
let ethValue = root.getGasEthValue(inputGasPrice.text, inputGasLimit.text)
let fiatValue = root.getFiatValue(ethValue, "ETH", root.defaultCurrency)
@ -44,39 +73,114 @@ Item {
selectedGasFiatValue = fiatValue
}
Component.onCompleted: updateGasEthValue()
function appendError(accum, error, nonBlocking = false) {
return accum + ` <span class="${nonBlocking ? "non-blocking" : ""}">${error}.</span>`
}
function checkLimits(){
if(!eip1599Enabled) return;
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 = "";
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)
}
// Per-gas overall limit rules
if(inputOverallLimit < latestBaseFeeGwei){
errorMsg = appendError(errorMsg, qsTr("The limit is below the current base fee of %1 %2").arg(latestBaseFeeGwei).arg("Gwei"))
showPriceLimitWarning = true
}
/* TODO: change these values false once EIP1559 suggestions are revised
else if((inputOverallLimit - inputTipLimit) < latestBaseFeeGwei){
errorMsg = appendError(errorMsg, qsTr("The limit should be at least %1 Gwei above the base fee").arg(perGasTipLimitFloor))
} else if((inputOverallLimit - perGasTipLimitAverage) < latestBaseFeeGwei) {
errorMsg = appendError(errorMsg, qsTr("The maximum miner tip after the current base fee will be %1 Gwei, the minimum miner tip is currently %2 Gwei").arg(inputOverallLimit).arg(perGasTipLimitFloor), true)
showTipLimitWarning = true
}*/
errorsText.text = `<style type="text/css">span { color: "#ff0000" } span.non-blocking { color: "#FE8F59" }</style>${errorMsg}`
}
Component.onCompleted: {
updateGasEthValue()
checkLimits()
}
function validate() {
// causes error on application load without a null check
if (!inputGasLimit || !inputGasPrice) {
if (!inputGasLimit || !inputGasPrice || !inputPerGasTipLimit) {
return
}
inputGasLimit.validationError = ""
inputGasPrice.validationError = ""
inputPerGasTipLimit.validationError = ""
const noInputLimit = inputGasLimit.text === ""
const noInputPrice = inputGasPrice.text === ""
const noPerGasTip = inputPerGasTipLimit.text === ""
if (noInputLimit) {
inputGasLimit.validationError = root.noInputErrorMessage
}
if (noInputPrice) {
inputGasPrice.validationError = root.noInputErrorMessage
}
if (noPerGasTip) {
inputPerGasTipLimit.validationError = root.noInputErrorMessage
}
if (isNaN(inputGasLimit.text)) {
inputGasLimit.validationError = invalidInputErrorMessage
}
if (isNaN(inputGasPrice.text)) {
inputGasPrice.validationError = invalidInputErrorMessage
}
if (isNaN(inputPerGasTipLimit.text)) {
inputPerGasTipLimit.validationError = invalidInputErrorMessage
}
let inputLimit = parseFloat(inputGasLimit.text || "0.00")
let inputPrice = parseFloat(inputGasPrice.text || "0.00")
if (inputLimit <= 0) {
let inputTipLimit = parseFloat(inputPerGasTipLimit.text || "0.00")
if (inputLimit <= 0.00) {
inputGasLimit.validationError = root.greaterThan0ErrorMessage
}
if (inputPrice <= 0) {
if (inputPrice <= 0.00) {
inputGasPrice.validationError = root.greaterThan0ErrorMessage
}
const isValid = inputGasLimit.validationError === "" && inputGasPrice.validationError === ""
return isValid
if (inputTipLimit <= 0.00) {
inputPerGasTipLimit.validationError = root.greaterThan0ErrorMessage
}
const isInputValid = inputGasLimit.validationError === "" && inputGasPrice.validationError === "" && inputPerGasTipLimit.validationError === ""
return isInputValid
}
@ -91,7 +195,20 @@ Item {
color: Style.current.textColor
}
StyledText {
id: baseFeeText
visible: eip1599Enabled && advancedMode
anchors.top: parent.top
anchors.left: prioritytext.right
anchors.leftMargin: Style.current.smallPadding
text: qsTr("Current base fee: %1 %2").arg(latestBaseFeeGwei).arg("Gwei")
font.weight: Font.Medium
font.pixelSize: 13
color: Style.current.secondaryText
}
StatusButton {
visible: false // Change to TRUE once EIP1559 suggestions are revised
id: buttonAdvanced
anchors.verticalCenter: prioritytext.verticalCenter
anchors.right: parent.right
@ -119,14 +236,25 @@ Item {
GasSelectorButton {
buttonGroup: gasGroup
//% "Low"
text: qsTrId("low")
price: slowestGasPrice
text: qsTr("Low")
price: {
if (!eip1599Enabled) return gasPrice;
return formatDec(suggestedFees.maxFeePerGasL, 6)
}
gasLimit: inputGasLimit ? inputGasLimit.text : ""
getGasEthValue: root.getGasEthValue
getFiatValue: root.getFiatValue
defaultCurrency: root.defaultCurrency
onChecked: inputGasPrice.text = price
onChecked: {
if (eip1599Enabled){
inputPerGasTipLimit.text = formatDec(suggestedFees.maxPriorityFeePerGas, 2);
inputGasPrice.text = formatDec(suggestedFees.maxFeePerGasL, 2);
} else {
inputGasPrice.text = price
}
root.updateGasEthValue()
root.checkLimits()
}
}
GasSelectorButton {
id: optimalGasButton
@ -135,28 +263,52 @@ Item {
//% "Optimal"
text: qsTrId("optimal")
price: {
const price = (fastestGasPrice + slowestGasPrice) / 2
// Setting the gas price field here because the binding didn't work
inputGasPrice.text = price
return price
if (!eip1599Enabled) {
const price = gasPrice
// Setting the gas price field here because the binding didn't work
inputGasPrice.text = price
return price
}
return formatDec(suggestedFees.maxFeePerGasM, 6)
}
gasLimit: inputGasLimit ? inputGasLimit.text : ""
getGasEthValue: root.getGasEthValue
getFiatValue: root.getFiatValue
defaultCurrency: root.defaultCurrency
onChecked: inputGasPrice.text = price
onChecked: {
if (eip1599Enabled){
inputPerGasTipLimit.text = formatDec(suggestedFees.maxPriorityFeePerGas, 2);
inputGasPrice.text = formatDec(suggestedFees.maxFeePerGasM, 2);
} else {
inputGasPrice.text = price
}
root.updateGasEthValue()
root.checkLimits()
}
}
GasSelectorButton {
buttonGroup: gasGroup
//% "High"
text: qsTrId("high")
price: fastestGasPrice
text: qsTr("High")
price: {
if (!eip1599Enabled) return gasPrice;
return formatDec(suggestedFees.maxFeePerGasH,6);
}
gasLimit: inputGasLimit ? inputGasLimit.text : ""
getGasEthValue: root.getGasEthValue
getFiatValue: root.getFiatValue
defaultCurrency: root.defaultCurrency
onChecked: inputGasPrice.text = price
onChecked: {
if (eip1599Enabled){
inputPerGasTipLimit.text = formatDec(suggestedFees.maxPriorityFeePerGas, 2);
inputGasPrice.text = formatDec(suggestedFees.maxFeePerGasH, 2);
} else {
inputGasPrice.text = price
}
root.updateGasEthValue()
root.checkLimits()
}
}
}
@ -173,10 +325,11 @@ Item {
//% "Gas amount limit"
label: qsTrId("gas-amount-limit")
text: "21000"
inputLabel.color: Style.current.secondaryText
customHeight: 56
anchors.top: parent.top
anchors.left: parent.left
anchors.right: inputGasPrice.left
anchors.right: eip1599Enabled ? inputPerGasTipLimit.left : inputGasPrice.left
anchors.rightMargin: Style.current.padding
placeholderText: "21000"
validator: IntValidator{
@ -187,23 +340,59 @@ Item {
onTextChanged: {
if (root.validate()) {
root.updateGasEthValue()
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
anchors.left: undefined
visible: eip1599Enabled
width: 125
customHeight: 56
text: formatDec(suggestedFees.maxPriorityFeePerGas, 2);
placeholderText: "20"
onTextChanged: {
if (root.validate()) {
root.updateGasEthValue()
root.checkLimits()
}
}
}
StyledText {
color: Style.current.secondaryText
//% "Gwei"
text: qsTrId("gwei")
visible: eip1599Enabled
anchors.top: parent.top
anchors.topMargin: 42
anchors.right: inputPerGasTipLimit.right
anchors.rightMargin: Style.current.padding
font.pixelSize: 15
}
Input {
id: inputGasPrice
//% "Per-gas overall limit"
label: qsTrId("per-gas-overall-limit")
inputLabel.color: Style.current.secondaryText
anchors.top: parent.top
anchors.left: undefined
anchors.right: parent.right
width: 130
width: 125
customHeight: 56
placeholderText: "20"
onTextChanged: {
if (root.validate()) {
root.updateGasEthValue()
root.checkLimits()
}
}
}
@ -220,17 +409,37 @@ Item {
}
StyledText {
id: maxPriorityFeeText
//% "Maximum priority fee: %1 ETH"
text: qsTrId("maximum-priority-fee---1-eth").arg(selectedGasEthValue)
id: errorsText
text: ""
width: parent.width - Style.current.padding
visible: text != ""
height: visible ? undefined : 0
anchors.top: inputGasLimit.bottom
anchors.topMargin: 19
anchors.topMargin: Style.current.smallPadding + 5
font.pixelSize: 13
textFormat: Text.RichText
color: Style.current.secondaryText
wrapMode: Text.WordWrap
}
StyledText {
id: maxPriorityFeeText
anchors.left: parent.left
//% "Maximum priority fee: %1 ETH"
text: {
let v = selectedGasEthValue > 0.00009 ? selectedGasEthValue :
(selectedGasEthValue < 0.000001 ? "0.000000..." : selectedGasEthValue.toFixed(6))
return qsTrId("maximum-priority-fee---1-eth").arg(v)
}
anchors.top: errorsText.bottom
anchors.topMargin: Style.current.smallPadding + 5
font.pixelSize: 13
color: Style.current.textColor
}
StyledText {
id: maxPriorityFeeFiatText
text: `${selectedGasFiatValue} ${root.defaultCurrency}`
text: `${selectedGasFiatValue} ${root.defaultCurrency.toUpperCase()}`
anchors.verticalCenter: maxPriorityFeeText.verticalCenter
anchors.left: maxPriorityFeeText.right
anchors.leftMargin: 6

View File

@ -17,11 +17,17 @@ Rectangle {
property bool checkedByDefault: false
property var getGasEthValue: function () {}
property var getFiatValue: function () {}
function formatDec(num, dec){
return Math.round((num + Number.EPSILON) * Math.pow(10, dec)) / Math.pow(10, dec)
}
property double ethValue: {
if (!gasLimit) {
return 0
}
return getGasEthValue(price, gasLimit)
return formatDec(parseFloat(getGasEthValue(price, gasLimit)), 6)
}
property double fiatValue: getFiatValue(ethValue, "ETH", defaultCurrency)
signal checked()

View File

@ -9,6 +9,8 @@ import "."
Item {
property alias textField: inputValue
property alias inputLabel: inputLabel
property string placeholderText: "My placeholder"
property string placeholderTextColor: Style.current.secondaryText
property alias text: inputValue.text

View File

@ -5,6 +5,7 @@ import QtQuick.Dialogs 1.3
import "../../imports"
import "../../shared"
import "../../shared/status"
import "../../app/AppLayouts/Wallet/"
ModalPopup {
id: root
@ -20,14 +21,17 @@ ModalPopup {
walletModel.gasView.getGasPricePredictions()
}
height: 540
function sendTransaction() {
try {
let responseStr = onSendTransaction(selectFromAccount.selectedAccount.address,
gasSelector.selectedGasLimit,
gasSelector.selectedGasPrice,
transactionSigner.enteredPassword);
let responseStr = profileModel.ens.setPubKey(root.ensUsername,
selectFromAccount.selectedAccount.address,
gasSelector.selectedGasLimit,
gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
transactionSigner.enteredPassword)
let response = JSON.parse(responseStr)
if (!response.success) {
@ -105,11 +109,11 @@ ModalPopup {
visible: true
anchors.top: selectFromAccount.bottom
anchors.topMargin: Style.current.bigPadding * 2
slowestGasPrice: parseFloat(walletModel.gasView.safeLowGasPrice)
fastestGasPrice: parseFloat(walletModel.gasView.fastestGasPrice)
gasPrice: parseFloat(walletModel.gasView.gasPrice)
getGasEthValue: walletModel.gasView.getGasEthValue
getFiatValue: walletModel.balanceView.getFiatValue
defaultCurrency: walletModel.balanceView.defaultCurrency
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
let estimatedGas = root.estimateGasFunction(selectFromAccount.selectedAccount);
gasSelector.selectedGasLimit = estimatedGas
@ -168,7 +172,7 @@ ModalPopup {
width: parent.width
height: btnNext.height
StatusRoundButton {
StatusRoundButton {
id: btnBack
anchors.left: parent.left
icon.name: "arrow-right"
@ -185,6 +189,13 @@ ModalPopup {
}
}
Component {
id: transactionSettingsConfirmationPopupComponent
TransactionSettingsConfirmationPopup {
}
}
StatusButton {
id: btnNext
anchors.right: parent.right
@ -197,6 +208,27 @@ ModalPopup {
if (stack.isLastGroup) {
return root.sendTransaction()
}
if(gasSelector.eip1599Enabled && stack.currentGroup === group2 && gasSelector.advancedMode){
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
openPopup(transactionSettingsConfirmationPopupComponent, {
currentBaseFee: gasSelector.latestBaseFeeGwei,
currentMinimumTip: gasSelector.perGasTipLimitFloor,
currentAverageTip: gasSelector.perGasTipLimitAverage,
tipLimit: gasSelector.selectedTipLimit,
suggestedTipLimit: gasSelector.perGasTipLimitFloor,
priceLimit: gasSelector.selectedOverallLimit,
suggestedPriceLimit: gasSelector.latestBaseFeeGwei + gasSelector.perGasTipLimitFloor,
showPriceLimitWarning: gasSelector.showPriceLimitWarning,
showTipLimitWarning: gasSelector.showTipLimitWarning,
onConfirm: function(){
stack.next();
}
})
return
}
}
stack.next()
}
}

View File

@ -5,6 +5,7 @@ import QtQuick.Dialogs 1.3
import "../../imports"
import "../../shared"
import "../../shared/status"
import "../../app/AppLayouts/Wallet/"
ModalPopup {
id: root
@ -12,13 +13,15 @@ ModalPopup {
property string assetPrice
property string contractAddress
property var estimateGasFunction: (function(userAddress, uuid) { return 0; })
property var onSendTransaction: (function(userAddress, gasLimit, gasPrice, password){ return ""; })
property var onSendTransaction: (function(userAddress, gasLimit, gasPrice, tipLimit, overallLimit, password){ return ""; })
property var onSuccess: (function(){})
Component.onCompleted: {
walletModel.gasView.getGasPricePredictions()
walletModel.gasView.getGasPrice()
}
height: 540
//% "Authorize %1 %2"
title: qsTrId("authorize--1--2").arg(Utils.stripTrailingZeros(assetPrice)).arg(asset.symbol)
@ -33,13 +36,16 @@ ModalPopup {
function setAsyncGasLimitResult(uuid, value) {
if (uuid === gasSelector.uuid) {
gasSelector.selectedGasLimit = value
gasSelector.defaultGasLimit = value
}
}
function sendTransaction() {
let responseStr = onSendTransaction(selectFromAccount.selectedAccount.address,
gasSelector.selectedGasLimit,
gasSelector.selectedGasPrice,
gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
transactionSigner.enteredPassword);
let response = JSON.parse(responseStr)
@ -108,12 +114,12 @@ ModalPopup {
id: gasSelector
anchors.top: selectFromAccount.bottom
anchors.topMargin: Style.current.bigPadding * 2
slowestGasPrice: parseFloat(walletModel.gasView.safeLowGasPrice)
fastestGasPrice: parseFloat(walletModel.gasView.fastestGasPrice)
gasPrice: parseFloat(walletModel.gasView.gasPrice)
getGasEthValue: walletModel.gasView.getGasEthValue
getFiatValue: walletModel.balanceView.getFiatValue
defaultCurrency: walletModel.balanceView.defaultCurrency
width: stack.width
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
let estimatedGas = root.estimateGasFunction(selectFromAccount.selectedAccount, uuid);
gasSelector.selectedGasLimit = estimatedGas
@ -190,6 +196,14 @@ ModalPopup {
stack.back()
}
}
Component {
id: transactionSettingsConfirmationPopupComponent
TransactionSettingsConfirmationPopup {
}
}
StatusButton {
id: btnNext
anchors.right: parent.right
@ -203,6 +217,27 @@ ModalPopup {
if (stack.isLastGroup) {
return root.sendTransaction()
}
if(gasSelector.eip1599Enabled && stack.currentGroup === group2 && gasSelector.advancedMode){
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
openPopup(transactionSettingsConfirmationPopupComponent, {
currentBaseFee: gasSelector.latestBaseFeeGwei,
currentMinimumTip: gasSelector.perGasTipLimitFloor,
currentAverageTip: gasSelector.perGasTipLimitAverage,
tipLimit: gasSelector.selectedTipLimit,
suggestedTipLimit: gasSelector.perGasTipLimitFloor, // TODO:
priceLimit: gasSelector.selectedOverallLimit,
suggestedPriceLimit: gasSelector.latestBaseFeeGwei + gasSelector.perGasTipLimitFloor,
showPriceLimitWarning: gasSelector.showPriceLimitWarning,
showTipLimitWarning: gasSelector.showTipLimitWarning,
onConfirm: function(){
stack.next();
}
})
return
}
}
stack.next()
}
}

View File

@ -98,12 +98,14 @@ Item {
if (packId < 0 || !selectedAccount || !price) return 325000
return chatsModel.stickers.estimate(packId, selectedAccount.address, price, uuid)
}
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, password) {
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, tipLimit, overallLimit, password) {
return chatsModel.stickers.buy(packId,
selectedAddress,
price,
gasLimit,
gasPrice,
tipLimit,
overallLimit,
password)
}
onClosed: {

View File

@ -60,12 +60,14 @@ ModalPopup {
if (packId < 0 || !selectedAccount || !price) return 325000
return chatsModel.stickers.estimate(packId, selectedAccount.address, price, uuid)
}
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, password) {
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, tipLimit, overallLimit, password) {
return chatsModel.stickers.buy(packId,
selectedAddress,
price,
gasLimit,
gasPrice,
tipLimit,
overallLimit,
password)
}
onClosed: {

2
vendor/status-lib vendored

@ -1 +1 @@
Subproject commit efe2790db6cf5e3f01d4b3265d2a671fed70e2d1
Subproject commit c1d61a13c0592e83083161e4b6d5b2e126a8a424