chore(wallet) remove requesting detailed transaction info for activity
Closes #11598
This commit is contained in:
parent
a3b739b81d
commit
8138e5edcf
|
@ -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] = @[]
|
|
||||||
var transactionIdentities: seq[backend.TransactionIdentity] = @[]
|
|
||||||
var pendingTransactionIdentities: seq[backend.TransactionIdentity] = @[]
|
|
||||||
|
|
||||||
# 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:
|
|
||||||
case backendEntry.payloadType:
|
|
||||||
of MultiTransaction:
|
|
||||||
multiTransactionsIds.add(backendEntry.id)
|
|
||||||
of SimpleTransaction:
|
|
||||||
transactionIdentities.add(backendEntry.transaction.get())
|
|
||||||
of PendingTransaction:
|
|
||||||
pendingTransactionIdentities.add(backendEntry.transaction.get())
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
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
|
|
||||||
var tIndex = 0
|
|
||||||
var ptIndex = 0
|
|
||||||
for backendEntry in backendEntities:
|
for backendEntry in backendEntities:
|
||||||
case backendEntry.payloadType:
|
var ae: entry.ActivityEntry
|
||||||
|
case backendEntry.getPayloadType():
|
||||||
of MultiTransaction:
|
of MultiTransaction:
|
||||||
let id = multiTransactionsIds[mtIndex]
|
let extraData = self.buildMultiTransactionExtraData(backendEntry)
|
||||||
if multiTransactions.hasKey(id):
|
ae = entry.newMultiTransactionActivityEntry(backendEntry, extraData, amountToCurrencyConvertor)
|
||||||
let mt = multiTransactions[id]
|
of SimpleTransaction, PendingTransaction:
|
||||||
let extraData = self.buildMultiTransactionExtraData(backendEntry, mt)
|
let extraData = self.buildTransactionExtraData(backendEntry)
|
||||||
result.add(entry.newMultiTransactionActivityEntry(mt, backendEntry, extraData, amountToCurrencyConvertor))
|
ae = entry.newTransactionActivityEntry(backendEntry, self.addresses, extraData, amountToCurrencyConvertor)
|
||||||
else:
|
result.add(ae)
|
||||||
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.} =
|
proc fetchTxDetails*(self: Controller, entryIndex: int) {.slot.} =
|
||||||
self.activityDetails = newActivityDetails(id, isMultiTx)
|
let amountToCurrencyConvertor = proc(amount: UInt256, symbol: string): CurrencyAmount =
|
||||||
if isPending:
|
return currencyAmountToItem(self.currencyService.parseCurrencyValue(symbol, amount),
|
||||||
|
self.currencyService.getCurrencyFormat(symbol))
|
||||||
|
|
||||||
|
let entry = self.model.getEntry(entryIndex)
|
||||||
|
if entry == nil:
|
||||||
|
error "failed to find entry with index: ", entryIndex
|
||||||
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
|
||||||
|
|
|
@ -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
|
||||||
|
@ -178,7 +147,7 @@ QtObject:
|
||||||
|
|
||||||
QtProperty[int] chainIdIn:
|
QtProperty[int] chainIdIn:
|
||||||
read = getChainIdIn
|
read = getChainIdIn
|
||||||
|
|
||||||
proc getChainIdOut*(self: ActivityEntry): int {.slot.} =
|
proc getChainIdOut*(self: ActivityEntry): int {.slot.} =
|
||||||
return self.metadata.chainIdOut.get(ChainId(0)).int
|
return self.metadata.chainIdOut.get(ChainId(0)).int
|
||||||
|
|
||||||
|
@ -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,13 +231,13 @@ 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 ""
|
||||||
|
|
||||||
var tokenId: Option[TokenID]
|
var tokenId: Option[TokenID]
|
||||||
if self.isInTransactionType():
|
if self.isInTransactionType():
|
||||||
if self.metadata.tokenIn.isSome():
|
if self.metadata.tokenIn.isSome():
|
||||||
tokenId = self.metadata.tokenIn.unsafeGet().tokenId
|
tokenId = self.metadata.tokenIn.unsafeGet().tokenId
|
||||||
elif self.metadata.tokenOut.isSome():
|
elif self.metadata.tokenOut.isSome():
|
||||||
tokenId = self.metadata.tokenOut.unsafeGet().tokenId
|
tokenId = self.metadata.tokenOut.unsafeGet().tokenId
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue