Add transaction fee to account transactions list

Co-authored-by: jimmay5469 <jimmay5469@gmail.com>
Co-authored-by: Luke Imhoff <luke.imhof@dockyard.com>
pull/130/head
jimmay5469 7 years ago committed by Luke Imhoff
parent 362920288b
commit 9408f19ab6
  1. 45
      apps/explorer/lib/explorer/chain.ex
  2. 50
      apps/explorer/test/explorer/chain_test.exs
  3. 4
      apps/explorer_web/lib/explorer_web/templates/address_transaction/index.html.eex
  4. 1
      apps/explorer_web/lib/explorer_web/views/address_transaction_view.ex
  5. 12
      apps/explorer_web/lib/explorer_web/views/transaction_view.ex
  6. 20
      apps/explorer_web/priv/gettext/default.pot
  7. 20
      apps/explorer_web/priv/gettext/en/LC_MESSAGES/default.po
  8. 60
      apps/explorer_web/test/explorer_web/views/address_transaction_view_test.exs

@ -191,6 +191,51 @@ defmodule Explorer.Chain do
end end
end end
@doc """
The fee a `transaction` paid for the `t:Explorer.Transaction.t/0` `gas`
If the transaction is pending, then the fee will be a range of `unit`
iex> Explorer.Chain.fee(
...> %Explorer.Chain.Transaction{gas: Decimal.new(3), gas_price: Decimal.new(2), receipt: nil},
...> :wei
...> )
{:maximum, Decimal.new(6)}
If the transaction has been confirmed in block, then the fee will be the actual fee paid in `unit` for the `gas_used`
in the `receipt`.
iex> Explorer.Chain.fee(
...> %Explorer.Chain.Transaction{
...> gas: Decimal.new(3),
...> gas_price: Decimal.new(2),
...> receipt: Explorer.Chain.Receipt{gas_used: Decimal.new(2)}
...> },
...> :wei
...> )
{:actual, Decimal.new(4)}
"""
@spec fee(%Transaction{receipt: nil}, :ether | :gwei | :wei) :: {:maximum, Decimal.t()}
def fee(%Transaction{gas: gas, gas_price: gas_price, receipt: nil}, unit) do
fee =
gas
|> Decimal.mult(gas_price)
|> Wei.to(unit)
{:maximum, fee}
end
@spec fee(%Transaction{receipt: Receipt.t()}, :ether | :gwei | :wei) :: {:actual, Decimal.t()}
def fee(%Transaction{gas_price: gas_price, receipt: %Receipt{gas_used: gas_used}}, unit) do
fee =
gas_used
|> Decimal.mult(gas_price)
|> Wei.to(unit)
{:actual, fee}
end
@doc """ @doc """
The `t:Explorer.Chain.Transaction.t/0` `gas_price` of the `transaction` in `unit`. The `t:Explorer.Chain.Transaction.t/0` `gas_price` of the `transaction` in `unit`.
""" """

@ -340,6 +340,56 @@ defmodule Explorer.ChainTest do
end end
end end
describe "fee/2" do
test "without receipt with :wei unit" do
assert Chain.fee(%Transaction{gas: Decimal.new(3), gas_price: Decimal.new(2), receipt: nil}, :wei) ==
{:maximum, Decimal.new(6)}
end
test "without receipt with :gwei unit" do
assert Chain.fee(%Transaction{gas: Decimal.new(3), gas_price: Decimal.new(2), receipt: nil}, :gwei) ==
{:maximum, Decimal.new("6e-9")}
end
test "without receipt with :ether unit" do
assert Chain.fee(%Transaction{gas: Decimal.new(3), gas_price: Decimal.new(2), receipt: nil}, :ether) ==
{:maximum, Decimal.new("6e-18")}
end
test "with receipt with :wei unit" do
assert Chain.fee(
%Transaction{
gas: Decimal.new(3),
gas_price: Decimal.new(2),
receipt: %Receipt{gas_used: Decimal.new(2)}
},
:wei
) == {:actual, Decimal.new(4)}
end
test "with receipt with :gwei unit" do
assert Chain.fee(
%Transaction{
gas: Decimal.new(3),
gas_price: Decimal.new(2),
receipt: %Receipt{gas_used: Decimal.new(2)}
},
:gwei
) == {:actual, Decimal.new("4e-9")}
end
test "with receipt with :ether unit" do
assert Chain.fee(
%Transaction{
gas: Decimal.new(3),
gas_price: Decimal.new(2),
receipt: %Receipt{gas_used: Decimal.new(2)}
},
:ether
) == {:actual, Decimal.new("4e-18")}
end
end
describe "gas_price/2" do describe "gas_price/2" do
test ":wei unit" do test ":wei unit" do
assert Chain.gas_price(%Transaction{gas_price: Decimal.new(1)}, :wei) == Decimal.new(1) assert Chain.gas_price(%Transaction{gas_price: Decimal.new(1)}, :wei) == Decimal.new(1)

@ -62,6 +62,7 @@
<th class="transactions__column-header transactions__column-header--optional"><%= gettext "From" %></th> <th class="transactions__column-header transactions__column-header--optional"><%= gettext "From" %></th>
<th class="transactions__column-header transactions__column-header--optional"><%= gettext "To" %></th> <th class="transactions__column-header transactions__column-header--optional"><%= gettext "To" %></th>
<th class="transactions__column-header"><%= gettext "Value" %></th> <th class="transactions__column-header"><%= gettext "Value" %></th>
<th class="transactions__column-header"><%= gettext "Fee" %></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -110,6 +111,9 @@
<td class="transactions__column transactions__column--value"> <td class="transactions__column transactions__column--value">
<%= value(transaction) %> <%= gettext "Ether" %> <%= value(transaction) %> <%= gettext "Ether" %>
</td> </td>
<td class="transactions__column transactions__column--value">
<%= fee(transaction) %> <%= gettext "Ether" %>
</td>
</tr> </tr>
<% end %> <% end %>
</tbody> </tbody>

@ -4,6 +4,7 @@ defmodule ExplorerWeb.AddressTransactionView do
alias ExplorerWeb.{AddressView, TransactionView} alias ExplorerWeb.{AddressView, TransactionView}
defdelegate balance(address), to: AddressView defdelegate balance(address), to: AddressView
defdelegate fee(transaction), to: TransactionView
defdelegate status(transacton), to: TransactionView defdelegate status(transacton), to: TransactionView
defdelegate value(transaction), to: TransactionView defdelegate value(transaction), to: TransactionView
end end

@ -22,6 +22,18 @@ defmodule ExplorerWeb.TransactionView do
end end
end end
def fee(transaction) do
transaction
|> Chain.fee(:ether)
|> case do
{:actual, actual} ->
Cldr.Number.to_string!(actual, fractional_digits: 18)
{:maximum, maximum} ->
"<= " <> Cldr.Number.to_string!(maximum, fractional_digits: 18)
end
end
def first_seen(%Transaction{inserted_at: inserted_at}) do def first_seen(%Transaction{inserted_at: inserted_at}) do
Timex.from_now(inserted_at) Timex.from_now(inserted_at)
end end

@ -173,7 +173,7 @@ msgstr ""
msgid "Overview" msgid "Overview"
msgstr "" msgstr ""
#: lib/explorer_web/views/transaction_view.ex:72 #: lib/explorer_web/views/transaction_view.ex:84
msgid "Success" msgid "Success"
msgstr "" msgstr ""
@ -229,9 +229,9 @@ msgstr ""
#: lib/explorer_web/templates/transaction/overview.html.eex:56 #: lib/explorer_web/templates/transaction/overview.html.eex:56
#: lib/explorer_web/templates/transaction/overview.html.eex:70 #: lib/explorer_web/templates/transaction/overview.html.eex:70
#: lib/explorer_web/views/transaction_view.ex:20 #: lib/explorer_web/views/transaction_view.ex:20
#: lib/explorer_web/views/transaction_view.ex:35 #: lib/explorer_web/views/transaction_view.ex:47
#: lib/explorer_web/views/transaction_view.ex:42 #: lib/explorer_web/views/transaction_view.ex:54
#: lib/explorer_web/views/transaction_view.ex:71 #: lib/explorer_web/views/transaction_view.ex:83
msgid "Pending" msgid "Pending"
msgstr "" msgstr ""
@ -294,11 +294,11 @@ msgstr ""
msgid "Next Page" msgid "Next Page"
msgstr "" msgstr ""
#: lib/explorer_web/views/transaction_view.ex:69 #: lib/explorer_web/views/transaction_view.ex:81
msgid "Failed" msgid "Failed"
msgstr "" msgstr ""
#: lib/explorer_web/views/transaction_view.ex:70 #: lib/explorer_web/views/transaction_view.ex:82
msgid "Out of Gas" msgid "Out of Gas"
msgstr "" msgstr ""
@ -318,7 +318,8 @@ msgid "Showing #%{number}"
msgstr "" msgstr ""
#: lib/explorer_web/templates/address_transaction/index.html.eex:12 #: lib/explorer_web/templates/address_transaction/index.html.eex:12
#: lib/explorer_web/templates/address_transaction/index.html.eex:111 #: lib/explorer_web/templates/address_transaction/index.html.eex:112
#: lib/explorer_web/templates/address_transaction/index.html.eex:115
#: lib/explorer_web/templates/block_transaction/index.html.eex:90 #: lib/explorer_web/templates/block_transaction/index.html.eex:90
#: lib/explorer_web/templates/chain/show.html.eex:128 #: lib/explorer_web/templates/chain/show.html.eex:128
#: lib/explorer_web/templates/pending_transaction/index.html.eex:80 #: lib/explorer_web/templates/pending_transaction/index.html.eex:80
@ -373,3 +374,8 @@ msgstr ""
#: lib/explorer_web/templates/address_transaction/index.html.eex:31 #: lib/explorer_web/templates/address_transaction/index.html.eex:31
msgid "All" msgid "All"
msgstr "" msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address_transaction/index.html.eex:65
msgid "Fee"
msgstr ""

@ -185,7 +185,7 @@ msgstr "From"
msgid "Overview" msgid "Overview"
msgstr "Overview" msgstr "Overview"
#: lib/explorer_web/views/transaction_view.ex:72 #: lib/explorer_web/views/transaction_view.ex:84
msgid "Success" msgid "Success"
msgstr "Success" msgstr "Success"
@ -241,9 +241,9 @@ msgstr "Showing %{count} Transactions"
#: lib/explorer_web/templates/transaction/overview.html.eex:56 #: lib/explorer_web/templates/transaction/overview.html.eex:56
#: lib/explorer_web/templates/transaction/overview.html.eex:70 #: lib/explorer_web/templates/transaction/overview.html.eex:70
#: lib/explorer_web/views/transaction_view.ex:20 #: lib/explorer_web/views/transaction_view.ex:20
#: lib/explorer_web/views/transaction_view.ex:35 #: lib/explorer_web/views/transaction_view.ex:47
#: lib/explorer_web/views/transaction_view.ex:42 #: lib/explorer_web/views/transaction_view.ex:54
#: lib/explorer_web/views/transaction_view.ex:71 #: lib/explorer_web/views/transaction_view.ex:83
msgid "Pending" msgid "Pending"
msgstr "Pending" msgstr "Pending"
@ -306,11 +306,11 @@ msgstr ""
msgid "Next Page" msgid "Next Page"
msgstr "" msgstr ""
#: lib/explorer_web/views/transaction_view.ex:69 #: lib/explorer_web/views/transaction_view.ex:81
msgid "Failed" msgid "Failed"
msgstr "" msgstr ""
#: lib/explorer_web/views/transaction_view.ex:70 #: lib/explorer_web/views/transaction_view.ex:82
msgid "Out of Gas" msgid "Out of Gas"
msgstr "" msgstr ""
@ -330,7 +330,8 @@ msgid "Showing #%{number}"
msgstr "" msgstr ""
#: lib/explorer_web/templates/address_transaction/index.html.eex:12 #: lib/explorer_web/templates/address_transaction/index.html.eex:12
#: lib/explorer_web/templates/address_transaction/index.html.eex:111 #: lib/explorer_web/templates/address_transaction/index.html.eex:112
#: lib/explorer_web/templates/address_transaction/index.html.eex:115
#: lib/explorer_web/templates/block_transaction/index.html.eex:90 #: lib/explorer_web/templates/block_transaction/index.html.eex:90
#: lib/explorer_web/templates/chain/show.html.eex:128 #: lib/explorer_web/templates/chain/show.html.eex:128
#: lib/explorer_web/templates/pending_transaction/index.html.eex:80 #: lib/explorer_web/templates/pending_transaction/index.html.eex:80
@ -385,3 +386,8 @@ msgstr ""
#: lib/explorer_web/templates/address_transaction/index.html.eex:31 #: lib/explorer_web/templates/address_transaction/index.html.eex:31
msgid "All" msgid "All"
msgstr "" msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address_transaction/index.html.eex:65
msgid "Fee"
msgstr ""

@ -0,0 +1,60 @@
defmodule ExplorerWeb.AddressTransactionViewTest do
use Explorer.DataCase
alias ExplorerWeb.AddressTransactionView
describe "fee/0" do
test "formats the fee for a successful transaction" do
insert(:block, number: 24)
time = Timex.now() |> Timex.shift(hours: -2)
block =
insert(:block, %{
number: 1,
gas_used: 99523,
timestamp: time
})
to_address = insert(:address, hash: "0xsleepypuppy")
from_address = insert(:address, hash: "0xilovefrogs")
transaction =
insert(
:transaction,
inserted_at: Timex.parse!("1970-01-01T00:00:18-00:00", "{ISO:Extended}"),
updated_at: Timex.parse!("1980-01-01T00:00:18-00:00", "{ISO:Extended}"),
to_address_id: to_address.id,
from_address_id: from_address.id,
gas_price: Decimal.new(1_000_000_000.0)
)
|> with_block(block)
insert(:receipt, status: 1, gas_used: Decimal.new(435_334), transaction: transaction)
transaction =
transaction
|> Repo.preload([:receipt])
assert AddressTransactionView.fee(transaction) == "0.000,435,334,000,000,000"
end
test "fee returns max_gas for pending transaction" do
to_address = insert(:address, hash: "0xchadmuska")
from_address = insert(:address, hash: "0xtonyhawk")
transaction =
insert(
:transaction,
inserted_at: Timex.parse!("1970-01-01T00:00:18-00:00", "{ISO:Extended}"),
updated_at: Timex.parse!("1980-01-01T00:00:18-00:00", "{ISO:Extended}"),
to_address_id: to_address.id,
from_address_id: from_address.id,
gas: Decimal.new(21000.0),
gas_price: Decimal.new(1_000_000_000.0)
)
|> Repo.preload([:to_address, :from_address, :receipt])
assert AddressTransactionView.fee(transaction) == "<= 0.000,021,000,000,000,000"
end
end
end
Loading…
Cancel
Save