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

155 lines
5.5 KiB
QML

import QtQuick 2.15
import AppLayouts.Wallet.services.dapps.types 1.0
import StatusQ.Core.Utils 0.1 as SQUtils
import shared.stores 1.0
// The TransactionFeesBroker is responsible for managing the subscriptions to the estimated time, fees and gas limit for a transaction
// It will bundle the same requests to optimise the backend load and will notify the subscribers when the data is ready
// It can only work with a TransactionFeesSubscriber
SQUtils.QObject {
id: root
required property DAppsStore store
property int interval: 5000
function subscribe(subscriberObj) {
if (!(subscriberObj instanceof TransactionFeesSubscriber)) {
console.error("Invalid subscriber object")
return
}
try {
const estimatedTimeSub = estimatedTimeSubscription.createObject(subscriberObj, {
subscriber: subscriberObj
})
const feesSub = feesSubscription.createObject(subscriberObj, {
subscriber: subscriberObj
})
const gasLimitSub = gasLimitSubscription.createObject(subscriberObj, {
subscriber: subscriberObj
})
if (subscriberObj.txObject && (subscriberObj.txObject.gas || subscriberObj.txObject.gasLimit)) {
subscriberObj.setGas(subscriberObj.txObject.gas || subscriberObj.txObject.gasLimit)
}
broker.subscribe(estimatedTimeSub)
broker.subscribe(feesSub)
broker.subscribe(gasLimitSub)
} catch (e) {
console.error("Error subscribing to estimated time: ", e)
}
}
enum SubscriptionType {
Fees,
GasLimit,
EstimatedTime
}
SQUtils.SubscriptionBroker {
id: broker
active: Qt.application.state === Qt.ApplicationActive
onRequest: d.computeFees(topic)
}
SQUtils.QObject {
id: d
function computeFees(topic) {
try {
const args = JSON.parse(topic)
switch (args.type) {
case TransactionFeesBroker.SubscriptionType.Fees:
root.store.requestSuggestedFees(topic, args.chainId)
break
case TransactionFeesBroker.SubscriptionType.GasLimit:
root.store.requestGasEstimate(topic, args.chainId, args.tx)
break
case TransactionFeesBroker.SubscriptionType.EstimatedTime:
root.store.requestEstimatedTime(topic, args.chainId, args.maxFeePerGasHex)
break
}
} catch (e) {
console.error("Error computing fees: ", e)
}
}
}
Component {
id: feesSubscription
SQUtils.Subscription {
required property TransactionFeesSubscriber subscriber
readonly property var requestArgs: ({
type: TransactionFeesBroker.SubscriptionType.Fees,
chainId: subscriber.chainId
})
isReady: subscriber.active
topic: isReady ? JSON.stringify(requestArgs) : ""
onResponseChanged: {
if (!response || !response.success)
return
subscriber.setFees(response.suggestedFees)
}
}
}
Component {
id: estimatedTimeSubscription
SQUtils.Subscription {
required property TransactionFeesSubscriber subscriber
readonly property var requestArgs: ({
type: TransactionFeesBroker.SubscriptionType.EstimatedTime,
chainId: subscriber.chainId,
maxFeePerGasHex: subscriber.txObject ? (subscriber.txObject.maxFeePerGas || subscriber.txObject.gasPrice || "") :
""
})
isReady: subscriber.active
topic: isReady ? JSON.stringify(requestArgs) : ""
onResponseChanged: {
if (!response || !response.success)
return
subscriber.setEstimatedTime(response.estimatedTime)
}
notificationInterval: root.interval
}
}
Component {
id: gasLimitSubscription
SQUtils.Subscription {
required property TransactionFeesSubscriber subscriber
readonly property var requestArgs: ({
type: TransactionFeesBroker.SubscriptionType.GasLimit,
chainId: subscriber.chainId,
tx: subscriber.txObject
})
isReady: subscriber.active && !!subscriber.txObject && !!subscriber.chainId && !subscriber.gasLimit /*Ask for gas just once*/
topic: isReady ? JSON.stringify(requestArgs) : ""
onResponseChanged: {
if (!response || !response.success)
return
subscriber.setGas(response.gasEstimate)
}
notificationInterval: root.interval
}
}
Connections {
id: storeConnections
target: root.store
function onEstimatedTimeResponse(topic, timeCategory, success) {
broker.response(topic, { estimatedTime: timeCategory, success})
}
function onSuggestedFeesResponse(topic, suggestedFeesJson, success) {
broker.response(topic, { suggestedFees: suggestedFeesJson, success: success })
}
function onEstimatedGasResponse(topic, gasEstimate, success) {
broker.response(topic, { gasEstimate, success })
}
}
}