feat: prepare token service for multichain
This commit is contained in:
parent
036d8491fb
commit
7268ec3773
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.} =
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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]
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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.} =
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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())
|
||||
|
||||
|
|
|
@ -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.} =
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue