chore(wallet) remove requesting detailed transaction info for activity

Closes #11598
This commit is contained in:
Stefan 2023-08-29 19:57:38 +01:00 committed by Stefan Dunca
parent a3b739b81d
commit 8138e5edcf
10 changed files with 140 additions and 222 deletions

View File

@ -74,136 +74,45 @@ QtObject:
QtProperty[QVariant] recipientsModel: QtProperty[QVariant] recipientsModel:
read = getRecipientsModel read = getRecipientsModel
proc buildMultiTransactionExtraData(self: Controller, metadata: backend_activity.ActivityEntry, item: MultiTransactionDto): ExtraData = proc buildMultiTransactionExtraData(self: Controller, metadata: backend_activity.ActivityEntry): ExtraData =
if metadata.symbolIn.isSome(): if metadata.symbolIn.isSome():
result.inAmount = self.currencyService.parseCurrencyValue(metadata.symbolIn.get(), metadata.amountIn) result.inAmount = self.currencyService.parseCurrencyValue(metadata.symbolIn.get(), metadata.amountIn)
if metadata.symbolOut.isSome(): if metadata.symbolOut.isSome():
result.outAmount = self.currencyService.parseCurrencyValue(metadata.symbolOut.get(), metadata.amountOut) result.outAmount = self.currencyService.parseCurrencyValue(metadata.symbolOut.get(), metadata.amountOut)
proc buildTransactionExtraData(self: Controller, metadata: backend_activity.ActivityEntry, item: ref TransactionDto): ExtraData = proc buildTransactionExtraData(self: Controller, metadata: backend_activity.ActivityEntry): ExtraData =
if metadata.symbolIn.isSome(): if metadata.symbolIn.isSome():
result.inAmount = self.currencyService.parseCurrencyValue(metadata.symbolIn.get(), metadata.amountIn) result.inAmount = self.currencyService.parseCurrencyValue(metadata.symbolIn.get(), metadata.amountIn)
if metadata.symbolOut.isSome(): if metadata.symbolOut.isSome():
result.outAmount = self.currencyService.parseCurrencyValue(metadata.symbolOut.get(), metadata.amountOut) result.outAmount = self.currencyService.parseCurrencyValue(metadata.symbolOut.get(), metadata.amountOut)
proc getResolvedSymbol(self: Controller, transaction: TransactionDto): string =
if transaction.symbol != "":
result = transaction.symbol
else:
let contractSymbol = self.tokenService.findTokenSymbolByAddress(transaction.contract)
if contractSymbol != "":
result = contractSymbol
else:
result = "ETH"
proc backendToPresentation(self: Controller, backendEntities: seq[backend_activity.ActivityEntry]): seq[entry.ActivityEntry] = proc backendToPresentation(self: Controller, backendEntities: seq[backend_activity.ActivityEntry]): seq[entry.ActivityEntry] =
var multiTransactionsIds: seq[int] = @[] let amountToCurrencyConvertor = proc(amount: UInt256, symbol: string): CurrencyAmount =
var transactionIdentities: seq[backend.TransactionIdentity] = @[] return currencyAmountToItem(self.currencyService.parseCurrencyValue(symbol, amount),
var pendingTransactionIdentities: seq[backend.TransactionIdentity] = @[] self.currencyService.getCurrencyFormat(symbol))
# Extract metadata required to fetch details
# TODO: see #11598. Temporary here to show the working API. Details for each entry will be done as required
# on a detail request from UI after metadata is extended to include the required info
for backendEntry in backendEntities: for backendEntry in backendEntities:
case backendEntry.payloadType: var ae: entry.ActivityEntry
case backendEntry.getPayloadType():
of MultiTransaction: of MultiTransaction:
multiTransactionsIds.add(backendEntry.id) let extraData = self.buildMultiTransactionExtraData(backendEntry)
of SimpleTransaction: ae = entry.newMultiTransactionActivityEntry(backendEntry, extraData, amountToCurrencyConvertor)
transactionIdentities.add(backendEntry.transaction.get()) of SimpleTransaction, PendingTransaction:
of PendingTransaction: let extraData = self.buildTransactionExtraData(backendEntry)
pendingTransactionIdentities.add(backendEntry.transaction.get()) ae = entry.newTransactionActivityEntry(backendEntry, self.addresses, extraData, amountToCurrencyConvertor)
result.add(ae)
var multiTransactions = initTable[int, MultiTransactionDto]()
if len(multiTransactionsIds) > 0:
let mts = transaction_service.getMultiTransactions(multiTransactionsIds)
for mt in mts:
multiTransactions[mt.id] = mt
var transactions = initTable[TransactionIdentity, ref TransactionDto]()
if len(transactionIdentities) > 0:
let response = backend.getTransfersForIdentities(transactionIdentities)
let res = response.result
if response.error != nil or res.kind != JArray or res.len == 0:
error "failed fetching transaction details; err: ", response.error, ", kind: ", res.kind, ", res.len: ", res.len
let transactionsDtos = res.getElems().map(x => x.toTransactionDto())
for dto in transactionsDtos:
transactions[TransactionIdentity(chainId: dto.chainId, hash: dto.id, address: dto.address)] = toRef(dto)
var pendingTransactions = initTable[TransactionIdentity, ref TransactionDto]()
if len(pendingTransactionIdentities) > 0:
let response = backend.getPendingTransactionsForIdentities(pendingTransactionIdentities)
let res = response.result
if response.error != nil or res.kind != JArray or res.len == 0:
error "failed fetching pending transactions details; err: ", response.error, ", kind: ", res.kind, ", res.len: ", res.len
let pendingTransactionsDtos = res.getElems().map(x => x.toPendingTransactionDto())
for dto in pendingTransactionsDtos:
pendingTransactions[TransactionIdentity(chainId: dto.chainId, hash: dto.id, address: dto.address)] = toRef(dto)
# Merge detailed transaction info in order
result = newSeqOfCap[entry.ActivityEntry](multiTransactions.len + transactions.len + pendingTransactions.len)
proc fetchTxDetails*(self: Controller, entryIndex: int) {.slot.} =
let amountToCurrencyConvertor = proc(amount: UInt256, symbol: string): CurrencyAmount = let amountToCurrencyConvertor = proc(amount: UInt256, symbol: string): CurrencyAmount =
return currencyAmountToItem(self.currencyService.parseCurrencyValue(symbol, amount), return currencyAmountToItem(self.currencyService.parseCurrencyValue(symbol, amount),
self.currencyService.getCurrencyFormat(symbol)) self.currencyService.getCurrencyFormat(symbol))
var mtIndex = 0 let entry = self.model.getEntry(entryIndex)
var tIndex = 0 if entry == nil:
var ptIndex = 0 error "failed to find entry with index: ", entryIndex
for backendEntry in backendEntities:
case backendEntry.payloadType:
of MultiTransaction:
let id = multiTransactionsIds[mtIndex]
if multiTransactions.hasKey(id):
let mt = multiTransactions[id]
let extraData = self.buildMultiTransactionExtraData(backendEntry, mt)
result.add(entry.newMultiTransactionActivityEntry(mt, backendEntry, extraData, amountToCurrencyConvertor))
else:
error "failed to find multi transaction with id: ", id
mtIndex += 1
of SimpleTransaction:
let identity = transactionIdentities[tIndex]
if transactions.hasKey(identity):
let tr = transactions[identity]
tr.symbol = self.getResolvedSymbol(tr[])
let extraData = self.buildTransactionExtraData(backendEntry, tr)
result.add(entry.newTransactionActivityEntry(tr, backendEntry, self.addresses, extraData, amountToCurrencyConvertor))
else:
error "failed to find transaction with identity: ", identity
tIndex += 1
of PendingTransaction:
let identity = pendingTransactionIdentities[ptIndex]
if pendingTransactions.hasKey(identity):
let tr = pendingTransactions[identity]
tr.symbol = self.getResolvedSymbol(tr[])
let extraData = self.buildTransactionExtraData(backendEntry, tr)
result.add(entry.newTransactionActivityEntry(tr, backendEntry, self.addresses, extraData, amountToCurrencyConvertor))
else:
error "failed to find pending transaction with identity: ", identity
ptIndex += 1
proc fetchTxDetails*(self: Controller, id: string, isMultiTx: bool, isPending: bool) {.slot.} =
self.activityDetails = newActivityDetails(id, isMultiTx)
if isPending:
return return
try: try:
let amountToCurrencyConvertor = proc(amount: UInt256, symbol: string): CurrencyAmount = self.activityDetails = newActivityDetails(entry.getMetadata(), amountToCurrencyConvertor)
return currencyAmountToItem(self.currencyService.parseCurrencyValue(symbol, amount),
self.currencyService.getCurrencyFormat(symbol))
if isMultiTx:
let res = backend_activity.getMultiTxDetails(parseInt(id))
if res.error != nil:
error "failed to fetch multi tx details: ", id
return
self.activityDetails = newActivityDetails(res.result, amountToCurrencyConvertor)
else:
let res = backend_activity.getTxDetails(id)
if res.error != nil:
error "failed to fetch tx details: ", id
return
self.activityDetails = newActivityDetails(res.result, amountToCurrencyConvertor)
except Exception as e: except Exception as e:
let errDescription = e.msg let errDescription = e.msg
error "error: ", errDescription error "error: ", errDescription

View File

@ -1,12 +1,10 @@
import NimQml, json, strformat, sequtils, strutils, logging, stint import NimQml, json, strformat, sequtils, strutils, logging, stint
import backend/transactions
import backend/activity as backend import backend/activity as backend
import app/modules/shared_models/currency_amount import app/modules/shared_models/currency_amount
import app/global/global_singleton import app/global/global_singleton
import app_service/service/transaction/dto
import app_service/service/currency/dto as currency import app_service/service/currency/dto as currency
import app_service/service/currency/service import app_service/service/currency/service
@ -22,22 +20,10 @@ type
AmountToCurrencyConvertor* = proc (amount: UInt256, symbol: string): CurrencyAmount AmountToCurrencyConvertor* = proc (amount: UInt256, symbol: string): CurrencyAmount
# It is used to display an activity history entry in the QML UI # Used to display an activity history header entry in the QML UI
#
# TODO remove this legacy after the NFT is served async; see #11598
#
# Looking into going away from carying the whole detailed data and just keep the required data for the UI
# and request the detailed data on demand
#
# Outdated: The ActivityEntry contains one of the following instances transaction, pending transaction or multi-transaction
QtObject: QtObject:
type type
ActivityEntry* = ref object of QObject ActivityEntry* = ref object of QObject
# TODO: these should be removed; see #11598
multi_transaction: MultiTransactionDto
transaction: ref TransactionDto
isPending: bool
valueConvertor: AmountToCurrencyConvertor valueConvertor: AmountToCurrencyConvertor
metadata: backend.ActivityEntry metadata: backend.ActivityEntry
extradata: ExtraData extradata: ExtraData
@ -54,74 +40,57 @@ QtObject:
proc delete*(self: ActivityEntry) = proc delete*(self: ActivityEntry) =
self.QObject.delete self.QObject.delete
proc newMultiTransactionActivityEntry*(mt: MultiTransactionDto, metadata: backend.ActivityEntry, extradata: ExtraData, valueConvertor: AmountToCurrencyConvertor): ActivityEntry = proc newMultiTransactionActivityEntry*(metadata: backend.ActivityEntry, extradata: ExtraData, valueConvertor: AmountToCurrencyConvertor): ActivityEntry =
new(result, delete) new(result, delete)
result.multi_transaction = mt
result.transaction = nil
result.isPending = false
result.valueConvertor = valueConvertor result.valueConvertor = valueConvertor
result.metadata = metadata result.metadata = metadata
result.extradata = extradata result.extradata = extradata
result.noAmount = newCurrencyAmount() result.noAmount = newCurrencyAmount()
result.amountCurrency = valueConvertor( result.amountCurrency = valueConvertor(
if metadata.activityType == backend.ActivityType.Receive: metadata.amountIn else: metadata.amountOut, if metadata.activityType == backend.ActivityType.Receive: metadata.amountIn else: metadata.amountOut,
if metadata.activityType == backend.ActivityType.Receive: mt.toAsset else: mt.fromAsset, if metadata.activityType == backend.ActivityType.Receive: metadata.symbolIn.get("") else: metadata.symbolOut.get(""),
) )
result.setup() result.setup()
proc newTransactionActivityEntry*(tr: ref TransactionDto, metadata: backend.ActivityEntry, fromAddresses: seq[string], extradata: ExtraData, valueConvertor: AmountToCurrencyConvertor): ActivityEntry = proc newTransactionActivityEntry*(metadata: backend.ActivityEntry, fromAddresses: seq[string], extradata: ExtraData, valueConvertor: AmountToCurrencyConvertor): ActivityEntry =
new(result, delete) new(result, delete)
result.multi_transaction = nil
result.transaction = tr
result.isPending = metadata.payloadType == backend.PayloadType.PendingTransaction
result.valueConvertor = valueConvertor result.valueConvertor = valueConvertor
result.metadata = metadata result.metadata = metadata
result.extradata = extradata result.extradata = extradata
result.amountCurrency = valueConvertor( result.amountCurrency = valueConvertor(
if metadata.activityType == backend.ActivityType.Receive: metadata.amountIn else: metadata.amountOut, if metadata.activityType == backend.ActivityType.Receive: metadata.amountIn else: metadata.amountOut,
tr.symbol if metadata.activityType == backend.ActivityType.Receive: metadata.symbolIn.get("") else: metadata.symbolOut.get(""),
) )
result.noAmount = newCurrencyAmount() result.noAmount = newCurrencyAmount()
result.setup() result.setup()
proc isMultiTransaction*(self: ActivityEntry): bool {.slot.} = proc isMultiTransaction*(self: ActivityEntry): bool {.slot.} =
return self.multi_transaction != nil return self.metadata.getPayloadType() == backend.PayloadType.MultiTransaction
QtProperty[bool] isMultiTransaction: QtProperty[bool] isMultiTransaction:
read = isMultiTransaction read = isMultiTransaction
proc isPendingTransaction*(self: ActivityEntry): bool {.slot.} = proc isPendingTransaction*(self: ActivityEntry): bool {.slot.} =
return (not self.isMultiTransaction()) and self.isPending return self.metadata.getPayloadType() == backend.PayloadType.PendingTransaction
QtProperty[bool] isPendingTransaction: QtProperty[bool] isPendingTransaction:
read = isPendingTransaction read = isPendingTransaction
proc `$`*(self: ActivityEntry): string = proc `$`*(self: ActivityEntry): string =
let mtStr = if self.multi_transaction != nil: $(self.multi_transaction.id) else: "0"
let trStr = if self.transaction != nil: $(self.transaction[]) else: "nil"
return fmt"""ActivityEntry( return fmt"""ActivityEntry(
multi_transaction.id:{mtStr}, metadata:{$self.metadata},
transaction:{trStr},
isPending:{self.isPending}
)""" )"""
proc isInTransactionType(self: ActivityEntry): bool = proc isInTransactionType(self: ActivityEntry): bool =
return self.metadata.activityType == backend.ActivityType.Receive or self.metadata.activityType == backend.ActivityType.Mint return self.metadata.activityType == backend.ActivityType.Receive or self.metadata.activityType == backend.ActivityType.Mint
proc getMultiTransaction*(self: ActivityEntry): MultiTransactionDto = # TODO: is this the right way to pass transaction identity? Why not use the instance?
if not self.isMultiTransaction():
raise newException(Defect, "ActivityEntry is not a MultiTransaction")
return self.multi_transaction
proc getId*(self: ActivityEntry): string {.slot.} = proc getId*(self: ActivityEntry): string {.slot.} =
if self.isMultiTransaction(): if self.isMultiTransaction():
return $self.multi_transaction.id return $(self.metadata.getMultiTransactionId().get())
elif self.transaction != nil: return $(self.metadata.getTransactionIdentity().get().hash)
return self.transaction[].id
return ""
QtProperty[string] id: QtProperty[string] id:
read = getId read = getId
@ -233,20 +202,6 @@ QtObject:
QtProperty[int] txType: QtProperty[int] txType:
read = getTxType read = getTxType
proc getTokenType*(self: ActivityEntry): string {.slot.} =
let s = if self.transaction != nil: self.transaction[].symbol else: ""
if self.transaction != nil:
return self.transaction[].typeValue
if self.isInTransactionType() and self.metadata.tokenOut.isSome:
return $self.metadata.tokenOut.unsafeGet().tokenType
if self.metadata.tokenIn.isSome:
return $self.metadata.tokenIn.unsafeGet().tokenType
return ""
# TODO: used only in details, move it to a entry_details.nim. See #11598
QtProperty[string] tokenType:
read = getTokenType
proc getTokenInAddress*(self: ActivityEntry): string {.slot.} = proc getTokenInAddress*(self: ActivityEntry): string {.slot.} =
if self.metadata.tokenIn.isSome: if self.metadata.tokenIn.isSome:
let address = self.metadata.tokenIn.unsafeGet().address let address = self.metadata.tokenIn.unsafeGet().address
@ -276,7 +231,7 @@ QtObject:
read = getTokenAddress read = getTokenAddress
proc getTokenID*(self: ActivityEntry): string {.slot.} = proc getTokenID*(self: ActivityEntry): string {.slot.} =
if self.metadata.payloadType == backend.PayloadType.MultiTransaction: if self.metadata.getPayloadType() == backend.PayloadType.MultiTransaction:
error "getTokenID: ActivityEntry is not a transaction" error "getTokenID: ActivityEntry is not a transaction"
return "" return ""

View File

@ -1,6 +1,7 @@
import NimQml, json, stint, strutils import NimQml, json, stint, strutils, logging, options
import backend/activity as backend import backend/activity as backend
import backend/backend as common_backend
import app/modules/shared_models/currency_amount import app/modules/shared_models/currency_amount
@ -14,6 +15,10 @@ QtObject:
type type
ActivityDetails* = ref object of QObject ActivityDetails* = ref object of QObject
id*: string id*: string
metadata: backend.ActivityEntry
# TODO use medatada
multiTxId: int multiTxId: int
nonce*: int nonce*: int
blockNumber*: int blockNumber*: int
@ -33,41 +38,57 @@ QtObject:
proc getMaxTotalFees(maxFee: string, gasLimit: string): string = proc getMaxTotalFees(maxFee: string, gasLimit: string): string =
return (stint.fromHex(Uint256, maxFee) * stint.fromHex(Uint256, gasLimit)).toHex return (stint.fromHex(Uint256, maxFee) * stint.fromHex(Uint256, gasLimit)).toHex
proc newActivityDetails*(id: string, isMultiTx: bool): ActivityDetails = proc newActivityDetails*(metadata: backend.ActivityEntry, valueConvertor: AmountToCurrencyConvertor): ActivityDetails =
new(result, delete) new(result, delete)
if isMultiTx: defer: result.setup()
result.multiTxId = parseInt(id)
else:
result.id = id
result.maxTotalFees = newCurrencyAmount() result.maxTotalFees = newCurrencyAmount()
result.totalFees = newCurrencyAmount() result.totalFees = newCurrencyAmount()
result.setup()
proc newActivityDetails*(e: JsonNode, valueConvertor: AmountToCurrencyConvertor): ActivityDetails = var e: JsonNode
new(result, delete) case metadata.getPayloadType():
of PendingTransaction:
result.id = metadata.getTransactionIdentity().get().hash
return
of MultiTransaction:
result.multiTxId = metadata.getMultiTransactionId.get(0)
let res = backend.getMultiTxDetails(metadata.getMultiTransactionId().get(0))
if res.error != nil:
error "failed to fetch multi tx details: ", metadata.getMultiTransactionId()
return
e = res.result
of SimpleTransaction:
let res = backend.getTxDetails(metadata.getTransactionIdentity().get().hash)
if res.error != nil:
error "failed to fetch tx details: ", metadata.getTransactionIdentity().get().hash
return
e = res.result
const protocolTypeField = "protocolType" const protocolTypeField = "protocolType"
const hashField = "hash" const hashField = "hash"
const contractAddressField = "contractAddress" const contractAddressField = "contractAddress"
const inputField = "input" const inputField = "input"
const totalFeesField = "totalFees" const totalFeesField = "totalFees"
result = ActivityDetails( result.id = e["id"].getStr()
id: e["id"].getStr(), result.multiTxId = e["multiTxId"].getInt()
multiTxId: e["multiTxId"].getInt(), result.nonce = e["nonce"].getInt()
nonce: e["nonce"].getInt(), result.blockNumber = e["blockNumber"].getInt()
blockNumber: e["blockNumber"].getInt()
)
let maxFeePerGas = e["maxFeePerGas"].getStr() let maxFeePerGas = e["maxFeePerGas"].getStr()
let gasLimit = e["gasLimit"].getStr() let gasLimit = e["gasLimit"].getStr()
const gweiSymbol = "Gwei"
if len(maxFeePerGas) > 0 and len(gasLimit) > 0: if len(maxFeePerGas) > 0 and len(gasLimit) > 0:
let maxTotalFees = getMaxTotalFees(maxFeePerGas, gasLimit) let maxTotalFees = getMaxTotalFees(maxFeePerGas, gasLimit)
result.maxTotalFees = valueConvertor(stint.fromHex(UInt256, maxTotalFees), "Gwei") result.maxTotalFees = valueConvertor(stint.fromHex(UInt256, maxTotalFees), gweiSymbol)
else:
result.maxTotalFees = newCurrencyAmount()
if e.hasKey(totalFeesField) and e[totalFeesField].kind != JNull: if e.hasKey(totalFeesField) and e[totalFeesField].kind != JNull:
let totalFees = e[totalFeesField].getStr() let totalFees = e[totalFeesField].getStr()
result.totalFees = valueConvertor(stint.fromHex(UInt256, totalFees), "Gwei") let resTotalFees = valueConvertor(stint.fromHex(UInt256, totalFees), gweiSymbol)
if resTotalFees != nil:
result.totalFees = resTotalFees
if e.hasKey(hashField) and e[hashField].kind != JNull: if e.hasKey(hashField) and e[hashField].kind != JNull:
result.txHash = e[hashField].getStr() result.txHash = e[hashField].getStr()
@ -79,8 +100,6 @@ QtObject:
var contractAddress: eth.Address var contractAddress: eth.Address
fromJson(e[contractAddressField], contractAddressField, contractAddress) fromJson(e[contractAddressField], contractAddressField, contractAddress)
result.contractAddress = some(contractAddress) result.contractAddress = some(contractAddress)
result.setup()
proc getNonce*(self: ActivityDetails): int {.slot.} = proc getNonce*(self: ActivityDetails): int {.slot.} =
return self.nonce return self.nonce
@ -131,3 +150,14 @@ QtObject:
QtProperty[QVariant] totalFees: QtProperty[QVariant] totalFees:
read = getTotalFees read = getTotalFees
proc getTokenType*(self: ActivityDetails): string {.slot.} =
if self.metadata.tokenIn.isSome:
return $self.metadata.tokenIn.get().tokenType
if self.metadata.tokenOut.isSome:
return $self.metadata.tokenOut.get().tokenType
return ""
QtProperty[string] tokenType:
read = getTokenType

View File

@ -35,6 +35,12 @@ QtObject:
for i in 0 ..< self.entries.len: for i in 0 ..< self.entries.len:
result &= fmt"""[{i}]:({$self.entries[i]})""" result &= fmt"""[{i}]:({$self.entries[i]})"""
proc getEntry*(self: Model, index: int): entry.ActivityEntry =
if index < 0 or index >= self.entries.len:
return nil
return self.entries[index]
proc countChanged(self: Model) {.signal.} proc countChanged(self: Model) {.signal.}
proc getCount*(self: Model): int {.slot.} = proc getCount*(self: Model): int {.slot.} =
@ -97,13 +103,13 @@ QtObject:
proc sameIdentity(e: entry.ActivityEntry, d: backend.Data): bool = proc sameIdentity(e: entry.ActivityEntry, d: backend.Data): bool =
let m = e.getMetadata() let m = e.getMetadata()
if m.payloadType != d.payloadType: if m.getPayloadType() != d.payloadType:
return false return false
if m.payloadType == MultiTransaction: if m.getPayloadType() == MultiTransaction:
return m.id == d.id.get() return m.getMultiTransactionId().get(0) == d.id.get()
return m.transaction.isSome() and d.transaction.isSome() and m.transaction.get() == d.transaction.get() return m.getTransactionIdentity().isSome() and d.transaction.isSome() and m.getTransactionIdentity().get() == d.transaction.get()
proc updateEntries*(self: Model, updates: seq[backend.Data]) = proc updateEntries*(self: Model, updates: seq[backend.Data]) =
for i in countdown(self.entries.high, 0): for i in countdown(self.entries.high, 0):

View File

@ -253,14 +253,13 @@ proc `%`*(pt: TransferType): JsonNode {.inline.} =
proc fromJson*(jn: JsonNode, T: typedesc[TransferType]): TransferType {.inline.} = proc fromJson*(jn: JsonNode, T: typedesc[TransferType]): TransferType {.inline.} =
return cast[TransferType](jn.getInt()) return cast[TransferType](jn.getInt())
# TODO: hide internals behind safe interface
# Mirrors status-go/services/wallet/activity/activity.go Entry # Mirrors status-go/services/wallet/activity/activity.go Entry
type type
ActivityEntry* = object ActivityEntry* = object
# Identification # Identification
payloadType*: PayloadType payloadType: PayloadType
transaction*: Option[TransactionIdentity] transaction: Option[TransactionIdentity]
id*: int id: int
timestamp*: int timestamp*: int
@ -322,6 +321,19 @@ type
hasMore*: bool hasMore*: bool
errorCode*: ErrorCode errorCode*: ErrorCode
proc getPayloadType*(ae: ActivityEntry): PayloadType =
return ae.payloadType
proc getTransactionIdentity*(ae: ActivityEntry): Option[TransactionIdentity] =
if ae.payloadType == PayloadType.MultiTransaction:
return none(TransactionIdentity)
return ae.transaction
proc getMultiTransactionId*(ae: ActivityEntry): Option[int] =
if ae.payloadType != PayloadType.MultiTransaction:
return none(int)
return some(ae.id)
proc toJson*(ae: ActivityEntry): JsonNode {.inline.} = proc toJson*(ae: ActivityEntry): JsonNode {.inline.} =
return %*(ae) return %*(ae)

View File

@ -137,8 +137,10 @@ Item {
HistoryView { HistoryView {
overview: RootStore.overview overview: RootStore.overview
showAllAccounts: root.showAllAccounts showAllAccounts: root.showAllAccounts
onLaunchTransactionDetail: { onLaunchTransactionDetail: function (entry, entryIndex) {
transactionDetailView.transaction = transaction transactionDetailView.transactionIndex = entryIndex
transactionDetailView.transaction = entry
stack.currentIndex = 3 stack.currentIndex = 3
} }
} }

View File

@ -27,23 +27,13 @@ Item {
property var overview: WalletStores.RootStore.overview property var overview: WalletStores.RootStore.overview
property var contactsStore property var contactsStore
property var transaction property var transaction
property int transactionIndex
property var sendModal property var sendModal
property bool showAllAccounts: false property bool showAllAccounts: false
readonly property bool isTransactionValid: transaction !== undefined && !!transaction readonly property bool isTransactionValid: transaction !== undefined && !!transaction
onTransactionChanged: { onTransactionChanged: d.updateTransactionDetails()
d.decodedInputData = "" Component.onCompleted: d.updateTransactionDetails()
if (!transaction)
return
RootStore.fetchTxDetails(transaction.id, transaction.isMultiTransaction, transaction.isPending)
d.details = RootStore.getTxDetails()
if (!!d.details && !!d.details.input) {
d.loadingInputDate = true
RootStore.fetchDecodedTxData(d.details.txHash, d.details.input)
}
}
QtObject { QtObject {
id: d id: d
@ -83,7 +73,7 @@ Item {
const formatted = RootStore.formatCurrencyAmount(transaction.outAmount, transaction.outSymbol) const formatted = RootStore.formatCurrencyAmount(transaction.outAmount, transaction.outSymbol)
return outSymbol || !transaction.tokenOutAddress ? formatted : "%1 (%2)".arg(formatted).arg(Utils.compactAddress(transaction.tokenOutAddress, 4)) return outSymbol || !transaction.tokenOutAddress ? formatted : "%1 (%2)".arg(formatted).arg(Utils.compactAddress(transaction.tokenOutAddress, 4))
} }
readonly property real feeEthValue: root.isTransactionValid ? RootStore.getFeeEthValue(d.details.totalFees) : 0 readonly property real feeEthValue: d.details ? RootStore.getFeeEthValue(d.details.totalFees) : 0
readonly property real feeFiatValue: root.isTransactionValid ? RootStore.getFiatValue(d.feeEthValue, Constants.ethToken, RootStore.currentCurrency) : 0 // TODO use directly? readonly property real feeFiatValue: root.isTransactionValid ? RootStore.getFiatValue(d.feeEthValue, Constants.ethToken, RootStore.currentCurrency) : 0 // TODO use directly?
readonly property int transactionType: root.isTransactionValid ? transaction.txType : Constants.TransactionType.Send readonly property int transactionType: root.isTransactionValid ? transaction.txType : Constants.TransactionType.Send
readonly property bool isBridge: d.transactionType === Constants.TransactionType.Bridge readonly property bool isBridge: d.transactionType === Constants.TransactionType.Bridge
@ -94,6 +84,20 @@ Item {
function retryTransaction() { function retryTransaction() {
// TODO handle failed transaction retry // TODO handle failed transaction retry
} }
function updateTransactionDetails() {
d.decodedInputData = ""
if (!transaction)
return
RootStore.fetchTxDetails(transactionIndex)
d.details = RootStore.getTxDetails()
if (!!d.details && !!d.details.input) {
d.loadingInputDate = true
RootStore.fetchDecodedTxData(d.details.txHash, d.details.input)
}
}
} }
Connections { Connections {
@ -459,7 +463,7 @@ Item {
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
title: qsTr("Token format") title: qsTr("Token format")
subTitle: root.isTransactionValid ? transaction.tokenType.toUpperCase() : "" subTitle: root.isTransactionValid ? d.details.tokenType.toUpperCase() : ""
visible: !!subTitle visible: !!subTitle
} }
TransactionDataTile { TransactionDataTile {
@ -634,7 +638,7 @@ Item {
case Constants.TransactionType.Send: case Constants.TransactionType.Send:
case Constants.TransactionType.Swap: case Constants.TransactionType.Swap:
case Constants.TransactionType.Bridge: case Constants.TransactionType.Bridge:
return LocaleUtils.currencyAmountToLocaleString(d.details.totalFees) return d.details ? LocaleUtils.currencyAmountToLocaleString(d.details.totalFees) : ""
default: default:
return "" return ""
} }

View File

@ -170,7 +170,7 @@ StatusListItem {
function getDetailsString(detailsObj) { function getDetailsString(detailsObj) {
if (!detailsObj) { if (!detailsObj) {
rootStore.fetchTxDetails(modelData.id, modelData.isMultiTransaction, modelData.isPending) rootStore.fetchTxDetails(index)
detailsObj = rootStore.getTxDetails() detailsObj = rootStore.getTxDetails()
} }

View File

@ -247,8 +247,8 @@ QtObject {
walletSectionInst.fetchDecodedTxData(txHash, input) walletSectionInst.fetchDecodedTxData(txHash, input)
} }
function fetchTxDetails(id, isMultiTx, isPending) { function fetchTxDetails(modelIndex) {
walletSectionInst.activityController.fetchTxDetails(id, isMultiTx, isPending) walletSectionInst.activityController.fetchTxDetails(modelIndex)
} }
function getTxDetails() { function getTxDetails() {

View File

@ -29,7 +29,7 @@ ColumnLayout {
property var overview property var overview
property bool showAllAccounts: false property bool showAllAccounts: false
signal launchTransactionDetail(var transaction) signal launchTransactionDetail(var transaction, int entryIndex)
onVisibleChanged: { onVisibleChanged: {
if (!visible) if (!visible)
@ -356,7 +356,7 @@ ColumnLayout {
if (mouse.button === Qt.RightButton) { if (mouse.button === Qt.RightButton) {
delegateMenu.openMenu(this, mouse, modelData) delegateMenu.openMenu(this, mouse, modelData)
} else { } else {
launchTransactionDetail(modelData) launchTransactionDetail(modelData, index)
} }
} }
} }