From 0da2afb1caafac30fa3d1ac21c6fff61f9f10975 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 21 Aug 2019 12:15:04 +0300 Subject: [PATCH 01/14] use CoinGecko instead of CoinMarketcap for exchange rates CoinMarketcap deprecated and took offline its v1 API. They have v2 API which has free plan and requires API keys. But as part of https://github.com/poanetwork/blockscout/issues/234 we alresy implemented fetching from CoinGecko. Now, coin id should be set for CoinGecko for the required coin. ``` config :explorer, Explorer.ExchangeRates.Source.CoinGecko, coin_id: System.get_env("COIN_GECKO_ID", "poa-network") ``` Or the `COIN_GECKO_ID` env var should be set. For example, COIN_GECKO_ID=poa-network --- apps/explorer/config/config.exs | 2 + apps/explorer/lib/explorer/chain.ex | 2 +- .../{coin_market_cap.ex => exchange_rate.ex} | 4 +- .../lib/explorer/exchange_rates/source.ex | 2 +- .../exchange_rates/source/coin_gecko.ex | 38 +++++++++++-------- 5 files changed, 28 insertions(+), 20 deletions(-) rename apps/explorer/lib/explorer/chain/supply/{coin_market_cap.ex => exchange_rate.ex} (72%) diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs index 95c80ba445..87b57d5f82 100644 --- a/apps/explorer/config/config.exs +++ b/apps/explorer/config/config.exs @@ -34,6 +34,8 @@ config :explorer, Explorer.Chain.Cache.BlockNumber, enabled: true config :explorer, Explorer.ExchangeRates.Source.CoinMarketCap, pages: String.to_integer(System.get_env("COINMARKETCAP_PAGES") || "10") +config :explorer, Explorer.ExchangeRates.Source.CoinGecko, coin_id: System.get_env("COIN_GECKO_ID", "poa-network") + balances_update_interval = if System.get_env("ADDRESS_WITH_BALANCES_UPDATE_INTERVAL") do case Integer.parse(System.get_env("ADDRESS_WITH_BALANCES_UPDATE_INTERVAL")) do diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 58253c0f27..90df61749c 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -2717,7 +2717,7 @@ defmodule Explorer.Chain do end defp supply_module do - Application.get_env(:explorer, :supply, Explorer.Chain.Supply.CoinMarketCap) + Application.get_env(:explorer, :supply, Explorer.Chain.Supply.ExchangeRate) end @doc """ diff --git a/apps/explorer/lib/explorer/chain/supply/coin_market_cap.ex b/apps/explorer/lib/explorer/chain/supply/exchange_rate.ex similarity index 72% rename from apps/explorer/lib/explorer/chain/supply/coin_market_cap.ex rename to apps/explorer/lib/explorer/chain/supply/exchange_rate.ex index ebaadb3c47..d45a8edc02 100644 --- a/apps/explorer/lib/explorer/chain/supply/coin_market_cap.ex +++ b/apps/explorer/lib/explorer/chain/supply/exchange_rate.ex @@ -1,6 +1,6 @@ -defmodule Explorer.Chain.Supply.CoinMarketCap do +defmodule Explorer.Chain.Supply.ExchangeRate do @moduledoc """ - Defines the supply API for calculating supply for coins from coinmarketcap. + Defines the supply API for calculating supply for coins from exchange_rate.. """ use Explorer.Chain.Supply diff --git a/apps/explorer/lib/explorer/exchange_rates/source.ex b/apps/explorer/lib/explorer/exchange_rates/source.ex index 41b87c1e29..d733b22222 100644 --- a/apps/explorer/lib/explorer/exchange_rates/source.ex +++ b/apps/explorer/lib/explorer/exchange_rates/source.ex @@ -83,7 +83,7 @@ defmodule Explorer.ExchangeRates.Source do @spec exchange_rates_source() :: module() defp exchange_rates_source do - config(:source) || Explorer.ExchangeRates.Source.CoinMarketCap + config(:source) || Explorer.ExchangeRates.Source.CoinGecko end @spec config(atom()) :: term diff --git a/apps/explorer/lib/explorer/exchange_rates/source/coin_gecko.ex b/apps/explorer/lib/explorer/exchange_rates/source/coin_gecko.ex index 4e59537bf6..f12eaca844 100644 --- a/apps/explorer/lib/explorer/exchange_rates/source/coin_gecko.ex +++ b/apps/explorer/lib/explorer/exchange_rates/source/coin_gecko.ex @@ -15,39 +15,45 @@ defmodule Explorer.ExchangeRates.Source.CoinGecko do {:ok, price} = get_btc_price() btc_price = to_decimal(price) - for item <- decode_json(data), - not is_nil(item["total_supply"]) and not is_nil(item["current_price"]) do - {:ok, last_updated, 0} = DateTime.from_iso8601(item["last_updated"]) + json_data = decode_json(data) - current_price = to_decimal(item["current_price"]) + market_data = json_data["market_data"] + {:ok, last_updated, 0} = DateTime.from_iso8601(market_data["last_updated"]) - id = item["id"] - btc_value = if id != "btc", do: Decimal.div(current_price, btc_price), else: 1 + current_price = to_decimal(market_data["current_price"]["usd"]) + id = json_data["id"] + btc_value = if id != "btc", do: Decimal.div(current_price, btc_price), else: 1 + + [ %Token{ - available_supply: to_decimal(item["total_supply"]), - total_supply: to_decimal(item["total_supply"]), + available_supply: to_decimal(market_data["circulating_supply"]), + total_supply: to_decimal(market_data["total_supply"]), btc_value: btc_value, - id: id, + id: json_data["id"], last_updated: last_updated, - market_cap_usd: to_decimal(item["market_cap"]), - name: item["name"], - symbol: item["symbol"], + market_cap_usd: to_decimal(market_data["market_cap"]["usd"]), + name: json_data["name"], + symbol: String.upcase(json_data["symbol"]), usd_value: current_price, - volume_24h_usd: to_decimal(item["total_volume"]) + volume_24h_usd: to_decimal(market_data["total_volume"]["usd"]) } - end + ] end @impl Source - def source_url(currency \\ "usd") do - "#{base_url()}/coins/markets?vs_currency=#{currency}" + def source_url do + "#{base_url()}/coins/#{coin_id()}" end defp base_url do config(:base_url) || "https://api.coingecko.com/api/v3" end + defp coin_id do + Application.get_env(:explorer, __MODULE__)[:coin_id] + end + defp get_btc_price(currency \\ "usd") do url = "#{base_url()}/exchange_rates" From 6990cac077063258515be73e2867314a11a1dbd9 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 21 Aug 2019 12:24:54 +0300 Subject: [PATCH 02/14] add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a49616a0a5..d54e46cc71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - [#2497](https://github.com/poanetwork/blockscout/pull/2497) - Add generic Ordered Cache behaviour and implementation ### Fixes +- [#2610](https://github.com/poanetwork/blockscout/pull/2610) - use CoinGecko instead of CoinMarketcap for exchange rates - [#2572](https://github.com/poanetwork/blockscout/pull/2572) - Ease non-critical css - [#2570](https://github.com/poanetwork/blockscout/pull/2570) - Network icons preload - [#2569](https://github.com/poanetwork/blockscout/pull/2569) - do not fetch emission rewards for transactions csv exporter From 8bae16459a7db6482bb8df42279248eb9a7546b5 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 21 Aug 2019 12:28:05 +0300 Subject: [PATCH 03/14] add entry to env vars file --- docs/env-variables.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/env-variables.md b/docs/env-variables.md index 60c9eee442..5ede197596 100644 --- a/docs/env-variables.md +++ b/docs/env-variables.md @@ -53,6 +53,7 @@ $ export NETWORK=POA | `ADDRESS_WITH_BALANCES`
`_UPDATE_INTERVAL`| | Interval in seconds to restart the task, which calculates addresses with balances. | 30 * 60 | v1.3.9+ | | `LINK_TO_OTHER_EXPLORERS` | | true/false. If true, links to other explorers are added in the footer | (empty) | v1.3.0+ | | `COINMARKETCAP_PAGES` | | the number of pages on coinmarketcap to list in order to find token's price | 10 | v1.3.10+ | +| `COIN_GECKO_ID` | | CoinGecko coin id required for fetching an exchange rate | poa-network | master | | `CHAIN_SPEC_PATH` | | Chain specification path (absolute file system path or url) to import block emission reward ranges and genesis account balances from | (empty) | master | | `SUPPORTED_CHAINS` | | Array of supported chains that displays in the footer and in the chains dropdown. This var was introduced in this PR [#1900](https://github.com/poanetwork/blockscout/pull/1900) and looks like an array of JSON objects. | (empty) | v2.0.0+ | | `BLOCK_COUNT_CACHE_PERIOD ` | | time to live of cache in seconds. This var was introduced in [#1876](https://github.com/poanetwork/blockscout/pull/1876) | 600 | v2.0.0+ | From c563ee363802bebc17672f13c96a9adaeaa49b89 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 21 Aug 2019 13:28:44 +0300 Subject: [PATCH 04/14] fix CoinGecko tests --- .../exchange_rates/source/coin_gecko.ex | 5 +- .../exchange_rates/source/coin_gecko_test.exs | 57 +++++-------------- 2 files changed, 18 insertions(+), 44 deletions(-) diff --git a/apps/explorer/lib/explorer/exchange_rates/source/coin_gecko.ex b/apps/explorer/lib/explorer/exchange_rates/source/coin_gecko.ex index f12eaca844..5b0bed2b3b 100644 --- a/apps/explorer/lib/explorer/exchange_rates/source/coin_gecko.ex +++ b/apps/explorer/lib/explorer/exchange_rates/source/coin_gecko.ex @@ -11,7 +11,7 @@ defmodule Explorer.ExchangeRates.Source.CoinGecko do @behaviour Source @impl Source - def format_data(data) do + def format_data(%{"market_data" => _} = data) do {:ok, price} = get_btc_price() btc_price = to_decimal(price) @@ -41,6 +41,9 @@ defmodule Explorer.ExchangeRates.Source.CoinGecko do ] end + @impl Source + def format_data(_), do: [] + @impl Source def source_url do "#{base_url()}/coins/#{coin_id()}" diff --git a/apps/explorer/test/explorer/exchange_rates/source/coin_gecko_test.exs b/apps/explorer/test/explorer/exchange_rates/source/coin_gecko_test.exs index 3c2a9b6feb..b4b3313d6c 100644 --- a/apps/explorer/test/explorer/exchange_rates/source/coin_gecko_test.exs +++ b/apps/explorer/test/explorer/exchange_rates/source/coin_gecko_test.exs @@ -18,34 +18,6 @@ defmodule Explorer.ExchangeRates.Source.CoinGeckoTest do } """ - @json_mkt_data """ - [ - { - "id": "poa-network", - "symbol": "poa", - "name": "POA Network", - "image": "https://assets.coingecko.com/coins/images/3157/large/poa.jpg?1520829019", - "current_price": 0.114782883773693, - "market_cap": 25248999.6735956, - "market_cap_rank": 185, - "total_volume": 2344442.13578437, - "high_24h": 0.115215129840519, - "low_24h": 0.101039753612939, - "price_change_24h": 0.0135970966607094, - "price_change_percentage_24h": 13.437753511298, - "market_cap_change_24h": 3058195.58191147, - "market_cap_change_percentage_24h": 13.7813644304017, - "circulating_supply": "219935174.0", - "total_supply": 252193195, - "ath": 0.935923393359191, - "ath_change_percentage": -87.731057963078, - "ath_date": "2018-05-10T09:45:31.809Z", - "roi": null, - "last_updated": "2018-10-23T01:25:31.764Z" - } - ] - """ - describe "format_data/1" do setup do bypass = Bypass.open() @@ -59,31 +31,30 @@ defmodule Explorer.ExchangeRates.Source.CoinGeckoTest do Conn.resp(conn, 200, @json_btc_price) end) - {:ok, expected_date, 0} = "2018-10-23T01:25:31.764Z" |> DateTime.from_iso8601() + json_data = + "#{File.cwd!()}/test/support/fixture/exchange_rates/coin_gecko.json" + |> File.read!() + |> Jason.decode!() expected = [ %Token{ - available_supply: Decimal.new("252193195"), - total_supply: Decimal.new("252193195"), - btc_value: Decimal.new("0.00001753101509231471092879666458"), + available_supply: Decimal.new("220167621.0"), + total_supply: Decimal.new("252193195.0"), + btc_value: Decimal.new("0.000002055310963802830367634997491"), id: "poa-network", - last_updated: expected_date, - market_cap_usd: Decimal.new("25248999.6735956"), + last_updated: ~U[2019-08-21 08:36:49.371Z], + market_cap_usd: Decimal.new("2962791"), name: "POA Network", - symbol: "poa", - usd_value: Decimal.new("0.114782883773693"), - volume_24h_usd: Decimal.new("2344442.13578437") + symbol: "POA", + usd_value: Decimal.new("0.01345698"), + volume_24h_usd: Decimal.new("119946") } ] - assert expected == CoinGecko.format_data(@json_mkt_data) + assert expected == CoinGecko.format_data(json_data) end - test "returns nothing when given bad data", %{bypass: bypass} do - Bypass.expect(bypass, "GET", "/exchange_rates", fn conn -> - Conn.resp(conn, 200, @json_btc_price) - end) - + test "returns nothing when given bad data" do bad_data = """ [{"id": "poa-network"}] """ From 61c65de470ee6dc6907613b19e24a7ce733ebe5d Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 21 Aug 2019 13:29:12 +0300 Subject: [PATCH 05/14] add example CoinGecko response --- .../fixture/exchange_rates/coin_gecko.json | 1806 +++++++++++++++++ 1 file changed, 1806 insertions(+) create mode 100644 apps/explorer/test/support/fixture/exchange_rates/coin_gecko.json diff --git a/apps/explorer/test/support/fixture/exchange_rates/coin_gecko.json b/apps/explorer/test/support/fixture/exchange_rates/coin_gecko.json new file mode 100644 index 0000000000..cc110eb402 --- /dev/null +++ b/apps/explorer/test/support/fixture/exchange_rates/coin_gecko.json @@ -0,0 +1,1806 @@ +{ + "asset_platform_id": null, + "block_time_in_minutes": 0, + "categories": [], + "coingecko_rank": 376, + "coingecko_score": 33.7, + "community_data": { + "facebook_likes": 0, + "reddit_accounts_active_48h": 0, + "reddit_average_comments_48h": 0.0, + "reddit_average_posts_48h": 0.0, + "reddit_subscribers": 0, + "telegram_channel_user_count": 5125, + "twitter_followers": 17737 + }, + "community_score": 9.403, + "country_origin": "", + "description": { + "ar": "", + "de": "", + "en": "", + "es": "", + "fr": "", + "hu": "", + "id": "", + "it": "", + "ja": "", + "ko": "", + "nl": "", + "pl": "", + "pt": "", + "ro": "", + "ru": "", + "sv": "", + "th": "", + "tr": "", + "vi": "", + "zh": "", + "zh-tw": "" + }, + "developer_data": { + "closed_issues": 0, + "code_additions_deletions_4_weeks": { + "additions": 0, + "deletions": 0 + }, + "commit_count_4_weeks": 0, + "forks": 44, + "last_4_weeks_commit_activity_series": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "pull_request_contributors": 6, + "pull_requests_merged": 133, + "stars": 58, + "subscribers": 8, + "total_issues": 0 + }, + "developer_score": 52.776, + "genesis_date": null, + "id": "poa-network", + "image": { + "large": "https://assets.coingecko.com/coins/images/3157/large/poa-network.png?1548331565", + "small": "https://assets.coingecko.com/coins/images/3157/small/poa-network.png?1548331565", + "thumb": "https://assets.coingecko.com/coins/images/3157/thumb/poa-network.png?1548331565" + }, + "last_updated": "2019-08-21T08:36:49.371Z", + "links": { + "announcement_url": [ + "", + "" + ], + "bitcointalk_thread_identifier": null, + "blockchain_site": [ + "https://blockscout.com/poa/core/", + "", + "", + "", + "" + ], + "chat_url": [ + "", + "", + "" + ], + "facebook_username": "", + "homepage": [ + "https://poa.network/", + "", + "" + ], + "official_forum_url": [ + "", + "", + "" + ], + "repos_url": { + "bitbucket": [], + "github": [ + "https://github.com/poanetwork/poa-network-consensus-contracts" + ] + }, + "subreddit_url": null, + "telegram_channel_identifier": "oraclesnetwork", + "twitter_screen_name": "poanetwork" + }, + "liquidity_score": 19.334, + "localization": { + "ar": "POA Network", + "de": "POA Network", + "en": "POA Network", + "es": "POA Network", + "fr": "POA Network", + "hu": "POA Network", + "id": "POA Network", + "it": "POA Network", + "ja": "ポアネットワーク", + "ko": "POA 네트워크", + "nl": "POA Network", + "pl": "POA Network", + "pt": "POA Network", + "ro": "POA Network", + "ru": "POA Network", + "sv": "POA Network", + "th": "POA Network", + "tr": "POA Network", + "vi": "POA Network", + "zh": "POA Network", + "zh-tw": "POA Network" + }, + "market_cap_rank": 499, + "market_data": { + "ath": { + "aed": 3.06, + "ars": 18.93, + "aud": 1.25, + "bch": 0.00076772, + "bdt": 70.74, + "bhd": 0.314495, + "bmd": 0.833914, + "bnb": 0.01322268, + "brl": 3.36, + "btc": 0.00010137, + "cad": 1.2, + "chf": 0.938803, + "clp": 519.58, + "cny": 5.94, + "czk": 17.83, + "dkk": 5.87, + "eos": 0.02444974, + "eth": 0.0011725, + "eur": 0.787803, + "gbp": 0.689151, + "hkd": 7.35, + "huf": 219.96, + "idr": 13179.33, + "ils": 2.97, + "inr": 62.94, + "jpy": 102.6, + "krw": 1000.83, + "kwd": 0.251571, + "lkr": 131.79, + "ltc": 0.00537407, + "mmk": 1125.41, + "mxn": 18.15, + "myr": 3.76, + "nok": 6.67, + "nzd": 1.35, + "php": 48.59, + "pkr": 96.55, + "pln": 3.34, + "rub": 58.27, + "sar": 3.13, + "sek": 8.13, + "sgd": 1.25, + "thb": 26.65, + "try": 3.54, + "twd": 27.89, + "uah": 1.44, + "usd": 0.935923, + "vef": 58307, + "vnd": 1281.67, + "xag": 0.056398, + "xau": 0.00071129, + "xdr": 0.656022, + "xlm": 0.58965135, + "xrp": 0.2920468, + "zar": 11.63 + }, + "ath_change_percentage": { + "aed": -98.3819, + "ars": -96.09901, + "aud": -98.40941, + "bch": -94.11046, + "bdt": -98.39058, + "bhd": -98.38261, + "bmd": -98.38194, + "bnb": -96.24179, + "brl": -98.37442, + "btc": -98.68937, + "cad": -98.49893, + "chf": -98.59269, + "clp": -98.15517, + "cny": -98.39701, + "czk": -98.2406, + "dkk": -98.45473, + "eos": -84.56025, + "eth": -93.8673, + "eur": -98.45627, + "gbp": -98.38711, + "hkd": -98.55948, + "huf": -98.18974, + "idr": -98.54127, + "ils": -98.39903, + "inr": -98.46908, + "jpy": -98.59899, + "krw": -98.37868, + "kwd": -98.3684, + "lkr": -98.16735, + "ltc": -96.51103, + "mmk": -98.17585, + "mxn": -98.53298, + "myr": -98.49907, + "nok": -98.18519, + "nzd": -98.43938, + "php": -98.54716, + "pkr": -97.76349, + "pln": -98.41583, + "rub": -98.4658, + "sar": -98.3821, + "sek": -98.39542, + "sgd": -98.51152, + "thb": -98.44172, + "try": -97.81784, + "twd": -98.48322, + "uah": -76.52065, + "usd": -98.5583, + "vef": -94.2496, + "vnd": -75.59837, + "xag": -98.59644, + "xau": -98.73411, + "xdr": -98.49988, + "xlm": -66.24383, + "xrp": -82.56607, + "zar": -98.23009 + }, + "ath_date": { + "aed": "2018-05-10T00:00:00.000Z", + "ars": "2018-05-10T00:00:00.000Z", + "aud": "2018-05-10T09:45:31.809Z", + "bch": "2018-04-14T00:00:00.000Z", + "bdt": "2018-05-10T00:00:00.000Z", + "bhd": "2018-05-10T00:00:00.000Z", + "bmd": "2018-05-10T00:00:00.000Z", + "bnb": "2018-10-16T12:40:17.749Z", + "brl": "2018-05-10T09:45:31.809Z", + "btc": "2018-05-10T09:45:31.809Z", + "cad": "2018-05-10T09:45:31.809Z", + "chf": "2018-05-10T09:45:31.809Z", + "clp": "2018-05-10T00:00:00.000Z", + "cny": "2018-05-10T09:45:31.809Z", + "czk": "2018-05-10T00:00:00.000Z", + "dkk": "2018-05-10T09:45:31.809Z", + "eos": "2018-10-16T12:40:17.749Z", + "eth": "2018-04-09T00:00:00.000Z", + "eur": "2018-05-10T09:45:31.809Z", + "gbp": "2018-05-10T09:45:31.809Z", + "hkd": "2018-05-10T09:45:31.809Z", + "huf": "2018-05-10T00:00:00.000Z", + "idr": "2018-05-10T09:45:31.809Z", + "ils": "2018-05-10T00:00:00.000Z", + "inr": "2018-05-10T09:45:31.809Z", + "jpy": "2018-05-10T09:45:31.809Z", + "krw": "2018-05-10T09:45:31.809Z", + "kwd": "2018-05-10T00:00:00.000Z", + "lkr": "2018-05-10T00:00:00.000Z", + "ltc": "2018-05-10T00:00:00.000Z", + "mmk": "2018-05-10T00:00:00.000Z", + "mxn": "2018-05-10T09:45:31.809Z", + "myr": "2018-05-10T09:45:31.809Z", + "nok": "2018-05-10T00:00:00.000Z", + "nzd": "2018-05-10T09:45:31.809Z", + "php": "2018-05-10T09:45:31.809Z", + "pkr": "2018-05-10T00:00:00.000Z", + "pln": "2018-05-10T09:45:31.809Z", + "rub": "2018-05-10T09:45:31.809Z", + "sar": "2018-05-10T00:00:00.000Z", + "sek": "2018-05-10T09:45:31.809Z", + "sgd": "2018-05-10T09:45:31.809Z", + "thb": "2018-05-10T00:00:00.000Z", + "try": "2018-05-10T00:00:00.000Z", + "twd": "2018-05-10T09:45:31.809Z", + "uah": "2019-05-27T12:49:29.532Z", + "usd": "2018-05-10T09:45:31.809Z", + "vef": "2018-05-10T00:00:00.000Z", + "vnd": "2019-05-27T12:49:29.532Z", + "xag": "2018-05-10T09:45:31.809Z", + "xau": "2018-05-10T09:45:31.809Z", + "xdr": "2018-05-10T09:45:31.809Z", + "xlm": "2018-10-16T12:49:26.379Z", + "xrp": "2018-10-16T12:40:17.749Z", + "zar": "2018-05-10T09:45:31.809Z" + }, + "circulating_supply": 220167621.0, + "current_price": { + "aed": 0.04942712, + "ars": 0.73641, + "aud": 0.0198328, + "bch": 4.486e-05, + "bdt": 1.14, + "bhd": 0.00507448, + "bmd": 0.01345698, + "bnb": 0.00049505, + "brl": 0.054544, + "btc": 1.32e-06, + "cad": 0.0178991, + "chf": 0.01317061, + "clp": 9.55, + "cny": 0.095047, + "czk": 0.312629, + "dkk": 0.090366, + "eos": 0.0037559, + "eth": 7.147e-05, + "eur": 0.01211961, + "gbp": 0.01107566, + "hkd": 0.105541, + "huf": 3.97, + "idr": 191.75, + "ils": 0.04745883, + "inr": 0.960893, + "jpy": 1.43, + "krw": 16.19, + "kwd": 0.00409361, + "lkr": 2.4, + "ltc": 0.00018598, + "mmk": 20.47, + "mxn": 0.26536, + "myr": 0.056211, + "nok": 0.120606, + "nzd": 0.02100918, + "php": 0.704042, + "pkr": 2.15, + "pln": 0.052749, + "rub": 0.891153, + "sar": 0.050476, + "sek": 0.129909, + "sgd": 0.01861909, + "thb": 0.414071, + "try": 0.076819, + "twd": 0.422042, + "uah": 0.338308, + "usd": 0.01345698, + "vef": 3343.89, + "vnd": 311.66, + "xag": 0.00078867, + "xau": 8.98e-06, + "xdr": 0.00981471, + "xlm": 0.1975895, + "xrp": 0.05067322, + "zar": 0.204922 + }, + "high_24h": { + "aed": 0.053611, + "ars": 0.810805, + "aud": 0.02152674, + "bch": 4.628e-05, + "bdt": 1.23, + "bhd": 0.00550347, + "bmd": 0.0145949, + "bnb": 0.00052215, + "brl": 0.058875, + "btc": 1.37e-06, + "cad": 0.01943935, + "chf": 0.01428979, + "clp": 10.36, + "cny": 0.103044, + "czk": 0.339287, + "dkk": 0.098076, + "eos": 0.00402026, + "eth": 7.423e-05, + "eur": 0.01315448, + "gbp": 0.01201087, + "hkd": 0.114474, + "huf": 4.31, + "idr": 208.11, + "ils": 0.051491, + "inr": 1.04, + "jpy": 1.55, + "krw": 17.63, + "kwd": 0.00443977, + "lkr": 2.6, + "ltc": 0.00019631, + "mmk": 22.24, + "mxn": 0.288202, + "myr": 0.061014, + "nok": 0.131376, + "nzd": 0.02274396, + "php": 0.76332, + "pkr": 2.34, + "pln": 0.057291, + "rub": 0.972261, + "sar": 0.054726, + "sek": 0.14165, + "sgd": 0.02021141, + "thb": 0.449117, + "try": 0.083602, + "twd": 0.457778, + "uah": 0.367456, + "usd": 0.0145949, + "vef": 3626.65, + "vnd": 338.27, + "xag": 0.00085369, + "xau": 9.72e-06, + "xdr": 0.01064365, + "xlm": 0.20827298, + "xrp": 0.05318558, + "zar": 0.223696 + }, + "last_updated": "2019-08-21T08:36:49.371Z", + "low_24h": { + "aed": 0.0491677, + "ars": 0.732555, + "aud": 0.0197477, + "bch": 4.364e-05, + "bdt": 1.13, + "bhd": 0.00504693, + "bmd": 0.01338635, + "bnb": 0.00049273, + "brl": 0.054256, + "btc": 1.3e-06, + "cad": 0.01782004, + "chf": 0.01311131, + "clp": 9.51, + "cny": 0.094517, + "czk": 0.311235, + "dkk": 0.089982, + "eos": 0.00373147, + "eth": 7.098e-05, + "eur": 0.01206786, + "gbp": 0.01103078, + "hkd": 0.104993, + "huf": 3.95, + "idr": 190.79, + "ils": 0.04723279, + "inr": 0.958004, + "jpy": 1.43, + "krw": 16.1, + "kwd": 0.00406945, + "lkr": 2.39, + "ltc": 0.00018228, + "mmk": 20.37, + "mxn": 0.264134, + "myr": 0.055903, + "nok": 0.120189, + "nzd": 0.02091282, + "php": 0.700581, + "pkr": 2.14, + "pln": 0.052569, + "rub": 0.886879, + "sar": 0.050214, + "sek": 0.129578, + "sgd": 0.01853166, + "thb": 0.412199, + "try": 0.076627, + "twd": 0.4198, + "uah": 0.336532, + "usd": 0.01338635, + "vef": 3326.34, + "vnd": 310.32, + "xag": 0.00078625, + "xau": 8.93e-06, + "xdr": 0.0097632, + "xlm": 0.19635382, + "xrp": 0.05037993, + "zar": 0.204544 + }, + "market_cap": { + "aed": 10882251, + "ars": 162133701, + "aud": 4366541, + "bch": 9877, + "bdt": 249997342, + "bhd": 1117236, + "bmd": 2962791, + "bnb": 108994, + "brl": 12008719, + "btc": 290.732, + "cad": 3940802, + "chf": 2899743, + "clp": 2101619696, + "cny": 20926193, + "czk": 68830802, + "dkk": 19895675, + "eos": 826927, + "eth": 15736, + "eur": 2668346, + "gbp": 2438501, + "hkd": 23236814, + "huf": 873552757, + "idr": 42217105275, + "ils": 10448899, + "inr": 211557455, + "jpy": 315583737, + "krw": 3564593111, + "kwd": 901281, + "lkr": 529480380, + "ltc": 40948, + "mmk": 4507718929, + "mxn": 58423768, + "myr": 12375904, + "nok": 26553448, + "nzd": 4625542, + "php": 155007300, + "pkr": 474133000, + "pln": 11613646, + "rub": 196202962, + "sar": 11113192, + "sek": 28601664, + "sgd": 4099321, + "thb": 91165079, + "try": 16912998, + "twd": 92920077, + "uah": 74484427, + "usd": 2962791, + "vef": 736216950688, + "vnd": 68617204931, + "xag": 173639, + "xau": 1976.89, + "xdr": 2160882, + "xlm": 43502811, + "xrp": 11156602, + "zar": 45117091 + }, + "market_cap_change_24h": -160615.84039035, + "market_cap_change_24h_in_currency": { + "aed": -590899.65443375, + "ars": -9124373.5980551, + "aud": -239353.78003874, + "bch": 102.549, + "bdt": -13867874.4362154, + "bhd": -60251.00254582, + "bmd": -160615.84039035, + "bnb": -1507.543569741, + "brl": -718070.38245432, + "btc": 0.03769596, + "cad": -221121.61427417, + "chf": -161095.94704691, + "clp": -127118490.79824165, + "cny": -1134429.68067712, + "czk": -3925858.7665586, + "dkk": -1136450.3780936, + "eos": -24548.1071608166, + "eth": -56.533938946, + "eur": -152193.5816755, + "gbp": -144996.42715597, + "hkd": -1263688.72303977, + "huf": -48860628.81047357, + "idr": -2346101857.217293, + "ils": -576162.08791993, + "inr": -12451722.53525829, + "jpy": -16857632.06248754, + "krw": -209731718.0214291, + "kwd": -49171.67933105, + "lkr": -26048761.01962376, + "ltc": -309.0831858893, + "mmk": -251710124.48363495, + "mxn": -3503488.89323037, + "myr": -687829.52792143, + "nok": -1513569.75537506, + "nzd": -244980.03753899, + "php": -8388263.35503852, + "pkr": -26642819.2931419, + "pln": -696325.10549893, + "rub": -12221976.62125358, + "sar": -601457.67784725, + "sek": -1668070.90346983, + "sgd": -230174.18438848, + "thb": -5107689.97148955, + "try": -927927.24538566, + "twd": -5107834.82635887, + "uah": -4241989.31565817, + "usd": -160615.84039035, + "vef": -39911051485.156494, + "vnd": -4088394297.5983276, + "xag": -9606.58322042, + "xau": -102.32803274, + "xdr": -115659.93877989, + "xlm": -1276957.0373063833, + "xrp": -122973.5124849025, + "zar": -2969034.78716005 + }, + "market_cap_change_percentage_24h": -5.14233, + "market_cap_change_percentage_24h_in_currency": { + "aed": -5.15028, + "ars": -5.32785, + "aud": -5.19668, + "bch": 1.0491, + "bdt": -5.25567, + "bhd": -5.11691, + "bmd": -5.14233, + "bnb": -1.36428, + "brl": -5.6422, + "btc": 0.01297, + "cad": -5.31297, + "chf": -5.26313, + "clp": -5.70361, + "cny": -5.14233, + "czk": -5.39588, + "dkk": -5.4034, + "eos": -2.88301, + "eth": -0.35797, + "eur": -5.3959, + "gbp": -5.61241, + "hkd": -5.15781, + "huf": -5.29704, + "idr": -5.26466, + "ils": -5.22593, + "inr": -5.55858, + "jpy": -5.07086, + "krw": -5.5568, + "kwd": -5.1735, + "lkr": -4.689, + "ltc": -0.74917, + "mmk": -5.28866, + "mxn": -5.65743, + "myr": -5.26518, + "nok": -5.3927, + "nzd": -5.02985, + "php": -5.13372, + "pkr": -5.32031, + "pln": -5.65659, + "rub": -5.86397, + "sar": -5.13424, + "sek": -5.51069, + "sgd": -5.31642, + "thb": -5.30544, + "try": -5.20112, + "twd": -5.21059, + "uah": -5.38827, + "usd": -5.14233, + "vef": -5.14233, + "vnd": -5.62322, + "xag": -5.24248, + "xau": -4.92146, + "xdr": -5.08051, + "xlm": -2.85164, + "xrp": -1.09023, + "zar": -6.17441 + }, + "market_cap_rank": 499, + "price_change_24h": -0.00070501, + "price_change_24h_in_currency": { + "aed": -0.00259384, + "ars": -0.0401764, + "aud": -0.00106049, + "bch": 4.401e-07, + "bdt": -0.06091731, + "bhd": -0.00026442, + "bmd": -0.00070501, + "bnb": -7.9537e-06, + "brl": -0.00316161, + "btc": -7e-10, + "cad": -0.000975, + "chf": -0.00070391, + "clp": -0.55975334, + "cny": -0.00498938, + "czk": -0.01720638, + "dkk": -0.00497873, + "eos": -0.0001041039, + "eth": -1.756e-07, + "eur": -0.00066664, + "gbp": -0.00063744, + "hkd": -0.00554812, + "huf": -0.21652693, + "idr": -10.32117361, + "ils": -0.00254123, + "inr": -0.05433204, + "jpy": -0.07396812, + "krw": -0.92440016, + "kwd": -0.00021588, + "lkr": -0.11324611, + "ltc": -1.1432e-06, + "mmk": -1.10591975, + "mxn": -0.01564173, + "myr": -0.00303114, + "nok": -0.0066618, + "nzd": -0.00108422, + "php": -0.03666507, + "pkr": -0.11708205, + "pln": -0.0030605, + "rub": -0.05396307, + "sar": -0.00263569, + "sek": -0.00737328, + "sgd": -0.00101489, + "thb": -0.02240118, + "try": -0.00415931, + "twd": -0.02243055, + "uah": -0.01864934, + "usd": -0.00070501, + "vef": -175.18566197, + "vnd": -17.91454955, + "xag": -4.268e-05, + "xau": -4.5e-07, + "xdr": -0.00050746, + "xlm": -0.0043814329, + "xrp": -0.0005808077, + "zar": -0.01325238 + }, + "price_change_percentage_14d": -20.09212, + "price_change_percentage_14d_in_currency": { + "aed": -20.09664, + "ars": -3.40252, + "aud": -20.3743, + "bch": -10.35771, + "bdt": -20.21051, + "bhd": -20.07198, + "bmd": -20.09212, + "bnb": -18.90438, + "brl": -18.21564, + "btc": -10.20835, + "cad": -19.99931, + "chf": -19.86474, + "clp": -20.70274, + "cny": -19.67703, + "czk": -19.20224, + "dkk": -19.44946, + "eos": -6.27667, + "eth": -3.85819, + "eur": -19.3615, + "gbp": -19.99287, + "hkd": -20.04155, + "huf": -18.72941, + "idr": -19.92585, + "ils": -19.11955, + "inr": -19.53455, + "jpy": -19.93789, + "krw": -20.72061, + "kwd": -20.08213, + "lkr": -19.39749, + "ltc": 3.01755, + "mmk": -19.52559, + "mxn": -19.64657, + "myr": -20.39088, + "nok": -19.55283, + "nzd": -18.54, + "php": -19.79625, + "pkr": -19.69932, + "pln": -18.70635, + "rub": -18.9447, + "sar": -20.11299, + "sek": -19.43426, + "sgd": -19.93866, + "thb": -19.96922, + "try": -17.50796, + "twd": -20.26871, + "uah": -21.43567, + "usd": -20.09212, + "vef": -20.09212, + "vnd": -20.39781, + "xag": -22.82706, + "xau": -21.25807, + "xdr": -19.80447, + "xlm": -6.90503, + "xrp": -5.82792, + "zar": -18.53383 + }, + "price_change_percentage_1h_in_currency": { + "aed": -0.65082, + "ars": -0.65814, + "aud": -0.81241, + "bch": 1.34916, + "bdt": -0.64945, + "bhd": -0.62736, + "bmd": -0.65082, + "bnb": -0.66128, + "brl": -0.65109, + "btc": -0.64949, + "cad": -0.75327, + "chf": -0.6566, + "clp": -0.81121, + "cny": -0.61001, + "czk": -0.71198, + "dkk": -0.72865, + "eos": -0.27623, + "eth": -0.72711, + "eur": -0.73062, + "gbp": -0.79594, + "hkd": -0.65424, + "huf": -0.65304, + "idr": -0.69877, + "ils": -0.68895, + "inr": -0.85681, + "jpy": -0.70261, + "krw": -0.64504, + "kwd": -0.68347, + "lkr": -0.66193, + "ltc": 0.20669, + "mmk": -0.65082, + "mxn": -0.79588, + "myr": -0.58632, + "nok": -0.94166, + "nzd": -0.77361, + "php": -0.65651, + "pkr": -0.65082, + "pln": -0.82133, + "rub": -0.80523, + "sar": -0.62904, + "sek": -0.92466, + "sgd": -0.72845, + "thb": -0.71559, + "try": -0.93842, + "twd": -0.63818, + "uah": -0.65082, + "usd": -0.65082, + "vef": -0.65082, + "vnd": -0.72098, + "xag": -0.86625, + "xau": -0.66422, + "xdr": -0.65082, + "xlm": -0.6397, + "xrp": -0.05073, + "zar": -1.25864 + }, + "price_change_percentage_1y": -80.39683, + "price_change_percentage_1y_in_currency": { + "aed": -80.39794, + "ars": -61.05676, + "aud": -78.80429, + "bch": -66.67604, + "bdt": -80.26581, + "bhd": -80.39891, + "bmd": -80.39683, + "brl": -79.97401, + "btc": -87.93415, + "cad": -80.00734, + "chf": -80.63119, + "clp": -79.21186, + "cny": -79.80673, + "czk": -79.67769, + "dkk": -79.72199, + "eth": -71.77736, + "eur": -79.71573, + "gbp": -79.34655, + "hkd": -80.41399, + "huf": -79.49619, + "idr": -80.5156, + "ils": -81.08059, + "inr": -79.93604, + "jpy": -81.01454, + "krw": -78.90452, + "kwd": -80.34132, + "lkr": -78.15787, + "ltc": -85.4361, + "mmk": -80.27721, + "mxn": -79.65762, + "myr": -80.02222, + "nok": -79.18424, + "nzd": -79.67365, + "php": -80.76747, + "pkr": -74.51734, + "pln": -79.50758, + "rub": -80.62327, + "sar": -80.39647, + "sek": -79.31728, + "sgd": -80.18923, + "thb": -81.67711, + "try": -81.65737, + "twd": -79.98887, + "uah": -82.20648, + "usd": -80.39683, + "vef": -80.39558, + "vnd": -80.34916, + "xag": -83.03235, + "xau": -84.4215, + "xdr": -80.03907, + "zar": -79.43625 + }, + "price_change_percentage_200d": -50.1114, + "price_change_percentage_200d_in_currency": { + "aed": -50.11196, + "ars": -26.51722, + "aud": -46.67198, + "bch": -80.79243, + "bdt": -49.71149, + "bhd": -50.09578, + "bmd": -50.1114, + "bnb": -87.93302, + "brl": -44.75887, + "btc": -83.02991, + "cad": -49.34427, + "chf": -50.94689, + "clp": -45.88183, + "cny": -47.75857, + "czk": -48.37087, + "dkk": -48.59098, + "eos": -67.57399, + "eth": -71.6239, + "eur": -48.52075, + "gbp": -46.27358, + "hkd": -50.136, + "huf": -46.91923, + "idr": -49.00487, + "ils": -51.63145, + "inr": -50.15368, + "jpy": -51.46878, + "krw": -46.36111, + "kwd": -49.91845, + "lkr": -49.53248, + "ltc": -77.44522, + "mmk": -49.82943, + "mxn": -48.49618, + "myr": -49.12989, + "nok": -47.01887, + "nzd": -46.2816, + "php": -50.10377, + "pkr": -42.33563, + "pln": -47.7461, + "rub": -49.52654, + "sar": -50.10515, + "sek": -46.7992, + "sgd": -48.88484, + "thb": -50.95616, + "try": -45.32063, + "twd": -49.1634, + "uah": -54.76622, + "usd": -50.1114, + "vef": -50.1114, + "vnd": -50.2089, + "xag": -53.50147, + "xau": -56.13406, + "xdr": -49.07152, + "xlm": -39.53366, + "xrp": -42.37148, + "zar": -42.98063 + }, + "price_change_percentage_24h": -4.97817, + "price_change_percentage_24h_in_currency": { + "aed": -4.98614, + "ars": -5.17346, + "aud": -5.07575, + "bch": 0.99066, + "bdt": -5.0917, + "bhd": -4.95271, + "bmd": -4.97817, + "bnb": -1.58124, + "brl": -5.4789, + "btc": -0.05257, + "cad": -5.16583, + "chf": -5.07341, + "clp": -5.53921, + "cny": -4.98758, + "czk": -5.21666, + "dkk": -5.22182, + "eos": -2.69699, + "eth": -0.24506, + "eur": -5.21371, + "gbp": -5.44209, + "hkd": -4.99428, + "huf": -5.17487, + "idr": -5.1077, + "ils": -5.08246, + "inr": -5.35173, + "jpy": -4.90717, + "krw": -5.40119, + "kwd": -5.00939, + "lkr": -4.49721, + "ltc": -0.61091, + "mmk": -5.12476, + "mxn": -5.56641, + "myr": -5.1165, + "nok": -5.23449, + "nzd": -4.90745, + "php": -4.95001, + "pkr": -5.15646, + "pln": -5.48383, + "rub": -5.70968, + "sar": -4.96254, + "sek": -5.3709, + "sgd": -5.16905, + "thb": -5.13232, + "try": -5.13634, + "twd": -5.04655, + "uah": -5.22453, + "usd": -4.97817, + "vef": -4.97817, + "vnd": -5.43568, + "xag": -5.1341, + "xau": -4.8084, + "xdr": -4.91624, + "xlm": -2.16934, + "xrp": -1.13319, + "zar": -6.07423 + }, + "price_change_percentage_30d": -34.83569, + "price_change_percentage_30d_in_currency": { + "aed": -34.83544, + "ars": -15.98426, + "aud": -32.35353, + "bch": -30.11906, + "bdt": -34.93771, + "bhd": -34.7457, + "bmd": -34.83569, + "bnb": -27.08407, + "brl": -29.51868, + "btc": -32.08124, + "cad": -33.60701, + "chf": -35.09987, + "clp": -32.84418, + "cny": -33.12269, + "czk": -33.51308, + "dkk": -34.24389, + "eos": -21.08346, + "eth": -21.69788, + "eur": -34.16271, + "gbp": -32.89529, + "hkd": -34.53494, + "huf": -33.76133, + "idr": -33.48833, + "ils": -35.07099, + "inr": -32.4077, + "jpy": -35.60577, + "krw": -33.33925, + "kwd": -34.83162, + "lkr": -33.78522, + "ltc": -10.07379, + "mmk": -34.67478, + "mxn": -32.46726, + "myr": -33.79734, + "nok": -31.87864, + "nzd": -31.23716, + "php": -33.28065, + "pkr": -34.80085, + "pln": -32.59928, + "rub": -31.5309, + "sar": -34.83447, + "sek": -32.96828, + "sgd": -33.73135, + "thb": -35.04678, + "try": -34.23351, + "twd": -34.17354, + "uah": -36.37221, + "usd": -34.83569, + "vef": -34.83569, + "vnd": -35.19581, + "xag": -38.03606, + "xau": -38.0235, + "xdr": -34.25025, + "xlm": -12.74201, + "xrp": -18.8697, + "zar": -28.75132 + }, + "price_change_percentage_60d": -61.24989, + "price_change_percentage_60d_in_currency": { + "aed": -61.25202, + "ars": -50.32249, + "aud": -60.412, + "bch": -43.0945, + "bdt": -61.20391, + "bhd": -61.23344, + "bmd": -61.24989, + "bnb": -44.49169, + "brl": -58.90604, + "btc": -61.42639, + "cad": -61.04496, + "chf": -61.10703, + "clp": -59.79652, + "cny": -60.16104, + "czk": -60.03065, + "dkk": -60.38034, + "eos": -23.51938, + "eth": -39.23291, + "eur": -60.26215, + "gbp": -59.36192, + "hkd": -61.10542, + "huf": -59.91464, + "idr": -60.90777, + "ils": -62.26651, + "inr": -60.23354, + "jpy": -61.53855, + "krw": -59.78067, + "kwd": -61.16844, + "lkr": -60.71768, + "ltc": -25.65935, + "mmk": -61.20413, + "mxn": -60.04539, + "myr": -60.87356, + "nok": -59.13075, + "nzd": -60.12056, + "php": -60.49041, + "pkr": -60.53743, + "pln": -59.42569, + "rub": -59.28727, + "sar": -61.24451, + "sek": -59.99926, + "sgd": -60.43237, + "thb": -61.1805, + "try": -62.00162, + "twd": -60.74424, + "uah": -62.83383, + "usd": -61.24989, + "vef": -61.24989, + "vnd": -61.16958, + "xag": -65.19693, + "xau": -63.82007, + "xdr": -60.62729, + "xlm": -29.85582, + "xrp": -35.11899, + "zar": -58.83133 + }, + "price_change_percentage_7d": -12.91815, + "price_change_percentage_7d_in_currency": { + "aed": -12.92308, + "ars": -14.25115, + "aud": -12.76443, + "bch": 0.88592, + "bdt": -13.147, + "bhd": -12.88673, + "bmd": -12.91815, + "bnb": -5.78627, + "brl": -10.95714, + "btc": -6.92663, + "cad": -12.35787, + "chf": -12.68629, + "clp": -12.25865, + "cny": -12.67706, + "czk": -12.47009, + "dkk": -12.42719, + "eos": -0.91188, + "eth": -3.2526, + "eur": -12.3442, + "gbp": -13.56715, + "hkd": -12.94473, + "huf": -11.29007, + "idr": -13.63998, + "ils": -11.80257, + "inr": -12.53093, + "jpy": -12.98836, + "krw": -13.1693, + "kwd": -12.90068, + "lkr": -11.99684, + "ltc": 1.8824, + "mmk": -12.2934, + "mxn": -11.39186, + "myr": -13.13461, + "nok": -11.99025, + "nzd": -12.14546, + "php": -12.50757, + "pkr": -13.04362, + "pln": -11.96443, + "rub": -11.16958, + "sar": -12.91768, + "sek": -11.88369, + "sgd": -12.90808, + "thb": -12.98884, + "try": -10.77039, + "twd": -12.26523, + "uah": -12.97908, + "usd": -12.91815, + "vef": -12.91815, + "vnd": -13.40154, + "xag": -13.34686, + "xau": -12.77828, + "xdr": -12.6042, + "xlm": -3.71389, + "xrp": -2.40223, + "zar": -12.40714 + }, + "roi": null, + "total_supply": 252193195.0, + "total_volume": { + "aed": 440559, + "ars": 6563849, + "aud": 176776, + "bch": 399.879, + "bdt": 10120936, + "bhd": 45230, + "bmd": 119946, + "bnb": 4413, + "brl": 486163, + "btc": 11.770053, + "cad": 159540, + "chf": 117394, + "clp": 85082341, + "cny": 847180, + "czk": 2786558, + "dkk": 805460, + "eos": 33477, + "eth": 637.075, + "eur": 108026, + "gbp": 98721, + "hkd": 940723, + "huf": 35365063, + "idr": 1709124708, + "ils": 423015, + "inr": 8564729, + "jpy": 12776147, + "krw": 144309614, + "kwd": 36488, + "lkr": 21435577, + "ltc": 1658, + "mmk": 182491285, + "mxn": 2365238, + "myr": 501028, + "nok": 1074994, + "nzd": 187261, + "php": 6275343, + "pkr": 19194884, + "pln": 470169, + "rub": 7943115, + "sar": 449908, + "sek": 1157915, + "sgd": 165958, + "thb": 3690743, + "try": 684709, + "twd": 3761793, + "uah": 3015441, + "usd": 119946, + "vef": 29805136391, + "vnd": 2777910981, + "xag": 7029.61, + "xau": 80.03, + "xdr": 87482, + "xlm": 1761175, + "xrp": 451666, + "zar": 1826528 + } + }, + "name": "POA Network", + "public_interest_score": 27.778, + "public_interest_stats": { + "alexa_rank": 702581, + "bing_matches": 107000 + }, + "sentiment_votes_down_percentage": null, + "sentiment_votes_up_percentage": null, + "status_updates": [], + "symbol": "poa", + "tickers": [ + { + "base": "POA", + "bid_ask_spread_percentage": 1.503759, + "coin_id": "poa-network", + "converted_last": { + "btc": 1.32e-06, + "eth": 7.139e-05, + "usd": 0.01344331 + }, + "converted_volume": { + "btc": 10.856044, + "eth": 587.121, + "usd": 110562 + }, + "is_anomaly": false, + "is_stale": false, + "last": 1.32e-06, + "last_fetch_at": "2019-08-21T08:34:21+00:00", + "last_traded_at": "2019-08-21T08:34:21+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "binance", + "name": "Binance" + }, + "target": "BTC", + "timestamp": "2019-08-21T08:34:21+00:00", + "trade_url": "https://www.binance.com/trade.html?symbol=POA_BTC", + "trust_score": "green", + "volume": 8224275.5227272725 + }, + { + "base": "POA", + "bid_ask_spread_percentage": 1.729386, + "coin_id": "poa-network", + "converted_last": { + "btc": 1.34e-06, + "eth": 7.226e-05, + "usd": 0.01360764 + }, + "converted_volume": { + "btc": 0.35219856, + "eth": 19.04774, + "usd": 3586.91 + }, + "is_anomaly": false, + "is_stale": false, + "last": 7.238e-05, + "last_fetch_at": "2019-08-21T08:34:26+00:00", + "last_traded_at": "2019-08-21T08:34:26+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "binance", + "name": "Binance" + }, + "target": "ETH", + "timestamp": "2019-08-21T08:34:26+00:00", + "trade_url": "https://www.binance.com/trade.html?symbol=POA_ETH", + "trust_score": "green", + "volume": 263595.07819839736 + }, + { + "base": "POA", + "bid_ask_spread_percentage": 1.39165, + "coin_id": "poa-network", + "converted_last": { + "btc": 1.34e-06, + "eth": 7.259e-05, + "usd": 0.01363846 + }, + "converted_volume": { + "btc": 0.24038472, + "eth": 13.008637, + "usd": 2444.17 + }, + "is_anomaly": false, + "is_stale": false, + "last": 0.000502, + "last_fetch_at": "2019-08-21T08:34:26+00:00", + "last_traded_at": "2019-08-21T08:13:08+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "binance", + "name": "Binance" + }, + "target": "BNB", + "timestamp": "2019-08-21T08:13:08+00:00", + "trade_url": "https://www.binance.com/trade.html?symbol=POA_BNB", + "trust_score": "green", + "volume": 179211.83864541832 + }, + { + "base": "POA", + "bid_ask_spread_percentage": 2.985075, + "coin_id": "poa-network", + "converted_last": { + "btc": 1.3e-06, + "eth": 7.036e-05, + "usd": 0.01324803 + }, + "converted_volume": { + "btc": 0.1595777, + "eth": 8.637423, + "usd": 1626.22 + }, + "is_anomaly": false, + "is_stale": false, + "last": 1.3e-06, + "last_fetch_at": "2019-08-21T08:36:07+00:00", + "last_traded_at": "2019-08-21T08:36:07+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "bibox", + "name": "Bibox" + }, + "target": "BTC", + "timestamp": "2019-08-21T08:36:07+00:00", + "trade_url": "https://www.bibox.com/exchange?coinPair=POA_BTC", + "trust_score": "yellow", + "volume": 122752.0737 + }, + { + "base": "POA", + "bid_ask_spread_percentage": 3.247202, + "coin_id": "poa-network", + "converted_last": { + "btc": 1.31e-06, + "eth": 7.077e-05, + "usd": 0.01332498 + }, + "converted_volume": { + "btc": 0.1127777, + "eth": 6.104291, + "usd": 1149.29 + }, + "is_anomaly": false, + "is_stale": false, + "last": 7.087e-05, + "last_fetch_at": "2019-08-21T08:35:50+00:00", + "last_traded_at": "2019-08-21T08:35:50+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "bibox", + "name": "Bibox" + }, + "target": "ETH", + "timestamp": "2019-08-21T08:35:50+00:00", + "trade_url": "https://www.bibox.com/exchange?coinPair=POA_ETH", + "trust_score": "yellow", + "volume": 86251.0552 + }, + { + "base": "POA20", + "bid_ask_spread_percentage": 13.032676, + "coin_id": "poa-network", + "converted_last": { + "btc": 1.16e-06, + "eth": 6.257e-05, + "usd": 0.01177973 + }, + "converted_volume": { + "btc": 0.00087672, + "eth": 0.04748752, + "usd": 8.94 + }, + "is_anomaly": false, + "is_stale": false, + "last": 1.1551e-06, + "last_fetch_at": "2019-08-21T08:37:38+00:00", + "last_traded_at": "2019-08-21T07:08:25+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "hitbtc", + "name": "HitBTC" + }, + "target": "BTC", + "timestamp": "2019-08-21T07:08:25+00:00", + "trade_url": "https://hitbtc.com/POA20-to-BTC", + "trust_score": "red", + "volume": 759.0 + }, + { + "base": "POA20", + "bid_ask_spread_percentage": 33.072445, + "coin_id": "poa-network", + "converted_last": { + "btc": 1.57e-06, + "eth": 8.48e-05, + "usd": 0.01595278 + }, + "converted_volume": { + "btc": 0.00021915, + "eth": 0.0118714, + "usd": 2.23 + }, + "is_anomaly": false, + "is_stale": false, + "last": 8.4891e-05, + "last_fetch_at": "2019-08-21T08:37:21+00:00", + "last_traded_at": "2019-08-21T07:37:25+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "hitbtc", + "name": "HitBTC" + }, + "target": "ETH", + "timestamp": "2019-08-21T07:37:25+00:00", + "trade_url": "https://hitbtc.com/POA20-to-ETH", + "trust_score": "red", + "volume": 140.0 + }, + { + "base": "POA20", + "bid_ask_spread_percentage": 53.1004, + "coin_id": "poa-network", + "converted_last": { + "btc": 1.15e-06, + "eth": 6.232e-05, + "usd": 0.0117249 + }, + "converted_volume": { + "btc": 7.478e-05, + "eth": 0.00405098, + "usd": 0.762119 + }, + "is_anomaly": false, + "is_stale": false, + "last": 0.0117249, + "last_fetch_at": "2019-08-21T08:37:46+00:00", + "last_traded_at": "2019-08-21T07:37:33+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "hitbtc", + "name": "HitBTC" + }, + "target": "USD", + "timestamp": "2019-08-21T07:37:33+00:00", + "trade_url": "https://hitbtc.com/POA20-to-USD", + "trust_score": null, + "volume": 65.0 + }, + { + "base": "POA20", + "bid_ask_spread_percentage": null, + "coin_id": "poa-network", + "converted_last": { + "btc": 1.32e-06, + "eth": 7.134e-05, + "usd": 0.01339322 + }, + "converted_volume": { + "btc": 0.03831341, + "eth": 2.073192, + "usd": 389.22 + }, + "is_anomaly": false, + "is_stale": false, + "last": 0.034733328618915156, + "last_fetch_at": "2019-08-21T08:21:59+00:00", + "last_traded_at": "2019-08-21T08:21:59+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "bancor", + "name": "Bancor Network" + }, + "target": "BNT", + "timestamp": "2019-08-21T08:21:59+00:00", + "trade_url": null, + "trust_score": null, + "volume": 29061.03634563883 + }, + { + "base": "POA20", + "bid_ask_spread_percentage": null, + "coin_id": "poa-network", + "converted_last": { + "btc": 1.31e-06, + "eth": 7.074e-05, + "usd": 0.0132809 + }, + "converted_volume": { + "btc": 0.009587, + "eth": 0.51876605, + "usd": 97.39 + }, + "is_anomaly": false, + "is_stale": false, + "last": 7.0704231362995e-05, + "last_fetch_at": "2019-08-21T08:26:12+00:00", + "last_traded_at": "2019-08-21T08:21:13+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "uniswap", + "name": "Uniswap" + }, + "target": "ETH", + "timestamp": "2019-08-21T08:21:13+00:00", + "trade_url": null, + "trust_score": null, + "volume": 7333.316809051611 + }, + { + "base": "POA", + "bid_ask_spread_percentage": 40.083051, + "coin_id": "poa-network", + "converted_last": { + "btc": 1.33e-06, + "eth": 7.005e-05, + "usd": 0.01377146 + }, + "converted_volume": { + "btc": 0.0022752, + "eth": 0.12002061, + "usd": 23.59 + }, + "is_anomaly": false, + "is_stale": true, + "last": 7.004e-05, + "last_fetch_at": "2019-08-21T08:32:14+00:00", + "last_traded_at": "2019-08-18T18:43:13+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "ethfinex", + "name": "Ethfinex" + }, + "target": "ETH", + "timestamp": "2019-08-18T18:43:13+00:00", + "trade_url": "https://ethfinex.com", + "trust_score": "red", + "volume": 1713.3067 + }, + { + "base": "POA", + "bid_ask_spread_percentage": 44.440399, + "coin_id": "poa-network", + "converted_last": { + "btc": 1.33e-06, + "eth": 7.311e-05, + "usd": 0.013499 + }, + "converted_volume": { + "btc": 0.00442255, + "eth": 0.24305992, + "usd": 44.88 + }, + "is_anomaly": false, + "is_stale": true, + "last": 0.013499, + "last_fetch_at": "2019-08-21T08:32:13+00:00", + "last_traded_at": "2019-08-14T17:19:27+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "ethfinex", + "name": "Ethfinex" + }, + "target": "USD", + "timestamp": "2019-08-14T17:19:27+00:00", + "trade_url": "https://ethfinex.com", + "trust_score": "red", + "volume": 3324.44883078 + }, + { + "base": "POA", + "bid_ask_spread_percentage": 14.012015, + "coin_id": "poa-network", + "converted_last": { + "btc": 1.36e-06, + "eth": 7.49e-05, + "usd": 0.01446844 + }, + "converted_volume": { + "btc": 5.45e-06, + "eth": 0.00029958, + "usd": 0.057874 + }, + "is_anomaly": false, + "is_stale": true, + "last": 7.4743e-05, + "last_fetch_at": "2019-08-21T08:37:09+00:00", + "last_traded_at": "2019-08-21T02:52:09+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "hitbtc", + "name": "HitBTC" + }, + "target": "ETH", + "timestamp": "2019-08-21T02:52:09+00:00", + "trade_url": "https://hitbtc.com/POA-to-ETH", + "trust_score": null, + "volume": 4.0 + }, + { + "base": "POA", + "bid_ask_spread_percentage": 64.645979, + "coin_id": "poa-network", + "converted_last": { + "btc": 1.36e-06, + "eth": 7.473e-05, + "usd": 0.01443604 + }, + "converted_volume": { + "btc": 2.72e-06, + "eth": 0.00014946, + "usd": 0.02887207 + }, + "is_anomaly": false, + "is_stale": true, + "last": 0.0143016, + "last_fetch_at": "2019-08-21T08:37:44+00:00", + "last_traded_at": "2019-08-21T02:52:25+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "hitbtc", + "name": "HitBTC" + }, + "target": "DAI", + "timestamp": "2019-08-21T02:52:25+00:00", + "trade_url": "https://hitbtc.com/POA-to-DAI", + "trust_score": null, + "volume": 2.0 + }, + { + "base": "POA", + "bid_ask_spread_percentage": 64.353312, + "coin_id": "poa-network", + "converted_last": { + "btc": 2.23e-06, + "eth": 0.00012505, + "usd": 0.02310309 + }, + "converted_volume": { + "btc": 0.00275182, + "eth": 0.15430951, + "usd": 28.51 + }, + "is_anomaly": true, + "is_stale": true, + "last": 2.23e-06, + "last_fetch_at": "2019-08-21T08:32:12+00:00", + "last_traded_at": "2019-08-17T12:50:06+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "ethfinex", + "name": "Ethfinex" + }, + "target": "BTC", + "timestamp": "2019-08-17T12:50:06+00:00", + "trade_url": "https://ethfinex.com", + "trust_score": "red", + "volume": 1234.0 + }, + { + "base": "POA", + "bid_ask_spread_percentage": 21.080977, + "coin_id": "poa-network", + "converted_last": { + "btc": 1.23e-06, + "eth": 6.72e-05, + "usd": 0.01322824 + }, + "converted_volume": { + "btc": 0.0, + "eth": 0.0, + "usd": 0.0 + }, + "is_anomaly": true, + "is_stale": true, + "last": 1.2331e-06, + "last_fetch_at": "2019-08-21T08:37:17+00:00", + "last_traded_at": "2019-08-20T18:50:31+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "hitbtc", + "name": "HitBTC" + }, + "target": "BTC", + "timestamp": "2019-08-20T18:50:31+00:00", + "trade_url": "https://hitbtc.com/POA-to-BTC", + "trust_score": null, + "volume": 0.0 + }, + { + "base": "POA", + "bid_ask_spread_percentage": 36.441715, + "coin_id": "poa-network", + "converted_last": { + "btc": 1.22e-06, + "eth": 6.66e-05, + "usd": 0.0131106 + }, + "converted_volume": { + "btc": 0.0, + "eth": 0.0, + "usd": 0.0 + }, + "is_anomaly": true, + "is_stale": true, + "last": 0.0131106, + "last_fetch_at": "2019-08-21T08:37:14+00:00", + "last_traded_at": "2019-08-20T18:50:15+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "hitbtc", + "name": "HitBTC" + }, + "target": "USD", + "timestamp": "2019-08-20T18:50:15+00:00", + "trade_url": "https://hitbtc.com/POA-to-USD", + "trust_score": null, + "volume": 0.0 + }, + { + "base": "POA20", + "bid_ask_spread_percentage": 70.656026, + "coin_id": "poa-network", + "converted_last": { + "btc": 7.522e-07, + "eth": 4.006e-05, + "usd": 0.0080416 + }, + "converted_volume": { + "btc": 0.0, + "eth": 0.0, + "usd": 0.0 + }, + "is_anomaly": true, + "is_stale": true, + "last": 0.008, + "last_fetch_at": "2019-08-21T08:37:29+00:00", + "last_traded_at": "2019-08-19T09:09:06+00:00", + "market": { + "has_trading_incentive": false, + "identifier": "hitbtc", + "name": "HitBTC" + }, + "target": "DAI", + "timestamp": "2019-08-19T09:09:06+00:00", + "trade_url": "https://hitbtc.com/POA20-to-DAI", + "trust_score": null, + "volume": 0.0 + } + ] +} From 48a01e98a599ad34c892fa01fb031059ef2fbcfe Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Thu, 22 Aug 2019 11:22:54 +0300 Subject: [PATCH 06/14] fix json decoding --- apps/explorer/lib/explorer/exchange_rates/source.ex | 7 ++++++- .../lib/explorer/exchange_rates/source/coin_gecko.ex | 4 +--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/explorer/lib/explorer/exchange_rates/source.ex b/apps/explorer/lib/explorer/exchange_rates/source.ex index d733b22222..6d95e48796 100644 --- a/apps/explorer/lib/explorer/exchange_rates/source.ex +++ b/apps/explorer/lib/explorer/exchange_rates/source.ex @@ -39,7 +39,12 @@ defmodule Explorer.ExchangeRates.Source do defp fetch_exchange_rates_request(source) do case HTTPoison.get(source.source_url(), headers()) do {:ok, %Response{body: body, status_code: 200}} -> - {:ok, source.format_data(body)} + result = + body + |> decode_json() + |> source.format_data() + + {:ok, result} {:ok, %Response{body: body, status_code: status_code}} when status_code in 400..499 -> {:error, decode_json(body)["error"]} diff --git a/apps/explorer/lib/explorer/exchange_rates/source/coin_gecko.ex b/apps/explorer/lib/explorer/exchange_rates/source/coin_gecko.ex index 5b0bed2b3b..95ecafb046 100644 --- a/apps/explorer/lib/explorer/exchange_rates/source/coin_gecko.ex +++ b/apps/explorer/lib/explorer/exchange_rates/source/coin_gecko.ex @@ -11,12 +11,10 @@ defmodule Explorer.ExchangeRates.Source.CoinGecko do @behaviour Source @impl Source - def format_data(%{"market_data" => _} = data) do + def format_data(%{"market_data" => _} = json_data) do {:ok, price} = get_btc_price() btc_price = to_decimal(price) - json_data = decode_json(data) - market_data = json_data["market_data"] {:ok, last_updated, 0} = DateTime.from_iso8601(market_data["last_updated"]) From 372fb0d51d6e2e43a0ea3df6249de3e3026fd498 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 28 Aug 2019 12:57:01 +0300 Subject: [PATCH 07/14] remove CoinMarketCap logic --- apps/explorer/config/config.exs | 3 - .../lib/explorer/exchange_rates/source.ex | 25 +------- .../exchange_rates/source/coin_market_cap.ex | 52 ---------------- .../exchange_rates/source/token_bridge.ex | 2 +- .../source/coin_market_cap_test.exs | 59 ------------------- 5 files changed, 2 insertions(+), 139 deletions(-) delete mode 100644 apps/explorer/lib/explorer/exchange_rates/source/coin_market_cap.ex delete mode 100644 apps/explorer/test/explorer/exchange_rates/source/coin_market_cap_test.exs diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs index 39307741cd..10e8a66e82 100644 --- a/apps/explorer/config/config.exs +++ b/apps/explorer/config/config.exs @@ -31,9 +31,6 @@ config :explorer, Explorer.ChainSpec.GenesisData, enabled: false, chain_spec_pat config :explorer, Explorer.Chain.Cache.BlockNumber, enabled: true -config :explorer, Explorer.ExchangeRates.Source.CoinMarketCap, - pages: String.to_integer(System.get_env("COINMARKETCAP_PAGES") || "10") - config :explorer, Explorer.ExchangeRates.Source.CoinGecko, coin_id: System.get_env("COIN_GECKO_ID", "poa-network") balances_update_interval = diff --git a/apps/explorer/lib/explorer/exchange_rates/source.ex b/apps/explorer/lib/explorer/exchange_rates/source.ex index 6d95e48796..fdb0e06fc3 100644 --- a/apps/explorer/lib/explorer/exchange_rates/source.ex +++ b/apps/explorer/lib/explorer/exchange_rates/source.ex @@ -2,8 +2,6 @@ defmodule Explorer.ExchangeRates.Source do @moduledoc """ Behaviour for fetching exchange rates from external sources. """ - - alias Explorer.ExchangeRates.Source.CoinMarketCap alias Explorer.ExchangeRates.Token alias HTTPoison.{Error, Response} @@ -12,28 +10,7 @@ defmodule Explorer.ExchangeRates.Source do """ @spec fetch_exchange_rates(module) :: {:ok, [Token.t()]} | {:error, any} def fetch_exchange_rates(source \\ exchange_rates_source()) do - if(source == CoinMarketCap) do - fetch_exchange_rates_from_paginable_source(source) - else - fetch_exchange_rates_request(source) - end - end - - defp fetch_exchange_rates_from_paginable_source(source, page \\ 1) do - case HTTPoison.get(source.source_url(page), headers()) do - {:ok, %Response{body: body, status_code: 200}} -> - cond do - body =~ Explorer.coin() -> {:ok, source.format_data(body)} - page == source.max_page_number -> {:error, "exchange rates not found for this network"} - true -> fetch_exchange_rates_from_paginable_source(source, page + 1) - end - - {:ok, %Response{body: body, status_code: status_code}} when status_code in 400..502 -> - {:error, decode_json(body)["error"]} - - {:error, %Error{reason: reason}} -> - {:error, reason} - end + fetch_exchange_rates_request(source) end defp fetch_exchange_rates_request(source) do diff --git a/apps/explorer/lib/explorer/exchange_rates/source/coin_market_cap.ex b/apps/explorer/lib/explorer/exchange_rates/source/coin_market_cap.ex deleted file mode 100644 index efe592e0fa..0000000000 --- a/apps/explorer/lib/explorer/exchange_rates/source/coin_market_cap.ex +++ /dev/null @@ -1,52 +0,0 @@ -defmodule Explorer.ExchangeRates.Source.CoinMarketCap do - @moduledoc """ - Adapter for fetching exchange rates from https://coinmarketcap.com. - """ - - alias Explorer.ExchangeRates.{Source, Token} - - import Source, only: [decode_json: 1, to_decimal: 1] - - @behaviour Source - - @impl Source - def format_data(data) do - for item <- decode_json(data), not is_nil(item["last_updated"]) do - {last_updated_as_unix, _} = Integer.parse(item["last_updated"]) - last_updated = DateTime.from_unix!(last_updated_as_unix) - - %Token{ - available_supply: to_decimal(item["available_supply"]), - total_supply: to_decimal(item["total_supply"]), - btc_value: to_decimal(item["price_btc"]), - id: item["id"], - last_updated: last_updated, - market_cap_usd: to_decimal(item["market_cap_usd"]), - name: item["name"], - symbol: item["symbol"], - usd_value: to_decimal(item["price_usd"]), - volume_24h_usd: to_decimal(item["24h_volume_usd"]) - } - end - end - - @impl Source - def source_url do - source_url(1) - end - - def source_url(page) do - "#{base_url()}/v1/ticker/?start=#{page - 1}00" - end - - def max_page_number, do: config(:pages) - - defp base_url do - config(:base_url) || "https://api.coinmarketcap.com" - end - - @spec config(atom()) :: term - defp config(key) do - Application.get_env(:explorer, __MODULE__, [])[key] - end -end diff --git a/apps/explorer/lib/explorer/exchange_rates/source/token_bridge.ex b/apps/explorer/lib/explorer/exchange_rates/source/token_bridge.ex index 03234ff649..531e3ab181 100644 --- a/apps/explorer/lib/explorer/exchange_rates/source/token_bridge.ex +++ b/apps/explorer/lib/explorer/exchange_rates/source/token_bridge.ex @@ -45,7 +45,7 @@ defmodule Explorer.ExchangeRates.Source.TokenBridge do @spec secondary_source() :: module() defp secondary_source do - config(:secondary_source) || Explorer.ExchangeRates.Source.CoinMarketCap + config(:secondary_source) || Explorer.ExchangeRates.Source.CoinGecko end @spec config(atom()) :: term diff --git a/apps/explorer/test/explorer/exchange_rates/source/coin_market_cap_test.exs b/apps/explorer/test/explorer/exchange_rates/source/coin_market_cap_test.exs deleted file mode 100644 index e0f1693212..0000000000 --- a/apps/explorer/test/explorer/exchange_rates/source/coin_market_cap_test.exs +++ /dev/null @@ -1,59 +0,0 @@ -defmodule Explorer.ExchangeRates.Source.CoinMarketCapTest do - use ExUnit.Case - - alias Explorer.ExchangeRates.Token - alias Explorer.ExchangeRates.Source.CoinMarketCap - - @json """ - [ - { - "id": "poa-network", - "name": "POA Network", - "symbol": "POA", - "rank": "103", - "price_usd": "0.485053", - "price_btc": "0.00007032", - "24h_volume_usd": "20185000.0", - "market_cap_usd": "98941986.0", - "available_supply": "203981804.0", - "total_supply": "254473964.0", - "max_supply": null, - "percent_change_1h": "-0.66", - "percent_change_24h": "12.34", - "percent_change_7d": "49.15", - "last_updated": "1523473200" - } - ] - """ - - describe "format_data/1" do - test "returns valid tokens with valid data" do - expected_date = ~N[2018-04-11 19:00:00] |> DateTime.from_naive!("Etc/UTC") - - expected = [ - %Token{ - available_supply: Decimal.new("203981804.0"), - total_supply: Decimal.new("254473964.0"), - btc_value: Decimal.new("0.00007032"), - id: "poa-network", - last_updated: expected_date, - market_cap_usd: Decimal.new("98941986.0"), - name: "POA Network", - symbol: "POA", - usd_value: Decimal.new("0.485053"), - volume_24h_usd: Decimal.new("20185000.0") - } - ] - - assert expected == CoinMarketCap.format_data(@json) - end - - test "returns nothing when given bad data" do - bad_data = """ - [{"id": "poa-network"}] - """ - - assert [] = CoinMarketCap.format_data(bad_data) - end - end -end From 56bb2018fb4cde594adc425217479095db91eb86 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 28 Aug 2019 13:15:22 +0300 Subject: [PATCH 08/14] fix test --- .../exchange_rates/source/token_bridge.ex | 10 +++++++- .../source/token_bridge_test.exs | 24 +++---------------- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/apps/explorer/lib/explorer/exchange_rates/source/token_bridge.ex b/apps/explorer/lib/explorer/exchange_rates/source/token_bridge.ex index 531e3ab181..aa2b849a11 100644 --- a/apps/explorer/lib/explorer/exchange_rates/source/token_bridge.ex +++ b/apps/explorer/lib/explorer/exchange_rates/source/token_bridge.ex @@ -30,7 +30,7 @@ defmodule Explorer.ExchangeRates.Source.TokenBridge do btc_value: original_token.btc_value, id: original_token.id, last_updated: original_token.last_updated, - market_cap_usd: Decimal.mult(to_decimal(Chain.circulating_supply()), original_token.usd_value), + market_cap_usd: market_cap_usd(Chain.circulating_supply(), original_token), name: original_token.name, symbol: original_token.symbol, usd_value: original_token.usd_value, @@ -38,6 +38,14 @@ defmodule Explorer.ExchangeRates.Source.TokenBridge do } end + defp market_cap_usd(nil, _original_token), do: Decimal.new(0) + + defp market_cap_usd(supply, original_token) do + supply + |> to_decimal() + |> Decimal.mult(original_token.usd_value) + end + @impl Source def source_url do secondary_source().source_url() diff --git a/apps/explorer/test/explorer/exchange_rates/source/token_bridge_test.exs b/apps/explorer/test/explorer/exchange_rates/source/token_bridge_test.exs index d5bd5f9b96..078c280fda 100644 --- a/apps/explorer/test/explorer/exchange_rates/source/token_bridge_test.exs +++ b/apps/explorer/test/explorer/exchange_rates/source/token_bridge_test.exs @@ -3,27 +3,9 @@ defmodule Explorer.ExchangeRates.Source.TokenBridgeTest do alias Explorer.ExchangeRates.Source.TokenBridge alias Explorer.ExchangeRates.Token - @json """ - [ - { - "id": "poa-network", - "name": "POA Network", - "symbol": "POA", - "rank": "103", - "price_usd": "0.485053", - "price_btc": "0.00007032", - "24h_volume_usd": "20185000.0", - "market_cap_usd": "98941986.0", - "available_supply": "203981804.0", - "total_supply": "254473964.0", - "max_supply": null, - "percent_change_1h": "-0.66", - "percent_change_24h": "12.34", - "percent_change_7d": "49.15", - "last_updated": "1523473200" - } - ] - """ + @json "#{File.cwd!()}/test/support/fixture/exchange_rates/coin_gecko.json" + |> File.read!() + |> Jason.decode!() describe "format_data/1" do test "bring a list with one %Token{}" do From 9bd5ea52710b2b3bc1d5839e27e3c011fc10d630 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 28 Aug 2019 13:20:44 +0300 Subject: [PATCH 09/14] add new column to env vars --- docs/env-variables.md | 104 +++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/docs/env-variables.md b/docs/env-variables.md index 2b4f767f13..2dc8763b8d 100644 --- a/docs/env-variables.md +++ b/docs/env-variables.md @@ -14,55 +14,55 @@ $ export NETWORK=POA ``` -| Variable | Required | Description | Default | Version | Need recompile | -| --- | --- | --- | ---| --- | --- | -| `NETWORK`| :white_check_mark: | Environment variable for the main EVM network such as Ethereum Network or POA Network | POA Network | all | | -| `SUBNETWORK` | :white_check_mark: | Environment variable for the subnetwork such as Core or Sokol Network | Sokol Testnet | all | | -| `NETWORK_ICON` | :white_check_mark: | Environment variable for the main network icon or testnet icon. Two options are `_test_network_icon.html` and `_network_icon.html` | `_test_network_icon.html` | all | | -| `LOGO` | :white_check_mark: | Environment variable for the logo image location. The logo files names for different chains can be found [here](https://github.com/poanetwork/blockscout/tree/master/apps/block_scout_web/assets/static/images) | /images/blockscout_logo.svg | all | | -| `ETHEREUM_JSONRPC_VARIANT` | :white_check_mark: | This environment variable is used to tell the application which RPC Client the node is using (i.e. Geth, Parity, or Ganache) | parity | all | | -| `ETHEREUM_JSONRPC_HTTP_URL` | :white_check_mark: | The RPC endpoint used to fetch blocks, transactions, receipts, tokens. | localhost:8545 | all | | -| `ETHEREUM_JSONRPC_TRACE_URL` | | The RPC endpoint specifically for the Geth/Parity client used by trace_block and trace_replayTransaction. This can be used to designate a tracing node. | localhost:8545 | all | | -| `ETHEREUM_JSONRPC_WS_URL` | :white_check_mark: | The WebSockets RPC endpoint used to subscribe to the `newHeads` subscription alerting the indexer to fetch new blocks. | ws://localhost:8546 | all | | -| `NETWORK_PATH` | | Used to set a network path other than what is displayed in the root directory. An example would be to add /eth/mainnet/ to the root directory. | (empty) | all | | -| `SECRET_KEY_BASE` | :white_check_mark: | Use mix phx.gen.secret to generate a new Secret Key Base string to protect production assets. | (empty) | all | | -| `CHECK_ORIGIN` | | Used to check the origin of requests when the origin header is present. It defaults to false. In case of true, it will check against the host value. | false | all | | -| `PORT` | :white_check_mark: | Default port the application runs on is 4000 | 4000 | all | | -| `COIN` | :white_check_mark: | The coin here is checked via the Coinmarketcap API to obtain USD prices on graphs and other areas of the UI | POA | all | | -| `METADATA_CONTRACT` | | This environment variable is specifically used by POA Network to obtain Validators information to display in the UI. | (empty) | all | | -| `VALIDATORS_CONTRACT` | | This environment variable is specifically used by POA Network to obtain the Emission Fund contract. | (empty) | all | | -| `SUPPLY_MODULE` | | This environment variable is used by the xDai Chain in order to tell the application how to calculate the total supply of the chain. | false | all | | -| `SOURCE_MODULE` | | This environment variable is used to calculate the exchange rate and is specifically used by the xDai Chain. | false | all | | -| `DATABASE_URL` | | Production environment variable to define the Database endpoint. | (empty) | all | | -| `POOL_SIZE` | | Production environment variable to define the number of database connections allowed. | 20 | all | | -| `ECTO_USE_SSL` | | Production environment variable to use SSL on Ecto queries. | true | all | | -| `DATADOG_HOST` | | Host configuration setting for [Datadog integration](https://docs.datadoghq.com/integrations/) | (empty) | all | | -| `DATADOG_PORT` | | Port configuration setting for [Datadog integration](https://docs.datadoghq.com/integrations/). | (empty} | all | | -| `SPANDEX_BATCH_SIZE` | | [Spandex](https://github.com/spandex-project/spandex) and Datadog configuration setting. | (empty) | all | -| `SPANDEX_SYNC_THRESHOLD` | | [Spandex](https://github.com/spandex-project/spandex) and Datadog configuration setting. | (empty) | all | | -| `HEART_BEAT_TIMEOUT` | | Production environment variable to restart the application in the event of a crash. | 30 | all | | -| `HEART_COMMAND` | | Production environment variable to restart the application in the event of a crash. | systemctl restart explorer.service | all | | -| `BLOCKSCOUT_VERSION` | | Added to the footer to signify the current BlockScout version. | (empty) | v1.3.4+ | | -| `RELEASE_LINK` | | The link to Blockscout release notes in the footer. | https: //github.com/poanetwork/
blockscout/releases/
tag/${BLOCKSCOUT_VERSION} | v1.3.5+ | | -| `ELIXIR_VERSION` | | Elixir version to install on the node before Blockscout deploy. | (empty) | all | | -| `BLOCK_TRANSFORMER` | | Transformer for blocks: base or clique. | base | v1.3.4+ | | -| `GRAPHIQL_TRANSACTION` | | Default transaction in query to GraphiQL. | (empty) | v1.2.0+ | :white_check_mark: | -| `FIRST_BLOCK` | | The block number, where indexing begins from. | 0 | v1.3.8+ | | -| `LAST_BLOCK` | | The block number, where indexing stops. | (empty) | v2.0.3+ | | -| `TXS_COUNT_CACHE_PERIOD` | | Interval in seconds to restart the task, which calculates the total txs count. | 60 * 60 * 2 | v1.3.9+ | | -| `ADDRESS_WITH_BALANCES`
`_UPDATE_INTERVAL`| | Interval in seconds to restart the task, which calculates addresses with balances. | 30 * 60 | v1.3.9+ | | -| `LINK_TO_OTHER_EXPLORERS` | | true/false. If true, links to other explorers are added in the footer | (empty) | v1.3.0+ | | -| `COINMARKETCAP_PAGES` | | the number of pages on coinmarketcap to list in order to find token's price | 10 | v1.3.10+ | | -| `SUPPORTED_CHAINS` | | Array of supported chains that displays in the footer and in the chains dropdown. This var was introduced in this PR [#1900](https://github.com/poanetwork/blockscout/pull/1900) and looks like an array of JSON objects. | (empty) | v2.0.0+ | | -| `BLOCK_COUNT_CACHE_PERIOD ` | | time to live of cache in seconds. This var was introduced in [#1876](https://github.com/poanetwork/blockscout/pull/1876) | 600 | v2.0.0+ | | -| `ALLOWED_EVM_VERSIONS ` | | the comma-separated list of allowed EVM versions for contracts verification. This var was introduced in [#1964](https://github.com/poanetwork/blockscout/pull/1964) | "homestead, tangerineWhistle, spuriousDragon, byzantium, constantinople, petersburg" | v2.0.0+ | | -| `AVERAGE_BLOCK_CACHE_PERIOD` | | Update of average block cache, in seconds | 30 minutes | v2.0.2+ | -| `MARKET_HISTORY_CACHE_PERIOD` | | Update of market history cache, in seconds | 6 hours | v2.0.2+ | -| `DISABLE_WEBAPP` | | If `true`, endpoints to webapp are hidden (compile-time) | `false` | v2.0.3+ | :white_check_mark: | -| `DISABLE_READ_API` | | If `true`, read-only endpoints to API are hidden (compile-time) | `false` | v2.0.3+ | :white_check_mark: | -| `DISABLE_WRITE_API` | | If `true`, write endpoints to API are hidden (compile-time) | `false` | v2.0.3+ | :white_check_mark: | -| `DISABLE_INDEXER` | | If `true`, indexer application doesn't run | `false` | v2.0.3+ | :white_check_mark: | -| `WEBAPP_URL` | | Link to web application instance, e.g. `http://host/path` | (empty) | v2.0.3+ | | -| `API_URL` | | Link to API instance, e.g. `http://host/path` | (empty) | v2.0.3+ | | -| `CHAIN_SPEC_PATH` | | Chain specification path (absolute file system path or url) to import block emission reward ranges and genesis account balances from | (empty) | master | | -| `COIN_GECKO_ID` | | CoinGecko coin id required for fetching an exchange rate | poa-network | master | \ No newline at end of file +| Variable | Required | Description | Default | Version | Need recompile | Deprecated in Version | +| --- | --- | --- | ---| --- | --- | --- | +| `NETWORK`| :white_check_mark: | Environment variable for the main EVM network such as Ethereum Network or POA Network | POA Network | all | | | +| `SUBNETWORK` | :white_check_mark: | Environment variable for the subnetwork such as Core or Sokol Network | Sokol Testnet | all | | | +| `NETWORK_ICON` | :white_check_mark: | Environment variable for the main network icon or testnet icon. Two options are `_test_network_icon.html` and `_network_icon.html` | `_test_network_icon.html` | all | | | +| `LOGO` | :white_check_mark: | Environment variable for the logo image location. The logo files names for different chains can be found [here](https://github.com/poanetwork/blockscout/tree/master/apps/block_scout_web/assets/static/images) | /images/blockscout_logo.svg | all | | | +| `ETHEREUM_JSONRPC_VARIANT` | :white_check_mark: | This environment variable is used to tell the application which RPC Client the node is using (i.e. Geth, Parity, or Ganache) | parity | all | | | +| `ETHEREUM_JSONRPC_HTTP_URL` | :white_check_mark: | The RPC endpoint used to fetch blocks, transactions, receipts, tokens. | localhost:8545 | all | | | +| `ETHEREUM_JSONRPC_TRACE_URL` | | The RPC endpoint specifically for the Geth/Parity client used by trace_block and trace_replayTransaction. This can be used to designate a tracing node. | localhost:8545 | all | | | +| `ETHEREUM_JSONRPC_WS_URL` | :white_check_mark: | The WebSockets RPC endpoint used to subscribe to the `newHeads` subscription alerting the indexer to fetch new blocks. | ws://localhost:8546 | all | | | +| `NETWORK_PATH` | | Used to set a network path other than what is displayed in the root directory. An example would be to add /eth/mainnet/ to the root directory. | (empty) | all | | | +| `SECRET_KEY_BASE` | :white_check_mark: | Use mix phx.gen.secret to generate a new Secret Key Base string to protect production assets. | (empty) | all | | | +| `CHECK_ORIGIN` | | Used to check the origin of requests when the origin header is present. It defaults to false. In case of true, it will check against the host value. | false | all | | | +| `PORT` | :white_check_mark: | Default port the application runs on is 4000 | 4000 | all | | | +| `COIN` | :white_check_mark: | The coin here is checked via the Coinmarketcap API to obtain USD prices on graphs and other areas of the UI | POA | all | | | +| `METADATA_CONTRACT` | | This environment variable is specifically used by POA Network to obtain Validators information to display in the UI. | (empty) | all | | | +| `VALIDATORS_CONTRACT` | | This environment variable is specifically used by POA Network to obtain the Emission Fund contract. | (empty) | all | | | +| `SUPPLY_MODULE` | | This environment variable is used by the xDai Chain in order to tell the application how to calculate the total supply of the chain. | false | all | | | +| `SOURCE_MODULE` | | This environment variable is used to calculate the exchange rate and is specifically used by the xDai Chain. | false | all | | | +| `DATABASE_URL` | | Production environment variable to define the Database endpoint. | (empty) | all | | | +| `POOL_SIZE` | | Production environment variable to define the number of database connections allowed. | 20 | all | | | +| `ECTO_USE_SSL` | | Production environment variable to use SSL on Ecto queries. | true | all | | | +| `DATADOG_HOST` | | Host configuration setting for [Datadog integration](https://docs.datadoghq.com/integrations/) | (empty) | all | | | +| `DATADOG_PORT` | | Port configuration setting for [Datadog integration](https://docs.datadoghq.com/integrations/). | (empty} | all | | | +| `SPANDEX_BATCH_SIZE` | | [Spandex](https://github.com/spandex-project/spandex) and Datadog configuration setting. | (empty) | all | | +| `SPANDEX_SYNC_THRESHOLD` | | [Spandex](https://github.com/spandex-project/spandex) and Datadog configuration setting. | (empty) | all | | | +| `HEART_BEAT_TIMEOUT` | | Production environment variable to restart the application in the event of a crash. | 30 | all | | | +| `HEART_COMMAND` | | Production environment variable to restart the application in the event of a crash. | systemctl restart explorer.service | all | | | +| `BLOCKSCOUT_VERSION` | | Added to the footer to signify the current BlockScout version. | (empty) | v1.3.4+ | | | +| `RELEASE_LINK` | | The link to Blockscout release notes in the footer. | https: //github.com/poanetwork/
blockscout/releases/
tag/${BLOCKSCOUT_VERSION} | v1.3.5+ | | | +| `ELIXIR_VERSION` | | Elixir version to install on the node before Blockscout deploy. | (empty) | all | | | +| `BLOCK_TRANSFORMER` | | Transformer for blocks: base or clique. | base | v1.3.4+ | | | +| `GRAPHIQL_TRANSACTION` | | Default transaction in query to GraphiQL. | (empty) | v1.2.0+ | :white_check_mark: | | +| `FIRST_BLOCK` | | The block number, where indexing begins from. | 0 | v1.3.8+ | | | +| `LAST_BLOCK` | | The block number, where indexing stops. | (empty) | v2.0.3+ | | | +| `TXS_COUNT_CACHE_PERIOD` | | Interval in seconds to restart the task, which calculates the total txs count. | 60 * 60 * 2 | v1.3.9+ | | | +| `ADDRESS_WITH_BALANCES`
`_UPDATE_INTERVAL`| | Interval in seconds to restart the task, which calculates addresses with balances. | 30 * 60 | v1.3.9+ | | | +| `LINK_TO_OTHER_EXPLORERS` | | true/false. If true, links to other explorers are added in the footer | (empty) | v1.3.0+ | | | +| `COINMARKETCAP_PAGES` | | the number of pages on coinmarketcap to list in order to find token's price | 10 | v1.3.10+ | | master | +| `SUPPORTED_CHAINS` | | Array of supported chains that displays in the footer and in the chains dropdown. This var was introduced in this PR [#1900](https://github.com/poanetwork/blockscout/pull/1900) and looks like an array of JSON objects. | (empty) | v2.0.0+ | | | +| `BLOCK_COUNT_CACHE_PERIOD ` | | time to live of cache in seconds. This var was introduced in [#1876](https://github.com/poanetwork/blockscout/pull/1876) | 600 | v2.0.0+ | | | +| `ALLOWED_EVM_VERSIONS ` | | the comma-separated list of allowed EVM versions for contracts verification. This var was introduced in [#1964](https://github.com/poanetwork/blockscout/pull/1964) | "homestead, tangerineWhistle, spuriousDragon, byzantium, constantinople, petersburg" | v2.0.0+ | | | +| `AVERAGE_BLOCK_CACHE_PERIOD` | | Update of average block cache, in seconds | 30 minutes | v2.0.2+ | | +| `MARKET_HISTORY_CACHE_PERIOD` | | Update of market history cache, in seconds | 6 hours | v2.0.2+ | | +| `DISABLE_WEBAPP` | | If `true`, endpoints to webapp are hidden (compile-time) | `false` | v2.0.3+ | :white_check_mark: | | +| `DISABLE_READ_API` | | If `true`, read-only endpoints to API are hidden (compile-time) | `false` | v2.0.3+ | :white_check_mark: | | +| `DISABLE_WRITE_API` | | If `true`, write endpoints to API are hidden (compile-time) | `false` | v2.0.3+ | :white_check_mark: | | +| `DISABLE_INDEXER` | | If `true`, indexer application doesn't run | `false` | v2.0.3+ | :white_check_mark: | | +| `WEBAPP_URL` | | Link to web application instance, e.g. `http://host/path` | (empty) | v2.0.3+ | | | +| `API_URL` | | Link to API instance, e.g. `http://host/path` | (empty) | v2.0.3+ | | | +| `CHAIN_SPEC_PATH` | | Chain specification path (absolute file system path or url) to import block emission reward ranges and genesis account balances from | (empty) | master | | | +| `COIN_GECKO_ID` | | CoinGecko coin id required for fetching an exchange rate | poa-network | master | | | From e40786a9bbec5212e884d3eec53bb93637ff5881 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 28 Aug 2019 13:32:12 +0300 Subject: [PATCH 10/14] mock actual request --- .../source/token_bridge_test.exs | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/apps/explorer/test/explorer/exchange_rates/source/token_bridge_test.exs b/apps/explorer/test/explorer/exchange_rates/source/token_bridge_test.exs index 078c280fda..febb9e7722 100644 --- a/apps/explorer/test/explorer/exchange_rates/source/token_bridge_test.exs +++ b/apps/explorer/test/explorer/exchange_rates/source/token_bridge_test.exs @@ -1,14 +1,41 @@ defmodule Explorer.ExchangeRates.Source.TokenBridgeTest do use Explorer.DataCase + + alias Explorer.ExchangeRates.Source.CoinGecko alias Explorer.ExchangeRates.Source.TokenBridge alias Explorer.ExchangeRates.Token + alias Plug.Conn @json "#{File.cwd!()}/test/support/fixture/exchange_rates/coin_gecko.json" |> File.read!() |> Jason.decode!() + @json_btc_price """ + { + "rates": { + "usd": { + "name": "US Dollar", + "unit": "$", + "value": 6547.418, + "type": "fiat" + } + } + } + """ + describe "format_data/1" do - test "bring a list with one %Token{}" do + setup do + bypass = Bypass.open() + Application.put_env(:explorer, CoinGecko, base_url: "http://localhost:#{bypass.port}") + + {:ok, bypass: bypass} + end + + test "bring a list with one %Token{}", %{bypass: bypass} do + Bypass.expect(bypass, "GET", "/exchange_rates", fn conn -> + Conn.resp(conn, 200, @json_btc_price) + end) + assert [%Token{}] = TokenBridge.format_data(@json) end end From 18f545b1b87b5302e76a5cbfecb836cc9db89c10 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 28 Aug 2019 15:44:57 +0300 Subject: [PATCH 11/14] fix env var description --- docs/env-variables.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/env-variables.md b/docs/env-variables.md index 2dc8763b8d..dd01cbe26f 100644 --- a/docs/env-variables.md +++ b/docs/env-variables.md @@ -28,7 +28,7 @@ $ export NETWORK=POA | `SECRET_KEY_BASE` | :white_check_mark: | Use mix phx.gen.secret to generate a new Secret Key Base string to protect production assets. | (empty) | all | | | | `CHECK_ORIGIN` | | Used to check the origin of requests when the origin header is present. It defaults to false. In case of true, it will check against the host value. | false | all | | | | `PORT` | :white_check_mark: | Default port the application runs on is 4000 | 4000 | all | | | -| `COIN` | :white_check_mark: | The coin here is checked via the Coinmarketcap API to obtain USD prices on graphs and other areas of the UI | POA | all | | | +| `COIN` | :white_check_mark: | The coin here is checked via the CoinGecko API to obtain USD prices on graphs and other areas of the UI | POA | all | | | | `METADATA_CONTRACT` | | This environment variable is specifically used by POA Network to obtain Validators information to display in the UI. | (empty) | all | | | | `VALIDATORS_CONTRACT` | | This environment variable is specifically used by POA Network to obtain the Emission Fund contract. | (empty) | all | | | | `SUPPLY_MODULE` | | This environment variable is used by the xDai Chain in order to tell the application how to calculate the total supply of the chain. | false | all | | | From 44cf49ea7580108815d94a1dd72d92f9e246c53d Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 2 Sep 2019 09:58:56 +0300 Subject: [PATCH 12/14] fix market_cap calculation --- apps/block_scout_web/lib/block_scout_web/views/chain_view.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/block_scout_web/lib/block_scout_web/views/chain_view.ex b/apps/block_scout_web/lib/block_scout_web/views/chain_view.ex index 506d6ff3c8..528cf3671f 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/chain_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/chain_view.ex @@ -4,7 +4,7 @@ defmodule BlockScoutWeb.ChainView do alias BlockScoutWeb.LayoutView defp market_cap(:standard, exchange_rate) do - exchange_rate.market_cap_usd + Decimal.mult(exchange_rate.available_supply, exchange_rate.usd_value) end defp market_cap(module, exchange_rate) do From ff1b7568d6762ec9a2cd84628347f9c2a5d6abb6 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 2 Sep 2019 10:51:14 +0300 Subject: [PATCH 13/14] fix tests --- .../lib/block_scout_web/views/chain_view.ex | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/views/chain_view.ex b/apps/block_scout_web/lib/block_scout_web/views/chain_view.ex index 528cf3671f..3033dbc0fe 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/chain_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/chain_view.ex @@ -3,8 +3,13 @@ defmodule BlockScoutWeb.ChainView do alias BlockScoutWeb.LayoutView - defp market_cap(:standard, exchange_rate) do - Decimal.mult(exchange_rate.available_supply, exchange_rate.usd_value) + defp market_cap(:standard, %{available_supply: available_supply, usd_value: usd_value}) + when is_nil(available_supply) or is_nil(usd_value) do + Decimal.new(0) + end + + defp market_cap(:standard, %{available_supply: available_supply, usd_value: usd_value}) do + Decimal.mult(available_supply, usd_value) end defp market_cap(module, exchange_rate) do From d2d99eb60b3170d7f5aa158c150ca7ea3093d510 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 2 Sep 2019 10:57:15 +0300 Subject: [PATCH 14/14] add fallback --- apps/block_scout_web/lib/block_scout_web/views/chain_view.ex | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/block_scout_web/lib/block_scout_web/views/chain_view.ex b/apps/block_scout_web/lib/block_scout_web/views/chain_view.ex index 3033dbc0fe..a5f0ebef50 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/chain_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/chain_view.ex @@ -12,6 +12,10 @@ defmodule BlockScoutWeb.ChainView do Decimal.mult(available_supply, usd_value) end + defp market_cap(:standard, exchange_rate) do + exchange_rate.market_cap_usd + end + defp market_cap(module, exchange_rate) do module.market_cap(exchange_rate) end