mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-22 11:38:57 +00:00
feat(@wallet): Enable multi network for wallet account
This commit is contained in:
parent
b2579230a9
commit
1d83b64fae
@ -143,9 +143,11 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
|
|||||||
statusFoundation.events, statusFoundation.threadpool, result.settingsService, result.networkService
|
statusFoundation.events, statusFoundation.threadpool, result.settingsService, result.networkService
|
||||||
)
|
)
|
||||||
result.collectibleService = collectible_service.newService(result.settingsService)
|
result.collectibleService = collectible_service.newService(result.settingsService)
|
||||||
result.walletAccountService = wallet_account_service.newService(statusFoundation.events, result.settingsService,
|
result.walletAccountService = wallet_account_service.newService(
|
||||||
result.accountsService, result.tokenService)
|
statusFoundation.events, result.settingsService, result.accountsService, result.tokenService,
|
||||||
result.transactionService = transaction_service.newService(statusFoundation.events, statusFoundation.threadpool,
|
result.networkService,
|
||||||
|
)
|
||||||
|
result.transactionService = transaction_service.newService(statusFoundation.events, statusFoundation.threadpool,
|
||||||
result.walletAccountService, result.ethService, result.networkService, result.settingsService)
|
result.walletAccountService, result.ethService, result.networkService, result.settingsService)
|
||||||
result.bookmarkService = bookmark_service.newService()
|
result.bookmarkService = bookmark_service.newService()
|
||||||
result.profileService = profile_service.newService()
|
result.profileService = profile_service.newService()
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import tables
|
||||||
import ./controller_interface
|
import ./controller_interface
|
||||||
import ./io_interface
|
import ./io_interface
|
||||||
|
|
||||||
@ -35,7 +36,9 @@ method init*(self: Controller) =
|
|||||||
self.delegate.tokenDetailsWereResolved(args.tokenDetails)
|
self.delegate.tokenDetailsWereResolved(args.tokenDetails)
|
||||||
|
|
||||||
method getTokens*(self: Controller): seq[token_service.TokenDto] =
|
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) =
|
method addCustomToken*(self: Controller, chainId: int, address: string, name: string, symbol: string, decimals: int) =
|
||||||
self.tokenService.addCustomToken(chainId, address, name, symbol, decimals)
|
self.tokenService.addCustomToken(chainId, address, name, symbol, decimals)
|
||||||
|
@ -185,7 +185,7 @@ var NODE_CONFIG* = %* {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"chainId": 3,
|
"chainId": 3,
|
||||||
"chainName": "Ropsten",
|
"chainName": "Ethereum Ropsten",
|
||||||
"rpcUrl": "https://ropsten.infura.io/v3/" & INFURA_TOKEN_RESOLVED,
|
"rpcUrl": "https://ropsten.infura.io/v3/" & INFURA_TOKEN_RESOLVED,
|
||||||
"blockExplorerUrl": "https://ropsten.etherscan.io/",
|
"blockExplorerUrl": "https://ropsten.etherscan.io/",
|
||||||
"iconUrl": "",
|
"iconUrl": "",
|
||||||
@ -198,7 +198,7 @@ var NODE_CONFIG* = %* {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"chainId": 4,
|
"chainId": 4,
|
||||||
"chainName": "Rinkeby",
|
"chainName": "Ethereum Rinkeby",
|
||||||
"rpcUrl": "https://rinkeby.infura.io/v3/" & INFURA_TOKEN_RESOLVED,
|
"rpcUrl": "https://rinkeby.infura.io/v3/" & INFURA_TOKEN_RESOLVED,
|
||||||
"blockExplorerUrl": "https://rinkeby.etherscan.io/",
|
"blockExplorerUrl": "https://rinkeby.etherscan.io/",
|
||||||
"iconUrl": "",
|
"iconUrl": "",
|
||||||
@ -211,7 +211,7 @@ var NODE_CONFIG* = %* {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"chainId": 5,
|
"chainId": 5,
|
||||||
"chainName": "Goerli",
|
"chainName": "Ethereum Goerli",
|
||||||
"rpcUrl": "http://goerli.blockscout.com/",
|
"rpcUrl": "http://goerli.blockscout.com/",
|
||||||
"blockExplorerUrl": "https://goerli.etherscan.io/",
|
"blockExplorerUrl": "https://goerli.etherscan.io/",
|
||||||
"iconUrl": "",
|
"iconUrl": "",
|
||||||
|
@ -420,10 +420,11 @@ QtObject:
|
|||||||
var decimals = 18
|
var decimals = 18
|
||||||
|
|
||||||
let allTokens = self.tokenService.getTokens()
|
let allTokens = self.tokenService.getTokens()
|
||||||
for t in allTokens:
|
for tokens in allTokens.values:
|
||||||
if(t.address == sntContract.address):
|
for t in tokens:
|
||||||
decimals = t.decimals
|
if(t.address == sntContract.address):
|
||||||
break
|
decimals = t.decimals
|
||||||
|
break
|
||||||
|
|
||||||
result = ens_utils.hex2Token(balance, decimals)
|
result = ens_utils.hex2Token(balance, decimals)
|
||||||
|
|
||||||
|
@ -71,11 +71,6 @@ method getNetwork*(self: Service, chainId: int): NetworkDto =
|
|||||||
if chainId == network.chainId:
|
if chainId == network.chainId:
|
||||||
return network
|
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 =
|
method getNetwork*(self: Service, networkType: NetworkType): NetworkDto =
|
||||||
for network in self.getNetworks():
|
for network in self.getNetworks():
|
||||||
if networkType.toChainId() == network.chainId:
|
if networkType.toChainId() == network.chainId:
|
||||||
|
@ -93,13 +93,17 @@ QtObject:
|
|||||||
error "error: ", errDesription
|
error "error: ", errDesription
|
||||||
return
|
return
|
||||||
|
|
||||||
proc getTokens*(self: Service, useCache: bool = true): seq[TokenDto] =
|
proc getTokens*(self: Service, useCache: bool = true): Table[NetworkDto, seq[TokenDto]] =
|
||||||
if not useCache:
|
if not useCache:
|
||||||
self.init()
|
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:
|
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) =
|
proc addCustomToken*(self: Service, chainId: int, address: string, name: string, symbol: string, decimals: int) =
|
||||||
# TODO(alaile): use chainId rather than first enabled network
|
# TODO(alaile): use chainId rather than first enabled network
|
||||||
|
@ -4,6 +4,7 @@ import web3/[ethtypes, conversions]
|
|||||||
import ../settings/service_interface as settings_service
|
import ../settings/service_interface as settings_service
|
||||||
import ../accounts/service_interface as accounts_service
|
import ../accounts/service_interface as accounts_service
|
||||||
import ../token/service as token_service
|
import ../token/service as token_service
|
||||||
|
import ../network/service as network_service
|
||||||
import ../../common/account_constants
|
import ../../common/account_constants
|
||||||
|
|
||||||
import ./service_interface, ./dto
|
import ./service_interface, ./dto
|
||||||
@ -74,16 +75,15 @@ proc fetchAccounts(): seq[WalletAccountDto] =
|
|||||||
x => x.toWalletAccountDto()
|
x => x.toWalletAccountDto()
|
||||||
).filter(a => not a.isChat)
|
).filter(a => not a.isChat)
|
||||||
|
|
||||||
proc fetchEthBalance(accountAddress: string): float64 =
|
proc fetchNativeChainBalance(network: NetworkDto, accountAddress: string): float64 =
|
||||||
let key = "0x0" & accountAddress
|
let key = "0x0" & accountAddress
|
||||||
if balanceCache.hasKey(key):
|
if balanceCache.hasKey(key):
|
||||||
return balanceCache[key]
|
return balanceCache[key]
|
||||||
|
|
||||||
let ethBalanceResponse = status_go_eth.getEthBalance(accountAddress)
|
let nativeBalanceResponse = status_go_eth.getNativeChainBalance(network.chainId, accountAddress)
|
||||||
result = parsefloat(hex2Balance(ethBalanceResponse.result.getStr, 18))
|
result = parsefloat(hex2Balance(nativeBalanceResponse.result.getStr, network.nativeCurrencyDecimals))
|
||||||
balanceCache[key] = result
|
balanceCache[key] = result
|
||||||
|
|
||||||
|
|
||||||
type AccountSaved = ref object of Args
|
type AccountSaved = ref object of Args
|
||||||
account: WalletAccountDto
|
account: WalletAccountDto
|
||||||
|
|
||||||
@ -103,46 +103,49 @@ type
|
|||||||
settingsService: settings_service.ServiceInterface
|
settingsService: settings_service.ServiceInterface
|
||||||
accountsService: accounts_service.ServiceInterface
|
accountsService: accounts_service.ServiceInterface
|
||||||
tokenService: token_service.Service
|
tokenService: token_service.Service
|
||||||
|
networkService: network_service.Service
|
||||||
accounts: OrderedTable[string, WalletAccountDto]
|
accounts: OrderedTable[string, WalletAccountDto]
|
||||||
|
|
||||||
method delete*(self: Service) =
|
method delete*(self: Service) =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
proc newService*(
|
proc newService*(
|
||||||
events: EventEmitter, settingsService: settings_service.ServiceInterface,
|
events: EventEmitter,
|
||||||
|
settingsService: settings_service.ServiceInterface,
|
||||||
accountsService: accounts_service.ServiceInterface,
|
accountsService: accounts_service.ServiceInterface,
|
||||||
tokenService: token_service.Service):
|
tokenService: token_service.Service,
|
||||||
Service =
|
networkService: network_service.Service,
|
||||||
|
): Service =
|
||||||
result = Service()
|
result = Service()
|
||||||
result.events = events
|
result.events = events
|
||||||
result.settingsService = settingsService
|
result.settingsService = settingsService
|
||||||
result.accountsService = accountsService
|
result.accountsService = accountsService
|
||||||
result.tokenService = tokenService
|
result.tokenService = tokenService
|
||||||
|
result.networkService = networkService
|
||||||
result.accounts = initOrderedTable[string, WalletAccountDto]()
|
result.accounts = initOrderedTable[string, WalletAccountDto]()
|
||||||
|
|
||||||
method getVisibleTokens(self: Service): seq[TokenDto] =
|
|
||||||
return self.tokenService.getTokens().filter(t => t.isVisible)
|
|
||||||
|
|
||||||
method buildTokens(
|
method buildTokens(
|
||||||
self: Service,
|
self: Service,
|
||||||
account: WalletAccountDto,
|
account: WalletAccountDto,
|
||||||
prices: Table[string, float64],
|
prices: Table[string, float64],
|
||||||
balances: JsonNode
|
balances: JsonNode
|
||||||
): seq[WalletTokenDto] =
|
): seq[WalletTokenDto] =
|
||||||
let balance = fetchEthBalance(account.address)
|
for network in self.networkService.getEnabledNetworks():
|
||||||
result = @[WalletTokenDto(
|
let balance = fetchNativeChainBalance(network, account.address)
|
||||||
name:"Ethereum",
|
|
||||||
address: "0x0000000000000000000000000000000000000000",
|
|
||||||
symbol: "ETH",
|
|
||||||
decimals: 18,
|
|
||||||
hasIcon: true,
|
|
||||||
color: "blue",
|
|
||||||
isCustom: false,
|
|
||||||
balance: balance,
|
|
||||||
currencyBalance: balance * prices["ETH"]
|
|
||||||
)]
|
|
||||||
|
|
||||||
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))
|
let balance = parsefloat(hex2Balance(balances{token.addressAsString()}.getStr, token.decimals))
|
||||||
result.add(
|
result.add(
|
||||||
WalletTokenDto(
|
WalletTokenDto(
|
||||||
@ -163,16 +166,20 @@ method getPrice*(self: Service, crypto: string, fiat: string): float64 =
|
|||||||
|
|
||||||
method fetchPrices(self: Service): Table[string, float64] =
|
method fetchPrices(self: Service): Table[string, float64] =
|
||||||
let currency = self.settingsService.getCurrency()
|
let currency = self.settingsService.getCurrency()
|
||||||
var prices = {"ETH": fetchPrice("ETH", currency)}.toTable
|
var prices = initTable[string, float64]()
|
||||||
for token in self.getVisibleTokens():
|
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)
|
prices[token.symbol] = fetchPrice(token.symbol, currency)
|
||||||
|
|
||||||
return prices
|
return prices
|
||||||
|
|
||||||
method fetchBalances(self: Service, accounts: seq[string]): JsonNode =
|
method fetchBalances(self: Service, accounts: seq[string]): JsonNode =
|
||||||
let chainId = self.settingsService.getCurrentNetworkId()
|
let visibleTokens = self.tokenService.getVisibleTokens()
|
||||||
let tokens = self.getVisibleTokens().map(t => t.addressAsString())
|
let tokens = visibleTokens.map(t => t.addressAsString())
|
||||||
return status_go_tokens.getBalances(chainId, accounts, tokens).result
|
let chainIds = visibleTokens.map(t => t.chainId)
|
||||||
|
return status_go_tokens.getBalances(chainIds, accounts, tokens).result
|
||||||
|
|
||||||
method refreshBalances(self: Service) =
|
method refreshBalances(self: Service) =
|
||||||
let prices = self.fetchPrices()
|
let prices = self.fetchPrices()
|
||||||
|
@ -10,7 +10,7 @@ proc getBlockByNumber*(blockNumber: string): RpcResponse[JsonNode] {.raises: [Ex
|
|||||||
let payload = %* [blockNumber, false]
|
let payload = %* [blockNumber, false]
|
||||||
return core.callPrivateRPC("eth_getBlockByNumber", payload)
|
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"]
|
let payload = %* [address, "latest"]
|
||||||
return core.callPrivateRPC("eth_getBalance", payload)
|
return core.callPrivateRPC("eth_getBalance", payload)
|
||||||
|
|
||||||
|
@ -7,5 +7,5 @@ export response_type
|
|||||||
proc getTokens*(chainId: int): RpcResponse[JsonNode] {.raises: [Exception].} =
|
proc getTokens*(chainId: int): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
return callPrivateRPC("wallet_getTokens", %* [chainId])
|
return callPrivateRPC("wallet_getTokens", %* [chainId])
|
||||||
|
|
||||||
proc getBalances*(chainId: int, accounts: seq[string], tokens: seq[string]): RpcResponse[JsonNode] {.raises: [Exception].} =
|
proc getBalances*(chainIds: seq[int], accounts: seq[string], tokens: seq[string]): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
return callPrivateRPC("wallet_getTokensBalancesForChainIDs", %* [@[chainId], accounts, tokens])
|
return callPrivateRPC("wallet_getTokensBalancesForChainIDs", %* [chainIds, accounts, tokens])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user