feat(@wallet): move suggested fees to status-go

This commit is contained in:
Anthony Laibe 2022-03-23 09:32:25 +01:00 committed by Anthony Laibe
parent 4b9b93a873
commit 08131e1d2d
14 changed files with 36 additions and 146 deletions

View File

@ -8,7 +8,6 @@ type WalletSignal* = ref object of Signal
eventType*: string
blockNumber*: int
accounts*: seq[string]
baseFeePerGas*: string
# newTransactions*: ???
erc20*: bool
@ -19,7 +18,6 @@ proc fromEvent*(T: type WalletSignal, jsonSignal: JsonNode): WalletSignal =
if jsonSignal["event"].kind != JNull:
result.eventType = jsonSignal["event"]["type"].getStr
result.blockNumber = jsonSignal["event"]{"blockNumber"}.getInt
result.baseFeePerGas = jsonSignal["event"]{"baseFeePerGas"}.getStr
result.erc20 = jsonSignal["event"]{"erc20"}.getBool
result.accounts = @[]
if jsonSignal["event"]["accounts"].kind != JNull:

View File

@ -95,9 +95,6 @@ proc transferTokens*(self: Controller, from_addr: string, to_addr: string, contr
result = self.transactionService.transferTokens(from_addr, to_addr, contractAddress, value, gas,
gasPrice, maxPriorityFeePerGas, maxFeePerGas, password, uuid)
proc baseFeePerGas*(self: Controller): string =
return self.transactionService.baseFeePerGas()
proc suggestedFees*(self: Controller): string =
let suggestedFees = self.transactionService.suggestedFees()
return suggestedFees.toJson()

View File

@ -57,9 +57,6 @@ method transferTokens*(self: AccessInterface, from_addr: string, to_addr: string
method transactionWasSent*(self: AccessInterface, result: string) {.base.} =
raise newException(ValueError, "No implementation available")
method baseFeePerGas*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
method suggestedFees*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -103,8 +103,5 @@ method transferTokens*(self: Module, from_addr: string, to_addr: string, contrac
method transactionWasSent*(self: Module, result: string) =
self.view.transactionWasSent(result)
method baseFeePerGas*(self: Module): string =
return self.controller.baseFeePerGas()
method suggestedFees*(self: Module): string =
return self.controller.suggestedFees()

View File

@ -129,9 +129,5 @@ QtObject:
result = self.delegate.transferTokens(from_addr, to_addr, contractAddress, value, gas, gasPrice,
maxPriorityFeePerGas, maxFeePerGas, password, uuid)
proc latestBaseFeePerGas*(self: View): string {.slot.} =
let baseFeeWei = self.delegate.baseFeePerGas()
return common_conversion.wei2Gwei(baseFeeWei)
proc suggestedFees*(self: View): string {.slot.} =
return self.delegate.suggestedFees()

View File

@ -51,18 +51,13 @@ type
result*: string
type SuggestedFees = object
gasPrice: string
gasPrice: float
baseFee: float
maxPriorityFeePerGas: float
maxFeePerGasL: float
maxFeePerGasM: float
maxFeePerGasH: float
proc cmpUint256(x, y: Uint256): int =
if x > y: 1
elif x == y: 0
else: -1
QtObject:
type Service* = ref object of QObject
events: EventEmitter
@ -72,8 +67,6 @@ QtObject:
networkService: network_service.Service
settingsService: settings_service.Service
baseFeePerGas: string
# Forward declaration
proc checkPendingTransactions*(self: Service)
proc checkPendingTransactions*(self: Service, address: string)
@ -98,25 +91,15 @@ QtObject:
result.networkService = networkService
result.settingsService = settingsService
proc baseFeePerGas*(self: Service): string =
return self.baseFeePerGas
proc setLatestBaseFeePerGas*(self: Service) =
let response = eth.getBlockByNumber("latest")
self.baseFeePerGas = $fromHex(Stuint[256], response.result{"baseFeePerGas"}.getStr)
proc doConnect*(self: Service) =
self.events.on(SignalType.Wallet.event) do(e:Args):
var data = WalletSignal(e)
if(data.eventType == "newblock"):
self.setLatestBaseFeePerGas()
for acc in data.accounts:
self.checkPendingTransactions(acc)
proc init*(self: Service) =
self.doConnect()
self.setLatestBaseFeePerGas()
proc checkRecentHistory*(self: Service) =
try:
@ -356,57 +339,18 @@ QtObject:
return false
return true
proc maxPriorityFeePerGas(self: Service): Uint256 =
let response = eth.maxPriorityFeePerGas()
return fromHex(Stuint[256], response.result.getStr)
proc getGasPrice(self: Service): Uint256 =
let response = eth.getGasPrice()
return fromHex(Stuint[256], response.result.getStr)
proc feeHistory(self: Service, n:int): seq[Uint256] =
let response = eth.feeHistory(101)
for it in response.result["baseFeePerGas"]:
result.add(fromHex(Stuint[256], it.getStr))
result.sort(cmpUint256)
proc suggestedFees*(self: Service): SuggestedFees =
#[
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.maxPriorityFeePerGas()
let feeHistory = self.feeHistory(101)
let baseFee = self.baseFeePerGas.u256
let gasPrice = self.getGasPrice()
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
let networkType = self.settingsService.getCurrentNetwork().toNetworkType()
let network = self.networkService.getNetwork(networkType)
let response = eth.suggestedFees(network.chainId).result
return SuggestedFees(
gasPrice: $gasPrice,
baseFee: parseFloat(common_conversion.wei2gwei($baseFee)),
maxPriorityFeePerGas: parseFloat(common_conversion.wei2gwei($maxPriorityFeePerGas)),
maxFeePerGasL: parseFloat(common_conversion.wei2gwei($(perc10 + maxPriorityFeePerGas))),
maxFeePerGasM: parseFloat(common_conversion.wei2gwei($(maxFeePerGasM))),
maxFeePerGasH: parseFloat(common_conversion.wei2gwei($(baseFee + maxPriorityFeePerGas)))
gasPrice: parseFloat(response{"gasPrice"}.getStr),
baseFee: parseFloat(response{"baseFee"}.getStr),
maxPriorityFeePerGas: parseFloat(response{"maxPriorityFeePerGas"}.getStr),
maxFeePerGasL: parseFloat(response{"maxFeePerGasLow"}.getStr),
maxFeePerGasM: parseFloat(response{"maxFeePerGasMedium"}.getStr),
maxFeePerGasH: parseFloat(response{"maxFeePerGasHigh"}.getStr)
)
proc fetchCryptoServices*(self: Service): seq[CryptoRampDto] =

View File

@ -30,10 +30,6 @@ proc getEthAccounts*(): RpcResponse[JsonNode] {.raises: [Exception].} =
proc getGasPrice*(payload = %* []): RpcResponse[JsonNode] {.raises: [Exception].} =
return core.callPrivateRPC("eth_gasPrice", payload)
proc maxPriorityFeePerGas*(): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* []
return core.callPrivateRPC("eth_maxPriorityFeePerGas", payload)
proc feeHistory*(n: int): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [n, "latest", nil]
return core.callPrivateRPC("eth_feeHistory", payload)
proc suggestedFees*(chainId: int): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [chainId]
return core.callPrivateRPC("wallet_getSuggestedFees", payload)

View File

@ -503,10 +503,6 @@ QtObject {
return walletSection.isEIP1559Enabled()
}
function latestBaseFeePerGas() {
return walletSectionTransactions.latestBaseFeePerGas()
}
function suggestedFees() {
return JSON.parse(walletSectionTransactions.suggestedFees())
}

View File

@ -104,10 +104,6 @@ QtObject {
return walletSection.isEIP1559Enabled()
}
function latestBaseFeePerGas() {
return walletSectionTransactions.latestBaseFeePerGas()
}
function suggestedFees() {
return JSON.parse(walletSectionTransactions.suggestedFees())
}

View File

@ -18,17 +18,8 @@ Item {
property bool isEIP1559Enabled: true
property var latestBaseFeePerGas: ""
// Not Refactored Yet
property var suggestedFees: ""
property double latestBaseFeePerGasGwei: {
if (!isEIP1559Enabled) return 0;
return parseFloat(latestBaseFeePerGas)
}
property var getGasGweiValue: function () {}
property var getGasEthValue: function () {}
property var getFiatValue: function () {}
@ -53,11 +44,11 @@ Item {
property bool isValid: true
readonly property string uuid: Utils.uuid()
property bool advancedMode: true // TODO: change to false once EIP1559 suggestions are revised
property bool advancedMode: false
// 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 double perGasTipLimitAverage: formatDec(root.suggestedFees.maxPriorityFeePerGas, 2) // 1.5 // Matches status-react average-priority-fee
property bool showPriceLimitWarning : false
@ -110,20 +101,6 @@ Item {
errorMsg = appendError(errorMsg, qsTr("The average miner tip is %1 Gwei").arg(perGasTipLimitAverage), true)
}
// Per-gas overall limit rules
if(inputOverallLimit < latestBaseFeePerGasGwei){
errorMsg = appendError(errorMsg, qsTr("The limit is below the current base fee of %1 %2").arg(latestBaseFeePerGasGwei).arg("Gwei"))
showPriceLimitWarning = true
}
/* TODO: change these values false once EIP1559 suggestions are revised
else if((inputOverallLimit - inputTipLimit) < latestBaseFeePerGasGwei){
errorMsg = appendError(errorMsg, qsTr("The limit should be at least %1 Gwei above the base fee").arg(perGasTipLimitFloor))
} else if((inputOverallLimit - perGasTipLimitAverage) < latestBaseFeePerGasGwei) {
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}`
}
@ -185,6 +162,7 @@ Item {
inputPerGasTipLimit.validationError = root.greaterThan0ErrorMessage
}
const isInputValid = inputGasLimit.validationError === "" && inputGasPrice.validationError === "" && (!isEIP1559Enabled || (isEIP1559Enabled && inputPerGasTipLimit.validationError === ""))
return isInputValid
}
@ -206,14 +184,13 @@ Item {
anchors.top: parent.top
anchors.left: prioritytext.right
anchors.leftMargin: Style.current.smallPadding
text: qsTr("Current base fee: %1 %2").arg(latestBaseFeePerGasGwei).arg("Gwei")
text: qsTr("Current base fee: %1 %2").arg(root.suggestedFees.baseFee).arg("Gwei")
font.weight: Font.Medium
font.pixelSize: 13
color: Style.current.secondaryText
}
StatusFlatButton {
visible: false // Change to TRUE once EIP1559 suggestions are revised
id: buttonAdvanced
anchors.verticalCenter: prioritytext.verticalCenter
anchors.right: parent.right
@ -243,7 +220,7 @@ Item {
text: qsTr("Low")
price: {
if (!isEIP1559Enabled) return gasPrice;
return formatDec(suggestedFees.maxFeePerGasL, 6)
return formatDec(root.suggestedFees.maxFeePerGasL, 6)
}
gasLimit: inputGasLimit ? inputGasLimit.text : ""
getGasEthValue: root.getGasEthValue
@ -251,8 +228,8 @@ Item {
defaultCurrency: root.defaultCurrency
onChecked: {
if (isEIP1559Enabled){
inputPerGasTipLimit.text = formatDec(suggestedFees.maxPriorityFeePerGas, 2);
inputGasPrice.text = formatDec(suggestedFees.maxFeePerGasL, 2);
inputPerGasTipLimit.text = formatDec(root.suggestedFees.maxPriorityFeePerGas, 2);
inputGasPrice.text = formatDec(root.suggestedFees.maxFeePerGasL, 2);
} else {
inputGasPrice.text = price
}
@ -273,7 +250,7 @@ Item {
return root.gasPrice
}
return formatDec(suggestedFees.maxFeePerGasM, 6)
return formatDec(root.suggestedFees.maxFeePerGasM, 6)
}
gasLimit: inputGasLimit ? inputGasLimit.text : ""
getGasEthValue: root.getGasEthValue
@ -281,8 +258,8 @@ Item {
defaultCurrency: root.defaultCurrency
onChecked: {
if (isEIP1559Enabled){
inputPerGasTipLimit.text = formatDec(suggestedFees.maxPriorityFeePerGas, 2);
inputGasPrice.text = formatDec(suggestedFees.maxFeePerGasM, 2);
inputPerGasTipLimit.text = formatDec(root.suggestedFees.maxPriorityFeePerGas, 2);
inputGasPrice.text = formatDec(root.suggestedFees.maxFeePerGasM, 2);
} else {
inputGasPrice.text = root.gasPrice
}
@ -296,7 +273,7 @@ Item {
text: qsTr("High")
price: {
if (!isEIP1559Enabled) return gasPrice;
return formatDec(suggestedFees.maxFeePerGasH,6);
return formatDec(root.suggestedFees.maxFeePerGasH,6);
}
gasLimit: inputGasLimit ? inputGasLimit.text : ""
getGasEthValue: root.getGasEthValue
@ -304,8 +281,8 @@ Item {
defaultCurrency: root.defaultCurrency
onChecked: {
if (isEIP1559Enabled){
inputPerGasTipLimit.text = formatDec(suggestedFees.maxPriorityFeePerGas, 2);
inputGasPrice.text = formatDec(suggestedFees.maxFeePerGasH, 2);
inputPerGasTipLimit.text = formatDec(root.suggestedFees.maxPriorityFeePerGas, 2);
inputGasPrice.text = formatDec(root.suggestedFees.maxFeePerGasH, 2);
} else {
inputGasPrice.text = price
}
@ -359,7 +336,7 @@ Item {
visible: isEIP1559Enabled
width: 125
customHeight: 56
text: formatDec(suggestedFees.maxPriorityFeePerGas, 2);
text: formatDec(root.suggestedFees.maxPriorityFeePerGas, 2);
placeholderText: "20"
onTextChanged: {
if (root.validate()) {

View File

@ -146,7 +146,6 @@ StatusModal {
getFiatValue: popup.store.getFiatValue
defaultCurrency: popup.store.currentCurrency
isEIP1559Enabled: popup.store.isEIP1559Enabled()
latestBaseFeePerGas: popup.store.latestBaseFeePerGas()
suggestedFees: popup.store.suggestedFees()
visible: !popup.store.isMultiNetworkEnabled
@ -220,13 +219,13 @@ StatusModal {
if(gasSelector.isEIP1559Enabled && popup.contentItem.currentGroup === group1 && gasSelector.advancedMode){
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
Global.openPopup(transactionSettingsConfirmationPopupComponent, {
currentBaseFee: gasSelector.latestBaseFeePerGasGwei,
currentBaseFee: gasSelector.suggestedFees.baseFee,
currentMinimumTip: gasSelector.perGasTipLimitFloor,
currentAverageTip: gasSelector.perGasTipLimitAverage,
tipLimit: gasSelector.selectedTipLimit,
suggestedTipLimit: gasSelector.perGasTipLimitFloor,
priceLimit: gasSelector.selectedOverallLimit,
suggestedPriceLimit: gasSelector.latestBaseFeePerGasGwei + gasSelector.perGasTipLimitFloor,
suggestedPriceLimit: gasSelector.suggestedFees.baseFee + gasSelector.perGasTipLimitFloor,
showPriceLimitWarning: gasSelector.showPriceLimitWarning,
showTipLimitWarning: gasSelector.showTipLimitWarning,
onConfirm: function(){

View File

@ -157,7 +157,6 @@ StatusModal {
getFiatValue: root.store.getFiatValue
defaultCurrency: root.store.currentCurrency
isEIP1559Enabled: root.store.isEIP1559Enabled()
latestBaseFeePerGas: root.store.latestBaseFeePerGas()
suggestedFees: root.store.suggestedFees()
width: stack.width
@ -307,13 +306,13 @@ StatusModal {
if(gasSelector.isEIP1559Enabled && stack.currentGroup === groupSelectGas && gasSelector.advancedMode){
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
Global.openPopup(transactionSettingsConfirmationPopupComponent, {
currentBaseFee: gasSelector.latestBaseFeePerGasGwei,
currentBaseFee: gasSelector.suggestedFees.baseFee,
currentMinimumTip: gasSelector.perGasTipLimitFloor,
currentAverageTip: gasSelector.perGasTipLimitAverage,
tipLimit: gasSelector.selectedTipLimit,
suggestedTipLimit: gasSelector.perGasTipLimitFloor, // TODO:
priceLimit: gasSelector.selectedOverallLimit,
suggestedPriceLimit: gasSelector.latestBaseFeePerGasGwei + gasSelector.perGasTipLimitFloor,
suggestedPriceLimit: gasSelector.suggestedFees.baseFee + gasSelector.perGasTipLimitFloor,
showPriceLimitWarning: gasSelector.showPriceLimitWarning,
showTipLimitWarning: gasSelector.showTipLimitWarning,
onConfirm: function(){

View File

@ -121,7 +121,6 @@ ModalPopup {
getFiatValue: root.ensUsernamesStore.getFiatValue
defaultCurrency: root.ensUsernamesStore.getCurrentCurrency()
isEIP1559Enabled: root.store.isEIP1559Enabled()
latestBaseFeePerGas: root.store.latestBaseFeePerGas()
suggestedFees: root.store.suggestedFees()
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
@ -221,13 +220,13 @@ ModalPopup {
if(gasSelector.isEIP1559Enabled && stack.currentGroup === group2 && gasSelector.advancedMode){
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
Global.openPopup(transactionSettingsConfirmationPopupComponent, {
currentBaseFee: gasSelector.latestBaseFeePerGasGwei,
currentBaseFee: gasSelector.suggestedFees.baseFee,
currentMinimumTip: gasSelector.perGasTipLimitFloor,
currentAverageTip: gasSelector.perGasTipLimitAverage,
tipLimit: gasSelector.selectedTipLimit,
suggestedTipLimit: gasSelector.perGasTipLimitFloor,
priceLimit: gasSelector.selectedOverallLimit,
suggestedPriceLimit: gasSelector.latestBaseFeePerGasGwei + gasSelector.perGasTipLimitFloor,
suggestedPriceLimit: gasSelector.suggestedFees.baseFee + gasSelector.perGasTipLimitFloor,
showPriceLimitWarning: gasSelector.showPriceLimitWarning,
showTipLimitWarning: gasSelector.showTipLimitWarning,
onConfirm: function(){

View File

@ -139,7 +139,6 @@ ModalPopup {
getFiatValue: root.stickersStore.getFiatValue
defaultCurrency: root.stickersStore.getCurrentCurrency()
isEIP1559Enabled: root.store.isEIP1559Enabled()
latestBaseFeePerGas: root.store.latestBaseFeePerGas()
suggestedFees: root.store.suggestedFees()
width: stack.width
@ -247,13 +246,13 @@ ModalPopup {
if(gasSelector.isEIP1559Enabled && stack.currentGroup === group2 && gasSelector.advancedMode){
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
Global.openPopup(transactionSettingsConfirmationPopupComponent, {
currentBaseFee: gasSelector.latestBaseFeePerGasGwei,
currentBaseFee: gasSelector.suggestedFees.baseFee,
currentMinimumTip: gasSelector.perGasTipLimitFloor,
currentAverageTip: gasSelector.perGasTipLimitAverage,
tipLimit: gasSelector.selectedTipLimit,
suggestedTipLimit: gasSelector.perGasTipLimitFloor, // TODO:
priceLimit: gasSelector.selectedOverallLimit,
suggestedPriceLimit: gasSelector.latestBaseFeePerGasGwei + gasSelector.perGasTipLimitFloor,
suggestedPriceLimit: gasSelector.suggestedFees.baseFee + gasSelector.perGasTipLimitFloor,
showPriceLimitWarning: gasSelector.showPriceLimitWarning,
showTipLimitWarning: gasSelector.showTipLimitWarning,
onConfirm: function(){