feat(@dekstop/wallet): use amounts from activity backend
Part of #11080
This commit is contained in:
parent
a7b78bb6e8
commit
9fc8f66fbd
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.} =
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ""
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) : ""
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 51e3d800bb0f334e0d6f6167fd461ebefede458f
|
||||
Subproject commit 60b160997c7f583c2f1e0ebbe5b995ca117e86f3
|
Loading…
Reference in New Issue