diff --git a/src/app/boot/app_controller.nim b/src/app/boot/app_controller.nim index ae7cca56fa..0a27aea1dc 100644 --- a/src/app/boot/app_controller.nim +++ b/src/app/boot/app_controller.nim @@ -143,9 +143,11 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController = 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) - result.transactionService = transaction_service.newService(statusFoundation.events, statusFoundation.threadpool, + result.walletAccountService = wallet_account_service.newService( + statusFoundation.events, result.settingsService, result.accountsService, result.tokenService, + result.networkService, + ) + result.transactionService = transaction_service.newService(statusFoundation.events, statusFoundation.threadpool, result.walletAccountService, result.ethService, result.networkService, result.settingsService) result.bookmarkService = bookmark_service.newService() result.profileService = profile_service.newService() diff --git a/src/app/modules/main/wallet_section/all_tokens/controller.nim b/src/app/modules/main/wallet_section/all_tokens/controller.nim index ab66c74d67..0079b28b9e 100644 --- a/src/app/modules/main/wallet_section/all_tokens/controller.nim +++ b/src/app/modules/main/wallet_section/all_tokens/controller.nim @@ -1,3 +1,4 @@ +import tables import ./controller_interface import ./io_interface @@ -35,7 +36,9 @@ method init*(self: Controller) = self.delegate.tokenDetailsWereResolved(args.tokenDetails) method getTokens*(self: Controller): seq[token_service.TokenDto] = - return self.tokenService.getTokens() + for tokens in self.tokenService.getTokens().values: + for token in tokens: + result.add(token) method addCustomToken*(self: Controller, chainId: int, address: string, name: string, symbol: string, decimals: int) = self.tokenService.addCustomToken(chainId, address, name, symbol, decimals) diff --git a/src/app_service/common/network_constants.nim b/src/app_service/common/network_constants.nim index eeee3277fe..810d23edee 100644 --- a/src/app_service/common/network_constants.nim +++ b/src/app_service/common/network_constants.nim @@ -185,7 +185,7 @@ var NODE_CONFIG* = %* { }, { "chainId": 3, - "chainName": "Ropsten", + "chainName": "Ethereum Ropsten", "rpcUrl": "https://ropsten.infura.io/v3/" & INFURA_TOKEN_RESOLVED, "blockExplorerUrl": "https://ropsten.etherscan.io/", "iconUrl": "", @@ -198,7 +198,7 @@ var NODE_CONFIG* = %* { }, { "chainId": 4, - "chainName": "Rinkeby", + "chainName": "Ethereum Rinkeby", "rpcUrl": "https://rinkeby.infura.io/v3/" & INFURA_TOKEN_RESOLVED, "blockExplorerUrl": "https://rinkeby.etherscan.io/", "iconUrl": "", @@ -211,7 +211,7 @@ var NODE_CONFIG* = %* { }, { "chainId": 5, - "chainName": "Goerli", + "chainName": "Ethereum Goerli", "rpcUrl": "http://goerli.blockscout.com/", "blockExplorerUrl": "https://goerli.etherscan.io/", "iconUrl": "", diff --git a/src/app_service/service/ens/service.nim b/src/app_service/service/ens/service.nim index fdf52a763b..b7843ae6ac 100644 --- a/src/app_service/service/ens/service.nim +++ b/src/app_service/service/ens/service.nim @@ -420,10 +420,11 @@ QtObject: var decimals = 18 let allTokens = self.tokenService.getTokens() - for t in allTokens: - if(t.address == sntContract.address): - decimals = t.decimals - break + for tokens in allTokens.values: + for t in tokens: + if(t.address == sntContract.address): + decimals = t.decimals + break result = ens_utils.hex2Token(balance, decimals) diff --git a/src/app_service/service/network/service.nim b/src/app_service/service/network/service.nim index 59ab1a40d7..216c2d5b48 100644 --- a/src/app_service/service/network/service.nim +++ b/src/app_service/service/network/service.nim @@ -71,11 +71,6 @@ method getNetwork*(self: Service, chainId: int): NetworkDto = if chainId == network.chainId: return network -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: diff --git a/src/app_service/service/token/service.nim b/src/app_service/service/token/service.nim index 3b6979f960..d72a25eaba 100644 --- a/src/app_service/service/token/service.nim +++ b/src/app_service/service/token/service.nim @@ -93,13 +93,17 @@ QtObject: error "error: ", errDesription return - proc getTokens*(self: Service, useCache: bool = true): seq[TokenDto] = + proc getTokens*(self: Service, useCache: bool = true): Table[NetworkDto, seq[TokenDto]] = if not useCache: self.init() - for tokens in self.tokens.values: + return self.tokens + + proc getVisibleTokens*(self: Service): seq[TokenDto] = + for tokens in self.getTokens().values: for token in tokens: - result.add(token) + if token.isVisible: + 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 diff --git a/src/app_service/service/wallet_account/service.nim b/src/app_service/service/wallet_account/service.nim index 756baa1105..34b972448d 100644 --- a/src/app_service/service/wallet_account/service.nim +++ b/src/app_service/service/wallet_account/service.nim @@ -4,6 +4,7 @@ import web3/[ethtypes, conversions] import ../settings/service_interface as settings_service import ../accounts/service_interface as accounts_service import ../token/service as token_service +import ../network/service as network_service import ../../common/account_constants import ./service_interface, ./dto @@ -74,16 +75,15 @@ proc fetchAccounts(): seq[WalletAccountDto] = x => x.toWalletAccountDto() ).filter(a => not a.isChat) -proc fetchEthBalance(accountAddress: string): float64 = +proc fetchNativeChainBalance(network: NetworkDto, accountAddress: string): float64 = let key = "0x0" & accountAddress if balanceCache.hasKey(key): return balanceCache[key] - let ethBalanceResponse = status_go_eth.getEthBalance(accountAddress) - result = parsefloat(hex2Balance(ethBalanceResponse.result.getStr, 18)) + let nativeBalanceResponse = status_go_eth.getNativeChainBalance(network.chainId, accountAddress) + result = parsefloat(hex2Balance(nativeBalanceResponse.result.getStr, network.nativeCurrencyDecimals)) balanceCache[key] = result - type AccountSaved = ref object of Args account: WalletAccountDto @@ -103,46 +103,49 @@ type settingsService: settings_service.ServiceInterface accountsService: accounts_service.ServiceInterface tokenService: token_service.Service + networkService: network_service.Service accounts: OrderedTable[string, WalletAccountDto] method delete*(self: Service) = discard proc newService*( - events: EventEmitter, settingsService: settings_service.ServiceInterface, + events: EventEmitter, + settingsService: settings_service.ServiceInterface, accountsService: accounts_service.ServiceInterface, - tokenService: token_service.Service): - Service = + tokenService: token_service.Service, + networkService: network_service.Service, +): Service = result = Service() result.events = events result.settingsService = settingsService result.accountsService = accountsService result.tokenService = tokenService + result.networkService = networkService result.accounts = initOrderedTable[string, WalletAccountDto]() -method getVisibleTokens(self: Service): seq[TokenDto] = - return self.tokenService.getTokens().filter(t => t.isVisible) - method buildTokens( self: Service, account: WalletAccountDto, prices: Table[string, float64], balances: JsonNode ): seq[WalletTokenDto] = - let balance = fetchEthBalance(account.address) - result = @[WalletTokenDto( - name:"Ethereum", - address: "0x0000000000000000000000000000000000000000", - symbol: "ETH", - decimals: 18, - hasIcon: true, - color: "blue", - isCustom: false, - balance: balance, - currencyBalance: balance * prices["ETH"] - )] + for network in self.networkService.getEnabledNetworks(): + let balance = fetchNativeChainBalance(network, account.address) - for token in self.getVisibleTokens(): + result.add(WalletTokenDto( + name: network.chainName, + address: "0x0000000000000000000000000000000000000000", + symbol: network.nativeCurrencySymbol, + decimals: network.nativeCurrencyDecimals, + hasIcon: true, + color: "blue", + isCustom: false, + balance: balance, + currencyBalance: balance * prices[network.nativeCurrencySymbol] + )) + + for token in self.tokenService.getVisibleTokens(): let balance = parsefloat(hex2Balance(balances{token.addressAsString()}.getStr, token.decimals)) result.add( WalletTokenDto( @@ -163,16 +166,20 @@ method getPrice*(self: Service, crypto: string, fiat: string): float64 = method fetchPrices(self: Service): Table[string, float64] = let currency = self.settingsService.getCurrency() - var prices = {"ETH": fetchPrice("ETH", currency)}.toTable - for token in self.getVisibleTokens(): + var prices = initTable[string, float64]() + for network in self.networkService.getEnabledNetworks(): + prices[network.nativeCurrencySymbol] = fetchPrice(network.nativeCurrencySymbol, currency) + + for token in self.tokenService.getVisibleTokens(): prices[token.symbol] = fetchPrice(token.symbol, currency) return prices method fetchBalances(self: Service, accounts: seq[string]): JsonNode = - let chainId = self.settingsService.getCurrentNetworkId() - let tokens = self.getVisibleTokens().map(t => t.addressAsString()) - return status_go_tokens.getBalances(chainId, accounts, tokens).result + let visibleTokens = self.tokenService.getVisibleTokens() + let tokens = visibleTokens.map(t => t.addressAsString()) + let chainIds = visibleTokens.map(t => t.chainId) + return status_go_tokens.getBalances(chainIds, accounts, tokens).result method refreshBalances(self: Service) = let prices = self.fetchPrices() diff --git a/src/backend/eth.nim b/src/backend/eth.nim index 429d5f9dfc..4f543dec48 100644 --- a/src/backend/eth.nim +++ b/src/backend/eth.nim @@ -10,7 +10,7 @@ proc getBlockByNumber*(blockNumber: string): RpcResponse[JsonNode] {.raises: [Ex let payload = %* [blockNumber, false] return core.callPrivateRPC("eth_getBlockByNumber", payload) -proc getEthBalance*(address: string): RpcResponse[JsonNode] {.raises: [Exception].} = +proc getNativeChainBalance*(chainId: int, address: string): RpcResponse[JsonNode] {.raises: [Exception].} = let payload = %* [address, "latest"] return core.callPrivateRPC("eth_getBalance", payload) diff --git a/src/backend/tokens.nim b/src/backend/tokens.nim index 87c4d2d668..a05b77d9a1 100644 --- a/src/backend/tokens.nim +++ b/src/backend/tokens.nim @@ -7,5 +7,5 @@ export response_type proc getTokens*(chainId: int): RpcResponse[JsonNode] {.raises: [Exception].} = return callPrivateRPC("wallet_getTokens", %* [chainId]) -proc getBalances*(chainId: int, accounts: seq[string], tokens: seq[string]): RpcResponse[JsonNode] {.raises: [Exception].} = - return callPrivateRPC("wallet_getTokensBalancesForChainIDs", %* [@[chainId], accounts, tokens]) +proc getBalances*(chainIds: seq[int], accounts: seq[string], tokens: seq[string]): RpcResponse[JsonNode] {.raises: [Exception].} = + return callPrivateRPC("wallet_getTokensBalancesForChainIDs", %* [chainIds, accounts, tokens])