mirror of
https://github.com/status-im/status-desktop.git
synced 2025-01-11 14:54:48 +00:00
chore(@desktop/wallet): Wallet: explore streamlining "all tokens model" spread across different sections
closes #12424
This commit is contained in:
parent
5257d003d9
commit
b315d8b9b8
src
app/modules/main
app_service
common
service
ens
message
network
stickers
token
transaction
backend
storybook
ui
app/AppLayouts
imports/utils
vendor
@ -593,7 +593,7 @@ proc buildTokensAndCollectiblesFromWallet(self: Module) =
|
||||
key = token.symbol,
|
||||
name = token.name,
|
||||
symbol = token.symbol,
|
||||
color = token.color,
|
||||
color = "",
|
||||
communityId = token.communityId,
|
||||
image = "",
|
||||
category = ord(TokenListItemCategory.General),
|
||||
|
@ -252,7 +252,7 @@ method delete*[T](self: Module[T]) =
|
||||
self.view.delete
|
||||
self.viewVariant.delete
|
||||
|
||||
proc createTokenItem[T](self: Module[T], tokenDto: CommunityTokenDto) : TokenItem =
|
||||
proc createTokenItem[T](self: Module[T], tokenDto: CommunityTokenDto) : token_item.TokenItem =
|
||||
let network = self.controller.getNetwork(tokenDto.chainId)
|
||||
let tokenOwners = self.controller.getCommunityTokenOwners(tokenDto.communityId, tokenDto.chainId, tokenDto.address)
|
||||
let ownerAddressName = if len(tokenDto.deployer) > 0: self.controller.getCommunityTokenOwnerName(tokenDto.deployer) else: ""
|
||||
@ -262,7 +262,7 @@ proc createTokenItem[T](self: Module[T], tokenDto: CommunityTokenDto) : TokenIte
|
||||
let destructedAmount = self.controller.getRemoteDestructedAmount(tokenDto.chainId, tokenDto.address)
|
||||
result = initTokenItem(tokenDto, network, tokenOwners, ownerAddressName, burnState, remoteDestructedAddresses, remainingSupply, destructedAmount)
|
||||
|
||||
proc createTokenItemImproved[T](self: Module[T], tokenDto: CommunityTokenDto, communityTokenJsonItems: JsonNode) : TokenItem =
|
||||
proc createTokenItemImproved[T](self: Module[T], tokenDto: CommunityTokenDto, communityTokenJsonItems: JsonNode) : token_item.TokenItem =
|
||||
# These 3 values come from local caches so they can be done sync
|
||||
let network = self.controller.getNetwork(tokenDto.chainId)
|
||||
let tokenOwners = self.controller.getCommunityTokenOwners(tokenDto.communityId, tokenDto.chainId, tokenDto.address)
|
||||
|
@ -155,10 +155,13 @@ proc getPrice*(self: Controller, crypto: string, fiat: string): float64 =
|
||||
proc getStatusToken*(self: Controller): string =
|
||||
let token = self.ensService.getStatusToken()
|
||||
|
||||
if token == nil:
|
||||
return $ %*{}
|
||||
|
||||
let jsonObj = %* {
|
||||
"name": token.name,
|
||||
"symbol": token.symbol,
|
||||
"address": token.addressAsString()
|
||||
"address": token.address
|
||||
}
|
||||
return $jsonObj
|
||||
|
||||
|
@ -165,10 +165,13 @@ proc getChainIdForStickers*(self: Controller): int =
|
||||
proc getStatusToken*(self: Controller): string =
|
||||
let token = self.stickerService.getStatusToken()
|
||||
|
||||
if token == nil:
|
||||
return $ %*{}
|
||||
|
||||
let jsonObj = %* {
|
||||
"name": token.name,
|
||||
"symbol": token.symbol,
|
||||
"address": token.addressAsString()
|
||||
"address": token.address
|
||||
}
|
||||
return $jsonObj
|
||||
|
||||
|
@ -18,6 +18,7 @@ import app/core/signals/types
|
||||
import backend/activity as backend_activity
|
||||
import backend/backend as backend
|
||||
|
||||
import app_service/common/conversion
|
||||
import app_service/service/currency/service as currency_service
|
||||
import app_service/service/transaction/service as transaction_service
|
||||
import app_service/service/token/service as token_service
|
||||
@ -361,7 +362,7 @@ QtObject:
|
||||
assets.add(backend_activity.Token(
|
||||
tokenType: tokenType,
|
||||
chainId: backend_activity.ChainId(token.chainId),
|
||||
address: some(token.address)
|
||||
address: some(parseAddress(token.address))
|
||||
))
|
||||
|
||||
self.currentActivityFilter.assets = assets
|
||||
|
@ -0,0 +1,55 @@
|
||||
import NimQml, Tables, strutils
|
||||
|
||||
import ./io_interface
|
||||
|
||||
type
|
||||
ModelRole {.pure.} = enum
|
||||
ChainId = UserRole + 1
|
||||
Address
|
||||
|
||||
QtObject:
|
||||
type AddressPerChainModel* = ref object of QAbstractListModel
|
||||
delegate: io_interface.TokenBySymbolModelDataSource
|
||||
index: int
|
||||
|
||||
proc setup(self: AddressPerChainModel) =
|
||||
self.QAbstractListModel.setup
|
||||
self.index = 0
|
||||
|
||||
proc delete(self: AddressPerChainModel) =
|
||||
self.QAbstractListModel.delete
|
||||
|
||||
proc newAddressPerChainModel*(delegate: io_interface.TokenBySymbolModelDataSource, index: int): AddressPerChainModel =
|
||||
new(result, delete)
|
||||
result.setup
|
||||
result.delegate = delegate
|
||||
result.index = index
|
||||
|
||||
method rowCount(self: AddressPerChainModel, index: QModelIndex = nil): int =
|
||||
return self.delegate.getTokenBySymbolList()[self.index].addressPerChainId.len
|
||||
|
||||
proc countChanged(self: AddressPerChainModel) {.signal.}
|
||||
proc getCount(self: AddressPerChainModel): int {.slot.} =
|
||||
return self.rowCount()
|
||||
QtProperty[int] count:
|
||||
read = getCount
|
||||
notify = countChanged
|
||||
|
||||
method roleNames(self: AddressPerChainModel): Table[int, string] =
|
||||
{
|
||||
ModelRole.ChainId.int:"chainId",
|
||||
ModelRole.Address.int:"address",
|
||||
}.toTable
|
||||
|
||||
method data(self: AddressPerChainModel, index: QModelIndex, role: int): QVariant =
|
||||
if not index.isValid:
|
||||
return
|
||||
if index.row < 0 or index.row >= self.rowCount():
|
||||
return
|
||||
let item = self.delegate.getTokenBySymbolList()[self.index].addressPerChainId[index.row]
|
||||
let enumRole = role.ModelRole
|
||||
case enumRole:
|
||||
of ModelRole.ChainId:
|
||||
result = newQVariant(item.chainId)
|
||||
of ModelRole.Address:
|
||||
result = newQVariant(item.address)
|
@ -44,4 +44,13 @@ method getHistoricalDataForToken*(self: Controller, symbol: string, currency: st
|
||||
self.tokenService.getHistoricalDataForToken(symbol, currency, range)
|
||||
|
||||
method fetchHistoricalBalanceForTokenAsJson*(self: Controller, address: string, tokenSymbol: string, currencySymbol: string, timeIntervalEnum: int) =
|
||||
self.tokenService.fetchHistoricalBalanceForTokenAsJson(address, tokenSymbol, currencySymbol, BalanceHistoryTimeInterval(timeIntervalEnum))
|
||||
self.tokenService.fetchHistoricalBalanceForTokenAsJson(address, tokenSymbol, currencySymbol, BalanceHistoryTimeInterval(timeIntervalEnum))
|
||||
|
||||
proc getSourcesOfTokensList*(self: Controller): var seq[SupportedSourcesItem] =
|
||||
return self.tokenService.getSourcesOfTokensList()
|
||||
|
||||
proc getFlatTokensList*(self: Controller): var seq[TokenItem] =
|
||||
return self.tokenService.getFlatTokensList()
|
||||
|
||||
proc getTokenBySymbolList*(self: Controller): var seq[TokenBySymbolItem] =
|
||||
return self.tokenService.getTokenBySymbolList()
|
||||
|
@ -0,0 +1,116 @@
|
||||
import NimQml, Tables, strutils
|
||||
|
||||
import ./io_interface
|
||||
|
||||
const SOURCES_DELIMITER = ";"
|
||||
|
||||
type
|
||||
ModelRole {.pure.} = enum
|
||||
# The key is built as a concatenation of chainId and address
|
||||
# to create a unique key for each element in the flat tokens list
|
||||
Key = UserRole + 1
|
||||
Name
|
||||
Symbol
|
||||
# uniswap/status/custom seq[string]
|
||||
# returned as a string as nim doesnt support returning a StringList
|
||||
# using join api and semicolon (;) as a delimiter
|
||||
Sources
|
||||
ChainId
|
||||
Address
|
||||
Decimals
|
||||
Image
|
||||
# Native, Erc20, Erc721
|
||||
Type
|
||||
# only be valid if source is custom
|
||||
CommunityId
|
||||
# everything below should be lazy loaded
|
||||
Description
|
||||
# properties below this are optional and may not exist in case of community minted assets
|
||||
# built from chainId and address using networks service
|
||||
WebsiteUrl
|
||||
MarketValues
|
||||
|
||||
QtObject:
|
||||
type FlatTokensModel* = ref object of QAbstractListModel
|
||||
delegate: io_interface.FlatTokenModelDataSource
|
||||
|
||||
proc setup(self: FlatTokensModel) =
|
||||
self.QAbstractListModel.setup
|
||||
|
||||
proc delete(self: FlatTokensModel) =
|
||||
self.QAbstractListModel.delete
|
||||
|
||||
proc newFlatTokensModel*(delegate: io_interface.FlatTokenModelDataSource): FlatTokensModel =
|
||||
new(result, delete)
|
||||
result.setup
|
||||
result.delegate = delegate
|
||||
|
||||
method rowCount(self: FlatTokensModel, index: QModelIndex = nil): int =
|
||||
return self.delegate.getFlatTokensList().len
|
||||
|
||||
proc countChanged(self: FlatTokensModel) {.signal.}
|
||||
proc getCount(self: FlatTokensModel): int {.slot.} =
|
||||
return self.rowCount()
|
||||
QtProperty[int] count:
|
||||
read = getCount
|
||||
notify = countChanged
|
||||
|
||||
method roleNames(self: FlatTokensModel): Table[int, string] =
|
||||
{
|
||||
ModelRole.Key.int:"key",
|
||||
ModelRole.Name.int:"name",
|
||||
ModelRole.Symbol.int:"symbol",
|
||||
ModelRole.Sources.int:"sources",
|
||||
ModelRole.ChainId.int:"chainId",
|
||||
ModelRole.Address.int:"address",
|
||||
ModelRole.Decimals.int:"decimals",
|
||||
ModelRole.Image.int:"image",
|
||||
ModelRole.Type.int:"type",
|
||||
ModelRole.CommunityId.int:"communityId",
|
||||
ModelRole.Description.int:"description",
|
||||
ModelRole.WebsiteUrl.int:"websiteUrl",
|
||||
ModelRole.MarketValues.int:"marketValues",
|
||||
}.toTable
|
||||
|
||||
method data(self: FlatTokensModel, index: QModelIndex, role: int): QVariant =
|
||||
if not index.isValid:
|
||||
return
|
||||
if index.row < 0 or index.row >= self.rowCount():
|
||||
return
|
||||
# the only way to read items from service is by this single method getFlatTokensList
|
||||
let item = self.delegate.getFlatTokensList()[index.row]
|
||||
let enumRole = role.ModelRole
|
||||
case enumRole:
|
||||
of ModelRole.Key:
|
||||
result = newQVariant(item.key)
|
||||
of ModelRole.Name:
|
||||
result = newQVariant(item.name)
|
||||
of ModelRole.Symbol:
|
||||
result = newQVariant(item.symbol)
|
||||
of ModelRole.Sources:
|
||||
result = newQVariant(SOURCES_DELIMITER & item.sources.join(SOURCES_DELIMITER) & SOURCES_DELIMITER)
|
||||
of ModelRole.ChainId:
|
||||
result = newQVariant(item.chainId)
|
||||
of ModelRole.Address:
|
||||
result = newQVariant(item.address)
|
||||
of ModelRole.Decimals:
|
||||
result = newQVariant(item.decimals)
|
||||
of ModelRole.Image:
|
||||
result = newQVariant(item.image)
|
||||
of ModelRole.Type:
|
||||
result = newQVariant(ord(item.`type`))
|
||||
of ModelRole.CommunityId:
|
||||
result = newQVariant(item.communityId)
|
||||
# ToDo fetching of market values not done yet
|
||||
of ModelRole.Description:
|
||||
result = newQVariant("")
|
||||
of ModelRole.WebsiteUrl:
|
||||
result = newQVariant("")
|
||||
of ModelRole.MarketValues:
|
||||
result = newQVariant("")
|
||||
|
||||
proc modelsAboutToUpdate*(self: FlatTokensModel) =
|
||||
self.beginResetModel()
|
||||
|
||||
proc modelsUpdated*(self: FlatTokensModel) =
|
||||
self.endResetModel()
|
@ -1,3 +1,17 @@
|
||||
import app_service/service/token/service_items
|
||||
|
||||
type
|
||||
SourcesOfTokensModelDataSource* = tuple[
|
||||
getSourcesOfTokensList: proc(): var seq[SupportedSourcesItem]
|
||||
]
|
||||
type
|
||||
FlatTokenModelDataSource* = tuple[
|
||||
getFlatTokensList: proc(): var seq[TokenItem]
|
||||
]
|
||||
type
|
||||
TokenBySymbolModelDataSource* = tuple[
|
||||
getTokenBySymbolList: proc(): var seq[TokenBySymbolItem]
|
||||
]
|
||||
type
|
||||
AccessInterface* {.pure inheritable.} = ref object of RootObj
|
||||
## Abstract class for any input/interaction with this module.
|
||||
@ -26,6 +40,15 @@ method fetchHistoricalBalanceForTokenAsJson*(self: AccessInterface, address: str
|
||||
method tokenBalanceHistoryDataResolved*(self: AccessInterface, balanceHistoryJson: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getSourcesOfTokensModelDataSource*(self: AccessInterface): SourcesOfTokensModelDataSource {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getFlatTokenModelDataSource*(self: AccessInterface): FlatTokenModelDataSource {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getTokenBySymbolModelDataSource*(self: AccessInterface): TokenBySymbolModelDataSource {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
# View Delegate Interface
|
||||
# Delegate for the view must be declared here due to use of QtObject and multi
|
||||
# inheritance, which is not well supported in Nim.
|
||||
|
@ -39,6 +39,12 @@ method delete*(self: Module) =
|
||||
method load*(self: Module) =
|
||||
singletonInstance.engine.setRootContextProperty("walletSectionAllTokens", newQVariant(self.view))
|
||||
|
||||
# Passing on the events for changes in model to abstract model
|
||||
self.events.on(SIGNAL_TOKENS_LIST_ABOUT_TO_BE_UPDATED) do(e: Args):
|
||||
self.view.modelsAboutToUpdate()
|
||||
self.events.on(SIGNAL_TOKENS_LIST_UPDATED) do(e: Args):
|
||||
self.view.modelsUpdated()
|
||||
|
||||
self.controller.init()
|
||||
self.view.load()
|
||||
|
||||
@ -62,9 +68,34 @@ method getHistoricalDataForToken*(self: Module, symbol: string, currency: string
|
||||
method tokenHistoricalDataResolved*(self: Module, tokenDetails: string) =
|
||||
self.view.setTokenHistoricalDataReady(tokenDetails)
|
||||
|
||||
|
||||
method fetchHistoricalBalanceForTokenAsJson*(self: Module, address: string, tokenSymbol: string, currencySymbol: string, timeIntervalEnum: int) =
|
||||
self.controller.fetchHistoricalBalanceForTokenAsJson(address, tokenSymbol, currencySymbol,timeIntervalEnum)
|
||||
|
||||
method tokenBalanceHistoryDataResolved*(self: Module, balanceHistoryJson: string) =
|
||||
self.view.setTokenBalanceHistoryDataReady(balanceHistoryJson)
|
||||
|
||||
method getFlatTokensList*(self: Module): var seq[TokenItem] =
|
||||
return self.controller.getFlatTokensList()
|
||||
|
||||
method getTokenBySymbolList*(self: Module): var seq[TokenBySymbolItem] =
|
||||
return self.controller.getTokenBySymbolList()
|
||||
|
||||
method getSourcesOfTokensList*(self: Module): var seq[SupportedSourcesItem] =
|
||||
return self.controller.getSourcesOfTokensList()
|
||||
|
||||
# Interfaces for getting lists from the service files into the abstract models
|
||||
|
||||
method getSourcesOfTokensModelDataSource*(self: Module): SourcesOfTokensModelDataSource =
|
||||
return (
|
||||
getSourcesOfTokensList: proc(): var seq[SupportedSourcesItem] = self.getSourcesOfTokensList()
|
||||
)
|
||||
|
||||
method getFlatTokenModelDataSource*(self: Module): FlatTokenModelDataSource =
|
||||
return (
|
||||
getFlatTokensList: proc(): var seq[TokenItem] = self.getFlatTokensList()
|
||||
)
|
||||
|
||||
method getTokenBySymbolModelDataSource*(self: Module): TokenBySymbolModelDataSource =
|
||||
return (
|
||||
getTokenBySymbolList: proc(): var seq[TokenBySymbolItem] = self.getTokenBySymbolList()
|
||||
)
|
||||
|
@ -0,0 +1,76 @@
|
||||
import NimQml, Tables
|
||||
|
||||
|
||||
import ./io_interface
|
||||
|
||||
type
|
||||
ModelRole {.pure.} = enum
|
||||
# key = name
|
||||
Key = UserRole + 1
|
||||
Name
|
||||
UpdatedAt
|
||||
Source
|
||||
Version
|
||||
TokensCount
|
||||
|
||||
QtObject:
|
||||
type SourcesOfTokensModel* = ref object of QAbstractListModel
|
||||
delegate: io_interface.SourcesOfTokensModelDataSource
|
||||
|
||||
proc setup(self: SourcesOfTokensModel) =
|
||||
self.QAbstractListModel.setup
|
||||
|
||||
proc delete(self: SourcesOfTokensModel) =
|
||||
self.QAbstractListModel.delete
|
||||
|
||||
proc newSourcesOfTokensModel*(delegate: io_interface.SourcesOfTokensModelDataSource): SourcesOfTokensModel =
|
||||
new(result, delete)
|
||||
result.setup
|
||||
result.delegate = delegate
|
||||
|
||||
method rowCount(self: SourcesOfTokensModel, index: QModelIndex = nil): int =
|
||||
return self.delegate.getSourcesOfTokensList().len
|
||||
|
||||
proc countChanged(self: SourcesOfTokensModel) {.signal.}
|
||||
proc getCount(self: SourcesOfTokensModel): int {.slot.} =
|
||||
return self.rowCount()
|
||||
QtProperty[int] count:
|
||||
read = getCount
|
||||
notify = countChanged
|
||||
|
||||
method roleNames(self: SourcesOfTokensModel): Table[int, string] =
|
||||
{
|
||||
ModelRole.Key.int:"key",
|
||||
ModelRole.Name.int:"name",
|
||||
ModelRole.UpdatedAt.int:"updatedAt",
|
||||
ModelRole.Source.int:"source",
|
||||
ModelRole.Version.int:"version",
|
||||
ModelRole.TokensCount.int:"tokensCount",
|
||||
}.toTable
|
||||
|
||||
method data(self: SourcesOfTokensModel, index: QModelIndex, role: int): QVariant =
|
||||
if not index.isValid:
|
||||
return
|
||||
if index.row < 0 or index.row >= self.rowCount():
|
||||
return
|
||||
let item = self.delegate.getSourcesOfTokensList()[index.row]
|
||||
let enumRole = role.ModelRole
|
||||
case enumRole:
|
||||
of ModelRole.Key:
|
||||
result = newQVariant(item.name)
|
||||
of ModelRole.Name:
|
||||
result = newQVariant(item.name)
|
||||
of ModelRole.UpdatedAt:
|
||||
result = newQVariant(item.updatedAt)
|
||||
of ModelRole.Source:
|
||||
result = newQVariant(item.source)
|
||||
of ModelRole.Version:
|
||||
result = newQVariant(item.version)
|
||||
of ModelRole.TokensCount:
|
||||
result = newQVariant(item.tokensCount)
|
||||
|
||||
proc modelsAboutToUpdate*(self: SourcesOfTokensModel) =
|
||||
self.beginResetModel()
|
||||
|
||||
proc modelsUpdated*(self: SourcesOfTokensModel) =
|
||||
self.endResetModel()
|
@ -0,0 +1,117 @@
|
||||
import NimQml, Tables, strutils
|
||||
|
||||
import ./io_interface, ./address_per_chain_model
|
||||
|
||||
const SOURCES_DELIMITER = ";"
|
||||
|
||||
type
|
||||
ModelRole {.pure.} = enum
|
||||
# The key is "symbol" in case it is not a community token
|
||||
# and in case of the community token it will be the token "address"
|
||||
Key = UserRole + 1
|
||||
Name
|
||||
Symbol
|
||||
# uniswap/status/custom seq[string]
|
||||
# returned as a string as nim doesnt support returning a StringList
|
||||
# using join api and semicolon (;) as a delimiter
|
||||
Sources
|
||||
AddressPerChain
|
||||
Decimals
|
||||
Image
|
||||
# Native, Erc20, Erc721
|
||||
Type
|
||||
# only be valid if source is custom
|
||||
CommunityId
|
||||
# everything below should be lazy loaded
|
||||
Description
|
||||
# properties below this are optional and may not exist in case of community minted assets
|
||||
# built from chainId and address using networks service
|
||||
WebsiteUrl
|
||||
MarketValues
|
||||
|
||||
QtObject:
|
||||
type TokensBySymbolModel* = ref object of QAbstractListModel
|
||||
delegate: io_interface.TokenBySymbolModelDataSource
|
||||
addressPerChainModel: seq[AddressPerChainModel]
|
||||
|
||||
proc setup(self: TokensBySymbolModel) =
|
||||
self.QAbstractListModel.setup
|
||||
self.addressPerChainModel = @[]
|
||||
|
||||
proc delete(self: TokensBySymbolModel) =
|
||||
self.QAbstractListModel.delete
|
||||
|
||||
proc newTokensBySymbolModel*(delegate: io_interface.TokenBySymbolModelDataSource): TokensBySymbolModel =
|
||||
new(result, delete)
|
||||
result.setup
|
||||
result.delegate = delegate
|
||||
|
||||
method rowCount(self: TokensBySymbolModel, index: QModelIndex = nil): int =
|
||||
return self.delegate.getTokenBySymbolList().len
|
||||
|
||||
proc countChanged(self: TokensBySymbolModel) {.signal.}
|
||||
proc getCount(self: TokensBySymbolModel): int {.slot.} =
|
||||
return self.rowCount()
|
||||
QtProperty[int] count:
|
||||
read = getCount
|
||||
notify = countChanged
|
||||
|
||||
method roleNames(self: TokensBySymbolModel): Table[int, string] =
|
||||
{
|
||||
ModelRole.Key.int:"key",
|
||||
ModelRole.Name.int:"name",
|
||||
ModelRole.Symbol.int:"symbol",
|
||||
ModelRole.Sources.int:"sources",
|
||||
ModelRole.AddressPerChain.int:"addressPerChain",
|
||||
ModelRole.Decimals.int:"decimals",
|
||||
ModelRole.Image.int:"image",
|
||||
ModelRole.Type.int:"type",
|
||||
ModelRole.CommunityId.int:"communityId",
|
||||
ModelRole.Description.int:"description",
|
||||
ModelRole.WebsiteUrl.int:"websiteUrl",
|
||||
ModelRole.MarketValues.int:"marketValues",
|
||||
}.toTable
|
||||
|
||||
method data(self: TokensBySymbolModel, index: QModelIndex, role: int): QVariant =
|
||||
if not index.isValid:
|
||||
return
|
||||
if index.row < 0 or index.row >= self.rowCount():
|
||||
return
|
||||
# the only way to read items from service is by this single method getTokenBySymbolList
|
||||
let item = self.delegate.getTokenBySymbolList()[index.row]
|
||||
let enumRole = role.ModelRole
|
||||
case enumRole:
|
||||
of ModelRole.Key:
|
||||
result = newQVariant(item.key)
|
||||
of ModelRole.Name:
|
||||
result = newQVariant(item.name)
|
||||
of ModelRole.Symbol:
|
||||
result = newQVariant(item.symbol)
|
||||
of ModelRole.Sources:
|
||||
result = newQVariant(SOURCES_DELIMITER & item.sources.join(SOURCES_DELIMITER) & SOURCES_DELIMITER)
|
||||
of ModelRole.AddressPerChain:
|
||||
result = newQVariant(self.addressPerChainModel[index.row])
|
||||
of ModelRole.Decimals:
|
||||
result = newQVariant(item.decimals)
|
||||
of ModelRole.Image:
|
||||
result = newQVariant(item.image)
|
||||
of ModelRole.Type:
|
||||
result = newQVariant(ord(item.`type`))
|
||||
of ModelRole.CommunityId:
|
||||
result = newQVariant(item.communityId)
|
||||
# ToDo fetching of market values not done yet
|
||||
of ModelRole.Description:
|
||||
result = newQVariant("")
|
||||
of ModelRole.WebsiteUrl:
|
||||
result = newQVariant("")
|
||||
of ModelRole.MarketValues:
|
||||
result = newQVariant("")
|
||||
|
||||
proc modelsAboutToUpdate*(self: TokensBySymbolModel) =
|
||||
self.beginResetModel()
|
||||
|
||||
proc modelsUpdated*(self: TokensBySymbolModel) =
|
||||
self.addressPerChainModel = @[]
|
||||
for index in countup(0, self.delegate.getTokenBySymbolList().len):
|
||||
self.addressPerChainModel.add(newAddressPerChainModel(self.delegate,index))
|
||||
self.endResetModel()
|
@ -1,6 +1,6 @@
|
||||
import NimQml, sequtils, sugar, strutils
|
||||
|
||||
import ./io_interface
|
||||
import ./io_interface, ./sources_of_tokens_model, ./flat_tokens_model, ./token_by_symbol_model
|
||||
|
||||
QtObject:
|
||||
type
|
||||
@ -8,6 +8,16 @@ QtObject:
|
||||
delegate: io_interface.AccessInterface
|
||||
marketHistoryIsLoading: bool
|
||||
balanceHistoryIsLoading: bool
|
||||
# This contains the different sources for the tokens list
|
||||
# ex. uniswap list, status tokens list
|
||||
sourcesOfTokensModel: SourcesOfTokensModel
|
||||
# this list contains the complete list of tokens with separate
|
||||
# entry per token which has a unique address + network pair */
|
||||
flatTokensModel: FlatTokensModel
|
||||
# this list contains list of tokens grouped by symbol
|
||||
# EXCEPTION: We may have different entries for the same symbol in case
|
||||
# of symbol clash when minting community tokens
|
||||
tokensBySymbolModel: TokensBySymbolModel
|
||||
|
||||
proc delete*(self: View) =
|
||||
self.QObject.delete
|
||||
@ -18,36 +28,33 @@ QtObject:
|
||||
result.delegate = delegate
|
||||
result.marketHistoryIsLoading = false
|
||||
result.balanceHistoryIsLoading = false
|
||||
result.sourcesOfTokensModel = newSourcesOfTokensModel(delegate.getSourcesOfTokensModelDataSource())
|
||||
result.flatTokensModel = newFlatTokensModel(delegate.getFlatTokenModelDataSource())
|
||||
result.tokensBySymbolModel = newTokensBySymbolModel(delegate.getTokenBySymbolModelDataSource())
|
||||
|
||||
proc load*(self: View) =
|
||||
self.delegate.viewDidLoad()
|
||||
|
||||
proc marketHistoryIsLoadingChanged*(self: View) {.signal.}
|
||||
|
||||
proc getMarketHistoryIsLoading(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.marketHistoryIsLoading)
|
||||
|
||||
proc setMarketHistoryIsLoading(self: View, isLoading: bool) =
|
||||
if self.marketHistoryIsLoading == isLoading:
|
||||
return
|
||||
self.marketHistoryIsLoading = isLoading
|
||||
self.marketHistoryIsLoadingChanged()
|
||||
|
||||
QtProperty[QVariant] marketHistoryIsLoading:
|
||||
read = getMarketHistoryIsLoading
|
||||
notify = marketHistoryIsLoadingChanged
|
||||
|
||||
proc balanceHistoryIsLoadingChanged*(self: View) {.signal.}
|
||||
|
||||
proc getBalanceHistoryIsLoading(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.balanceHistoryIsLoading)
|
||||
|
||||
proc setBalanceHistoryIsLoading(self: View, isLoading: bool) =
|
||||
if self.balanceHistoryIsLoading == isLoading:
|
||||
return
|
||||
self.balanceHistoryIsLoading = isLoading
|
||||
self.balanceHistoryIsLoadingChanged()
|
||||
|
||||
QtProperty[QVariant] balanceHistoryIsLoading:
|
||||
read = getBalanceHistoryIsLoading
|
||||
notify = balanceHistoryIsLoadingChanged
|
||||
@ -74,3 +81,34 @@ QtObject:
|
||||
proc setTokenBalanceHistoryDataReady*(self: View, balanceHistoryJson: string) =
|
||||
self.setBalanceHistoryIsLoading(false)
|
||||
self.tokenBalanceHistoryDataReady(balanceHistoryJson)
|
||||
|
||||
proc sourcesOfTokensModelChanged*(self: View) {.signal.}
|
||||
proc getSourcesOfTokensModel(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.sourcesOfTokensModel)
|
||||
QtProperty[QVariant] sourcesOfTokensModel:
|
||||
read = getSourcesOfTokensModel
|
||||
notify = sourcesOfTokensModelChanged
|
||||
|
||||
proc flatTokensModelChanged*(self: View) {.signal.}
|
||||
proc getFlatTokensModel(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.flatTokensModel)
|
||||
QtProperty[QVariant] flatTokensModel:
|
||||
read = getFlatTokensModel
|
||||
notify = flatTokensModelChanged
|
||||
|
||||
proc tokensBySymbolModelChanged*(self: View) {.signal.}
|
||||
proc getTokensBySymbolModel(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.tokensBySymbolModel)
|
||||
QtProperty[QVariant] tokensBySymbolModel:
|
||||
read = getTokensBySymbolModel
|
||||
notify = tokensBySymbolModelChanged
|
||||
|
||||
proc modelsAboutToUpdate*(self: View) =
|
||||
self.sourcesOfTokensModel.modelsAboutToUpdate()
|
||||
self.flatTokensModel.modelsAboutToUpdate()
|
||||
self.tokensBySymbolModel.modelsAboutToUpdate()
|
||||
|
||||
proc modelsUpdated*(self: View) =
|
||||
self.sourcesOfTokensModel.modelsUpdated()
|
||||
self.flatTokensModel.modelsUpdated()
|
||||
self.tokensBySymbolModel.modelsUpdated()
|
||||
|
@ -34,11 +34,11 @@ proc init*(self: Controller) =
|
||||
self.events.on(SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED) do(e: Args):
|
||||
self.delegate.refreshNetworks()
|
||||
|
||||
proc getNetworks*(self: Controller): seq[NetworkDto] =
|
||||
return self.networkService.getNetworks()
|
||||
proc getFlatNetworks*(self: Controller): seq[NetworkDto] =
|
||||
return self.networkService.getFlatNetworks()
|
||||
|
||||
proc setNetworksState*(self: Controller, chainIds: seq[int], enabled: bool) =
|
||||
self.walletAccountService.setNetworksState(chainIds, enabled)
|
||||
|
||||
proc areTestNetworksEnabled*(self: Controller): bool =
|
||||
return self.settingsService.areTestNetworksEnabled()
|
||||
return self.settingsService.areTestNetworksEnabled()
|
||||
|
@ -1,5 +1,6 @@
|
||||
import NimQml, Tables, strutils, strformat, sequtils, sugar
|
||||
|
||||
import app_service/service/network/types
|
||||
import ./item
|
||||
|
||||
const EXPLORER_TX_PREFIX* = "/tx/"
|
||||
@ -193,7 +194,7 @@ QtObject:
|
||||
|
||||
proc getLayer1Network*(self: Model, testNet: bool): int =
|
||||
for item in self.items:
|
||||
if item.getLayer() == 1 and item.getIsTest() == testNet:
|
||||
if item.getLayer() == NETWORK_LAYER_1 and item.getIsTest() == testNet:
|
||||
return item.getChainId()
|
||||
return 0
|
||||
|
||||
|
@ -40,12 +40,12 @@ method delete*(self: Module) =
|
||||
|
||||
method refreshNetworks*(self: Module) =
|
||||
self.view.setAreTestNetworksEnabled(self.controller.areTestNetworksEnabled())
|
||||
self.view.setItems(self.controller.getNetworks())
|
||||
self.view.setItems(self.controller.getFlatNetworks())
|
||||
|
||||
method load*(self: Module) =
|
||||
self.controller.init()
|
||||
self.view.setAreTestNetworksEnabled(self.controller.areTestNetworksEnabled())
|
||||
self.view.load(self.controller.getNetworks())
|
||||
self.view.load()
|
||||
self.refreshNetworks()
|
||||
|
||||
method isLoaded*(self: Module): bool =
|
||||
return self.moduleLoaded
|
||||
@ -64,4 +64,4 @@ method setNetworksState*(self: Module, chainIds: seq[int], enabled: bool) =
|
||||
self.controller.setNetworksState(chainIds, enabled)
|
||||
|
||||
method getNetworkLayer*(self: Module, chainId: int): string =
|
||||
return self.view.getNetworkLayer(chainId)
|
||||
return self.view.getNetworkLayer(chainId)
|
||||
|
@ -1,7 +1,6 @@
|
||||
|
||||
import Tables, NimQml, sequtils, sugar
|
||||
|
||||
import ../../../../../app_service/service/network/dto
|
||||
import app_service/service/network/[dto, types]
|
||||
import ./io_interface
|
||||
import ./model
|
||||
import ./item
|
||||
@ -17,6 +16,7 @@ QtObject:
|
||||
enabled: Model
|
||||
layer1: Model
|
||||
layer2: Model
|
||||
flatNetworks: Model
|
||||
areTestNetworksEnabled: bool
|
||||
|
||||
proc setup(self: View) =
|
||||
@ -32,6 +32,7 @@ QtObject:
|
||||
result.layer1 = newModel()
|
||||
result.layer2 = newModel()
|
||||
result.enabled = newModel()
|
||||
result.flatNetworks = newModel()
|
||||
result.setup()
|
||||
|
||||
proc areTestNetworksEnabledChanged*(self: View) {.signal.}
|
||||
@ -74,6 +75,14 @@ QtObject:
|
||||
read = getLayer2
|
||||
notify = layer2Changed
|
||||
|
||||
|
||||
proc flatNetworksChanged*(self: View) {.signal.}
|
||||
proc getFlatNetworks(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.flatNetworks)
|
||||
QtProperty[QVariant] flatNetworks:
|
||||
read = getFlatNetworks
|
||||
notify = flatNetworksChanged
|
||||
|
||||
proc enabledChanged*(self: View) {.signal.}
|
||||
|
||||
proc getEnabled(self: View): QVariant {.slot.} =
|
||||
@ -105,18 +114,19 @@ QtObject:
|
||||
networkEnabledToUxEnabledState(n.enabled, allEnabled)
|
||||
))
|
||||
|
||||
self.all.setItems(items)
|
||||
self.layer1.setItems(items.filter(i => i.getLayer() == 1))
|
||||
self.layer2.setItems(items.filter(i => i.getLayer() == 2))
|
||||
self.enabled.setItems(items.filter(i => i.getIsEnabled()))
|
||||
let filteredItems = items.filter(i => i.getIsTest() == self.areTestNetworksEnabled)
|
||||
self.flatNetworks.setItems(items)
|
||||
self.all.setItems(filteredItems)
|
||||
self.layer1.setItems(filteredItems.filter(i => i.getLayer() == NETWORK_LAYER_1))
|
||||
self.layer2.setItems(filteredItems.filter(i => i.getLayer() == NETWORK_LAYER_2))
|
||||
self.enabled.setItems(filteredItems.filter(i => i.getIsEnabled()))
|
||||
|
||||
self.allChanged()
|
||||
self.layer1Changed()
|
||||
self.layer2Changed()
|
||||
self.enabledChanged()
|
||||
|
||||
proc load*(self: View, networks: seq[NetworkDto]) =
|
||||
self.setItems(networks)
|
||||
proc load*(self: View) =
|
||||
self.delegate.viewDidLoad()
|
||||
|
||||
proc toggleNetwork*(self: View, chainId: int) {.slot.} =
|
||||
|
@ -1,5 +1,6 @@
|
||||
import NimQml, Tables, strutils, strformat, sequtils, sugar, json, stint
|
||||
|
||||
import app_service/service/network/types
|
||||
import app/modules/shared_models/currency_amount
|
||||
import ./network_item, ./suggested_route_item
|
||||
|
||||
@ -322,6 +323,6 @@ QtObject:
|
||||
|
||||
proc getLayer1Network*(self: NetworkModel): int =
|
||||
for item in self.items:
|
||||
if item.getLayer() == 1:
|
||||
if item.getLayer() == NETWORK_LAYER_1:
|
||||
return item.getChainId()
|
||||
return 0
|
||||
|
@ -82,4 +82,11 @@ type Shard* = object
|
||||
|
||||
proc initShard*(cluster: int = -1, index: int = -1): Shard =
|
||||
result.cluster = cluster
|
||||
result.index = index
|
||||
result.index = index
|
||||
|
||||
# ToDo: Will be streamlined to single TokenType under https://github.com/status-im/status-desktop/pull/12654/files
|
||||
type NewTokenType* {.pure.} = enum
|
||||
Native = 0
|
||||
ERC20 = 1,
|
||||
ERC721 = 2,
|
||||
ERC1155
|
||||
|
@ -414,8 +414,8 @@ QtObject:
|
||||
proc getSNTBalance*(self: Service): string =
|
||||
let token = self.getStatusToken()
|
||||
let account = self.walletAccountService.getWalletAccount(0).address
|
||||
let balances = status_go_backend.getTokensBalancesForChainIDs(@[self.getChainId()], @[account], @[token.addressAsString()]).result
|
||||
return ens_utils.hex2Token(balances{account}{token.addressAsString()}.getStr, token.decimals)
|
||||
let balances = status_go_backend.getTokensBalancesForChainIDs(@[self.getChainId()], @[account], @[token.address]).result
|
||||
return ens_utils.hex2Token(balances{account}{token.address}.getStr, token.decimals)
|
||||
|
||||
proc resourceUrl*(self: Service, username: string): (string, string, string) =
|
||||
try:
|
||||
|
@ -419,11 +419,11 @@ QtObject:
|
||||
|
||||
proc getTransactionDetails*(self: Service, message: MessageDto): (string, string) =
|
||||
let networksDto = self.networkService.getNetworks()
|
||||
var token = newTokenDto(networksDto[0].nativeCurrencyName, networksDto[0].chainId, parseAddress(ZERO_ADDRESS), networksDto[0].nativeCurrencySymbol, networksDto[0].nativeCurrencyDecimals, true)
|
||||
var token = self.tokenService.findTokenByAddress(networksDto[0].chainId, ZERO_ADDRESS)
|
||||
|
||||
if message.transactionParameters.contract != "":
|
||||
for networkDto in networksDto:
|
||||
let tokenFound = self.tokenService.findTokenByAddress(networkDto, parseAddress(message.transactionParameters.contract))
|
||||
let tokenFound = self.tokenService.findTokenByAddress(networkDto.chainId, message.transactionParameters.contract)
|
||||
if tokenFound == nil:
|
||||
continue
|
||||
|
||||
|
@ -58,6 +58,14 @@ proc resetNetworks*(self: Service) =
|
||||
proc getCombinedNetworks*(self: Service): seq[CombinedNetworkDto] =
|
||||
return self.fetchNetworks()
|
||||
|
||||
# TODO:: update the networks service to unify the model exposed from this service
|
||||
# We currently have 3 types: combined, test/mainet and flat and probably can be optimized
|
||||
# follow up task https://github.com/status-im/status-desktop/issues/12717
|
||||
proc getFlatNetworks*(self: Service): seq[NetworkDto] =
|
||||
for network in self.fetchNetworks():
|
||||
result.add(network.test)
|
||||
result.add(network.prod)
|
||||
|
||||
proc getNetworks*(self: Service): seq[NetworkDto] =
|
||||
let testNetworksEnabled = self.settingsService.areTestNetworksEnabled()
|
||||
|
||||
@ -67,6 +75,11 @@ proc getNetworks*(self: Service): seq[NetworkDto] =
|
||||
else:
|
||||
result.add(network.prod)
|
||||
|
||||
proc getAllNetworkChainIds*(self: Service): seq[int] =
|
||||
for network in self.fetchNetworks():
|
||||
result.add(network.test.chainId)
|
||||
result.add(network.prod.chainId)
|
||||
|
||||
proc upsertNetwork*(self: Service, network: NetworkDto): bool =
|
||||
let response = backend.addEthereumChain(backend.Network(
|
||||
chainId: network.chainId,
|
||||
|
@ -7,7 +7,11 @@ const Optimism = 10
|
||||
const Poa = 99
|
||||
const XDai = 100
|
||||
|
||||
const NETWORK_LAYER_1 = 1
|
||||
const NETWORK_LAYER_2 = 2
|
||||
|
||||
export Mainnet, Ropsten, Rinkeby, Goerli, Optimism, Poa, XDai, Sepolia
|
||||
export NETWORK_LAYER_1, NETWORK_LAYER_2
|
||||
|
||||
type
|
||||
NetworkType* {.pure.} = enum
|
||||
@ -48,4 +52,4 @@ proc toChainId*(self: NetworkType): int =
|
||||
of NetworkType.Sepolia: result = Sepolia
|
||||
of NetworkType.XDai: result = XDai
|
||||
of NetworkType.Poa: result = 99
|
||||
of NetworkType.Other: result = -1
|
||||
of NetworkType.Other: result = -1
|
||||
|
@ -451,5 +451,5 @@ QtObject:
|
||||
let account = self.walletAccountService.getWalletAccount(0).address
|
||||
let network = self.networkService.getNetworkForStickers()
|
||||
|
||||
let balances = status_go_backend.getTokensBalancesForChainIDs(@[network.chainId], @[account], @[token.addressAsString()]).result
|
||||
return ens_utils.hex2Token(balances{account}{token.addressAsString()}.getStr, token.decimals)
|
||||
let balances = status_go_backend.getTokensBalancesForChainIDs(@[network.chainId], @[account], @[token.address]).result
|
||||
return ens_utils.hex2Token(balances{account}{token.address}.getStr, token.decimals)
|
||||
|
@ -1,8 +1,7 @@
|
||||
import times
|
||||
include ../../common/json_utils
|
||||
import backend/backend as backend
|
||||
|
||||
import ../../../backend/backend as backend
|
||||
import ./dto
|
||||
include app_service/common/json_utils
|
||||
#################################################
|
||||
# Async load transactions
|
||||
#################################################
|
||||
@ -10,6 +9,26 @@ import ./dto
|
||||
const DAYS_IN_WEEK = 7
|
||||
const HOURS_IN_DAY = 24
|
||||
|
||||
type
|
||||
GetTokenListTaskArg = ref object of QObjectTaskArg
|
||||
|
||||
const getSupportedTokenList*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[GetTokenListTaskArg](argEncoded)
|
||||
var response: RpcResponse[JsonNode]
|
||||
try:
|
||||
response = backend.getTokenList()
|
||||
let output = %* {
|
||||
"supportedTokensJson": response,
|
||||
"error": ""
|
||||
}
|
||||
arg.finish(output)
|
||||
except Exception as e:
|
||||
let output = %* {
|
||||
"supportedTokensJson": response,
|
||||
"error": e.msg
|
||||
}
|
||||
arg.finish(output)
|
||||
|
||||
type
|
||||
GetTokenHistoricalDataTaskArg = ref object of QObjectTaskArg
|
||||
symbol: string
|
||||
@ -98,4 +117,4 @@ const getTokenBalanceHistoryDataTask*: Task = proc(argEncoded: string) {.gcsafe,
|
||||
"timeInterval": int(arg.timeInterval),
|
||||
"error": e.msg,
|
||||
}
|
||||
arg.finish(output)
|
||||
arg.finish(output)
|
||||
|
@ -1,64 +1,67 @@
|
||||
import json
|
||||
import json, strformat
|
||||
|
||||
include ../../common/json_utils
|
||||
include app_service/common/json_utils
|
||||
|
||||
import
|
||||
web3/ethtypes, json_serialization
|
||||
from web3/conversions import `$`
|
||||
import json_serialization
|
||||
|
||||
# TODO: remove once this is moved to wallet_accounts service
|
||||
const WEEKLY_TIME_RANGE* = 0
|
||||
const MONTHLY_TIME_RANGE* = 1
|
||||
const HALF_YEARLY_TIME_RANGE* = 2
|
||||
const YEARLY_TIME_RANGE* = 3
|
||||
const ALL_TIME_RANGE* = 4
|
||||
|
||||
# Only contains DTO used for deserialisation of data from go lib
|
||||
|
||||
type
|
||||
TokenDto* = ref object of RootObj
|
||||
name*: string
|
||||
chainId*: int
|
||||
address*: Address
|
||||
symbol*: string
|
||||
decimals*: int
|
||||
hasIcon* {.dontSerialize.}: bool
|
||||
color*: string
|
||||
isCustom* {.dontSerialize.}: bool
|
||||
isVisible* {.dontSerialize.}: bool
|
||||
communityId*: string
|
||||
address* {.serializedFieldName("address").}: string
|
||||
name* {.serializedFieldName("name").}: string
|
||||
symbol* {.serializedFieldName("symbol").}: string
|
||||
decimals* {.serializedFieldName("decimals").}: int
|
||||
chainID* {.serializedFieldName("chainId").}: int
|
||||
communityID* {.serializedFieldName("communityId").}: string
|
||||
|
||||
proc `$`*(self: TokenDto): string =
|
||||
result = fmt"""TokenDto[
|
||||
address: {self.address},
|
||||
name: {self.name},
|
||||
symbol: {self.symbol},
|
||||
decimals: {self.decimals},
|
||||
chainID: {self.chainID},
|
||||
communityID: {self.communityID}
|
||||
]"""
|
||||
|
||||
# TODO: Remove after https://github.com/status-im/status-desktop/issues/12513
|
||||
proc newTokenDto*(
|
||||
address: string,
|
||||
name: string,
|
||||
chainId: int,
|
||||
address: Address,
|
||||
symbol: string,
|
||||
decimals: int,
|
||||
hasIcon: bool,
|
||||
isCustom: bool = false,
|
||||
chainId: int,
|
||||
communityId: string = ""
|
||||
): TokenDto =
|
||||
return TokenDto(
|
||||
name: name,
|
||||
chainId: chainId,
|
||||
address: address,
|
||||
name: name,
|
||||
symbol: symbol,
|
||||
decimals: decimals,
|
||||
hasIcon: hasIcon,
|
||||
communityId: communityId,
|
||||
isCustom: isCustom
|
||||
chainId: chainId,
|
||||
communityId: communityId
|
||||
)
|
||||
|
||||
proc toTokenDto*(jsonObj: JsonNode, isVisible: bool, hasIcon: bool = false, isCustom: bool = true): TokenDto =
|
||||
result = TokenDto()
|
||||
result.isCustom = isCustom
|
||||
result.hasIcon = hasIcon
|
||||
type TokenSourceDto* = ref object of RootObj
|
||||
name* {.serializedFieldName("name").}: string
|
||||
tokens* {.serializedFieldName("tokens").}: seq[TokenDto]
|
||||
updatedAt* {.serializedFieldName("updatedAt").}: int64
|
||||
source* {.serializedFieldName("source").}: string
|
||||
version* {.serializedFieldName("version").}: string
|
||||
|
||||
discard jsonObj.getProp("name", result.name)
|
||||
discard jsonObj.getProp("chainId", result.chainId)
|
||||
discard jsonObj.getProp("address", result.address)
|
||||
discard jsonObj.getProp("symbol", result.symbol)
|
||||
discard jsonObj.getProp("decimals", result.decimals)
|
||||
discard jsonObj.getProp("color", result.color)
|
||||
discard jsonObj.getProp("communityId", result.communityId)
|
||||
result.isVisible = isVisible
|
||||
|
||||
proc addressAsString*(self: TokenDto): string =
|
||||
return $self.address
|
||||
proc `$`*(self: TokenSourceDto): string =
|
||||
result = fmt"""TokenSourceDto[
|
||||
name: {self.name},
|
||||
tokens: {self.tokens},
|
||||
updatedAt: {self.updatedAt},
|
||||
source: {self.source},
|
||||
version: {self.version}
|
||||
]"""
|
||||
|
@ -1,20 +1,19 @@
|
||||
import NimQml, Tables, json, sequtils, chronicles, strutils
|
||||
import NimQml, Tables, json, sequtils, chronicles, strutils, strformat, algorithm
|
||||
|
||||
import web3/ethtypes
|
||||
from web3/conversions import `$`
|
||||
import ../../../backend/backend as backend
|
||||
import backend/backend as backend
|
||||
|
||||
import ../network/service as network_service
|
||||
import ../wallet_account/dto/account_dto as wallet_account_dto
|
||||
import ../../../app/global/global_singleton
|
||||
import app_service/service/network/service as network_service
|
||||
import app_service/service/wallet_account/dto/account_dto
|
||||
|
||||
import ../../../app/core/eventemitter
|
||||
import ../../../app/core/tasks/[qt, threadpool]
|
||||
import ../../common/cache
|
||||
import app/core/eventemitter
|
||||
import app/core/tasks/[qt, threadpool]
|
||||
import app_service/common/cache
|
||||
import ../../../constants as main_constants
|
||||
import ./dto
|
||||
import ./dto, ./service_items
|
||||
|
||||
export dto
|
||||
export dto, service_items
|
||||
|
||||
logScope:
|
||||
topics = "token-service"
|
||||
@ -32,6 +31,8 @@ const CRYPTO_SUB_UNITS_TO_FACTOR = {
|
||||
# Signals which may be emitted by this service:
|
||||
const SIGNAL_TOKEN_HISTORICAL_DATA_LOADED* = "tokenHistoricalDataLoaded"
|
||||
const SIGNAL_BALANCE_HISTORY_DATA_READY* = "tokenBalanceHistoryDataReady"
|
||||
const SIGNAL_TOKENS_LIST_UPDATED* = "tokensListUpdated"
|
||||
const SIGNAL_TOKENS_LIST_ABOUT_TO_BE_UPDATED* = "tokensListAboutToBeUpdated"
|
||||
|
||||
type
|
||||
TokenHistoricalDataArgs* = ref object of Args
|
||||
@ -51,11 +52,22 @@ QtObject:
|
||||
events: EventEmitter
|
||||
threadpool: ThreadPool
|
||||
networkService: network_service.Service
|
||||
|
||||
# TODO: remove these once community usage of this service is removed etc...
|
||||
tokens: Table[int, seq[TokenDto]]
|
||||
tokenList: seq[TokenDto]
|
||||
tokensToAddressesMap: Table[string, TokenData]
|
||||
|
||||
priceCache: TimedCache[float64]
|
||||
|
||||
sourcesOfTokensList: seq[SupportedSourcesItem]
|
||||
flatTokenList: seq[TokenItem]
|
||||
tokenBySymbolList: seq[TokenBySymbolItem]
|
||||
# TODO: Table[symbol, TokenDetails] fetched from cryptocompare
|
||||
# will be done under https://github.com/status-im/status-desktop/issues/12668
|
||||
tokenDetailsList: Table[string, TokenDetails]
|
||||
|
||||
|
||||
proc updateCachedTokenPrice(self: Service, crypto: string, fiat: string, price: float64)
|
||||
proc jsonToPricesMap(node: JsonNode): Table[string, Table[string, float64]]
|
||||
|
||||
@ -77,10 +89,106 @@ QtObject:
|
||||
result.tokenList = @[]
|
||||
result.tokensToAddressesMap = initTable[string, TokenData]()
|
||||
|
||||
proc loadData*(self: Service) =
|
||||
if(not main_constants.WALLET_ENABLED):
|
||||
return
|
||||
result.sourcesOfTokensList = @[]
|
||||
result.flatTokenList = @[]
|
||||
result.tokenBySymbolList = @[]
|
||||
result.tokenDetailsList = initTable[string, TokenDetails]()
|
||||
|
||||
# Callback to process the response of getSupportedTokensList call
|
||||
proc supportedTokensListRetrieved(self: Service, response: string) {.slot.} =
|
||||
# this is emited so that the models can know that the seq it depends on has been updated
|
||||
defer: self.events.emit(SIGNAL_TOKENS_LIST_UPDATED, Args())
|
||||
|
||||
let parsedJson = response.parseJson
|
||||
var errorString: string
|
||||
var supportedTokensJson, tokensResult: JsonNode
|
||||
discard parsedJson.getProp("supportedTokensJson", supportedTokensJson)
|
||||
discard parsedJson.getProp("supportedTokensJson", errorString)
|
||||
discard supportedTokensJson.getProp("result", tokensResult)
|
||||
|
||||
if not errorString.isEmptyOrWhitespace:
|
||||
raise newException(Exception, "Error getting supported tokens list: " & errorString)
|
||||
let sourcesList = if tokensResult.isNil or tokensResult.kind == JNull: @[]
|
||||
else: Json.decode($tokensResult, seq[TokenSourceDto], allowUnknownFields = true)
|
||||
|
||||
let supportedNetworkChains = self.networkService.getAllNetworkChainIds()
|
||||
var flatTokensList: Table[string, TokenItem] = initTable[string, TokenItem]()
|
||||
var tokenBySymbolList: Table[string, TokenBySymbolItem] = initTable[string, TokenBySymbolItem]()
|
||||
|
||||
for s in sourcesList:
|
||||
let newSource = SupportedSourcesItem(name: s.name, updatedAt: s.updatedAt, source: s.source, version: s.version, tokensCount: s.tokens.len)
|
||||
self.sourcesOfTokensList.add(newSource)
|
||||
|
||||
for token in s.tokens:
|
||||
# Remove tokens that are not on list of supported status networks
|
||||
if supportedNetworkChains.contains(token.chainID):
|
||||
# logic for building flat tokens list
|
||||
let unique_key = $token.chainID & token.address
|
||||
if flatTokensList.hasKey(unique_key):
|
||||
flatTokensList[unique_key].sources.add(s.name)
|
||||
else:
|
||||
let tokenType = if s.name == "native" : NewTokenType.Native
|
||||
else: NewTokenType.ERC20
|
||||
flatTokensList[unique_key] = TokenItem(
|
||||
key: unique_key,
|
||||
name: token.name,
|
||||
symbol: token.symbol,
|
||||
sources: @[s.name],
|
||||
chainID: token.chainID,
|
||||
address: token.address,
|
||||
decimals: token.decimals,
|
||||
image: "",
|
||||
`type`: tokenType,
|
||||
communityId: token.communityID)
|
||||
|
||||
# logic for building tokens by symbol list
|
||||
# In case the token is not a community token the unique key is symbol
|
||||
# In case this is a community token the only param reliably unique is its address
|
||||
# as there is always a rare case that a user can create two or more community token
|
||||
# with same symbol and cannot be avoided
|
||||
let token_by_symbol_key = if token.communityID.isEmptyOrWhitespace: token.symbol
|
||||
else: token.address
|
||||
if tokenBySymbolList.hasKey(token_by_symbol_key):
|
||||
if not tokenBySymbolList[token_by_symbol_key].sources.contains(s.name):
|
||||
tokenBySymbolList[token_by_symbol_key].sources.add(s.name)
|
||||
# this logic is to check if an entry for same chainId as been made already,
|
||||
# in that case we simply add it to address per chain
|
||||
var addedChains: seq[int] = @[]
|
||||
for addressPerChain in tokenBySymbolList[token_by_symbol_key].addressPerChainId:
|
||||
addedChains.add(addressPerChain.chainId)
|
||||
if not addedChains.contains(token.chainID):
|
||||
tokenBySymbolList[token_by_symbol_key].addressPerChainId.add(AddressPerChain(chainId: token.chainID, address: token.address))
|
||||
else:
|
||||
let tokenType = if s.name == "native": NewTokenType.Native
|
||||
else: NewTokenType.ERC20
|
||||
tokenBySymbolList[token_by_symbol_key] = TokenBySymbolItem(
|
||||
key: token_by_symbol_key,
|
||||
name: token.name,
|
||||
symbol: token.symbol,
|
||||
sources: @[s.name],
|
||||
addressPerChainId: @[AddressPerChain(chainId: token.chainID, address: token.address)],
|
||||
decimals: token.decimals,
|
||||
image: "",
|
||||
`type`: tokenType,
|
||||
communityId: token.communityID)
|
||||
|
||||
self.flatTokenList = toSeq(flatTokensList.values)
|
||||
self.flatTokenList.sort(cmpTokenItem)
|
||||
self.tokenBySymbolList = toSeq(tokenBySymbolList.values)
|
||||
self.tokenBySymbolList.sort(cmpTokenBySymbolItem)
|
||||
|
||||
proc getSupportedTokensList(self: Service) =
|
||||
# this is emited so that the models can know that an update is about to happen
|
||||
self.events.emit(SIGNAL_TOKENS_LIST_ABOUT_TO_BE_UPDATED, Args())
|
||||
let arg = GetTokenListTaskArg(
|
||||
tptr: cast[ByteAddress](getSupportedTokenList),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "supportedTokensListRetrieved",
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
|
||||
# TODO: Remove after https://github.com/status-im/status-desktop/issues/12513
|
||||
proc loadData*(self: Service) =
|
||||
try:
|
||||
let networks = self.networkService.getNetworks()
|
||||
|
||||
@ -95,21 +203,18 @@ QtObject:
|
||||
if found:
|
||||
continue
|
||||
let responseTokens = backend.getTokens(network.chainId)
|
||||
let default_tokens = map(
|
||||
responseTokens.result.getElems(),
|
||||
proc(x: JsonNode): TokenDto = x.toTokenDto(network.enabled, hasIcon=true, isCustom=false)
|
||||
)
|
||||
let default_tokens = Json.decode($responseTokens.result, seq[TokenDto], allowUnknownFields = true)
|
||||
self.tokens[network.chainId] = default_tokens.filter(
|
||||
proc(x: TokenDto): bool = x.chainId == network.chainId
|
||||
)
|
||||
|
||||
let nativeToken = newTokenDto(
|
||||
address = "0x0000000000000000000000000000000000000000",
|
||||
name = network.nativeCurrencyName,
|
||||
chainId = network.chainId,
|
||||
address = Address.fromHex("0x0000000000000000000000000000000000000000"),
|
||||
symbol = network.nativeCurrencySymbol,
|
||||
decimals = network.nativeCurrencyDecimals,
|
||||
hasIcon = false
|
||||
chainId = network.chainId,
|
||||
communityID = ""
|
||||
)
|
||||
|
||||
if not self.tokensToAddressesMap.hasKey(network.nativeCurrencySymbol):
|
||||
@ -137,8 +242,23 @@ QtObject:
|
||||
error "Tokens init error", errDesription = e.msg
|
||||
|
||||
proc init*(self: Service) =
|
||||
if(not main_constants.WALLET_ENABLED):
|
||||
return
|
||||
self.loadData()
|
||||
self.getSupportedTokensList()
|
||||
# ToDo: on self.events.on(SignalType.Message.event) do(e: Args):
|
||||
# update and populate internal list and then emit signal
|
||||
|
||||
proc getSourcesOfTokensList*(self: Service): var seq[SupportedSourcesItem] =
|
||||
return self.sourcesOfTokensList
|
||||
|
||||
proc getFlatTokensList*(self: Service): var seq[TokenItem] =
|
||||
return self.flatTokenList
|
||||
|
||||
proc getTokenBySymbolList*(self: Service): var seq[TokenBySymbolItem] =
|
||||
return self.tokenBySymbolList
|
||||
|
||||
# TODO: Remove after https://github.com/status-im/status-desktop/issues/12513
|
||||
proc getTokenList*(self: Service): seq[TokenDto] =
|
||||
return self.tokenList
|
||||
|
||||
@ -160,10 +280,11 @@ QtObject:
|
||||
if token.symbol == symbol:
|
||||
return token
|
||||
|
||||
proc findTokenByAddress*(self: Service, network: NetworkDto, address: Address): TokenDto =
|
||||
if not self.tokens.hasKey(network.chainId):
|
||||
# TODO: Shouldnt be needed after accounts assets are restructured
|
||||
proc findTokenByAddress*(self: Service, networkChainId: int, address: string): TokenDto =
|
||||
if not self.tokens.hasKey(networkChainId):
|
||||
return
|
||||
for token in self.tokens[network.chainId]:
|
||||
for token in self.tokens[networkChainId]:
|
||||
if token.address == address:
|
||||
return token
|
||||
|
||||
@ -179,7 +300,7 @@ QtObject:
|
||||
|
||||
for _, tokens in self.tokens:
|
||||
for token in tokens:
|
||||
if token.address == hexAddressValue:
|
||||
if token.address == $hexAddressValue:
|
||||
return token.symbol
|
||||
return ""
|
||||
|
||||
@ -264,7 +385,9 @@ QtObject:
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
|
||||
# Callback to process the response of fetchHistoricalBalanceForTokenAsJson call
|
||||
# TODO: The below two APIS are not linked with generic tokens list but with assets per account and should perhaps be moved to
|
||||
# wallet_account->token_service.nim and clean up rest of the code too. Callback to process the response of
|
||||
# fetchHistoricalBalanceForTokenAsJson call
|
||||
proc tokenBalanceHistoryDataResolved*(self: Service, response: string) {.slot.} =
|
||||
let responseObj = response.parseJson
|
||||
if (responseObj.kind != JObject):
|
||||
@ -291,7 +414,7 @@ QtObject:
|
||||
chainIds.add(network.chainId)
|
||||
|
||||
if chainIds.len == 0:
|
||||
error "faild to find a network with the symbol", tokenSymbol
|
||||
error "failed to find a network with the symbol", tokenSymbol
|
||||
return
|
||||
|
||||
let arg = GetTokenBalanceHistoryDataTaskArg(
|
||||
|
93
src/app_service/service/token/service_items.nim
Normal file
93
src/app_service/service/token/service_items.nim
Normal file
@ -0,0 +1,93 @@
|
||||
import strformat, Tables
|
||||
|
||||
import app_service/common/types as common_types
|
||||
#TODO: remove dependency
|
||||
import ../wallet_account/dto/token_dto
|
||||
|
||||
# This file holds the data types used by models internally
|
||||
|
||||
type SupportedSourcesItem* = ref object of RootObj
|
||||
name*: string
|
||||
updatedAt* : int64
|
||||
source*: string
|
||||
version*: string
|
||||
# Needed to show upfront on ui count of tokens on each list
|
||||
tokensCount*: int
|
||||
|
||||
proc `$`*(self: SupportedSourcesItem): string =
|
||||
result = fmt"""SupportedSourcesItem[
|
||||
name: {self.name},
|
||||
updatedAt: {self.updatedAt},
|
||||
source: {self.source},
|
||||
version: {self.version},
|
||||
tokensCount: {self.tokensCount}
|
||||
]"""
|
||||
|
||||
type
|
||||
TokenItem* = ref object of RootObj
|
||||
# key is created using chainId and Address
|
||||
key*: string
|
||||
name*: string
|
||||
symbol*: string
|
||||
# uniswap/status/custom seq[string]
|
||||
sources*: seq[string]
|
||||
chainID*: int
|
||||
address*: string
|
||||
decimals*: int
|
||||
# will remain empty until backend provides us this data
|
||||
image*: string
|
||||
`type`*: common_types.NewTokenType
|
||||
communityId*: string
|
||||
|
||||
proc `$`*(self: TokenItem): string =
|
||||
result = fmt"""TokenItem[
|
||||
key: {self.key},
|
||||
name: {self.name},
|
||||
symbol: {self.symbol},
|
||||
sources: {self.sources},
|
||||
chainID: {self.chainID},
|
||||
address: {self.address},
|
||||
decimals: {self.decimals},
|
||||
image: {self.image},
|
||||
`type`: {self.`type`},
|
||||
communityId: {self.communityId}
|
||||
]"""
|
||||
|
||||
type AddressPerChain* = ref object of RootObj
|
||||
chainId*: int
|
||||
address*: string
|
||||
|
||||
proc `$`*(self: AddressPerChain): string =
|
||||
result = fmt"""AddressPerChain[
|
||||
chainId: {self.chainId},
|
||||
address: {self.address}
|
||||
]"""
|
||||
|
||||
type
|
||||
TokenBySymbolItem* = ref object of TokenItem
|
||||
addressPerChainId*: seq[AddressPerChain]
|
||||
|
||||
proc `$`*(self: TokenBySymbolItem): string =
|
||||
result = fmt"""TokenBySymbolItem[
|
||||
key: {self.key},
|
||||
name: {self.name},
|
||||
symbol: {self.symbol},
|
||||
sources: {self.sources},
|
||||
addressPerChainId: {self.addressPerChainId},
|
||||
decimals: {self.decimals},
|
||||
image: {self.image},
|
||||
`type`: {self.`type`},
|
||||
communityId: {self.communityId}
|
||||
]"""
|
||||
|
||||
# In case of community tokens only the description will be available
|
||||
type TokenDetails* = ref object of RootObj
|
||||
description*: string
|
||||
websiteUrl*: string
|
||||
marketValues*: TokenMarketValuesDto
|
||||
|
||||
proc cmpTokenItem*(x, y: TokenItem): int =
|
||||
cmp(x.name, y.name)
|
||||
|
||||
proc cmpTokenBySymbolItem*(x, y: TokenBySymbolItem): int =
|
||||
cmp(x.name, y.name)
|
@ -341,7 +341,7 @@ QtObject:
|
||||
else:
|
||||
let network = self.networkService.getNetwork(chainID)
|
||||
let token = self.tokenService.findTokenBySymbol(network.chainId, tokenSym)
|
||||
toAddress = token.address
|
||||
toAddress = parseAddress(token.address)
|
||||
|
||||
let transfer = Transfer(
|
||||
to: parseAddress(to_addr),
|
||||
|
@ -95,6 +95,9 @@ rpc(checkConnected, "wallet"):
|
||||
rpc(getTokens, "wallet"):
|
||||
chainId: int
|
||||
|
||||
rpc(getTokenList, "wallet"):
|
||||
discard
|
||||
|
||||
rpc(getTokensBalancesForChainIDs, "wallet"):
|
||||
chainIds: seq[int]
|
||||
accounts: seq[string]
|
||||
|
@ -31,10 +31,6 @@ SplitView {
|
||||
ExpressionRole {
|
||||
name: "explorerUrl"
|
||||
expression: { return "https://status.im/" }
|
||||
},
|
||||
ExpressionRole {
|
||||
name: "jsArraySources"
|
||||
expression: model.sources.split(";")
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -29,10 +29,6 @@ SplitView {
|
||||
ExpressionRole {
|
||||
name: "explorerUrl"
|
||||
expression: { return "https://status.im/" }
|
||||
},
|
||||
ExpressionRole {
|
||||
name: "jsArraySources"
|
||||
expression: model.sources.split(";")
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -89,8 +85,9 @@ SplitView {
|
||||
sourceModel: root.tokensProxyModel
|
||||
|
||||
// Filter by source
|
||||
filters: ExpressionFilter {
|
||||
expression: model.jsArraySources.includes(keyFilter.value)
|
||||
filters: RegExpFilter {
|
||||
roleName: "sources"
|
||||
pattern: "\;" + keyFilter.value + "\;"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ ListModel {
|
||||
key: "0",
|
||||
name: "Unisocks",
|
||||
symbol: "SOCKS",
|
||||
sources: uniswap + ";" + status,
|
||||
sources: ";" + uniswap + ";" + status + ";",
|
||||
chainId: NetworksModel.ethNet,
|
||||
address: "0x0000000000000000000000000000000000000123",
|
||||
decimals: "18",
|
||||
@ -27,7 +27,7 @@ ListModel {
|
||||
key: "1",
|
||||
name: "Unisocks",
|
||||
symbol: "SOCKS",
|
||||
sources: uniswap + ";" + status,
|
||||
sources: ";" + uniswap + ";" + status + ";",
|
||||
chainId: NetworksModel.optimismNet,
|
||||
address: "0x00000000000000000000000000000000000ade21",
|
||||
decimals: "18",
|
||||
@ -41,7 +41,7 @@ ListModel {
|
||||
key: "2",
|
||||
name: "Ox",
|
||||
symbol: "ZRX",
|
||||
sources: uniswap + ";" + status,
|
||||
sources: ";" + uniswap + ";" + status + ";",
|
||||
chainId: NetworksModel.ethNet,
|
||||
address: "0x1230000000000000000000000000000000000123",
|
||||
decimals: "18",
|
||||
@ -55,7 +55,7 @@ ListModel {
|
||||
key: "3",
|
||||
name: "1inch",
|
||||
symbol: "1INCH",
|
||||
sources: uniswap + ";" + status,
|
||||
sources: ";" + uniswap + ";" + status + ";",
|
||||
chainId: NetworksModel.ethNet,
|
||||
address: "0x4321000000000000000000000000000000000123",
|
||||
decimals: "18",
|
||||
@ -69,7 +69,7 @@ ListModel {
|
||||
key: "4",
|
||||
name: "Aave",
|
||||
symbol: "AAVE",
|
||||
sources: uniswap + ";" + status,
|
||||
sources: ";" + uniswap + ";" + status + ";",
|
||||
chainId: NetworksModel.arbitrumNet,
|
||||
address: "0x6543000000000000000000000000000000000123",
|
||||
decimals: "18",
|
||||
@ -83,7 +83,7 @@ ListModel {
|
||||
key: "5",
|
||||
name: "Amp",
|
||||
symbol: "AMP",
|
||||
sources: uniswap,
|
||||
sources: ";" + uniswap + ";",
|
||||
chainId: NetworksModel.arbitrumNet,
|
||||
address: "0x6543700000000000000000000000000000000123",
|
||||
decimals: "18",
|
||||
@ -97,7 +97,7 @@ ListModel {
|
||||
key: "6",
|
||||
name: "Dai",
|
||||
symbol: "DAI",
|
||||
sources: uniswap,
|
||||
sources: ";" + uniswap + ";",
|
||||
chainId: NetworksModel.optimismNet,
|
||||
address: "0xabc2000000000000000000000000000000000123",
|
||||
decimals: "18",
|
||||
@ -111,7 +111,7 @@ ListModel {
|
||||
key: "7",
|
||||
name: "snt",
|
||||
symbol: "SNT",
|
||||
sources: status,
|
||||
sources: ";" + status + ";",
|
||||
chainId: NetworksModel.optimismNet,
|
||||
address: "0xbbc2000000000000000000000000000000000123",
|
||||
decimals: "18",
|
||||
@ -125,7 +125,7 @@ ListModel {
|
||||
key: "8",
|
||||
name: "snt",
|
||||
symbol: "SNT",
|
||||
sources: status,
|
||||
sources: ";" + status + ";",
|
||||
chainId: NetworksModel.ethNet,
|
||||
address: "0xbbc200000000000000000000000000000000abcd",
|
||||
decimals: "18",
|
||||
|
@ -94,8 +94,9 @@ StatusListView {
|
||||
sourceModel: root.tokensListModel
|
||||
|
||||
// Filter by source
|
||||
filters: ExpressionFilter {
|
||||
expression: (model.jsArraySources).includes(keyFilter.value)
|
||||
filters: RegExpFilter {
|
||||
roleName: "sources"
|
||||
pattern: "\;" + keyFilter.value + "\;"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ StatusDialog {
|
||||
required property int sourceUpdatedAt
|
||||
required property string sourceVersion
|
||||
required property int tokensCount
|
||||
required property var tokensListModel // Expected roles: name, symbol, image, chainName, explorerUrl
|
||||
required property var tokensListModel // Expected roles: name, symbol, image, chainName, explorerUrl, isTest
|
||||
|
||||
signal linkClicked(string link)
|
||||
|
||||
@ -45,7 +45,6 @@ StatusDialog {
|
||||
bottomMargin: Style.current.padding
|
||||
implicitHeight: contentHeight
|
||||
|
||||
model: root.tokensListModel
|
||||
header: ColumnLayout {
|
||||
spacing: 20
|
||||
width: list.width
|
||||
@ -60,6 +59,10 @@ StatusDialog {
|
||||
CustomHeaderDelegate {}
|
||||
}
|
||||
delegate: CustomDelegate {}
|
||||
/* This late binding has been added here because without it all
|
||||
the items in the list get initialised before the popup is launched
|
||||
creating a delay */
|
||||
Component.onCompleted: model = Qt.binding(() => root.tokensListModel)
|
||||
}
|
||||
|
||||
header: StatusDialogHeader {
|
||||
@ -102,6 +105,7 @@ StatusDialog {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: textBlock.text
|
||||
elide: Text.ElideRight
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
}
|
||||
@ -118,7 +122,7 @@ StatusDialog {
|
||||
textColor: Theme.palette.baseColor1
|
||||
textHoverColor: Theme.palette.directColor1
|
||||
icon.name: "external-link"
|
||||
onClicked: root.linkClicked(root.sourceUrl)
|
||||
onClicked: root.linkClicked(link)
|
||||
}
|
||||
|
||||
component CustomSourceInfoComponent: ColumnLayout {
|
||||
@ -236,7 +240,7 @@ StatusDialog {
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: model.chainName
|
||||
text: model.chainName + (model.isTest? " " + qsTr("(Test)") : "")
|
||||
elide: Text.ElideMiddle
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
|
@ -9,13 +9,13 @@ QtObject {
|
||||
id: root
|
||||
|
||||
/* PRIVATE: Modules used to get data from backend */
|
||||
readonly property var _walletModule: walletSectionNewModule
|
||||
readonly property var _allTokensModule: walletSectionAllTokens
|
||||
readonly property var _networksModule: networksModule
|
||||
|
||||
/* This contains the different sources for the tokens list
|
||||
ex. uniswap list, status tokens list */
|
||||
readonly property var sourcesOfTokensModel: SortFilterProxyModel {
|
||||
sourceModel: root._walletModule.sourcesOfTokensModel
|
||||
sourceModel: root._allTokensModule.sourcesOfTokensModel
|
||||
proxyRoles: ExpressionRole {
|
||||
function sourceImage(sourceKey) {
|
||||
return Constants.getSupportedTokenSourceImage(sourceKey)
|
||||
@ -23,16 +23,26 @@ QtObject {
|
||||
name: "image"
|
||||
expression: sourceImage(model.key)
|
||||
}
|
||||
filters: AnyOf {
|
||||
ValueFilter {
|
||||
roleName: "key"
|
||||
value: Constants.supportedTokenSources.uniswap
|
||||
}
|
||||
ValueFilter {
|
||||
roleName: "key"
|
||||
value: Constants.supportedTokenSources.status
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This list contains the complete list of tokens with separate
|
||||
entry per token which has a unique [address + network] pair */
|
||||
readonly property var flatTokensModel: root._walletModule.flatTokensModel
|
||||
readonly property var flatTokensModel: root._allTokensModule.flatTokensModel
|
||||
|
||||
/* PRIVATE: This model just combines tokens and network information in one */
|
||||
readonly property LeftJoinModel _joinFlatTokensModel : LeftJoinModel {
|
||||
leftModel: root.flatTokensModel
|
||||
rightModel: root._networksModule.all
|
||||
rightModel: root._networksModule.flatNetworks
|
||||
|
||||
joinRole: "chainId"
|
||||
}
|
||||
@ -46,7 +56,7 @@ QtObject {
|
||||
proxyRoles: [
|
||||
ExpressionRole {
|
||||
name: "explorerUrl"
|
||||
expression: { return model.blockExplorerURL + "/" + model.address } // TO REVIEW the correct composition!!
|
||||
expression: model.blockExplorerURL + "/token/" + model.address
|
||||
},
|
||||
ExpressionRole {
|
||||
function tokenIcon(symbol) {
|
||||
@ -54,10 +64,6 @@ QtObject {
|
||||
}
|
||||
name: "image"
|
||||
expression: tokenIcon(model.symbol)
|
||||
},
|
||||
ExpressionRole {
|
||||
name: "jsArraySources"
|
||||
expression: model.sources.split(";")
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -68,7 +74,7 @@ QtObject {
|
||||
there will be one entry per address + network pair */
|
||||
// TODO in #12513
|
||||
readonly property var tokensBySymbolModel: SortFilterProxyModel {
|
||||
sourceModel: root._walletModule.tokensBySymbolModel
|
||||
sourceModel: root._allTokensModule.tokensBySymbolModel
|
||||
proxyRoles: [
|
||||
ExpressionRole {
|
||||
function tokenIcon(symbol) {
|
||||
|
@ -789,8 +789,8 @@ QtObject {
|
||||
}
|
||||
|
||||
readonly property QtObject supportedTokenSources: QtObject {
|
||||
readonly property string uniswap: "uniswap"
|
||||
readonly property string status: "status"
|
||||
readonly property string uniswap: "Uniswap Labs Default Token List"
|
||||
readonly property string status: "Status Token List"
|
||||
readonly property string custom: "custom"
|
||||
}
|
||||
|
||||
|
2
vendor/status-go
vendored
2
vendor/status-go
vendored
@ -1 +1 @@
|
||||
Subproject commit ecbacb0a7fd5e4e9ee15dc8a6aa4209a582c4162
|
||||
Subproject commit 5381ec4a767750034722c6611686f69215110366
|
Loading…
x
Reference in New Issue
Block a user