From 826c0ed46df335d1621bcf7a83f8295e47a20fe4 Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Mon, 8 Jun 2020 09:55:18 -0400 Subject: [PATCH] get token balance get token balance fix token balance call Fix assets on load add token list display images cleanup cleanup cleanup clean up --- src/app/wallet/views/asset_list.nim | 5 +- src/status/libstatus/accounts.nim | 41 +- src/status/libstatus/tokens.nim | 29 +- src/status/libstatus/wallet.nim | 12 - src/status/wallet.nim | 131 +-- src/status/wallet/account.nim | 16 + src/status/wallet/balance_manager.nim | 67 ++ src/status/wallet/token_list.nim | 1333 ++++++++++++++++++++++++ ui/app/AppLayouts/Wallet/AssetsTab.qml | 2 +- ui/app/img/tokens/ETH.png | Bin 0 -> 870 bytes ui/app/img/tokens/ETH@2x.png | Bin 0 -> 1623 bytes ui/app/img/tokens/ETH@3x.png | Bin 0 -> 2377 bytes 12 files changed, 1496 insertions(+), 140 deletions(-) create mode 100644 src/status/wallet/account.nim create mode 100644 src/status/wallet/balance_manager.nim create mode 100644 src/status/wallet/token_list.nim create mode 100644 ui/app/img/tokens/ETH.png create mode 100644 ui/app/img/tokens/ETH@2x.png create mode 100644 ui/app/img/tokens/ETH@3x.png diff --git a/src/app/wallet/views/asset_list.nim b/src/app/wallet/views/asset_list.nim index 648ec4a239..5c3082df6c 100644 --- a/src/app/wallet/views/asset_list.nim +++ b/src/app/wallet/views/asset_list.nim @@ -9,6 +9,7 @@ type Value = UserRole + 3, FiatValue = UserRole + 4, Image = UserRole + 5 + HasIcon = UserRole + 6 QtObject: type AssetList* = ref object of QAbstractListModel @@ -41,13 +42,15 @@ QtObject: of AssetRoles.Value: result = newQVariant(asset.value) of AssetRoles.FiatValue: result = newQVariant(asset.fiatValue) of AssetRoles.Image: result = newQVariant(asset.image) + of AssetRoles.HasIcon: result = newQVariant(asset.hasIcon) method roleNames(self: AssetList): Table[int, string] = { AssetRoles.Name.int:"name", AssetRoles.Symbol.int:"symbol", AssetRoles.Value.int:"value", AssetRoles.FiatValue.int:"fiatValue", - AssetRoles.Image.int:"image" }.toTable + AssetRoles.Image.int:"image", + AssetRoles.Image.int:"hasIcon" }.toTable proc addAssetToList*(self: AssetList, asset: Asset) = self.beginInsertRows(newQModelIndex(), self.assets.len, self.assets.len) diff --git a/src/status/libstatus/accounts.nim b/src/status/libstatus/accounts.nim index f5aaff30d0..f1be3034b6 100644 --- a/src/status/libstatus/accounts.nim +++ b/src/status/libstatus/accounts.nim @@ -183,29 +183,32 @@ proc MultiAccountImportPrivateKey*(privateKey: string): GeneratedAccount = result = Json.decode(importResult, GeneratedAccount) proc saveAccount*(account: GeneratedAccount, password: string, color: string, accountType: string, isADerivedAccount = true): DerivedAccount = - # Only store derived accounts. Private key accounts are not multiaccounts - if (isADerivedAccount): - discard storeDerivedAccounts(account, password) + try: + # Only store derived accounts. Private key accounts are not multiaccounts + if (isADerivedAccount): + discard storeDerivedAccounts(account, password) - var address = account.derived.defaultWallet.address - var publicKey = account.derived.defaultWallet.publicKey + var address = account.derived.defaultWallet.address + var publicKey = account.derived.defaultWallet.publicKey - if (address == ""): - address = account.address - publicKey = account.publicKey + if (address == ""): + address = account.address + publicKey = account.publicKey - discard callPrivateRPC("accounts_saveAccounts", %* [ - [{ - "color": color, - "name": account.name, - "address": address, - "public-key": publicKey, - "type": accountType, - "path": "m/44'/60'/0'/0/1" - }] - ]) + discard callPrivateRPC("accounts_saveAccounts", %* [ + [{ + "color": color, + "name": account.name, + "address": address, + "public-key": publicKey, + "type": accountType, + "path": "m/44'/60'/0'/0/1" + }] + ]) - result = DerivedAccount(address: address, publicKey: publicKey) + result = DerivedAccount(address: address, publicKey: publicKey) + except: + error "Error storing the new account. Bad password?" proc deriveAccounts*(accountId: string): MultiAccounts = let deriveJson = %* { diff --git a/src/status/libstatus/tokens.nim b/src/status/libstatus/tokens.nim index 864cf4bc6e..8ca1cdd2d8 100644 --- a/src/status/libstatus/tokens.nim +++ b/src/status/libstatus/tokens.nim @@ -1,6 +1,10 @@ import core as status import json import chronicles +import strformat +import stint +import strutils +import wallet logScope: topics = "wallet" @@ -12,13 +16,13 @@ proc getCustomTokens*(): JsonNode = return %* [] return response["result"] -proc addCustomToken*(address: string, name: string, symbol: string, decimals: int, color: string): string = +proc addCustomToken*(address: string, name: string, symbol: string, decimals: int, color: string) = let payload = %* [{"address": address, "name": name, "symbol": symbol, "decimals": decimals, "color": color}] - status.callPrivateRPC("wallet_addCustomToken", payload) + discard status.callPrivateRPC("wallet_addCustomToken", payload) -proc removeCustomToken*(address: string): string = +proc removeCustomToken*(address: string) = let payload = %* [address] - status.callPrivateRPC("wallet_deleteCustomToken", payload) + discard status.callPrivateRPC("wallet_deleteCustomToken", payload) proc getTokensBalances*(accounts: openArray[string], tokens: openArray[string]): JsonNode = let payload = %* [accounts, tokens] @@ -26,3 +30,20 @@ proc getTokensBalances*(accounts: openArray[string], tokens: openArray[string]): if response["result"].kind == JNull: return %* {} response["result"] + +proc getTokenBalance*(tokenAddress: string, account: string): string = + var postfixedAccount: string = account + postfixedAccount.removePrefix("0x") + let payload = %* [{ + "to": tokenAddress, "from": account, "data": fmt"0x70a08231000000000000000000000000{postfixedAccount}" + }, "latest"] + var response = status.callPrivateRPC("eth_call", payload) + var balance = response.parseJson["result"].getStr + result = $hex2Eth(balance) + +proc addOrRemoveToken*(enable: bool, address: string, name: string, symbol: string, decimals: int, color: string): JsonNode = + if enable: + addCustomToken(address, name, symbol, decimals, color) + else: + removeCustomToken(address) + getCustomTokens() diff --git a/src/status/libstatus/wallet.nim b/src/status/libstatus/wallet.nim index ed8fa963a0..0c0870bc1c 100644 --- a/src/status/libstatus/wallet.nim +++ b/src/status/libstatus/wallet.nim @@ -34,7 +34,6 @@ proc getWalletAccounts*(): seq[WalletAccount] = let msg = getCurrentExceptionMsg() error "Failed getting wallet accounts", msg - proc sendTransaction*(from_address: string, to: string, value: string, password: string): string = var args = %* { "value": fmt"0x{toHex(value)}", @@ -44,17 +43,6 @@ proc sendTransaction*(from_address: string, to: string, value: string, password: var response = status.sendTransaction($args, password) result = response -proc getPrice*(crypto: string, fiat: string): string = - var url: string = fmt"https://min-api.cryptocompare.com/data/price?fsym={crypto}&tsyms={fiat}" - let client = newHttpClient() - client.headers = newHttpHeaders({ "Content-Type": "application/json" }) - - try: - let response = client.request(url) - result = $parseJson(response.body)[fiat.toUpper] - except: - echo "error getting price" - proc getBalance*(address: string): string = let payload = %* [address, "latest"] parseJson(status.callPrivateRPC("eth_getBalance", payload))["result"].str diff --git a/src/status/wallet.nim b/src/status/wallet.nim index 8b7709c9fc..8a9fb85f5d 100644 --- a/src/status/wallet.nim +++ b/src/status/wallet.nim @@ -1,28 +1,14 @@ -import eventemitter -import json -import strformat -import strutils -import libstatus/wallet as status_wallet -import libstatus/settings as status_settings +import eventemitter, json, strformat, strutils, tables, chronicles, sequtils import libstatus/accounts as status_accounts -import libstatus/accounts/constants as constants -import libstatus/types -import chronicles import libstatus/tokens as status_tokens - -type CurrencyArgs* = ref object of Args - currency*: string - -type Asset* = ref object - name*, symbol*, value*, fiatValue*, image*: string - -type Account* = ref object - name*, address*, iconColor*, balance*: string - realFiatBalance*: float - assetList*: seq[Asset] - -type AccountArgs* = ref object of Args - account*: Account +import libstatus/settings as status_settings +import libstatus/wallet as status_wallet +import libstatus/accounts/constants as constants +from libstatus/types import GeneratedAccount, DerivedAccount +import wallet/token_list +import wallet/balance_manager +import wallet/account +export account type WalletModel* = ref object events*: EventEmitter @@ -30,7 +16,6 @@ type WalletModel* = ref object defaultCurrency*: string tokens*: JsonNode -proc updateBalance*(self: Account) proc getDefaultCurrency*(self: WalletModel): string proc newWalletModel*(events: EventEmitter): WalletModel = @@ -44,7 +29,7 @@ proc initEvents*(self: WalletModel) = self.events.on("currencyChanged") do(e: Args): self.defaultCurrency = self.getDefaultCurrency() for account in self.accounts: - account.updateBalance() + updateBalance(account, self.getDefaultCurrency()) self.events.emit("accountsUpdated", Args()) proc delete*(self: WalletModel) = @@ -53,80 +38,34 @@ proc delete*(self: WalletModel) = proc sendTransaction*(self: WalletModel, from_value: string, to: string, value: string, password: string): string = status_wallet.sendTransaction(from_value, to, value, password) -proc getEthBalance*(address: string): string = - var balance = status_wallet.getBalance(address) - echo(fmt"balance in hex: {balance}") - - # 2. convert balance to eth - var eth_value = status_wallet.hex2Eth(balance) - echo(fmt"balance in eth: {eth_value}") - eth_value - -proc getDefaultCurrency*(): string = - status_settings.getSettings().parseJSON()["result"]["currency"].getStr - proc getDefaultCurrency*(self: WalletModel): string = - getDefaultCurrency() + status_settings.getSettings().parseJSON()["result"]["currency"].getStr proc setDefaultCurrency*(self: WalletModel, currency: string) = discard status_settings.saveSettings("currency", currency) self.events.emit("currencyChanged", CurrencyArgs(currency: currency)) -proc getFiatValue*(eth_balance: string, symbol: string, fiat_symbol: string): float = - if eth_balance == "0.0": return 0.0 - # 3. get usd price of 1 eth - var fiat_eth_price = status_wallet.getPrice("ETH", fiat_symbol) - echo(fmt"fiat_price: {fiat_eth_price}") - - # 4. convert balance to usd - var fiat_balance = parseFloat(eth_balance) * parseFloat(fiat_eth_price) - echo(fmt"balance in usd: {fiat_balance}") - fiat_balance - -proc hasAsset*(self: WalletModel, account: string, symbol: string): bool = - for token in self.tokens: - if symbol == token["symbol"].getStr: - return true - return false - -proc updateBalance*(self: Account) = - let defaultCurrency = getDefaultCurrency() - const symbol = "ETH" - let eth_balance = getEthBalance(self.address) - let usd_balance = getFiatValue(eth_balance, symbol, defaultCurrency) - var totalAccountBalance = usd_balance - self.balance = fmt"{totalAccountBalance:.2f} {defaultCurrency}" - proc generateAccountConfiguredAssets*(self: WalletModel): seq[Asset] = var assets: seq[Asset] = @[] - var symbol = "ETH" - var asset = Asset(name:"Ethereum", symbol: symbol, value: fmt"0.0", fiatValue: "$" & fmt"0.0", image: fmt"../../img/token-icons/{toLowerAscii(symbol)}.svg") + var asset = Asset(name:"Ethereum", symbol: "ETH", value: "0.0", fiatValue: "0.0", image: fmt"../../img/token-icons/eth.svg", hasIcon: true) assets.add(asset) for token in self.tokens: var symbol = token["symbol"].getStr - var existingToken = Asset(name: token["name"].getStr, symbol: symbol, value: fmt"0.0", fiatValue: "$0.0", image: fmt"../../img/token-icons/{toLowerAscii(symbol)}.svg") + var existingToken = Asset(name: token["name"].getStr, symbol: symbol, value: fmt"0.0", fiatValue: "$0.0", image: fmt"../../img/token-icons/{toLowerAscii(symbol)}.svg", hasIcon: true) assets.add(existingToken) assets +proc newAccount*(self: WalletModel, name: string, address: string, iconColor: string, balance: string): Account = + var assets: seq[Asset] = self.generateAccountConfiguredAssets() + var account = Account(name: name, address: address, iconColor: iconColor, balance: fmt"{balance} {self.defaultCurrency}", assetList: assets, realFiatBalance: 0.0) + updateBalance(account, self.getDefaultCurrency()) + account + proc initAccounts*(self: WalletModel) = self.tokens = status_tokens.getCustomTokens() let accounts = status_wallet.getWalletAccounts() - - var totalAccountBalance: float = 0 - const symbol = "ETH" - let defaultCurrency = getDefaultCurrency() - for account in accounts: - let address = account.address - let eth_balance = getEthBalance(address) - let usd_balance = getFiatValue(eth_balance, symbol, defaultCurrency) - - totalAccountBalance = totalAccountBalance + usd_balance - - var assets: seq[Asset] = self.generateAccountConfiguredAssets() - - var account = Account(name: account.name, address: address, iconColor: account.color, balance: "", assetList: assets, realFiatBalance: totalAccountBalance) - account.updateBalance() + var account = self.newAccount(account.name, account.address, account.color, "") self.accounts.add(account) proc getTotalFiatBalance*(self: WalletModel): string = @@ -135,21 +74,8 @@ proc getTotalFiatBalance*(self: WalletModel): string = proc addNewGeneratedAccount(self: WalletModel, generatedAccount: GeneratedAccount, password: string, accountName: string, color: string, accountType: string, isADerivedAccount = true) = generatedAccount.name = accountName - - var derivedAccount: DerivedAccount - try: - derivedAccount = status_accounts.saveAccount(generatedAccount, password, color, accountType, isADerivedAccount) - except: - error "Error storing the new account. Bad password?" - return - - # TODO actually fetch the balance for accounts that are not generated - var symbol = "SNT" - var asset = Asset(name:"Status", symbol: symbol, value: fmt"0.0", fiatValue: "$" & fmt"0.0", image: fmt"../../img/token-icons/{toLowerAscii(symbol)}.svg") - - var assets: seq[Asset] = self.generateAccountConfiguredAssets() - var account = Account(name: accountName, address: derivedAccount.address, iconColor: color, balance: fmt"0.00 {self.defaultCurrency}", assetList: assets, realFiatBalance: 0.0) - + var derivedAccount: DerivedAccount = status_accounts.saveAccount(generatedAccount, password, color, accountType, isADerivedAccount) + var account = self.newAccount(accountName, derivedAccount.address, color, fmt"0.00 {self.defaultCurrency}") self.accounts.add(account) self.events.emit("newAccountAdded", AccountArgs(account: account)) @@ -171,13 +97,12 @@ proc addWatchOnlyAccount*(self: WalletModel, address: string, accountName: strin let account = GeneratedAccount(address: address) self.addNewGeneratedAccount(account, "", accountName, color, constants.WATCH, false) +proc hasAsset*(self: WalletModel, account: string, symbol: string): bool = + self.tokens.anyIt(it["symbol"].getStr == symbol) + proc toggleAsset*(self: WalletModel, symbol: string, enable: bool, address: string, name: string, decimals: int, color: string) = - if enable: - discard status_tokens.addCustomToken(address, name, symbol, decimals, color) - else: - discard status_tokens.removeCustomToken(address) - self.tokens = status_tokens.getCustomTokens() + self.tokens = addOrRemoveToken(enable, address, name, symbol, decimals, color) for account in self.accounts: - var assets: seq[Asset] = self.generateAccountConfiguredAssets() - account.assetList = assets + account.assetList = self.generateAccountConfiguredAssets() + updateBalance(account, self.getDefaultCurrency()) self.events.emit("assetChanged", Args()) diff --git a/src/status/wallet/account.nim b/src/status/wallet/account.nim new file mode 100644 index 0000000000..1728c8e1fa --- /dev/null +++ b/src/status/wallet/account.nim @@ -0,0 +1,16 @@ +import eventemitter + +type CurrencyArgs* = ref object of Args + currency*: string + +type Asset* = ref object + name*, symbol*, value*, fiatValue*, image*: string + hasIcon*: bool + +type Account* = ref object + name*, address*, iconColor*, balance*: string + realFiatBalance*: float + assetList*: seq[Asset] + +type AccountArgs* = ref object of Args + account*: Account diff --git a/src/status/wallet/balance_manager.nim b/src/status/wallet/balance_manager.nim new file mode 100644 index 0000000000..3f7a51c656 --- /dev/null +++ b/src/status/wallet/balance_manager.nim @@ -0,0 +1,67 @@ +import tables, strformat, strutils, stint, httpclient, json +import ../libstatus/wallet as status_wallet +import ../libstatus/tokens as status_tokens +import account +import token_list + +type BalanceManager* = ref object + pricePairs: Table[string, string] + tokenBalances: Table[string, string] + +proc newBalanceManager*(): BalanceManager = + result = BalanceManager() + result.pricePairs = initTable[string, string]() + result.tokenBalances = initTable[string, string]() + +var balanceManager = newBalanceManager() + +proc getPrice(crypto: string, fiat: string): string = + try: + if balanceManager.pricePairs.hasKey(fiat): + return balanceManager.pricePairs[fiat] + var url: string = fmt"https://min-api.cryptocompare.com/data/price?fsym={crypto}&tsyms={fiat}" + echo url + let client = newHttpClient() + client.headers = newHttpHeaders({ "Content-Type": "application/json" }) + + let response = client.request(url) + echo $response.body + result = $parseJson(response.body)[fiat.toUpper] + balanceManager.pricePairs[fiat] = result + except Exception as e: + echo "error getting price" + echo e.msg + +proc getEthBalance(address: string): string = + var balance = status_wallet.getBalance(address) + result = status_wallet.hex2Eth(balance) + balanceManager.tokenBalances["ETH"] = result + +proc getBalance*(symbol: string, accountAddress: string): string = + if balanceManager.tokenBalances.hasKey(symbol): + return balanceManager.tokenBalances[symbol] + + if symbol == "ETH": + return getEthBalance(accountAddress) + var token: AssetConfig = getTokenConfig(symbol) + result = $status_tokens.getTokenBalance(token.address, accountAddress) + balanceManager.tokenBalances[symbol] = result + +proc getFiatValue*(crypto_balance: string, crypto_symbol: string, fiat_symbol: string): float = + if crypto_balance == "0.0": return 0.0 + var fiat_crypto_price = getPrice(crypto_symbol, fiat_symbol) + parseFloat(crypto_balance) * parseFloat(fiat_crypto_price) + +proc updateBalance*(asset: Asset, currency: string) = + var token_balance = getBalance(asset.symbol, "0xf977814e90da44bfa03b6295a0616a897441acec") + let fiat_balance = getFiatValue(token_balance, asset.symbol, currency) + asset.value = token_balance + asset.fiatValue = fmt"{fiat_Balance:.2f} {currency}" + +proc updateBalance*(account: Account, currency: string) = + let eth_balance = getBalance("ETH", account.address) + let usd_balance = getFiatValue(eth_balance, "ETH", currency) + var totalAccountBalance = usd_balance + account.balance = fmt"{totalAccountBalance:.2f} {currency}" + for asset in account.assetList: + updateBalance(asset, currency) diff --git a/src/status/wallet/token_list.nim b/src/status/wallet/token_list.nim new file mode 100644 index 0000000000..c5fb38457e --- /dev/null +++ b/src/status/wallet/token_list.nim @@ -0,0 +1,1333 @@ +import tables +import strutils + +type AssetConfig* = ref object + symbol*, name*, address*: string + hasIcon*: bool + decimals*: int + +# TODO: can be simplified with either ensuring the token list is ordered +# or creating a table with a struct +proc toAssetConfig*(self: openArray[tuple]): AssetConfig = + result = AssetConfig() + for element in self: + if element[0] == "symbol": + result.symbol = element[1] + if element[0] == "name": + result.name = element[1] + if element[0] == "address": + result.address = element[1] + if element[0] == "hasIcon": + result.hasIcon = (element[1] == "true") + if element[0] == "decimals": + result.decimals = parseInt(element[1]) + +var tokenList* = { + "DAI": { + "symbol": "DAI", + "name": "Dai Stablecoin", + "address": "0x6b175474e89094c44da98b954eedeac495271d0f", + "decimals": "18", + "hasIcon": "true" + }, + + "SAI": { + "symbol": "SAI", + "name": "Sai Stablecoin v1.0", + "address": "0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359", + "decimals": "18", + "hasIcon": "true" + }, + + "MKR": { + "symbol": "MKR", + "name": "MKR", + "address": "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2", + "decimals": "18", + "hasIcon": "true" + }, + + "EOS": { + "symbol": "EOS", + "name": "EOS", + "address": "0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0", + "decimals": "18", + "hasIcon": "true" + }, + + "OMG": { + "symbol": "OMG", + "name": "OMGToken", + "address": "0xd26114cd6ee289accf82350c8d8487fedb8a0c07", + "decimals": "18", + "hasIcon": "true" + }, + + "PPT": { + "symbol": "PPT", + "name": "Populous Platform", + "address": "0xd4fa1460f537bb9085d22c7bccb5dd450ef28e3a", + "decimals": "8", + "hasIcon": "true" + }, + + "REP": { + "symbol": "REP", + "name": "Reputation", + "address": "0x1985365e9f78359a9b6ad760e32412f4a445e862", + "decimals": "18", + "hasIcon": "true" + }, + + "POWR": { + "symbol": "POWR", + "name": "PowerLedger", + "address": "0x595832f8fc6bf59c85c527fec3740a1b7a361269", + "decimals": "6", + "hasIcon": "true" + }, + + "PAY": { + "symbol": "PAY", + "name": "TenX Pay Token", + "address": "0xb97048628db6b661d4c2aa833e95dbe1a905b280", + "decimals": "18", + "hasIcon": "true" + }, + + "VRS": { + "symbol": "VRS", + "name": "Veros", + "address": "0x92e78dae1315067a8819efd6dca432de9dcde2e9", + "decimals": "6", + "hasIcon": "false" + }, + + "GNT": { + "symbol": "GNT", + "name": "Golem Network Token", + "address": "0xa74476443119a942de498590fe1f2454d7d4ac0d", + "decimals": "18", + "hasIcon": "true" + }, + + "SALT": { + "symbol": "SALT", + "name": "Salt", + "address": "0x4156d3342d5c385a87d264f90653733592000581", + "decimals": "8", + "hasIcon": "true" + }, + + "BNB": { + "symbol": "BNB", + "name": "BNB", + "address": "0xb8c77482e45f1f44de1745f52c74426c631bdd52", + "decimals": "18", + "hasIcon": "true" + }, + + "BAT": { + "symbol": "BAT", + "name": "Basic Attention Token", + "address": "0x0d8775f648430679a709e98d2b0cb6250d2887ef", + "decimals": "18", + "hasIcon": "true" + }, + + "KNC": { + "symbol": "KNC", + "name": "Kyber Network Crystal", + "address": "0xdd974d5c2e2928dea5f71b9825b8b646686bd200", + "decimals": "18", + "hasIcon": "true" + }, + + "BTU": { + "symbol": "BTU", + "name": "BTU Protocol", + "address": "0xb683D83a532e2Cb7DFa5275eED3698436371cc9f", + "decimals": "18", + "hasIcon": "true" + }, + + # TODO: unsupported for now + # "DGD": { + # "symbol": "DGD", + # "name": "Digix DAO", + # "address": "0xe0b7927c4af23765cb51314a0e0521a9645f0e2a", + # "decimals": "9", + # "skipDecimalsCheck": "true", + # "hasIcon": "true" + # }, + + "AE": { + "symbol": "AE", + "name": "Aeternity", + "address": "0x5ca9a71b1d01849c0a95490cc00559717fcf0d1d", + "decimals": "18", + "hasIcon": "true" + }, + + "TRX": { + "symbol": "TRX", + "name": "Tronix", + "address": "0xf230b790e05390fc8295f4d3f60332c93bed42e2", + "decimals": "6", + "hasIcon": "true" + }, + + "ETHOS": { + "symbol": "ETHOS", + "name": "Ethos", + "address": "0x5af2be193a6abca9c8817001f45744777db30756", + "decimals": "8", + "hasIcon": "true" + }, + + "RDN": { + "symbol": "RDN", + "name": "Raiden Token", + "address": "0x255aa6df07540cb5d3d297f0d0d4d84cb52bc8e6", + "decimals": "18", + "hasIcon": "true" + }, + + "SNT": { + "symbol": "SNT", + "name": "Status Network Token", + "address": "0x744d70fdbe2ba4cf95131626614a1763df805b9e", + "decimals": "18", + "hasIcon": "true" + }, + + "SNGLS": { + "symbol": "SNGLS", + "name": "SingularDTV", + "address": "0xaec2e87e0a235266d9c5adc9deb4b2e29b54d009", + "decimals": "0", + "hasIcon": "true" + }, + + "GNO": { + "symbol": "GNO", + "name": "Gnosis Token", + "address": "0x6810e776880c02933d47db1b9fc05908e5386b96", + "decimals": "18", + "hasIcon": "true" + }, + + "STORJ": { + "symbol": "STORJ", + "name": "StorjToken", + "address": "0xb64ef51c888972c908cfacf59b47c1afbc0ab8ac", + "decimals": "8", + "hasIcon": "true" + }, + + "ADX": { + "symbol": "ADX", + "name": "AdEx", + "address": "0x4470bb87d77b963a013db939be332f927f2b992e", + "decimals": "4", + "hasIcon": "false" + }, + + "FUN": { + "symbol": "FUN", + "name": "FunFair", + "address": "0x419d0d8bdd9af5e606ae2232ed285aff190e711b", + "decimals": "8", + "hasIcon": "true" + }, + + "CVC": { + "symbol": "CVC", + "name": "Civic", + "address": "0x41e5560054824ea6b0732e656e3ad64e20e94e45", + "decimals": "8", + "hasIcon": "true" + }, + + "ICN": { + "symbol": "ICN", + "name": "ICONOMI", + "address": "0x888666ca69e0f178ded6d75b5726cee99a87d698", + "decimals": "18", + "hasIcon": "true" + }, + + "WTC": { + "symbol": "WTC", + "name": "Walton Token", + "address": "0xb7cb1c96db6b22b0d3d9536e0108d062bd488f74", + "decimals": "18", + "hasIcon": "true" + }, + + "BTM": { + "symbol": "BTM", + "name": "Bytom", + "address": "0xcb97e65f07da24d46bcdd078ebebd7c6e6e3d750", + "decimals": "8", + "hasIcon": "true" + }, + + "ZRX": { + "symbol": "ZRX", + "name": "0x Protocol Token", + "address": "0xe41d2489571d322189246dafa5ebde1f4699f498", + "decimals": "18", + "hasIcon": "true" + }, + + "BNT": { + "symbol": "BNT", + "name": "Bancor Network Token", + "address": "0x1f573d6fb3f13d689ff844b4ce37794d79a7ff1c", + "decimals": "18", + "hasIcon": "true" + }, + + "MTL": { + "symbol": "MTL", + "name": "Metal", + "address": "0xf433089366899d83a9f26a773d59ec7ecf30355e", + "decimals": "8", + "hasIcon": "false" + }, + + "PPP": { + "symbol": "PPP", + "name": "PayPie", + "address": "0xc42209accc14029c1012fb5680d95fbd6036e2a0", + "decimals": "18", + "hasIcon": "true" + }, + + "LINK": { + "symbol": "LINK", + "name": "ChainLink Token", + "address": "0x514910771af9ca656af840dff83e8264ecf986ca", + "decimals": "18", + "hasIcon": "true" + }, + + "KIN": { + "symbol": "KIN", + "name": "Kin", + "address": "0x818fc6c2ec5986bc6e2cbf00939d90556ab12ce5", + "decimals": "18", + "hasIcon": "true" + }, + + "ANT": { + "symbol": "ANT", + "name": "Aragon Network Token", + "address": "0x960b236a07cf122663c4303350609a66a7b288c0", + "decimals": "18", + "hasIcon": "true" + }, + + "MGO": { + "symbol": "MGO", + "name": "MobileGo Token", + "address": "0x40395044ac3c0c57051906da938b54bd6557f212", + "decimals": "8", + "hasIcon": "true" + }, + + "MCO": { + "symbol": "MCO", + "name": "Monaco", + "address": "0xb63b606ac810a52cca15e44bb630fd42d8d1d83d", + "decimals": "8", + "hasIcon": "true" + }, + + # TODO: unsupported for now + # "LRC": { + # "symbol": "LRC", + # "name": "loopring", + # "address": "0xef68e7c694f40c8202821edf525de3782458639f", + # "decimals": "18", + # "skipDecimalsCheck": "true", + # "hasIcon": "true" + # }, + + "ZSC": { + "symbol": "ZSC", + "name": "Zeus Shield Coin", + "address": "0x7a41e0517a5eca4fdbc7fbeba4d4c47b9ff6dc63", + "decimals": "18", + "hasIcon": "true" + }, + + "DATA": { + "symbol": "DATA", + "name": "Streamr DATAcoin", + "address": "0x0cf0ee63788a0849fe5297f3407f701e122cc023", + "decimals": "18", + "hasIcon": "true" + }, + + "RCN": { + "symbol": "RCN", + "name": "Ripio Credit Network Token", + "address": "0xf970b8e36e23f7fc3fd752eea86f8be8d83375a6", + "decimals": "18", + "hasIcon": "true" + }, + + "WINGS": { + "symbol": "WINGS", + "name": "WINGS", + "address": "0x667088b212ce3d06a1b553a7221e1fd19000d9af", + "decimals": "18", + "hasIcon": "true" + }, + + "EDG": { + "symbol": "EDG", + "name": "Edgeless", + "address": "0x08711d3b02c8758f2fb3ab4e80228418a7f8e39c", + "decimals": "0", + "hasIcon": "true" + }, + + "MLN": { + "symbol": "MLN", + "name": "Melon Token", + "address": "0xbeb9ef514a379b997e0798fdcc901ee474b6d9a1", + "decimals": "18", + "hasIcon": "true" + }, + + "MDA": { + "symbol": "MDA", + "name": "Moeda Loyalty Points", + "address": "0x51db5ad35c671a87207d88fc11d593ac0c8415bd", + "decimals": "18", + "hasIcon": "true" + }, + + "PLR": { + "symbol": "PLR", + "name": "PILLAR", + "address": "0xe3818504c1b32bf1557b16c238b2e01fd3149c17", + "decimals": "18", + "hasIcon": "true" + }, + + "QRL": { + "symbol": "QRL", + "name": "QRL", + "address": "0x697beac28b09e122c4332d163985e8a73121b97f", + "decimals": "8", + "hasIcon": "true" + }, + + "MOD": { + "symbol": "MOD", + "name": "Modum Token", + "address": "0x957c30ab0426e0c93cd8241e2c60392d08c6ac8e", + "decimals": "0", + "hasIcon": "true" + }, + + "TAAS": { + "symbol": "TAAS", + "name": "Token-as-a-Service", + "address": "0xe7775a6e9bcf904eb39da2b68c5efb4f9360e08c", + "decimals": "6", + "hasIcon": "true" + }, + + "GRID": { + "symbol": "GRID", + "name": "GRID Token", + "address": "0x12b19d3e2ccc14da04fae33e63652ce469b3f2fd", + "decimals": "12", + "hasIcon": "true" + }, + + "SAN": { + "symbol": "SAN", + "name": "SANtiment network token", + "address": "0x7c5a0ce9267ed19b22f8cae653f198e3e8daf098", + "decimals": "18", + "hasIcon": "true" + }, + + "SNM": { + "symbol": "SNM", + "name": "SONM Token", + "address": "0x983f6d60db79ea8ca4eb9968c6aff8cfa04b3c63", + "decimals": "18", + "hasIcon": "true" + }, + + "REQ": { + "symbol": "REQ", + "name": "Request Token", + "address": "0x8f8221afbb33998d8584a2b05749ba73c37a938a", + "decimals": "18", + "hasIcon": "true" + }, + + "SUB": { + "symbol": "SUB", + "name": "Substratum", + "address": "0x12480e24eb5bec1a9d4369cab6a80cad3c0a377a", + "decimals": "2", + "hasIcon": "true" + }, + + "MANA": { + "symbol": "MANA", + "name": "Decentraland MANA", + "address": "0x0f5d2fb29fb7d3cfee444a200298f468908cc942", + "decimals": "18", + "hasIcon": "true" + }, + + "AST": { + "symbol": "AST", + "name": "AirSwap Token", + "address": "0x27054b13b1b798b345b591a4d22e6562d47ea75a", + "decimals": "4", + "hasIcon": "true" + }, + + "R": { + "symbol": "R", + "name": "R token", + "address": "0x48f775efbe4f5ece6e0df2f7b5932df56823b990", + "decimals": "0", + "hasIcon": "true" + }, + + "1ST": { + "symbol": "1ST", + "name": "FirstBlood Token", + "address": "0xaf30d2a7e90d7dc361c8c4585e9bb7d2f6f15bc7", + "decimals": "18", + "hasIcon": "true" + }, + + "CFI": { + "symbol": "CFI", + "name": "Cofoundit", + "address": "0x12fef5e57bf45873cd9b62e9dbd7bfb99e32d73e", + "decimals": "18", + "hasIcon": "true" + }, + + "ENG": { + "symbol": "ENG", + "name": "Enigma", + "address": "0xf0ee6b27b759c9893ce4f094b49ad28fd15a23e4", + "decimals": "8", + "hasIcon": "true" + }, + + "AMB": { + "symbol": "AMB", + "name": "Amber Token", + "address": "0x4dc3643dbc642b72c158e7f3d2ff232df61cb6ce", + "decimals": "18", + "hasIcon": "true" + }, + + "XPA": { + "symbol": "XPA", + "name": "XPlay Token", + "address": "0x90528aeb3a2b736b780fd1b6c478bb7e1d643170", + "decimals": "18", + "hasIcon": "true" + }, + + "OTN": { + "symbol": "OTN", + "name": "Open Trading Network", + "address": "0x881ef48211982d01e2cb7092c915e647cd40d85c", + "decimals": "18", + "hasIcon": "true" + }, + + "TRST": { + "symbol": "TRST", + "name": "Trustcoin", + "address": "0xcb94be6f13a1182e4a4b6140cb7bf2025d28e41b", + "decimals": "6", + "hasIcon": "true" + }, + + "TKN": { + "symbol": "TKN", + "name": "Monolith TKN", + "address": "0xaaaf91d9b90df800df4f55c205fd6989c977e73a", + "decimals": "8", + "hasIcon": "true" + }, + + "RHOC": { + "symbol": "RHOC", + "name": "RHOC", + "address": "0x168296bb09e24a88805cb9c33356536b980d3fc5", + "decimals": "8", + "hasIcon": "true" + }, + + "TGT": { + "symbol": "TGT", + "name": "Target Coin", + "address": "0xac3da587eac229c9896d919abc235ca4fd7f72c1", + "decimals": "1", + "hasIcon": "false" + }, + + "EVX": { + "symbol": "EVX", + "name": "Everex", + "address": "0xf3db5fa2c66b7af3eb0c0b782510816cbe4813b8", + "decimals": "4", + "hasIcon": "true" + }, + + "ICOS": { + "symbol": "ICOS", + "name": "ICOS", + "address": "0x014b50466590340d41307cc54dcee990c8d58aa8", + "decimals": "6", + "hasIcon": "true" + }, + + "DNT": { + "symbol": "DNT", + "name": "district0x Network Token", + "address": "0x0abdace70d3790235af448c88547603b945604ea", + "decimals": "18", + "hasIcon": "true" + }, + + "٨": { + "symbol": "٨", + "name": "Dentacoin", + "address": "0x08d32b0da63e2c3bcf8019c9c5d849d7a9d791e6", + "decimals": "0", + "hasIcon": "false" + }, + + "EDO": { + "symbol": "EDO", + "name": "Eidoo Token", + "address": "0xced4e93198734ddaff8492d525bd258d49eb388e", + "decimals": "18", + "hasIcon": "true" + }, + + "CSNO": { + "symbol": "CSNO", + "name": "BitDice", + "address": "0x29d75277ac7f0335b2165d0895e8725cbf658d73", + "decimals": "8", + "hasIcon": "false" + }, + + "COB": { + "symbol": "COB", + "name": "Cobinhood Token", + "address": "0xb2f7eb1f2c37645be61d73953035360e768d81e6", + "decimals": "18", + "hasIcon": "true" + }, + + "ENJ": { + "symbol": "ENJ", + "name": "Enjin Coin", + "address": "0xf629cbd94d3791c9250152bd8dfbdf380e2a3b9c", + "decimals": "18", + "hasIcon": "false" + }, + + "AVT": { + "symbol": "AVT", + "name": "AVENTUS", + "address": "0x0d88ed6e74bbfd96b831231638b66c05571e824f", + "decimals": "18", + "hasIcon": "false" + }, + + "TIME": { + "symbol": "TIME", + "name": "Chronobank TIME", + "address": "0x6531f133e6deebe7f2dce5a0441aa7ef330b4e53", + "decimals": "8", + "hasIcon": "false" + }, + + "CND": { + "symbol": "CND", + "name": "Cindicator Token", + "address": "0xd4c435f5b09f855c3317c8524cb1f586e42795fa", + "decimals": "18", + "hasIcon": "true" + }, + + "STX": { + "symbol": "STX", + "name": "Stox", + "address": "0x006bea43baa3f7a6f765f14f10a1a1b08334ef45", + "decimals": "18", + "hasIcon": "true" + }, + + "XAUR": { + "symbol": "XAUR", + "name": "Xaurum", + "address": "0x4df812f6064def1e5e029f1ca858777cc98d2d81", + "decimals": "8", + "hasIcon": "true" + }, + + "VIB": { + "symbol": "VIB", + "name": "Vibe", + "address": "0x2c974b2d0ba1716e644c1fc59982a89ddd2ff724", + "decimals": "18", + "hasIcon": "true" + }, + + "PRG": { + "symbol": "PRG", + "name": "PRG", + "address": "0x7728dfef5abd468669eb7f9b48a7f70a501ed29d", + "decimals": "6", + "hasIcon": "false" + }, + + "DPY": { + "symbol": "DPY", + "name": "Delphy Token", + "address": "0x6c2adc2073994fb2ccc5032cc2906fa221e9b391", + "decimals": "18", + "hasIcon": "true" + }, + + "CDT": { + "symbol": "CDT", + "name": "CoinDash Token", + "address": "0x2fe6ab85ebbf7776fee46d191ee4cea322cecf51", + "decimals": "18", + "hasIcon": "true" + }, + + "TNT": { + "symbol": "TNT", + "name": "Tierion Network Token", + "address": "0x08f5a9235b08173b7569f83645d2c7fb55e8ccd8", + "decimals": "8", + "hasIcon": "true" + }, + + "DRT": { + "symbol": "DRT", + "name": "DomRaiderToken", + "address": "0x9af4f26941677c706cfecf6d3379ff01bb85d5ab", + "decimals": "8", + "hasIcon": "true" + }, + + "SPANK": { + "symbol": "SPANK", + "name": "SPANK", + "address": "0x42d6622dece394b54999fbd73d108123806f6a18", + "decimals": "18", + "hasIcon": "true" + }, + + "BRLN": { + "symbol": "BRLN", + "name": "Berlin Coin", + "address": "0x80046305aaab08f6033b56a360c184391165dc2d", + "decimals": "18", + "hasIcon": "true" + }, + + "USDC": { + "symbol": "USDC", + "name": "USD//C", + "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "decimals": "6", + "hasIcon": "true" + }, + + "LPT": { + "symbol": "LPT", + "name": "Livepeer Token", + "address": "0x58b6a8a3302369daec383334672404ee733ab239", + "decimals": "18", + "hasIcon": "true" + }, + + "ST": { + "symbol": "ST", + "name": "Simple Token", + "address": "0x2c4e8f2d746113d0696ce89b35f0d8bf88e0aeca", + "decimals": "18", + "hasIcon": "true" + }, + + "WBTC": { + "symbol": "WBTC", + "name": "Wrapped BTC", + "address": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599", + "decimals": "8", + "hasIcon": "true" + }, + + "BLT": { + "symbol": "BLT", + "name": "Bloom Token", + "address": "0x107c4504cd79c5d2696ea0030a8dd4e92601b82e", + "decimals": "18", + "hasIcon": "true" + }, + + # NOTE(goranjovic): the following tokens are collectibles + + "CK": { + "symbol": "CK", + "nft": "true", + "name": "CryptoKitties", + "address": "0x06012c8cf97bead5deae237070f9587f8e7a266d", + "hasIcon": "true" + }, + + "EMONA": { + "symbol": "EMONA", + "nft": "true", + "name": "EtheremonAsset", + "address": "0xb2c0782ae4a299f7358758b2d15da9bf29e1dd99", + "hasIcon": "true" + }, + + "STRK": { + "symbol": "STRK", + "nft": "true", + "name": "CryptoStrikers", + "address": "0xdcaad9fd9a74144d226dbf94ce6162ca9f09ed7e", + "hasIcon": "true" + }, + + "SUPR": { + "symbol": "SUPR", + "nft": "true", + "name": "SupeRare", + "address": "0x41a322b28d0ff354040e2cbc676f0320d8c8850d", + "hasIcon": "true" + }, + + "KDO": { + "symbol": "KDO", + "nft": "true", + "name": "KudosToken", + "address": "0x2aea4add166ebf38b63d09a75de1a7b94aa24163", + "hasIcon": "true" + }, + + "QSP": { + "symbol": "QSP", + "name": "Quantstamp Token", + "address": "0x99ea4dB9EE77ACD40B119BD1dC4E33e1C070b80d", + "decimals": "18", + "hasIcon": "true" + }, + + "LEND": { + "address": "0x80fB784B7eD66730e8b1DBd9820aFD29931aab03", + "decimals": "18", + "symbol": "LEND", + "name": "EHTLend", + "hasIcon": "false" + }, + + "NPXS": { + "address": "0xA15C7Ebe1f07CaF6bFF097D8a589fb8AC49Ae5B3", + "decimals": "18", + "symbol": "NPXS", + "name": "Pundi X Token", + "hasIcon": "false" + }, + + "LOOM": { + "address": "0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0", + "decimals": "18", + "symbol": "LOOM", + "name": "Loom Network", + "hasIcon": "false" + }, + + "POE": { + "address": "0x0e0989b1f9B8A38983c2BA8053269Ca62Ec9B195", + "decimals": "8", + "symbol": "POE", + "name": "Po.et Tokens", + "hasIcon": "false" + }, + + "BLZ": { + "address": "0x5732046A883704404F284Ce41FfADd5b007FD668", + "decimals": "18", + "symbol": "BLZ", + "name": "Bluzelle", + "hasIcon": "false" + }, + + "IOST": { + "address": "0xFA1a856Cfa3409CFa145Fa4e20Eb270dF3EB21ab", + "decimals": "18", + "symbol": "IOST", + "name": "IOSToken", + "hasIcon": "false" + }, + + "NMR": { + "address": "0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671", + "decimals": "18", + "symbol": "NMR", + "name": "Numerai", + "hasIcon": "true" + }, + + "PAX": { + "address": "0x8E870D67F660D95d5be530380D0eC0bd388289E1", + "decimals": "18", + "symbol": "PAX", + "name": "Paxos Standard (PAX)", + "hasIcon": "false" + }, + + "DCN": { + "address": "0x08d32b0da63e2C3bcF8019c9c5d849d7a9d791e6", + "decimals": "0", + "symbol": "DCN", + "name": "Dentacoin", + "hasIcon": "true" + }, + + "QKC": { + "address": "0xEA26c4aC16D4a5A106820BC8AEE85fd0b7b2b664", + "decimals": "18", + "symbol": "QKC", + "name": "QuarkChain", + "hasIcon": "false" + }, + + "PAXG": { + "address": "0x45804880De22913dAFE09f4980848ECE6EcbAf78", + "decimals": "18", + "symbol": "PAXG", + "name": "Paxos Gold", + "hasIcon": "false" + }, + + "MOC": { + "address": "0x865ec58b06bF6305B886793AA20A2da31D034E68", + "decimals": "18", + "symbol": "MOC", + "name": "Moss Coin", + "hasIcon": "false" + }, + + "REN": { + "address": "0x408e41876cCCDC0F92210600ef50372656052a38", + "decimals": "18", + "symbol": "REN", + "name": "Republic Token", + "hasIcon": "false" + }, + + "RLC": { + "address": "0x607F4C5BB672230e8672085532f7e901544a7375", + "decimals": "9", + "symbol": "RLC", + "name": "IEx.ec", + "hasIcon": "true" + }, + + "UBT": { + "address": "0x8400D94A5cb0fa0D041a3788e395285d61c9ee5e", + "decimals": "8", + "symbol": "UBT", + "name": "Unibright", + "hasIcon": "false" + }, + + "DGX": { + "address": "0x4f3AfEC4E5a3F2A6a1A411DEF7D7dFe50eE057bF", + "decimals": "9", + "symbol": "DGX", + "name": "Digix Gold Token", + "hasIcon": "false" + }, + + "FUEL": { + "address": "0xEA38eAa3C86c8F9B751533Ba2E562deb9acDED40", + "decimals": "18", + "symbol": "FUEL", + "name": "Etherparty FUEL", + "hasIcon": "true" + }, + + "TCAD": { + "address": "0x00000100F2A2bd000715001920eB70D229700085", + "decimals": "18", + "symbol": "TCAD", + "name": "TrueCAD", + "hasIcon": "false" + }, + + "MFG": { + "address": "0x6710c63432A2De02954fc0f851db07146a6c0312", + "decimals": "18", + "symbol": "MFG", + "name": "SyncFab Smart Manufacturing Blockchain", + "hasIcon": "false" + }, + + "GEN": { + "address": "0x543Ff227F64Aa17eA132Bf9886cAb5DB55DCAddf", + "decimals": "18", + "symbol": "GEN", + "name": "DAOstack", + "hasIcon": "false" + }, + + "ABYSS": { + "address": "0x0E8d6b471e332F140e7d9dbB99E5E3822F728DA6", + "decimals": "18", + "symbol": "ABYSS", + "name": "The Abyss", + "hasIcon": "false" + }, + + "NEXO": { + "address": "0xB62132e35a6c13ee1EE0f84dC5d40bad8d815206", + "decimals": "18", + "symbol": "NEXO", + "name": "Nexo", + "hasIcon": "false" + }, + + "TUSD": { + "address": "0x0000000000085d4780B73119b644AE5ecd22b376", + "decimals": "18", + "symbol": "TUSD", + "name": "TrueUSD", + "hasIcon": "false" + }, + + "STORM": { + "address": "0xD0a4b8946Cb52f0661273bfbC6fD0E0C75Fc6433", + "decimals": "18", + "symbol": "STORM", + "name": "Storm Token", + "hasIcon": "false" + }, + + "MTH": { + "address": "0xaF4DcE16Da2877f8c9e00544c93B62Ac40631F16", + "decimals": "5", + "symbol": "MTH", + "name": "Monetha", + "hasIcon": "true" + }, + + "TGBP": { + "address": "0x00000000441378008EA67F4284A57932B1c000a5", + "decimals": "18", + "symbol": "TGBP", + "name": "TrueGBP", + "hasIcon": "false" + }, + + "ELF": { + "address": "0xbf2179859fc6D5BEE9Bf9158632Dc51678a4100e", + "decimals": "18", + "symbol": "ELF", + "name": "ELF Token", + "hasIcon": "false" + }, + + "POLY": { + "address": "0x9992eC3cF6A55b00978cdDF2b27BC6882d88D1eC", + "decimals": "18", + "symbol": "POLY", + "name": "Polymath Network", + "hasIcon": "false" + }, + + "SPN": { + "address": "0x20F7A3DdF244dc9299975b4Da1C39F8D5D75f05A", + "decimals": "6", + "symbol": "SPN", + "name": "Sapien", + "hasIcon": "false" + }, + + "APPC": { + "address": "0x1a7a8BD9106F2B8D977E08582DC7d24c723ab0DB", + "decimals": "18", + "symbol": "APPC", + "name": "AppCoins", + "hasIcon": "false" + }, + + "USDT": { + "address": "0xdAC17F958D2ee523a2206206994597C13D831ec7", + "decimals": "6", + "symbol": "USDT", + "name": "USD Tether (erc20)", + "hasIcon": "false" + }, + + "MET": { + "address": "0xa3d58c4E56fedCae3a7c43A725aeE9A71F0ece4e", + "decimals": "18", + "symbol": "MET", + "name": "Metronome", + "hasIcon": "false" + }, + + "HT": { + "address": "0x6f259637dcD74C767781E37Bc6133cd6A68aa161", + "decimals": "18", + "symbol": "HT", + "name": "Huobi Token", + "hasIcon": "false" + }, + + "WETH": { + "address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "decimals": "18", + "symbol": "WETH", + "name": "WETH", + "hasIcon": "false" + }, + + "VERI": { + "address": "0x8f3470A7388c05eE4e7AF3d01D8C722b0FF52374", + "decimals": "18", + "symbol": "VERI", + "name": "Veritaseum", + "hasIcon": "true" + }, + + "TAUD": { + "address": "0x00006100F7090010005F1bd7aE6122c3C2CF0090", + "decimals": "18", + "symbol": "TAUD", + "name": "TrueAUD", + "hasIcon": "false" + }, + + "PT": { + "address": "0x66497A283E0a007bA3974e837784C6AE323447de", + "decimals": "18", + "symbol": "PT", + "name": "PornToken", + "hasIcon": "false" + }, + + "XRL": { + "address": "0xB24754bE79281553dc1adC160ddF5Cd9b74361a4", + "decimals": "9", + "symbol": "XRL", + "name": "XRL", + "hasIcon": "true" + }, + + "SNX": { + "address": "0xC011A72400E58ecD99Ee497CF89E3775d4bd732F", + "decimals": "18", + "symbol": "SNX", + "name": "Synthetix Network Token", + "hasIcon": "false" + }, + + "DLT": { + "address": "0x07e3c70653548B04f0A75970C1F81B4CBbFB606f", + "decimals": "18", + "symbol": "DLT", + "name": "Agrello", + "hasIcon": "true" + }, + + "OGN": { + "address": "0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26", + "decimals": "18", + "symbol": "OGN", + "name": "OriginToken", + "hasIcon": "false" + }, + + "HST": { + "address": "0x554C20B7c486beeE439277b4540A434566dC4C02", + "decimals": "18", + "symbol": "HST", + "name": "Decision Token", + "hasIcon": "true" + }, + + "WABI": { + "address": "0x286BDA1413a2Df81731D4930ce2F862a35A609fE", + "decimals": "18", + "symbol": "WABI", + "name": "Tael", + "hasIcon": "false" + }, + + "RAE": { + "address": "0xE5a3229CCb22b6484594973A03a3851dCd948756", + "decimals": "18", + "symbol": "RAE", + "name": "RAE Token", + "hasIcon": "false" + }, + + "UKG": { + "address": "0x24692791Bc444c5Cd0b81e3CBCaba4b04Acd1F3B", + "decimals": "18", + "symbol": "UKG", + "name": "UnikoinGold", + "hasIcon": "true" + }, + + "AMPL": { + "address": "0xD46bA6D942050d489DBd938a2C909A5d5039A161", + "decimals": "9", + "symbol": "AMPL", + "name": "Ampleforth", + "hasIcon": "false" + }, + + "USDS": { + "address": "0xA4Bdb11dc0a2bEC88d24A3aa1E6Bb17201112eBe", + "decimals": "6", + "symbol": "USDS", + "name": "StableUSD", + "hasIcon": "false" + }, + + "ABT": { + "address": "0xB98d4C97425d9908E66E53A6fDf673ACcA0BE986", + "decimals": "18", + "symbol": "ABT", + "name": "ArcBlock Token", + "hasIcon": "false" + }, + + "DAT": { + "address": "0x81c9151de0C8bafCd325a57E3dB5a5dF1CEBf79c", + "decimals": "18", + "symbol": "DAT", + "name": "Datum Token", + "hasIcon": "false" + }, + + "EKO": { + "address": "0xa6a840E50bCaa50dA017b91A0D86B8b2d41156EE", + "decimals": "18", + "symbol": "EKO", + "name": "EchoLink", + "hasIcon": "false" + }, + + "OST": { + "address": "0x2C4e8f2D746113d0696cE89B35F0d8bF88E0AEcA", + "decimals": "18", + "symbol": "OST", + "name": "Simple Token 'OST'", + "hasIcon": "false" + }, + + "FXC": { + "address": "0xc92D6E3E64302C59d734f3292E2A13A13D7E1817", + "decimals": "8", + "symbol": "FXC", + "name": "FUTURAX", + "hasIcon": "false" + }, + + "FXC": { + "address": "0x4a57E687b9126435a9B19E4A802113e266AdeBde", + "decimals": "18", + "symbol": "FXC", + "name": "Flexacoin", + "hasIcon": "false" + }, + + "UPP": { + "address": "0xC86D054809623432210c107af2e3F619DcFbf652", + "decimals": "18", + "symbol": "UPP", + "name": "Sentinel Protocol", + "hasIcon": "false" + }, + + "BQX": { + "address": "0x5Af2Be193a6ABCa9c8817001F45744777Db30756", + "decimals": "8", + "symbol": "BQX", + "name": "Bitquence", + "hasIcon": "false" + }, + + "DTA": { + "address": "0x69b148395ce0015c13e36bffbad63f49ef874e03", + "symbol": "DTA", + "name": "Data", + "decimals": "18", + "hasIcon": "false" + }, + + "SUSD": { + "address": "0x57ab1e02fee23774580c119740129eac7081e9d3", + "symbol": "SUSD", + "name": "Synth sUSD", + "decimals": "18", + "hasIcon": "false" + }, + + "CDAI": { + "address": "0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643", + "symbol": "CDAI", + "name": "Compound Dai", + "decimals": "8", + "hasIcon": "false" + }, + + "BAND": { + "address": "0xba11d00c5f74255f56a5e366f4f77f5a186d7f55", + "symbol": "BAND", + "name": "BandToken", + "decimals": "18", + "hasIcon": "false" + }, + + "SPIKE": { + "address": "0xa7fc5d2453e3f68af0cc1b78bcfee94a1b293650", + "symbol": "SPIKE", + "name": "Spiking", + "decimals": "10", + "hasIcon": "false" + } +}.toTable + +proc getTokenConfig*(symbol: string): AssetConfig = + if not tokenList.hasKey(symbol): + raise newException(Exception, "token not found in the token list") + # return tokenList["DEFAULT"].toAssetConfig + tokenList[symbol].toAssetConfig diff --git a/ui/app/AppLayouts/Wallet/AssetsTab.qml b/ui/app/AppLayouts/Wallet/AssetsTab.qml index 537646744f..e863434ef7 100644 --- a/ui/app/AppLayouts/Wallet/AssetsTab.qml +++ b/ui/app/AppLayouts/Wallet/AssetsTab.qml @@ -17,7 +17,7 @@ Item { id: assetInfoImage width: 36 height: 36 - source: image + source: hasIcon ? "../../img/tokens/" + symbol + ".png" : "../../img/tokens/0-native.png" anchors.left: parent.left anchors.leftMargin: 0 anchors.verticalCenter: parent.verticalCenter diff --git a/ui/app/img/tokens/ETH.png b/ui/app/img/tokens/ETH.png new file mode 100644 index 0000000000000000000000000000000000000000..0a964c3893a735318414d492398ae09110fb9450 GIT binary patch literal 870 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 literal 0 HcmV?d00001 diff --git a/ui/app/img/tokens/ETH@3x.png b/ui/app/img/tokens/ETH@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..33e83387734379165adb2f76032d097d014d57c1 GIT binary patch literal 2377 zcmXBVc{Eh-9|!QUq);lmzLv5yLiR}ZElb93?AfJcY=vR$ipah+VU$snWX8VzG^DW% z22&xULKwu@v&8t_(d&Hfb3dQw`RAVJywAB$EX|G1uw7sSfk0w#u&ZVu>y6*&6W z1I@o3U<7b+adC5V^YHNS0{H0o1q1{I1%-s^E{W2K10*CagTY`)Ng2S^t5;=Z<>cv< zl$DjQUAv~DqN1vLT}@5x#*G{5>KXt|O-(H=Ep2UGfS#VNzP`SJ!A&D$fQc!c83Y0` zH@C2~w6wCav8A(jaCC5VqH}h3c5!uab-fL6bMx>#=H=z>gwv++S>a1`o_k_CfycbdwcuOpFg|1yL)?k`}_NU|NcEVI5<2!q|s@4dRf4J^nh&b=WPZnB>(K5lQ1C2B3Zs~}l zIPQaeI|*{U6@q0E7nCeUE)tn9KT&pydh=0|IM#Z%t-3|60#&st|-Uc)|icE7}if0DHAYcgGo-S6{6x_)t!;kL;T&vTvmJrG790 z8T-ciMtRhZKG4j=2Y0skSkx_0rVyH&ld)F^%Oya;*Z~$W=*``1$`5ec^H7lWh@O)Z zv3(9yS;8ANSw$!X1%bgapp>;XDu+&K?|BJ^S5Tc(=$=J3V2Pzz*R!oH@ZB}1N zTk(DtwNSV*izD0$f60FFtX7x>h#Ov7etW3BE!^usLJdK~N^Q)uq-^(yG=l?$IeWWX zjX;GO*1pTxrT!b0!b0i{;_xtGfuiT7?e`e4J96*DR|!qIWojqwc^o6TarMucp1D|@ z!}G-|-R^<*GzO3t$AP7>ZoPc8u}S;ZZItRw;$%r(_~1`l$oBgs*jQHAL#f{zo~V7c za8~}Eg+ObKZPi(Mp`i(BJU=Q+|3GGO%$hBD1eYa!FYiG&3rjd;1iPH7@>vw^d1C2* z-dJRHO@SEW%Io}BI??%;`7s!8G)`vf99rYVy-XerwgA7D#tpVn$@hFY5)R438;U{k zqh{c;k_I9NHLtYjHzA^2&P3f|fHe4!xp;AhbY4a{o(pW1gxBPpB7`tzLXn(iXZP5{ zGJ8k@G8vtN>vE`y>t6ZN&0_Oza09y*F?8cY^VS5s@|wx~4}N2A%sInb;n;|m=kS}R zG#*zxStH&kFJAvA#>M$A+i>V2s|-iN*KMN?-1u;A4Uvc%n*_ci4#LDUjMnn#A_|RG z-#qkH*d?GJRDr!7lS<#z{cn3ua~f`&hB7dB9z=-6;Umu6?m%@A+VE6}B`G$Jri z`R(OfWECQx!LTE+oMWb9lnKdWhgn30Fk%7*mF3(=2SOO%u}8rJ~41IX#)m7SmYbTYxwX&>X5%?EEt6fu%)!`<^OHxVW7z9)*^Epn>8BcO04bx6% z#5lg|H90`yp7K22f2Lc6bQ|%I3%Hichw|B~`+HykZS;Uy=p}1TXp3<`uqOsie2@zg3UoI3 zeScytV9C{f4T>ltu;~Vh68@+q_FO>>b?>ulr5d|ZPr;1VtUie_RO!qVoL+n)7NL!} zsH4kpqs13hlgKA^{qt93Dy7g4+s8(Iq&06qtbf~airR(+d^ds*p9_ zbaH%ZMo;&;13dVJ=Nf2h$h3G>Ur!mvLV_BPJW)1J??S#2QN&yccA$vvoyE!NbC`|b zPOnSPE<0RzpNT_pZ2Q*JvV#!iDSPSw^K`Q8G#=4kvSgp^mni{`%lV>k z*}xX7-~`nfA*W8AsmZs3Eij2#DkjtwL$@F5WIrv>vZAnoI2=p<>)YGvEoc_u)2m>< z#66XFE8f*4UXw{Y8#Uxv`hz6skGd5)`nDnUUYKnAgOu?%%J&d3LF7WdZCKalPXFT{ zWF@RuzmuwLbScN&w19(CcsQS;2G@rbG4~x_1w);19L=rY{E#Lqj>Z^&#(71d=f_pF zc29IQdq}HqY<|B4v6(Y#H-Ge`)b2=$*spXS7l|AA)t*+GZw22}@f=$vDWci%54NFZ u_DY_uUl5l04J{McR}JN)6JjC