feat: add wallet token integration
This commit is contained in:
parent
e3bfdc0f09
commit
0d217c0db0
|
@ -1,18 +1,23 @@
|
|||
import sugar, sequtils
|
||||
import io_interface
|
||||
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
import ../../../../../app_service/service/network/service as network_service
|
||||
|
||||
type
|
||||
Controller* = ref object of RootObj
|
||||
delegate: io_interface.AccessInterface
|
||||
walletAccountService: wallet_account_service.Service
|
||||
networkService: network_service.Service
|
||||
|
||||
proc newController*(
|
||||
delegate: io_interface.AccessInterface,
|
||||
walletAccountService: wallet_account_service.Service
|
||||
walletAccountService: wallet_account_service.Service,
|
||||
networkService: network_service.Service,
|
||||
): Controller =
|
||||
result = Controller()
|
||||
result.delegate = delegate
|
||||
result.walletAccountService = walletAccountService
|
||||
result.networkService = networkService
|
||||
|
||||
proc delete*(self: Controller) =
|
||||
discard
|
||||
|
@ -28,3 +33,9 @@ proc getIndex*(self: Controller, address: string): int =
|
|||
|
||||
method findTokenSymbolByAddress*(self: Controller, address: string): string =
|
||||
return self.walletAccountService.findTokenSymbolByAddress(address)
|
||||
|
||||
proc getChainIds*(self: Controller): seq[int] =
|
||||
return self.networkService.getNetworks().map(n => n.chainId)
|
||||
|
||||
proc getEnabledChainIds*(self: Controller): seq[int] =
|
||||
return self.networkService.getNetworks().filter(n => n.enabled).map(n => n.chainId)
|
|
@ -3,6 +3,7 @@ import NimQml, Tables, sequtils
|
|||
import ../../../../global/global_singleton
|
||||
import ../../../../core/eventemitter
|
||||
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
import ../../../../../app_service/service/network/service as network_service
|
||||
import ../../../shared_models/token_model as token_model
|
||||
import ../../../shared_models/token_item as token_item
|
||||
|
||||
|
@ -26,13 +27,14 @@ proc newModule*(
|
|||
delegate: delegate_interface.AccessInterface,
|
||||
events: EventEmitter,
|
||||
walletAccountService: wallet_account_service.Service,
|
||||
networkService: network_service.Service,
|
||||
): Module =
|
||||
result = Module()
|
||||
result.delegate = delegate
|
||||
result.events = events
|
||||
result.currentAccountIndex = 0
|
||||
result.view = newView(result)
|
||||
result.controller = newController(result, walletAccountService)
|
||||
result.controller = newController(result, walletAccountService, networkService)
|
||||
result.moduleLoaded = false
|
||||
|
||||
method delete*(self: Module) =
|
||||
|
@ -40,20 +42,23 @@ method delete*(self: Module) =
|
|||
|
||||
proc setAssets(self: Module, tokens: seq[WalletTokenDto]) =
|
||||
var items: seq[Item]
|
||||
let chainIds = self.controller.getChainIds()
|
||||
let enabledChainIds = self.controller.getEnabledChainIds()
|
||||
|
||||
for t in tokens:
|
||||
let item = token_item.initItem(
|
||||
t.name,
|
||||
t.symbol,
|
||||
t.totalBalance.balance,
|
||||
t.totalBalance.currencyBalance,
|
||||
t.enabledNetworkBalance.balance,
|
||||
t.enabledNetworkBalance.currencybalance,
|
||||
t.visible,
|
||||
toSeq(t.balancesPerChain.values),
|
||||
t.getBalance(chainIds),
|
||||
t.getCurrencyBalance(chainIds),
|
||||
t.getBalance(enabledChainIds),
|
||||
t.getCurrencyBalance(enabledChainIds),
|
||||
t.getVisible(enabledChainIds),
|
||||
t.getBalances(enabledChainIds),
|
||||
t.description,
|
||||
t.assetWebsiteUrl,
|
||||
t.builtOn,
|
||||
t.smartContractAddress,
|
||||
t.getAddress(),
|
||||
t.marketCap,
|
||||
t.highDay,
|
||||
t.lowDay,
|
||||
|
@ -71,7 +76,8 @@ proc setAssets(self: Module, tokens: seq[WalletTokenDto]) =
|
|||
method switchAccount*(self: Module, accountIndex: int) =
|
||||
self.currentAccountIndex = accountIndex
|
||||
let walletAccount = self.controller.getWalletAccount(accountIndex)
|
||||
self.view.setData(walletAccount)
|
||||
let enabledChainIds = self.controller.getEnabledChainIds()
|
||||
self.view.setData(walletAccount, enabledChainIds)
|
||||
self.setAssets(walletAccount.tokens)
|
||||
|
||||
method load*(self: Module) =
|
||||
|
|
|
@ -143,7 +143,7 @@ QtObject:
|
|||
proc getTokenBalanceOnChain*(self: View, chainId: int, tokenSymbol: string): string {.slot.} =
|
||||
return self.assets.getTokenBalanceOnChain(chainId, tokenSymbol)
|
||||
|
||||
proc setData*(self: View, dto: wallet_account_service.WalletAccountDto) =
|
||||
proc setData*(self: View, dto: wallet_account_service.WalletAccountDto, chainIds: seq[int]) =
|
||||
self.name = dto.name
|
||||
self.nameChanged()
|
||||
self.address = dto.address
|
||||
|
@ -158,7 +158,7 @@ proc setData*(self: View, dto: wallet_account_service.WalletAccountDto) =
|
|||
self.walletTypeChanged()
|
||||
self.isChat = dto.isChat
|
||||
self.isChatChanged()
|
||||
self.currencyBalance = dto.getCurrencyBalance()
|
||||
self.currencyBalance = dto.getCurrencyBalance(chainIds)
|
||||
self.currencyBalanceChanged()
|
||||
self.emoji = dto.emoji
|
||||
self.emojiChanged()
|
||||
|
|
|
@ -46,7 +46,7 @@ proc newModule*(delegate: delegate_interface.AccessInterface,
|
|||
result.providerModule = provider_module.newModule(result, events, settingsService, networkService, providerService)
|
||||
result.bookmarkModule = bookmark_module.newModule(result, events, bookmarkService)
|
||||
result.dappsModule = dapps_module.newModule(result, dappPermissionsService, walletAccountService)
|
||||
result.currentAccountModule = current_account_module.newModule(result, events, walletAccountService)
|
||||
result.currentAccountModule = current_account_module.newModule(result, events, walletAccountService, networkService)
|
||||
|
||||
method delete*(self: Module) =
|
||||
self.view.delete
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import sugar, sequtils
|
||||
import io_interface
|
||||
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
import ../../../../../app_service/service/accounts/service as accounts_service
|
||||
import ../../../../../app_service/service/network/service as network_service
|
||||
|
||||
import ../../../../global/global_singleton
|
||||
import ../../../shared_modules/keycard_popup/io_interface as keycard_shared_module
|
||||
|
@ -16,18 +18,21 @@ type
|
|||
events: EventEmitter
|
||||
walletAccountService: wallet_account_service.Service
|
||||
accountsService: accounts_service.Service
|
||||
networkService: network_service.Service
|
||||
|
||||
proc newController*(
|
||||
delegate: io_interface.AccessInterface,
|
||||
events: EventEmitter,
|
||||
walletAccountService: wallet_account_service.Service,
|
||||
accountsService: accounts_service.Service
|
||||
accountsService: accounts_service.Service,
|
||||
networkService: network_service.Service,
|
||||
): Controller =
|
||||
result = Controller()
|
||||
result.delegate = delegate
|
||||
result.events = events
|
||||
result.walletAccountService = walletAccountService
|
||||
result.accountsService = accountsService
|
||||
result.networkService = networkService
|
||||
|
||||
proc delete*(self: Controller) =
|
||||
discard
|
||||
|
@ -100,4 +105,10 @@ proc getAllMigratedKeyPairs*(self: Controller): seq[KeyPairDto] =
|
|||
proc addWalletAccount*(self: Controller, name, address, path, addressAccountIsDerivedFrom, publicKey, keyUid, accountType,
|
||||
color, emoji: string): string =
|
||||
return self.walletAccountService.addWalletAccount(name, address, path, addressAccountIsDerivedFrom, publicKey, keyUid,
|
||||
accountType, color, emoji)
|
||||
accountType, color, emoji)
|
||||
|
||||
proc getChainIds*(self: Controller): seq[int] =
|
||||
return self.networkService.getNetworks().map(n => n.chainId)
|
||||
|
||||
proc getEnabledChainIds*(self: Controller): seq[int] =
|
||||
return self.networkService.getNetworks().filter(n => n.enabled).map(n => n.chainId)
|
||||
|
|
|
@ -8,6 +8,7 @@ import ../../../../../app_service/common/account_constants
|
|||
import ../../../../../app_service/service/keycard/service as keycard_service
|
||||
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
import ../../../../../app_service/service/accounts/service as accounts_service
|
||||
import ../../../../../app_service/service/network/service as network_service
|
||||
import ../../../shared_models/token_model as token_model
|
||||
import ../../../shared_models/token_item as token_item
|
||||
import ../../../shared_modules/keycard_popup/module as keycard_shared_module
|
||||
|
@ -41,7 +42,8 @@ proc newModule*(
|
|||
events: EventEmitter,
|
||||
keycardService: keycard_service.Service,
|
||||
walletAccountService: wallet_account_service.Service,
|
||||
accountsService: accounts_service.Service
|
||||
accountsService: accounts_service.Service,
|
||||
networkService: network_service.Service
|
||||
): Module =
|
||||
result = Module()
|
||||
result.delegate = delegate
|
||||
|
@ -50,7 +52,7 @@ proc newModule*(
|
|||
result.accountsService = accountsService
|
||||
result.walletAccountService = walletAccountService
|
||||
result.view = newView(result)
|
||||
result.controller = controller.newController(result, events, walletAccountService, accountsService)
|
||||
result.controller = controller.newController(result, events, walletAccountService, accountsService, networkService)
|
||||
result.moduleLoaded = false
|
||||
|
||||
method delete*(self: Module) =
|
||||
|
@ -69,25 +71,25 @@ method refreshWalletAccounts*(self: Module) =
|
|||
let walletAccounts = self.controller.getWalletAccounts()
|
||||
let migratedKeyPairs = self.controller.getAllMigratedKeyPairs()
|
||||
|
||||
let chainIds = self.controller.getChainIds()
|
||||
let enabledChainIds = self.controller.getEnabledChainIds()
|
||||
|
||||
let items = walletAccounts.map(proc (w: WalletAccountDto): item.Item =
|
||||
let assets = token_model.newModel()
|
||||
|
||||
|
||||
assets.setItems(
|
||||
w.tokens.map(t => token_item.initItem(
|
||||
t.name,
|
||||
t.symbol,
|
||||
t.totalBalance.balance,
|
||||
t.totalBalance.currencyBalance,
|
||||
t.enabledNetworkBalance.balance,
|
||||
t.enabledNetworkBalance.currencyBalance,
|
||||
t.visible,
|
||||
toSeq(t.balancesPerChain.values),
|
||||
t.getBalance(chainIds),
|
||||
t.getCurrencyBalance(chainIds),
|
||||
t.getBalance(enabledChainIds),
|
||||
t.getCurrencyBalance(enabledChainIds),
|
||||
t.getVisible(enabledChainIds),
|
||||
t.getBalances(enabledChainIds),
|
||||
t.description,
|
||||
t.assetWebsiteUrl,
|
||||
t.builtOn,
|
||||
t.smartContractAddress,
|
||||
t.getAddress(),
|
||||
t.marketCap,
|
||||
t.highDay,
|
||||
t.lowDay,
|
||||
|
@ -111,7 +113,7 @@ method refreshWalletAccounts*(self: Module) =
|
|||
x.walletType,
|
||||
x.isWallet,
|
||||
x.isChat,
|
||||
x.getCurrencyBalance(),
|
||||
x.getBalance(enabledChainIds),
|
||||
x.emoji,
|
||||
x.derivedfrom,
|
||||
))
|
||||
|
@ -126,7 +128,7 @@ method refreshWalletAccounts*(self: Module) =
|
|||
w.walletType,
|
||||
w.isWallet,
|
||||
w.isChat,
|
||||
w.getCurrencyBalance(),
|
||||
w.getBalance(enabledChainIds),
|
||||
assets,
|
||||
w.emoji,
|
||||
w.derivedfrom,
|
||||
|
|
|
@ -29,48 +29,10 @@ proc delete*(self: Controller) =
|
|||
discard
|
||||
|
||||
proc 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()
|
||||
|
||||
self.events.on(SIGNAL_TOKEN_HISTORICAL_DATA_LOADED) do(e:Args):
|
||||
let args = TokenHistoricalDataArgs(e)
|
||||
self.delegate.tokenHistoricalDataResolved(args.result)
|
||||
|
||||
self.events.on(SIGNAL_BALANCE_HISTORY_DATA_READY) do(e:Args):
|
||||
let args = TokenBalanceHistoryDataArgs(e)
|
||||
self.delegate.tokenBalanceHistoryDataResolved(args.result)
|
||||
|
||||
proc getTokens*(self: Controller): seq[token_service.TokenDto] =
|
||||
proc compare(x, y: token_service.TokenDto): int =
|
||||
if x.name < y.name:
|
||||
return -1
|
||||
elif x.name > y.name:
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
for tokens in self.tokenService.getTokens().values:
|
||||
for token in tokens:
|
||||
result.add(token)
|
||||
|
||||
result.sort(compare)
|
||||
|
||||
proc addCustomToken*(self: Controller, chainId: int, address: string, name: string, symbol: string, decimals: int): string =
|
||||
return self.tokenService.addCustomToken(chainId, address, name, symbol, decimals)
|
||||
|
||||
proc toggleVisible*(self: Controller, chainId: int, address: string) =
|
||||
self.walletAccountService.toggleTokenVisible(chainId, address)
|
||||
|
||||
proc removeCustomToken*(self: Controller, chainId: int, address: string) =
|
||||
self.tokenService.removeCustomToken(chainId, address)
|
||||
|
||||
proc getTokenDetails*(self: Controller, address: string) =
|
||||
self.tokenService.getTokenDetails(address)
|
||||
|
||||
method findTokenSymbolByAddress*(self: Controller, address: string): string =
|
||||
return self.walletAccountService.findTokenSymbolByAddress(address)
|
||||
|
||||
|
|
|
@ -11,24 +11,6 @@ method load*(self: AccessInterface) {.base.} =
|
|||
method isLoaded*(self: AccessInterface): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method addCustomToken*(self: AccessInterface, chainId: int, address: string, name: string, symbol: string, decimals: int): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method toggleVisible*(self: AccessInterface, chainId: int, address: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
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.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method tokenDetailsWereResolved*(self: AccessInterface, tokenDetails: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method findTokenSymbolByAddress*(self: AccessInterface, address: string): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
import strformat
|
||||
|
||||
type
|
||||
Item* = object
|
||||
name: string
|
||||
symbol: string
|
||||
hasIcon: bool
|
||||
address: string
|
||||
decimals: int
|
||||
isCustom: bool
|
||||
isVisible: bool
|
||||
chainId: int
|
||||
|
||||
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
|
||||
result.address = address
|
||||
result.decimals = decimals
|
||||
result.isCustom = isCustom
|
||||
result.isVisible = isVisible
|
||||
result.chainId = chainId
|
||||
|
||||
proc `$`*(self: Item): string =
|
||||
result = fmt"""AllTokensItem(
|
||||
name: {self.name},
|
||||
symbol: {self.symbol},
|
||||
hasIcon: {self.hasIcon},
|
||||
address: {self.address},
|
||||
decimals: {self.decimals},
|
||||
isCustom:{self.isCustom},
|
||||
isVisible:{self.isVisible},
|
||||
chainId:{self.chainId}
|
||||
]"""
|
||||
|
||||
proc getName*(self: Item): string =
|
||||
return self.name
|
||||
|
||||
proc getSymbol*(self: Item): string =
|
||||
return self.symbol
|
||||
|
||||
proc getHasIcon*(self: Item): bool =
|
||||
return self.hasIcon
|
||||
|
||||
proc getAddress*(self: Item): string =
|
||||
return self.address
|
||||
|
||||
proc getDecimals*(self: Item): int =
|
||||
return self.decimals
|
||||
|
||||
proc getIsCustom*(self: Item): bool =
|
||||
return self.isCustom
|
||||
|
||||
proc getIsVisible*(self: Item): bool =
|
||||
return self.isVisible
|
||||
|
||||
proc getChainId*(self: Item): int =
|
||||
return self.chainId
|
|
@ -1,92 +0,0 @@
|
|||
import NimQml, Tables, strutils, strformat
|
||||
|
||||
import ./item
|
||||
|
||||
type
|
||||
ModelRole {.pure.} = enum
|
||||
Name = UserRole + 1,
|
||||
Symbol
|
||||
HasIcon
|
||||
Address
|
||||
Decimals
|
||||
IsCustom
|
||||
IsVisible
|
||||
ChainId
|
||||
|
||||
QtObject:
|
||||
type
|
||||
Model* = ref object of QAbstractListModel
|
||||
items: seq[Item]
|
||||
|
||||
proc delete(self: Model) =
|
||||
self.items = @[]
|
||||
self.QAbstractListModel.delete
|
||||
|
||||
proc setup(self: Model) =
|
||||
self.QAbstractListModel.setup
|
||||
|
||||
proc newModel*(): Model =
|
||||
new(result, delete)
|
||||
result.setup
|
||||
|
||||
proc `$`*(self: Model): string =
|
||||
for i in 0 ..< self.items.len:
|
||||
result &= fmt"""[{i}]:({$self.items[i]})"""
|
||||
|
||||
proc countChanged(self: Model) {.signal.}
|
||||
|
||||
proc getCount(self: Model): int {.slot.} =
|
||||
self.items.len
|
||||
|
||||
QtProperty[int] count:
|
||||
read = getCount
|
||||
notify = countChanged
|
||||
|
||||
method rowCount(self: Model, index: QModelIndex = nil): int =
|
||||
return self.items.len
|
||||
|
||||
method roleNames(self: Model): Table[int, string] =
|
||||
{
|
||||
ModelRole.Name.int:"name",
|
||||
ModelRole.Symbol.int:"symbol",
|
||||
ModelRole.HasIcon.int:"hasIcon",
|
||||
ModelRole.Address.int:"address",
|
||||
ModelRole.Decimals.int:"decimals",
|
||||
ModelRole.IsCustom.int:"isCustom",
|
||||
ModelRole.IsVisible.int:"isVisible",
|
||||
ModelRole.ChainId.int:"chainId"
|
||||
}.toTable
|
||||
|
||||
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
||||
if (not index.isValid):
|
||||
return
|
||||
|
||||
if (index.row < 0 or index.row >= self.items.len):
|
||||
return
|
||||
|
||||
let item = self.items[index.row]
|
||||
let enumRole = role.ModelRole
|
||||
|
||||
case enumRole:
|
||||
of ModelRole.Name:
|
||||
result = newQVariant(item.getName())
|
||||
of ModelRole.Symbol:
|
||||
result = newQVariant(item.getSymbol())
|
||||
of ModelRole.HasIcon:
|
||||
result = newQVariant(item.getHasIcon())
|
||||
of ModelRole.Address:
|
||||
result = newQVariant(item.getAddress())
|
||||
of ModelRole.Decimals:
|
||||
result = newQVariant(item.getDecimals())
|
||||
of ModelRole.IsCustom:
|
||||
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()
|
||||
self.items = items
|
||||
self.endResetModel()
|
||||
self.countChanged()
|
|
@ -1,6 +1,6 @@
|
|||
import NimQml, sequtils, sugar
|
||||
|
||||
import ./io_interface, ./view, ./controller, ./item
|
||||
import ./io_interface, ./view, ./controller
|
||||
import ../io_interface as delegate_interface
|
||||
|
||||
import ../../../../global/global_singleton
|
||||
|
@ -36,34 +36,9 @@ method delete*(self: Module) =
|
|||
self.view.delete
|
||||
self.controller.delete
|
||||
|
||||
method refreshTokens*(self: Module) =
|
||||
let tokens = self.controller.getTokens()
|
||||
self.view.setItems(
|
||||
tokens.map(t => initItem(
|
||||
t.name,
|
||||
t.symbol,
|
||||
t.hasIcon,
|
||||
t.addressAsString(),
|
||||
t.decimals,
|
||||
t.isCustom,
|
||||
t.isVisible,
|
||||
t.chainId,
|
||||
))
|
||||
)
|
||||
|
||||
method load*(self: Module) =
|
||||
singletonInstance.engine.setRootContextProperty("walletSectionAllTokens", newQVariant(self.view))
|
||||
|
||||
# these connections should be part of the controller's init method
|
||||
self.events.on("token/customTokenAdded") do(e:Args):
|
||||
self.refreshTokens()
|
||||
|
||||
self.events.on("token/visibilityToggled") do(e:Args):
|
||||
self.refreshTokens()
|
||||
|
||||
self.events.on("token/customTokenRemoved") do(e:Args):
|
||||
self.refreshTokens()
|
||||
|
||||
self.controller.init()
|
||||
self.view.load()
|
||||
|
||||
|
@ -71,25 +46,9 @@ method isLoaded*(self: Module): bool =
|
|||
return self.moduleLoaded
|
||||
|
||||
method viewDidLoad*(self: Module) =
|
||||
self.refreshTokens()
|
||||
self.moduleLoaded = true
|
||||
self.delegate.allTokensModuleDidLoad()
|
||||
|
||||
method addCustomToken*(self: Module, chainId: int, address: string, name: string, symbol: string, decimals: int): string =
|
||||
return self.controller.addCustomToken(chainId, address, name, symbol, decimals)
|
||||
|
||||
method toggleVisible*(self: Module, chainId: int, address: string) =
|
||||
self.controller.toggleVisible(chainId, 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 tokenDetailsWereResolved*(self: Module, tokenDetails: string) =
|
||||
self.view.tokenDetailsWereResolved(tokenDetails)
|
||||
|
||||
method findTokenSymbolByAddress*(self: Module, address: string): string =
|
||||
return self.controller.findTokenSymbolByAddress(address)
|
||||
|
||||
|
|
|
@ -1,80 +1,23 @@
|
|||
import NimQml, sequtils, sugar, strutils
|
||||
|
||||
import ./model
|
||||
import ./item
|
||||
import ./io_interface
|
||||
|
||||
QtObject:
|
||||
type
|
||||
View* = ref object of QObject
|
||||
delegate: io_interface.AccessInterface
|
||||
default: Model
|
||||
custom: Model
|
||||
all: Model
|
||||
|
||||
proc delete*(self: View) =
|
||||
self.default.delete
|
||||
self.custom.delete
|
||||
self.all.delete
|
||||
self.QObject.delete
|
||||
|
||||
proc newView*(delegate: io_interface.AccessInterface): View =
|
||||
new(result, delete)
|
||||
result.QObject.setup
|
||||
result.delegate = delegate
|
||||
result.default = newModel()
|
||||
result.custom = newModel()
|
||||
result.all = newModel()
|
||||
|
||||
proc load*(self: View) =
|
||||
self.delegate.viewDidLoad()
|
||||
|
||||
proc allChanged*(self: View) {.signal.}
|
||||
|
||||
proc getAll(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.all)
|
||||
|
||||
QtProperty[QVariant] all:
|
||||
read = getAll
|
||||
notify = allChanged
|
||||
|
||||
proc defaultChanged*(self: View) {.signal.}
|
||||
|
||||
proc getDefault(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.default)
|
||||
|
||||
QtProperty[QVariant] default:
|
||||
read = getDefault
|
||||
notify = defaultChanged
|
||||
|
||||
proc customChanged*(self: View) {.signal.}
|
||||
|
||||
proc getCustom(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.custom)
|
||||
|
||||
QtProperty[QVariant] custom:
|
||||
read = getCustom
|
||||
notify = customChanged
|
||||
|
||||
proc setItems*(self: View, items: seq[Item]) =
|
||||
self.all.setItems(items)
|
||||
self.custom.setItems(items.filter(i => i.getIsCustom()))
|
||||
self.default.setItems(items.filter(i => not i.getIsCustom()))
|
||||
|
||||
proc addCustomToken(self: View, chainId: int, address: string, name: string, symbol: string, decimals: string): string {.slot.} =
|
||||
return self.delegate.addCustomToken(chainId, address, name, symbol, parseInt(decimals))
|
||||
|
||||
proc toggleVisible(self: View, chainId: int, address: string) {.slot.} =
|
||||
self.delegate.toggleVisible(chainId, 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 findTokenSymbolByAddress*(self: View, address: string): string {.slot.} =
|
||||
return self.delegate.findTokenSymbolByAddress(address)
|
||||
|
||||
|
|
|
@ -1,26 +1,22 @@
|
|||
import io_interface
|
||||
import ../../../../app_service/service/settings/service as settings_service
|
||||
import ../../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
import ../../../../app_service/service/network/service as network_service
|
||||
|
||||
type
|
||||
Controller* = ref object of RootObj
|
||||
delegate: io_interface.AccessInterface
|
||||
settingsService: settings_service.Service
|
||||
walletAccountService: wallet_account_service.Service
|
||||
networkService: network_service.Service
|
||||
|
||||
proc newController*(
|
||||
delegate: io_interface.AccessInterface,
|
||||
settingsService: settings_service.Service,
|
||||
walletAccountService: wallet_account_service.Service,
|
||||
networkService: network_service.Service,
|
||||
): Controller =
|
||||
result = Controller()
|
||||
result.delegate = delegate
|
||||
result.settingsService = settingsService
|
||||
result.walletAccountService = walletAccountService
|
||||
result.networkService = networkService
|
||||
|
||||
proc delete*(self: Controller) =
|
||||
discard
|
||||
|
@ -38,7 +34,7 @@ proc isMnemonicBackedUp*(self: Controller): bool =
|
|||
return self.settingsService.getMnemonic().len > 0
|
||||
|
||||
proc getCurrencyBalance*(self: Controller): float64 =
|
||||
return self.walletAccountService.getCurrencyBalance()
|
||||
return self.walletAccountService.getTotalCurrencyBalance()
|
||||
|
||||
proc updateCurrency*(self: Controller, currency: string) =
|
||||
self.walletAccountService.updateCurrency(currency)
|
||||
|
|
|
@ -1,19 +1,24 @@
|
|||
import sugar, sequtils
|
||||
import io_interface
|
||||
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
import ../../../../../app_service/service/network/service as network_service
|
||||
|
||||
|
||||
type
|
||||
Controller* = ref object of RootObj
|
||||
delegate: io_interface.AccessInterface
|
||||
walletAccountService: wallet_account_service.Service
|
||||
|
||||
networkService: network_service.Service
|
||||
|
||||
proc newController*(
|
||||
delegate: io_interface.AccessInterface,
|
||||
walletAccountService: wallet_account_service.Service
|
||||
walletAccountService: wallet_account_service.Service,
|
||||
networkService: network_service.Service,
|
||||
): Controller =
|
||||
result = Controller()
|
||||
result.delegate = delegate
|
||||
result.walletAccountService = walletAccountService
|
||||
result.networkService = networkService
|
||||
|
||||
proc delete*(self: Controller) =
|
||||
discard
|
||||
|
@ -29,3 +34,9 @@ proc update*(self: Controller, address: string, accountName: string, color: stri
|
|||
|
||||
method findTokenSymbolByAddress*(self: Controller, address: string): string =
|
||||
return self.walletAccountService.findTokenSymbolByAddress(address)
|
||||
|
||||
proc getChainIds*(self: Controller): seq[int] =
|
||||
return self.networkService.getNetworks().map(n => n.chainId)
|
||||
|
||||
proc getEnabledChainIds*(self: Controller): seq[int] =
|
||||
return self.networkService.getNetworks().filter(n => n.enabled).map(n => n.chainId)
|
|
@ -3,6 +3,7 @@ import NimQml, Tables, sequtils
|
|||
import ../../../../global/global_singleton
|
||||
import ../../../../core/eventemitter
|
||||
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
import ../../../../../app_service/service/network/service as network_service
|
||||
import ../../../shared_models/token_model as token_model
|
||||
import ../../../shared_models/token_item as token_item
|
||||
|
||||
|
@ -26,13 +27,14 @@ proc newModule*(
|
|||
delegate: delegate_interface.AccessInterface,
|
||||
events: EventEmitter,
|
||||
walletAccountService: wallet_account_service.Service,
|
||||
networkService: network_service.Service,
|
||||
): Module =
|
||||
result = Module()
|
||||
result.delegate = delegate
|
||||
result.events = events
|
||||
result.currentAccountIndex = 0
|
||||
result.view = newView(result)
|
||||
result.controller = newController(result, walletAccountService)
|
||||
result.controller = newController(result, walletAccountService, networkService)
|
||||
result.moduleLoaded = false
|
||||
|
||||
method delete*(self: Module) =
|
||||
|
@ -70,21 +72,24 @@ method viewDidLoad*(self: Module) =
|
|||
|
||||
proc setAssetsAndBalance(self: Module, tokens: seq[WalletTokenDto]) =
|
||||
var totalCurrencyBalanceForAllAssets = 0.0
|
||||
let chainIds = self.controller.getChainIds()
|
||||
let enabledChainIds = self.controller.getEnabledChainIds()
|
||||
|
||||
var items: seq[Item]
|
||||
for t in tokens:
|
||||
let item = token_item.initItem(
|
||||
t.name,
|
||||
t.symbol,
|
||||
t.totalBalance.balance,
|
||||
t.totalBalance.currencyBalance,
|
||||
t.enabledNetworkBalance.balance,
|
||||
t.enabledNetworkBalance.currencybalance,
|
||||
t.visible,
|
||||
toSeq(t.balancesPerChain.values),
|
||||
t.getBalance(chainIds),
|
||||
t.getCurrencyBalance(chainIds),
|
||||
t.getBalance(enabledChainIds),
|
||||
t.getCurrencyBalance(enabledChainIds),
|
||||
t.getVisible(enabledChainIds),
|
||||
t.getBalances(enabledChainIds),
|
||||
t.description,
|
||||
t.assetWebsiteUrl,
|
||||
t.builtOn,
|
||||
t.smartContractAddress,
|
||||
t.getAddress(),
|
||||
t.marketCap,
|
||||
t.highDay,
|
||||
t.lowDay,
|
||||
|
@ -96,17 +101,18 @@ proc setAssetsAndBalance(self: Module, tokens: seq[WalletTokenDto]) =
|
|||
t.decimals,
|
||||
)
|
||||
items.add(item)
|
||||
totalCurrencyBalanceForAllAssets += t.enabledNetworkBalance.currencybalance
|
||||
totalCurrencyBalanceForAllAssets += t.getCurrencyBalance(enabledChainIds)
|
||||
|
||||
self.view.getAssetsModel().setItems(items)
|
||||
self.view.setCurrencyBalance(totalCurrencyBalanceForAllAssets)
|
||||
|
||||
method switchAccount*(self: Module, accountIndex: int) =
|
||||
self.currentAccountIndex = accountIndex
|
||||
let enabledChainIds = self.controller.getEnabledChainIds()
|
||||
let walletAccount = self.controller.getWalletAccount(accountIndex)
|
||||
# can safely do this as the account will always contain atleast one account
|
||||
self.view.setDefaultWalletAccount(self.controller.getWalletAccount(0))
|
||||
self.view.setData(walletAccount)
|
||||
self.view.setData(walletAccount, enabledChainIds)
|
||||
self.setAssetsAndBalance(walletAccount.tokens)
|
||||
|
||||
method update*(self: Module, address: string, accountName: string, color: string, emoji: string) =
|
||||
|
|
|
@ -166,7 +166,7 @@ QtObject:
|
|||
proc setDefaultWalletAccount*(self: View, default: wallet_account_service.WalletAccountDto) =
|
||||
self.defaultAccount = default
|
||||
|
||||
proc setData*(self: View, dto: wallet_account_service.WalletAccountDto) =
|
||||
proc setData*(self: View, dto: wallet_account_service.WalletAccountDto, chainIds: seq[int]) =
|
||||
if(self.name != dto.name):
|
||||
self.name = dto.name
|
||||
self.nameChanged()
|
||||
|
@ -214,7 +214,7 @@ QtObject:
|
|||
x.walletType,
|
||||
x.isWallet,
|
||||
x.isChat,
|
||||
x.getCurrencyBalance(),
|
||||
x.getCurrencyBalance(chainIds),
|
||||
x.emoji,
|
||||
x.derivedfrom
|
||||
))
|
||||
|
|
|
@ -61,13 +61,13 @@ proc newModule*(
|
|||
result.delegate = delegate
|
||||
result.events = events
|
||||
result.moduleLoaded = false
|
||||
result.controller = newController(result, settingsService, walletAccountService, networkService)
|
||||
result.controller = newController(result, settingsService, walletAccountService)
|
||||
result.view = newView(result)
|
||||
|
||||
result.accountsModule = accounts_module.newModule(result, events, keycardService, walletAccountService, accountsService)
|
||||
result.accountsModule = accounts_module.newModule(result, events, keycardService, walletAccountService, accountsService, networkService)
|
||||
result.allTokensModule = all_tokens_module.newModule(result, events, tokenService, walletAccountService)
|
||||
result.collectiblesModule = collectibles_module.newModule(result, events, collectibleService, walletAccountService)
|
||||
result.currentAccountModule = current_account_module.newModule(result, events, walletAccountService)
|
||||
result.currentAccountModule = current_account_module.newModule(result, events, walletAccountService, networkService)
|
||||
result.transactionsModule = transactions_module.newModule(result, events, transactionService, walletAccountService, networkService)
|
||||
result.savedAddressesModule = saved_addresses_module.newModule(result, events, savedAddressService)
|
||||
result.buySellCryptoModule = buy_sell_crypto_module.newModule(result, events, transactionService)
|
||||
|
|
|
@ -7,8 +7,6 @@ type
|
|||
ChainId = UserRole + 1,
|
||||
Address
|
||||
Balance
|
||||
CurrencyBalance
|
||||
Enabled
|
||||
|
||||
QtObject:
|
||||
type
|
||||
|
@ -47,8 +45,6 @@ QtObject:
|
|||
ModelRole.ChainId.int:"chainId",
|
||||
ModelRole.Address.int:"address",
|
||||
ModelRole.Balance.int:"balance",
|
||||
ModelRole.CurrencyBalance.int:"currencyBalance",
|
||||
ModelRole.Enabled.int:"enabled",
|
||||
}.toTable
|
||||
|
||||
method data(self: BalanceModel, index: QModelIndex, role: int): QVariant =
|
||||
|
@ -67,11 +63,7 @@ QtObject:
|
|||
of ModelRole.Address:
|
||||
result = newQVariant(item.address)
|
||||
of ModelRole.Balance:
|
||||
result = newQVariant(item.balance)
|
||||
of ModelRole.CurrencyBalance:
|
||||
result = newQVariant(item.currencyBalance)
|
||||
of ModelRole.Enabled:
|
||||
result = newQVariant(item.enabled)
|
||||
result = newQVariant($item.balance)
|
||||
|
||||
proc rowData(self: BalanceModel, index: int, column: string): string {.slot.} =
|
||||
if (index >= self.items.len):
|
||||
|
@ -81,8 +73,6 @@ QtObject:
|
|||
of "chainId": result = $item.chainId
|
||||
of "address": result = $item.address
|
||||
of "balance": result = $item.balance
|
||||
of "currencyBalance": result = $item.currencyBalance
|
||||
of "enabled": result = $item.enabled
|
||||
|
||||
proc setItems*(self: BalanceModel, items: seq[BalanceDto]) =
|
||||
self.beginResetModel()
|
||||
|
|
|
@ -16,7 +16,7 @@ type
|
|||
description: string
|
||||
assetWebsiteUrl: string
|
||||
builtOn: string
|
||||
smartContractAddress: string
|
||||
address: string
|
||||
marketCap: string
|
||||
highDay: string
|
||||
lowDay: string
|
||||
|
@ -38,7 +38,7 @@ proc initItem*(
|
|||
description: string,
|
||||
assetWebsiteUrl: string,
|
||||
builtOn: string,
|
||||
smartContractAddress: string,
|
||||
address: string,
|
||||
marketCap: string,
|
||||
highDay: string,
|
||||
lowDay: string,
|
||||
|
@ -61,7 +61,7 @@ proc initItem*(
|
|||
result.description = description
|
||||
result.assetWebsiteUrl = assetWebsiteUrl
|
||||
result.builtOn = builtOn
|
||||
result.smartContractAddress = smartContractAddress
|
||||
result.address = address
|
||||
result.marketCap = marketCap
|
||||
result.highDay = highDay
|
||||
result.lowDay = lowDay
|
||||
|
@ -84,7 +84,7 @@ proc `$`*(self: Item): string =
|
|||
description: {self.description},
|
||||
assetWebsiteUrl: {self.assetWebsiteUrl}
|
||||
builtOn: {self.builtOn}
|
||||
smartContractAddress: {self.smartContractAddress}
|
||||
address: {self.address}
|
||||
marketCap: {self.marketCap},
|
||||
highDay: {self.highDay},
|
||||
lowDay: {self.lowDay},
|
||||
|
@ -129,8 +129,8 @@ proc getAssetWebsiteUrl*(self: Item): string =
|
|||
proc getBuiltOn*(self: Item): string =
|
||||
return self.builtOn
|
||||
|
||||
proc getSmartContractAddress*(self: Item): string =
|
||||
return self.smartContractAddress
|
||||
proc getAddress*(self: Item): string =
|
||||
return self.address
|
||||
|
||||
proc getMarketCap*(self: Item): string =
|
||||
return self.marketCap
|
||||
|
|
|
@ -15,7 +15,7 @@ type
|
|||
Description
|
||||
AssetWebsiteUrl
|
||||
BuiltOn
|
||||
SmartContractAddress
|
||||
Address
|
||||
MarketCap
|
||||
HighDay
|
||||
LowDay
|
||||
|
@ -71,7 +71,7 @@ QtObject:
|
|||
ModelRole.Description.int:"description",
|
||||
ModelRole.AssetWebsiteUrl.int:"assetWebsiteUrl",
|
||||
ModelRole.BuiltOn.int:"builtOn",
|
||||
ModelRole.SmartContractAddress.int:"smartContractAddress",
|
||||
ModelRole.Address.int:"address",
|
||||
ModelRole.MarketCap.int:"marketCap",
|
||||
ModelRole.HighDay.int:"highDay",
|
||||
ModelRole.LowDay.int:"lowDay",
|
||||
|
@ -116,8 +116,8 @@ QtObject:
|
|||
result = newQVariant(item.getAssetWebsiteUrl())
|
||||
of ModelRole.BuiltOn:
|
||||
result = newQVariant(item.getBuiltOn())
|
||||
of ModelRole.SmartContractAddress:
|
||||
result = newQVariant(item.getSmartContractAddress())
|
||||
of ModelRole.Address:
|
||||
result = newQVariant(item.getAddress())
|
||||
of ModelRole.MarketCap:
|
||||
result = newQVariant(item.getMarketCap())
|
||||
of ModelRole.HighDay:
|
||||
|
@ -152,7 +152,7 @@ QtObject:
|
|||
of "description": result = $item.getDescription()
|
||||
of "assetWebsiteUrl": result = $item.getAssetWebsiteUrl()
|
||||
of "builtOn": result = $item.getBuiltOn()
|
||||
of "smartContractAddress": result = $item.getSmartContractAddress()
|
||||
of "Address": result = $item.getAddress()
|
||||
of "marketCap": result = $item.getMarketCap()
|
||||
of "highDay": result = $item.getHighDay()
|
||||
of "lowDay": result = $item.getLowDay()
|
||||
|
|
|
@ -464,10 +464,10 @@ proc getWalletAccounts*(self: Controller): seq[wallet_account_service.WalletAcco
|
|||
return
|
||||
return self.walletAccountService.fetchAccounts()
|
||||
|
||||
proc getBalanceForAddress*(self: Controller, address: string): float64 =
|
||||
proc getCurrencyBalanceForAddress*(self: Controller, address: string): float64 =
|
||||
if not serviceApplicable(self.walletAccountService):
|
||||
return
|
||||
return self.walletAccountService.fetchBalanceForAddress(address)
|
||||
return self.walletAccountService.getCurrencyBalanceForAddress(address)
|
||||
|
||||
proc addMigratedKeyPair*(self: Controller, keyPair: KeyPairDto) =
|
||||
if not serviceApplicable(self.walletAccountService):
|
||||
|
|
|
@ -470,7 +470,7 @@ method setKeyPairStoredOnKeycard*[T](self: Module[T], cardMetadata: CardMetadata
|
|||
for wa in cardMetadata.walletAccounts:
|
||||
if self.updateKeyPairItemIfDataAreKnown(wa.address, item):
|
||||
continue
|
||||
let balance = self.controller.getBalanceForAddress(wa.address)
|
||||
let balance = self.controller.getCurrencyBalanceForAddress(wa.address)
|
||||
knownKeyPair = false
|
||||
item.addAccount(name = "", wa.path, wa.address, emoji = "", color = self.generateRandomColor(), icon = "wallet", balance)
|
||||
self.view.setKeyPairStoredOnKeycardIsKnown(knownKeyPair)
|
||||
|
|
|
@ -11,35 +11,6 @@ import ./dto
|
|||
const DAYS_IN_WEEK = 7
|
||||
const HOURS_IN_DAY = 24
|
||||
|
||||
type
|
||||
GetTokenDetailsTaskArg = ref object of QObjectTaskArg
|
||||
chainIds: seq[int]
|
||||
address: string
|
||||
|
||||
|
||||
const getTokenDetailsTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[GetTokenDetailsTaskArg](argEncoded)
|
||||
for chainId in arg.chainIds:
|
||||
try:
|
||||
let response = backend.discoverToken(chainId, arg.address).result
|
||||
|
||||
let output = %* {
|
||||
"address": arg.address,
|
||||
"name": response{"name"}.getStr,
|
||||
"symbol": response{"symbol"}.getStr,
|
||||
"decimals": response{"decimals"}.getInt
|
||||
}
|
||||
arg.finish(output)
|
||||
return
|
||||
except Exception as e:
|
||||
continue
|
||||
|
||||
let output = %* {
|
||||
"address": arg.address,
|
||||
"error": "Is this an ERC-20 or ERC-721 contract?",
|
||||
}
|
||||
arg.finish(output)
|
||||
|
||||
type
|
||||
GetTokenHistoricalDataTaskArg = ref object of QObjectTaskArg
|
||||
symbol: string
|
||||
|
|
|
@ -62,18 +62,7 @@ proc newTokenDto*(
|
|||
symbol: symbol,
|
||||
decimals: decimals,
|
||||
hasIcon: hasIcon,
|
||||
isCustom: isCustom,
|
||||
description: description,
|
||||
assetWebsiteUrl: assetWebsiteUrl,
|
||||
builtOn: builtOn,
|
||||
smartContractAddress: smartContractAddress,
|
||||
marketCap: marketCap,
|
||||
highDay: highDay,
|
||||
lowDay: lowDay,
|
||||
changePctHour: changePctHour,
|
||||
changePctDay: changePctDay,
|
||||
changePct24hour: changePct24hour,
|
||||
change24hour: change24hour,
|
||||
isCustom: isCustom
|
||||
)
|
||||
|
||||
proc toTokenDto*(jsonObj: JsonNode, isVisible: bool, hasIcon: bool = false, isCustom: bool = true): TokenDto =
|
||||
|
@ -87,18 +76,6 @@ proc toTokenDto*(jsonObj: JsonNode, isVisible: bool, hasIcon: bool = false, isCu
|
|||
discard jsonObj.getProp("symbol", result.symbol)
|
||||
discard jsonObj.getProp("decimals", result.decimals)
|
||||
discard jsonObj.getProp("color", result.color)
|
||||
discard jsonObj.getProp("description", result.description)
|
||||
discard jsonObj.getProp("assetWebsiteUrl", result.assetWebsiteUrl)
|
||||
discard jsonObj.getProp("builtOn", result.builtOn)
|
||||
discard jsonObj.getProp("smartContractAddress", result.smartContractAddress)
|
||||
discard jsonObj.getProp("marketCap", result.marketCap)
|
||||
discard jsonObj.getProp("highDay", result.highDay)
|
||||
discard jsonObj.getProp("lowDay", result.lowDay)
|
||||
discard jsonObj.getProp("changePctHour", result.changePctHour)
|
||||
discard jsonObj.getProp("changePctDay", result.changePctDay)
|
||||
discard jsonObj.getProp("changePct24hour", result.changePct24hour)
|
||||
discard jsonObj.getProp("change24hour", result.change24hour)
|
||||
|
||||
result.isVisible = isVisible
|
||||
|
||||
proc addressAsString*(self: TokenDto): string =
|
||||
|
|
|
@ -19,27 +19,9 @@ logScope:
|
|||
include async_tasks
|
||||
|
||||
# Signals which may be emitted by this service:
|
||||
const SIGNAL_TOKEN_DETAILS_LOADED* = "tokenDetailsLoaded"
|
||||
const SIGNAL_TOKEN_LIST_RELOADED* = "tokenListReloaded"
|
||||
const SIGNAL_TOKEN_HISTORICAL_DATA_LOADED* = "tokenHistoricalDataLoaded"
|
||||
const SIGNAL_BALANCE_HISTORY_DATA_READY* = "tokenBalanceHistoryDataReady"
|
||||
|
||||
type
|
||||
TokenDetailsLoadedArgs* = ref object of Args
|
||||
tokenDetails*: string
|
||||
|
||||
type
|
||||
CustomTokenAdded* = ref object of Args
|
||||
token*: TokenDto
|
||||
|
||||
type
|
||||
CustomTokenRemoved* = ref object of Args
|
||||
token*: TokenDto
|
||||
|
||||
type
|
||||
VisibilityToggled* = ref object of Args
|
||||
token*: TokenDto
|
||||
|
||||
type
|
||||
TokenHistoricalDataArgs* = ref object of Args
|
||||
result*: string
|
||||
|
@ -72,22 +54,27 @@ QtObject:
|
|||
|
||||
proc init*(self: Service) =
|
||||
try:
|
||||
self.tokens = initTable[NetworkDto, seq[TokenDto]]()
|
||||
let networks = self.networkService.getNetworks()
|
||||
let chainIds = networks.map(n => n.chainId)
|
||||
let responseCustomTokens = backend.getCustomTokens()
|
||||
|
||||
|
||||
for network in networks:
|
||||
var found = false
|
||||
for n in self.tokens.keys:
|
||||
if n.chainId == network.chainId:
|
||||
found = true
|
||||
break
|
||||
|
||||
|
||||
if found:
|
||||
continue
|
||||
|
||||
echo network.chainId
|
||||
let responseTokens = backend.getTokens(network.chainId)
|
||||
let default_tokens = map(
|
||||
responseTokens.result.getElems(),
|
||||
proc(x: JsonNode): TokenDto = x.toTokenDto(network.enabled, hasIcon=true, isCustom=false)
|
||||
)
|
||||
|
||||
self.tokens[network] = concat(
|
||||
default_tokens,
|
||||
map(responseCustomTokens.result.getElems(), proc(x: JsonNode): TokenDto = x.toTokenDto(network.enabled))
|
||||
).filter(
|
||||
self.tokens[network] = default_tokens.filter(
|
||||
proc(x: TokenDto): bool = x.chainId == network.chainId
|
||||
)
|
||||
|
||||
|
@ -99,11 +86,6 @@ QtObject:
|
|||
proc getTokens*(self: Service): Table[NetworkDto, seq[TokenDto]] =
|
||||
return self.tokens
|
||||
|
||||
proc findTokenByName*(self: Service, network: NetworkDto, name: string): TokenDto =
|
||||
for token in self.tokens[network]:
|
||||
if token.name == name:
|
||||
return token
|
||||
|
||||
proc findTokenBySymbol*(self: Service, network: NetworkDto, symbol: string): TokenDto =
|
||||
try:
|
||||
for token in self.tokens[network]:
|
||||
|
@ -117,7 +99,7 @@ QtObject:
|
|||
if token.address == address:
|
||||
return token
|
||||
|
||||
proc findTokenSymbolByAddressInAllNetworks*(self: Service, address: string): string =
|
||||
proc findTokenSymbolByAddress*(self: Service, address: string): string =
|
||||
if address.isEmptyOrWhitespace:
|
||||
return ""
|
||||
|
||||
|
@ -135,74 +117,6 @@ QtObject:
|
|||
return token.symbol
|
||||
return ""
|
||||
|
||||
proc addCustomToken*(self: Service, chainId: int, address: string, name: string, symbol: string, decimals: int): string =
|
||||
# TODO(alaile): use chainId rather than first enabled network
|
||||
let networkWIP = self.networkService.getNetworks()[0]
|
||||
let foundToken = self.findTokenByAddress(networkWIP, parseAddress(address))
|
||||
|
||||
if not foundToken.isNil:
|
||||
return "token already exists"
|
||||
|
||||
let backendToken = backend.Token(
|
||||
name: name, chainId: networkWIP.chainId, address: address, symbol: symbol, decimals: decimals, color: ""
|
||||
)
|
||||
discard backend.addCustomToken(backendToken)
|
||||
let token = newTokenDto(
|
||||
name,
|
||||
networkWIP.chainId,
|
||||
fromHex(Address, address),
|
||||
symbol,
|
||||
decimals,
|
||||
false,
|
||||
true
|
||||
)
|
||||
let network = self.networkService.getNetwork(networkWIP.chainId)
|
||||
self.tokens[network].add(token)
|
||||
self.events.emit("token/customTokenAdded", CustomTokenAdded(token: token))
|
||||
|
||||
proc toggleVisible*(self: Service, chainId: int, address: string) =
|
||||
discard backend.toggleVisibleToken(chainId, address)
|
||||
|
||||
let network = self.networkService.getNetwork(chainId)
|
||||
var tokenChanged = self.tokens[network][0]
|
||||
for token in self.tokens[network]:
|
||||
if token.addressAsString() == address:
|
||||
token.isVisible = not token.isVisible
|
||||
tokenChanged = token
|
||||
break
|
||||
|
||||
self.events.emit("token/visibilityToggled", VisibilityToggled(token: tokenChanged))
|
||||
|
||||
proc removeCustomToken*(self: Service, chainId: int, address: string) =
|
||||
let network = self.networkService.getNetwork(chainId)
|
||||
discard backend.deleteCustomTokenByChainID(chainId, address)
|
||||
var index = -1
|
||||
|
||||
for idx, token in self.tokens[network].pairs():
|
||||
if $token.address == address:
|
||||
index = idx
|
||||
break
|
||||
|
||||
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.} =
|
||||
self.events.emit(SIGNAL_TOKEN_DETAILS_LOADED, TokenDetailsLoadedArgs(
|
||||
tokenDetails: tokenDetails
|
||||
))
|
||||
|
||||
proc getTokenDetails*(self: Service, address: string) =
|
||||
let chainIds = self.networkService.getNetworks().map(n => n.chainId)
|
||||
let arg = GetTokenDetailsTaskArg(
|
||||
tptr: cast[ByteAddress](getTokenDetailsTask),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "tokenDetailsResolved",
|
||||
chainIds: chainIds,
|
||||
address: address
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
|
||||
proc tokenHistoricalDataResolved*(self: Service, response: string) {.slot.} =
|
||||
let responseObj = response.parseJson
|
||||
if (responseObj.kind != JObject):
|
||||
|
|
|
@ -109,339 +109,12 @@ const timerTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
|||
|
||||
type
|
||||
BuildTokensTaskArg = ref object of QObjectTaskArg
|
||||
walletAddresses: seq[string]
|
||||
currency: string
|
||||
networks: seq[NetworkDto]
|
||||
|
||||
proc getCustomTokens(): seq[TokenDto] =
|
||||
try:
|
||||
let responseCustomTokens = backend.getCustomTokens()
|
||||
result = map(responseCustomTokens.result.getElems(), proc(x: JsonNode): TokenDto = x.toTokenDto(true))
|
||||
except Exception as e:
|
||||
error "error fetching custom tokens: ", message = e.msg
|
||||
|
||||
proc getTokensForChainId(network: NetworkDto): seq[TokenDto] =
|
||||
try:
|
||||
let responseTokens = backend.getTokens(network.chainId)
|
||||
let defaultTokens = map(
|
||||
responseTokens.result.getElems(),
|
||||
proc(x: JsonNode): TokenDto = x.toTokenDto(network.enabled, hasIcon=true, isCustom=false)
|
||||
)
|
||||
result.add(defaultTokens)
|
||||
except Exception as e:
|
||||
error "error fetching tokens: ", message = e.msg, chainId=network.chainId
|
||||
|
||||
proc isNetworkEnabledForChainId(networks: seq[NetworkDto], chainId: int): bool =
|
||||
for network in networks:
|
||||
if network.chainId == chainId:
|
||||
return network.enabled
|
||||
|
||||
return false
|
||||
|
||||
proc prepareSymbols(networkSymbols: seq[string], allTokens: seq[TokenDto]): seq[seq[string]] =
|
||||
# we have to use up to 300 characters in a single request when we're fetching prices
|
||||
let charsMaxLenght = 300
|
||||
result.add(@[])
|
||||
var networkSymbolsIndex = 0
|
||||
var tokenSymbolsIndex = 0
|
||||
while networkSymbolsIndex < networkSymbols.len or tokenSymbolsIndex < allTokens.len:
|
||||
var currentCharsLen = 0
|
||||
var reachTheEnd = false
|
||||
while networkSymbolsIndex < networkSymbols.len:
|
||||
if(currentCharsLen + networkSymbols[networkSymbolsIndex].len >= charsMaxLenght):
|
||||
reachTheEnd = true
|
||||
result.add(@[])
|
||||
break
|
||||
else:
|
||||
currentCharsLen += networkSymbols[networkSymbolsIndex].len + 1 # we add one for ','
|
||||
result[result.len - 1].add(networkSymbols[networkSymbolsIndex])
|
||||
networkSymbolsIndex.inc
|
||||
while not reachTheEnd and tokenSymbolsIndex < allTokens.len:
|
||||
if(currentCharsLen + allTokens[tokenSymbolsIndex].symbol.len >= charsMaxLenght):
|
||||
reachTheEnd = true
|
||||
result.add(@[])
|
||||
break
|
||||
else:
|
||||
currentCharsLen += allTokens[tokenSymbolsIndex].symbol.len + 1 # we add one for ','
|
||||
result[result.len - 1].add(allTokens[tokenSymbolsIndex].symbol)
|
||||
tokenSymbolsIndex.inc
|
||||
|
||||
proc fetchNativeChainBalance(chainId: int, nativeCurrencyDecimals: int, accountAddress: string): float64 =
|
||||
result = 0.0
|
||||
try:
|
||||
let nativeBalanceResponse = status_go_eth.getNativeChainBalance(chainId, accountAddress)
|
||||
result = parsefloat(hex2Balance(nativeBalanceResponse.result.getStr, nativeCurrencyDecimals))
|
||||
except Exception as e:
|
||||
error "error getting balance", message = e.msg
|
||||
|
||||
proc fetchPrices(networkSymbols: seq[string], allTokens: seq[TokenDto], currency: string): Table[string, float] =
|
||||
let allSymbols = prepareSymbols(networkSymbols, allTokens)
|
||||
for symbols in allSymbols:
|
||||
if symbols.len == 0:
|
||||
continue
|
||||
|
||||
try:
|
||||
let response = backend.fetchPrices(symbols, currency)
|
||||
for (symbol, value) in response.result.pairs:
|
||||
result[symbol] = value.getFloat
|
||||
except Exception as e:
|
||||
error "error fetching prices: ", message = e.msg
|
||||
|
||||
proc getMarketValues(networkSymbols: seq[string], allTokens: seq[TokenDto], currency: string): Table[string, Table[string, string]] =
|
||||
let allSymbols = prepareSymbols(networkSymbols, allTokens)
|
||||
for symbols in allSymbols:
|
||||
if symbols.len == 0:
|
||||
continue
|
||||
|
||||
try:
|
||||
let response = backend.fetchMarketValues(symbols, currency)
|
||||
for (symbol, marketValue) in response.result.pairs:
|
||||
var marketValues: Table[string, string] = initTable[string, string]()
|
||||
for (key, value) in marketValue.pairs:
|
||||
marketValues[key] = value.getStr()
|
||||
result[symbol] = marketValues
|
||||
except Exception as e:
|
||||
error "error fetching markey values: ", message = e.msg
|
||||
|
||||
proc getTokenDetails(networkSymbols: seq[string], allTokens: seq[TokenDto]): Table[string, Table[string, string]] =
|
||||
let allSymbols = prepareSymbols(networkSymbols, allTokens)
|
||||
for symbols in allSymbols:
|
||||
if symbols.len == 0:
|
||||
continue
|
||||
|
||||
try:
|
||||
let response = backend.fetchTokenDetails(symbols)
|
||||
for (symbol, tokenDetail) in response.result.pairs:
|
||||
var tokenDetails: Table[string, string] = initTable[string, string]()
|
||||
for (key, value) in tokenDetail.pairs:
|
||||
tokenDetails[key] = value.getStr()
|
||||
result[symbol] = tokenDetails
|
||||
except Exception as e:
|
||||
error "error fetching markey values: ", message = e.msg
|
||||
|
||||
proc getTokensBalances(walletAddresses: seq[string], allTokens: seq[TokenDto]): JsonNode =
|
||||
try:
|
||||
result = newJObject()
|
||||
let tokensAddresses = allTokens.map(t => t.addressAsString())
|
||||
# We need to check, we should use `chainIdsFromSettings` instead `chainIds` deduced from the allTokens list?
|
||||
let chainIds = deduplicate(allTokens.map(t => t.chainId))
|
||||
let tokensBalancesResponse = backend.getTokensBalancesForChainIDs(chainIds, walletAddresses, tokensAddresses)
|
||||
result = tokensBalancesResponse.result
|
||||
except Exception as e:
|
||||
error "error fetching tokens balances: ", message = e.msg
|
||||
|
||||
proc groupNetworksBySymbol(networks: seq[NetworkDto]): Table[string, seq[NetworkDto]] =
|
||||
for network in networks:
|
||||
if not result.hasKey(network.nativeCurrencySymbol):
|
||||
result[network.nativeCurrencySymbol] = @[]
|
||||
result[network.nativeCurrencySymbol].add(network)
|
||||
|
||||
proc getNetworkByCurrencySymbol(networks: seq[NetworkDto], networkNativeCurrencySymbol: string): NetworkDto =
|
||||
for network in networks:
|
||||
if network.nativeCurrencySymbol != networkNativeCurrencySymbol:
|
||||
continue
|
||||
return network
|
||||
|
||||
proc groupTokensBySymbol(tokens: seq[TokenDto]): Table[string, seq[TokenDto]] =
|
||||
for token in tokens:
|
||||
if not result.hasKey(token.symbol):
|
||||
result[token.symbol] = @[]
|
||||
result[token.symbol].add(token)
|
||||
|
||||
proc getTokenForSymbol(tokens: seq[TokenDto], symbol: string): TokenDto =
|
||||
for token in tokens:
|
||||
if token.symbol != symbol:
|
||||
continue
|
||||
return token
|
||||
discard
|
||||
|
||||
const prepareTokensTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[BuildTokensTaskArg](argEncoded)
|
||||
|
||||
var networkSymbols: seq[string]
|
||||
var allTokens: seq[TokenDto]
|
||||
|
||||
for network in arg.networks:
|
||||
networkSymbols.add(network.nativeCurrencySymbol)
|
||||
allTokens.add(getTokensForChainId(network))
|
||||
|
||||
allTokens.add(getCustomTokens())
|
||||
allTokens = deduplicate(allTokens)
|
||||
|
||||
var prices = fetchPrices(networkSymbols, allTokens, arg.currency)
|
||||
var marketValues = getMarketValues(networkSymbols, allTokens, arg.currency)
|
||||
var tokenDetails = getTokenDetails(networkSymbols, allTokens)
|
||||
let tokenBalances = getTokensBalances(arg.walletAddresses, allTokens)
|
||||
|
||||
var builtTokensPerAccount = %*{ }
|
||||
for address in arg.walletAddresses:
|
||||
var builtTokens: seq[WalletTokenDto]
|
||||
|
||||
let groupedNetworks = groupNetworksBySymbol(arg.networks)
|
||||
var enabledNetworkBalance = BalanceDto(
|
||||
balance: 0.0,
|
||||
currencyBalance: 0.0
|
||||
)
|
||||
for networkNativeCurrencySymbol, networks in groupedNetworks.pairs:
|
||||
# Reset
|
||||
enabledNetworkBalance = BalanceDto(
|
||||
balance: 0.0,
|
||||
currencyBalance: 0.0
|
||||
)
|
||||
var balancesPerChain = initTable[int, BalanceDto]()
|
||||
for network in networks:
|
||||
let chainBalance = fetchNativeChainBalance(network.chainId, network.nativeCurrencyDecimals, address)
|
||||
balancesPerChain[network.chainId] = BalanceDto(
|
||||
balance: chainBalance,
|
||||
currencyBalance: chainBalance * prices[network.nativeCurrencySymbol],
|
||||
chainId: network.chainId,
|
||||
address: "0x0000000000000000000000000000000000000000",
|
||||
enabled: network.enabled,
|
||||
)
|
||||
if network.enabled:
|
||||
enabledNetworkBalance.balance += balancesPerChain[network.chainId].balance
|
||||
enabledNetworkBalance.currencyBalance += balancesPerChain[network.chainId].currencyBalance
|
||||
|
||||
let networkDto = getNetworkByCurrencySymbol(arg.networks, networkNativeCurrencySymbol)
|
||||
var totalTokenBalance: BalanceDto
|
||||
totalTokenBalance.balance = toSeq(balancesPerChain.values).map(x => x.balance).foldl(a + b)
|
||||
totalTokenBalance.currencyBalance = totalTokenBalance.balance * prices[networkDto.nativeCurrencySymbol]
|
||||
var marketCap: string = ""
|
||||
var highDay: string = ""
|
||||
var lowDay: string = ""
|
||||
var changePctHour: string = ""
|
||||
var changePctDay: string = ""
|
||||
var changePct24hour: string = ""
|
||||
var change24hour: string = ""
|
||||
|
||||
if(marketValues.hasKey(networkDto.nativeCurrencySymbol)):
|
||||
marketCap = marketValues[networkDto.nativeCurrencySymbol]["MKTCAP"]
|
||||
highDay = marketValues[networkDto.nativeCurrencySymbol]["HIGHDAY"]
|
||||
lowDay = marketValues[networkDto.nativeCurrencySymbol]["LOWDAY"]
|
||||
changePctHour = marketValues[networkDto.nativeCurrencySymbol]["CHANGEPCTHOUR"]
|
||||
changePctDay = marketValues[networkDto.nativeCurrencySymbol]["CHANGEPCTDAY"]
|
||||
changePct24hour = marketValues[networkDto.nativeCurrencySymbol]["CHANGEPCT24HOUR"]
|
||||
change24hour = marketValues[networkDto.nativeCurrencySymbol]["CHANGE24HOUR"]
|
||||
|
||||
builtTokens.add(WalletTokenDto(
|
||||
name: networkDto.nativeCurrencyName,
|
||||
symbol: networkDto.nativeCurrencySymbol,
|
||||
decimals: networkDto.nativeCurrencyDecimals,
|
||||
hasIcon: true,
|
||||
color: "blue",
|
||||
isCustom: false,
|
||||
totalBalance: totalTokenBalance,
|
||||
enabledNetworkBalance: enabledNetworkBalance,
|
||||
balancesPerChain: balancesPerChain,
|
||||
visible: networkDto.enabled,
|
||||
description: "Ethereum is a decentralized platform that runs smart contracts (applications that run exactly as programmed without any possibility of downtime, censorship, fraud or third party interference). In the Ethereum protocol and blockchain, there is a price for each operation. In order to have anything transferred or executed by the network, you have to consume or burn Gas. Ethereum’s native cryptocurrency is Ether (ETH) and it is used to pay for computation time and transaction fees.The introductory whitepaper was originally published in 2013 by Vitalik Buterin, the founder of Ethereum, the project was crowdfunded during August 2014 by fans all around the world and launched in 2015. Ethereum is developed and maintained by ETHDEV with contributions from minds across the globe. There is an Ecosystem Support Program which is a branch of the Ethereum Foundation focused on supporting projects and entities within the greater Ethereum community to promote the success and growth of the ecosystem. Multiple startups work with the Ethereum blockchain covering areas in: DeFi, NFTs, Ethereum Name Service, Wallets, Scaling, etc.The launch of Ethereum is a process divided into 4 main phases: Frontier, Homestead, Metropolis and Serenity.Ethereum 2.0, also known as Serenity, is the final phase of Ethereum, it aims to solve the decentralized scaling challenge. A naive way to solve Ethereum's problems would be to make it more centralized. But decentralization is too important, as it gives Ethereum censorship resistance, openness, data privacy and near-unbreakable security.The Eth2 upgrades will make Ethereum scalable, secure, and decentralized. Sharding will make Ethereum more scalable by increasing transactions per second while decreasing the power needed to run a node and validate the chain. The beacon chain will make Ethereum secure by coordinating validators across shards. And staking will lower the barrier to participation, creating a larger – more decentralized – network.The beacon chain will also introduce proof-of-stake to Ethereum. Ethereum is moving to the proof-of-stake (PoS) consensus mechanism from proof-of-work (PoW). This was always the plan as it's a key part of the community's strategy to scale Ethereum via the Eth2 upgrades. However, getting PoS right is a big technical challenge and not as straightforward as using PoW to reach consensus across the networkKeep up with Ethereum upgradesFor ETH holders and Dapp users, this has no impact whatsoever, however, for users wishing to get involved, there are ways to participate in Ethereum and future Eth2-related efforts. Get involved in Eth 2.0Blockchain data provided by: Etherchain (Main Source), Blockchair (Backup), and Etherscan (Total Supply only).",
|
||||
assetWebsiteUrl: "https://www.ethereum.org/",
|
||||
builtOn: "",
|
||||
smartContractAddress: "",
|
||||
marketCap: marketCap,
|
||||
highDay: highDay,
|
||||
lowDay: lowDay,
|
||||
changePctHour: changePctHour,
|
||||
changePctDay: changePctDay,
|
||||
changePct24hour: changePct24hour,
|
||||
change24hour: change24hour,
|
||||
currencyPrice: prices[networkDto.nativeCurrencySymbol],
|
||||
)
|
||||
)
|
||||
|
||||
let groupedTokens = groupTokensBySymbol(allTokens)
|
||||
for symbol, tokens in groupedTokens.pairs:
|
||||
# Reset
|
||||
enabledNetworkBalance = BalanceDto(
|
||||
balance: 0.0,
|
||||
currencyBalance: 0.0
|
||||
)
|
||||
var balancesPerChain = initTable[int, BalanceDto]()
|
||||
var visible = false
|
||||
|
||||
for token in tokens:
|
||||
let balanceForToken = tokenBalances{address}{token.addressAsString()}.getStr
|
||||
let chainBalanceForToken = parsefloat(hex2Balance(balanceForToken, token.decimals))
|
||||
var enabled = false
|
||||
for network in arg.networks:
|
||||
if network.chainId == token.chainId:
|
||||
enabled = true
|
||||
|
||||
balancesPerChain[token.chainId] = BalanceDto(
|
||||
balance: chainBalanceForToken,
|
||||
currencyBalance: chainBalanceForToken * prices[token.symbol],
|
||||
chainId: token.chainId,
|
||||
address: $token.address,
|
||||
enabled: enabled,
|
||||
)
|
||||
if isNetworkEnabledForChainId(arg.networks, token.chainId):
|
||||
visible = true
|
||||
enabledNetworkBalance.balance += balancesPerChain[token.chainId].balance
|
||||
enabledNetworkBalance.currencyBalance += balancesPerChain[token.chainId].currencyBalance
|
||||
|
||||
let tokenDto = getTokenForSymbol(allTokens, symbol)
|
||||
var totalTokenBalance: BalanceDto
|
||||
totalTokenBalance.balance = toSeq(balancesPerChain.values).map(x => x.balance).foldl(a + b)
|
||||
totalTokenBalance.currencyBalance = totalTokenBalance.balance * prices[tokenDto.symbol]
|
||||
var marketCap: string = ""
|
||||
var highDay: string = ""
|
||||
var lowDay: string = ""
|
||||
var changePctHour: string = ""
|
||||
var changePctDay: string = ""
|
||||
var changePct24hour: string = ""
|
||||
var change24hour: string = ""
|
||||
var description: string = ""
|
||||
var assetWebsiteUrl: string = ""
|
||||
var builtOn: string = ""
|
||||
var smartContractAddress: string = ""
|
||||
|
||||
if(tokenDetails.hasKey(tokenDto.symbol)):
|
||||
description = tokenDetails[tokenDto.symbol]["Description"]
|
||||
assetWebsiteUrl = tokenDetails[tokenDto.symbol]["AssetWebsiteUrl"]
|
||||
builtOn = tokenDetails[tokenDto.symbol]["BuiltOn"]
|
||||
smartContractAddress = tokenDetails[tokenDto.symbol]["SmartContractAddress"]
|
||||
|
||||
if(marketValues.hasKey(tokenDto.symbol)):
|
||||
marketCap = marketValues[tokenDto.symbol]["MKTCAP"]
|
||||
highDay = marketValues[tokenDto.symbol]["HIGHDAY"]
|
||||
lowDay = marketValues[tokenDto.symbol]["LOWDAY"]
|
||||
changePctHour = marketValues[tokenDto.symbol]["CHANGEPCTHOUR"]
|
||||
changePctDay = marketValues[tokenDto.symbol]["CHANGEPCTDAY"]
|
||||
changePct24hour = marketValues[tokenDto.symbol]["CHANGEPCT24HOUR"]
|
||||
change24hour = marketValues[tokenDto.symbol]["CHANGE24HOUR"]
|
||||
|
||||
let tokenDescription = description.multiReplace([("|", ""),("Facebook",""),("Telegram",""),("Discord",""),("Youtube",""),("YouTube",""),("Instagram",""),("Reddit",""),("Github",""),("GitHub",""),("Whitepaper",""),("Medium",""),("Weibo",""),("LinkedIn",""),("Litepaper",""),("KakaoTalk",""),("BitcoinTalk",""),("Slack",""),("Docs",""),("Kakao",""),("Gitter","")])
|
||||
builtTokens.add(WalletTokenDto(
|
||||
name: tokenDto.name,
|
||||
symbol: tokenDto.symbol,
|
||||
decimals: tokenDto.decimals,
|
||||
hasIcon: tokenDto.hasIcon,
|
||||
color: tokenDto.color,
|
||||
isCustom: tokenDto.isCustom,
|
||||
totalBalance: totalTokenBalance,
|
||||
balancesPerChain: balancesPerChain,
|
||||
enabledNetworkBalance: enabledNetworkBalance,
|
||||
visible: visible,
|
||||
description: tokenDescription,
|
||||
assetWebsiteUrl: assetWebsiteUrl,
|
||||
builtOn: builtOn,
|
||||
smartContractAddress: smartContractAddress,
|
||||
marketCap: marketCap,
|
||||
highDay: highDay,
|
||||
lowDay: lowDay,
|
||||
changePctHour: changePctHour,
|
||||
changePctDay: changePctDay,
|
||||
changePct24hour: changePct24hour,
|
||||
change24hour: change24hour,
|
||||
currencyPrice: prices[tokenDto.symbol],
|
||||
)
|
||||
)
|
||||
|
||||
var tokensJArray = newJArray()
|
||||
for wtDto in builtTokens:
|
||||
tokensJarray.add(walletTokenDtoToJson(wtDto))
|
||||
builtTokensPerAccount[address] = tokensJArray
|
||||
|
||||
arg.finish(builtTokensPerAccount)
|
||||
let response = backend.getWalletToken()
|
||||
arg.finish(response.result)
|
||||
|
||||
#################################################
|
||||
# Async add migrated keypair
|
||||
|
|
|
@ -8,29 +8,30 @@ const WalletTypeSeed* = "seed"
|
|||
const WalletTypeWatch* = "watch"
|
||||
const WalletTypeKey* = "key"
|
||||
|
||||
var alwaysVisible = {
|
||||
1: @["ETH", "SNT", "DAI"],
|
||||
10: @["ETH", "SNT", "DAI"],
|
||||
42161: @["ETH", "SNT", "DAI"],
|
||||
5: @["ETH", "STT", "DAI"],
|
||||
420: @["ETH", "STT", "DAI"],
|
||||
421613: @["ETH", "STT", "DAI"],
|
||||
}.toTable
|
||||
|
||||
type BalanceDto* = object
|
||||
balance*: float64
|
||||
currencyBalance*: float64
|
||||
address*: string
|
||||
chainId*: int
|
||||
enabled*: bool
|
||||
|
||||
type
|
||||
WalletTokenDto* = object
|
||||
name*: string
|
||||
symbol*: string
|
||||
decimals*: int
|
||||
hasIcon*: bool
|
||||
color*: string
|
||||
isCustom*: bool
|
||||
totalBalance*: BalanceDto
|
||||
enabledNetworkBalance*: BalanceDto
|
||||
balancesPerChain*: Table[int, BalanceDto]
|
||||
visible*: bool
|
||||
description*: string
|
||||
assetWebsiteUrl*: string
|
||||
builtOn*: string
|
||||
smartContractAddress*: string
|
||||
marketCap*: string
|
||||
highDay*: string
|
||||
lowDay*: string
|
||||
|
@ -99,30 +100,67 @@ proc toWalletAccountDto*(jsonObj: JsonNode): WalletAccountDto =
|
|||
discard jsonObj.getProp("emoji", result.emoji)
|
||||
discard jsonObj.getProp("derived-from", result.derivedfrom)
|
||||
|
||||
proc getCurrencyBalance*(self: WalletAccountDto): float64 =
|
||||
return self.tokens.map(t => t.enabledNetworkBalance.currencyBalance).foldl(a + b, 0.0)
|
||||
proc getCurrencyBalance*(self: BalanceDto, currencyPrice: float64): float64 =
|
||||
return self.balance * currencyPrice
|
||||
|
||||
proc getAddress*(self: WalletTokenDto): string =
|
||||
for balance in self.balancesPerChain.values:
|
||||
return balance.address
|
||||
|
||||
return ""
|
||||
|
||||
proc getBalances*(self: WalletTokenDto, chainIds: seq[int]): seq[BalanceDto] =
|
||||
for chainId in chainIds:
|
||||
if self.balancesPerChain.hasKey(chainId):
|
||||
result.add(self.balancesPerChain[chainId])
|
||||
|
||||
proc getCurrencyBalance*(self: WalletTokenDto, chainIds: seq[int]): float64 =
|
||||
var sum = 0.0
|
||||
for chainId in chainIds:
|
||||
if self.balancesPerChain.hasKey(chainId):
|
||||
sum += self.balancesPerChain[chainId].getCurrencyBalance(self.currencyPrice)
|
||||
|
||||
return sum
|
||||
|
||||
proc getVisible*(self: WalletTokenDto, chainIds: seq[int]): bool =
|
||||
for chainId in chainIds:
|
||||
if alwaysVisible.hasKey(chainId) and self.symbol in alwaysVisible[chainId]:
|
||||
return true
|
||||
|
||||
if self.balancesPerChain.hasKey(chainId) and self.balancesPerChain[chainId].balance > 0:
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
proc getCurrencyBalance*(self: WalletAccountDto, chainIds: seq[int]): float64 =
|
||||
return self.tokens.map(t => t.getCurrencyBalance(chainIds)).foldl(a + b, 0.0)
|
||||
|
||||
proc getBalance*(self: WalletTokenDto, chainIds: seq[int]): float64 =
|
||||
var sum = 0.0
|
||||
for chainId in chainIds:
|
||||
if self.balancesPerChain.hasKey(chainId):
|
||||
sum += self.balancesPerChain[chainId].balance
|
||||
|
||||
return sum
|
||||
|
||||
proc getBalance*(self: WalletAccountDto, chainIds: seq[int]): float64 =
|
||||
return self.tokens.map(t => t.getBalance(chainIds)).foldl(a + b, 0.0)
|
||||
|
||||
proc toBalanceDto*(jsonObj: JsonNode): BalanceDto =
|
||||
result = BalanceDto()
|
||||
discard jsonObj.getProp("balance", result.balance)
|
||||
discard jsonObj.getProp("currencyBalance", result.currencyBalance)
|
||||
result.balance = jsonObj{"balance"}.getStr.parseFloat()
|
||||
discard jsonObj.getProp("address", result.address)
|
||||
discard jsonObj.getProp("chainId", result.chainId)
|
||||
discard jsonObj.getProp("enabled", result.enabled)
|
||||
|
||||
proc toWalletTokenDto*(jsonObj: JsonNode): WalletTokenDto =
|
||||
result = WalletTokenDto()
|
||||
discard jsonObj.getProp("name", result.name)
|
||||
discard jsonObj.getProp("symbol", result.symbol)
|
||||
discard jsonObj.getProp("decimals", result.decimals)
|
||||
discard jsonObj.getProp("hasIcon", result.hasIcon)
|
||||
discard jsonObj.getProp("color", result.color)
|
||||
discard jsonObj.getProp("isCustom", result.isCustom)
|
||||
discard jsonObj.getProp("visible", result.visible)
|
||||
discard jsonObj.getProp("description", result.description)
|
||||
discard jsonObj.getProp("assetWebsiteUrl", result.assetWebsiteUrl)
|
||||
discard jsonObj.getProp("builtOn", result.builtOn)
|
||||
discard jsonObj.getProp("smartContractAddress", result.smartContractAddress)
|
||||
discard jsonObj.getProp("marketCap", result.marketCap)
|
||||
discard jsonObj.getProp("highDay", result.highDay)
|
||||
discard jsonObj.getProp("lowDay", result.lowDay)
|
||||
|
@ -132,45 +170,7 @@ proc toWalletTokenDto*(jsonObj: JsonNode): WalletTokenDto =
|
|||
discard jsonObj.getProp("change24hour", result.change24hour)
|
||||
discard jsonObj.getProp("currencyPrice", result.currencyPrice)
|
||||
|
||||
var totalBalanceObj: JsonNode
|
||||
if(jsonObj.getProp("totalBalance", totalBalanceObj)):
|
||||
result.totalBalance = toBalanceDto(totalBalanceObj)
|
||||
|
||||
var enabledNetworkBalanceObj: JsonNode
|
||||
if(jsonObj.getProp("enabledNetworkBalance", enabledNetworkBalanceObj)):
|
||||
result.enabledNetworkBalance = toBalanceDto(enabledNetworkBalanceObj)
|
||||
|
||||
var balancesPerChainObj: JsonNode
|
||||
if(jsonObj.getProp("balancesPerChain", balancesPerChainObj)):
|
||||
for chainId, balanceObj in balancesPerChainObj:
|
||||
result.balancesPerChain[parseInt(chainId)] = toBalanceDto(balanceObj)
|
||||
|
||||
proc walletTokenDtoToJson*(dto: WalletTokenDto): JsonNode =
|
||||
var balancesPerChainJsonObj = newJObject()
|
||||
for k, v in dto.balancesPerChain.pairs:
|
||||
balancesPerChainJsonObj[$k] = %* v
|
||||
|
||||
result = %* {
|
||||
"name": dto.name,
|
||||
"symbol": dto.symbol,
|
||||
"decimals": dto.decimals,
|
||||
"hasIcon": dto.hasIcon,
|
||||
"color": dto.color,
|
||||
"isCustom": dto.isCustom,
|
||||
"totalBalance": %* dto.totalBalance,
|
||||
"enabledNetworkBalance": %* dto.enabledNetworkBalance,
|
||||
"balancesPerChain": balancesPerChainJsonObj,
|
||||
"visible": dto.visible,
|
||||
"description": dto.description,
|
||||
"assetWebsiteUrl": dto.assetWebsiteUrl,
|
||||
"builtOn": dto.builtOn,
|
||||
"smartContractAddress": dto.smartContractAddress,
|
||||
"marketCap": dto.marketCap,
|
||||
"highDay": dto.highDay,
|
||||
"lowDay": dto.lowDay,
|
||||
"changePctHour": dto.changePctHour,
|
||||
"changePctDay": dto.changePctDay,
|
||||
"changePct24hour": dto.changePct24hour,
|
||||
"change24hour": dto.change24hour,
|
||||
"currencyPrice": dto.currencyPrice,
|
||||
}
|
||||
result.balancesPerChain[parseInt(chainId)] = toBalanceDto(balanceObj)
|
|
@ -248,9 +248,6 @@ QtObject:
|
|||
error "error: ", errDescription
|
||||
return
|
||||
|
||||
proc getCurrencyBalance*(self: Service): float64 =
|
||||
return self.getWalletAccounts().map(a => a.getCurrencyBalance()).foldl(a + b, 0.0)
|
||||
|
||||
proc addNewAccountToLocalStore(self: Service) =
|
||||
let accounts = self.fetchAccounts()
|
||||
var newAccount = accounts[0]
|
||||
|
@ -360,21 +357,13 @@ QtObject:
|
|||
self.buildAllTokens()
|
||||
self.events.emit(SIGNAL_WALLET_ACCOUNT_CURRENCY_UPDATED, CurrencyUpdated())
|
||||
|
||||
proc toggleTokenVisible*(self: Service, chainId: int, address: string) =
|
||||
self.tokenService.toggleVisible(chainId, address)
|
||||
self.buildAllTokens()
|
||||
self.events.emit(SIGNAL_WALLET_ACCOUNT_TOKEN_VISIBILITY_UPDATED, TokenVisibilityToggled())
|
||||
|
||||
proc toggleNetworkEnabled*(self: Service, chainId: int) =
|
||||
self.networkService.toggleNetwork(chainId)
|
||||
self.tokenService.init()
|
||||
self.buildAllTokens()
|
||||
self.events.emit(SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED, NetwordkEnabledToggled())
|
||||
|
||||
method toggleTestNetworksEnabled*(self: Service) =
|
||||
discard self.settingsService.toggleTestNetworksEnabled()
|
||||
self.tokenService.init()
|
||||
self.buildAllTokens()
|
||||
self.checkRecentHistory()
|
||||
self.events.emit(SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED, NetwordkEnabledToggled())
|
||||
|
||||
|
@ -488,24 +477,23 @@ QtObject:
|
|||
self.threadpool.start(arg)
|
||||
|
||||
proc onAllTokensBuilt*(self: Service, response: string) {.slot.} =
|
||||
let responseObj = response.parseJson
|
||||
if (responseObj.kind != JObject):
|
||||
info "prepared tokens are not a json object"
|
||||
return
|
||||
try:
|
||||
let responseObj = response.parseJson
|
||||
var data = TokensPerAccountArgs()
|
||||
let walletAddresses = toSeq(self.walletAccounts.keys)
|
||||
for wAddress in walletAddresses:
|
||||
var tokensArr: JsonNode
|
||||
var tokens: seq[WalletTokenDto]
|
||||
if(responseObj.getProp(wAddress, tokensArr)):
|
||||
tokens = map(tokensArr.getElems(), proc(x: JsonNode): WalletTokenDto = x.toWalletTokenDto())
|
||||
|
||||
tokens.sort(priorityTokenCmp)
|
||||
self.walletAccounts[wAddress].tokens = tokens
|
||||
data.accountsTokens[wAddress] = tokens
|
||||
|
||||
var data = TokensPerAccountArgs()
|
||||
let walletAddresses = toSeq(self.walletAccounts.keys)
|
||||
for wAddress in walletAddresses:
|
||||
var tokensArr: JsonNode
|
||||
var tokens: seq[WalletTokenDto]
|
||||
if(responseObj.getProp(wAddress, tokensArr)):
|
||||
tokens = map(tokensArr.getElems(), proc(x: JsonNode): WalletTokenDto = x.toWalletTokenDto())
|
||||
|
||||
tokens.sort(priorityTokenCmp)
|
||||
self.walletAccounts[wAddress].tokens = tokens
|
||||
data.accountsTokens[wAddress] = tokens
|
||||
|
||||
self.events.emit(SIGNAL_WALLET_ACCOUNT_TOKENS_REBUILT, data)
|
||||
self.events.emit(SIGNAL_WALLET_ACCOUNT_TOKENS_REBUILT, data)
|
||||
except Exception as e:
|
||||
error "error: ", procName="onAllTokensBuilt", errName = e.name, errDesription = e.msg
|
||||
|
||||
# run timer again...
|
||||
self.startBuildingTokensTimer()
|
||||
|
@ -520,15 +508,10 @@ QtObject:
|
|||
if not calledFromTimerOrInit:
|
||||
self.ignoreTimeInitiatedTokensBuild = true
|
||||
|
||||
let walletAddresses = toSeq(self.walletAccounts.keys)
|
||||
|
||||
let arg = BuildTokensTaskArg(
|
||||
tptr: cast[ByteAddress](prepareTokensTask),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "onAllTokensBuilt",
|
||||
walletAddresses: walletAddresses,
|
||||
currency: self.settingsService.getCurrency(),
|
||||
networks: self.networkService.getNetworks()
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
|
||||
|
@ -537,34 +520,18 @@ QtObject:
|
|||
|
||||
proc getNetworkCurrencyBalance*(self: Service, network: NetworkDto): float64 =
|
||||
for walletAccount in toSeq(self.walletAccounts.values):
|
||||
for token in walletAccount.tokens:
|
||||
if token.balancesPerChain.hasKey(network.chainId):
|
||||
let balance = token.balancesPerChain[network.chainId]
|
||||
result += balance.currencyBalance
|
||||
|
||||
result += walletAccount.getCurrencyBalance(@[network.chainId])
|
||||
|
||||
proc findTokenSymbolByAddress*(self: Service, address: string): string =
|
||||
return self.tokenService.findTokenSymbolByAddressInAllNetworks(address)
|
||||
return self.tokenService.findTokenSymbolByAddress(address)
|
||||
|
||||
proc fetchBalanceForAddress*(self: Service, address: string): float64 =
|
||||
let currency = self.settingsService.getCurrency()
|
||||
let networks = self.networkService.getNetworks()
|
||||
var networkSymbols: seq[string]
|
||||
var allTokens: seq[TokenDto]
|
||||
for n in networks:
|
||||
networkSymbols.add(n.nativeCurrencySymbol)
|
||||
allTokens.add(getTokensForChainId(n))
|
||||
allTokens.add(getCustomTokens())
|
||||
allTokens = deduplicate(allTokens)
|
||||
proc getCurrencyBalanceForAddress*(self: Service, address: string): float64 =
|
||||
let chainIds = self.networkService.getNetworks().map(n => n.chainId)
|
||||
return self.walletAccounts[address].getCurrencyBalance(chainIds)
|
||||
|
||||
var prices = fetchPrices(networkSymbols, allTokens, currency)
|
||||
let tokenBalances = getTokensBalances(@[address], allTokens)
|
||||
|
||||
var totalBalance = 0.0
|
||||
for token in allTokens:
|
||||
let balanceForToken = tokenBalances{address}{token.addressAsString()}.getStr
|
||||
let chainBalanceForToken = parsefloat(hex2Balance(balanceForToken, token.decimals))
|
||||
totalBalance = totalBalance + chainBalanceForToken * prices[token.symbol]
|
||||
return totalBalance
|
||||
proc getTotalCurrencyBalance*(self: Service): float64 =
|
||||
let chainIds = self.networkService.getNetworks().filter(a => a.enabled).map(a => a.chainId)
|
||||
return self.getWalletAccounts().map(a => a.getCurrencyBalance(chainIds)).foldl(a + b, 0.0)
|
||||
|
||||
proc responseHasNoErrors(self: Service, procName: string, response: RpcResponse[JsonNode]): bool =
|
||||
var errMsg = ""
|
||||
|
|
|
@ -48,16 +48,6 @@ type
|
|||
rpc(clientVersion, "web3"):
|
||||
discard
|
||||
|
||||
rpc(getCustomTokens, "wallet"):
|
||||
discard
|
||||
|
||||
rpc(deleteCustomTokenByChainID, "wallet"):
|
||||
chainId: int
|
||||
address: string
|
||||
|
||||
rpc(addCustomToken, "wallet"):
|
||||
token: Token
|
||||
|
||||
rpc(getOpenseaCollectionsByOwner, "wallet"):
|
||||
chainId: int
|
||||
address: string
|
||||
|
@ -95,16 +85,11 @@ rpc(getTokensBalancesForChainIDs, "wallet"):
|
|||
accounts: seq[string]
|
||||
tokens: seq[string]
|
||||
|
||||
rpc(discoverToken, "wallet"):
|
||||
chainId: int
|
||||
address: string
|
||||
|
||||
rpc(getPendingTransactionsByChainIDs, "wallet"):
|
||||
chainIds: seq[int]
|
||||
|
||||
rpc(toggleVisibleToken, "wallet"):
|
||||
chainId: int
|
||||
address: string
|
||||
rpc(getWalletToken, "wallet"):
|
||||
discard
|
||||
|
||||
rpc(getTransactionEstimatedTime, "wallet"):
|
||||
chainId: int
|
||||
|
|
|
@ -1,172 +0,0 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Dialogs 1.3
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
import shared.controls 1.0
|
||||
import "../stores"
|
||||
|
||||
StatusModal {
|
||||
id: popup
|
||||
|
||||
property bool editable: true
|
||||
property int marginBetweenInputs: 35
|
||||
property string validationError: ""
|
||||
property WalletStore walletStore
|
||||
|
||||
header.title: editable ?
|
||||
qsTr("Add custom token")
|
||||
: nameInput.text
|
||||
|
||||
x: Math.round(((parent ? parent.width : 0) - width) / 2)
|
||||
y: Math.round(((parent ? parent.height : 0) - height) / 2)
|
||||
|
||||
height: editable ? 450 : 380
|
||||
|
||||
onOpened: {
|
||||
addressInput.forceActiveFocus(Qt.MouseFocusReason)
|
||||
}
|
||||
|
||||
function openEditable(){
|
||||
addressInput.text = "";
|
||||
nameInput.text = "";
|
||||
symbolInput.text = "";
|
||||
decimalsInput.text = "";
|
||||
editable = true;
|
||||
open();
|
||||
}
|
||||
|
||||
function openWithData(chainId, address, name, symbol, decimals){
|
||||
addressInput.text = address;
|
||||
nameInput.text = name;
|
||||
symbolInput.text = symbol;
|
||||
decimalsInput.text = decimals;
|
||||
editable = false;
|
||||
open();
|
||||
}
|
||||
|
||||
|
||||
function validate() {
|
||||
if (addressInput.text !== "" && !Utils.isAddress(addressInput.text)) {
|
||||
validationError = qsTr("This needs to be a valid address");
|
||||
}
|
||||
return validationError === ""
|
||||
}
|
||||
|
||||
property var getTokenDetails: Backpressure.debounce(popup, 500, function (tokenAddress){
|
||||
popup.walletStore.walletTokensModule.getTokenDetails(tokenAddress)
|
||||
});
|
||||
|
||||
function onKeyReleased(){
|
||||
validationError = "";
|
||||
if (!validate() || addressInput.text === "") {
|
||||
return;
|
||||
}
|
||||
Qt.callLater(getTokenDetails, addressInput.text)
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: popup.walletStore.walletTokensModule
|
||||
onTokenDetailsWereResolved: {
|
||||
const jsonObj = JSON.parse(tokenDetails)
|
||||
if (jsonObj.error) {
|
||||
validationError = jsonObj.error
|
||||
return
|
||||
}
|
||||
if (jsonObj.name === "" && jsonObj.symbol === "" && jsonObj.decimals === "") {
|
||||
validationError = qsTr("Invalid ERC20 address")
|
||||
return;
|
||||
}
|
||||
|
||||
if (addressInput.text.toLowerCase() === jsonObj.address.toLowerCase()) {
|
||||
symbolInput.text = jsonObj.symbol;
|
||||
decimalsInput.text = jsonObj.decimals;
|
||||
nameInput.text = jsonObj.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: Style.current.padding
|
||||
anchors.rightMargin: Style.current.padding
|
||||
Input {
|
||||
id: addressInput
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
readOnly: !editable
|
||||
textField.maximumLength: 42
|
||||
placeholderText: qsTr("Enter contract address...")
|
||||
label: qsTr("Contract address")
|
||||
validationError: popup.validationError
|
||||
Keys.onReleased: onKeyReleased()
|
||||
}
|
||||
|
||||
Input {
|
||||
id: nameInput
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: addressInput.bottom
|
||||
anchors.topMargin: marginBetweenInputs
|
||||
readOnly: !editable
|
||||
placeholderText: qsTr("The name of your token...")
|
||||
label: qsTr("Name")
|
||||
}
|
||||
|
||||
Input {
|
||||
id: symbolInput
|
||||
readOnly: !editable
|
||||
placeholderText: qsTr("ABC")
|
||||
label: qsTr("Symbol")
|
||||
anchors.top: nameInput.bottom
|
||||
anchors.topMargin: marginBetweenInputs
|
||||
anchors.left: parent.left
|
||||
anchors.right: undefined
|
||||
width: parent.width / 2 - 20
|
||||
}
|
||||
|
||||
Input {
|
||||
id: decimalsInput
|
||||
readOnly: !editable
|
||||
placeholderText: "18"
|
||||
label: qsTr("Decimals")
|
||||
text: "18"
|
||||
anchors.top: nameInput.bottom
|
||||
anchors.topMargin: marginBetweenInputs
|
||||
anchors.right: parent.right
|
||||
anchors.left: undefined
|
||||
width: parent.width / 2 - 20
|
||||
}
|
||||
}
|
||||
|
||||
MessageDialog {
|
||||
id: changeError
|
||||
title: qsTr("Changing settings failed")
|
||||
icon: StandardIcon.Critical
|
||||
standardButtons: StandardButton.Ok
|
||||
}
|
||||
|
||||
rightButtons: [
|
||||
StatusButton {
|
||||
text: qsTr("Add")
|
||||
enabled: validationError === "" && addressInput.text !== "" && nameInput.text !== "" && symbolInput.text !== "" && decimalsInput.text !== ""
|
||||
visible: editable
|
||||
onClicked: {
|
||||
const error = popup.walletStore.addCustomToken(0, addressInput.text, nameInput.text, symbolInput.text, decimalsInput.text);
|
||||
|
||||
if (error) {
|
||||
Global.playErrorSound();
|
||||
changeError.text = error;
|
||||
changeError.open();
|
||||
return;
|
||||
}
|
||||
popup.close();
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
import "../panels"
|
||||
import "../stores"
|
||||
|
||||
StatusModal {
|
||||
id: popup
|
||||
x: Math.round(((parent ? parent.width : 0) - width) / 2)
|
||||
y: Math.round(((parent ? parent.height : 0) - height) / 2)
|
||||
height: 480
|
||||
property WalletStore walletStore
|
||||
header.title: qsTr("Manage Assets")
|
||||
|
||||
rightButtons: [
|
||||
StatusButton {
|
||||
text: qsTr("Add custom token")
|
||||
onClicked: {
|
||||
addShowTokenModal.openEditable();
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
contentItem: TokenSettingsModalContent {
|
||||
id: settingsModalContent
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: Style.current.padding
|
||||
anchors.rightMargin: Style.current.padding
|
||||
defaultTokenList: walletStore.defaultTokenList
|
||||
customTokenList: walletStore.customTokenList
|
||||
|
||||
onToggleVisibleClicked: {
|
||||
walletStore.toggleVisible(chainId, address)
|
||||
}
|
||||
onRemoveCustomTokenTriggered: {
|
||||
walletStore.removeCustomToken(chainId, address)
|
||||
}
|
||||
onShowTokenDetailsTriggered: {
|
||||
addShowTokenModal.openWithData(chainId, address, name, symbol, decimals);
|
||||
}
|
||||
|
||||
AddShowTokenModal{
|
||||
id: addShowTokenModal
|
||||
walletStore: root.walletStore
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,25 +21,9 @@ QtObject {
|
|||
property var importedAccounts: walletSectionAccounts.imported
|
||||
property var generatedAccounts: walletSectionAccounts.generated
|
||||
property var watchOnlyAccounts: walletSectionAccounts.watchOnly
|
||||
property var walletTokensModule: walletSectionAllTokens
|
||||
property var defaultTokenList: walletSectionAllTokens.default
|
||||
property var customTokenList: walletSectionAllTokens.custom
|
||||
|
||||
|
||||
property var currencyStore: SharedStore.RootStore.currencyStore
|
||||
|
||||
function addCustomToken(chainId, address, name, symbol, decimals) {
|
||||
return walletSectionAllTokens.addCustomToken(chainId, address, name, symbol, decimals)
|
||||
}
|
||||
|
||||
function toggleVisible(chainId, address) {
|
||||
walletSectionAllTokens.toggleVisible(chainId, address)
|
||||
}
|
||||
|
||||
function removeCustomToken(chainId, address) {
|
||||
walletSectionAllTokens.removeCustomToken(chainId, address)
|
||||
}
|
||||
|
||||
property var currentAccount: walletSectionCurrent
|
||||
|
||||
function switchAccountByAddress(address) {
|
||||
|
|
|
@ -20,33 +20,6 @@ Column {
|
|||
signal goToAccountView(address: string)
|
||||
signal goToDappPermissionsView()
|
||||
|
||||
// Temporary commented, we need to bring it back after MVP
|
||||
// https://github.com/status-im/status-desktop/issues/5856
|
||||
|
||||
// StatusListItem {
|
||||
// title: qsTr("Manage Assets & List")
|
||||
// height: 64
|
||||
// width: parent.width
|
||||
// onClicked: Global.openPopup(tokenSettingsModalComponent)
|
||||
// components: [
|
||||
// StatusIcon {
|
||||
// icon: "chevron-down"
|
||||
// rotation: 270
|
||||
// color: Theme.palette.baseColor1
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
|
||||
Component {
|
||||
id: tokenSettingsModalComponent
|
||||
TokenSettingsModal {
|
||||
walletStore: root.walletStore
|
||||
onClosed: {
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Separator {
|
||||
height: 17
|
||||
}
|
||||
|
|
|
@ -31,9 +31,6 @@ QtObject {
|
|||
property string signingPhrase: walletSection.signingPhrase
|
||||
property string mnemonicBackedUp: walletSection.isMnemonicBackedUp
|
||||
|
||||
property var walletTokensModule: walletSectionAllTokens
|
||||
property var tokens: walletSectionAllTokens.all
|
||||
|
||||
property var collectionList: walletSectionCollectiblesCollections.model
|
||||
property var collectibleLists: walletSectionCollectiblesCollectibles.model
|
||||
property var currentCollectible: walletSectionCollectibleCurrent
|
||||
|
|
|
@ -10,11 +10,6 @@ Item {
|
|||
id: assetDelegate
|
||||
objectName: symbol
|
||||
|
||||
QtObject {
|
||||
id: _internal
|
||||
readonly property var alwaysVisible : ["ETH", "SNT", "DAI", "STT"]
|
||||
}
|
||||
|
||||
property string locale: ""
|
||||
property string currency: ""
|
||||
property string currencySymbol: ""
|
||||
|
@ -22,7 +17,7 @@ Item {
|
|||
anchors.right: parent.right
|
||||
|
||||
anchors.left: parent.left
|
||||
visible: _internal.alwaysVisible.includes(symbol) || (networkVisible && enabledNetworkBalance > 0)
|
||||
visible: networkVisible
|
||||
height: visible ? 40 + 2 * Style.current.padding : 0
|
||||
|
||||
Image {
|
||||
|
|
|
@ -77,7 +77,6 @@ Control {
|
|||
id: chainRepeater
|
||||
model: balances ? balances : null
|
||||
delegate: InformationTag {
|
||||
visible: model.enabled
|
||||
tagPrimaryLabel.text: model.balance
|
||||
tagPrimaryLabel.color: root.getNetworkColor(model.chainId)
|
||||
image.source: Style.svg("tiny/%1".arg(root.getNetworkIcon(model.chainId)))
|
||||
|
|
|
@ -76,7 +76,9 @@ Item {
|
|||
ExpressionFilter {
|
||||
expression: {
|
||||
var tokenSymbolByAddress = searchTokenSymbolByAddressFn(d.searchString)
|
||||
return symbol.startsWith(d.searchString.toUpperCase()) || name.toUpperCase().startsWith(d.searchString.toUpperCase()) || (tokenSymbolByAddress!=="" && symbol.startsWith(tokenSymbolByAddress))
|
||||
return networkVisible && (
|
||||
symbol.startsWith(d.searchString.toUpperCase()) || name.toUpperCase().startsWith(d.searchString.toUpperCase()) || (tokenSymbolByAddress!=="" && symbol.startsWith(tokenSymbolByAddress))
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -39,10 +39,6 @@ QtObject {
|
|||
property bool isNonArchivalNode: history.isNonArchivalNode
|
||||
|
||||
property var currentAccount: walletSectionCurrent
|
||||
property var walletTokensModule: walletSectionAllTokens
|
||||
property var tokens: walletSectionAllTokens.all
|
||||
property var accounts: walletSectionAccounts.model
|
||||
|
||||
property var marketValueStore: TokenMarketValuesStore{}
|
||||
|
||||
function getNetworkColor(chainId) {
|
||||
|
|
|
@ -374,10 +374,10 @@ Item {
|
|||
|
||||
image.source: token && token.builtOn !== "" ? Style.svg("tiny/" + RootStore.getNetworkIconUrl(token.builtOn)) : ""
|
||||
tagPrimaryLabel.text: token && token.builtOn !== "" ? RootStore.getNetworkName(token.builtOn) : "---"
|
||||
tagSecondaryLabel.text: token && token.smartContractAddress !== "" ? token.smartContractAddress : "---"
|
||||
tagSecondaryLabel.text: token && token.address !== "" ? token.address : "---"
|
||||
controlBackground.color: Theme.palette.baseColor2
|
||||
controlBackground.border.color: "transparent"
|
||||
visible: typeof token != "undefined" && token && token.builtOn !== "" && token.smartContractAddress !== ""
|
||||
visible: typeof token != "undefined" && token && token.builtOn !== "" && token.address !== ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ Item {
|
|||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property var alwaysVisible : ["ETH", "SNT", "DAI", "STT"]
|
||||
property int selectedAssetIndex: -1
|
||||
}
|
||||
|
||||
|
@ -37,7 +36,7 @@ Item {
|
|||
sourceModel: account.assets
|
||||
filters: [
|
||||
ExpressionFilter {
|
||||
expression: d.alwaysVisible.includes(symbol) || (networkVisible && enabledNetworkBalance > 0)
|
||||
expression: networkVisible
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 194f26f3b4503494702be4e8148a166f61730c4d
|
||||
Subproject commit eff02a79a986611fd4ef0302a59ac8c86e250641
|
Loading…
Reference in New Issue