From 63a970c69d867ea74e9c56fd4531c1d4d6271552 Mon Sep 17 00:00:00 2001 From: Luke Imhoff Date: Thu, 10 May 2018 14:28:51 -0500 Subject: [PATCH 01/18] Update to credo 0.9.2 --- apps/explorer/mix.exs | 2 +- apps/explorer_web/mix.exs | 2 +- mix.lock | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/explorer/mix.exs b/apps/explorer/mix.exs index 39506b6576..215759ae40 100644 --- a/apps/explorer/mix.exs +++ b/apps/explorer/mix.exs @@ -70,7 +70,7 @@ defmodule Explorer.Mixfile do defp deps do [ {:bypass, "~> 0.8", only: :test}, - {:credo, "0.9.1", only: [:dev, :test], runtime: false}, + {:credo, "0.9.2", only: [:dev, :test], runtime: false}, {:crontab, "~> 1.1"}, {:dialyxir, "~> 0.5", only: [:dev, :test], runtime: false}, {:ethereumex, "~> 0.3"}, diff --git a/apps/explorer_web/mix.exs b/apps/explorer_web/mix.exs index b531535689..a374662127 100644 --- a/apps/explorer_web/mix.exs +++ b/apps/explorer_web/mix.exs @@ -70,7 +70,7 @@ defmodule ExplorerWeb.Mixfile do defp deps do [ {:cowboy, "~> 1.0"}, - {:credo, "0.9.1", only: [:dev, :test], runtime: false}, + {:credo, "0.9.2", only: [:dev, :test], runtime: false}, {:crontab, "~> 1.1"}, {:dialyxir, "~> 0.5", only: [:dev, :test], runtime: false}, {:ex_cldr_numbers, "~> 1.0"}, diff --git a/mix.lock b/mix.lock index 770401f6a9..9dac358b4e 100644 --- a/mix.lock +++ b/mix.lock @@ -7,7 +7,7 @@ "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"}, "cowboy": {:hex, :cowboy, "1.1.2", "61ac29ea970389a88eca5a65601460162d370a70018afe6f949a29dca91f3bb0", [:rebar3], [{:cowlib, "~> 1.0.2", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3.2", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"}, "cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], [], "hexpm"}, - "credo": {:hex, :credo, "0.9.1", "f021affa11b32a94dc2e807a6472ce0914289c9132f99644a97fc84432b202a1", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:poison, ">= 0.0.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"}, + "credo": {:hex, :credo, "0.9.2", "841d316612f568beb22ba310d816353dddf31c2d94aa488ae5a27bb53760d0bf", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:poison, ">= 0.0.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"}, "crontab": {:hex, :crontab, "1.1.2", "4784a50987b4a19af07a908f98e8a308b00f9c93efc5a7892155dc10cd8fc7d9", [:mix], [{:ecto, "~> 1.0 or ~> 2.0 or ~> 2.1", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"}, "db_connection": {:hex, :db_connection, "1.1.3", "89b30ca1ef0a3b469b1c779579590688561d586694a3ce8792985d4d7e575a61", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"}, "decimal": {:hex, :decimal, "1.4.1", "ad9e501edf7322f122f7fc151cce7c2a0c9ada96f2b0155b8a09a795c2029770", [:mix], [], "hexpm"}, From a07e673c43d3e6a5a50f9f8a65e6a8f9a8afc21d Mon Sep 17 00:00:00 2001 From: jimmay5469 Date: Fri, 4 May 2018 11:11:12 -0400 Subject: [PATCH 02/18] Fetch market history data for homepage Co-authored-by: tmecklem --- .../factories/market/market_history_factory.ex | 16 ++++++++++++++++ apps/explorer/test/support/factory.ex | 1 + .../explorer_web/controllers/chain_controller.ex | 8 +++++++- .../controllers/chain_controller_test.exs | 10 ++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 apps/explorer/test/support/factories/market/market_history_factory.ex diff --git a/apps/explorer/test/support/factories/market/market_history_factory.ex b/apps/explorer/test/support/factories/market/market_history_factory.ex new file mode 100644 index 0000000000..75395a1cf5 --- /dev/null +++ b/apps/explorer/test/support/factories/market/market_history_factory.ex @@ -0,0 +1,16 @@ +defmodule Explorer.Market.MarketHistoryFactory do + defmacro __using__(_opts) do + quote do + alias Explorer.Merket.MarketHistory + alias Explorer.Repo + + def market_history_factory do + %Explorer.Market.MarketHistory{ + closing_price: Decimal.new(Enum.random(1..10_000) / 100), + opening_price: Decimal.new(Enum.random(1..10_000) / 100), + date: Date.utc_today() + } + end + end + end +end diff --git a/apps/explorer/test/support/factory.ex b/apps/explorer/test/support/factory.ex index fe715c6d77..88cb72c2c3 100644 --- a/apps/explorer/test/support/factory.ex +++ b/apps/explorer/test/support/factory.ex @@ -10,4 +10,5 @@ defmodule Explorer.Factory do use Explorer.Chain.ReceiptFactory use Explorer.Chain.ToAddressFactory use Explorer.Chain.TransactionFactory + use Explorer.Market.MarketHistoryFactory end diff --git a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex index 8d3943730b..b50968f7e3 100644 --- a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex +++ b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex @@ -2,10 +2,16 @@ defmodule ExplorerWeb.ChainController do use ExplorerWeb, :controller alias Explorer.Chain.{Address, Block, Statistics, Transaction} + alias Explorer.Market alias ExplorerWeb.Chain def show(conn, _params) do - render(conn, "show.html", chain: Statistics.fetch()) + render( + conn, + "show.html", + chain: Statistics.fetch(), + market_history_data: Market.fetch_recent_history(8) + ) end def search(conn, %{"q" => query}) do diff --git a/apps/explorer_web/test/explorer_web/controllers/chain_controller_test.exs b/apps/explorer_web/test/explorer_web/controllers/chain_controller_test.exs index 73fd9506b3..6b9733fc81 100644 --- a/apps/explorer_web/test/explorer_web/controllers/chain_controller_test.exs +++ b/apps/explorer_web/test/explorer_web/controllers/chain_controller_test.exs @@ -58,6 +58,16 @@ defmodule ExplorerWeb.ChainControllerTest do assert(List.first(conn.assigns.chain.transactions).hash == "0xDECAFBAD") end + + test "returns market history data", %{conn: conn} do + today = Date.utc_today + for day <- -14..0, do: insert(:market_history, date: Date.add(today, day)) + + conn = get(conn, "/en") + + assert Map.has_key?(conn.assigns, :market_history_data) + assert length(conn.assigns.market_history_data) == 8 + end end describe "GET q/2" do From 204fba3d6dc8c2766bccbc19b9a22f2bebd4ebf0 Mon Sep 17 00:00:00 2001 From: jimmay5469 Date: Fri, 4 May 2018 11:47:32 -0400 Subject: [PATCH 03/18] Display market history data in chart Co-authored-by: jimmay5469 --- apps/explorer_web/assets/js/app.js | 1 + .../assets/js/lib/market_history_chart.js | 50 +++++++++++++++++++ apps/explorer_web/assets/package-lock.json | 41 ++++++++++++++- apps/explorer_web/assets/package.json | 1 + .../controllers/chain_controller.ex | 2 +- .../templates/chain/show.html.eex | 3 ++ .../lib/explorer_web/views/chain_view.ex | 10 ++++ 7 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 apps/explorer_web/assets/js/lib/market_history_chart.js diff --git a/apps/explorer_web/assets/js/app.js b/apps/explorer_web/assets/js/app.js index 361c7539a2..2073c9ac07 100644 --- a/apps/explorer_web/assets/js/app.js +++ b/apps/explorer_web/assets/js/app.js @@ -20,3 +20,4 @@ import 'bootstrap' // import socket from "./socket" import './lib/sidebar' +import './lib/market_history_chart' diff --git a/apps/explorer_web/assets/js/lib/market_history_chart.js b/apps/explorer_web/assets/js/lib/market_history_chart.js new file mode 100644 index 0000000000..76ba136879 --- /dev/null +++ b/apps/explorer_web/assets/js/lib/market_history_chart.js @@ -0,0 +1,50 @@ +import $ from 'jquery' +import Chart from 'chart.js' + +$('[data-chart="marketHistoryChart"]').each((i, ctx)=> { + const marketHistoryData = JSON.parse(ctx.dataset.market_history_data) + console.log("Market History Data: ", marketHistoryData) + + var myChart = new Chart(ctx, { + type: 'line', + responsive: true, + data: { + datasets: [{ + label: 'Price', + data: marketHistoryData.map(({ date, closing_price }) => ({x: date, y: closing_price})), + fill: false, + pointRadius: 0, + borderColor: 'darkgray' + }] + }, + options: { + legend: { + display: false + }, + scales: { + xAxes: [{ + type: 'time', + time: { + unit: 'week', + displayFormats: { + week: 'MMM D' + } + } + }], + yAxes: [{ + ticks: { + beginAtZero:true, + callback: (value, index, values) => { + return '$' + value.toFixed(2); + }, + maxTicksLimit: 6 + } + }] + }, + tooltips: { + mode: 'index', + intersect: false + } + } + }); +}) diff --git a/apps/explorer_web/assets/package-lock.json b/apps/explorer_web/assets/package-lock.json index a852ce9f6f..2924c256a1 100644 --- a/apps/explorer_web/assets/package-lock.json +++ b/apps/explorer_web/assets/package-lock.json @@ -1673,6 +1673,39 @@ "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", "dev": true }, + "chart.js": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.7.2.tgz", + "integrity": "sha512-90wl3V9xRZ8tnMvMlpcW+0Yg13BelsGS9P9t0ClaDxv/hdypHDr/YAGf+728m11P5ljwyB0ZHfPKCapZFqSqYA==", + "requires": { + "chartjs-color": "2.2.0", + "moment": "2.22.1" + } + }, + "chartjs-color": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.2.0.tgz", + "integrity": "sha1-hKL7dVeH7YXDndbdjHsdiEKbrq4=", + "requires": { + "chartjs-color-string": "0.5.0", + "color-convert": "0.5.3" + }, + "dependencies": { + "color-convert": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=" + } + } + }, + "chartjs-color-string": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz", + "integrity": "sha512-amWNvCOXlOUYxZVDSa0YOab5K/lmEhbFNKI55PWc4mlv28BDzA7zaoQTGxSBgJMHIW+hGX8YUrvw/FH4LyhwSQ==", + "requires": { + "color-name": "1.1.3" + } + }, "chokidar": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz", @@ -2004,8 +2037,7 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-string": { "version": "0.3.0", @@ -6427,6 +6459,11 @@ "minimist": "0.0.8" } }, + "moment": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.1.tgz", + "integrity": "sha512-shJkRTSebXvsVqk56I+lkb2latjBs8I+pc2TzWc545y2iFnSjm7Wg0QMh+ZWcdSLQyGEau5jI8ocnmkyTgr9YQ==" + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", diff --git a/apps/explorer_web/assets/package.json b/apps/explorer_web/assets/package.json index 49d3cb2056..f710515d1f 100644 --- a/apps/explorer_web/assets/package.json +++ b/apps/explorer_web/assets/package.json @@ -20,6 +20,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^5.1.0-4", "bootstrap": "^4.1.0", + "chart.js": "^2.7.2", "jquery": "^3.3.1", "phoenix": "file:../../../deps/phoenix", "phoenix_html": "file:../../../deps/phoenix_html", diff --git a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex index b50968f7e3..aaa93746ed 100644 --- a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex +++ b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex @@ -10,7 +10,7 @@ defmodule ExplorerWeb.ChainController do conn, "show.html", chain: Statistics.fetch(), - market_history_data: Market.fetch_recent_history(8) + market_history_data: Market.fetch_recent_history(30) ) end diff --git a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex index 3c0cf063e2..e477fa4d5f 100644 --- a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex +++ b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex @@ -1,5 +1,8 @@
+
+ +
" /> diff --git a/apps/explorer_web/lib/explorer_web/views/chain_view.ex b/apps/explorer_web/lib/explorer_web/views/chain_view.ex index a8f253f504..2a4359c3a5 100644 --- a/apps/explorer_web/lib/explorer_web/views/chain_view.ex +++ b/apps/explorer_web/lib/explorer_web/views/chain_view.ex @@ -1,3 +1,13 @@ defmodule ExplorerWeb.ChainView do use ExplorerWeb, :view + + def encode_market_history_data(market_history_data) do + market_history_data + |> Enum.map(fn(day) -> Map.take(day, [:closing_price, :date]) end) + |> Jason.encode() + |> case do + {:ok, data} -> data + _ -> [] + end + end end From 84a36b2e553d8cb1a4eba9107c40b52559a54cef Mon Sep 17 00:00:00 2001 From: Tim Mecklem Date: Mon, 7 May 2018 16:24:46 -0400 Subject: [PATCH 04/18] Add market cap data to chart --- apps/explorer/lib/explorer/market/market.ex | 11 +++++ .../assets/js/lib/market_history_chart.js | 47 ++++++++++++++++--- apps/explorer_web/assets/package-lock.json | 5 ++ apps/explorer_web/assets/package.json | 1 + .../controllers/chain_controller.ex | 3 +- .../templates/chain/show.html.eex | 2 +- 6 files changed, 61 insertions(+), 8 deletions(-) diff --git a/apps/explorer/lib/explorer/market/market.ex b/apps/explorer/lib/explorer/market/market.ex index 1d2fcb8bc2..8d141b8b63 100644 --- a/apps/explorer/lib/explorer/market/market.ex +++ b/apps/explorer/lib/explorer/market/market.ex @@ -5,9 +5,20 @@ defmodule Explorer.Market do import Ecto.Query + alias Explorer.ExchangeRates + alias Explorer.ExchangeRates.Token alias Explorer.Market.MarketHistory alias Explorer.Repo + @doc """ + Get most recent exchange rate for the given symbol. + """ + @spec fetch_exchange_rate(String.t()) :: Token.t() + def fetch_exchange_rate(symbol) do + ExchangeRates.list() + |> Enum.find(fn(token) -> token.symbol == symbol end) + end + @doc """ Retrieves the history for the recent specified amount of days. diff --git a/apps/explorer_web/assets/js/lib/market_history_chart.js b/apps/explorer_web/assets/js/lib/market_history_chart.js index 76ba136879..5f9155a299 100644 --- a/apps/explorer_web/assets/js/lib/market_history_chart.js +++ b/apps/explorer_web/assets/js/lib/market_history_chart.js @@ -1,9 +1,18 @@ import $ from 'jquery' import Chart from 'chart.js' +import numeral from 'numeral' + +function formatPrice(price) { + return '$' + price.toFixed(2) +} + +function formatMarketCap(marketCap) { + return numeral(marketCap).format('($0,0a)') +} $('[data-chart="marketHistoryChart"]').each((i, ctx)=> { const marketHistoryData = JSON.parse(ctx.dataset.market_history_data) - console.log("Market History Data: ", marketHistoryData) + const availableSupply = JSON.parse(ctx.dataset.available_supply) var myChart = new Chart(ctx, { type: 'line', @@ -11,10 +20,18 @@ $('[data-chart="marketHistoryChart"]').each((i, ctx)=> { data: { datasets: [{ label: 'Price', + yAxisID: 'price', data: marketHistoryData.map(({ date, closing_price }) => ({x: date, y: closing_price})), fill: false, pointRadius: 0, borderColor: 'darkgray' + },{ + label: 'Market Cap', + yAxisID: 'marketCap', + data: marketHistoryData.map(({ date, closing_price }) => ({x: date, y: closing_price * availableSupply})), + fill: false, + pointRadius: 0.5, + borderColor: 'lightgray' }] }, options: { @@ -32,19 +49,37 @@ $('[data-chart="marketHistoryChart"]').each((i, ctx)=> { } }], yAxes: [{ + id: 'price', ticks: { beginAtZero:true, - callback: (value, index, values) => { - return '$' + value.toFixed(2); - }, + callback: (value, index, values) => formatPrice(value), + maxTicksLimit: 6 + } + }, { + id: 'marketCap', + position: 'right', + ticks: { + callback: (value, index, values) => formatMarketCap(value), maxTicksLimit: 6 } }] }, tooltips: { mode: 'index', - intersect: false + intersect: false, + callbacks: { + label: ({datasetIndex, yLabel}, {datasets}) => { + const label = datasets[datasetIndex].label + if(datasets[datasetIndex].label === 'Price') { + return `${label}: ${formatPrice(yLabel)}` + } else if(datasets[datasetIndex].label === 'Market Cap') { + return `${label}: ${formatMarketCap(yLabel)}` + } else { + return yLabel + } + } + } } } - }); + }) }) diff --git a/apps/explorer_web/assets/package-lock.json b/apps/explorer_web/assets/package-lock.json index 2924c256a1..d44d02c5d0 100644 --- a/apps/explorer_web/assets/package-lock.json +++ b/apps/explorer_web/assets/package-lock.json @@ -6774,6 +6774,11 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, + "numeral": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/numeral/-/numeral-2.0.6.tgz", + "integrity": "sha1-StCAk21EPCVhrtnyGX7//iX05QY=" + }, "oauth-sign": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", diff --git a/apps/explorer_web/assets/package.json b/apps/explorer_web/assets/package.json index f710515d1f..a3725de3b1 100644 --- a/apps/explorer_web/assets/package.json +++ b/apps/explorer_web/assets/package.json @@ -22,6 +22,7 @@ "bootstrap": "^4.1.0", "chart.js": "^2.7.2", "jquery": "^3.3.1", + "numeral": "^2.0.6", "phoenix": "file:../../../deps/phoenix", "phoenix_html": "file:../../../deps/phoenix_html", "popper.js": "^1.14.3" diff --git a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex index aaa93746ed..ff39ec8414 100644 --- a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex +++ b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex @@ -10,7 +10,8 @@ defmodule ExplorerWeb.ChainController do conn, "show.html", chain: Statistics.fetch(), - market_history_data: Market.fetch_recent_history(30) + market_history_data: Market.fetch_recent_history(30), + exchange_rate: Market.fetch_exchange_rate(Application.get_env(:explorer, :coin)) ) end diff --git a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex index e477fa4d5f..fb5d012771 100644 --- a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex +++ b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex @@ -1,7 +1,7 @@
- +
From 3b553cbacfac7ec679a99a7e98d2a59a799fcfd3 Mon Sep 17 00:00:00 2001 From: Tim Mecklem Date: Tue, 8 May 2018 13:02:58 -0400 Subject: [PATCH 05/18] Rename babelrc to .babelrc --- apps/explorer_web/assets/{babelrc => .babelrc} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/explorer_web/assets/{babelrc => .babelrc} (100%) diff --git a/apps/explorer_web/assets/babelrc b/apps/explorer_web/assets/.babelrc similarity index 100% rename from apps/explorer_web/assets/babelrc rename to apps/explorer_web/assets/.babelrc From 36e33e000be8405363523cffb939feaf8b5e35a8 Mon Sep 17 00:00:00 2001 From: Tim Mecklem Date: Tue, 8 May 2018 13:04:16 -0400 Subject: [PATCH 06/18] Add test for `fetch_exchange_rate` Currently it throws a lot of red error stuff about not mocking the `TestSource` calls, but the tests still pass. --- .../test/explorer/market/market_test.exs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/apps/explorer/test/explorer/market/market_test.exs b/apps/explorer/test/explorer/market/market_test.exs index b989f6a1de..9d4164200a 100644 --- a/apps/explorer/test/explorer/market/market_test.exs +++ b/apps/explorer/test/explorer/market/market_test.exs @@ -1,10 +1,29 @@ defmodule Explorer.MarketTest do use Explorer.DataCase + alias Explorer.ExchangeRates + alias Explorer.ExchangeRates.Token alias Explorer.Market alias Explorer.Market.MarketHistory alias Explorer.Repo + describe "fetch_exchange_rate/1" do + setup do + {:ok, _} = ExchangeRates.start_link([]) + rate = %Token{id: "POA", symbol: "POA"} + :ets.insert(ExchangeRates.table_name(), {rate.id, rate}) + {:ok, %{rate: rate}} + end + + test "with matching symbol", %{rate: rate} do + assert Market.fetch_exchange_rate("POA") == rate + end + + test "with no matching symbol" do + assert Market.fetch_exchange_rate("ETH") == nil + end + end + test "fetch_recent_history/1" do today = Date.utc_today() From af6be7c0585db19cf4ac8fcd70bb56c016c08dd6 Mon Sep 17 00:00:00 2001 From: katibest Date: Tue, 8 May 2018 15:05:00 -0400 Subject: [PATCH 07/18] Updated layout of graph and stats --- .../assets/css/components/_chain.scss | 21 ++++++++ .../templates/chain/show.html.eex | 51 ++++--------------- 2 files changed, 32 insertions(+), 40 deletions(-) diff --git a/apps/explorer_web/assets/css/components/_chain.scss b/apps/explorer_web/assets/css/components/_chain.scss index c61fd46a85..67e6284f0e 100644 --- a/apps/explorer_web/assets/css/components/_chain.scss +++ b/apps/explorer_web/assets/css/components/_chain.scss @@ -25,6 +25,27 @@ } } +.container__stats { + @extend %paper; + padding: 15px; + width: 18%; + font-size: 12px; + justify-conntent: space-around; + text-align: center; + + &--contain { + padding: 10px; + + & img { + display: inline-block; + height: explorer-size(1); + margin-bottom: explorer-size(-2); + text-align: center; + } + } +} + + @media (min-width: $explorer-breakpoint-sm) { .chain { &__image { diff --git a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex index fb5d012771..dc29ed97ca 100644 --- a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex +++ b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex @@ -1,55 +1,26 @@
-
- -
-
-
- " /> -
<%= gettext("Skipped") %>
-
<%= @chain.skipped_blocks |> Cldr.Number.to_string! %>
-
-
- " /> -
<%= gettext("Lag") %>
-
<%= @chain.lag |> Timex.format_duration(:humanized) %>
-
-
- " /> -
<%= gettext("BPM") %>
-
<%= @chain.block_velocity |> Cldr.Number.to_string! %>
-
-
- " /> -
<%= gettext("TPM") %>
-
<%= @chain.transaction_velocity |> Cldr.Number.to_string! %>
-
-
-
-
+
+
" />
<%= gettext("Block") %>
#<%= @chain.number %>
-
- " /> +
+ " />
<%= gettext("Last Block") %>
<%= @chain.timestamp |> Timex.from_now() %>
-
- " /> -
<%= gettext("Average Block Time") %>
-
+
+ " /> +
<%= gettext("Avg Block Time") %>
+
<%= @chain.average_time |> Timex.format_duration(:humanized) %>
-
- " /> -
<%= gettext("Transactions") %>
-
- <%= gettext("%{count} per day", count: Cldr.Number.to_string!(@chain.transaction_count)) %> -
-
+
+
+
From e28835c194afe8feca28b9c776d69964770571a1 Mon Sep 17 00:00:00 2001 From: jimmay5469 Date: Wed, 9 May 2018 09:05:46 -0400 Subject: [PATCH 08/18] Use colors from SASS in chart --- apps/explorer_web/assets/css/app.scss | 5 +++++ apps/explorer_web/assets/js/lib/market_history_chart.js | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/explorer_web/assets/css/app.scss b/apps/explorer_web/assets/css/app.scss index c2c25e6ad0..4247dc9803 100644 --- a/apps/explorer_web/assets/css/app.scss +++ b/apps/explorer_web/assets/css/app.scss @@ -32,3 +32,8 @@ $fa-font-path: "~@fortawesome/fontawesome-free/webfonts"; @import "components/sidebar"; @import "explorer/button"; @import "explorer/filter"; + +:export { + primary: $primary; + secondary: $secondary; +} diff --git a/apps/explorer_web/assets/js/lib/market_history_chart.js b/apps/explorer_web/assets/js/lib/market_history_chart.js index 5f9155a299..0d2a2a5ba9 100644 --- a/apps/explorer_web/assets/js/lib/market_history_chart.js +++ b/apps/explorer_web/assets/js/lib/market_history_chart.js @@ -1,6 +1,7 @@ import $ from 'jquery' import Chart from 'chart.js' import numeral from 'numeral' +import sassVariables from '../../css/app.scss' function formatPrice(price) { return '$' + price.toFixed(2) @@ -24,14 +25,16 @@ $('[data-chart="marketHistoryChart"]').each((i, ctx)=> { data: marketHistoryData.map(({ date, closing_price }) => ({x: date, y: closing_price})), fill: false, pointRadius: 0, - borderColor: 'darkgray' + backgroundColor: sassVariables.primary, + borderColor: sassVariables.primary },{ label: 'Market Cap', yAxisID: 'marketCap', data: marketHistoryData.map(({ date, closing_price }) => ({x: date, y: closing_price * availableSupply})), fill: false, pointRadius: 0.5, - borderColor: 'lightgray' + backgroundColor: sassVariables.secondary, + borderColor: sassVariables.secondary }] }, options: { From 0b6b338819aab4a51a4f7e4b1fbe89984842b668 Mon Sep 17 00:00:00 2001 From: jimmay5469 Date: Wed, 9 May 2018 10:46:31 -0400 Subject: [PATCH 09/18] Display Price, Market Cap, and 24h Volume --- .../assets/js/lib/market_history_chart.js | 36 ++++++++++++------- apps/explorer_web/assets/package-lock.json | 5 +++ apps/explorer_web/assets/package.json | 2 ++ .../templates/chain/show.html.eex | 10 +++++- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/apps/explorer_web/assets/js/lib/market_history_chart.js b/apps/explorer_web/assets/js/lib/market_history_chart.js index 0d2a2a5ba9..7fa0ffb448 100644 --- a/apps/explorer_web/assets/js/lib/market_history_chart.js +++ b/apps/explorer_web/assets/js/lib/market_history_chart.js @@ -1,36 +1,44 @@ import $ from 'jquery' import Chart from 'chart.js' +import humps from 'humps' +import moment from 'moment' import numeral from 'numeral' import sassVariables from '../../css/app.scss' -function formatPrice(price) { +function formatPrice (price) { return '$' + price.toFixed(2) } -function formatMarketCap(marketCap) { +function formatMarketCap (marketCap) { return numeral(marketCap).format('($0,0a)') } -$('[data-chart="marketHistoryChart"]').each((i, ctx)=> { - const marketHistoryData = JSON.parse(ctx.dataset.market_history_data) - const availableSupply = JSON.parse(ctx.dataset.available_supply) +function createMarketHistoryChart (ctx) { + const currentExchangeRate = ctx.dataset.current_exchange_rate + const availableSupply = ctx.dataset.available_supply + const marketHistoryData = humps.camelizeKeys(JSON.parse(ctx.dataset.market_history_data)) + const today = moment().format('YYYY-MM-DD') + const currentMarketHistoryData = marketHistoryData.map(({date, closingPrice}) => ({ + date, + closingPrice: date === today ? currentExchangeRate : closingPrice + })) - var myChart = new Chart(ctx, { + return new Chart(ctx, { type: 'line', responsive: true, data: { datasets: [{ label: 'Price', yAxisID: 'price', - data: marketHistoryData.map(({ date, closing_price }) => ({x: date, y: closing_price})), + data: currentMarketHistoryData.map(({ date, closingPrice }) => ({x: date, y: closingPrice})), fill: false, pointRadius: 0, backgroundColor: sassVariables.primary, borderColor: sassVariables.primary - },{ + }, { label: 'Market Cap', yAxisID: 'marketCap', - data: marketHistoryData.map(({ date, closing_price }) => ({x: date, y: closing_price * availableSupply})), + data: currentMarketHistoryData.map(({ date, closingPrice }) => ({x: date, y: closingPrice * availableSupply})), fill: false, pointRadius: 0.5, backgroundColor: sassVariables.secondary, @@ -54,7 +62,7 @@ $('[data-chart="marketHistoryChart"]').each((i, ctx)=> { yAxes: [{ id: 'price', ticks: { - beginAtZero:true, + beginAtZero: true, callback: (value, index, values) => formatPrice(value), maxTicksLimit: 6 } @@ -73,9 +81,9 @@ $('[data-chart="marketHistoryChart"]').each((i, ctx)=> { callbacks: { label: ({datasetIndex, yLabel}, {datasets}) => { const label = datasets[datasetIndex].label - if(datasets[datasetIndex].label === 'Price') { + if (datasets[datasetIndex].label === 'Price') { return `${label}: ${formatPrice(yLabel)}` - } else if(datasets[datasetIndex].label === 'Market Cap') { + } else if (datasets[datasetIndex].label === 'Market Cap') { return `${label}: ${formatMarketCap(yLabel)}` } else { return yLabel @@ -85,4 +93,6 @@ $('[data-chart="marketHistoryChart"]').each((i, ctx)=> { } } }) -}) +} + +$('[data-chart="marketHistoryChart"]').each((i, ctx) => createMarketHistoryChart(ctx)) diff --git a/apps/explorer_web/assets/package-lock.json b/apps/explorer_web/assets/package-lock.json index d44d02c5d0..8594fd4d37 100644 --- a/apps/explorer_web/assets/package-lock.json +++ b/apps/explorer_web/assets/package-lock.json @@ -4751,6 +4751,11 @@ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", "dev": true }, + "humps": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/humps/-/humps-2.0.1.tgz", + "integrity": "sha1-3QLqYIG9BWjcXQcxhEY5V7qe+ao=" + }, "iconv-lite": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", diff --git a/apps/explorer_web/assets/package.json b/apps/explorer_web/assets/package.json index a3725de3b1..5c4101013a 100644 --- a/apps/explorer_web/assets/package.json +++ b/apps/explorer_web/assets/package.json @@ -21,7 +21,9 @@ "@fortawesome/fontawesome-free": "^5.1.0-4", "bootstrap": "^4.1.0", "chart.js": "^2.7.2", + "humps": "^2.0.1", "jquery": "^3.3.1", + "moment": "^2.22.1", "numeral": "^2.0.6", "phoenix": "file:../../../deps/phoenix", "phoenix_html": "file:../../../deps/phoenix_html", diff --git a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex index dc29ed97ca..a3b47c1535 100644 --- a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex +++ b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex @@ -20,7 +20,15 @@
- + +
+
+
<%= gettext "Price" %>
+
<%= @exchange_rate.usd_value %>
+
<%= gettext "Market Cap" %>
+
<%= @exchange_rate.market_cap_usd %>
+
<%= gettext "24h Volume" %>
+
<%= @exchange_rate.volume_24h_usd %>
From 417c24172ad1c171d3948742f976dfc5180432a9 Mon Sep 17 00:00:00 2001 From: jimmay5469 Date: Wed, 9 May 2018 14:49:44 -0400 Subject: [PATCH 10/18] Basic formatting for price, market cap, and 24h volume Co-authored-by: tmecklem --- .../lib/explorer_web/templates/chain/show.html.eex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex index a3b47c1535..30c91a0d6f 100644 --- a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex +++ b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex @@ -24,11 +24,11 @@
<%= gettext "Price" %>
-
<%= @exchange_rate.usd_value %>
+
$<%= @exchange_rate.usd_value %> <%= gettext "USD" %>
<%= gettext "Market Cap" %>
-
<%= @exchange_rate.market_cap_usd %>
+
$<%= @exchange_rate.market_cap_usd %> <%= gettext "USD" %>
<%= gettext "24h Volume" %>
-
<%= @exchange_rate.volume_24h_usd %>
+
$<%= @exchange_rate.volume_24h_usd %> <%= gettext "USD" %>
From a773062b3ae70acd9ca45e88afc4bc8ed52ea824 Mon Sep 17 00:00:00 2001 From: jimmay5469 Date: Wed, 9 May 2018 14:52:30 -0400 Subject: [PATCH 11/18] Remove line smoothing Co-authored-by: tmecklem --- apps/explorer_web/assets/js/lib/market_history_chart.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/explorer_web/assets/js/lib/market_history_chart.js b/apps/explorer_web/assets/js/lib/market_history_chart.js index 7fa0ffb448..bdcdcca9c5 100644 --- a/apps/explorer_web/assets/js/lib/market_history_chart.js +++ b/apps/explorer_web/assets/js/lib/market_history_chart.js @@ -34,7 +34,8 @@ function createMarketHistoryChart (ctx) { fill: false, pointRadius: 0, backgroundColor: sassVariables.primary, - borderColor: sassVariables.primary + borderColor: sassVariables.primary, + lineTension: 0 }, { label: 'Market Cap', yAxisID: 'marketCap', @@ -42,7 +43,8 @@ function createMarketHistoryChart (ctx) { fill: false, pointRadius: 0.5, backgroundColor: sassVariables.secondary, - borderColor: sassVariables.secondary + borderColor: sassVariables.secondary, + lineTension: 0 }] }, options: { From f7d67b7a8620097ee1fea9c0de5e1e0ed4ae048a Mon Sep 17 00:00:00 2001 From: Tim Mecklem Date: Wed, 9 May 2018 16:02:28 -0400 Subject: [PATCH 12/18] Change `Market.fetch_exchange_rate/1` and supporting code to be testable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace default test configuration for `ExchangeRates` to use a no-op Source and bypass :ets. This allows higher level feature tests to run without having to manage GenServer processes when they don’t need Exchange rate information but allows the lower tests to exercise the specific behavior as before. Add `Token.null`. Co-authored-by: jimmay5469 --- .../explorer/exchange_rates/exchange_rates.ex | 22 ++++++++++++++----- .../lib/explorer/exchange_rates/token.ex | 2 ++ apps/explorer/lib/explorer/market/market.ex | 5 ++--- .../exchange_rates/exchange_rates_test.exs | 10 +++++++++ .../test/explorer/market/market_test.exs | 17 ++++++++++++++ .../test/support/fakes/no_op_source.ex | 10 +++++++++ .../controllers/chain_controller.ex | 7 +++++- .../lib/explorer_web/views/chain_view.ex | 8 +++---- .../controllers/chain_controller_test.exs | 6 ++--- config/test.exs | 4 +++- coveralls.json | 2 +- 11 files changed, 74 insertions(+), 19 deletions(-) create mode 100644 apps/explorer/test/support/fakes/no_op_source.ex diff --git a/apps/explorer/lib/explorer/exchange_rates/exchange_rates.ex b/apps/explorer/lib/explorer/exchange_rates/exchange_rates.ex index e0c2dcee4a..2fb8fbf28b 100644 --- a/apps/explorer/lib/explorer/exchange_rates/exchange_rates.ex +++ b/apps/explorer/lib/explorer/exchange_rates/exchange_rates.ex @@ -33,7 +33,7 @@ defmodule Explorer.ExchangeRates do {symbol, token} end - :ets.insert(table_name(), records) + if store() == :ets, do: :ets.insert(table_name(), records) {:noreply, state} end @@ -67,7 +67,7 @@ defmodule Explorer.ExchangeRates do write_concurrency: true ] - :ets.new(table_name(), table_opts) + if store() == :ets, do: :ets.new(table_name(), table_opts) {:ok, %{}} end @@ -83,10 +83,7 @@ defmodule Explorer.ExchangeRates do """ @spec list :: [Token.t()] def list do - table_name() - |> :ets.tab2list() - |> Enum.map(fn {_, rate} -> rate end) - |> Enum.sort_by(fn %Token{symbol: symbol} -> symbol end) + list_from_store(store()) end ## Undocumented public functions @@ -113,4 +110,17 @@ defmodule Explorer.ExchangeRates do exchange_rates_source().fetch_exchange_rates() end) end + + defp list_from_store(:ets) do + table_name() + |> :ets.tab2list() + |> Enum.map(fn {_, rate} -> rate end) + |> Enum.sort_by(fn %Token{symbol: symbol} -> symbol end) + end + + defp list_from_store(_), do: [] + + defp store do + config(:store) || :ets + end end diff --git a/apps/explorer/lib/explorer/exchange_rates/token.ex b/apps/explorer/lib/explorer/exchange_rates/token.ex index eb4f577a1e..6830d5236b 100644 --- a/apps/explorer/lib/explorer/exchange_rates/token.ex +++ b/apps/explorer/lib/explorer/exchange_rates/token.ex @@ -29,4 +29,6 @@ defmodule Explorer.ExchangeRates.Token do } defstruct ~w(available_supply btc_value id last_updated market_cap_usd name symbol usd_value volume_24h_usd)a + + def null, do: %__MODULE__{} end diff --git a/apps/explorer/lib/explorer/market/market.ex b/apps/explorer/lib/explorer/market/market.ex index 8d141b8b63..ddb08eb398 100644 --- a/apps/explorer/lib/explorer/market/market.ex +++ b/apps/explorer/lib/explorer/market/market.ex @@ -5,10 +5,9 @@ defmodule Explorer.Market do import Ecto.Query - alias Explorer.ExchangeRates + alias Explorer.{ExchangeRates, Repo} alias Explorer.ExchangeRates.Token alias Explorer.Market.MarketHistory - alias Explorer.Repo @doc """ Get most recent exchange rate for the given symbol. @@ -16,7 +15,7 @@ defmodule Explorer.Market do @spec fetch_exchange_rate(String.t()) :: Token.t() def fetch_exchange_rate(symbol) do ExchangeRates.list() - |> Enum.find(fn(token) -> token.symbol == symbol end) + |> Enum.find(fn token -> token.symbol == symbol end) end @doc """ diff --git a/apps/explorer/test/explorer/exchange_rates/exchange_rates_test.exs b/apps/explorer/test/explorer/exchange_rates/exchange_rates_test.exs index 427da15bb1..e36902be99 100644 --- a/apps/explorer/test/explorer/exchange_rates/exchange_rates_test.exs +++ b/apps/explorer/test/explorer/exchange_rates/exchange_rates_test.exs @@ -11,6 +11,16 @@ defmodule Explorer.ExchangeRatesTest do setup :verify_on_exit! + setup do + # Use TestSource mock and ets table for this test set + configuration = Application.get_env(:explorer, Explorer.ExchangeRates) + Application.put_env(:explorer, Explorer.ExchangeRates, source: TestSource) + + on_exit(fn -> + Application.put_env(:explorer, Explorer.ExchangeRates, configuration) + end) + end + test "start_link" do stub(TestSource, :fetch_exchange_rates, fn -> {:ok, [%Token{}]} end) set_mox_global() diff --git a/apps/explorer/test/explorer/market/market_test.exs b/apps/explorer/test/explorer/market/market_test.exs index 9d4164200a..c43690baa2 100644 --- a/apps/explorer/test/explorer/market/market_test.exs +++ b/apps/explorer/test/explorer/market/market_test.exs @@ -9,6 +9,8 @@ defmodule Explorer.MarketTest do describe "fetch_exchange_rate/1" do setup do + use_ets_store() + {:ok, _} = ExchangeRates.start_link([]) rate = %Token{id: "POA", symbol: "POA"} :ets.insert(ExchangeRates.table_name(), {rate.id, rate}) @@ -103,4 +105,19 @@ defmodule Explorer.MarketTest do assert fetched_record.opening_price == new_record.opening_price end end + + defp use_ets_store do + # Use ets tables as ExchangeRates store and put some test data in to + # exercise Context filtering + exchange_config = Application.get_env(:explorer, Explorer.ExchangeRates) + Application.put_env( + :explorer, + Explorer.ExchangeRates, + Keyword.put(exchange_config, :store, :ets) + ) + + on_exit(fn -> + Application.put_env(:explorer, Explorer.ExchangeRates, exchange_config) + end) + end end diff --git a/apps/explorer/test/support/fakes/no_op_source.ex b/apps/explorer/test/support/fakes/no_op_source.ex new file mode 100644 index 0000000000..15eedb6aca --- /dev/null +++ b/apps/explorer/test/support/fakes/no_op_source.ex @@ -0,0 +1,10 @@ +defmodule Explorer.ExchangeRates.Source.NoOpSource do + @moduledoc false + + alias Explorer.ExchangeRates.Source + + @behaviour Source + + @impl Source + def fetch_exchange_rates, do: {:ok, []} +end diff --git a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex index ff39ec8414..5c4e73072c 100644 --- a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex +++ b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex @@ -2,6 +2,7 @@ defmodule ExplorerWeb.ChainController do use ExplorerWeb, :controller alias Explorer.Chain.{Address, Block, Statistics, Transaction} + alias Explorer.ExchangeRates.Token alias Explorer.Market alias ExplorerWeb.Chain @@ -11,7 +12,7 @@ defmodule ExplorerWeb.ChainController do "show.html", chain: Statistics.fetch(), market_history_data: Market.fetch_recent_history(30), - exchange_rate: Market.fetch_exchange_rate(Application.get_env(:explorer, :coin)) + exchange_rate: Market.fetch_exchange_rate(coin()) || Token.null() ) end @@ -28,6 +29,10 @@ defmodule ExplorerWeb.ChainController do end end + defp coin do + Application.get_env(:explorer, :coin) + end + defp redirect_search_results(conn, %Address{} = item) do redirect(conn, to: address_path(conn, :show, Gettext.get_locale(), item.hash)) end diff --git a/apps/explorer_web/lib/explorer_web/views/chain_view.ex b/apps/explorer_web/lib/explorer_web/views/chain_view.ex index 2a4359c3a5..889533c424 100644 --- a/apps/explorer_web/lib/explorer_web/views/chain_view.ex +++ b/apps/explorer_web/lib/explorer_web/views/chain_view.ex @@ -3,11 +3,11 @@ defmodule ExplorerWeb.ChainView do def encode_market_history_data(market_history_data) do market_history_data - |> Enum.map(fn(day) -> Map.take(day, [:closing_price, :date]) end) + |> Enum.map(fn day -> Map.take(day, [:closing_price, :date]) end) |> Jason.encode() |> case do - {:ok, data} -> data - _ -> [] - end + {:ok, data} -> data + _ -> [] + end end end diff --git a/apps/explorer_web/test/explorer_web/controllers/chain_controller_test.exs b/apps/explorer_web/test/explorer_web/controllers/chain_controller_test.exs index 6b9733fc81..9e225b45f9 100644 --- a/apps/explorer_web/test/explorer_web/controllers/chain_controller_test.exs +++ b/apps/explorer_web/test/explorer_web/controllers/chain_controller_test.exs @@ -60,13 +60,13 @@ defmodule ExplorerWeb.ChainControllerTest do end test "returns market history data", %{conn: conn} do - today = Date.utc_today - for day <- -14..0, do: insert(:market_history, date: Date.add(today, day)) + today = Date.utc_today() + for day <- -40..0, do: insert(:market_history, date: Date.add(today, day)) conn = get(conn, "/en") assert Map.has_key?(conn.assigns, :market_history_data) - assert length(conn.assigns.market_history_data) == 8 + assert length(conn.assigns.market_history_data) == 30 end end diff --git a/config/test.exs b/config/test.exs index 27bf64ea42..3c5bc99626 100644 --- a/config/test.exs +++ b/config/test.exs @@ -3,4 +3,6 @@ use Mix.Config # Print only warnings and errors during test config :logger, level: :warn -config :explorer, Explorer.ExchangeRates, source: Explorer.ExchangeRates.Source.TestSource +config :explorer, Explorer.ExchangeRates, + source: Explorer.ExchangeRates.Source.NoOpSource, + store: :none diff --git a/coveralls.json b/coveralls.json index 252126b717..1d36563da0 100644 --- a/coveralls.json +++ b/coveralls.json @@ -1,7 +1,7 @@ { "coverage_options": { "treat_no_relevant_lines_as_covered": true, - "minimum_coverage": 85 + "minimum_coverage": 86 }, "terminal_options": { "file_column_width": 120 From 3239a248b9579171269af7e121683243605bf5de Mon Sep 17 00:00:00 2001 From: jimmay5469 Date: Thu, 10 May 2018 08:22:50 -0400 Subject: [PATCH 13/18] Format price, market cap, and 24h volume --- .../lib/explorer_web/templates/chain/show.html.eex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex index 30c91a0d6f..4f24d288fe 100644 --- a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex +++ b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex @@ -24,11 +24,11 @@
<%= gettext "Price" %>
-
$<%= @exchange_rate.usd_value %> <%= gettext "USD" %>
+
$<%= @exchange_rate.usd_value |> Cldr.Number.to_string!(fractional_digits: 6) %> <%= gettext "USD" %>
<%= gettext "Market Cap" %>
-
$<%= @exchange_rate.market_cap_usd %> <%= gettext "USD" %>
+
$<%= @exchange_rate.market_cap_usd |> Cldr.Number.to_string! %> <%= gettext "USD" %>
<%= gettext "24h Volume" %>
-
$<%= @exchange_rate.volume_24h_usd %> <%= gettext "USD" %>
+
$<%= @exchange_rate.volume_24h_usd |> Cldr.Number.to_string! %> <%= gettext "USD" %>
From 007c2a2ba222143aaaf5974a6039940df78a305b Mon Sep 17 00:00:00 2001 From: katibest Date: Thu, 10 May 2018 11:20:24 -0400 Subject: [PATCH 14/18] Formatted stats on the bottom of the graph --- .../assets/css/components/_chain.scss | 57 ++++++++++++++----- .../templates/chain/show.html.eex | 34 ++++++----- 2 files changed, 63 insertions(+), 28 deletions(-) diff --git a/apps/explorer_web/assets/css/components/_chain.scss b/apps/explorer_web/assets/css/components/_chain.scss index 67e6284f0e..3b68d5f865 100644 --- a/apps/explorer_web/assets/css/components/_chain.scss +++ b/apps/explorer_web/assets/css/components/_chain.scss @@ -1,9 +1,5 @@ .chain { @extend %paper; - - display: flex; - justify-conntent: space-around; - align-items: flex-start; padding: explorer-size(0) 0; &__container { @@ -27,24 +23,40 @@ .container__stats { @extend %paper; + display: flex; padding: 15px; - width: 18%; + width: 100%; font-size: 12px; - justify-conntent: space-around; text-align: center; + flex-direction: row; + justify-content: space-around; + + img { + display: inline-block; + height: explorer-size(1); + margin-bottom: explorer-size(-2); + text-align: center; + } +} - &--contain { - padding: 10px; +.graph__squares { + width: 12px; + height: 12px; + display: inline-block; - & img { - display: inline-block; - height: explorer-size(1); - margin-bottom: explorer-size(-2); - text-align: center; - } + &--price { + background-color: explorer-color("blue", "500"); + } + + &--mcap { + background-color: explorer-color("gray", "500"); } } +.flex { + display: flex; + justify-content: space-between; +} @media (min-width: $explorer-breakpoint-sm) { .chain { @@ -59,6 +71,23 @@ } @media (min-width: $explorer-breakpoint-md) { + + .container__stats { + width: 18%; + flex-direction: column; + align-content: space-between; + + img { + display: inline-block; + height: explorer-size(1); + margin-bottom: explorer-size(-2); + text-align: center; + } + + div { + flex-grow: 1; + } + } .chain { &__image { height: explorer-size(1); diff --git a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex index 4f24d288fe..934741a8c7 100644 --- a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex +++ b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex @@ -1,34 +1,40 @@
-
+
" />
<%= gettext("Block") %>
#<%= @chain.number %>
-
+
" />
<%= gettext("Last Block") %>
<%= @chain.timestamp |> Timex.from_now() %>
-
+
" />
<%= gettext("Avg Block Time") %>
-
- <%= @chain.average_time |> Timex.format_duration(:humanized) %> -
+ <%= @chain.average_time |> Timex.format_duration(:humanized) %>
-
-
-
<%= gettext "Price" %>
-
$<%= @exchange_rate.usd_value |> Cldr.Number.to_string!(fractional_digits: 6) %> <%= gettext "USD" %>
-
<%= gettext "Market Cap" %>
-
$<%= @exchange_rate.market_cap_usd |> Cldr.Number.to_string! %> <%= gettext "USD" %>
-
<%= gettext "24h Volume" %>
-
$<%= @exchange_rate.volume_24h_usd |> Cldr.Number.to_string! %> <%= gettext "USD" %>
+
+
+
+ <%= gettext "Price" %>
+ $<%= @exchange_rate.usd_value |> Cldr.Number.to_string!(fractional_digits: 6) %> <%= gettext "USD" %> +
+
+
+ <%= gettext "Market Cap" %>
+ $<%= @exchange_rate.market_cap_usd |> Cldr.Number.to_string! %> <%= gettext "USD" %> +
+
+ <%= gettext "24h Volume" %>
+ $<%= @exchange_rate.volume_24h_usd |> Cldr.Number.to_string! %> <%= gettext "USD" %> +
+
From c5fa6795eceb4b12a5b51162901be720846b15c8 Mon Sep 17 00:00:00 2001 From: katibest Date: Thu, 10 May 2018 11:51:29 -0400 Subject: [PATCH 15/18] Handle nil values in exchange rate token --- .../test/explorer/market/market_test.exs | 1 + .../templates/chain/show.html.eex | 6 +++--- .../lib/explorer_web/views/chain_view.ex | 20 +++++++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/apps/explorer/test/explorer/market/market_test.exs b/apps/explorer/test/explorer/market/market_test.exs index c43690baa2..3c4d318b0c 100644 --- a/apps/explorer/test/explorer/market/market_test.exs +++ b/apps/explorer/test/explorer/market/market_test.exs @@ -110,6 +110,7 @@ defmodule Explorer.MarketTest do # Use ets tables as ExchangeRates store and put some test data in to # exercise Context filtering exchange_config = Application.get_env(:explorer, Explorer.ExchangeRates) + Application.put_env( :explorer, Explorer.ExchangeRates, diff --git a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex index 934741a8c7..2abcf37cc4 100644 --- a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex +++ b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex @@ -23,16 +23,16 @@
<%= gettext "Price" %>
- $<%= @exchange_rate.usd_value |> Cldr.Number.to_string!(fractional_digits: 6) %> <%= gettext "USD" %> + $<%= format_exchange_rate(@exchange_rate) %> <%= gettext "USD" %>
<%= gettext "Market Cap" %>
- $<%= @exchange_rate.market_cap_usd |> Cldr.Number.to_string! %> <%= gettext "USD" %> + $<%= format_market_cap(@exchange_rate) %> <%= gettext "USD" %>
<%= gettext "24h Volume" %>
- $<%= @exchange_rate.volume_24h_usd |> Cldr.Number.to_string! %> <%= gettext "USD" %> + $<%= format_volume_24h(@exchange_rate) %> <%= gettext "USD" %>
diff --git a/apps/explorer_web/lib/explorer_web/views/chain_view.ex b/apps/explorer_web/lib/explorer_web/views/chain_view.ex index 889533c424..d7ac3e117a 100644 --- a/apps/explorer_web/lib/explorer_web/views/chain_view.ex +++ b/apps/explorer_web/lib/explorer_web/views/chain_view.ex @@ -1,6 +1,8 @@ defmodule ExplorerWeb.ChainView do use ExplorerWeb, :view + alias Explorer.ExchangeRates.Token + def encode_market_history_data(market_history_data) do market_history_data |> Enum.map(fn day -> Map.take(day, [:closing_price, :date]) end) @@ -10,4 +12,22 @@ defmodule ExplorerWeb.ChainView do _ -> [] end end + + def format_exchange_rate(%Token{usd_value: nil}), do: nil + + def format_exchange_rate(%Token{usd_value: usd_value}) do + usd_value + |> Cldr.Number.to_string!(fractional_digits: 6) + end + + def format_volume_24h(%Token{volume_24h_usd: volume_24h}) do + format_number(volume_24h) + end + + def format_market_cap(%Token{market_cap_usd: market_cap}) do + format_number(market_cap) + end + + defp format_number(nil), do: nil + defp format_number(number), do: Cldr.Number.to_string!(number) end From 5bedf25a665c1cfafec70cb10f3d72f71fa58000 Mon Sep 17 00:00:00 2001 From: Tim Mecklem Date: Thu, 10 May 2018 12:34:50 -0400 Subject: [PATCH 16/18] Update gettext --- apps/explorer_web/priv/gettext/default.pot | 47 ++++++++++++++----- .../priv/gettext/en/LC_MESSAGES/default.po | 47 ++++++++++++++----- 2 files changed, 68 insertions(+), 26 deletions(-) diff --git a/apps/explorer_web/priv/gettext/default.pot b/apps/explorer_web/priv/gettext/default.pot index 1a26d0a17f..ec38ed30ab 100644 --- a/apps/explorer_web/priv/gettext/default.pot +++ b/apps/explorer_web/priv/gettext/default.pot @@ -2,8 +2,8 @@ #: lib/explorer_web/templates/address_transaction/index.html.eex:69 #: lib/explorer_web/templates/block/index.html.eex:30 #: lib/explorer_web/templates/block_transaction/index.html.eex:99 -#: lib/explorer_web/templates/chain/show.html.eex:71 -#: lib/explorer_web/templates/chain/show.html.eex:110 +#: lib/explorer_web/templates/chain/show.html.eex:59 +#: lib/explorer_web/templates/chain/show.html.eex:98 #: lib/explorer_web/templates/transaction/index.html.eex:36 #: lib/explorer_web/templates/transaction/overview.html.eex:37 msgid "Age" @@ -12,13 +12,13 @@ msgstr "" #: lib/explorer_web/templates/address_internal_transaction/index.html.eex:64 #: lib/explorer_web/templates/address_transaction/index.html.eex:68 #: lib/explorer_web/templates/block_transaction/index.html.eex:98 -#: lib/explorer_web/templates/chain/show.html.eex:28 -#: lib/explorer_web/templates/chain/show.html.eex:109 +#: lib/explorer_web/templates/chain/show.html.eex:6 +#: lib/explorer_web/templates/chain/show.html.eex:97 #: lib/explorer_web/templates/transaction/index.html.eex:35 msgid "Block" msgstr "" -#: lib/explorer_web/templates/chain/show.html.eex:58 +#: lib/explorer_web/templates/chain/show.html.eex:46 #: lib/explorer_web/templates/layout/app.html.eex:25 msgid "Blocks" msgstr "" @@ -29,21 +29,21 @@ msgstr "" #: lib/explorer_web/templates/block/index.html.eex:32 #: lib/explorer_web/templates/block_transaction/index.html.eex:60 -#: lib/explorer_web/templates/chain/show.html.eex:73 +#: lib/explorer_web/templates/chain/show.html.eex:61 msgid "Gas Used" msgstr "" #: lib/explorer_web/templates/address_transaction/index.html.eex:67 #: lib/explorer_web/templates/block_transaction/index.html.eex:22 #: lib/explorer_web/templates/block_transaction/index.html.eex:97 -#: lib/explorer_web/templates/chain/show.html.eex:108 +#: lib/explorer_web/templates/chain/show.html.eex:96 #: lib/explorer_web/templates/pending_transaction/index.html.eex:34 #: lib/explorer_web/templates/transaction/index.html.eex:34 msgid "Hash" msgstr "" #: lib/explorer_web/templates/block/index.html.eex:29 -#: lib/explorer_web/templates/chain/show.html.eex:70 +#: lib/explorer_web/templates/chain/show.html.eex:58 msgid "Height" msgstr "" @@ -56,9 +56,8 @@ msgstr "" #: lib/explorer_web/templates/block/index.html.eex:31 #: lib/explorer_web/templates/block_transaction/index.html.eex:16 #: lib/explorer_web/templates/block_transaction/index.html.eex:84 -#: lib/explorer_web/templates/chain/show.html.eex:45 -#: lib/explorer_web/templates/chain/show.html.eex:72 -#: lib/explorer_web/templates/chain/show.html.eex:99 +#: lib/explorer_web/templates/chain/show.html.eex:60 +#: lib/explorer_web/templates/chain/show.html.eex:87 #: lib/explorer_web/templates/layout/app.html.eex:31 #: lib/explorer_web/templates/pending_transaction/index.html.eex:12 #: lib/explorer_web/templates/transaction/index.html.eex:12 @@ -68,7 +67,7 @@ msgstr "" #: lib/explorer_web/templates/address_internal_transaction/index.html.eex:68 #: lib/explorer_web/templates/address_transaction/index.html.eex:72 #: lib/explorer_web/templates/block_transaction/index.html.eex:102 -#: lib/explorer_web/templates/chain/show.html.eex:111 +#: lib/explorer_web/templates/chain/show.html.eex:99 #: lib/explorer_web/templates/pending_transaction/index.html.eex:38 #: lib/explorer_web/templates/transaction/index.html.eex:39 #: lib/explorer_web/templates/transaction/overview.html.eex:43 @@ -289,7 +288,7 @@ msgstr "" msgid "Lag" msgstr "" -#: lib/explorer_web/templates/chain/show.html.eex:33 +#: lib/explorer_web/templates/chain/show.html.eex:11 msgid "Last Block" msgstr "" @@ -402,3 +401,25 @@ msgstr "" #: lib/explorer_web/templates/address_internal_transaction/index.html.eex:63 msgid "Parent Tx Hash" msgstr "" + +#: lib/explorer_web/templates/chain/show.html.eex:34 +msgid "24h Volume" +msgstr "" + +#: lib/explorer_web/templates/chain/show.html.eex:16 +msgid "Avg Block Time" +msgstr "" + +#: lib/explorer_web/templates/chain/show.html.eex:30 +msgid "Market Cap" +msgstr "" + +#: lib/explorer_web/templates/chain/show.html.eex:25 +msgid "Price" +msgstr "" + +#: lib/explorer_web/templates/chain/show.html.eex:26 +#: lib/explorer_web/templates/chain/show.html.eex:31 +#: lib/explorer_web/templates/chain/show.html.eex:35 +msgid "USD" +msgstr "" diff --git a/apps/explorer_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/explorer_web/priv/gettext/en/LC_MESSAGES/default.po index abb23ef10b..4aa8e6baf1 100644 --- a/apps/explorer_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/explorer_web/priv/gettext/en/LC_MESSAGES/default.po @@ -14,8 +14,8 @@ msgstr "" #: lib/explorer_web/templates/address_transaction/index.html.eex:69 #: lib/explorer_web/templates/block/index.html.eex:30 #: lib/explorer_web/templates/block_transaction/index.html.eex:99 -#: lib/explorer_web/templates/chain/show.html.eex:71 -#: lib/explorer_web/templates/chain/show.html.eex:110 +#: lib/explorer_web/templates/chain/show.html.eex:59 +#: lib/explorer_web/templates/chain/show.html.eex:98 #: lib/explorer_web/templates/transaction/index.html.eex:36 #: lib/explorer_web/templates/transaction/overview.html.eex:37 msgid "Age" @@ -24,13 +24,13 @@ msgstr "Age" #: lib/explorer_web/templates/address_internal_transaction/index.html.eex:64 #: lib/explorer_web/templates/address_transaction/index.html.eex:68 #: lib/explorer_web/templates/block_transaction/index.html.eex:98 -#: lib/explorer_web/templates/chain/show.html.eex:28 -#: lib/explorer_web/templates/chain/show.html.eex:109 +#: lib/explorer_web/templates/chain/show.html.eex:6 +#: lib/explorer_web/templates/chain/show.html.eex:97 #: lib/explorer_web/templates/transaction/index.html.eex:35 msgid "Block" msgstr "Block" -#: lib/explorer_web/templates/chain/show.html.eex:58 +#: lib/explorer_web/templates/chain/show.html.eex:46 #: lib/explorer_web/templates/layout/app.html.eex:25 msgid "Blocks" msgstr "Blocks" @@ -41,21 +41,21 @@ msgstr "%{year} POA Network Ltd. All rights reserved" #: lib/explorer_web/templates/block/index.html.eex:32 #: lib/explorer_web/templates/block_transaction/index.html.eex:60 -#: lib/explorer_web/templates/chain/show.html.eex:73 +#: lib/explorer_web/templates/chain/show.html.eex:61 msgid "Gas Used" msgstr "Gas Used" #: lib/explorer_web/templates/address_transaction/index.html.eex:67 #: lib/explorer_web/templates/block_transaction/index.html.eex:22 #: lib/explorer_web/templates/block_transaction/index.html.eex:97 -#: lib/explorer_web/templates/chain/show.html.eex:108 +#: lib/explorer_web/templates/chain/show.html.eex:96 #: lib/explorer_web/templates/pending_transaction/index.html.eex:34 #: lib/explorer_web/templates/transaction/index.html.eex:34 msgid "Hash" msgstr "Hash" #: lib/explorer_web/templates/block/index.html.eex:29 -#: lib/explorer_web/templates/chain/show.html.eex:70 +#: lib/explorer_web/templates/chain/show.html.eex:58 msgid "Height" msgstr "Height" @@ -68,9 +68,8 @@ msgstr "POA Network Explorer" #: lib/explorer_web/templates/block/index.html.eex:31 #: lib/explorer_web/templates/block_transaction/index.html.eex:16 #: lib/explorer_web/templates/block_transaction/index.html.eex:84 -#: lib/explorer_web/templates/chain/show.html.eex:45 -#: lib/explorer_web/templates/chain/show.html.eex:72 -#: lib/explorer_web/templates/chain/show.html.eex:99 +#: lib/explorer_web/templates/chain/show.html.eex:60 +#: lib/explorer_web/templates/chain/show.html.eex:87 #: lib/explorer_web/templates/layout/app.html.eex:31 #: lib/explorer_web/templates/pending_transaction/index.html.eex:12 #: lib/explorer_web/templates/transaction/index.html.eex:12 @@ -80,7 +79,7 @@ msgstr "Transactions" #: lib/explorer_web/templates/address_internal_transaction/index.html.eex:68 #: lib/explorer_web/templates/address_transaction/index.html.eex:72 #: lib/explorer_web/templates/block_transaction/index.html.eex:102 -#: lib/explorer_web/templates/chain/show.html.eex:111 +#: lib/explorer_web/templates/chain/show.html.eex:99 #: lib/explorer_web/templates/pending_transaction/index.html.eex:38 #: lib/explorer_web/templates/transaction/index.html.eex:39 #: lib/explorer_web/templates/transaction/overview.html.eex:43 @@ -301,7 +300,7 @@ msgstr "" msgid "Lag" msgstr "" -#: lib/explorer_web/templates/chain/show.html.eex:33 +#: lib/explorer_web/templates/chain/show.html.eex:11 msgid "Last Block" msgstr "" @@ -414,3 +413,25 @@ msgstr "" #: lib/explorer_web/templates/address_internal_transaction/index.html.eex:63 msgid "Parent Tx Hash" msgstr "" + +#: lib/explorer_web/templates/chain/show.html.eex:34 +msgid "24h Volume" +msgstr "" + +#: lib/explorer_web/templates/chain/show.html.eex:16 +msgid "Avg Block Time" +msgstr "" + +#: lib/explorer_web/templates/chain/show.html.eex:30 +msgid "Market Cap" +msgstr "" + +#: lib/explorer_web/templates/chain/show.html.eex:25 +msgid "Price" +msgstr "" + +#: lib/explorer_web/templates/chain/show.html.eex:26 +#: lib/explorer_web/templates/chain/show.html.eex:31 +#: lib/explorer_web/templates/chain/show.html.eex:35 +msgid "USD" +msgstr "" From 7e03c940e71658704f13ee50a74bd9cc396fbb49 Mon Sep 17 00:00:00 2001 From: Tim Mecklem Date: Thu, 10 May 2018 14:38:42 -0400 Subject: [PATCH 17/18] Changing to multiline `if` and remove pipe on single call --- .../lib/explorer/exchange_rates/exchange_rates.ex | 8 ++++++-- apps/explorer_web/lib/explorer_web/views/chain_view.ex | 3 +-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/explorer/lib/explorer/exchange_rates/exchange_rates.ex b/apps/explorer/lib/explorer/exchange_rates/exchange_rates.ex index 2fb8fbf28b..c200494150 100644 --- a/apps/explorer/lib/explorer/exchange_rates/exchange_rates.ex +++ b/apps/explorer/lib/explorer/exchange_rates/exchange_rates.ex @@ -33,7 +33,9 @@ defmodule Explorer.ExchangeRates do {symbol, token} end - if store() == :ets, do: :ets.insert(table_name(), records) + if store() == :ets do + :ets.insert(table_name(), records) + end {:noreply, state} end @@ -67,7 +69,9 @@ defmodule Explorer.ExchangeRates do write_concurrency: true ] - if store() == :ets, do: :ets.new(table_name(), table_opts) + if store() == :ets do + :ets.new(table_name(), table_opts) + end {:ok, %{}} end diff --git a/apps/explorer_web/lib/explorer_web/views/chain_view.ex b/apps/explorer_web/lib/explorer_web/views/chain_view.ex index d7ac3e117a..42d081905c 100644 --- a/apps/explorer_web/lib/explorer_web/views/chain_view.ex +++ b/apps/explorer_web/lib/explorer_web/views/chain_view.ex @@ -16,8 +16,7 @@ defmodule ExplorerWeb.ChainView do def format_exchange_rate(%Token{usd_value: nil}), do: nil def format_exchange_rate(%Token{usd_value: usd_value}) do - usd_value - |> Cldr.Number.to_string!(fractional_digits: 6) + Cldr.Number.to_string!(usd_value, fractional_digits: 6) end def format_volume_24h(%Token{volume_24h_usd: volume_24h}) do From 36d0fa236006b2e0dd662a2c0e602924802990c3 Mon Sep 17 00:00:00 2001 From: Tim Mecklem Date: Thu, 10 May 2018 15:52:35 -0400 Subject: [PATCH 18/18] =?UTF-8?q?Use=20lookup=20instead=20of=20filtering?= =?UTF-8?q?=20the=20list=20to=20get=20a=20symbol=E2=80=99s=20exchange=20ra?= =?UTF-8?q?te?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../explorer/exchange_rates/exchange_rates.ex | 13 +++++++ apps/explorer/lib/explorer/market/market.ex | 7 ++-- .../exchange_rates/exchange_rates_test.exs | 19 ++++++++-- .../test/explorer/market/market_test.exs | 37 ------------------- .../controllers/chain_controller.ex | 2 +- 5 files changed, 33 insertions(+), 45 deletions(-) diff --git a/apps/explorer/lib/explorer/exchange_rates/exchange_rates.ex b/apps/explorer/lib/explorer/exchange_rates/exchange_rates.ex index c200494150..5e2f6c8d79 100644 --- a/apps/explorer/lib/explorer/exchange_rates/exchange_rates.ex +++ b/apps/explorer/lib/explorer/exchange_rates/exchange_rates.ex @@ -90,6 +90,19 @@ defmodule Explorer.ExchangeRates do list_from_store(store()) end + @doc """ + Returns a specific rate from the tracked tickers by symbol + """ + @spec lookup(String.t()) :: Token.t() + def lookup(symbol) do + if store() == :ets do + case :ets.lookup(table_name(), symbol) do + [{_key, token} | _] -> token + _ -> nil + end + end + end + ## Undocumented public functions @doc false diff --git a/apps/explorer/lib/explorer/market/market.ex b/apps/explorer/lib/explorer/market/market.ex index ddb08eb398..73ee59fb69 100644 --- a/apps/explorer/lib/explorer/market/market.ex +++ b/apps/explorer/lib/explorer/market/market.ex @@ -12,10 +12,9 @@ defmodule Explorer.Market do @doc """ Get most recent exchange rate for the given symbol. """ - @spec fetch_exchange_rate(String.t()) :: Token.t() - def fetch_exchange_rate(symbol) do - ExchangeRates.list() - |> Enum.find(fn token -> token.symbol == symbol end) + @spec get_exchange_rate(String.t()) :: Token.t() + def get_exchange_rate(symbol) do + ExchangeRates.lookup(symbol) end @doc """ diff --git a/apps/explorer/test/explorer/exchange_rates/exchange_rates_test.exs b/apps/explorer/test/explorer/exchange_rates/exchange_rates_test.exs index e36902be99..235a4be295 100644 --- a/apps/explorer/test/explorer/exchange_rates/exchange_rates_test.exs +++ b/apps/explorer/test/explorer/exchange_rates/exchange_rates_test.exs @@ -97,13 +97,26 @@ defmodule Explorer.ExchangeRatesTest do ExchangeRates.init([]) rates = [ - %Token{id: "z", symbol: "z"}, - %Token{id: "a", symbol: "a"} + %Token{symbol: "z"}, + %Token{symbol: "a"} ] expected_rates = Enum.reverse(rates) - for rate <- rates, do: :ets.insert(ExchangeRates.table_name(), {rate.id, rate}) + for rate <- rates, do: :ets.insert(ExchangeRates.table_name(), {rate.symbol, rate}) assert expected_rates == ExchangeRates.list() end + + test "lookup/1" do + ExchangeRates.init([]) + + z = %Token{symbol: "z"} + + rates = [z, %Token{symbol: "a"}] + + for rate <- rates, do: :ets.insert(ExchangeRates.table_name(), {rate.symbol, rate}) + + assert z == ExchangeRates.lookup("z") + assert nil == ExchangeRates.lookup("nope") + end end diff --git a/apps/explorer/test/explorer/market/market_test.exs b/apps/explorer/test/explorer/market/market_test.exs index 3c4d318b0c..b989f6a1de 100644 --- a/apps/explorer/test/explorer/market/market_test.exs +++ b/apps/explorer/test/explorer/market/market_test.exs @@ -1,31 +1,10 @@ defmodule Explorer.MarketTest do use Explorer.DataCase - alias Explorer.ExchangeRates - alias Explorer.ExchangeRates.Token alias Explorer.Market alias Explorer.Market.MarketHistory alias Explorer.Repo - describe "fetch_exchange_rate/1" do - setup do - use_ets_store() - - {:ok, _} = ExchangeRates.start_link([]) - rate = %Token{id: "POA", symbol: "POA"} - :ets.insert(ExchangeRates.table_name(), {rate.id, rate}) - {:ok, %{rate: rate}} - end - - test "with matching symbol", %{rate: rate} do - assert Market.fetch_exchange_rate("POA") == rate - end - - test "with no matching symbol" do - assert Market.fetch_exchange_rate("ETH") == nil - end - end - test "fetch_recent_history/1" do today = Date.utc_today() @@ -105,20 +84,4 @@ defmodule Explorer.MarketTest do assert fetched_record.opening_price == new_record.opening_price end end - - defp use_ets_store do - # Use ets tables as ExchangeRates store and put some test data in to - # exercise Context filtering - exchange_config = Application.get_env(:explorer, Explorer.ExchangeRates) - - Application.put_env( - :explorer, - Explorer.ExchangeRates, - Keyword.put(exchange_config, :store, :ets) - ) - - on_exit(fn -> - Application.put_env(:explorer, Explorer.ExchangeRates, exchange_config) - end) - end end diff --git a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex index 5c4e73072c..1e50a2d208 100644 --- a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex +++ b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex @@ -12,7 +12,7 @@ defmodule ExplorerWeb.ChainController do "show.html", chain: Statistics.fetch(), market_history_data: Market.fetch_recent_history(30), - exchange_rate: Market.fetch_exchange_rate(coin()) || Token.null() + exchange_rate: Market.get_exchange_rate(coin()) || Token.null() ) end