chore(wallet) optimize fetching request by using metadata

Use metadata instead of details for displaying activity headers.

Bump status-go to include the required API changes

Closes #11173
This commit is contained in:
Stefan 2023-07-18 16:59:35 +01:00 committed by Stefan Dunca
parent 45784cf0cd
commit 03923b223b
3 changed files with 85 additions and 37 deletions

View File

@ -1,4 +1,4 @@
import NimQml, json, strformat, sequtils, strutils, logging, stint, strutils
import NimQml, json, strformat, sequtils, strutils, logging, stint, options
import ../transactions/view
import ../transactions/item
@ -6,6 +6,8 @@ import ./backend/transactions
import backend/activity as backend
import ../../../shared_models/currency_amount
import web3/ethtypes as eth
# Additional data needed to build an Entry, which is
# not included in the metadata and needs to be
# fetched from a different source.
@ -19,7 +21,7 @@ type
# It is used to display an activity history entry in the QML UI
#
# TODO add all required metadata from filtering
# 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
@ -93,23 +95,13 @@ QtObject:
return self.transaction
proc getSender*(self: ActivityEntry): string {.slot.} =
if self.isMultiTransaction():
return self.multi_transaction.fromAddress
if self.transaction == nil:
error "getSender: ActivityEntry is not an transaction.Item"
return ""
return self.transaction[].getfrom()
return if self.metadata.sender.isSome(): "0x" & self.metadata.sender.unsafeGet().toHex() else: ""
QtProperty[string] sender:
read = getSender
proc getRecipient*(self: ActivityEntry): string {.slot.} =
if self.isMultiTransaction():
return self.multi_transaction.toAddress
if self.transaction == nil:
error "getRecipient: ActivityEntry is not an transaction.Item"
return ""
return self.transaction[].getTo()
return if self.metadata.recipient.isSome(): "0x" & self.metadata.recipient.unsafeGet().toHex() else: ""
QtProperty[string] recipient:
read = getRecipient
@ -135,13 +127,7 @@ QtObject:
read = getSymbol
proc getTimestamp*(self: ActivityEntry): int {.slot.} =
if self.isMultiTransaction():
return self.multi_transaction.timestamp
if self.transaction == nil:
error "getTimestamp: ActivityEntry is not an transaction.Item"
return 0
# TODO: should we account for self.transaction[].isTimeStamp?
return self.transaction[].getTimestamp()
return self.metadata.timestamp
QtProperty[int] timestamp:
read = getTimestamp
@ -153,19 +139,19 @@ QtObject:
read = getStatus
proc getChainId*(self: ActivityEntry): int {.slot.} =
if self.transaction == nil:
error "getChainId: ActivityEntry is not an transaction.Item"
if self.metadata.payloadType == backend.PayloadType.MultiTransaction:
error "getChainId: ActivityEntry is not a transaction"
return 0
return self.transaction[].getChainId()
if self.metadata.activityType == backend.ActivityType.Receive:
return self.metadata.chainIdIn.get(ChainId(0)).int
return self.metadata.chainIdOut.get(ChainId(0)).int
QtProperty[int] chainId:
read = getChainId
proc getIsNFT*(self: ActivityEntry): bool {.slot.} =
if self.transaction == nil:
error "getIsNFT: ActivityEntry is not an transaction.Item"
return false
return self.transaction[].getIsNFT()
return self.metadata.transferType.isSome() and self.metadata.transferType.unsafeGet() == TransferType.Erc721
QtProperty[int] isNFT:
read = getIsNFT
@ -176,6 +162,7 @@ QtObject:
return ""
return self.transaction[].getNFTName()
# TODO: lazy load this in activity history service. See #11597
QtProperty[string] nftName:
read = getNFTName
@ -185,6 +172,7 @@ QtObject:
return ""
return self.transaction[].getNFTImageURL()
# TODO: lazy load this in activity history service. See #11597
QtProperty[string] nftImageURL:
read = getNFTImageURL
@ -194,6 +182,7 @@ QtObject:
return newQVariant(newCurrencyAmount())
return newQVariant(self.transaction[].getTotalFees())
# TODO: lazy load this in activity history service. See #11597
QtProperty[QVariant] totalFees:
read = getTotalFees
@ -203,6 +192,7 @@ QtObject:
return newQVariant(newCurrencyAmount())
return newQVariant(self.transaction[].getMaxTotalFees())
# TODO: used only in details, move it to a entry_details.nim. See #11598
QtProperty[QVariant] maxTotalFees:
read = getMaxTotalFees
@ -212,6 +202,7 @@ QtObject:
return ""
return self.transaction[].getInput()
# TODO: used only in details, move it to a entry_details.nim. See #11598
QtProperty[string] input:
read = getInput
@ -227,14 +218,12 @@ QtObject:
return ""
return self.transaction[].getType()
# TODO: used only in details, move it to a entry_details.nim. See #11598
QtProperty[string] type:
read = getType
proc getContract*(self: ActivityEntry): string {.slot.} =
if self.transaction == nil:
error "getContract: ActivityEntry is not an transaction.Item"
return ""
return self.transaction[].getContract()
return if self.metadata.contractAddress.isSome(): "0x" & self.metadata.contractAddress.unsafeGet().toHex() else: ""
QtProperty[string] contract:
read = getContract
@ -245,18 +234,23 @@ QtObject:
return ""
return self.transaction[].getTxHash()
# TODO: used only in details, move it to a entry_details.nim. See #11598
QtProperty[string] txHash:
read = getTxHash
proc getTokenID*(self: ActivityEntry): string {.slot.} =
if self.transaction == nil:
error "getTokenID: ActivityEntry is not an transaction.Item"
if self.metadata.payloadType == backend.PayloadType.MultiTransaction:
error "getTokenID: ActivityEntry is not a transaction"
return ""
return $self.transaction[].getTokenID()
if self.metadata.activityType == backend.ActivityType.Receive:
return if self.metadata.tokenIn.isSome(): $self.metadata.tokenIn.unsafeGet().tokenId else: ""
return if self.metadata.tokenOut.isSome(): $self.metadata.tokenOut.unsafeGet().tokenId else: ""
QtProperty[string] tokenID:
read = getTokenID
# TODO: used only in details, move it to a entry_details.nim. See #11598
proc getNonce*(self: ActivityEntry): string {.slot.} =
if self.transaction == nil:
error "getNonce: ActivityEntry is not an transaction.Item"
@ -272,6 +266,7 @@ QtObject:
return ""
return $self.transaction[].getBlockNumber()
# TODO: used only in details, move it to a entry_details.nim. See #11598
QtProperty[string] blockNumber:
read = getBlockNumber

View File

@ -205,7 +205,24 @@ proc `%`*(pt: PayloadType): JsonNode {.inline.} =
proc fromJson*(jn: JsonNode, T: typedesc[PayloadType]): PayloadType {.inline.} =
return cast[PayloadType](jn.getInt())
# Mirrors status-go/services/wallet/activity/activity.go TransferType
type
TransferType* {.pure.} = enum
Eth = 1
Erc20
Erc721
Erc1155
# Define toJson proc for TransferType
proc `%`*(pt: TransferType): JsonNode {.inline.} =
return newJInt(ord(pt))
# Define fromJson proc for TransferType
proc fromJson*(jn: JsonNode, T: typedesc[TransferType]): TransferType {.inline.} =
return cast[TransferType](jn.getInt())
# TODO: hide internals behind safe interface
# Mirrors status-go/services/wallet/activity/activity.go Entry
type
ActivityEntry* = object
# Identification
@ -224,6 +241,13 @@ type
tokenOut*: Option[Token]
tokenIn*: Option[Token]
sender*: Option[eth.Address]
recipient*: Option[eth.Address]
chainIdOut*: Option[ChainId]
chainIdIn*: Option[ChainId]
transferType*: Option[TransferType]
contractAddress*: Option[eth.Address]
# Mirrors services/wallet/activity/service.go ErrorCode
ErrorCode* = enum
ErrorCodeSuccess = 1,
@ -245,6 +269,12 @@ proc toJson*(ae: ActivityEntry): JsonNode {.inline.} =
proc fromJson*(e: JsonNode, T: typedesc[ActivityEntry]): ActivityEntry {.inline.} =
const tokenOutField = "tokenOut"
const tokenInField = "tokenIn"
const senderField = "sender"
const recipientField = "recipient"
const chainIdOutField = "chainIdOut"
const chainIdInField = "chainIdIn"
const transferTypeField = "transferType"
const contractAddressField = "contractAddress"
result = T(
payloadType: fromJson(e["payloadType"], PayloadType),
transaction: if e.hasKey("transaction"):
@ -266,8 +296,26 @@ proc fromJson*(e: JsonNode, T: typedesc[ActivityEntry]): ActivityEntry {.inline.
tokenIn: if e.contains(tokenInField):
some(fromJson(e[tokenInField], Token))
else:
none(Token)
none(Token),
)
if e.hasKey(senderField) and e[senderField].kind != JNull:
var address: eth.Address
fromJson(e[senderField], senderField, address)
result.sender = some(address)
if e.hasKey(recipientField) and e[recipientField].kind != JNull:
var address: eth.Address
fromJson(e[recipientField], recipientField, address)
result.recipient = some(address)
if e.hasKey(chainIdOutField) and e[chainIdOutField].kind != JNull:
result.chainIdOut = some(fromJson(e[chainIdOutField], ChainId))
if e.hasKey(chainIdInField) and e[chainIdInField].kind != JNull:
result.chainIdIn = some(fromJson(e[chainIdInField], ChainId))
if e.hasKey(transferTypeField) and e[transferTypeField].kind != JNull:
result.transferType = some(fromJson(e[transferTypeField], TransferType))
if e.hasKey(contractAddressField) and e[contractAddressField].kind != JNull:
var address: eth.Address
fromJson(e[contractAddressField], contractAddressField, address)
result.contractAddress = some(address)
proc `$`*(self: ActivityEntry): string =
let transactionStr = if self.transaction.isSome: $self.transaction.get()
@ -283,6 +331,11 @@ proc `$`*(self: ActivityEntry): string =
amountIn* {$self.amountIn},
tokenOut* {$self.tokenOut},
tokenIn* {$self.tokenIn}
sender* {$self.sender}
recipient* {$self.recipient}
chainIdOut* {$self.chainIdOut}
chainIdIn* {$self.chainIdIn}
transferType* {$self.transferType}
)"""
proc fromJson*(e: JsonNode, T: typedesc[FilterResponse]): FilterResponse {.inline.} =

View File

@ -197,7 +197,7 @@ QtObject {
}
function getNameForAddress(address) {
let name = getNameForWalletAddress(address)
var name = getNameForWalletAddress(address)
if (name.length === 0) {
name = getNameForSavedWalletAddress(address)
}