feat: prepare token service for multichain

This commit is contained in:
Anthony Laibe 2022-02-08 14:32:21 +01:00 committed by Anthony Laibe
parent 036d8491fb
commit 7268ec3773
22 changed files with 212 additions and 146 deletions

View File

@ -128,17 +128,19 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
result.keychainService = keychain_service.newService(statusFoundation.events)
result.ethService = eth_service.newService()
result.accountsService = accounts_service.newService(statusFoundation.fleetConfiguration)
result.networkService = network_service.newService()
result.contactsService = contacts_service.newService(statusFoundation.events,
statusFoundation.threadpool, result.settingsService)
result.networkService = network_service.newService(result.settingsService)
result.contactsService = contacts_service.newService(
statusFoundation.events, statusFoundation.threadpool, result.settingsService
)
result.chatService = chat_service.newService(statusFoundation.events, result.contactsService)
result.communityService = community_service.newService(statusFoundation.events, result.chatService)
result.messageService = message_service.newService(statusFoundation.events, statusFoundation.threadpool,
result.contactsService)
result.activityCenterService = activity_center_service.newService(statusFoundation.events,
statusFoundation.threadpool, result.chatService)
result.tokenService = token_service.newService(statusFoundation.events, statusFoundation.threadpool,
result.settingsService)
result.tokenService = token_service.newService(
statusFoundation.events, statusFoundation.threadpool, result.settingsService, result.networkService
)
result.collectibleService = collectible_service.newService(result.settingsService)
result.walletAccountService = wallet_account_service.newService(statusFoundation.events, result.settingsService,
result.accountsService, result.tokenService)

View File

@ -37,14 +37,14 @@ method init*(self: Controller) =
method getTokens*(self: Controller): seq[token_service.TokenDto] =
return self.tokenService.getTokens()
method addCustomToken*(self: Controller, address: string, name: string, symbol: string, decimals: int) =
self.tokenService.addCustomToken(address, name, symbol, decimals)
method addCustomToken*(self: Controller, chainId: int, address: string, name: string, symbol: string, decimals: int) =
self.tokenService.addCustomToken(chainId, address, name, symbol, decimals)
method toggleVisible*(self: Controller, symbol: string) =
self.walletAccountService.toggleTokenVisible(symbol)
method toggleVisible*(self: Controller, chainId: int, symbol: string) =
self.walletAccountService.toggleTokenVisible(chainId, symbol)
method removeCustomToken*(self: Controller, address: string) =
self.tokenService.removeCustomToken(address)
method removeCustomToken*(self: Controller, chainId: int, address: string) =
self.tokenService.removeCustomToken(chainId, address)
method getTokenDetails*(self: Controller, address: string) =
self.tokenService.getTokenDetails(address)
method getTokenDetails*(self: Controller, chainId: int, address: string) =
self.tokenService.getTokenDetails(chainId, address)

View File

@ -13,16 +13,16 @@ method init*(self: AccessInterface) {.base.} =
method getTokens*(self: AccessInterface): seq[token_service.TokenDto] {.base.} =
raise newException(ValueError, "No implementation available")
method addCustomToken*(self: AccessInterface, address: string, name: string, symbol: string, decimals: int) =
method addCustomToken*(self: AccessInterface, chainId: int, address: string, name: string, symbol: string, decimals: int) =
raise newException(ValueError, "No implementation available")
method toggleVisible*(self: AccessInterface, symbol: string) =
method toggleVisible*(self: AccessInterface, chainId: int, symbol: string) =
raise newException(ValueError, "No implementation available")
method removeCustomToken*(self: AccessInterface, address: string) =
method removeCustomToken*(self: AccessInterface, chainId: int, address: string) =
raise newException(ValueError, "No implementation available")
method getTokenDetails*(self: AccessInterface, address: string) =
method getTokenDetails*(self: AccessInterface, chainId: int, address: string) =
raise newException(ValueError, "No implementation available")
type

View File

@ -11,19 +11,19 @@ method load*(self: AccessInterface) {.base.} =
method isLoaded*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")
method addCustomToken*(self: AccessInterface, address: string, name: string, symbol: string, decimals: int) {.base.} =
method addCustomToken*(self: AccessInterface, chainId: int, address: string, name: string, symbol: string, decimals: int) {.base.} =
raise newException(ValueError, "No implementation available")
method toggleVisible*(self: AccessInterface, symbol: string) {.base.} =
method toggleVisible*(self: AccessInterface, chainId: int, symbol: string) {.base.} =
raise newException(ValueError, "No implementation available")
method removeCustomToken*(self: AccessInterface, address: string) {.base.} =
method removeCustomToken*(self: AccessInterface, chainId: int, address: string) {.base.} =
raise newException(ValueError, "No implementation available")
method refreshTokens*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method getTokenDetails*(self: AccessInterface, address: string) {.base.} =
method getTokenDetails*(self: AccessInterface, chainId: int, address: string) {.base.} =
raise newException(ValueError, "No implementation available")
method tokenDetailsWereResolved*(self: AccessInterface, tokenDetails: string) {.base.} =

View File

@ -9,8 +9,11 @@ type
decimals: int
isCustom: bool
isVisible: bool
chainId: int
proc initItem*(name, symbol: string, hasIcon: bool, address: string, decimals: int, isCustom: bool, isVisible: bool): Item =
proc initItem*(
name, symbol: string, hasIcon: bool, address: string, decimals: int, isCustom: bool, isVisible: bool, chainId: int
): Item =
result.name = name
result.symbol = symbol
result.hasIcon = hasIcon
@ -18,6 +21,7 @@ proc initItem*(name, symbol: string, hasIcon: bool, address: string, decimals: i
result.decimals = decimals
result.isCustom = isCustom
result.isVisible = isVisible
result.chainId = chainId
proc `$`*(self: Item): string =
result = fmt"""AllTokensItem(
@ -27,7 +31,8 @@ proc `$`*(self: Item): string =
address: {self.address},
decimals: {self.decimals},
isCustom:{self.isCustom},
isVisible:{self.isVisible}
isVisible:{self.isVisible},
chainId:{self.chainId}
]"""
proc getName*(self: Item): string =
@ -50,3 +55,6 @@ proc getIsCustom*(self: Item): bool =
proc getIsVisible*(self: Item): bool =
return self.isVisible
proc getChainId*(self: Item): int =
return self.chainId

View File

@ -11,6 +11,7 @@ type
Decimals
IsCustom
IsVisible
ChainId
QtObject:
type
@ -52,7 +53,8 @@ QtObject:
ModelRole.Address.int:"address",
ModelRole.Decimals.int:"decimals",
ModelRole.IsCustom.int:"isCustom",
ModelRole.IsVisible.int:"isVisible"
ModelRole.IsVisible.int:"isVisible",
ModelRole.ChainId.int:"chainId"
}.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant =
@ -80,6 +82,8 @@ QtObject:
result = newQVariant(item.getIsCustom())
of ModelRole.IsVisible:
result = newQVariant(item.getIsVisible())
of ModelRole.ChainId:
result = newQVariant(item.getChainId())
proc setItems*(self: Model, items: seq[Item]) =
self.beginResetModel()

View File

@ -45,7 +45,8 @@ method refreshTokens*(self: Module) =
t.addressAsString(),
t.decimals,
t.isCustom,
t.isVisible
t.isVisible,
t.chainId,
))
)
@ -73,17 +74,17 @@ method viewDidLoad*(self: Module) =
self.moduleLoaded = true
self.delegate.allTokensModuleDidLoad()
method addCustomToken*(self: Module, address: string, name: string, symbol: string, decimals: int) =
self.controller.addCustomToken(address, name, symbol, decimals)
method addCustomToken*(self: Module, chainId: int, address: string, name: string, symbol: string, decimals: int) =
self.controller.addCustomToken(chainId, address, name, symbol, decimals)
method toggleVisible*(self: Module, symbol: string) =
self.controller.toggleVisible(symbol)
method toggleVisible*(self: Module, chainId: int, symbol: string) =
self.controller.toggleVisible(chainId, symbol)
method removeCustomToken*(self: Module, address: string) =
self.controller.removeCustomToken(address)
method removeCustomToken*(self: Module, chainId: int, address: string) =
self.controller.removeCustomToken(chainId, address)
method getTokenDetails*(self: Module, address: string) =
self.controller.getTokenDetails(address)
method getTokenDetails*(self: Module, chainId: int, address: string) =
self.controller.getTokenDetails(chainId, address)
method tokenDetailsWereResolved*(self: Module, tokenDetails: string) =
self.view.tokenDetailsWereResolved(tokenDetails)

View File

@ -61,16 +61,16 @@ QtObject:
self.custom.setItems(items.filter(i => i.getIsCustom()))
self.default.setItems(items.filter(i => not i.getIsCustom()))
proc addCustomToken(self: View, address: string, name: string, symbol: string, decimals: string) {.slot.} =
self.delegate.addCustomToken(address, name, symbol, parseInt(decimals))
proc addCustomToken(self: View, chainId: int, address: string, name: string, symbol: string, decimals: string) {.slot.} =
self.delegate.addCustomToken(chainId, address, name, symbol, parseInt(decimals))
proc toggleVisible(self: View, symbol: string) {.slot.} =
self.delegate.toggleVisible(symbol)
proc toggleVisible(self: View, chainId: int, symbol: string) {.slot.} =
self.delegate.toggleVisible(chainId, symbol)
proc removeCustomToken(self: View, address: string) {.slot.} =
self.delegate.removeCustomToken(address)
proc removeCustomToken(self: View, chainId: int, address: string) {.slot.} =
self.delegate.removeCustomToken(chainId, address)
proc tokenDetailsWereResolved*(self: View, tokenDetails: string) {.signal.}
proc getTokenDetails*(self: View, address: string) {.slot.} =
self.delegate.getTokenDetails(address)
proc getTokenDetails*(self: View, chainId: int, address: string) {.slot.} =
self.delegate.getTokenDetails(chainId, address)

View File

@ -1,5 +1,5 @@
import strformat, json, json_serialization
import hashes, strformat, json, json_serialization
import ./types
@ -19,6 +19,9 @@ type NetworkDto* = ref object
proc `$`*(self: NetworkDto): string =
return fmt"Network(chainId:{self.chainId}, name:{self.chainName}, rpcURL:{self.rpcURL}, isTest:{self.isTest}, enabled:{self.enabled})"
proc hash*(self: NetworkDto): Hash =
return self.chainId.hash
proc toPayload*(self: NetworkDto): JsonNode =
return %* [Json.encode(self).parseJson]

View File

@ -1,26 +1,32 @@
import json, json_serialization, chronicles, atomics
import options
import ../../../backend/network as status_network
import ./service_interface
export service_interface
import ../../../app/global/global_singleton
import ../../../backend/network as status_network
import ../settings/service as settings_service
import ./service_interface as network_interface
export network_interface
logScope:
topics = "network-service"
type
Service* = ref object of ServiceInterface
Service* = ref object of network_interface.ServiceInterface
networks: seq[NetworkDto]
networksInited: bool
dirty: Atomic[bool]
settingsService: settings_service.Service
method delete*(self: Service) =
discard
proc newService*(): Service =
proc newService*(settingsService: settings_service.Service): Service =
result = Service()
result.settingsService = settingsService
method init*(self: Service) =
discard
@ -40,6 +46,18 @@ method getNetworks*(self: Service, useCached: bool = true): seq[NetworkDto] =
self.networks = result
self.networksInited = true
method getEnabledNetworks*(self: Service): seq[NetworkDto] =
if not singletonInstance.localAccountSensitiveSettings.getIsMultiNetworkEnabled():
let currentNetworkType = self.settingsService.getCurrentNetwork().toNetworkType()
for network in self.getNetworks():
if currentNetworkType.toChainId() == network.chainId:
return @[network]
let networks = self.getNetworks()
for network in networks:
if network.enabled:
result.add(network)
method upsertNetwork*(self: Service, network: NetworkDto) =
discard status_network.upsertNetwork(network.toPayload())
self.dirty.store(true)
@ -48,6 +66,11 @@ method deleteNetwork*(self: Service, network: NetworkDto) =
discard status_network.deleteNetwork(%* [network.chainId])
self.dirty.store(true)
method getNetwork*(self: Service, chainId: int): NetworkDto =
for network in self.getNetworks():
if chainId == network.chainId:
return network
method getNetwork*(self: Service, networkType: NetworkType): NetworkDto =
for network in self.getNetworks():
if networkType.toChainId() == network.chainId:

View File

@ -15,6 +15,9 @@ method init*(self: ServiceInterface) {.base.} =
method getNetworks*(self: ServiceInterface, useCached: bool = true): seq[NetworkDto] {.base.} =
raise newException(ValueError, "No implementation available")
method getEnabledNetworks*(self: ServiceInterface): seq[NetworkDto] {.base.} =
raise newException(ValueError, "No implementation available")
method upsertNetwork*(self: ServiceInterface, network: NetworkDto) {.base.} =
raise newException(ValueError, "No implementation available")
@ -23,3 +26,6 @@ method deleteNetwork*(self: ServiceInterface, network: NetworkDto) {.base.} =
method getNetwork*(self: ServiceInterface, networkType: NetworkType): NetworkDto {.base.} =
raise newException(ValueError, "No implementation available")
method getNetwork*(self: ServiceInterface, chainId: int): NetworkDto {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -1,4 +1,4 @@
import json, options, tables, strutils, marshal
import Tables, json, options, tables, strutils, marshal
import ../../stickers/dto/stickers
include ../../../common/json_utils
@ -73,9 +73,6 @@ type CurrentUserStatus* = object
clock*: int64
text*: string
type WalletVisibleTokens* = object
tokens*: seq[string]
type
SettingsDto* = object # There is no point to keep all these info as settings, but we must follow status-go response
address*: string
@ -109,7 +106,7 @@ type
telemetryServerUrl*: string
fleet*: string
currentUserStatus*: CurrentUserStatus
walletVisibleTokens*: WalletVisibleTokens
walletVisibleTokens*: Table[int, seq[string]] # [chainId, seq[tokenIds]]
nodeConfig*: JsonNode
wakuBloomFilterMode*: bool
recentStickerHashes*: seq[string]
@ -153,16 +150,17 @@ proc toCurrentUserStatus*(jsonObj: JsonNode): CurrentUserStatus =
discard jsonObj.getProp("clock", result.clock)
discard jsonObj.getProp("text", result.text)
proc toWalletVisibleTokens*(jsonObj: JsonNode, networkId: string): WalletVisibleTokens =
for netId, tokenArr in jsonObj:
if(netId != networkId or tokenArr.kind != JArray):
proc toWalletVisibleTokens*(jsonObj: JsonNode): Table[int, seq[string]] =
for chainIdStr, tokenArr in jsonObj:
if(tokenArr.kind != JArray):
continue
let chainId = parseInt(chainIdStr)
result[chainId] = @[]
for token in tokenArr:
result.tokens.add(token.getStr)
result[chainId].add(token.getStr)
proc toSettingsDto*(jsonObj: JsonNode): SettingsDto =
discard jsonObj.getProp(KEY_ADDRESS, result.address)
discard jsonObj.getProp(KEY_CURRENCY, result.currency)
discard jsonObj.getProp(KEY_NETWORKS_CURRENT_NETWORK, result.currentNetwork)
@ -226,7 +224,7 @@ proc toSettingsDto*(jsonObj: JsonNode): SettingsDto =
var walletVisibleTokensObj: JsonNode
if(jsonObj.getProp(KEY_WALLET_VISIBLE_TOKENS, walletVisibleTokensObj)):
result.walletVisibleTokens = toWalletVisibleTokens(walletVisibleTokensObj, result.currentNetwork)
result.walletVisibleTokens = toWalletVisibleTokens(walletVisibleTokensObj)
discard jsonObj.getProp(KEY_NODE_CONFIG, result.nodeConfig)
discard jsonObj.getProp(KEY_WAKU_BLOOM_FILTER_MODE, result.wakuBloomFilterMode)

View File

@ -375,15 +375,18 @@ method pinMailserver*(self: Service, address: string, fleet: Fleet): bool =
method unpinMailserver*(self: Service, fleet: Fleet): bool =
return self.pinMailserver("", fleet)
method getWalletVisibleTokens*(self: Service): seq[string] =
self.settings.walletVisibleTokens.tokens
method getWalletVisibleTokens*(self: Service): Table[int, seq[string]] =
self.settings.walletVisibleTokens
method saveWalletVisibleTokens*(self: Service, tokens: seq[string]): bool =
method saveWalletVisibleTokens*(self: Service, visibleTokens: Table[int, seq[string]]): bool =
var obj = newJObject()
obj[self.getCurrentNetwork()] = %* tokens
for chainId, tokens in visibleTokens.pairs:
obj[$chainId] = %* tokens
if(self.saveSetting(KEY_WALLET_VISIBLE_TOKENS, obj)):
self.settings.walletVisibleTokens.tokens = tokens
self.settings.walletVisibleTokens = visibleTokens
return true
return false
method isEIP1559Enabled*(self: Service, blockNumber: int): bool =

View File

@ -221,10 +221,10 @@ method pinMailserver*(self: ServiceInterface, address: string, fleet: Fleet): bo
method unpinMailserver*(self: ServiceInterface, fleet: Fleet): bool {.base.} =
raise newException(ValueError, "No implementation available")
method getWalletVisibleTokens*(self: ServiceInterface): seq[string] {.base.} =
method getWalletVisibleTokens*(self: ServiceInterface): Table[int, seq[string]] {.base.} =
raise newException(ValueError, "No implementation available")
method saveWalletVisibleTokens*(self: ServiceInterface, tokens: seq[string]): bool {.base.} =
method saveWalletVisibleTokens*(self: ServiceInterface, tokens: Table[int, seq[string]]): bool {.base.} =
raise newException(ValueError, "No implementation available")
method isEIP1559Enabled*(self: ServiceInterface, blockNumber: int): bool {.base.} =

View File

@ -1,4 +1,4 @@
import NimQml, json, sequtils, chronicles, strformat, strutils
import NimQml, Tables, json, sequtils, chronicles, strformat, strutils
from sugar import `=>`
import web3/ethtypes
@ -7,6 +7,7 @@ import ../../../backend/custom_tokens as custom_tokens
import ../../../backend/tokens as token_backend
import ../settings/service_interface as settings_service
import ../network/service_interface as network_service
import ../../../app/core/eventemitter
import ../../../app/core/tasks/[qt, threadpool]
@ -19,6 +20,7 @@ logScope:
include async_tasks
const DEFAULT_VISIBLE_TOKENS = {1: @["SNT"], 3: @["STT"], 4: @["STT"]}.toTable()
# Signals which may be emitted by this service:
const SIGNAL_TOKEN_DETAILS_LOADED* = "tokenDetailsLoaded"
@ -43,7 +45,8 @@ QtObject:
events: EventEmitter
threadpool: ThreadPool
settingsService: settings_service.ServiceInterface
tokens: seq[TokenDto]
networkService: network_service.ServiceInterface
tokens: Table[NetworkDto, seq[TokenDto]]
proc delete*(self: Service) =
self.QObject.delete
@ -51,46 +54,38 @@ QtObject:
proc newService*(
events: EventEmitter,
threadpool: ThreadPool,
settingsService: settings_service.ServiceInterface
settingsService: settings_service.ServiceInterface,
networkService: network_service.ServiceInterface,
): Service =
new(result, delete)
result.QObject.setup
result.events = events
result.threadpool = threadpool
result.settingsService = settingsService
result.tokens = @[]
proc getDefaultVisibleSymbols(self: Service): seq[string] =
let networkSlug = self.settingsService.getCurrentNetwork()
if networkSlug == DEFAULT_CURRENT_NETWORK:
return @["SNT"]
if networkSlug == "testnet_rpc" or networkSlug == "rinkeby_rpc":
return @["STT"]
return @[]
result.networkService = networkService
result.tokens = initTable[NetworkDto, seq[TokenDto]]()
proc init*(self: Service) =
try:
var activeTokenSymbols = self.settingsService.getWalletVisibleTokens()
if activeTokenSymbols.len == 0:
activeTokenSymbols = self.getDefaultVisibleSymbols()
let networks = self.networkService.getEnabledNetworks()
let responseCustomTokens = custom_tokens.getCustomTokens()
let chainId = self.settingsService.getCurrentNetworkId()
let responseTokens = token_backend.getTokens(chainId)
for network in networks:
if not activeTokenSymbols.hasKey(network.chainId):
activeTokenSymbols[network.chainId] = DEFAULT_VISIBLE_TOKENS[network.chainId]
let responseTokens = token_backend.getTokens(network.chainId)
let default_tokens = map(
responseTokens.result.getElems(),
proc(x: JsonNode): TokenDto = x.toTokenDto(activeTokenSymbols, hasIcon=true, isCustom=false)
proc(x: JsonNode): TokenDto = x.toTokenDto(activeTokenSymbols[network.chainId], hasIcon=true, isCustom=false)
)
let responseCustomTokens = custom_tokens.getCustomTokens()
self.tokens = concat(
self.tokens[network] = concat(
default_tokens,
map(responseCustomTokens.result.getElems(), proc(x: JsonNode): TokenDto = x.toTokenDto(activeTokenSymbols))
map(responseCustomTokens.result.getElems(), proc(x: JsonNode): TokenDto = x.toTokenDto(activeTokenSymbols[network.chainId]))
).filter(
proc(x: TokenDto): bool = x.chainId == chainId
proc(x: TokenDto): bool = x.chainId == network.chainId
)
except Exception as e:
@ -98,46 +93,60 @@ QtObject:
error "error: ", errDesription
return
proc getTokens*(self: Service): seq[TokenDto] =
return self.tokens
proc getTokens*(self: Service, useCache: bool = true): seq[TokenDto] =
if not useCache:
self.init()
proc addCustomToken*(self: Service, address: string, name: string, symbol: string, decimals: int) =
custom_tokens.addCustomToken(address, name, symbol, decimals, "")
for tokens in self.tokens.values:
for token in tokens:
result.add(token)
proc addCustomToken*(self: Service, chainId: int, address: string, name: string, symbol: string, decimals: int) =
# TODO(alaile): use chainId rather than first enabled network
let networkWIP = self.networkService.getEnabledNetworks()[0]
custom_tokens.addCustomToken(networkWIP.chainId, address, name, symbol, decimals, "")
let token = newDto(
name,
self.settingsService.getCurrentNetworkId(),
networkWIP.chainId,
fromHex(Address, address),
symbol,
decimals,
false,
true
)
self.tokens.add(token)
let network = self.networkService.getNetwork(networkWIP.chainId)
self.tokens[network].add(token)
self.events.emit("token/customTokenAdded", CustomTokenAdded(token: token))
proc toggleVisible*(self: Service, symbol: string) =
var tokenChanged = self.tokens[0]
for token in self.tokens:
proc toggleVisible*(self: Service, chainId: int, symbol: string) =
let network = self.networkService.getNetwork(chainId)
var tokenChanged = self.tokens[network][0]
for token in self.tokens[network]:
if token.symbol == symbol:
token.isVisible = not token.isVisible
tokenChanged = token
break
let visibleSymbols = self.tokens.filter(t => t.isVisible).map(t => t.symbol)
var visibleSymbols = initTable[int, seq[string]]()
for network, tokens in self.tokens.pairs:
let symbols = tokens.filter(t => t.isVisible).map(t => t.symbol)
visibleSymbols[network.chainId] = symbols
discard self.settingsService.saveWalletVisibleTokens(visibleSymbols)
self.events.emit("token/visibilityToggled", VisibilityToggled(token: tokenChanged))
proc removeCustomToken*(self: Service, address: string) =
custom_tokens.removeCustomToken(address)
proc removeCustomToken*(self: Service, chainId: int, address: string) =
let network = self.networkService.getNetwork(chainId)
custom_tokens.removeCustomToken(chainId, address)
var index = -1
for idx, token in self.tokens.pairs():
for idx, token in self.tokens[network].pairs():
if $token.address == address:
index = idx
break
let tokenRemoved = self.tokens[index]
self.tokens.del(index)
let tokenRemoved = self.tokens[network][index]
self.tokens[network].del(index)
self.events.emit("token/customTokenRemoved", CustomTokenRemoved(token: tokenRemoved))
proc tokenDetailsResolved*(self: Service, tokenDetails: string) {.slot.} =
@ -145,8 +154,7 @@ QtObject:
tokenDetails: tokenDetails
))
proc getTokenDetails*(self: Service, address: string) =
let chainId = self.settingsService.getCurrentNetworkId()
proc getTokenDetails*(self: Service, chainId: int, address: string) =
let arg = GetTokenDetailsTaskArg(
tptr: cast[ByteAddress](getTokenDetailsTask),
vptr: cast[ByteAddress](self.vptr),

View File

@ -285,8 +285,8 @@ method updateCurrency*(self: Service, newCurrency: string) =
self.refreshBalances()
self.events.emit(SIGNAL_WALLET_ACCOUNT_CURRENCY_UPDATED, CurrencyUpdated())
method toggleTokenVisible*(self: Service, symbol: string) =
self.tokenService.toggleVisible(symbol)
method toggleTokenVisible*(self: Service, chainId: int, symbol: string) =
self.tokenService.toggleVisible(chainId, symbol)
self.refreshBalances()
self.events.emit(SIGNAL_WALLET_ACCOUNT_TOKEN_VISIBILITY_UPDATED, TokenVisibilityToggled())

View File

@ -45,7 +45,7 @@ method updateCurrency*(self: ServiceInterface, newCurrency: string) {.base.} =
method updateWalletAccount*(self: ServiceInterface, address: string, accountName: string, color: string) {.base.} =
raise newException(ValueError, "No implementation available")
method toggleTokenVisible*(self: ServiceInterface, symbol: string) {.base.} =
method toggleTokenVisible*(self: ServiceInterface, chainId: int, symbol: string) {.base.} =
raise newException(ValueError, "No implementation available")
method getPrice*(self: ServiceInterface, crypto: string, fiat: string): float64 {.base.} =

View File

@ -6,10 +6,12 @@ export response_type
proc getCustomTokens*(): RpcResponse[JsonNode] {.raises: [Exception].} =
return callPrivateRPC("wallet_getCustomTokens", %* [])
proc addCustomToken*(address: string, name: string, symbol: string, decimals: int, color: string) {.raises: [Exception].} =
proc addCustomToken*(
chainId: int, address: string, name: string, symbol: string, decimals: int, color: string
) {.raises: [Exception].} =
discard callPrivateRPC("wallet_addCustomToken", %* [
{"address": address, "name": name, "symbol": symbol, "decimals": decimals, "color": color}
{"chainId": chainId, "address": address, "name": name, "symbol": symbol, "decimals": decimals, "color": color}
])
proc removeCustomToken*(address: string) {.raises: [Exception].} =
discard callPrivateRPC("wallet_deleteCustomToken", %* [address])
proc removeCustomToken*(chainId: int, address: string) {.raises: [Exception].} =
discard callPrivateRPC("wallet_deleteCustomTokenByChainID", %* [chainId, address])

View File

@ -15,9 +15,9 @@ Item {
property var defaultTokenList
property var customTokenList
signal toggleVisibleClicked(string symbol)
signal removeCustomTokenTriggered(string address)
signal showTokenDetailsTriggered(string address, string name, string symbol, string decimals)
signal toggleVisibleClicked(int chainId, string symbol)
signal removeCustomTokenTriggered(int chainId, string address)
signal showTokenDetailsTriggered(int chainId, string address, string name, string symbol, string decimals)
SearchBox {
id: searchBox
@ -48,6 +48,13 @@ Item {
anchors.left: parent.left
anchors.leftMargin: Style.current.smallPadding
anchors.verticalCenter: parent.verticalCenter
onStatusChanged: {
if (assetInfoImage.status == Image.Error) {
assetInfoImage.source = Style.png("tokens/DEFAULT-TOKEN@3x")
}
}
}
StyledText {
id: assetSymbol
@ -73,7 +80,7 @@ Item {
checked: model.isVisible
anchors.right: parent.right
anchors.rightMargin: Style.current.smallPadding
onClicked: toggleVisibleClicked(symbol)
onClicked: toggleVisibleClicked(chainId, symbol)
anchors.verticalCenter: parent.verticalCenter
}
@ -87,7 +94,7 @@ Item {
return contextMenu.popup(assetSymbol.x - 100, assetSymbol.y + 25)
}
assetCheck.checked = !assetCheck.checked
toggleVisibleClicked(symbol)
toggleVisibleClicked(chainId, symbol)
}
onEntered: {
tokenContainer.hovered = true
@ -103,7 +110,7 @@ Item {
//% "Token details"
text: qsTrId("token-details")
onTriggered: {
modalBody.showTokenDetailsTriggered(address, name, symbol, decimals);
modalBody.showTokenDetailsTriggered(chainId, address, name, symbol, decimals);
}
}
Action {
@ -112,7 +119,7 @@ Item {
enabled: isCustom
//% "Remove token"
text: qsTrId("remove-token")
onTriggered: removeCustomTokenTriggered(address)
onTriggered: removeCustomTokenTriggered(chainId, address)
}
}
}

View File

@ -166,7 +166,8 @@ ModalPopup {
enabled: validationError === "" && addressInput.text !== "" && nameInput.text !== "" && symbolInput.text !== "" && decimalsInput.text !== ""
onClicked : {
const error = RootStore.addCustomToken(addressInput.text, nameInput.text, symbolInput.text, decimalsInput.text);
// TODO(alaibe): replace the placeholder 0 with the value of the chain selector
const error = RootStore.addCustomToken(0, addressInput.text, nameInput.text, symbolInput.text, decimalsInput.text);
if (error) {
Global.playErrorSound();

View File

@ -27,13 +27,13 @@ ModalPopup {
customTokenList: RootStore.customTokenList
onToggleVisibleClicked: {
RootStore.toggleVisible(symbol)
RootStore.toggleVisible(chainId, symbol)
}
onRemoveCustomTokenTriggered: {
RootStore.removeCustomToken(address)
RootStore.removeCustomToken(chainId, address)
}
onShowTokenDetailsTriggered: {
addShowTokenModal.openWithData(address, name, symbol, decimals);
addShowTokenModal.openWithData(chainId, address, name, symbol, decimals);
}
AddShowTokenModal{

View File

@ -121,16 +121,16 @@ QtObject {
walletSection.updateCurrency(newCurrency)
}
function addCustomToken(address, name, symbol, decimals) {
return walletSectionAllTokens.addCustomToken(address, name, symbol, decimals)
function addCustomToken(chainId, address, name, symbol, decimals) {
return walletSectionAllTokens.addCustomToken(chainId, address, name, symbol, decimals)
}
function toggleVisible(symbol) {
walletSectionAllTokens.toggleVisible(symbol)
function toggleVisible(chainId, symbol) {
walletSectionAllTokens.toggleVisible(chainId, symbol)
}
function removeCustomToken(address) {
walletSectionAllTokens.removeCustomToken(address)
function removeCustomToken(chainId, address) {
walletSectionAllTokens.removeCustomToken(chainId, address)
}
function getQrCode(address) {