feat(@dekstop/wallet): use amounts from activity backend

Part of #11080
This commit is contained in:
Dario Gabriel Lipicar 2023-06-14 16:53:13 -03:00 committed by dlipicar
parent a7b78bb6e8
commit 9fc8f66fbd
10 changed files with 151 additions and 54 deletions

View File

@ -1,5 +1,5 @@
import NimQml, logging, std/json, sequtils, sugar, options
import tables
import tables, stint
import model
import entry
@ -15,6 +15,7 @@ import backend/activity as backend_activity
import backend/backend as backend
import backend/transactions
import app_service/service/currency/service as currency_service
import app_service/service/transaction/service as transaction_service
proc toRef*[T](obj: T): ref T =
@ -31,6 +32,7 @@ QtObject:
recipientsModel: RecipientsModel
transactionsModule: transactions_module.AccessInterface
currentActivityFilter: backend_activity.ActivityFilter
currencyService: currency_service.Service
events: EventEmitter
@ -59,6 +61,20 @@ QtObject:
QtProperty[QVariant] recipientsModel:
read = getRecipientsModel
proc buildMultiTransactionExtraData(self: Controller, metadata: backend_activity.ActivityEntry, item: MultiTransactionDto): ExtraData =
# TODO: Use symbols from backendEntry when they're available
result.inSymbol = item.toAsset
result.inAmount = self.currencyService.parseCurrencyValue(result.inSymbol, metadata.amountIn)
result.outSymbol = item.fromAsset
result.outAmount = self.currencyService.parseCurrencyValue(result.outSymbol, metadata.amountOut)
proc buildTransactionExtraData(self: Controller, metadata: backend_activity.ActivityEntry, item: ref Item): ExtraData =
# TODO: Use symbols from backendEntry when they're available
result.inSymbol = item[].getSymbol()
result.inAmount = self.currencyService.parseCurrencyValue(result.inSymbol, metadata.amountIn)
result.outSymbol = item[].getSymbol()
result.outAmount = self.currencyService.parseCurrencyValue(result.outSymbol, metadata.amountOut)
proc backendToPresentation(self: Controller, backendEntities: seq[backend_activity.ActivityEntry]): seq[entry.ActivityEntry] =
var multiTransactionsIds: seq[int] = @[]
var transactionIdentities: seq[backend.TransactionIdentity] = @[]
@ -116,21 +132,27 @@ QtObject:
of MultiTransaction:
let id = multiTransactionsIds[mtIndex]
if multiTransactions.hasKey(id):
result.add(entry.newMultiTransactionActivityEntry(multiTransactions[id], backendEntry))
let mt = multiTransactions[id]
let extraData = self.buildMultiTransactionExtraData(backendEntry, mt)
result.add(entry.newMultiTransactionActivityEntry(mt, backendEntry, extraData))
else:
error "failed to find multi transaction with id: ", id
mtIndex += 1
of SimpleTransaction:
let identity = transactionIdentities[tIndex]
if transactions.hasKey(identity):
result.add(entry.newTransactionActivityEntry(transactions[identity], backendEntry, self.addresses))
let tr = transactions[identity]
let extraData = self.buildTransactionExtraData(backendEntry, tr)
result.add(entry.newTransactionActivityEntry(tr, backendEntry, self.addresses, extraData))
else:
error "failed to find transaction with identity: ", identity
tIndex += 1
of PendingTransaction:
let identity = pendingTransactionIdentities[ptIndex]
if pendingTransactions.hasKey(identity):
result.add(entry.newTransactionActivityEntry(pendingTransactions[identity], backendEntry, self.addresses))
let tr = pendingTransactions[identity]
let extraData = self.buildTransactionExtraData(backendEntry, tr)
result.add(entry.newTransactionActivityEntry(tr, backendEntry, self.addresses, extraData))
else:
error "failed to find pending transaction with identity: ", identity
ptIndex += 1
@ -192,13 +214,14 @@ QtObject:
self.currentActivityFilter.types = types
proc newController*(transactionsModule: transactions_module.AccessInterface, events: EventEmitter): Controller =
proc newController*(transactionsModule: transactions_module.AccessInterface, events: EventEmitter, currencyService: currency_service.Service): Controller =
new(result, delete)
result.model = newModel()
result.recipientsModel = newRecipientsModel()
result.transactionsModule = transactionsModule
result.currentActivityFilter = backend_activity.getIncludeAllActivityFilter()
result.events = events
result.currencyService = currencyService
result.setup()
let controller = result

View File

@ -4,6 +4,18 @@ import ../transactions/view
import ../transactions/item
import ./backend/transactions
import backend/activity as backend
import ../../../shared_models/currency_amount
# Additional data needed to build an Entry, which is
# not included in the metadata and needs to be
# fetched from a different source.
type
ExtraData* = object
inAmount*: float64
outAmount*: float64
# TODO: Fields below should come from the metadata
inSymbol*: string
outSymbol*: string
# It is used to display an activity history entry in the QML UI
#
@ -23,6 +35,7 @@ QtObject:
activityType: backend.ActivityType
metadata: backend.ActivityEntry
extradata: ExtraData
proc setup(self: ActivityEntry) =
self.QObject.setup
@ -30,20 +43,22 @@ QtObject:
proc delete*(self: ActivityEntry) =
self.QObject.delete
proc newMultiTransactionActivityEntry*(mt: MultiTransactionDto, metadata: backend.ActivityEntry): ActivityEntry =
proc newMultiTransactionActivityEntry*(mt: MultiTransactionDto, metadata: backend.ActivityEntry, extradata: ExtraData): ActivityEntry =
new(result, delete)
result.multi_transaction = mt
result.transaction = nil
result.isPending = false
result.metadata = metadata
result.extradata = extradata
result.setup()
proc newTransactionActivityEntry*(tr: ref Item, metadata: backend.ActivityEntry, fromAddresses: seq[string]): ActivityEntry =
proc newTransactionActivityEntry*(tr: ref Item, metadata: backend.ActivityEntry, fromAddresses: seq[string], extradata: ExtraData): ActivityEntry =
new(result, delete)
result.multi_transaction = nil
result.transaction = tr
result.isPending = metadata.payloadType == backend.PayloadType.PendingTransaction
result.metadata = metadata
result.extradata = extradata
result.activityType = backend.ActivityType.Send
if tr != nil:
for address in fromAddresses:
@ -104,38 +119,30 @@ QtObject:
QtProperty[string] recipient:
read = getRecipient
# TODO: use CurrencyAmount?
proc getFromAmount*(self: ActivityEntry): string {.slot.} =
if self.isMultiTransaction():
return self.multi_transaction.fromAmount
error "getFromAmount: ActivityEntry is not a MultiTransaction"
return "0"
proc getInAmount*(self: ActivityEntry): float {.slot.} =
return float(self.extradata.inAmount)
QtProperty[string] fromAmount:
read = getFromAmount
QtProperty[float] inAmount:
read = getInAmount
proc getToAmount*(self: ActivityEntry): string {.slot.} =
if not self.isMultiTransaction():
error "getToAmount: ActivityEntry is not a MultiTransaction"
return "0"
proc getOutAmount*(self: ActivityEntry): float {.slot.} =
return float(self.extradata.outAmount)
return self.multi_transaction.fromAmount
QtProperty[float] outAmount:
read = getOutAmount
QtProperty[string] toAmount:
read = getToAmount
proc getValue*(self: ActivityEntry): QVariant {.slot.} =
if self.isMultiTransaction():
return newQVariant(0)
proc getInSymbol*(self: ActivityEntry): string {.slot.} =
return self.extradata.inSymbol
if self.transaction == nil:
error "getValue: ActivityEntry is not an transaction.Item"
return newQVariant(0)
QtProperty[string] inSymbol:
read = getInSymbol
return newQVariant(self.transaction[].getValue())
proc getOutSymbol*(self: ActivityEntry): string {.slot.} =
return self.extradata.outSymbol
QtProperty[QVariant] value:
read = getValue
QtProperty[string] outSymbol:
read = getOutSymbol
proc getTimestamp*(self: ActivityEntry): int {.slot.} =
if self.isMultiTransaction():
@ -161,15 +168,6 @@ QtObject:
QtProperty[int] chainId:
read = getChainId
proc getSymbol*(self: ActivityEntry): string {.slot.} =
if self.transaction == nil:
error "getSymbol: ActivityEntry is not an transaction.Item"
return ""
return self.transaction[].getSymbol()
QtProperty[string] symbol:
read = getSymbol
proc getIsNFT*(self: ActivityEntry): bool {.slot.} =
if self.transaction == nil:
error "getIsNFT: ActivityEntry is not an transaction.Item"
@ -265,3 +263,52 @@ QtObject:
QtProperty[string] nonce:
read = getNonce
# TODO: Replaced usage of these for in/out versions in the QML modules
proc getSymbol*(self: ActivityEntry): string {.slot.} =
if self.transaction == nil:
error "getSymbol: ActivityEntry is not an transaction.Item"
return ""
if self.activityType == backend.ActivityType.Receive:
return self.getInSymbol()
return self.getOutSymbol()
QtProperty[string] symbol:
read = getSymbol
proc getFromAmount*(self: ActivityEntry): float {.slot.} =
if self.isMultiTransaction():
return self.getOutAmount()
error "getFromAmount: ActivityEntry is not a MultiTransaction"
return 0.0
QtProperty[float] fromAmount:
read = getFromAmount
proc getToAmount*(self: ActivityEntry): float {.slot.} =
if self.isMultiTransaction():
return self.getInAmount()
error "getToAmount: ActivityEntry is not a MultiTransaction"
return 0.0
QtProperty[float] toAmount:
read = getToAmount
proc getValue*(self: ActivityEntry): float {.slot.} =
if self.isMultiTransaction():
error "getToAmount: ActivityEntry is a MultiTransaction"
return 0.0
if self.activityType == backend.ActivityType.Receive:
return self.getInAmount()
# For some reason status-go is categorizing every activity as Receive,
# inverting the In/Out fields for Send operations. Revert this when
# that gets fixed.
#return self.getOutAmount()
return self.getInAmount()
QtProperty[float] value:
read = getValue

View File

@ -101,7 +101,7 @@ proc newModule*(
result.overviewModule = overview_module.newModule(result, events, walletAccountService, currencyService)
result.networksModule = networks_module.newModule(result, events, networkService, walletAccountService, settingsService)
result.networksService = networkService
result.activityController = activityc.newController(result.transactionsModule, events)
result.activityController = activityc.newController(result.transactionsModule, events, currencyService)
result.filter = initFilter(result.controller, result.activityController)
result.view = newView(result, result.activityController)

View File

@ -1,4 +1,4 @@
import NimQml, chronicles, strutils, tables, json
import NimQml, chronicles, strutils, tables, json, stint
import ../../../backend/backend as backend
@ -99,4 +99,23 @@ QtObject:
proc getCurrencyFormat*(self: Service, symbol: string): CurrencyFormatDto =
if not self.currencyFormatCache.hasKey(symbol):
return newCurrencyFormatDto(symbol)
return self.currencyFormatCache[symbol]
return self.currencyFormatCache[symbol]
proc toFloat(amountInt: UInt256): float64 =
return float64(amountInt.truncate(uint64))
proc u256ToFloat(decimals: int, amountInt: UInt256): float64 =
if decimals == 0:
return amountInt.toFloat()
# Convert to float at the end to avoid losing precision
let base = 10.to(UInt256)
let p = base.pow(decimals)
let i = amountInt.div(p)
let r = amountInt.mod(p)
return i.toFloat() + r.toFloat() / p.toFloat()
proc parseCurrencyValue*(self: Service, symbol: string, amountInt: UInt256): float64 =
let decimals = self.tokenService.getTokenDecimals(symbol)
return u256ToFloat(decimals, amountInt)

View File

@ -1,6 +1,7 @@
import times, strformat, options
import json, json_serialization
import core, response_type
import stint
from gen import rpc
import backend
import transactions
@ -148,6 +149,8 @@ type
activityType*: MultiTransactionType
activityStatus*: ActivityStatus
tokenType*: TokenType
amountOut*: UInt256
amountIn*: UInt256
# Mirrors services/wallet/activity/service.go ErrorCode
ErrorCode* = enum
@ -174,7 +177,9 @@ proc fromJson*(e: JsonNode, T: typedesc[ActivityEntry]): ActivityEntry {.inline.
else: none(TransactionIdentity),
id: e["id"].getInt(),
activityStatus: fromJson(e["activityStatus"], ActivityStatus),
timestamp: e["timestamp"].getInt()
timestamp: e["timestamp"].getInt(),
amountOut: stint.fromHex(UInt256, e["amountOut"].getStr()),
amountIn: stint.fromHex(UInt256, e["amountIn"].getStr())
)
proc `$`*(self: ActivityEntry): string =
@ -188,6 +193,8 @@ proc `$`*(self: ActivityEntry): string =
activityType* {$self.activityType},
activityStatus* {$self.activityStatus},
tokenType* {$self.tokenType},
amountOut* {$self.amountOut},
amountIn* {$self.amountIn},
)"""
proc fromJson*(e: JsonNode, T: typedesc[FilterResponse]): FilterResponse {.inline.} =

View File

@ -130,7 +130,7 @@ SplitView {
}
readonly property var totalFees: QtObject {
property real amount: (transactionData.value.amount / 15) * Math.pow(10, 9)
property real amount: (transactionData.value / 15) * Math.pow(10, 9)
property string symbol: "Gwei"
property int displayDecimals: 8
property bool stripTrailingZeroes: true

View File

@ -52,10 +52,10 @@ Item {
readonly property string swapSymbol: "" // TODO fill when swap data is implemented
readonly property string symbol: root.isTransactionValid ? transaction.symbol : ""
readonly property var multichainNetworks: [] // TODO fill icon for networks for multichain
readonly property double cryptoValue: root.isTransactionValid && transaction.value ? transaction.value.amount: 0.0
readonly property double cryptoValue: root.isTransactionValid ? transaction.value : 0.0
readonly property double fiatValue: root.isTransactionValid ? RootStore.getFiatValue(cryptoValue, symbol, RootStore.currentCurrency): 0.0
readonly property string fiatValueFormatted: root.isTransactionValid ? RootStore.formatCurrencyAmount(d.fiatValue, RootStore.currentCurrency) : ""
readonly property string cryptoValueFormatted: root.isTransactionValid && transaction.value ? LocaleUtils.currencyAmountToLocaleString(transaction.value) : ""
readonly property string cryptoValueFormatted: root.isTransactionValid ? RootStore.formatCurrencyAmount(d.cryptoValue, symbol) : ""
readonly property real feeEthValue: root.isTransactionValid && transaction.totalFees ? RootStore.getGasEthValue(transaction.totalFees.amount, 1) : 0
readonly property real feeFiatValue: root.isTransactionValid ? RootStore.getFiatValue(d.feeEthValue, "ETH", RootStore.currentCurrency) : 0
readonly property int transactionType: root.isTransactionValid ? transaction.txType : Constants.TransactionType.Send
@ -278,7 +278,7 @@ Item {
TransactionContractTile {
// Used to display contract address for any network
address: root.isTransactionValid ? transaction.contract : ""
symbol: root.isTransactionValid && transaction.value ? transaction.value.symbol.toUpperCase() : ""
symbol: root.isTransactionValid ? d.symbol : ""
networkName: d.networkFullName
shortNetworkName: d.networkShortName
}
@ -311,7 +311,7 @@ Item {
case Constants.TransactionType.Swap:
return d.swapSymbol
case Constants.TransactionType.Bridge:
return transaction.value.symbol.toUpperCase()
return d.symbol
default:
return ""
}

View File

@ -344,13 +344,14 @@ Control {
spacing: 5
RowLayout {
Label { text: entry.isMultiTransaction ? entry.fromAmount : entry.amount }
Label { text: qsTr("in"); Layout.leftMargin: 5; Layout.rightMargin: 5 }
Label { text: entry.inAmount }
Label { text: qsTr("out"); Layout.leftMargin: 5; Layout.rightMargin: 5 }
Label { text: entry.outAmount }
Label { text: qsTr("from"); Layout.leftMargin: 5; Layout.rightMargin: 5 }
Label { text: entry.sender; Layout.maximumWidth: 200; elide: Text.ElideMiddle }
Label { text: qsTr("to"); Layout.leftMargin: 5; Layout.rightMargin: 5 }
Label { text: entry.recipient; Layout.maximumWidth: 200; elide: Text.ElideMiddle }
Label { text: qsTr("got"); Layout.leftMargin: 5; Layout.rightMargin: 5; visible: entry.isMultiTransaction }
Label { text: entry.toAmount; Layout.leftMargin: 5; Layout.rightMargin: 5; visible: entry.isMultiTransaction }
RowLayout {} // Spacer
}
RowLayout {

View File

@ -275,7 +275,7 @@ ColumnLayout {
width: ListView.view.width
modelData: model.activityEntry
currentCurrency: RootStore.currentCurrency
cryptoValue: isModelDataValid && modelData.value ? modelData.value.amount : 0.0
cryptoValue: isModelDataValid ? modelData.value : 0.0
fiatValue: isModelDataValid ? RootStore.getFiatValue(cryptoValue, symbol, currentCurrency): 0.0
networkIcon: isModelDataValid ? RootStore.getNetworkIcon(modelData.chainId) : ""
networkColor: isModelDataValid ? RootStore.getNetworkColor(modelData.chainId) : ""

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit 51e3d800bb0f334e0d6f6167fd461ebefede458f
Subproject commit 60b160997c7f583c2f1e0ebbe5b995ca117e86f3