status-desktop/ui/app/AppLayouts/Wallet/services/dapps/internal/TransactionFeesSubscriber.qml
Alex Jbanca 793aeb15c3 fix(Dapps): Fixing fees in transaction requests
Fixes:
1. Fixing the laggy scrolling on transaction requiests popups. The root cause of this issue was the fees request and also the estimated time request. These periodic requests were blocking. Now we'll call these API async.
2. Fixing the max fees: The fees computation was using 21k as gasLimit. This value was hardcoded in WC. Now we're requesting the gasLimit if it's not provided by the dApp. This call is also async.
3. Fixing the periodicity of the fees computation. The fees were computed by the client only if the tx object didn't already provide the fees. But the tx could fail if when the fees are highly volatile because it was not being overridden. Now Status is computing the fees periodically for all tx requests.
4. Fixing an issue where the loading state of the fees text in the modal was showing text underneath the loading animation. Fixed by updating the AnimatedText to support a custom target property. The text component used for session requests is using `cusomColor` property to set the text color and the `color` for the text must not be overriden.
2024-11-22 11:32:41 +02:00

134 lines
4.4 KiB
QML

import QtQuick 2.15
import StatusQ.Core.Utils 0.1 as SQUtils
import utils 1.0
SQUtils.QObject {
id: root
/*
Input properties
*/
// standard transaction object
required property var txObject
// subscriber id
required property string key
// chainId -> chain id for the transaction
required property int chainId
// active specifies if the subscriber has an active subscription
required property bool active
// selectedFeesMode -> selected fees mode. Defaults to Constants.TransactionFeesMode.Medium
property int selectedFeesMode: Constants.TransactionFeesMode.Medium
// Required function to be implemented by the subscriber
required property var hexToDec /*(hexValue) => decValue*/
/*
Published properties
*/
// estimatedTimeResponse -> maps to Constants.TransactionEstimatedTime
readonly property int estimatedTimeResponse: d.estimatedTimeResponse
// maxEthFee -> Big number in Gwei. Represens the total fees for the transaction
readonly property var maxEthFee: d.computedFees
// feesInfo -> status-go fees info with updated maxFeePerGas based on selectedFeesMode
readonly property var feesInfo: d.computedFeesInfo
// gasLimit -> gas limit for the transaction
readonly property var gasLimit: d.gasResponse
function setFees(fees) {
if (d.feesResponse === fees) {
return
}
d.feesResponse = fees
d.resetFees()
}
function setGas(gas) {
if (d.gasResponse === gas) {
return
}
d.gasResponse = gas
d.resetFees()
}
function setEstimatedTime(estimatedTime) {
if(!estimatedTime) {
estimatedTime = Constants.TransactionEstimatedTime.Unknown
return
}
d.estimatedTimeResponse = estimatedTime
}
QtObject {
id: d
property int estimatedTimeResponse: Constants.TransactionEstimatedTime.Unknown
property var feesResponse
property var gasResponse
// Eth max fee in Gwei
property var computedFees
// feesResponse with additional `maxFeePerGas` property based on selectedFeesMode
property var computedFeesInfo
function resetFees() {
if (!d.feesResponse) {
return
}
if (!gasResponse) {
return
}
try {
d.computedFees = getEstimatedMaxFees()
d.computedFeesInfo = d.feesResponse
d.computedFeesInfo.maxFeePerGas = getFeesForFeesMode(d.feesResponse)
} catch (e) {
console.error("Failed to compute fees", e, e.stack)
}
}
function getFeesForFeesMode(feesObj) {
if (!(feesObj.hasOwnProperty("maxFeePerGasLow") &&
feesObj.hasOwnProperty("maxFeePerGasMedium") &&
feesObj.hasOwnProperty("maxFeePerGasHigh"))) {
print ("feesObj", JSON.stringify(feesObj))
throw new Error("inappropriate fees object provided")
}
const BigOps = SQUtils.AmountsArithmetic
if (!feesObj.eip1559Enabled && !!feesObj.gasPrice) {
return feesObj.gasPrice
}
switch (root.selectedFeesMode) {
case Constants.FeesMode.Low:
return feesObj.maxFeePerGasLow
case Constants.FeesMode.Medium:
return feesObj.maxFeePerGasMedium
case Constants.FeesMode.High:
return feesObj.maxFeePerGasHigh
default:
throw new Error("unknown selected mode")
}
}
function getEstimatedMaxFees() {
// Note: Use the received fee arguments only once!
// Complete what's missing with the suggested fees
const BigOps = SQUtils.AmountsArithmetic
const gasLimitStr = root.hexToDec(d.gasResponse)
const gasLimit = BigOps.fromString(gasLimitStr)
const maxFeesPerGas = BigOps.fromNumber(getFeesForFeesMode(d.feesResponse))
const l1GasFee = d.feesResponse.l1GasFee ? BigOps.fromNumber(d.feesResponse.l1GasFee)
: BigOps.fromNumber(0)
let maxGasFee = BigOps.times(gasLimit, maxFeesPerGas).plus(l1GasFee)
return maxGasFee
}
Component.onCompleted: {
resetFees()
}
}
}