Use a join table to link Blocks and Transactions.

pull/2/head
CJ Bryan and Matt Olenick 7 years ago
parent 5409faf7e3
commit 9570cd46de
  1. 13
      lib/explorer/block.ex
  2. 24
      lib/explorer/block_transaction.ex
  3. 23
      lib/explorer/fetcher.ex
  4. 18
      lib/explorer/forms/block_form.ex
  5. 48
      lib/explorer/forms/transaction_form.ex
  6. 7
      lib/explorer/from_address.ex
  7. 95
      lib/explorer/importers/transaction_importer.ex
  8. 7
      lib/explorer/to_address.ex
  9. 14
      lib/explorer/transaction.ex
  10. 8
      lib/explorer_web/controllers/block_controller.ex
  11. 19
      lib/explorer_web/controllers/chain_controller.ex
  12. 16
      lib/explorer_web/controllers/transaction_controller.ex
  13. 2
      lib/explorer_web/templates/transaction/show.html.eex
  14. 47
      priv/gettext/default.pot
  15. 47
      priv/gettext/en/LC_MESSAGES/default.po
  16. 14
      priv/repo/migrations/20180202195342_create_block_transactions.exs
  17. 9
      priv/repo/migrations/20180202215933_remove_block_id_from_transactions.exs
  18. 17
      test/explorer/block_transaction_test.exs
  19. 52
      test/explorer/fetcher_test.exs
  20. 4
      test/explorer/forms/block_form_test.exs
  21. 56
      test/explorer/forms/transaction_form_test.exs
  22. 235
      test/explorer/importers/transaction_importer_test.exs
  23. 9
      test/explorer/transaction_test.exs
  24. 26
      test/explorer_web/controllers/chain_controller_test.exs
  25. 25
      test/explorer_web/controllers/transaction_controller_test.exs
  26. 6
      test/explorer_web/features/contributor_browsing_test.exs
  27. 9
      test/support/factories/block_transaction_factory.ex
  28. 21
      test/support/factories/transaction_factory.ex
  29. 1
      test/support/factory.ex
  30. 30
      test/support/fixture/vcr_cassettes/transaction_importer_creates_a_from_address.json
  31. 30
      test/support/fixture/vcr_cassettes/transaction_importer_creates_a_to_address.json
  32. 30
      test/support/fixture/vcr_cassettes/transaction_importer_creates_a_to_address_from_creates.json
  33. 30
      test/support/fixture/vcr_cassettes/transaction_importer_download_transaction.json
  34. 30
      test/support/fixture/vcr_cassettes/transaction_importer_download_transaction_with_a_bad_hash.json
  35. 30
      test/support/fixture/vcr_cassettes/transaction_importer_import_saves_the_transaction.json
  36. 30
      test/support/fixture/vcr_cassettes/transaction_importer_saves_the_association.json
  37. 30
      test/support/fixture/vcr_cassettes/transaction_importer_txn_without_block.json
  38. 30
      test/support/fixture/vcr_cassettes/transaction_importer_updates_the_association.json

@ -1,8 +1,9 @@
defmodule Explorer.Block do
use Ecto.Schema
alias Explorer.Block
alias Explorer.BlockTransaction
import Ecto.Changeset
use Ecto.Schema
import Ecto.Query
alias Explorer.Block
@moduledoc false
@ -10,6 +11,8 @@ defmodule Explorer.Block do
autogenerate: {Timex.Ecto.DateTime, :autogenerate, []}]
schema "blocks" do
has_many :block_transactions, BlockTransaction
has_many :transactions, through: [:block_transactions, :transaction]
field :number, :integer
field :hash, :string
field :parent_hash, :string
@ -22,19 +25,15 @@ defmodule Explorer.Block do
field :gas_used, :integer
field :timestamp, Timex.Ecto.DateTime
timestamps()
has_many :transactions, Explorer.Transaction
end
@required_attrs ~w(number hash parent_hash nonce miner difficulty
total_difficulty size gas_limit gas_used timestamp)a
@optional_attrs ~w()a
@doc false
def changeset(%Block{} = block, attrs) do
block
|> cast(attrs, @required_attrs, @optional_attrs)
|> cast_assoc(:transactions)
|> cast(attrs, @required_attrs)
|> validate_required(@required_attrs)
|> update_change(:hash, &String.downcase/1)
|> unique_constraint(:hash)

@ -0,0 +1,24 @@
defmodule Explorer.BlockTransaction do
@moduledoc false
alias Explorer.BlockTransaction
import Ecto.Changeset
use Ecto.Schema
@timestamps_opts [type: Timex.Ecto.DateTime,
autogenerate: {Timex.Ecto.DateTime, :autogenerate, []}]
@primary_key false
schema "block_transactions" do
belongs_to :block, Explorer.Block
belongs_to :transaction, Explorer.Transaction, primary_key: true
timestamps()
end
@required_attrs ~w(block_id transaction_id)a
def changeset(%BlockTransaction{} = block_transaction, attrs \\ %{}) do
block_transaction
|> cast(attrs, @required_attrs)
|> validate_required(@required_attrs)
end
end

@ -2,6 +2,7 @@ defmodule Explorer.Fetcher do
@moduledoc false
alias Explorer.Address
alias Explorer.Block
alias Explorer.BlockTransaction
alias Explorer.FromAddress
alias Explorer.Repo.NewRelic, as: Repo
alias Explorer.ToAddress
@ -52,13 +53,30 @@ defmodule Explorer.Fetcher do
def create_transaction(block, changes) do
transaction = Repo.get_by(Transaction, hash: changes["hash"]) || %Transaction{}
transaction
|> Transaction.changeset(extract_transaction(block, changes))
|> Transaction.changeset(extract_transaction(changes))
|> Repo.insert_or_update!
|> create_from_address(changes["from"])
|> create_to_address(changes["to"] || changes["creates"])
|> create_block_transaction(block)
end
def extract_transaction(block, transaction) do
def create_block_transaction(transaction, block) do
if block do
block_transaction =
Repo.get_by(BlockTransaction, transaction_id: transaction.id) ||
%BlockTransaction{}
changes = %{block_id: block.id, transaction_id: transaction.id}
block_transaction
|> BlockTransaction.changeset(changes)
|> Repo.insert_or_update!
end
transaction
end
def extract_transaction(transaction) do
%{
hash: transaction["hash"],
value: transaction["value"] |> decode_integer_field,
@ -72,7 +90,6 @@ defmodule Explorer.Fetcher do
standard_v: transaction["standardV"],
transaction_index: transaction["transactionIndex"],
v: transaction["v"],
block_id: block.id,
}
end

@ -1,9 +1,9 @@
defmodule Explorer.BlockForm do
import Ecto.Query
alias Explorer.Transaction
alias Explorer.Repo
@moduledoc false
alias Explorer.Block
alias Explorer.BlockTransaction
alias Explorer.Repo
import Ecto.Query
def build(block) do
block |> Map.merge(%{
@ -14,10 +14,12 @@ defmodule Explorer.BlockForm do
end
def get_transactions_count(block) do
Transaction
|> where([t], t.block_id == ^block.id)
|> Repo.all
|> Enum.count
query = from block_transaction in BlockTransaction,
join: block in Block,
where: block.id == block_transaction.block_id,
where: block.id == ^block.id,
select: count(block_transaction.block_id)
Repo.one(query)
end
def calculate_age(block) do

@ -1,40 +1,56 @@
defmodule Explorer.TransactionForm do
@moduledoc false
alias Cldr.Number
alias Explorer.Address
alias Explorer.Block
alias Explorer.BlockTransaction
alias Explorer.FromAddress
alias Explorer.Repo
alias Explorer.ToAddress
alias Explorer.Transaction
import Ecto.Query
@moduledoc "Format a Block and a Transaction for display."
def build(transaction) do
block = with_block(transaction)
transaction
|> Map.merge(%{
block_number: transaction |> block_number,
age: transaction |> block_age,
formatted_timestamp: transaction |> format_timestamp,
cumulative_gas_used: transaction |> cumulative_gas_used,
block_number: block |> block_number,
age: block |> block_age,
formatted_timestamp: block |> format_timestamp,
cumulative_gas_used: block |> cumulative_gas_used,
to_address: transaction |> to_address,
from_address: transaction |> from_address,
confirmations: transaction |> confirmations,
confirmations: block |> confirmations,
})
end
def block_number(transaction) do
transaction.block.number
def with_block(transaction) do
Repo.one(
from block in Block,
join: block_transaction in BlockTransaction,
where: block_transaction.block_id == block.id,
join: transaction in Transaction,
where: transaction.id == block_transaction.transaction_id,
where: transaction.id == ^transaction.id
)
end
def block_number(block) do
block && block.number || ""
end
def block_age(transaction) do
transaction.block.timestamp |> Timex.from_now
def block_age(block) do
block && block.timestamp |> Timex.from_now || ""
end
def format_timestamp(transaction) do
transaction.block.timestamp |> Timex.format!("%b-%d-%Y %H:%M:%S %p %Z", :strftime)
def format_timestamp(block) do
block && block.timestamp |> Timex.format!("%b-%d-%Y %H:%M:%S %p %Z", :strftime) || ""
end
def cumulative_gas_used(transaction) do
transaction.block.gas_used
def cumulative_gas_used(block) do
block && block.gas_used |> Number.to_string! || ""
end
def to_address(transaction) do
@ -59,8 +75,8 @@ defmodule Explorer.TransactionForm do
Repo.one(query).hash
end
def confirmations(transaction) do
def confirmations(block) do
query = from block in Block, select: max(block.number)
Repo.one(query) - transaction.block.number
block && Repo.one(query) - block.number || 0
end
end

@ -1,9 +1,8 @@
defmodule Explorer.FromAddress do
use Ecto.Schema
import Ecto.Changeset
alias Explorer.FromAddress
@moduledoc false
alias Explorer.FromAddress
import Ecto.Changeset
use Ecto.Schema
@timestamps_opts [type: Timex.Ecto.DateTime,
autogenerate: {Timex.Ecto.DateTime, :autogenerate, []}]

@ -0,0 +1,95 @@
defmodule Explorer.TransactionImporter do
@moduledoc "Imports a transaction given a unique hash."
import Ethereumex.HttpClient, only: [eth_get_transaction_by_hash: 1]
alias Explorer.Address
alias Explorer.Block
alias Explorer.BlockTransaction
alias Explorer.Repo
alias Explorer.FromAddress
alias Explorer.ToAddress
alias Explorer.Transaction
def import(hash) do
raw_transaction = download_transaction(hash)
changes = extract_attrs(raw_transaction)
transaction = Repo.get_by(Transaction, hash: changes.hash) || %Transaction{}
transaction
|> Transaction.changeset(changes)
|> Repo.insert_or_update!
|> create_from_address(raw_transaction["from"])
|> create_to_address(raw_transaction["to"] || raw_transaction["creates"])
|> create_block_transaction(raw_transaction["blockHash"])
end
def download_transaction(hash) do
{:ok, payload} = eth_get_transaction_by_hash(hash)
payload
end
def extract_attrs(raw_transaction) do
%{
hash: raw_transaction["hash"],
value: raw_transaction["value"] |> decode_integer_field,
gas: raw_transaction["gas"] |> decode_integer_field,
gas_price: raw_transaction["gasPrice"] |> decode_integer_field,
input: raw_transaction["input"],
nonce: raw_transaction["nonce"] |> decode_integer_field,
public_key: raw_transaction["publicKey"],
r: raw_transaction["r"],
s: raw_transaction["s"],
standard_v: raw_transaction["standardV"],
transaction_index: raw_transaction["transactionIndex"],
v: raw_transaction["v"],
}
end
def create_block_transaction(transaction, block_hash) do
block = Repo.get_by(Block, hash: block_hash)
if block do
block_transaction =
Repo.get_by(BlockTransaction, transaction_id: transaction.id) ||
%BlockTransaction{}
changes = %{block_id: block.id, transaction_id: transaction.id}
block_transaction
|>BlockTransaction.changeset(changes)
|> Repo.insert_or_update!
end
transaction
end
def create_from_address(transaction, hash) do
address = Address.find_or_create_by_hash(hash)
changes = %{transaction_id: transaction.id, address_id: address.id}
from_address = Repo.get_by(FromAddress, changes) || %FromAddress{}
from_address
|> FromAddress.changeset(changes)
|> Repo.insert_or_update!
transaction
end
def create_to_address(transaction, hash) do
address = Address.find_or_create_by_hash(hash)
changes = %{transaction_id: transaction.id, address_id: address.id}
to_address = Repo.get_by(ToAddress, changes) || %ToAddress{}
to_address
|> ToAddress.changeset(changes)
|> Repo.insert_or_update!
transaction
end
def decode_integer_field(hex) do
{"0x", base_16} = String.split_at(hex, 2)
String.to_integer(base_16, 16)
end
end

@ -1,9 +1,8 @@
defmodule Explorer.ToAddress do
use Ecto.Schema
import Ecto.Changeset
alias Explorer.ToAddress
@moduledoc false
alias Explorer.ToAddress
import Ecto.Changeset
use Ecto.Schema
@timestamps_opts [type: Timex.Ecto.DateTime,
autogenerate: {Timex.Ecto.DateTime, :autogenerate, []}]

@ -1,14 +1,16 @@
defmodule Explorer.Transaction do
@moduledoc false
use Ecto.Schema
import Ecto.Changeset
alias Explorer.BlockTransaction
alias Explorer.Transaction
import Ecto.Changeset
use Ecto.Schema
@timestamps_opts [type: Timex.Ecto.DateTime,
autogenerate: {Timex.Ecto.DateTime, :autogenerate, []}]
schema "transactions" do
has_one :block_transaction, BlockTransaction
has_one :block, through: [:block_transaction, :block]
field :hash, :string
field :value, :decimal
field :gas, :decimal
@ -22,10 +24,6 @@ defmodule Explorer.Transaction do
field :transaction_index, :string
field :v, :string
timestamps()
belongs_to :block, Explorer.Block
many_to_many :to_address, Explorer.Address, join_through: "to_addresses", unique: true
end
@required_attrs ~w(hash value gas gas_price input nonce public_key r s
@ -35,7 +33,7 @@ defmodule Explorer.Transaction do
@doc false
def changeset(%Transaction{} = transaction, attrs \\ %{}) do
transaction
|> cast(attrs, [:block_id | @required_attrs], @optional_attrs)
|> cast(attrs, @required_attrs, @optional_attrs)
|> validate_required(@required_attrs)
|> foreign_key_constraint(:block_id)
|> update_change(:hash, &String.downcase/1)

@ -8,9 +8,11 @@ defmodule ExplorerWeb.BlockController do
alias Explorer.Repo.NewRelic, as: Repo
def index(conn, params) do
blocks = from b in Block,
order_by: [desc: b.number],
preload: :transactions
blocks = from block in Block,
left_join: block_transaction in assoc(block, :block_transactions),
left_join: transactions in assoc(block_transaction, :transaction),
preload: [transactions: transactions],
order_by: [desc: block.number]
render(conn, "index.html", blocks: Repo.paginate(blocks, params))
end

@ -4,8 +4,10 @@ defmodule ExplorerWeb.ChainController do
import Ecto.Query
alias Explorer.Block
alias Explorer.BlockForm
alias Explorer.Repo.NewRelic, as: Repo
alias Explorer.Transaction
alias Explorer.TransactionForm
def show(conn, _params) do
blocks = from b in Block,
@ -13,17 +15,20 @@ defmodule ExplorerWeb.ChainController do
preload: :transactions,
limit: 5
transactions = from t in Transaction,
join: b in Block, on: b.id == t.block_id,
order_by: [desc: b.number],
preload: :block,
limit: 5
transactions = from transaction in Transaction,
left_join: block_transaction in assoc(transaction, :block_transaction),
left_join: block in assoc(block_transaction, :block),
preload: [block_transaction: block_transaction, block: block],
limit: 5,
order_by: [desc: block.number]
render(
conn,
"show.html",
blocks: Repo.all(blocks),
transactions: Repo.all(transactions)
blocks: blocks |> Repo.all |> Enum.map(&BlockForm.build/1),
transactions: transactions
|> Repo.all
|> Enum.map(&TransactionForm.build/1)
)
end
end

@ -3,18 +3,20 @@ defmodule ExplorerWeb.TransactionController do
import Ecto.Query
alias Explorer.Block
alias Explorer.Repo.NewRelic, as: Repo
alias Explorer.Transaction
alias Explorer.TransactionForm
def index(conn, params) do
transactions = from t in Transaction,
join: b in Block, on: b.id == t.block_id,
order_by: [desc: b.number],
preload: :block
query = from transaction in Transaction,
left_join: block_transaction in assoc(transaction, :block_transaction),
left_join: block in assoc(block_transaction, :block),
preload: [block_transaction: block_transaction, block: block],
order_by: [asc: block.inserted_at]
render(conn, "index.html", transactions: Repo.paginate(transactions, params))
transactions = Repo.paginate(query, params)
render(conn, "index.html", transactions: transactions)
end
def show(conn, params) do
@ -22,8 +24,8 @@ defmodule ExplorerWeb.TransactionController do
|> where(hash: ^params["id"])
|> first
|> Repo.one
|> Repo.preload(:block)
|> TransactionForm.build
render(conn, "show.html", transaction: transaction)
end
end

@ -63,7 +63,7 @@
</div>
<div class="transaction__item">
<dt class="transaction__item-key"><%= gettext "Cumulative Gas Used" %></dt>
<dd class="transaction__item-value"><%= @transaction.cumulative_gas_used |> Cldr.Number.to_string! %></dd>
<dd class="transaction__item-value"><%= @transaction.cumulative_gas_used %></dd>
</div>
<div class="transaction__item">
<dt class="transaction__item-key"><%= gettext "Nonce" %></dt>

@ -1,14 +1,18 @@
#: lib/explorer_web/templates/page/index.html.eex:11
#: lib/explorer_web/templates/page/index.html.eex:39
#: lib/explorer_web/templates/block/index.html.eex:12
#: lib/explorer_web/templates/chain/show.html.eex:11
#: lib/explorer_web/templates/chain/show.html.eex:39
#: lib/explorer_web/templates/transaction/index.html.eex:13
#: lib/explorer_web/templates/transaction/show.html.eex:33
msgid "Age"
msgstr ""
#: lib/explorer_web/templates/page/index.html.eex:38
#: lib/explorer_web/templates/chain/show.html.eex:38
#: lib/explorer_web/templates/transaction/index.html.eex:12
msgid "Block"
msgstr ""
#: lib/explorer_web/templates/page/index.html.eex:4
#: lib/explorer_web/templates/chain/show.html.eex:4
#: lib/explorer_web/templates/layout/_header.html.eex:16
msgid "Blocks"
msgstr ""
@ -16,17 +20,20 @@ msgstr ""
msgid "Copyright %{year} POA"
msgstr ""
#: lib/explorer_web/templates/block/index.html.eex:14
#: lib/explorer_web/templates/block/show.html.eex:53
#: lib/explorer_web/templates/page/index.html.eex:13
#: lib/explorer_web/templates/chain/show.html.eex:13
msgid "Gas Used"
msgstr ""
#: lib/explorer_web/templates/block/show.html.eex:25
#: lib/explorer_web/templates/page/index.html.eex:37
#: lib/explorer_web/templates/chain/show.html.eex:37
#: lib/explorer_web/templates/transaction/index.html.eex:11
msgid "Hash"
msgstr ""
#: lib/explorer_web/templates/page/index.html.eex:10
#: lib/explorer_web/templates/block/index.html.eex:11
#: lib/explorer_web/templates/chain/show.html.eex:10
msgid "Height"
msgstr ""
@ -35,13 +42,16 @@ msgstr ""
msgid "POA Network Explorer"
msgstr ""
#: lib/explorer_web/templates/block/index.html.eex:13
#: lib/explorer_web/templates/block/show.html.eex:21
#: lib/explorer_web/templates/page/index.html.eex:12
#: lib/explorer_web/templates/page/index.html.eex:31
#: lib/explorer_web/templates/chain/show.html.eex:12
#: lib/explorer_web/templates/chain/show.html.eex:31
#: lib/explorer_web/templates/layout/_header.html.eex:12
msgid "Transactions"
msgstr ""
#: lib/explorer_web/templates/page/index.html.eex:40
#: lib/explorer_web/templates/chain/show.html.eex:40
#: lib/explorer_web/templates/transaction/index.html.eex:14
#: lib/explorer_web/templates/transaction/show.html.eex:37
#: lib/explorer_web/templates/transaction/show.html.eex:49
msgid "Value"
@ -55,6 +65,7 @@ msgstr ""
msgid "Difficulty"
msgstr ""
#: lib/explorer_web/templates/block/index.html.eex:15
#: lib/explorer_web/templates/block/show.html.eex:57
#: lib/explorer_web/templates/transaction/show.html.eex:57
msgid "Gas Limit"
@ -105,6 +116,7 @@ msgstr ""
msgid "Gas"
msgstr ""
#: lib/explorer_web/templates/block/index.html.eex:16
#: lib/explorer_web/templates/transaction/show.html.eex:61
msgid "Gas Price"
msgstr ""
@ -155,7 +167,20 @@ msgid "Balance"
msgstr ""
#: lib/explorer_web/templates/address/show.html.eex:11
#: lib/explorer_web/templates/page/index.html.eex:53
#: lib/explorer_web/templates/chain/show.html.eex:53
#: lib/explorer_web/templates/transaction/index.html.eex:25
#: lib/explorer_web/templates/transaction/show.html.eex:38
msgid "POA"
msgstr ""
#: lib/explorer_web/templates/block/index.html.eex:24
msgid "%{count} transactions"
msgstr ""
#: lib/explorer_web/templates/block/index.html.eex:3
msgid "Showing #%{start_block} to #%{end_block}"
msgstr ""
#: lib/explorer_web/templates/transaction/index.html.eex:3
msgid "Showing %{count} Transactions"
msgstr ""

@ -10,17 +10,21 @@ msgid ""
msgstr ""
"Language: en\n"
#: lib/explorer_web/templates/page/index.html.eex:11
#: lib/explorer_web/templates/page/index.html.eex:39
#: lib/explorer_web/templates/block/index.html.eex:12
#: lib/explorer_web/templates/chain/show.html.eex:11
#: lib/explorer_web/templates/chain/show.html.eex:39
#: lib/explorer_web/templates/transaction/index.html.eex:13
#: lib/explorer_web/templates/transaction/show.html.eex:33
msgid "Age"
msgstr "Age"
#: lib/explorer_web/templates/page/index.html.eex:38
#: lib/explorer_web/templates/chain/show.html.eex:38
#: lib/explorer_web/templates/transaction/index.html.eex:12
msgid "Block"
msgstr "Block"
#: lib/explorer_web/templates/page/index.html.eex:4
#: lib/explorer_web/templates/chain/show.html.eex:4
#: lib/explorer_web/templates/layout/_header.html.eex:16
msgid "Blocks"
msgstr "Blocks"
@ -28,17 +32,20 @@ msgstr "Blocks"
msgid "Copyright %{year} POA"
msgstr "%{year} POA Network Ltd. All rights reserved"
#: lib/explorer_web/templates/block/index.html.eex:14
#: lib/explorer_web/templates/block/show.html.eex:53
#: lib/explorer_web/templates/page/index.html.eex:13
#: lib/explorer_web/templates/chain/show.html.eex:13
msgid "Gas Used"
msgstr "Gas Used"
#: lib/explorer_web/templates/block/show.html.eex:25
#: lib/explorer_web/templates/page/index.html.eex:37
#: lib/explorer_web/templates/chain/show.html.eex:37
#: lib/explorer_web/templates/transaction/index.html.eex:11
msgid "Hash"
msgstr "Hash"
#: lib/explorer_web/templates/page/index.html.eex:10
#: lib/explorer_web/templates/block/index.html.eex:11
#: lib/explorer_web/templates/chain/show.html.eex:10
msgid "Height"
msgstr "Height"
@ -47,13 +54,16 @@ msgstr "Height"
msgid "POA Network Explorer"
msgstr "POA Network Explorer"
#: lib/explorer_web/templates/block/index.html.eex:13
#: lib/explorer_web/templates/block/show.html.eex:21
#: lib/explorer_web/templates/page/index.html.eex:12
#: lib/explorer_web/templates/page/index.html.eex:31
#: lib/explorer_web/templates/chain/show.html.eex:12
#: lib/explorer_web/templates/chain/show.html.eex:31
#: lib/explorer_web/templates/layout/_header.html.eex:12
msgid "Transactions"
msgstr "Transactions"
#: lib/explorer_web/templates/page/index.html.eex:40
#: lib/explorer_web/templates/chain/show.html.eex:40
#: lib/explorer_web/templates/transaction/index.html.eex:14
#: lib/explorer_web/templates/transaction/show.html.eex:37
#: lib/explorer_web/templates/transaction/show.html.eex:49
msgid "Value"
@ -67,6 +77,7 @@ msgstr "Block #%{number} Details"
msgid "Difficulty"
msgstr "Difficulty"
#: lib/explorer_web/templates/block/index.html.eex:15
#: lib/explorer_web/templates/block/show.html.eex:57
#: lib/explorer_web/templates/transaction/show.html.eex:57
msgid "Gas Limit"
@ -117,6 +128,7 @@ msgstr "Cumulative Gas Used"
msgid "Gas"
msgstr "Gas"
#: lib/explorer_web/templates/block/index.html.eex:16
#: lib/explorer_web/templates/transaction/show.html.eex:61
msgid "Gas Price"
msgstr "Gas Price"
@ -167,7 +179,20 @@ msgid "Balance"
msgstr "Balance"
#: lib/explorer_web/templates/address/show.html.eex:11
#: lib/explorer_web/templates/page/index.html.eex:53
#: lib/explorer_web/templates/chain/show.html.eex:53
#: lib/explorer_web/templates/transaction/index.html.eex:25
#: lib/explorer_web/templates/transaction/show.html.eex:38
msgid "POA"
msgstr "POA"
#: lib/explorer_web/templates/block/index.html.eex:24
msgid "%{count} transactions"
msgstr "%{count} transactions"
#: lib/explorer_web/templates/block/index.html.eex:3
msgid "Showing #%{start_block} to #%{end_block}"
msgstr "Showing #%{start_block} to #%{end_block}"
#: lib/explorer_web/templates/transaction/index.html.eex:3
msgid "Showing %{count} Transactions"
msgstr "Showing %{count} Transactions"

@ -0,0 +1,14 @@
defmodule Explorer.Repo.Migrations.CreateBlockTransactions do
use Ecto.Migration
def change do
create table(:block_transactions, primary_key: false) do
add :block_id, references(:blocks)
add :transaction_id, references(:transactions), primary_key: true
timestamps null: false
end
create unique_index(:block_transactions, :transaction_id)
create unique_index(:block_transactions, [:block_id, :transaction_id])
end
end

@ -0,0 +1,9 @@
defmodule Explorer.Repo.Migrations.RemoveBlockIdFromTransactions do
use Ecto.Migration
def change do
alter table(:transactions) do
remove :block_id
end
end
end

@ -0,0 +1,17 @@
defmodule Explorer.BlockTransactionTest do
use Explorer.DataCase
alias Explorer.BlockTransaction
describe "changeset/2" do
test "with empty attributes" do
changeset = BlockTransaction.changeset(%BlockTransaction{}, %{})
refute(changeset.valid?)
end
test "with valid attributes" do
attrs = %{block_id: 4, transaction_id: 3}
changeset = BlockTransaction.changeset(%BlockTransaction{}, attrs)
assert(changeset.valid?)
end
end
end

@ -8,6 +8,7 @@ defmodule Explorer.FetcherTest do
alias Explorer.Address
alias Explorer.ToAddress
alias Explorer.FromAddress
alias Explorer.BlockTransaction
@raw_block %{
"difficulty" => "0xfffffffffffffffffffffffffffffffe",
@ -69,7 +70,6 @@ defmodule Explorer.FetcherTest do
standard_v: "0x11",
transaction_index: "0x12",
v: "0x13",
block_id: 100,
}
describe "fetch/1" do
@ -143,9 +143,12 @@ defmodule Explorer.FetcherTest do
describe "extract_transactions/2" do
test "that it creates a list of transactions" do
block = insert(:block, %{id: 100})
transactions = Fetcher.extract_transactions(block, [@raw_transaction])
assert List.first(transactions).block_id == 100
raw_transactions = [%{@raw_transaction | "hash" => "0xlimon"}, %{@raw_transaction | "hash" => "0xpepino"}]
block = insert(:block)
Fetcher.extract_transactions(block, raw_transactions)
transaction_hashes = Repo.all(from transaction in Transaction, select: transaction.hash)
assert(transaction_hashes == ["0xlimon", "0xpepino"])
end
end
@ -158,6 +161,41 @@ defmodule Explorer.FetcherTest do
assert last_transaction.hash == "0xab1"
end
test "that it creates a block transaction when there is a block" do
block = insert(:block)
transaction_attrs = %{@raw_transaction | "hash" => "0xab1"}
Fetcher.create_transaction(block, transaction_attrs)
transaction = Transaction |> Repo.get_by(hash: "0xab1")
block_transaction = BlockTransaction |> Repo.get_by(block_id: block.id, transaction_id: transaction.id)
assert block_transaction
end
test "that it updates the block transaction when it is called multiple times" do
first_block = insert(:block)
second_block = insert(:block)
transaction_attrs = %{@raw_transaction | "hash" => "0xsabzi"}
Fetcher.create_transaction(first_block, transaction_attrs)
transaction = Transaction |> Repo.get_by(hash: "0xsabzi")
block_transaction = BlockTransaction |> Repo.get_by(transaction_id: transaction.id)
assert block_transaction.block_id == first_block.id
Fetcher.create_transaction(second_block, transaction_attrs)
block_transaction = BlockTransaction |> Repo.get_by(transaction_id: transaction.id)
assert block_transaction.block_id == second_block.id
refute block_transaction.block_id == first_block.id
end
test "that it does not create a block transaction when there is no block" do
transaction_attrs = %{@raw_transaction | "hash" => "0xab1"}
Fetcher.create_transaction(nil, transaction_attrs)
transaction = Transaction |> Repo.get_by(hash: "0xab1")
block_transaction = BlockTransaction |> Repo.get_by(transaction_id: transaction.id)
refute block_transaction
end
test "that it creates a 'to address'" do
block = insert(:block)
transaction_attrs = %{@raw_transaction | "to" => "0xSmoothiesRGr8"}
@ -238,14 +276,14 @@ defmodule Explorer.FetcherTest do
end
end
describe "extract_transaction/2" do
describe "extract_transaction/1" do
test "that it extracts the transaction" do
assert Fetcher.extract_transaction(%{id: 100}, @raw_transaction) == @processed_transaction
assert Fetcher.extract_transaction(@raw_transaction) == @processed_transaction
end
test "when the transaction value is zero it returns a decimal" do
transaction = %{@raw_transaction | "value" => "0x0"}
assert Fetcher.extract_transaction(%{id: 100}, transaction).value == 0
assert Fetcher.extract_transaction(transaction).value == 0
end
end

@ -5,13 +5,13 @@ defmodule Explorer.BlockFormTest do
describe "build/1" do
test "that it has a number" do
block = insert(:block, number: 311)
insert_list(2, :transaction, block: block)
insert_list(2, :transaction) |> list_with_block(block)
assert BlockForm.build(block).number == 311
end
test "that it returns a count of transactions" do
block = insert(:block, number: 311)
insert_list(2, :transaction, block: block)
insert_list(2, :transaction) |> list_with_block(block)
assert BlockForm.build(block).transactions_count == 2
end

@ -11,31 +11,55 @@ defmodule Explorer.TransactionFormTest do
gas_used: 99523,
timestamp: Timex.parse!(date, "%b-%d-%Y %H:%M:%S %p %Z", :strftime),
})
transaction = insert(:transaction, block: block) |> with_addresses(%{to: "0xsleepypuppy", from: "0xilovefrogs"})
transaction =
insert(:transaction)
|> with_block(block)
|> with_addresses(%{to: "0xsleepypuppy", from: "0xilovefrogs"})
form = TransactionForm.build(transaction)
{:ok, %{form: form}}
end
test "that it has a block number", %{form: form} do
test "that it has a block number when it has a block", %{form: form} do
assert form.block_number == 1
end
test "that it returns the block's age" do
test "shows a blank block number when the transaction is pending" do
transaction = insert(:transaction) |> with_addresses
assert TransactionForm.build(transaction).block_number == ""
end
test "that it returns the block's age when has a block" do
block = insert(:block, %{
number: 1,
gas_used: 99523,
timestamp: Timex.now |> Timex.shift(hours: -2),
})
transaction = insert(:transaction, block: block) |> with_addresses(%{to: "0xsiskelnebert", from: "0xleonardmaltin"})
transaction = insert(:transaction) |> with_block(block) |> with_addresses(%{to: "0xsiskelnebert", from: "0xleonardmaltin"})
assert TransactionForm.build(transaction).age == "2 hours ago"
end
test "formats the block's timestamp", %{form: form} do
test "that it has an empty age when it is pending" do
transaction = insert(:transaction) |> with_addresses
assert TransactionForm.build(transaction).age == ""
end
test "formats the timestamp when it has a block", %{form: form} do
assert form.formatted_timestamp == "Feb-02-2010 10:48:56 AM Etc/UTC"
end
test "formats the timestamp when the transaction is pending" do
transaction = insert(:transaction) |> with_addresses
assert TransactionForm.build(transaction).formatted_timestamp == ""
end
test "that it returns the cumulative gas used for validating the block", %{form: form} do
assert form.cumulative_gas_used == 99523
assert form.cumulative_gas_used == "99,523"
end
test "shows the cumulative gas used for a pending transaction" do
transaction = insert(:transaction) |> with_addresses
assert TransactionForm.build(transaction).cumulative_gas_used == ""
end
test "that it returns a 'to address'", %{form: form} do
@ -49,13 +73,29 @@ defmodule Explorer.TransactionFormTest do
test "that it returns confirmations", %{form: form} do
assert form.confirmations == 23
end
test "shows confirmations when the transaction is pending" do
transaction = insert(:transaction) |> with_addresses
assert TransactionForm.build(transaction).confirmations == 0
end
end
describe "cumulative_gas_used/1" do
test "when there is a block" do
block = insert(:block, %{gas_used: 1_000})
assert TransactionForm.cumulative_gas_used(block) == "1,000"
end
test "when there is not a block" do
assert TransactionForm.cumulative_gas_used(nil) == ""
end
end
describe "confirmations/1" do
test "when there is only one block" do
block = insert(:block, %{number: 1})
transaction = insert(:transaction, %{block: block})
assert TransactionForm.confirmations(transaction) == 0
insert(:transaction) |> with_block(block) |> with_addresses
assert TransactionForm.confirmations(block) == 0
end
end
end

@ -0,0 +1,235 @@
defmodule Explorer.TransactionImporterTest do
use Explorer.DataCase
alias Explorer.Address
alias Explorer.BlockTransaction
alias Explorer.FromAddress
alias Explorer.ToAddress
alias Explorer.Transaction
alias Explorer.TransactionImporter
@raw_transaction %{
"creates" => nil,
"hash" => "pepino",
"value" => "0xde0b6b3a7640000",
"from" => "0x34d0ef2c",
"gas" => "0x21000",
"gasPrice" => "0x10000",
"input" => "0x5c8eff12",
"nonce" => "0x31337",
"publicKey" => "0xb39af9c",
"r" => "0x9",
"s" => "0x10",
"to" => "0x7a33b7d",
"standardV" => "0x11",
"transactionIndex" => "0x12",
"v" => "0x13",
}
@processed_transaction %{
hash: "pepino",
value: 1000000000000000000,
gas: 135168,
gas_price: 65536,
input: "0x5c8eff12",
nonce: 201527,
public_key: "0xb39af9c",
r: "0x9",
s: "0x10",
standard_v: "0x11",
transaction_index: "0x12",
v: "0x13",
}
describe "import/1" do
test "imports and saves a transaction to the database" do
use_cassette "transaction_importer_import_saves_the_transaction" do
TransactionImporter.import("0xdc3a0dfd0bbffd5eabbe40fb13afbe35ac5f5c030bff148f3e50afe32974b291")
transaction = Transaction |> order_by(desc: :inserted_at) |> Repo.one
assert transaction.hash == "0xdc3a0dfd0bbffd5eabbe40fb13afbe35ac5f5c030bff148f3e50afe32974b291"
end
end
test "when it has previously been saved it updates the transaction" do
use_cassette "transaction_importer_updates_the_association" do
insert(:transaction, hash: "0x170baac4eca26076953370dd603c68eab340c0135b19b585010d3158a5dbbf23", gas: 5)
TransactionImporter.import("0x170baac4eca26076953370dd603c68eab340c0135b19b585010d3158a5dbbf23")
transaction = Transaction |> order_by(desc: :inserted_at) |> Repo.one
assert transaction.gas == Decimal.new(231855)
end
end
test "when it has a block hash that's saved in the database it saves the association" do
use_cassette "transaction_importer_saves_the_association" do
block = insert(:block, hash: "0xfce13392435a8e7dab44c07d482212efb9dc39a9bea1915a9ead308b55a617f9")
TransactionImporter.import("0x64d851139325479c3bb7ccc6e6ab4cde5bc927dce6810190fe5d770a4c1ac333")
transaction = Transaction |> Repo.get_by(hash: "0x64d851139325479c3bb7ccc6e6ab4cde5bc927dce6810190fe5d770a4c1ac333")
block_transaction = BlockTransaction |> Repo.get_by(transaction_id: transaction.id)
assert block_transaction.block_id == block.id
end
end
test "when there is no block it does not save a block transaction" do
use_cassette "transaction_importer_txn_without_block" do
TransactionImporter.import("0xc6aa189827c14880f012a65292f7add7b5310094f8773a3d85b66303039b9dcf")
transaction = Transaction |> Repo.get_by(hash: "0xc6aa189827c14880f012a65292f7add7b5310094f8773a3d85b66303039b9dcf")
block_transaction = BlockTransaction |> Repo.get_by(transaction_id: transaction.id)
refute block_transaction
end
end
test "it creates a from address" do
use_cassette "transaction_importer_creates_a_from_address" do
TransactionImporter.import("0xc445f5410912458c480d992dd93355ae3dad64d9f65db25a3cf43a9c609a2e0d")
transaction = Transaction |> Repo.get_by(hash: "0xc445f5410912458c480d992dd93355ae3dad64d9f65db25a3cf43a9c609a2e0d")
address = Address |> Repo.get_by(hash: "0xa5b4b372112ab8dbbb48c8d0edd89227e24ec785")
from_address = FromAddress |> Repo.get_by(transaction_id: transaction.id, address_id: address.id)
assert from_address
end
end
test "it creates a to address" do
use_cassette "transaction_importer_creates_a_to_address" do
TransactionImporter.import("0xdc533d4227734a7cacd75a069e8dc57ac571b865ed97bae5ea4cb74b54145f4c")
transaction = Transaction |> Repo.get_by(hash: "0xdc533d4227734a7cacd75a069e8dc57ac571b865ed97bae5ea4cb74b54145f4c")
address = Address |> Repo.get_by(hash: "0x24e5b8528fe83257d5fe3497ef616026713347f8")
to_address = ToAddress |> Repo.get_by(transaction_id: transaction.id, address_id: address.id)
assert(to_address)
end
end
test "it creates a to address using creates when to is nil" do
use_cassette "transaction_importer_creates_a_to_address_from_creates" do
TransactionImporter.import("0xdc533d4227734a7cacd75a069e8dc57ac571b865ed97bae5ea4cb74b54145f4c")
transaction = Transaction |> Repo.get_by(hash: "0xdc533d4227734a7cacd75a069e8dc57ac571b865ed97bae5ea4cb74b54145f4c")
address = Address |> Repo.get_by(hash: "0x24e5b8528fe83257d5fe3497ef616026713347f8")
to_address = ToAddress |> Repo.get_by(transaction_id: transaction.id, address_id: address.id)
assert(to_address)
end
end
end
describe "download_transaction/1" do
test "downloads a transaction" do
use_cassette "transaction_importer_download_transaction" do
raw_transaction = TransactionImporter.download_transaction("0x170baac4eca26076953370dd603c68eab340c0135b19b585010d3158a5dbbf23")
assert(raw_transaction["from"] == "0xbe96ef1d056c97323e210fd0dd818aa027e57143")
end
end
test "when it has an invalid hash" do
use_cassette "transaction_importer_download_transaction_with_a_bad_hash" do
assert_raise MatchError, fn ->
TransactionImporter.download_transaction("0xdecafisbadzzzz")
end
end
end
end
describe "extract_attrs/1" do
test "returns a changeset-friendly list of transaction attributes" do
transaction_attrs = TransactionImporter.extract_attrs(@raw_transaction)
assert transaction_attrs == @processed_transaction
end
end
describe "create_block_transaction/2" do
test "inserts a block transaction" do
block = insert(:block)
transaction = insert(:transaction)
TransactionImporter.create_block_transaction(transaction, block.hash)
block_transaction =
BlockTransaction
|> Repo.get_by(transaction_id: transaction.id, block_id: block.id)
assert block_transaction
end
test "updates an already existing block transaction" do
block = insert(:block)
transaction = insert(:transaction)
the_seventies = Timex.parse!("1970-01-01T00:00:18-00:00", "{ISO:Extended}")
block_transaction = insert(:block_transaction, %{block_id: block.id, transaction_id: transaction.id, inserted_at: the_seventies, updated_at: the_seventies})
update_block = insert(:block)
TransactionImporter.create_block_transaction(transaction, update_block.hash)
updated_block_transaction =
BlockTransaction
|> Repo.get_by(transaction_id: transaction.id)
refute block_transaction.block_id == updated_block_transaction.block_id
refute block_transaction.updated_at == updated_block_transaction.updated_at
end
end
describe "create_from_address/2" do
test "that it creates a new address when one does not exist" do
transaction = insert(:transaction)
TransactionImporter.create_from_address(transaction, "0xbb8")
last_address = Address |> order_by(desc: :inserted_at) |> Repo.one
assert last_address.hash == "0xbb8"
end
test "that it joins transaction and from address" do
transaction = insert(:transaction)
TransactionImporter.create_from_address(transaction, "0xFreshPrince")
address = Address |> order_by(desc: :inserted_at) |> Repo.one
from_address = FromAddress |> order_by(desc: :inserted_at) |> Repo.one
assert from_address.transaction_id == transaction.id
assert from_address.address_id == address.id
end
test "when the address already exists it does not insert a new address" do
transaction = insert(:transaction)
insert(:address, hash: "0xbb8")
TransactionImporter.create_from_address(transaction, "0xbb8")
assert Address |> Repo.all |> length == 1
end
end
describe "create_to_address/2" do
test "that it creates a new address when one does not exist" do
transaction = insert(:transaction)
TransactionImporter.create_to_address(transaction, "0xFreshPrince")
last_address = Address |> order_by(desc: :inserted_at) |> Repo.one
assert last_address.hash == "0xfreshprince"
end
test "that it joins transaction and address" do
transaction = insert(:transaction)
TransactionImporter.create_to_address(transaction, "0xFreshPrince")
address = Address |> order_by(desc: :inserted_at) |> Repo.one
to_address = ToAddress |> order_by(desc: :inserted_at) |> Repo.one
assert to_address.transaction_id == transaction.id
assert to_address.address_id == address.id
end
test "when the address already exists it does not insert a new address" do
transaction = insert(:transaction)
insert(:address, hash: "bigmouthbillybass")
TransactionImporter.create_to_address(transaction, "bigmouthbillybass")
assert Address |> Repo.all |> length == 1
end
end
describe "decode_integer_field/1" do
test "returns the integer value of a hex value" do
assert(TransactionImporter.decode_integer_field("0x7f2fb") == 520955)
end
end
end

@ -5,17 +5,10 @@ defmodule Explorer.TransactionTest do
describe "changeset/2" do
test "with valid attributes" do
block = insert(:block)
changeset = Transaction.changeset(%Transaction{}, %{hash: "0x0", block_id: block.id, value: 1, gas: 21000, gas_price: 10000, input: "0x5c8eff12", nonce: "31337", public_key: "0xb39af9c", r: "0x9", s: "0x10", standard_v: "0x11", transaction_index: "0x12", v: "0x13"})
changeset = Transaction.changeset(%Transaction{}, %{hash: "0x0", value: 1, gas: 21000, gas_price: 10000, input: "0x5c8eff12", nonce: "31337", public_key: "0xb39af9c", r: "0x9", s: "0x10", standard_v: "0x11", transaction_index: "0x12", v: "0x13"})
assert changeset.valid?
end
test "with a block that does not exist in the database" do
{:error, changeset} = Transaction.changeset(%Transaction{}, %{hash: "0x0", block_id: 0, value: 1, gas: 21000, gas_price: 10000, input: "0x5c8eff12", nonce: "31337", public_key: "0xb39af9c", r: "0x9", s: "0x10", standard_v: "0x11", transaction_index: "0x12", v: "0x13"}) |> Repo.insert
refute changeset.valid?
assert [block_id: {"does not exist", []}] = changeset.errors
end
test "with invalid attributes" do
changeset = Transaction.changeset(%Transaction{}, %{racecar: "yellow ham"})
refute changeset.valid?

@ -1,15 +1,6 @@
defmodule ExplorerWeb.ChainControllerTest do
use ExplorerWeb.ConnCase
def build_transaction(block \\ nil) do
block = block || insert(:block)
transaction = insert(:transaction, block: block)
to_address = insert(:address)
from_address = insert(:address)
insert(:to_address, transaction: transaction, address: to_address)
insert(:from_address, transaction: transaction, address: from_address)
end
describe "GET index/2 without a locale" do
test "redirects to the en locale", %{conn: conn} do
conn = get conn, "/"
@ -39,25 +30,12 @@ defmodule ExplorerWeb.ChainControllerTest do
test "returns a transaction", %{conn: conn} do
block = insert(:block, number: 33)
insert(:transaction, hash: "0xDECAFBAD", block: block) |> with_addresses(%{to: "0xsleepypuppy", from: "0xilovefrogs"})
insert(:transaction, hash: "0xDECAFBAD") |> with_block(block) |> with_addresses(%{to: "0xsleepypuppy", from: "0xilovefrogs"})
conn = get conn, "/en"
assert(List.first(conn.assigns.transactions).hash == "0xDECAFBAD")
assert(List.first(conn.assigns.transactions).block.number == 33)
end
test "returns only the five most recent transactions", %{conn: conn} do
block_mined_today = insert(:block, number: 2)
insert(:transaction, hash: "0xStuff", block: block_mined_today) |> with_addresses
block_mined_last_week = insert(:block, number: 1)
for _ <- 0..4, do: insert(:transaction, %{block: block_mined_last_week}) |> with_addresses
conn = get conn, "/en"
assert Enum.count(conn.assigns.transactions) == 5
assert List.first(conn.assigns.transactions).hash == "0xStuff"
assert(List.first(conn.assigns.transactions).block_number == 33)
end
end
end

@ -1,19 +1,28 @@
defmodule ExplorerWeb.TransactionControllerTest do
use ExplorerWeb.ConnCase
describe "GET index/2" do
test "returns all transactions", %{conn: conn} do
transaction_ids = insert_list(4, :transaction) |> list_with_block |> Enum.map(fn (transaction) -> transaction.id end)
conn = get(conn, "/en/transactions")
assert conn.assigns.transactions |> Enum.map(fn (transaction) -> transaction.id end) == transaction_ids
end
end
describe "GET show/3" do
test "returns a transaction", %{conn: conn} do
transaction = insert(:transaction, hash: "0x8") |> with_addresses
test "when there is an associated block, it returns a transaction with block data", %{conn: conn} do
block = insert(:block, %{number: 777})
transaction = insert(:transaction, hash: "0x8") |> with_block(block) |> with_addresses
conn = get(conn, "/en/transactions/0x8")
assert conn.assigns.transaction.id == transaction.id
assert conn.assigns.transaction.block_number == block.number
end
end
describe "GET index/2" do
test "returns all blocks", %{conn: conn} do
transaction_ids = insert_list(4, :transaction) |> Enum.map(fn (transaction) -> transaction.id end)
conn = get(conn, "/en/transactions")
assert conn.assigns.transactions |> Enum.reverse |> Enum.map(fn (transaction) -> transaction.id end) == transaction_ids
test "returns a transaction without associated block data", %{conn: conn} do
transaction = insert(:transaction, hash: "0x8") |> with_addresses
conn = get(conn, "/en/transactions/0x8")
assert conn.assigns.transaction.id == transaction.id
assert conn.assigns.transaction.block_number == ""
end
end
end

@ -27,7 +27,7 @@ defmodule ExplorerWeb.UserListTest do
gas_used: 1010101,
gas_limit: 5030101
})
for _ <- 0..2, do: insert(:transaction, %{block: fifth_block}) |> with_addresses
for _ <- 0..2, do: insert(:transaction) |> with_block(fifth_block) |> with_addresses
session
|> visit("/en")
@ -56,7 +56,7 @@ defmodule ExplorerWeb.UserListTest do
timestamp: Timex.now |> Timex.shift(hours: -2),
gas_used: 123987,
})
for _ <- 0..3, do: insert(:transaction, %{block: block}) |> with_addresses
for _ <- 0..3, do: insert(:transaction) |> with_block(block) |> with_addresses
insert(:transaction, %{
hash: "0xSk8",
@ -65,8 +65,8 @@ defmodule ExplorerWeb.UserListTest do
gas_price: 7890000000898912300045,
input: "0x00012",
nonce: 99045,
block: block,
})
|> with_block(block)
|> with_addresses(%{to: "0xabelincoln", from: "0xhowardtaft"})
session

@ -0,0 +1,9 @@
defmodule Explorer.BlockTransactionFactory do
defmacro __using__(_opts) do
quote do
def block_transaction_factory do
%Explorer.BlockTransaction{}
end
end
end
end

@ -1,9 +1,12 @@
defmodule Explorer.TransactionFactory do
defmacro __using__(_opts) do
quote do
alias Explorer.Address
alias Explorer.BlockTransaction
alias Explorer.Repo
def transaction_factory do
%Explorer.Transaction{
block: build(:block),
hash: sequence("0x"),
value: Enum.random(1..100_000),
gas: Enum.random(21_000..100_000),
@ -20,12 +23,24 @@ defmodule Explorer.TransactionFactory do
end
def with_addresses(transaction, %{to: to, from: from} \\ %{to: nil, from: nil}) do
to_address = if to, do: Explorer.Repo.get_by(Explorer.Address, %{hash: to}) || insert(:address, hash: to), else: insert(:address)
from_address = if from, do: Explorer.Repo.get_by(Explorer.Address, %{hash: from}) ||insert(:address, hash: from), else: insert(:address)
to_address = if to, do: Repo.get_by(Address, %{hash: to}) || insert(:address, hash: to), else: insert(:address)
from_address = if from, do: Repo.get_by(Address, %{hash: from}) ||insert(:address, hash: from), else: insert(:address)
insert(:to_address, %{transaction_id: transaction.id, address_id: to_address.id})
insert(:from_address, %{transaction_id: transaction.id, address_id: from_address.id})
transaction
end
def with_block(transaction, block \\ nil) do
block = block || insert(:block)
insert(:block_transaction, %{block_id: block.id, transaction_id: transaction.id})
# block_transaction_changeset = BlockTransaction.changeset(%BlockTransaction{}, %{block_id: block.id, transaction_id: transaction.id})
# Repo.insert(block_transaction_changeset)
transaction
end
def list_with_block(transactions, block \\ nil) do
Enum.map(transactions, fn(transaction) -> with_block(transaction, block) end)
end
end
end
end

@ -3,6 +3,7 @@ defmodule Explorer.Factory do
use ExMachina.Ecto, repo: Explorer.Repo
use Explorer.BlockFactory
use Explorer.TransactionFactory
use Explorer.BlockTransactionFactory
use Explorer.AddressFactory
use Explorer.ToAddressFactory
use Explorer.FromAddressFactory

@ -0,0 +1,30 @@
[
{
"request": {
"body": "{\"params\":[\"0xc445f5410912458c480d992dd93355ae3dad64d9f65db25a3cf43a9c609a2e0d\"],\"method\":\"eth_getTransactionByHash\",\"jsonrpc\":\"2.0\",\"id\":2}",
"headers": {
"Content-Type": "application/json"
},
"method": "post",
"options": [],
"request_body": "",
"url": "https://sokol.poa.network:443"
},
"response": {
"binary": false,
"body": "{\"jsonrpc\":\"2.0\",\"result\":{\"blockHash\":\"0x30996f4f3e53a2b22766f535877b6840b08518027268b3385e46dbcd4ebe633d\",\"blockNumber\":\"0xc197a\",\"chainId\":null,\"condition\":null,\"creates\":\"0x60d5233e8a1798c7b7a8a1f9083ae31f770073d7\",\"from\":\"0xa5b4b372112ab8dbbb48c8d0edd89227e24ec785\",\"gas\":\"0x3782f\",\"gasPrice\":\"0x3b9aca00\",\"hash\":\"0xc445f5410912458c480d992dd93355ae3dad64d9f65db25a3cf43a9c609a2e0d\",\"input\":\"0x6060604052341561000f57600080fd5b7fb94ae47ec9f4248692e2ecf9740b67ab493f3dcc8452bedc7d9cd911c28d1ca5426040518082815260200191505060405180910390a1609e806100546000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063557ed1ba146044575b600080fd5b3415604e57600080fd5b6054606a565b6040518082815260200191505060405180910390f35b6000429050905600a165627a7a7230582053883c0c39da080adc15a91094921659c200b3bb60aed9e49b79b0274da3f4010029\",\"nonce\":\"0xa3cd\",\"publicKey\":\"0x3366f04816d42836375b8f28d5b0d341f8a47fb46a59a754ca924c7397d335a7b89a0f94f7c4d36f29ae6f6acdd3f2c0bdf12d9314799c407cf5b6bc4b370d4f\",\"r\":\"0xbfabcb7ca06c8b1f78cd4a2e70ae645bea6e5b512febbb93663d152541e26923\",\"raw\":\"0xf9014582a3cd843b9aca008303782f8080b8f26060604052341561000f57600080fd5b7fb94ae47ec9f4248692e2ecf9740b67ab493f3dcc8452bedc7d9cd911c28d1ca5426040518082815260200191505060405180910390a1609e806100546000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063557ed1ba146044575b600080fd5b3415604e57600080fd5b6054606a565b6040518082815260200191505060405180910390f35b6000429050905600a165627a7a7230582053883c0c39da080adc15a91094921659c200b3bb60aed9e49b79b0274da3f40100291ba0bfabcb7ca06c8b1f78cd4a2e70ae645bea6e5b512febbb93663d152541e26923a035bb5cf4b0c14240954bc73254cd761a964f7f8ceb45a79fb2a7464fd16383a1\",\"s\":\"0x35bb5cf4b0c14240954bc73254cd761a964f7f8ceb45a79fb2a7464fd16383a1\",\"standardV\":\"0x0\",\"to\":null,\"transactionIndex\":\"0x5\",\"v\":\"0x1b\",\"value\":\"0x0\"},\"id\":2}\n",
"headers": {
"Date": "Tue, 06 Feb 2018 03:33:25 GMT",
"Content-Type": "application/json",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Set-Cookie": "__cfduid=d291677b65b9ebf5fbc09dec36364c58f1517888004; expires=Wed, 06-Feb-19 03:33:24 GMT; path=/; domain=.poa.network; HttpOnly; Secure",
"Expect-CT": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
"Server": "cloudflare",
"CF-RAY": "3e8b0c3ebff39607-SJC"
},
"status_code": 200,
"type": "ok"
}
}
]

@ -0,0 +1,30 @@
[
{
"request": {
"body": "{\"params\":[\"0xdc533d4227734a7cacd75a069e8dc57ac571b865ed97bae5ea4cb74b54145f4c\"],\"method\":\"eth_getTransactionByHash\",\"jsonrpc\":\"2.0\",\"id\":5}",
"headers": {
"Content-Type": "application/json"
},
"method": "post",
"options": [],
"request_body": "",
"url": "https://sokol.poa.network:443"
},
"response": {
"binary": false,
"body": "{\"jsonrpc\":\"2.0\",\"result\":{\"blockHash\":\"0x30996f4f3e53a2b22766f535877b6840b08518027268b3385e46dbcd4ebe633d\",\"blockNumber\":\"0xc197a\",\"chainId\":null,\"condition\":null,\"creates\":null,\"from\":\"0xb2867180771b196518651c174c9240d5e8bd0ecd\",\"gas\":\"0x3755b\",\"gasPrice\":\"0x3b9aca00\",\"hash\":\"0xdc533d4227734a7cacd75a069e8dc57ac571b865ed97bae5ea4cb74b54145f4c\",\"input\":\"0x6060604052341561000f57600080fd5b7fb94ae47ec9f4248692e2ecf9740b67ab493f3dcc8452bedc7d9cd911c28d1ca5426040518082815260200191505060405180910390a1609e806100546000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063557ed1ba146044575b600080fd5b3415604e57600080fd5b6054606a565b6040518082815260200191505060405180910390f35b6000429050905600a165627a7a7230582053883c0c39da080adc15a91094921659c200b3bb60aed9e49b79b0274da3f4010029\",\"nonce\":\"0xa4e9\",\"publicKey\":\"0xbf0cf158b32b838553af2c4f9e3393e6fb4cb0a97a7e4025d3fe3a552e3cfa720779da708ec4a5a89c9a6ca7f16d1b49605a9b8bdb28bd2a45818418743d153c\",\"r\":\"0xb40a4357f5b6316df0bd0f054a94c09b443fc16ebed9c9c95932c460776dc7bf\",\"raw\":\"0xf9014582a4e9843b9aca008303755b8080b8f26060604052341561000f57600080fd5b7fb94ae47ec9f4248692e2ecf9740b67ab493f3dcc8452bedc7d9cd911c28d1ca5426040518082815260200191505060405180910390a1609e806100546000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063557ed1ba146044575b600080fd5b3415604e57600080fd5b6054606a565b6040518082815260200191505060405180910390f35b6000429050905600a165627a7a7230582053883c0c39da080adc15a91094921659c200b3bb60aed9e49b79b0274da3f40100291ba0b40a4357f5b6316df0bd0f054a94c09b443fc16ebed9c9c95932c460776dc7bfa01672c0bcc52ae7348a226ab8232118f6a74197c99ec715d7186c16b0837766bf\",\"s\":\"0x1672c0bcc52ae7348a226ab8232118f6a74197c99ec715d7186c16b0837766bf\",\"standardV\":\"0x0\",\"to\":\"0x24e5b8528fe83257d5fe3497ef616026713347f8\",\"transactionIndex\":\"0x2\",\"v\":\"0x1b\",\"value\":\"0x0\"},\"id\":5}\n",
"headers": {
"Date": "Tue, 06 Feb 2018 03:33:26 GMT",
"Content-Type": "application/json",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Set-Cookie": "__cfduid=d9137691f355994dc6bb3a8c2e4033e621517888006; expires=Wed, 06-Feb-19 03:33:26 GMT; path=/; domain=.poa.network; HttpOnly; Secure",
"Expect-CT": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
"Server": "cloudflare",
"CF-RAY": "3e8b0c46aac89607-SJC"
},
"status_code": 200,
"type": "ok"
}
}
]

@ -0,0 +1,30 @@
[
{
"request": {
"body": "{\"params\":[\"0xdc533d4227734a7cacd75a069e8dc57ac571b865ed97bae5ea4cb74b54145f4c\"],\"method\":\"eth_getTransactionByHash\",\"jsonrpc\":\"2.0\",\"id\":5}",
"headers": {
"Content-Type": "application/json"
},
"method": "post",
"options": [],
"request_body": "",
"url": "https://sokol.poa.network:443"
},
"response": {
"binary": false,
"body": "{\"jsonrpc\":\"2.0\",\"result\":{\"blockHash\":\"0x30996f4f3e53a2b22766f535877b6840b08518027268b3385e46dbcd4ebe633d\",\"blockNumber\":\"0xc197a\",\"chainId\":null,\"condition\":null,\"creates\":\"0x24e5b8528fe83257d5fe3497ef616026713347f8\",\"from\":\"0xb2867180771b196518651c174c9240d5e8bd0ecd\",\"gas\":\"0x3755b\",\"gasPrice\":\"0x3b9aca00\",\"hash\":\"0xdc533d4227734a7cacd75a069e8dc57ac571b865ed97bae5ea4cb74b54145f4c\",\"input\":\"0x6060604052341561000f57600080fd5b7fb94ae47ec9f4248692e2ecf9740b67ab493f3dcc8452bedc7d9cd911c28d1ca5426040518082815260200191505060405180910390a1609e806100546000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063557ed1ba146044575b600080fd5b3415604e57600080fd5b6054606a565b6040518082815260200191505060405180910390f35b6000429050905600a165627a7a7230582053883c0c39da080adc15a91094921659c200b3bb60aed9e49b79b0274da3f4010029\",\"nonce\":\"0xa4e9\",\"publicKey\":\"0xbf0cf158b32b838553af2c4f9e3393e6fb4cb0a97a7e4025d3fe3a552e3cfa720779da708ec4a5a89c9a6ca7f16d1b49605a9b8bdb28bd2a45818418743d153c\",\"r\":\"0xb40a4357f5b6316df0bd0f054a94c09b443fc16ebed9c9c95932c460776dc7bf\",\"raw\":\"0xf9014582a4e9843b9aca008303755b8080b8f26060604052341561000f57600080fd5b7fb94ae47ec9f4248692e2ecf9740b67ab493f3dcc8452bedc7d9cd911c28d1ca5426040518082815260200191505060405180910390a1609e806100546000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063557ed1ba146044575b600080fd5b3415604e57600080fd5b6054606a565b6040518082815260200191505060405180910390f35b6000429050905600a165627a7a7230582053883c0c39da080adc15a91094921659c200b3bb60aed9e49b79b0274da3f40100291ba0b40a4357f5b6316df0bd0f054a94c09b443fc16ebed9c9c95932c460776dc7bfa01672c0bcc52ae7348a226ab8232118f6a74197c99ec715d7186c16b0837766bf\",\"s\":\"0x1672c0bcc52ae7348a226ab8232118f6a74197c99ec715d7186c16b0837766bf\",\"standardV\":\"0x0\",\"to\":null,\"transactionIndex\":\"0x2\",\"v\":\"0x1b\",\"value\":\"0x0\"},\"id\":5}\n",
"headers": {
"Date": "Tue, 06 Feb 2018 03:33:26 GMT",
"Content-Type": "application/json",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Set-Cookie": "__cfduid=d9137691f355994dc6bb3a8c2e4033e621517888006; expires=Wed, 06-Feb-19 03:33:26 GMT; path=/; domain=.poa.network; HttpOnly; Secure",
"Expect-CT": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
"Server": "cloudflare",
"CF-RAY": "3e8b0c46aac89607-SJC"
},
"status_code": 200,
"type": "ok"
}
}
]

@ -0,0 +1,30 @@
[
{
"request": {
"body": "{\"params\":[\"0x170baac4eca26076953370dd603c68eab340c0135b19b585010d3158a5dbbf23\"],\"method\":\"eth_getTransactionByHash\",\"jsonrpc\":\"2.0\",\"id\":0}",
"headers": {
"Content-Type": "application/json"
},
"method": "post",
"options": [],
"request_body": "",
"url": "https://sokol.poa.network:443"
},
"response": {
"binary": false,
"body": "{\"jsonrpc\":\"2.0\",\"result\":{\"blockHash\":\"0x8663df28453934be1e0fc59995d8b5295e83e4db689ade8b0244525f8f7c118a\",\"blockNumber\":\"0xc10ab\",\"chainId\":null,\"condition\":null,\"creates\":\"0xac4ff5b5c29338d0046e40f22dbec4d9ef32ed11\",\"from\":\"0xbe96ef1d056c97323e210fd0dd818aa027e57143\",\"gas\":\"0x389af\",\"gasPrice\":\"0x77359400\",\"hash\":\"0x170baac4eca26076953370dd603c68eab340c0135b19b585010d3158a5dbbf23\",\"input\":\"0x6060604052341561000f57600080fd5b7fb94ae47ec9f4248692e2ecf9740b67ab493f3dcc8452bedc7d9cd911c28d1ca5426040518082815260200191505060405180910390a1609e806100546000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063557ed1ba146044575b600080fd5b3415604e57600080fd5b6054606a565b6040518082815260200191505060405180910390f35b6000429050905600a165627a7a7230582053883c0c39da080adc15a91094921659c200b3bb60aed9e49b79b0274da3f4010029\",\"nonce\":\"0x9601\",\"publicKey\":\"0x565e1e48534a6764a50baead6ec60f573d3294cab28b766c928fd6eb8b9c89268bf3452b57bbe8d0c699ac8ed9227344ee72e42f41577fb51777d66520ccdc9c\",\"r\":\"0x81c2771372d8e71d4569bbb0a830f5bb6cdba285178f68e0917e65a682a1cd46\",\"raw\":\"0xf901458296018477359400830389af8080b8f26060604052341561000f57600080fd5b7fb94ae47ec9f4248692e2ecf9740b67ab493f3dcc8452bedc7d9cd911c28d1ca5426040518082815260200191505060405180910390a1609e806100546000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063557ed1ba146044575b600080fd5b3415604e57600080fd5b6054606a565b6040518082815260200191505060405180910390f35b6000429050905600a165627a7a7230582053883c0c39da080adc15a91094921659c200b3bb60aed9e49b79b0274da3f40100291ba081c2771372d8e71d4569bbb0a830f5bb6cdba285178f68e0917e65a682a1cd46a00a1718c45816d32ddbe5efcbe2e41cffe537bc703d80b9632b75ee5a9d445dcd\",\"s\":\"0xa1718c45816d32ddbe5efcbe2e41cffe537bc703d80b9632b75ee5a9d445dcd\",\"standardV\":\"0x0\",\"to\":null,\"transactionIndex\":\"0x11\",\"v\":\"0x1b\",\"value\":\"0x0\"},\"id\":0}\n",
"headers": {
"Date": "Tue, 06 Feb 2018 03:37:56 GMT",
"Content-Type": "application/json",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Set-Cookie": "__cfduid=d5ef068dc553a6d30310731eac55ffcf11517888276; expires=Wed, 06-Feb-19 03:37:56 GMT; path=/; domain=.poa.network; HttpOnly; Secure",
"Expect-CT": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
"Server": "cloudflare",
"CF-RAY": "3e8b12de6e6992b8-SJC"
},
"status_code": 200,
"type": "ok"
}
}
]

@ -0,0 +1,30 @@
[
{
"request": {
"body": "{\"params\":[\"0xdecafisbadzzzz\"],\"method\":\"eth_getTransactionByHash\",\"jsonrpc\":\"2.0\",\"id\":0}",
"headers": {
"Content-Type": "application/json"
},
"method": "post",
"options": [],
"request_body": "",
"url": "https://sokol.poa.network:443"
},
"response": {
"binary": false,
"body": "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32602,\"message\":\"Invalid params: invalid length 14, expected a 0x-prefixed, padded, hex-encoded hash with length 64.\"},\"id\":0}\n",
"headers": {
"Date": "Tue, 06 Feb 2018 03:36:54 GMT",
"Content-Type": "application/json",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Set-Cookie": "__cfduid=d53dce2a5d0bec9953b3957e3b0384b2d1517888214; expires=Wed, 06-Feb-19 03:36:54 GMT; path=/; domain=.poa.network; HttpOnly; Secure",
"Expect-CT": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
"Server": "cloudflare",
"CF-RAY": "3e8b115c59f89342-SJC"
},
"status_code": 200,
"type": "ok"
}
}
]

@ -0,0 +1,30 @@
[
{
"request": {
"body": "{\"params\":[\"0xdc3a0dfd0bbffd5eabbe40fb13afbe35ac5f5c030bff148f3e50afe32974b291\"],\"method\":\"eth_getTransactionByHash\",\"jsonrpc\":\"2.0\",\"id\":5}",
"headers": {
"Content-Type": "application/json"
},
"method": "post",
"options": [],
"request_body": "",
"url": "https://sokol.poa.network:443"
},
"response": {
"binary": false,
"body": "{\"jsonrpc\":\"2.0\",\"result\":{\"blockHash\":\"0x8663df28453934be1e0fc59995d8b5295e83e4db689ade8b0244525f8f7c118a\",\"blockNumber\":\"0xc10ab\",\"chainId\":null,\"condition\":null,\"creates\":\"0x353fe3ffbf77edef7f9c352c47965a38c07e837c\",\"from\":\"0x8a35723e64a47764b9acfec5e647b39a4e5d635c\",\"gas\":\"0x381ae\",\"gasPrice\":\"0x77359400\",\"hash\":\"0xdc3a0dfd0bbffd5eabbe40fb13afbe35ac5f5c030bff148f3e50afe32974b291\",\"input\":\"0x6060604052341561000f57600080fd5b7fb94ae47ec9f4248692e2ecf9740b67ab493f3dcc8452bedc7d9cd911c28d1ca5426040518082815260200191505060405180910390a1609e806100546000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063557ed1ba146044575b600080fd5b3415604e57600080fd5b6054606a565b6040518082815260200191505060405180910390f35b6000429050905600a165627a7a7230582053883c0c39da080adc15a91094921659c200b3bb60aed9e49b79b0274da3f4010029\",\"nonce\":\"0x9b62\",\"publicKey\":\"0xbd2c35eb20bfab52e22b8b9fbcfc3f5f8a927f7d6b800960026921929eeb0976a304639c785ce1a509900922d6ef8fd1222b7b48cdcb38c97b49c0f37c59c0f7\",\"r\":\"0x380bb4c084a241ffbf69ad1f52cd8689aeb986db451bf85d715b4d9afdd89b0d\",\"raw\":\"0xf90145829b628477359400830381ae8080b8f26060604052341561000f57600080fd5b7fb94ae47ec9f4248692e2ecf9740b67ab493f3dcc8452bedc7d9cd911c28d1ca5426040518082815260200191505060405180910390a1609e806100546000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063557ed1ba146044575b600080fd5b3415604e57600080fd5b6054606a565b6040518082815260200191505060405180910390f35b6000429050905600a165627a7a7230582053883c0c39da080adc15a91094921659c200b3bb60aed9e49b79b0274da3f40100291ba0380bb4c084a241ffbf69ad1f52cd8689aeb986db451bf85d715b4d9afdd89b0da01b1b1cca94b24cabba08bcc5d4fb99f2fdcb4f1f76d80091c061771040af3432\",\"s\":\"0x1b1b1cca94b24cabba08bcc5d4fb99f2fdcb4f1f76d80091c061771040af3432\",\"standardV\":\"0x0\",\"to\":null,\"transactionIndex\":\"0x0\",\"v\":\"0x1b\",\"value\":\"0x0\"},\"id\":5}\n",
"headers": {
"Date": "Tue, 06 Feb 2018 03:41:44 GMT",
"Content-Type": "application/json",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Set-Cookie": "__cfduid=db1f077d751ae0ba2508cbbe43d8047de1517888504; expires=Wed, 06-Feb-19 03:41:44 GMT; path=/; domain=.poa.network; HttpOnly; Secure",
"Expect-CT": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
"Server": "cloudflare",
"CF-RAY": "3e8b1871fa3d6d42-SJC"
},
"status_code": 200,
"type": "ok"
}
}
]

@ -0,0 +1,30 @@
[
{
"request": {
"body": "{\"params\":[\"0x64d851139325479c3bb7ccc6e6ab4cde5bc927dce6810190fe5d770a4c1ac333\"],\"method\":\"eth_getTransactionByHash\",\"jsonrpc\":\"2.0\",\"id\":1}",
"headers": {
"Content-Type": "application/json"
},
"method": "post",
"options": [],
"request_body": "",
"url": "https://sokol.poa.network:443"
},
"response": {
"binary": false,
"body": "{\"jsonrpc\":\"2.0\",\"result\":{\"blockHash\":\"0xfce13392435a8e7dab44c07d482212efb9dc39a9bea1915a9ead308b55a617f9\",\"blockNumber\":\"0xc10d9\",\"chainId\":\"0x4d\",\"condition\":null,\"creates\":null,\"from\":\"0x82e4e61e7f5139ff0a4157a5bc687ef42294c248\",\"gas\":\"0x5208\",\"gasPrice\":\"0x3b9aca00\",\"hash\":\"0x64d851139325479c3bb7ccc6e6ab4cde5bc927dce6810190fe5d770a4c1ac333\",\"input\":\"0x\",\"nonce\":\"0x23c\",\"publicKey\":\"0x750f765a7790aa361dde0ff1d4c9dadd0e1c62fe79dee9c3d6b953abe99ce79755568215a2524d0efe0d5a48d8082e86f317434b62964b0c2e3e3446ebe08099\",\"r\":\"0xb5c079b9b6b131c1f726dc90f829a9dedf7e4d72a787ff90224c630104768afb\",\"raw\":\"0xf86f82023c843b9aca008252089496604b744e9c5a72680d33e7faf9629e19c97eaa8902a18aeae7e44a70008081bea0b5c079b9b6b131c1f726dc90f829a9dedf7e4d72a787ff90224c630104768afba0609d0d6ab60888059000f1c8b3d75c7193462c3dac83f91cf378ad5c5242ec1b\",\"s\":\"0x609d0d6ab60888059000f1c8b3d75c7193462c3dac83f91cf378ad5c5242ec1b\",\"standardV\":\"0x1\",\"to\":\"0x96604b744e9c5a72680d33e7faf9629e19c97eaa\",\"transactionIndex\":\"0x9\",\"v\":\"0xbe\",\"value\":\"0x2a18aeae7e44a7000\"},\"id\":1}\n",
"headers": {
"Date": "Tue, 06 Feb 2018 03:41:43 GMT",
"Content-Type": "application/json",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Set-Cookie": "__cfduid=df89a2810de64c37a8a65bfffe6c4a1b41517888503; expires=Wed, 06-Feb-19 03:41:43 GMT; path=/; domain=.poa.network; HttpOnly; Secure",
"Expect-CT": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
"Server": "cloudflare",
"CF-RAY": "3e8b18694f146d42-SJC"
},
"status_code": 200,
"type": "ok"
}
}
]

@ -0,0 +1,30 @@
[
{
"request": {
"body": "{\"params\":[\"0xc6aa189827c14880f012a65292f7add7b5310094f8773a3d85b66303039b9dcf\"],\"method\":\"eth_getTransactionByHash\",\"jsonrpc\":\"2.0\",\"id\":0}",
"headers": {
"Content-Type": "application/json"
},
"method": "post",
"options": [],
"request_body": "",
"url": "https://sokol.poa.network:443"
},
"response": {
"binary": false,
"body": "{\"jsonrpc\":\"2.0\",\"result\":{\"blockHash\":\"null\",\"blockNumber\":\"0xc13ac\",\"chainId\":null,\"condition\":null,\"creates\":\"0xee0ea6a585b7002840cb1aab374f9ea159772196\",\"from\":\"0x23359b2330a82cca0618ffbc84cde3b760e69443\",\"gas\":\"0x3683b\",\"gasPrice\":\"0x12a05f200\",\"hash\":\"0xc6aa189827c14880f012a65292f7add7b5310094f8773a3d85b66303039b9dcf\",\"input\":\"0x6060604052341561000f57600080fd5b7fb94ae47ec9f4248692e2ecf9740b67ab493f3dcc8452bedc7d9cd911c28d1ca5426040518082815260200191505060405180910390a1609e806100546000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063557ed1ba146044575b600080fd5b3415604e57600080fd5b6054606a565b6040518082815260200191505060405180910390f35b6000429050905600a165627a7a7230582053883c0c39da080adc15a91094921659c200b3bb60aed9e49b79b0274da3f4010029\",\"nonce\":\"0x963d\",\"publicKey\":\"0x86189842eca4e1195fe49edf3c14438e3fcc1f8d9672f7cc943eee2b5f3143058dc79769a0d5b279a26169a37274eb05d5fe9e303dac3f25873a45cc13cc08a5\",\"r\":\"0x4a6668eea531cfefafc7299d83dbc975752d068b4afcff77a17de9faa6a92dd7\",\"raw\":\"0xf9014582963d85012a05f2008303683b8080b8f26060604052341561000f57600080fd5b7fb94ae47ec9f4248692e2ecf9740b67ab493f3dcc8452bedc7d9cd911c28d1ca5426040518082815260200191505060405180910390a1609e806100546000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063557ed1ba146044575b600080fd5b3415604e57600080fd5b6054606a565b6040518082815260200191505060405180910390f35b6000429050905600a165627a7a7230582053883c0c39da080adc15a91094921659c200b3bb60aed9e49b79b0274da3f40100291ba04a6668eea531cfefafc7299d83dbc975752d068b4afcff77a17de9faa6a92dd79fcdf765f678470f08279278653caa4cbf55c42c570b996f2fb037b815111d36\",\"s\":\"0xcdf765f678470f08279278653caa4cbf55c42c570b996f2fb037b815111d36\",\"standardV\":\"0x0\",\"to\":null,\"transactionIndex\":\"0x5\",\"v\":\"0x1b\",\"value\":\"0x0\"},\"id\":0}\n",
"headers": {
"Date": "Tue, 06 Feb 2018 01:25:56 GMT",
"Content-Type": "application/json",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Set-Cookie": "__cfduid=d01ad5566804036879ac82a9f9bd4bf1f1517880356; expires=Wed, 06-Feb-19 01:25:56 GMT; path=/; domain=.poa.network; HttpOnly; Secure",
"Expect-CT": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
"Server": "cloudflare",
"CF-RAY": "3e8a5183b8bf9607-SJC"
},
"status_code": 200,
"type": "ok"
}
}
]

@ -0,0 +1,30 @@
[
{
"request": {
"body": "{\"params\":[\"0x170baac4eca26076953370dd603c68eab340c0135b19b585010d3158a5dbbf23\"],\"method\":\"eth_getTransactionByHash\",\"jsonrpc\":\"2.0\",\"id\":0}",
"headers": {
"Content-Type": "application/json"
},
"method": "post",
"options": [],
"request_body": "",
"url": "https://sokol.poa.network:443"
},
"response": {
"binary": false,
"body": "{\"jsonrpc\":\"2.0\",\"result\":{\"blockHash\":\"0x8663df28453934be1e0fc59995d8b5295e83e4db689ade8b0244525f8f7c118a\",\"blockNumber\":\"0xc10ab\",\"chainId\":null,\"condition\":null,\"creates\":\"0xac4ff5b5c29338d0046e40f22dbec4d9ef32ed11\",\"from\":\"0xbe96ef1d056c97323e210fd0dd818aa027e57143\",\"gas\":\"0x389af\",\"gasPrice\":\"0x77359400\",\"hash\":\"0x170baac4eca26076953370dd603c68eab340c0135b19b585010d3158a5dbbf23\",\"input\":\"0x6060604052341561000f57600080fd5b7fb94ae47ec9f4248692e2ecf9740b67ab493f3dcc8452bedc7d9cd911c28d1ca5426040518082815260200191505060405180910390a1609e806100546000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063557ed1ba146044575b600080fd5b3415604e57600080fd5b6054606a565b6040518082815260200191505060405180910390f35b6000429050905600a165627a7a7230582053883c0c39da080adc15a91094921659c200b3bb60aed9e49b79b0274da3f4010029\",\"nonce\":\"0x9601\",\"publicKey\":\"0x565e1e48534a6764a50baead6ec60f573d3294cab28b766c928fd6eb8b9c89268bf3452b57bbe8d0c699ac8ed9227344ee72e42f41577fb51777d66520ccdc9c\",\"r\":\"0x81c2771372d8e71d4569bbb0a830f5bb6cdba285178f68e0917e65a682a1cd46\",\"raw\":\"0xf901458296018477359400830389af8080b8f26060604052341561000f57600080fd5b7fb94ae47ec9f4248692e2ecf9740b67ab493f3dcc8452bedc7d9cd911c28d1ca5426040518082815260200191505060405180910390a1609e806100546000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063557ed1ba146044575b600080fd5b3415604e57600080fd5b6054606a565b6040518082815260200191505060405180910390f35b6000429050905600a165627a7a7230582053883c0c39da080adc15a91094921659c200b3bb60aed9e49b79b0274da3f40100291ba081c2771372d8e71d4569bbb0a830f5bb6cdba285178f68e0917e65a682a1cd46a00a1718c45816d32ddbe5efcbe2e41cffe537bc703d80b9632b75ee5a9d445dcd\",\"s\":\"0xa1718c45816d32ddbe5efcbe2e41cffe537bc703d80b9632b75ee5a9d445dcd\",\"standardV\":\"0x0\",\"to\":null,\"transactionIndex\":\"0x11\",\"v\":\"0x1b\",\"value\":\"0x0\"},\"id\":0}\n",
"headers": {
"Date": "Tue, 06 Feb 2018 03:41:42 GMT",
"Content-Type": "application/json",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Set-Cookie": "__cfduid=d9d4f6391b8873087c5766cadd87dbbf51517888502; expires=Wed, 06-Feb-19 03:41:42 GMT; path=/; domain=.poa.network; HttpOnly; Secure",
"Expect-CT": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
"Server": "cloudflare",
"CF-RAY": "3e8b1862cd286d42-SJC"
},
"status_code": 200,
"type": "ok"
}
}
]
Loading…
Cancel
Save