feat(@wallet): toggle network

This commit is contained in:
Anthony Laibe 2022-02-17 10:15:37 +01:00 committed by Anthony Laibe
parent fc24f16525
commit 92bc1fdab1
34 changed files with 268 additions and 191 deletions

View File

@ -128,7 +128,7 @@ 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.settingsService)
result.networkService = network_service.newService(statusFoundation.events, result.settingsService)
result.contactsService = contacts_service.newService(
statusFoundation.events, statusFoundation.threadpool, result.settingsService
)
@ -304,10 +304,8 @@ proc load(self: AppController) =
self.tokenService.init()
self.dappPermissionsService.init()
self.providerService.init()
self.walletAccountService.init()
self.transactionService.init()
self.stickersService.init()
self.networkService.init()
self.activityCenterService.init()
self.savedAddressService.init()
self.aboutService.init()
@ -321,6 +319,9 @@ proc load(self: AppController) =
singletonInstance.engine.setRootContextProperty("localAccountSensitiveSettings", self.localAccountSensitiveSettingsVariant)
singletonInstance.engine.setRootContextProperty("globalUtils", self.globalUtilsVariant)
self.networkService.init()
self.walletAccountService.init()
# other global instances
self.buildAndRegisterLocalAccountSensitiveSettings()
self.buildAndRegisterUserProfile()

View File

@ -14,7 +14,7 @@ include ./private_interfaces/module_app_search_delegate_interface
include ./private_interfaces/module_browser_section_delegate_interface
include ./private_interfaces/module_communities_section_delegate_interface
include ./private_interfaces/module_node_section_delegate_interface
include ./private_interfaces/module_networks_delegate_interface
# This way (using concepts) is used only for the modules managed by AppController
type

View File

@ -19,6 +19,7 @@ import stickers/module as stickers_module
import activity_center/module as activity_center_module
import communities/module as communities_module
import node_section/module as node_section_module
import networks/module as networks_module
import ../../../app_service/service/keychain/service as keychain_service
import ../../../app_service/service/chat/service as chat_service
@ -70,6 +71,7 @@ type
communitiesModule: communities_module.AccessInterface
appSearchModule: app_search_module.AccessInterface
nodeSectionModule: node_section_module.AccessInterface
networksModule: networks_module.AccessInterface
moduleLoaded: bool
# Forward declaration
@ -141,7 +143,7 @@ proc newModule*[T](
result.profileSectionModule = profile_section_module.newModule(
result, events, accountsService, settingsService,
profileService, contactsService, aboutService, languageService, privacyService, nodeConfigurationService,
devicesService, mailserversService, chatService, ensService, walletAccountService, networkService,
devicesService, mailserversService, chatService, ensService, walletAccountService,
)
result.stickersModule = stickers_module.newModule(result, events, stickersService)
result.activityCenterModule = activity_center_module.newModule(result, events, activityCenterService, contactsService,
@ -150,6 +152,7 @@ proc newModule*[T](
result.appSearchModule = app_search_module.newModule(result, events, contactsService, chatService, communityService,
messageService)
result.nodeSectionModule = node_section_module.newModule(result, events, settingsService, nodeService, nodeConfigurationService)
result.networksModule = networks_module.newModule(result, events, networkService, walletAccountService)
method delete*[T](self: Module[T]) =
self.chatSectionModule.delete
@ -164,6 +167,7 @@ method delete*[T](self: Module[T]) =
self.browserSectionModule.delete
self.appSearchModule.delete
self.nodeSectionModule.delete
self.networksModule.delete
self.view.delete
self.viewVariant.delete
self.controller.delete
@ -342,10 +346,12 @@ method load*[T](
self.chatSectionModule.load(events, settingsService, contactsService, chatService, communityService, messageService, gifService, mailserversService)
for cModule in self.communitySectionsModule.values:
cModule.load(events, settingsService, contactsService, chatService, communityService, messageService, gifService, mailserversService)
self.browserSectionModule.load()
# self.nodeManagementSectionModule.load()
self.profileSectionModule.load()
self.stickersModule.load()
self.networksModule.load()
self.activityCenterModule.load()
self.communitiesModule.load()
self.appSearchModule.load()
@ -391,6 +397,9 @@ proc checkIfModuleDidLoad [T](self: Module[T]) =
if(not self.appSearchModule.isLoaded()):
return
if(not self.networksModule.isLoaded()):
return
self.moduleLoaded = true
self.delegate.mainDidLoad()
@ -424,6 +433,9 @@ proc profileSectionDidLoad*[T](self: Module[T]) =
method nodeSectionDidLoad*[T](self: Module[T]) =
self.checkIfModuleDidLoad()
method networksModuleDidLoad*[T](self: Module[T]) =
self.checkIfModuleDidLoad()
method viewDidLoad*[T](self: Module[T]) =
self.checkIfModuleDidLoad()

View File

@ -0,0 +1,39 @@
import ./controller_interface
import ../../../core/eventemitter
import ../../../../app_service/service/network/service as network_service
import ../../../../app_service/service/wallet_account/service as wallet_account_service
import ./io_interface
export controller_interface
type
Controller* = ref object of controller_interface.AccessInterface
delegate: io_interface.AccessInterface
events: EventEmitter
networkService: network_service.Service
walletAccountService: wallet_account_service.Service
proc newController*(
delegate: io_interface.AccessInterface,
events: EventEmitter,
networkService: network_service.Service,
walletAccountService: wallet_account_service.Service,
): Controller =
result = Controller()
result.delegate = delegate
result.events = events
result.networkService = networkService
result.walletAccountService = walletAccountService
method delete*(self: Controller) =
discard
method init*(self: Controller) =
self.events.on(SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED) do(e: Args):
self.delegate.refreshNetworks()
method getNetworks*(self: Controller): seq[NetworkDto] =
return self.networkService.getNetworks()
method toggleNetwork*(self: Controller, chainId: int) =
self.walletAccountService.toggleNetworkEnabled(chainId)

View File

@ -1,4 +1,4 @@
import ../../../../../../app_service/service/network/dto
import ../../../../app_service/service/network/dto
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
@ -11,4 +11,7 @@ method init*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method getNetworks*(self: AccessInterface): seq[NetworkDto] {.base.} =
raise newException(ValueError, "No implementation available")
method toggleNetwork*(self: AccessInterface, chainId: int) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -19,6 +19,11 @@ method isLoaded*(self: AccessInterface): bool {.base.} =
method viewDidLoad*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method toggleNetwork*(self: AccessInterface, chainId: int) {.base.} =
raise newException(ValueError, "No implementation available")
method refreshNetworks*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
type
## Abstract class (concept) which must be implemented by object/s used in this

View File

@ -11,6 +11,7 @@ type
nativeCurrencyName: string
nativeCurrencySymbol: string
isTest: bool
isEnabled: bool
proc initItem*(
chainId: int,
@ -21,7 +22,8 @@ proc initItem*(
blockExplorerURL: string,
nativeCurrencyName: string,
nativeCurrencySymbol: string,
isTest: bool
isTest: bool,
isEnabled: bool,
): Item =
result.chainId = chainId
result.nativeCurrencyDecimals = nativeCurrencyDecimals
@ -32,6 +34,7 @@ proc initItem*(
result.nativeCurrencyName = nativeCurrencyName
result.nativeCurrencySymbol = nativeCurrencySymbol
result.isTest = isTest
result.isEnabled = isEnabled
proc `$`*(self: Item): string =
result = fmt"""NetworkItem(
@ -44,6 +47,7 @@ proc `$`*(self: Item): string =
nativeCurrencyName:{self.nativeCurrencyName},
nativeCurrencySymbol:{self.nativeCurrencySymbol},
isTest:{self.isTest}
isEnabled:{self.isEnabled}
]"""
proc getChainId*(self: Item): int =
@ -71,4 +75,7 @@ proc getNativeCurrencySymbol*(self: Item): string =
return self.nativeCurrencySymbol
proc getIsTest*(self: Item): bool =
return self.isTest
return self.isTest
proc getIsEnabled*(self: Item): bool =
return self.isEnabled

View File

@ -13,6 +13,7 @@ type
NativeCurrencyName
NativeCurrencySymbol
IsTest
IsEnabled
QtObject:
type
@ -57,6 +58,7 @@ QtObject:
ModelRole.NativeCurrencyName.int:"nativeCurrencyName",
ModelRole.NativeCurrencySymbol.int:"nativeCurrencySymbol",
ModelRole.IsTest.int:"isTest",
ModelRole.IsEnabled.int:"isEnabled",
}.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant =
@ -88,6 +90,8 @@ QtObject:
result = newQVariant(item.getNativeCurrencySymbol())
of ModelRole.IsTest:
result = newQVariant(item.getIsTest())
of ModelRole.IsEnabled:
result = newQVariant(item.getIsEnabled())
proc setItems*(self: Model, items: seq[Item]) =
self.beginResetModel()

View File

@ -1,9 +1,10 @@
import NimQml
import ../io_interface as delegate_interface
import io_interface, view, controller
import ../../../../../global/global_singleton
import ../../../../../core/eventemitter
import ../../../../../../app_service/service/network/service as network_service
import ../../../global/global_singleton
import ../../../core/eventemitter
import ../../../../app_service/service/network/service as network_service
import ../../../../app_service/service/wallet_account/service as wallet_account_service
export io_interface
@ -19,25 +20,30 @@ proc newModule*(
delegate: delegate_interface.AccessInterface,
events: EventEmitter,
networkService: networkService.Service,
walletAccountService: wallet_account_service.Service,
): Module =
result = Module()
result.delegate = delegate
result.view = view.newView(result)
result.viewVariant = newQVariant(result.view)
result.controller = controller.newController(result, events, networkService)
result.controller = controller.newController(result, events, networkService, walletAccountService)
result.moduleLoaded = false
singletonInstance.engine.setRootContextProperty("profileSectionWalletNetworkModule", result.viewVariant)
singletonInstance.engine.setRootContextProperty("networksModule", result.viewVariant)
method delete*(self: Module) =
self.view.delete
self.viewVariant.delete
self.controller.delete
method load*(self: Module) =
method refreshNetworks*(self: Module) =
let networks = self.controller.getNetworks()
self.view.load(networks)
method load*(self: Module) =
self.controller.init()
self.refreshNetworks()
method isLoaded*(self: Module): bool =
return self.moduleLoaded
@ -46,4 +52,7 @@ proc checkIfModuleDidLoad(self: Module) =
self.delegate.networksModuleDidLoad()
method viewDidLoad*(self: Module) =
self.checkIfModuleDidLoad()
self.checkIfModuleDidLoad()
method toggleNetwork*(self: Module, chainId: int) =
self.controller.toggleNetwork(chainId)

View File

@ -1,6 +1,6 @@
import NimQml, sequtils, sugar
import ../../../../../../app_service/service/network/dto
import ../../../../app_service/service/network/dto
import ./io_interface
import ./model
import ./item
@ -9,6 +9,7 @@ QtObject:
type
View* = ref object of QObject
delegate: io_interface.AccessInterface
enabled: Model
layer1: Model
layer2: Model
test: Model
@ -25,6 +26,7 @@ QtObject:
result.layer1 = newModel()
result.layer2 = newModel()
result.test = newModel()
result.enabled = newModel()
result.setup()
proc layer1Changed*(self: View) {.signal.}
@ -54,6 +56,15 @@ QtObject:
read = getTest
notify = testChanged
proc enabledChanged*(self: View) {.signal.}
proc getEnabled(self: View): QVariant {.slot.} =
return newQVariant(self.enabled)
QtProperty[QVariant] enabled:
read = getEnabled
notify = enabledChanged
proc load*(self: View, networks: seq[NetworkDto]) =
let items = networks.map(n => initItem(
n.chainId,
@ -64,10 +75,19 @@ QtObject:
n.blockExplorerURL,
n.nativeCurrencyName,
n.nativeCurrencySymbol,
n.isTest
n.isTest,
n.enabled,
))
self.layer1.setItems(items.filter(i => i.getLayer() == 1 and not i.getIsTest()))
self.layer2.setItems(items.filter(i => i.getLayer() == 2 and not i.getIsTest()))
self.test.setItems(items.filter(i => i.getIsTest()))
self.enabled.setItems(items.filter(i => i.getIsEnabled()))
self.delegate.viewDidLoad()
self.layer1Changed()
self.layer2Changed()
self.testChanged()
self.delegate.viewDidLoad()
proc toggleNetwork*(self: View, chainId: int) {.slot.} =
self.delegate.toggleNetwork(chainId)

View File

@ -0,0 +1,2 @@
method networksModuleDidLoad*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -80,9 +80,6 @@ method ensUsernamesModuleDidLoad*(self: AccessInterface) {.base.} =
method getEnsUsernamesModule*(self: AccessInterface): QVariant {.base.} =
raise newException(ValueError, "No implementation available")
method walletModuleDidLoad*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
type
## Abstract class (concept) which must be implemented by object/s used in this
## module.

View File

@ -15,7 +15,6 @@ import ../../../../app_service/service/mailservers/service as mailservers_servic
import ../../../../app_service/service/chat/service as chat_service
import ../../../../app_service/service/ens/service as ens_service
import ../../../../app_service/service/wallet_account/service_interface as wallet_account_service
import ../../../../app_service/service/network/service as network_service
import ./profile/module as profile_module
import ./contacts/module as contacts_module
@ -27,7 +26,6 @@ import ./devices/module as devices_module
import ./sync/module as sync_module
import ./notifications/module as notifications_module
import ./ens_usernames/module as ens_usernames_module
import ./wallet/module as wallet_module
export io_interface
@ -49,7 +47,6 @@ type
syncModule: sync_module.AccessInterface
notificationsModule: notifications_module.AccessInterface
ensUsernamesModule: ens_usernames_module.AccessInterface
walletModule: wallet_module.AccessInterface
proc newModule*[T](delegate: T,
events: EventEmitter,
@ -66,7 +63,6 @@ proc newModule*[T](delegate: T,
chatService: chat_service.Service,
ensService: ens_service.Service,
walletAccountService: wallet_account_service.ServiceInterface,
networkService: network_service.Service,
): Module[T] =
result = Module[T]()
result.delegate = delegate
@ -87,7 +83,6 @@ proc newModule*[T](delegate: T,
result.ensUsernamesModule = ens_usernames_module.newModule(
result, events, settingsService, ensService, walletAccountService
)
result.walletModule = wallet_module.newModule(result, events, networkService)
singletonInstance.engine.setRootContextProperty("profileSectionModule", result.viewVariant)
@ -100,7 +95,6 @@ method delete*[T](self: Module[T]) =
self.advancedModule.delete
self.devicesModule.delete
self.syncModule.delete
self.walletModule.delete
self.view.delete
self.viewVariant.delete
@ -118,7 +112,6 @@ method load*[T](self: Module[T]) =
self.syncModule.load()
self.notificationsModule.load()
self.ensUsernamesModule.load()
self.walletModule.load()
method isLoaded*[T](self: Module[T]): bool =
return self.moduleLoaded
@ -154,9 +147,6 @@ proc checkIfModuleDidLoad[T](self: Module[T]) =
if(not self.ensUsernamesModule.isLoaded()):
return
if(not self.walletModule.isLoaded()):
return
self.moduleLoaded = true
self.delegate.profileSectionDidLoad()
@ -169,9 +159,6 @@ method profileModuleDidLoad*[T](self: Module[T]) =
method getProfileModule*[T](self: Module[T]): QVariant =
self.profileModule.getModuleAsVariant()
method walletModuleDidLoad*[T](self: Module[T]) =
self.checkIfModuleDidLoad()
method contactsModuleDidLoad*[T](self: Module[T]) =
self.checkIfModuleDidLoad()

View File

@ -1,3 +0,0 @@
# Defines how parent module accesses this module
include ./private_interfaces/module_base_interface
include ./private_interfaces/module_access_interface

View File

@ -1,48 +0,0 @@
import NimQml
import ./io_interface
import ../../../../global/global_singleton
import ../../../../core/eventemitter
import ../../../../../app_service/service/network/service as network_service
import ../io_interface as delegate_interface
import ./networks/module as networks_module
export io_interface
type
Module* = ref object of io_interface.AccessInterface
delegate: delegate_interface.AccessInterface
moduleLoaded: bool
networksModule: networks_module.AccessInterface
proc newModule*(
delegate: delegate_interface.AccessInterface,
events: EventEmitter,
networkService: network_service.Service,
): Module =
result = Module()
result.delegate = delegate
result.moduleLoaded = false
result.networksModule = networks_module.newModule(result, events, networkService)
method delete*(self: Module) =
self.networksModule.delete
method load*(self: Module) =
self.networksModule.load()
method isLoaded*(self: Module): bool =
return self.moduleLoaded
proc checkIfModuleDidLoad(self: Module) =
if(not self.networksModule.isLoaded()):
return
self.moduleLoaded = true
self.delegate.walletModuleDidLoad()
method networksModuleDidLoad*(self: Module) =
self.checkIfModuleDidLoad()

View File

@ -1,31 +0,0 @@
import ./controller_interface
import ../../../../../core/eventemitter
import ../../../../../../app_service/service/network/service as network_service
import ./io_interface
export controller_interface
type
Controller* = ref object of controller_interface.AccessInterface
delegate: io_interface.AccessInterface
events: EventEmitter
networkService: network_service.Service
proc newController*(
delegate: io_interface.AccessInterface,
events: EventEmitter,
networkService: network_service.Service
): Controller =
result = Controller()
result.delegate = delegate
result.events = events
result.networkService = networkService
method delete*(self: Controller) =
discard
method init*(self: Controller) =
discard
method getNetworks*(self: Controller): seq[NetworkDto] =
return self.networkService.getNetworks()

View File

@ -1,13 +0,0 @@
import NimQml
method delete*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method load*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method isLoaded*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")
method networksModuleDidLoad*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -1,5 +0,0 @@
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
# Since nim doesn't support using concepts in second level nested types we
# define delegate interfaces within access interface.

View File

@ -55,6 +55,9 @@ method load*(self: Module) =
self.events.on(SIGNAL_WALLET_ACCOUNT_TOKEN_VISIBILITY_UPDATED) do(e:Args):
self.switchAccount(self.currentAccountIndex)
self.events.on(SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED) do(e:Args):
self.switchAccount(self.currentAccountIndex)
self.controller.init()
self.view.load()

View File

@ -85,6 +85,9 @@ method load*(self: Module) =
self.events.on(SIGNAL_WALLET_ACCOUNT_TOKEN_VISIBILITY_UPDATED) do(e:Args):
self.refreshWalletAccounts()
self.events.on(SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED) do(e:Args):
self.refreshWalletAccounts()
self.controller.init()
self.view.load()

View File

@ -34,6 +34,9 @@ method init*(self: Controller) =
self.events.on(SIGNAL_TOKEN_DETAILS_LOADED) do(e:Args):
let args = TokenDetailsLoadedArgs(e)
self.delegate.tokenDetailsWereResolved(args.tokenDetails)
self.events.on(SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED) do(e:Args):
self.delegate.refreshTokens()
method getTokens*(self: Controller): seq[token_service.TokenDto] =
for tokens in self.tokenService.getTokens().values:

View File

@ -47,6 +47,9 @@ method load*(self: Module) =
self.events.on(SIGNAL_WALLET_ACCOUNT_TOKEN_VISIBILITY_UPDATED) do(e:Args):
self.switchAccount(self.currentAccountIndex)
self.events.on(SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED) do(e: Args):
self.switchAccount(self.currentAccountIndex)
self.controller.init()
self.view.load()
@ -63,4 +66,4 @@ method switchAccount*(self: Module, accountIndex: int) =
self.view.setData(walletAccount)
method update*(self: Module, address: string, accountName: string, color: string) =
self.controller.update(address, accountName, color)
self.controller.update(address, accountName, color)

View File

@ -98,6 +98,8 @@ method load*[T](self: Module[T]) =
self.setTotalCurrencyBalance()
self.events.on(SIGNAL_WALLET_ACCOUNT_TOKEN_VISIBILITY_UPDATED) do(e:Args):
self.setTotalCurrencyBalance()
self.events.on(SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED) do(e:Args):
self.setTotalCurrencyBalance()
self.controller.init()
self.view.load()

View File

@ -238,7 +238,7 @@ var NODE_CONFIG* = %* {
{
"chainId": 10,
"chainName": "Optimistic Ethereum",
"rpcUrl": "https://mainnet.infura.io/v3/" & INFURA_TOKEN_RESOLVED,
"rpcUrl": "https://optimism-mainnet.infura.io/v3/" & INFURA_TOKEN_RESOLVED,
"blockExplorerUrl": "https://optimistic.etherscan.io",
"iconUrl": "",
"nativeCurrencyName": "Ether",

View File

@ -1,7 +1,6 @@
import json, json_serialization, chronicles, atomics
import options
import ../../../app/core/eventemitter
import ../../../app/global/global_singleton
import ../../../backend/network as status_network
import ../settings/service as settings_service
@ -15,6 +14,7 @@ logScope:
type
Service* = ref object of network_interface.ServiceInterface
events: EventEmitter
networks: seq[NetworkDto]
networksInited: bool
dirty: Atomic[bool]
@ -24,8 +24,9 @@ type
method delete*(self: Service) =
discard
proc newService*(settingsService: settings_service.Service): Service =
proc newService*(events: EventEmitter, settingsService: settings_service.Service): Service =
result = Service()
result.events = events
result.settingsService = settingsService
method init*(self: Service) =
@ -78,3 +79,9 @@ method getNetwork*(self: Service, networkType: NetworkType): NetworkDto =
# Will be removed, this is used in case of legacy chain Id
return NetworkDto(chainId: networkType.toChainId())
method toggleNetwork*(self: Service, chainId: int) =
let network = self.getNetwork(chainId)
network.enabled = not network.enabled
self.upsertNetwork(network)

View File

@ -29,3 +29,6 @@ method getNetwork*(self: ServiceInterface, networkType: NetworkType): NetworkDto
method getNetwork*(self: ServiceInterface, chainId: int): NetworkDto {.base.} =
raise newException(ValueError, "No implementation available")
method toggleNetwork*(self: ServiceInterface, chainId: int) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -23,6 +23,7 @@ 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"
const SIGNAL_TOKEN_LIST_RELOADED* = "tokenListReloaded"
type
TokenDetailsLoadedArgs* = ref object of Args
@ -67,13 +68,16 @@ QtObject:
proc init*(self: Service) =
try:
self.tokens = initTable[NetworkDto, seq[TokenDto]]()
var activeTokenSymbols = self.settingsService.getWalletVisibleTokens()
let networks = self.networkService.getEnabledNetworks()
let responseCustomTokens = custom_tokens.getCustomTokens()
for network in networks:
if not activeTokenSymbols.hasKey(network.chainId):
if not activeTokenSymbols.hasKey(network.chainId) and DEFAULT_VISIBLE_TOKENS.hasKey(network.chainId):
activeTokenSymbols[network.chainId] = DEFAULT_VISIBLE_TOKENS[network.chainId]
else:
activeTokenSymbols[network.chainId] = @[]
let responseTokens = token_backend.getTokens(network.chainId)
let default_tokens = map(
@ -93,10 +97,7 @@ QtObject:
error "error: ", errDesription
return
proc getTokens*(self: Service, useCache: bool = true): Table[NetworkDto, seq[TokenDto]] =
if not useCache:
self.init()
proc getTokens*(self: Service): Table[NetworkDto, seq[TokenDto]] =
return self.tokens
proc getVisibleTokens*(self: Service): seq[TokenDto] =

View File

@ -25,6 +25,7 @@ const SIGNAL_WALLET_ACCOUNT_DELETED* = "walletAccount/accountDeleted"
const SIGNAL_WALLET_ACCOUNT_CURRENCY_UPDATED* = "walletAccount/currencyUpdated"
const SIGNAL_WALLET_ACCOUNT_TOKEN_VISIBILITY_UPDATED* = "walletAccount/tokenVisibilityUpdated"
const SIGNAL_WALLET_ACCOUNT_UPDATED* = "walletAccount/walletAccountUpdated"
const SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED* = "walletAccount/networkEnabledUpdated"
var
priceCache {.threadvar.}: Table[string, float64]
@ -76,13 +77,17 @@ proc fetchAccounts(): seq[WalletAccountDto] =
).filter(a => not a.isChat)
proc fetchNativeChainBalance(network: NetworkDto, accountAddress: string): float64 =
let key = "0x0" & accountAddress
let key = "0x0" & accountAddress & $network.chainId
if balanceCache.hasKey(key):
return balanceCache[key]
let nativeBalanceResponse = status_go_eth.getNativeChainBalance(network.chainId, accountAddress)
result = parsefloat(hex2Balance(nativeBalanceResponse.result.getStr, network.nativeCurrencyDecimals))
balanceCache[key] = result
try:
let nativeBalanceResponse = status_go_eth.getNativeChainBalance(network.chainId, accountAddress)
result = parsefloat(hex2Balance(nativeBalanceResponse.result.getStr, network.nativeCurrencyDecimals))
balanceCache[key] = result
except Exception as e:
error "Error getting balance", message = e.msg
result = 0.0
type AccountSaved = ref object of Args
account: WalletAccountDto
@ -94,6 +99,8 @@ type CurrencyUpdated = ref object of Args
type TokenVisibilityToggled = ref object of Args
type NetwordkEnabledToggled = ref object of Args
type WalletAccountUpdated = ref object of Args
account: WalletAccountDto
@ -297,6 +304,12 @@ method toggleTokenVisible*(self: Service, chainId: int, symbol: string) =
self.refreshBalances()
self.events.emit(SIGNAL_WALLET_ACCOUNT_TOKEN_VISIBILITY_UPDATED, TokenVisibilityToggled())
method toggleNetworkEnabled*(self: Service, chainId: int) =
self.networkService.toggleNetwork(chainId)
self.tokenService.init()
self.refreshBalances()
self.events.emit(SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED, NetwordkEnabledToggled())
method updateWalletAccount*(self: Service, address: string, accountName: string, color: string) =
let account = self.accounts[address]
status_go_accounts.updateAccount(

View File

@ -11,16 +11,12 @@ proc callRPC*(inputJSON: string): string =
return $status_go.callRPC(inputJSON)
proc callPrivateRPCRaw*(inputJSON: string): string {.raises: [].} =
result = $status_go.callPrivateRPC(inputJSON)
result = $status_go.callPrivateRPC(inputJSON)
proc callPrivateRPC*(methodName: string, payload = %* []): RpcResponse[JsonNode]
{.raises: [RpcException, ValueError, Defect, SerializationError].} =
proc makePrivateRpcCall*(
methodName: string, inputJSON: JsonNode
): RpcResponse[JsonNode] {.raises: [RpcException, ValueError, Defect, SerializationError].} =
try:
let inputJSON = %* {
"jsonrpc": "2.0",
"method": methodName,
"params": %payload
}
debug "NewBE_callPrivateRPC", rpc_method=methodName
let rpcResponseRaw = status_go.callPrivateRPC($inputJSON)
result = Json.decode(rpcResponseRaw, RpcResponse[JsonNode])
@ -38,6 +34,27 @@ proc callPrivateRPC*(methodName: string, payload = %* []): RpcResponse[JsonNode]
error "error doing rpc request", methodName = methodName, exception=e.msg
raise newException(RpcException, e.msg)
proc callPrivateRPCWithChainId*(
methodName: string, chainId: int, payload = %* []
): RpcResponse[JsonNode] {.raises: [RpcException, ValueError, Defect, SerializationError].} =
let inputJSON = %* {
"jsonrpc": "2.0",
"method": methodName,
"chainId": chainId,
"params": %payload
}
return makePrivateRpcCall(methodName, inputJSON)
proc callPrivateRPC*(
methodName: string, payload = %* []
): RpcResponse[JsonNode] {.raises: [RpcException, ValueError, Defect, SerializationError].} =
let inputJSON = %* {
"jsonrpc": "2.0",
"method": methodName,
"params": %payload
}
return makePrivateRpcCall(methodName, inputJSON)
proc signMessage*(rpcParams: string): string =
return $status_go.signMessage(rpcParams)

View File

@ -12,7 +12,7 @@ proc getBlockByNumber*(blockNumber: string): RpcResponse[JsonNode] {.raises: [Ex
proc getNativeChainBalance*(chainId: int, address: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [address, "latest"]
return core.callPrivateRPC("eth_getBalance", payload)
return core.callPrivateRPCWithChainId("eth_getBalance", chainId, payload)
proc sendTransaction*(transactionData: string, password: string): RpcResponse[JsonNode] {.raises: [Exception].} =
core.sendTransaction(transactionData, password)

View File

@ -3,7 +3,7 @@ import QtQuick 2.13
QtObject {
id: root
property var layer1Networks: profileSectionWalletNetworkModule.layer1
property var layer2Networks: profileSectionWalletNetworkModule.layer2
property var testNetworks: profileSectionWalletNetworkModule.test
property var layer1Networks: networksModule.layer1
property var layer2Networks: networksModule.layer2
property var testNetworks: networksModule.test
}

View File

@ -9,7 +9,6 @@ Item {
id: root
width: selectRectangle.width
height: childrenRect.height
signal toggleNetwork(int chainId)
property var store
@ -23,7 +22,7 @@ Item {
StyledText {
id: text
text: qsTr("All networks")
text: qsTr("Select networks")
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
anchors.verticalCenter: parent.verticalCenter
@ -56,10 +55,13 @@ Item {
Grid {
id: enabledNetworks
columns: 2
columns: 4
spacing: 2
visible: (chainRepeater.count > 0)
anchors.top: selectRectangle.bottom
anchors.topMargin: Style.current.padding
Repeater {
id: chainRepeater
model: store.enabledNetworks
@ -87,8 +89,10 @@ Item {
NetworkSelectPopup {
id: selectPopup
x: (parent.width - width)
y: (root.height - networkFilterPanel.height)
model: store.allNetworks
layer1Networks: store.layer1Networks
layer2Networks: store.layer2Networks
testNetworks: store.testNetworks
onToggleNetwork: {
store.toggleNetwork(chainId)
}

View File

@ -16,8 +16,11 @@ Popup {
modal: false
width: 360
height: 432
closePolicy: Popup.CloseOnEscape
property var model
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
property var layer1Networks
property var layer2Networks
property var testNetworks
signal toggleNetwork(int chainId)
background: Rectangle {
@ -49,32 +52,51 @@ Popup {
width: popup.width
spacing: Style.current.padding
Repeater {
id: chainRepeater
model: popup.model
Repeater {
id: chainRepeater1
model: popup.layer1Networks
Item {
width: content.width
height: 40
StatusBaseText {
anchors.left: parent.left
anchors.leftMargin: Style.current.bigPadding
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: Style.current.primaryTextFontSize
text: model.chainName
color: Theme.palette.directColor1
}
delegate: chainItem
}
StatusCheckBox {
anchors.right: parent.right
anchors.rightMargin: Style.current.bigPadding
anchors.verticalCenter: parent.verticalCenter
checked: model.enabled
onCheckedChanged: {
if(checked !== model.enabled){
popup.toggleNetwork(model.chainId)
}
}
Repeater {
id: chainRepeater2
model: popup.layer2Networks
delegate: chainItem
}
Repeater {
id: chainRepeater3
model: popup.testNetworks
delegate: chainItem
}
}
}
Component {
id: chainItem
Item {
width: content.width
height: 40
StatusBaseText {
anchors.left: parent.left
anchors.leftMargin: Style.current.bigPadding
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: Style.current.primaryTextFontSize
text: model.chainName
color: Theme.palette.directColor1
}
StatusCheckBox {
anchors.right: parent.right
anchors.rightMargin: Style.current.bigPadding
anchors.verticalCenter: parent.verticalCenter
checked: model.isEnabled
onCheckedChanged: {
if (model.isEnabled !== checked) {
popup.toggleNetwork(model.chainId)
}
}
}

View File

@ -33,6 +33,12 @@ QtObject {
property var savedAddresses: walletSectionSavedAddresses.model
property var layer1Networks: networksModule.layer1
property var layer2Networks: networksModule.layer2
property var testNetworks: networksModule.test
property var enabledNetworks: networksModule.enabled
// This should be exposed to the UI via "walletModule", WalletModule should use
// Accounts Service which keeps the info about that (isFirstTimeAccountLogin).
// Then in the View of WalletModule we may have either QtProperty or
@ -184,4 +190,8 @@ QtObject {
function deleteSavedAddress(address) {
walletSectionSavedAddresses.deleteSavedAddress(address)
}
function toggleNetwork(chainId) {
networksModule.toggleNetwork(chainId)
}
}