From 95de1ebcb0a7123c72dfc967650c6ead7f337d02 Mon Sep 17 00:00:00 2001 From: Amanda Sposito Date: Wed, 25 Jul 2018 14:29:33 -0300 Subject: [PATCH] Add token details page backend --- apps/explorer/lib/explorer/chain.ex | 16 ++ apps/explorer/lib/explorer/chain/token.ex | 2 +- .../lib/explorer/chain/token_transfer.ex | 80 +++++++- .../explorer/chain/token_transfer_test.exs | 189 ++++++++++++++++++ apps/explorer_web/lib/explorer_web/chain.ex | 14 +- .../controllers/token_controller.ex | 31 ++- .../templates/token/_token_transfer.html.eex | 48 +++++ .../templates/token/show.html.eex | 87 +++----- .../explorer_web/views/currency_helpers.ex | 24 ++- .../lib/explorer_web/views/token_view.ex | 6 + apps/explorer_web/priv/gettext/default.pot | 36 ++++ .../priv/gettext/en/LC_MESSAGES/default.po | 36 ++++ .../views/currency_helpers_test.exs | 6 + 13 files changed, 501 insertions(+), 74 deletions(-) create mode 100644 apps/explorer/test/explorer/chain/token_transfer_test.exs create mode 100644 apps/explorer_web/lib/explorer_web/templates/token/_token_transfer.html.eex diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 3e0133ad4b..630671fe27 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -28,6 +28,7 @@ defmodule Explorer.Chain do Log, SmartContract, Token, + TokenTransfer, Transaction, Wei } @@ -1701,4 +1702,19 @@ defmodule Explorer.Chain do {:ok, token} end end + + @spec fetch_token_transfers_from_token_hash(Hash.t(), [paging_options]) :: [] + def fetch_token_transfers_from_token_hash(token_address_hash, options \\ []) do + TokenTransfer.fetch_token_transfers_from_token_hash(token_address_hash, options) + end + + @spec count_token_transfers_from_token_hash(Hash.t()) :: non_neg_integer() + def count_token_transfers_from_token_hash(token_address_hash) do + TokenTransfer.count_token_transfers_from_token_hash(token_address_hash) + end + + @spec count_addresses_in_token_transfers_from_token_hash(Hash.t()) :: non_neg_integer() + def count_addresses_in_token_transfers_from_token_hash(token_address_hash) do + TokenTransfer.count_addresses_in_token_transfers_from_token_hash(token_address_hash) + end end diff --git a/apps/explorer/lib/explorer/chain/token.ex b/apps/explorer/lib/explorer/chain/token.ex index b58fefb8f4..e3b0ee58b8 100644 --- a/apps/explorer/lib/explorer/chain/token.ex +++ b/apps/explorer/lib/explorer/chain/token.ex @@ -19,7 +19,7 @@ defmodule Explorer.Chain.Token do use Ecto.Schema - import Ecto.Changeset + import Ecto.{Changeset} alias Explorer.Chain.{Address, Hash, Token} @typedoc """ diff --git a/apps/explorer/lib/explorer/chain/token_transfer.ex b/apps/explorer/lib/explorer/chain/token_transfer.ex index 5563e43db6..3f055e193c 100644 --- a/apps/explorer/lib/explorer/chain/token_transfer.ex +++ b/apps/explorer/lib/explorer/chain/token_transfer.ex @@ -24,9 +24,13 @@ defmodule Explorer.Chain.TokenTransfer do use Ecto.Schema - import Ecto.Changeset + import Ecto.{Changeset, Query} - alias Explorer.Chain.{Address, Hash, Transaction, TokenTransfer} + alias Explorer.Chain.{Address, Block, Hash, Transaction, TokenTransfer} + alias Explorer.{PagingOptions, Repo} + alias Ecto.Adapters.SQL + + @default_paging_options %PagingOptions{page_size: 50} @typedoc """ * `:amount` - The token transferred amount @@ -56,6 +60,8 @@ defmodule Explorer.Chain.TokenTransfer do log_index: non_neg_integer() } + @typep paging_options :: {:paging_options, PagingOptions.t()} + @constant "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" schema "token_transfers" do @@ -100,4 +106,74 @@ defmodule Explorer.Chain.TokenTransfer do `first_topic` field. """ def constant, do: @constant + + @spec fetch_token_transfers_from_token_hash(Hash.t(), [paging_options]) :: [] + def fetch_token_transfers_from_token_hash(token_address_hash, options) do + paging_options = Keyword.get(options, :paging_options, @default_paging_options) + + query = + from( + tt in TokenTransfer, + join: t in Transaction, + on: tt.transaction_hash == t.hash, + join: b in Block, + on: t.block_hash == b.hash, + where: tt.token_contract_address_hash == ^token_address_hash, + preload: [{:transaction, :block}, :token, :from_address, :to_address], + order_by: [desc: b.timestamp] + ) + + query + |> page_token_transfer(paging_options) + |> limit(^paging_options.page_size) + |> Repo.all() + end + + @spec count_token_transfers_from_token_hash(Hash.t()) :: non_neg_integer() + def count_token_transfers_from_token_hash(token_address_hash) do + query = + from( + tt in TokenTransfer, + where: tt.token_contract_address_hash == ^token_address_hash, + select: count(tt.id) + ) + + Repo.one(query) + end + + @spec count_addresses_in_token_transfers_from_token_hash(Hash.t()) :: non_neg_integer() + def count_addresses_in_token_transfers_from_token_hash(token_address_hash) do + {:ok, %{rows: [[result]]}} = + SQL.query( + Repo, + """ + select count(*) as "addresses" + from + ( + select to_address_hash as "address_hash" + from token_transfers tt1 + where tt1.token_contract_address_hash = $1 + + union + + select from_address_hash as "address_hash" + from token_transfers tt2 + where tt2.token_contract_address_hash = $1 + ) as addresses_count + """, + [token_address_hash.bytes] + ) + + result + end + + defp page_token_transfer(query, %PagingOptions{key: nil}), do: query + + defp page_token_transfer(query, %PagingOptions{key: inserted_at}) do + where( + query, + [token_transfer], + token_transfer.inserted_at < ^inserted_at + ) + end end diff --git a/apps/explorer/test/explorer/chain/token_transfer_test.exs b/apps/explorer/test/explorer/chain/token_transfer_test.exs new file mode 100644 index 0000000000..a993465e22 --- /dev/null +++ b/apps/explorer/test/explorer/chain/token_transfer_test.exs @@ -0,0 +1,189 @@ +defmodule Explorer.Chain.TokenTransferTest do + use Explorer.DataCase + + import Explorer.Factory + + alias Explorer.PagingOptions + alias Explorer.Chain.TokenTransfer + + doctest Explorer.Chain.TokenTransfer + + describe "fetch_token_transfers/2" do + test "returns token transfers for the given address" do + token_contract_address = insert(:contract_address) + + transaction = + :transaction + |> insert() + |> with_block() + + token = insert(:token, contract_address: token_contract_address) + + token_transfer = + insert( + :token_transfer, + to_address: build(:address), + transaction: transaction, + token_contract_address: token_contract_address, + token: token + ) + + another_transfer = + insert( + :token_transfer, + to_address: build(:address), + transaction: transaction, + token_contract_address: token_contract_address, + token: token + ) + + insert( + :token_transfer, + to_address: build(:address), + transaction: transaction, + token_contract_address: build(:address), + token: token + ) + + transfers_ids = + token_contract_address.hash + |> TokenTransfer.fetch_token_transfers_from_token_hash([]) + |> Enum.map(& &1.id) + + assert transfers_ids == [another_transfer.id, token_transfer.id] + end + + test "when there isn't token transfers won't show anything" do + token_contract_address = insert(:contract_address) + + insert(:token, contract_address: token_contract_address) + + transfers_ids = + token_contract_address.hash + |> TokenTransfer.fetch_token_transfers_from_token_hash([]) + |> Enum.map(& &1.id) + + assert transfers_ids == [] + end + + test "token transfers can be paginated" do + token_contract_address = insert(:contract_address) + + transaction = + :transaction + |> insert() + |> with_block() + + token = insert(:token) + + second_page = + insert( + :token_transfer, + to_address: build(:address), + transaction: transaction, + token_contract_address: token_contract_address, + token: token + ) + + first_page = + insert( + :token_transfer, + to_address: build(:address), + transaction: transaction, + token_contract_address: token_contract_address, + token: token + ) + + paging_options = %PagingOptions{key: first_page.inserted_at, page_size: 1} + + token_transfers_ids_paginated = + TokenTransfer.fetch_token_transfers_from_token_hash( + token_contract_address.hash, + paging_options: paging_options + ) + |> Enum.map(& &1.id) + + assert token_transfers_ids_paginated == [second_page.id] + end + end + + describe "count_token_transfers/1" do + test "counts how many token transfers a token has" do + token_contract_address = insert(:contract_address) + + transaction = + :transaction + |> insert() + |> with_block() + + token = insert(:token) + + insert( + :token_transfer, + to_address: build(:address), + transaction: transaction, + token_contract_address: token_contract_address, + token: token + ) + + insert( + :token_transfer, + to_address: build(:address), + transaction: transaction, + token_contract_address: token_contract_address, + token: token + ) + + assert TokenTransfer.count_token_transfers_from_token_hash(token_contract_address.hash) == 2 + end + end + + describe "count_addresses_in_transfers/1" do + test "counts how many unique addresses that appeared at `to` or `from`" do + token_contract_address = insert(:contract_address) + + transaction = + :transaction + |> insert() + |> with_block() + + john_address = insert(:address) + jane_address = insert(:address) + bob_address = insert(:address) + + insert( + :token_transfer, + from_address: jane_address, + to_address: john_address, + transaction: transaction, + token_contract_address: token_contract_address + ) + + insert( + :token_transfer, + from_address: john_address, + to_address: jane_address, + transaction: transaction, + token_contract_address: token_contract_address + ) + + insert( + :token_transfer, + from_address: bob_address, + to_address: jane_address, + transaction: transaction, + token_contract_address: token_contract_address + ) + + insert( + :token_transfer, + from_address: jane_address, + to_address: bob_address, + transaction: transaction, + token_contract_address: token_contract_address + ) + + assert TokenTransfer.count_addresses_in_token_transfers_from_token_hash(token_contract_address.hash) == 3 + end + end +end diff --git a/apps/explorer_web/lib/explorer_web/chain.ex b/apps/explorer_web/lib/explorer_web/chain.ex index baf595d84b..e73cac7679 100644 --- a/apps/explorer_web/lib/explorer_web/chain.ex +++ b/apps/explorer_web/lib/explorer_web/chain.ex @@ -12,7 +12,7 @@ defmodule ExplorerWeb.Chain do string_to_transaction_hash: 1 ] - alias Explorer.Chain.{Address, Block, InternalTransaction, Log, Transaction} + alias Explorer.Chain.{Address, Block, InternalTransaction, Log, Transaction, TokenTransfer} alias Explorer.PagingOptions @page_size 50 @@ -95,6 +95,9 @@ defmodule ExplorerWeb.Chain do end end + def paging_options(%{"inserted_at" => inserted_at}), + do: [paging_options: %{@default_paging_options | key: inserted_at}] + def paging_options(_params), do: [paging_options: @default_paging_options] def param_to_block_number(formatted_number) when is_binary(formatted_number) do @@ -135,6 +138,15 @@ defmodule ExplorerWeb.Chain do %{"block_number" => block_number, "index" => index} end + defp paging_params(%TokenTransfer{inserted_at: inserted_at}) do + inserted_at_datetime = + inserted_at + |> DateTime.from_naive!("Etc/UTC") + |> DateTime.to_iso8601() + + %{"inserted_at" => inserted_at_datetime} + end + defp transaction_from_param(param) do with {:ok, hash} <- string_to_transaction_hash(param) do hash_to_transaction(hash) diff --git a/apps/explorer_web/lib/explorer_web/controllers/token_controller.ex b/apps/explorer_web/lib/explorer_web/controllers/token_controller.ex index 551199b2c0..9bd0434120 100644 --- a/apps/explorer_web/lib/explorer_web/controllers/token_controller.ex +++ b/apps/explorer_web/lib/explorer_web/controllers/token_controller.ex @@ -1,10 +1,31 @@ defmodule ExplorerWeb.TokenController do use ExplorerWeb, :controller - def show(conn, %{"id" => id, "locale" => locale}) do - render( - conn, - "show.html" - ) + alias Explorer.Chain + + import ExplorerWeb.Chain, only: [split_list_by_page: 1, paging_options: 1, next_page_params: 3] + + def show(conn, %{"id" => address_hash_string} = params) do + with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), + {:ok, token} <- Chain.token_from_address_hash(address_hash), + token_transfers <- Chain.fetch_token_transfers_from_token_hash(address_hash, paging_options(params)) do + {token_transfers_paginated, next_page} = split_list_by_page(token_transfers) + + render( + conn, + "show.html", + transfers: token_transfers_paginated, + token: token, + total_token_transfers: Chain.count_token_transfers_from_token_hash(address_hash), + total_address_in_token_transfers: Chain.count_addresses_in_token_transfers_from_token_hash(address_hash), + next_page_params: next_page_params(next_page, token_transfers_paginated, params) + ) + else + :error -> + not_found(conn) + + {:error, :not_found} -> + not_found(conn) + end end end diff --git a/apps/explorer_web/lib/explorer_web/templates/token/_token_transfer.html.eex b/apps/explorer_web/lib/explorer_web/templates/token/_token_transfer.html.eex new file mode 100644 index 0000000000..8982c6db9a --- /dev/null +++ b/apps/explorer_web/lib/explorer_web/templates/token/_token_transfer.html.eex @@ -0,0 +1,48 @@ +
+
+
+ <%= gettext "Token Transfer" %> +
+ +
+

+ <%= render ExplorerWeb.TransactionView, "_link.html", locale: @locale, transaction_hash: @transfer.transaction_hash %> +

+ + <%= render ExplorerWeb.AddressView, + "_link.html", + address_hash: to_string(@transfer.from_address_hash), + contract: ExplorerWeb.AddressView.contract?(@transfer.from_address), + locale: @locale %> + + → + + <%= render ExplorerWeb.AddressView, + "_link.html", + address_hash: to_string(@transfer.to_address_hash), + contract: ExplorerWeb.AddressView.contract?(@transfer.to_address), + locale: @locale %> + + + + + <%= token_transfer_amount(@transfer) %> <%= @transfer.token.symbol %> + +
+ +
+ + + + <%= link( + gettext( + "Block #%{number}", + number: @transfer.transaction.block_number + ), + class: "mr-2 mr-sm-0 text-muted", + to: block_path(ExplorerWeb.Endpoint, :show, @locale, @transfer.transaction.block_number) + ) %> + +
+
+
diff --git a/apps/explorer_web/lib/explorer_web/templates/token/show.html.eex b/apps/explorer_web/lib/explorer_web/templates/token/show.html.eex index 074b321a5f..09e4172beb 100644 --- a/apps/explorer_web/lib/explorer_web/templates/token/show.html.eex +++ b/apps/explorer_web/lib/explorer_web/templates/token/show.html.eex @@ -4,14 +4,22 @@
-

<%= gettext("Token Details") %>

+

+ <%= if token_name?(@token.name) do %> + <%= @token.name %> + <% else %> + <%= gettext("Token Details") %> + <% end %> +

-

0x95426f2bc716022fcf1def006dbc4bb81f5b5164

+

<%= to_string(@token.contract_address_hash) %>

- 10 <%= gettext "addresses" %> - 10 <%= gettext "Transfers" %> - 10 <%= gettext "decimals" %> + <%= @total_address_in_token_transfers %> <%= gettext "addresses" %> + <%= @total_token_transfers %> <%= gettext "Transfers" %> + <%= if decimals?(@token.decimals) do %> + <%= @token.decimals %> <%= gettext "decimals" %> + <% end %>
@@ -20,12 +28,12 @@
-

Total Suply

+

<%= gettext "Total Supply" %>

-

12345661223123456612231234 symbol

+

<%= "#{@token.total_supply} #{@token.symbol}" %>


@@ -37,7 +45,6 @@
- -
- <%= if true do %> -

<%= gettext "Token Transfers" %>

- - -
-
-
- - Token Transfer -
- -
-

0x95426f2bc716022fcf1def006dbc4bb81f5b5164

- - <%= render ExplorerWeb.AddressView, "_link.html", address_hash: "0x95426f2bc716022fcf1def006dbc4bb81f5b5164", contract: false, locale: @locale %> - - → +

<%= gettext "Token Transfers" %>

- <%= render ExplorerWeb.AddressView, "_link.html", address_hash: "0x95426f2bc716022fcf1def006dbc4bb81f5b5164", contract: false, locale: @locale %> -
- - - N symbol - -
- -
- - - - <%= link( - gettext( - "Block #%{number}", - number: "12" - ), - class: "mr-2 mr-sm-0 text-muted", - to: block_path(ExplorerWeb.Endpoint, :show, @locale, "12") - ) %> - -
-
-
-
+ <%= if Enum.any?(@transfers) do %> + <%= for transfer <- @transfers do %> + <%= render("_token_transfer.html", locale: @locale, token: @token, transfer: transfer) %> + <% end %> <% else %>
- <%= gettext "There are no transfers for this Token." %> + + <%= gettext "There are no transfers for this Token." %> +
<% end %> - <%= link( - gettext("Next"), - class: "button button--secondary button--small float-right mt-4", - to: token_path(@conn, :show, @conn.assigns.locale, "1") - ) %> + <%= if @next_page_params do %> + <%= link( + gettext("Older"), + class: "button button--secondary button--small float-right mt-4", + to: token_path(@conn, :show, @conn.assigns.locale, @token.contract_address_hash, @next_page_params) + ) %> + <% end %>
diff --git a/apps/explorer_web/lib/explorer_web/views/currency_helpers.ex b/apps/explorer_web/lib/explorer_web/views/currency_helpers.ex index 0762095d57..66c0e9e6b2 100644 --- a/apps/explorer_web/lib/explorer_web/views/currency_helpers.ex +++ b/apps/explorer_web/lib/explorer_web/views/currency_helpers.ex @@ -34,6 +34,14 @@ defmodule ExplorerWeb.CurrencyHelpers do end end + @doc """ + Formats the given integer value to a currency format. + + ## Examples + + iex> ExplorerWeb.CurrencyHelpers.format_integer_to_currency(1000000) + "1,000,000" + """ @spec format_integer_to_currency(non_neg_integer()) :: String.t() def format_integer_to_currency(value) do {:ok, formatted} = Cldr.Number.to_string(value, format: "#,##0") @@ -46,17 +54,17 @@ defmodule ExplorerWeb.CurrencyHelpers do ## Examples - iex> format_according_to_decimals(Decimal.new(20500000), 5) - "205" + iex> format_according_to_decimals(Decimal.new(20500000), 5) + "205" - iex> format_according_to_decimals(Decimal.new(20500000), 7) - "2.05" + iex> format_according_to_decimals(Decimal.new(20500000), 7) + "2.05" - iex> format_according_to_decimals(Decimal.new(205000), 12) - "0.000000205" + iex> format_according_to_decimals(Decimal.new(205000), 12) + "0.000000205" - iex> format_according_to_decimals(Decimal.new(205000), 2) - "2,050" + iex> format_according_to_decimals(Decimal.new(205000), 2) + "2,050" """ @spec format_according_to_decimals(Decimal.t(), non_neg_integer()) :: String.t() def format_according_to_decimals(%Decimal{sign: sign, coef: coef, exp: exp}, decimals) do diff --git a/apps/explorer_web/lib/explorer_web/views/token_view.ex b/apps/explorer_web/lib/explorer_web/views/token_view.ex index 2b0e651676..2a9c42e2ea 100644 --- a/apps/explorer_web/lib/explorer_web/views/token_view.ex +++ b/apps/explorer_web/lib/explorer_web/views/token_view.ex @@ -1,3 +1,9 @@ defmodule ExplorerWeb.TokenView do use ExplorerWeb, :view + + def decimals?(nil), do: false + def decimals?(_), do: true + + def token_name?(nil), do: false + def token_name?(_), do: true end diff --git a/apps/explorer_web/priv/gettext/default.pot b/apps/explorer_web/priv/gettext/default.pot index a6289cc377..0c7d301e7a 100644 --- a/apps/explorer_web/priv/gettext/default.pot +++ b/apps/explorer_web/priv/gettext/default.pot @@ -471,6 +471,7 @@ msgstr "" #: lib/explorer_web/templates/block/index.html.eex:15 #: lib/explorer_web/templates/block_transaction/index.html.eex:51 #: lib/explorer_web/templates/pending_transaction/index.html.eex:78 +#: lib/explorer_web/templates/token/show.html.eex:91 #: lib/explorer_web/templates/transaction/index.html.eex:66 msgid "Older" msgstr "" @@ -623,6 +624,7 @@ msgstr "" #, elixir-format #: lib/explorer_web/templates/address_transaction/_transaction.html.eex:41 +#: lib/explorer_web/templates/token/_token_transfer.html.eex:38 #: lib/explorer_web/templates/transaction/_tile.html.eex:28 msgid "Block #%{number}" msgstr "" @@ -707,12 +709,14 @@ msgid "Used" msgstr "" #, elixir-format +#: lib/explorer_web/templates/token/_token_transfer.html.eex:4 #: lib/explorer_web/views/transaction_view.ex:116 msgid "Token Transfer" msgstr "" #, elixir-format #: lib/explorer_web/templates/address_transaction/_transaction.html.eex:64 +#: lib/explorer_web/templates/token/show.html.eex:19 msgid "Transfers" msgstr "" @@ -739,3 +743,35 @@ msgstr "" #: lib/explorer_web/templates/transaction/index.html.eex:57 msgid "Validated Transactions" msgstr "" + +#: lib/explorer_web/templates/token/show.html.eex:84 +msgid "There are no transfers for this Token." +msgstr "" + +#, elixir-format +#: lib/explorer_web/templates/token/show.html.eex:11 +msgid "Token Details" +msgstr "" + +#, elixir-format +#: lib/explorer_web/templates/token/show.html.eex:52 +#: lib/explorer_web/templates/token/show.html.eex:62 +#: lib/explorer_web/templates/token/show.html.eex:65 +#: lib/explorer_web/templates/token/show.html.eex:75 +msgid "Token Transfers" +msgstr "" + +#, elixir-format +#: lib/explorer_web/templates/token/show.html.eex:18 +msgid "addresses" +msgstr "" + +#, elixir-format +#: lib/explorer_web/templates/token/show.html.eex:21 +msgid "decimals" +msgstr "" + +#, elixir-format +#: lib/explorer_web/templates/token/show.html.eex:31 +msgid "Total Supply" +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 ea4de2d2c0..8902c011ef 100644 --- a/apps/explorer_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/explorer_web/priv/gettext/en/LC_MESSAGES/default.po @@ -483,6 +483,7 @@ msgstr "" #: lib/explorer_web/templates/block/index.html.eex:15 #: lib/explorer_web/templates/block_transaction/index.html.eex:51 #: lib/explorer_web/templates/pending_transaction/index.html.eex:78 +#: lib/explorer_web/templates/token/show.html.eex:91 #: lib/explorer_web/templates/transaction/index.html.eex:66 msgid "Older" msgstr "" @@ -635,6 +636,7 @@ msgstr "" #, elixir-format #: lib/explorer_web/templates/address_transaction/_transaction.html.eex:41 +#: lib/explorer_web/templates/token/_token_transfer.html.eex:38 #: lib/explorer_web/templates/transaction/_tile.html.eex:28 msgid "Block #%{number}" msgstr "" @@ -719,12 +721,14 @@ msgid "Used" msgstr "" #, elixir-format +#: lib/explorer_web/templates/token/_token_transfer.html.eex:4 #: lib/explorer_web/views/transaction_view.ex:116 msgid "Token Transfer" msgstr "" #, elixir-format #: lib/explorer_web/templates/address_transaction/_transaction.html.eex:64 +#: lib/explorer_web/templates/token/show.html.eex:19 msgid "Transfers" msgstr "" @@ -751,3 +755,35 @@ msgstr "" #: lib/explorer_web/templates/transaction/index.html.eex:57 msgid "Validated Transactions" msgstr "" + +#: lib/explorer_web/templates/token/show.html.eex:84 +msgid "There are no transfers for this Token." +msgstr "" + +#, elixir-format +#: lib/explorer_web/templates/token/show.html.eex:11 +msgid "Token Details" +msgstr "" + +#, elixir-format +#: lib/explorer_web/templates/token/show.html.eex:52 +#: lib/explorer_web/templates/token/show.html.eex:62 +#: lib/explorer_web/templates/token/show.html.eex:65 +#: lib/explorer_web/templates/token/show.html.eex:75 +msgid "Token Transfers" +msgstr "" + +#, elixir-format +#: lib/explorer_web/templates/token/show.html.eex:18 +msgid "addresses" +msgstr "" + +#, elixir-format +#: lib/explorer_web/templates/token/show.html.eex:21 +msgid "decimals" +msgstr "" + +#, elixir-format, fuzzy +#: lib/explorer_web/templates/token/show.html.eex:31 +msgid "Total Supply" +msgstr "" diff --git a/apps/explorer_web/test/explorer_web/views/currency_helpers_test.exs b/apps/explorer_web/test/explorer_web/views/currency_helpers_test.exs index 758b057835..c25972a664 100644 --- a/apps/explorer_web/test/explorer_web/views/currency_helpers_test.exs +++ b/apps/explorer_web/test/explorer_web/views/currency_helpers_test.exs @@ -50,4 +50,10 @@ defmodule ExplorerWeb.CurrencyHelpersTest do assert CurrencyHelpers.format_according_to_decimals(amount, decimals) == "10,004.5" end end + + describe "format_integer_to_currency/1" do + test "formats the integer value to a currency format" do + assert CurrencyHelpers.format_integer_to_currency(9000) == "9,000" + end + end end