Merge branch 'master' into ab-decode-decoding-cadidates-for-logs

pull/2555/head
Ayrat Badykov 5 years ago committed by GitHub
commit 5c401a49ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      CHANGELOG.md
  2. 1
      apps/block_scout_web/assets/css/_images-preload.scss
  3. 3
      apps/block_scout_web/assets/css/components/_network-selector.scss
  4. 6
      apps/block_scout_web/assets/css/theme/_dai_variables-non-critical.scss
  5. 6
      apps/block_scout_web/assets/css/theme/_ether1_variables-non-critical.scss
  6. 6
      apps/block_scout_web/assets/css/theme/_ethereum_classic_variables-non-critical.scss
  7. 6
      apps/block_scout_web/assets/css/theme/_ethereum_variables-non-critical.scss
  8. 7
      apps/block_scout_web/assets/css/theme/_goerli_variables-non-critical.scss
  9. 6
      apps/block_scout_web/assets/css/theme/_kovan_variables-non-critical.scss
  10. 6
      apps/block_scout_web/assets/css/theme/_lukso_variables-non-critical.scss
  11. 6
      apps/block_scout_web/assets/css/theme/_neutral_variables-non-critical.scss
  12. 6
      apps/block_scout_web/assets/css/theme/_poa_variables-non-critical.scss
  13. 6
      apps/block_scout_web/assets/css/theme/_rinkeby_variables-non-critical.scss
  14. 6
      apps/block_scout_web/assets/css/theme/_ropsten_variables-non-critical.scss
  15. 6
      apps/block_scout_web/assets/css/theme/_rsk_variables-non-critical.scss
  16. 7
      apps/block_scout_web/assets/css/theme/_sokol_variables-non-critical.scss
  17. 5
      apps/block_scout_web/mix.exs
  18. 255
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/address_controller_test.exs
  19. 29
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/block_controller_test.exs
  20. 100
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs
  21. 46
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/logs_controller_test.exs
  22. 42
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/stats_controller_test.exs
  23. 22
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/token_controller_test.exs
  24. 107
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/transaction_controller_test.exs
  25. 14
      apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/decode_error.ex
  26. 8
      apps/explorer/priv/repo/migrations/20190807113117_create_suggested_indexes.exs
  27. 3
      mix.lock

@ -16,6 +16,8 @@
- [#2538](https://github.com/poanetwork/blockscout/pull/2538) - fetch the last not empty coin balance records - [#2538](https://github.com/poanetwork/blockscout/pull/2538) - fetch the last not empty coin balance records
### Chore ### Chore
- [#2590](https://github.com/poanetwork/blockscout/pull/2590) - restore backward compatablity with old releases
- [#2574](https://github.com/poanetwork/blockscout/pull/2574) - limit request body in json rpc error
- [#2566](https://github.com/poanetwork/blockscout/pull/2566) - upgrade absinthe phoenix - [#2566](https://github.com/poanetwork/blockscout/pull/2566) - upgrade absinthe phoenix
@ -46,6 +48,7 @@
- [#2520](https://github.com/poanetwork/blockscout/pull/2520) - Hide loading message when fetching is failed - [#2520](https://github.com/poanetwork/blockscout/pull/2520) - Hide loading message when fetching is failed
- [#2523](https://github.com/poanetwork/blockscout/pull/2523) - Avoid importing internal_transactions of pending transactions - [#2523](https://github.com/poanetwork/blockscout/pull/2523) - Avoid importing internal_transactions of pending transactions
- [#2519](https://github.com/poanetwork/blockscout/pull/2519) - enable `First` page button in pagination - [#2519](https://github.com/poanetwork/blockscout/pull/2519) - enable `First` page button in pagination
- [#2518](https://github.com/poanetwork/blockscout/pull/2518) - create suggested indexes
- [#2517](https://github.com/poanetwork/blockscout/pull/2517) - remove duplicate indexes - [#2517](https://github.com/poanetwork/blockscout/pull/2517) - remove duplicate indexes
- [#2515](https://github.com/poanetwork/blockscout/pull/2515) - do not aggregate NFT token transfers - [#2515](https://github.com/poanetwork/blockscout/pull/2515) - do not aggregate NFT token transfers
- [#2514](https://github.com/poanetwork/blockscout/pull/2514) - Isolating of staking dapp css && extracting of non-critical css - [#2514](https://github.com/poanetwork/blockscout/pull/2514) - Isolating of staking dapp css && extracting of non-critical css

@ -2,6 +2,7 @@ body:after {
position:absolute; width:0; height:0; overflow:hidden; z-index:-1; position:absolute; width:0; height:0; overflow:hidden; z-index:-1;
content: content:
url(/images/network-selector-icons/callisto-mainnet.png) url(/images/network-selector-icons/callisto-mainnet.png)
url(/images/network-selector-icons/ethereum-mainnet.png)
url(/images/network-selector-icons/ethereum-classic.png) url(/images/network-selector-icons/ethereum-classic.png)
url(/images/network-selector-icons/goerli-testnet.png) url(/images/network-selector-icons/goerli-testnet.png)
url(/images/network-selector-icons/kovan-testnet.png) url(/images/network-selector-icons/kovan-testnet.png)

@ -247,6 +247,9 @@ $network-selector-item-icon-dimensions: 30px !default;
&-callisto-mainnet { &-callisto-mainnet {
background-image: url(/images/network-selector-icons/callisto-mainnet.png) background-image: url(/images/network-selector-icons/callisto-mainnet.png)
} }
&-ethereum-mainnet {
background-image: url(/images/network-selector-icons/ethereum-mainnet.png)
}
&-ethereum-classic { &-ethereum-classic {
background-image: url(/images/network-selector-icons/ethereum-classic.png) background-image: url(/images/network-selector-icons/ethereum-classic.png)
} }

@ -1 +1,7 @@
// general
$primary: #17314f;
$secondary: #15bba6;
$tertiary: #93d7ff;
$additional-font: #fff;
$btn-line-color: $secondary; // button border and font color && hover bg color $btn-line-color: $secondary; // button border and font color && hover bg color

@ -1 +1,7 @@
// general
$primary: #840032;
$secondary: #343434;
$tertiary: #7f7f7f;
$additional-font: #ff95db;
$btn-line-color: #4b021e; // button border and font color && hover bg color $btn-line-color: #4b021e; // button border and font color && hover bg color

@ -1 +1,7 @@
// general
$primary: #1c1c3d;
$secondary: #4ad7a7;
$tertiary: #5959d8;
$additional-font: #bdbdff;
$btn-line-color: $tertiary; // button border and font color && hover bg color $btn-line-color: $tertiary; // button border and font color && hover bg color

@ -1 +1,7 @@
// general
$primary: #153550;
$secondary: #49a2ee;
$tertiary: #4ad7a7;
$additional-font: #89cae6;
$btn-line-color: $secondary; // button border and font color && hover bg color $btn-line-color: $secondary; // button border and font color && hover bg color

@ -1 +1,8 @@
// general
$primary: #2b2b2b;
$secondary: #eac247;
$tertiary: #929292;
$additional-font: #ffffff;
$sub-accent-color: #a46f30;
$btn-line-color: $sub-accent-color; // button border and font color && hover bg color $btn-line-color: $sub-accent-color; // button border and font color && hover bg color

@ -1 +1,7 @@
// general
$primary: #101f25;
$secondary: #35e3d8;
$tertiary: #1f857f;
$additional-font: #99fff9;
$btn-line-color: $tertiary; // button border and font color && hover bg color $btn-line-color: $tertiary; // button border and font color && hover bg color

@ -1 +1,7 @@
// general
$primary: #1d3154;
$secondary: #fdcec4;
$tertiary: #a96c55;
$additional-font: #a1ded1;
$btn-line-color: $primary; // button border and font color && hover bg color $btn-line-color: $primary; // button border and font color && hover bg color

@ -1 +1,7 @@
// general
$primary: #5c34a2;
$secondary: #87e1a9;
$tertiary: #bf9cff;
$additional-font: #fff;
$btn-line-color: $primary; // button border and font color && hover bg color $btn-line-color: $primary; // button border and font color && hover bg color

@ -1 +1,7 @@
// general
$primary: #5c34a2;
$secondary: #87e1a9;
$tertiary: #bf9cff;
$additional-font: #fff;
$btn-line-color: $primary; // button border and font color && hover bg color $btn-line-color: $primary; // button border and font color && hover bg color

@ -1 +1,7 @@
// general
$primary: #153550;
$secondary: #38a9f5;
$tertiary: #76f1ff;
$additional-font: #89cae6;
$btn-line-color: $secondary; // button border and font color && hover bg color $btn-line-color: $secondary; // button border and font color && hover bg color

@ -1 +1,7 @@
// general
$primary: #153550;
$secondary: #38a9f5;
$tertiary: #76f1ff;
$additional-font: #89cae6;
$btn-line-color: $secondary; // button border and font color && hover bg color $btn-line-color: $secondary; // button border and font color && hover bg color

@ -1 +1,7 @@
// general
$primary: #101f25;
$secondary: #27ac8d;
$tertiary: #e39a54;
$additional-font: #a1ded1;
$btn-line-color: $secondary; // button border and font color && hover bg color $btn-line-color: $secondary; // button border and font color && hover bg color

@ -1 +1,8 @@
// general
$primary: #093731;
$secondary: #40bfb2;
$tertiary: #25c9ff;
$additional-font: #93e8dd;
$sub-accent-color: #1c9f90;
$btn-line-color: $sub-accent-color; // button border and font color && hover bg color $btn-line-color: $sub-accent-color; // button border and font color && hover bg color

@ -62,7 +62,7 @@ defmodule BlockScoutWeb.Mixfile do
# GraphQL toolkit # GraphQL toolkit
{:absinthe, "~> 1.4"}, {:absinthe, "~> 1.4"},
# Integrates Absinthe subscriptions with Phoenix # Integrates Absinthe subscriptions with Phoenix
{:absinthe_phoenix, git: "https://github.com/ayrat555/absinthe_phoenix.git", branch: "master"}, {:absinthe_phoenix, git: "https://github.com/ayrat555/absinthe_phoenix.git", branch: "ab-update-plug"},
# Plug support for Absinthe # Plug support for Absinthe
{:absinthe_plug, git: "https://github.com/ayrat555/absinthe_plug.git", branch: "ab-enable-default-query"}, {:absinthe_plug, git: "https://github.com/ayrat555/absinthe_plug.git", branch: "ab-enable-default-query"},
# Absinthe support for the Relay framework # Absinthe support for the Relay framework
@ -130,7 +130,8 @@ defmodule BlockScoutWeb.Mixfile do
{:wallaby, "~> 0.22", only: [:test], runtime: false}, {:wallaby, "~> 0.22", only: [:test], runtime: false},
# `:cowboy` `~> 2.0` and Phoenix 1.4 compatibility # `:cowboy` `~> 2.0` and Phoenix 1.4 compatibility
{:wobserver, "~> 0.2.0", github: "poanetwork/wobserver", branch: "support-https"}, {:wobserver, "~> 0.2.0", github: "poanetwork/wobserver", branch: "support-https"},
{:phoenix_form_awesomplete, "~> 0.1.4"} {:phoenix_form_awesomplete, "~> 0.1.4"},
{:ex_json_schema, "~> 0.6.1"}
] ]
end end

@ -47,6 +47,8 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
schema = listaccounts_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
assert response["message"] == "OK" assert response["message"] == "OK"
assert response["status"] == "1" assert response["status"] == "1"
assert response["result"] == [] assert response["result"] == []
@ -63,6 +65,8 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
schema = listaccounts_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
assert response["message"] == "OK" assert response["message"] == "OK"
assert response["status"] == "1" assert response["status"] == "1"
@ -120,6 +124,8 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
schema = listaccounts_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
assert response["message"] == "OK" assert response["message"] == "OK"
assert response["status"] == "1" assert response["status"] == "1"
@ -158,6 +164,8 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
schema = balance_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
assert response["message"] =~ "'address' is required" assert response["message"] =~ "'address' is required"
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
@ -176,6 +184,8 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
schema = balance_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
assert response["message"] =~ "Invalid address hash" assert response["message"] =~ "Invalid address hash"
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
@ -194,6 +204,8 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
schema = balance_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
assert response["result"] == "0" assert response["result"] == "0"
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
@ -213,6 +225,8 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
schema = balance_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
assert response["result"] == "#{address.fetched_coin_balance.value}" assert response["result"] == "#{address.fetched_coin_balance.value}"
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
@ -245,6 +259,8 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
schema = balance_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
@ -289,6 +305,8 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
schema = balance_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
assert response["message"] =~ "Invalid address hash" assert response["message"] =~ "Invalid address hash"
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
@ -315,6 +333,9 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
schema = balance_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
assert :ok = ExJsonSchema.Validator.validate(schema, response)
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
@ -350,6 +371,9 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
schema = balance_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
end end
test "with an address that exists and one that doesn't", %{conn: conn} do test "with an address that exists and one that doesn't", %{conn: conn} do
@ -375,6 +399,9 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
schema = balance_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
end end
test "up to a maximum of 20 addresses in a single request", %{conn: conn} do test "up to a maximum of 20 addresses in a single request", %{conn: conn} do
@ -399,6 +426,9 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert length(response["result"]) == 20 assert length(response["result"]) == 20
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
schema = balance_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
end end
test "with a single address", %{conn: conn} do test "with a single address", %{conn: conn} do
@ -422,6 +452,9 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
schema = balance_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
end end
test "supports GET and POST requests", %{conn: conn} do test "supports GET and POST requests", %{conn: conn} do
@ -471,6 +504,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "with an invalid address hash", %{conn: conn} do test "with an invalid address hash", %{conn: conn} do
@ -489,6 +523,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "with an address that doesn't exist", %{conn: conn} do test "with an address that doesn't exist", %{conn: conn} do
@ -506,6 +541,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == [] assert response["result"] == []
assert response["status"] == "0" assert response["status"] == "0"
assert response["message"] == "No transactions found" assert response["message"] == "No transactions found"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "with a valid address", %{conn: conn} do test "with a valid address", %{conn: conn} do
@ -556,6 +592,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "includes correct confirmations value", %{conn: conn} do test "includes correct confirmations value", %{conn: conn} do
@ -580,12 +617,14 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
expected_confirmations = block_height - transaction.block_number expected_confirmations = block_height - transaction.block_number
assert %{"result" => [returned_transaction]} = assert %{"result" => [returned_transaction]} =
response =
conn conn
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
assert returned_transaction["confirmations"] == "#{expected_confirmations}" assert returned_transaction["confirmations"] == "#{expected_confirmations}"
assert returned_transaction["hash"] == "#{hash}" assert returned_transaction["hash"] == "#{hash}"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "returns '1' for 'isError' with failed transaction", %{conn: conn} do test "returns '1' for 'isError' with failed transaction", %{conn: conn} do
@ -605,6 +644,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
} }
assert %{"result" => [returned_transaction]} = assert %{"result" => [returned_transaction]} =
response =
conn conn
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
@ -612,6 +652,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert returned_transaction["isError"] == "1" assert returned_transaction["isError"] == "1"
assert returned_transaction["txreceipt_status"] == "0" assert returned_transaction["txreceipt_status"] == "0"
assert returned_transaction["hash"] == "#{hash}" assert returned_transaction["hash"] == "#{hash}"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "with address with multiple transactions", %{conn: conn} do test "with address with multiple transactions", %{conn: conn} do
@ -648,6 +689,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "orders transactions by block, in ascending order", %{conn: conn} do test "orders transactions by block, in ascending order", %{conn: conn} do
@ -688,6 +730,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert block_numbers_order == Enum.sort(block_numbers_order, &(&1 <= &2)) assert block_numbers_order == Enum.sort(block_numbers_order, &(&1 <= &2))
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "orders transactions by block, in descending order", %{conn: conn} do test "orders transactions by block, in descending order", %{conn: conn} do
@ -728,6 +771,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert block_numbers_order == Enum.sort(block_numbers_order, &(&1 >= &2)) assert block_numbers_order == Enum.sort(block_numbers_order, &(&1 >= &2))
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "ignores invalid sort option, defaults to ascending", %{conn: conn} do test "ignores invalid sort option, defaults to ascending", %{conn: conn} do
@ -768,6 +812,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert block_numbers_order == Enum.sort(block_numbers_order, &(&1 <= &2)) assert block_numbers_order == Enum.sort(block_numbers_order, &(&1 <= &2))
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "with valid pagination params", %{conn: conn} do test "with valid pagination params", %{conn: conn} do
@ -821,6 +866,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "ignores pagination params when invalid", %{conn: conn} do test "ignores pagination params when invalid", %{conn: conn} do
@ -862,6 +908,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert length(response["result"]) == 6 assert length(response["result"]) == 6
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "ignores offset param if offset is less than 1", %{conn: conn} do test "ignores offset param if offset is less than 1", %{conn: conn} do
@ -889,6 +936,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert length(response["result"]) == 6 assert length(response["result"]) == 6
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "ignores offset param if offset is over 10,000", %{conn: conn} do test "ignores offset param if offset is over 10,000", %{conn: conn} do
@ -916,6 +964,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert length(response["result"]) == 6 assert length(response["result"]) == 6
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "with page number with no results", %{conn: conn} do test "with page number with no results", %{conn: conn} do
@ -957,6 +1006,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == [] assert response["result"] == []
assert response["status"] == "0" assert response["status"] == "0"
assert response["message"] == "No transactions found" assert response["message"] == "No transactions found"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "with startblock and endblock params", %{conn: conn} do test "with startblock and endblock params", %{conn: conn} do
@ -995,6 +1045,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "with startblock but without endblock", %{conn: conn} do test "with startblock but without endblock", %{conn: conn} do
@ -1032,6 +1083,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "with endblock but without startblock", %{conn: conn} do test "with endblock but without startblock", %{conn: conn} do
@ -1069,6 +1121,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "ignores invalid startblock and endblock", %{conn: conn} do test "ignores invalid startblock and endblock", %{conn: conn} do
@ -1097,6 +1150,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert length(response["result"]) == 8 assert length(response["result"]) == 8
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "with starttimestamp and endtimestamp params", %{conn: conn} do test "with starttimestamp and endtimestamp params", %{conn: conn} do
@ -1144,6 +1198,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "with starttimestamp but without endtimestamp", %{conn: conn} do test "with starttimestamp but without endtimestamp", %{conn: conn} do
@ -1191,6 +1246,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "with endtimestamp but without starttimestamp", %{conn: conn} do test "with endtimestamp but without starttimestamp", %{conn: conn} do
@ -1236,6 +1292,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "with filterby=to option", %{conn: conn} do test "with filterby=to option", %{conn: conn} do
@ -1263,6 +1320,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert length(response["result"]) == 1 assert length(response["result"]) == 1
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "with filterby=from option", %{conn: conn} do test "with filterby=from option", %{conn: conn} do
@ -1293,6 +1351,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert length(response["result"]) == 2 assert length(response["result"]) == 2
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlist_schema(), response)
end end
test "supports GET and POST requests", %{conn: conn} do test "supports GET and POST requests", %{conn: conn} do
@ -1338,6 +1397,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(txlistinternal_schema(), response)
end end
end end
@ -1358,6 +1418,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(txlistinternal_schema(), response)
end end
test "with a txhash that doesn't exist", %{conn: conn} do test "with a txhash that doesn't exist", %{conn: conn} do
@ -1375,6 +1436,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == [] assert response["result"] == []
assert response["status"] == "0" assert response["status"] == "0"
assert response["message"] == "No internal transactions found" assert response["message"] == "No internal transactions found"
assert :ok = ExJsonSchema.Validator.validate(txlistinternal_schema(), response)
end end
test "response includes all the expected fields", %{conn: conn} do test "response includes all the expected fields", %{conn: conn} do
@ -1427,6 +1489,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlistinternal_schema(), response)
end end
test "isError is true if internal transaction has an error", %{conn: conn} do test "isError is true if internal transaction has an error", %{conn: conn} do
@ -1459,6 +1522,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert found_internal_transaction["isError"] == "1" assert found_internal_transaction["isError"] == "1"
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlistinternal_schema(), response)
end end
test "with transaction with multiple internal transactions", %{conn: conn} do test "with transaction with multiple internal transactions", %{conn: conn} do
@ -1486,6 +1550,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert length(found_internal_transactions) == 3 assert length(found_internal_transactions) == 3
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlistinternal_schema(), response)
end end
end end
@ -1506,6 +1571,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(txlistinternal_schema(), response)
end end
test "with a address that doesn't exist", %{conn: conn} do test "with a address that doesn't exist", %{conn: conn} do
@ -1523,6 +1589,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == [] assert response["result"] == []
assert response["status"] == "0" assert response["status"] == "0"
assert response["message"] == "No internal transactions found" assert response["message"] == "No internal transactions found"
assert :ok = ExJsonSchema.Validator.validate(txlistinternal_schema(), response)
end end
test "response includes all the expected fields", %{conn: conn} do test "response includes all the expected fields", %{conn: conn} do
@ -1575,6 +1642,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlistinternal_schema(), response)
end end
test "isError is true if internal transaction has an error", %{conn: conn} do test "isError is true if internal transaction has an error", %{conn: conn} do
@ -1610,6 +1678,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert found_internal_transaction["isError"] == "1" assert found_internal_transaction["isError"] == "1"
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlistinternal_schema(), response)
end end
test "with transaction with multiple internal transactions", %{conn: conn} do test "with transaction with multiple internal transactions", %{conn: conn} do
@ -1645,6 +1714,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert length(found_internal_transactions) == 3 assert length(found_internal_transactions) == 3
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(txlistinternal_schema(), response)
end end
end end
@ -1664,6 +1734,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(tokentx_schema(), response)
end end
test "with an invalid address hash", %{conn: conn} do test "with an invalid address hash", %{conn: conn} do
@ -1682,6 +1753,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(tokentx_schema(), response)
end end
test "with an address that doesn't exist", %{conn: conn} do test "with an address that doesn't exist", %{conn: conn} do
@ -1699,6 +1771,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == [] assert response["result"] == []
assert response["status"] == "0" assert response["status"] == "0"
assert response["message"] == "No token transfers found" assert response["message"] == "No token transfers found"
assert :ok = ExJsonSchema.Validator.validate(tokentx_schema(), response)
end end
test "has correct value for ERC-721", %{conn: conn} do test "has correct value for ERC-721", %{conn: conn} do
@ -1734,6 +1807,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert result["value"] == to_string(token_transfer.token_id) assert result["value"] == to_string(token_transfer.token_id)
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(tokentx_schema(), response)
end end
test "returns all the required fields", %{conn: conn} do test "returns all the required fields", %{conn: conn} do
@ -1785,6 +1859,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(tokentx_schema(), response)
end end
test "with an invalid contract address", %{conn: conn} do test "with an invalid contract address", %{conn: conn} do
@ -1804,6 +1879,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(tokentx_schema(), response)
end end
test "filters results by contract address", %{conn: conn} do test "filters results by contract address", %{conn: conn} do
@ -1837,6 +1913,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert result["contractAddress"] == to_string(contract_address.hash) assert result["contractAddress"] == to_string(contract_address.hash)
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(tokentx_schema(), response)
end end
end end
@ -1856,6 +1933,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(tokenbalance_schema(), response)
end end
test "with contractaddress but without address", %{conn: conn} do test "with contractaddress but without address", %{conn: conn} do
@ -1874,6 +1952,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(tokenbalance_schema(), response)
end end
test "with address but without contractaddress", %{conn: conn} do test "with address but without contractaddress", %{conn: conn} do
@ -1892,6 +1971,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(tokenbalance_schema(), response)
end end
test "with an invalid contractaddress hash", %{conn: conn} do test "with an invalid contractaddress hash", %{conn: conn} do
@ -1911,6 +1991,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(tokenbalance_schema(), response)
end end
test "with an invalid address hash", %{conn: conn} do test "with an invalid address hash", %{conn: conn} do
@ -1930,6 +2011,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(tokenbalance_schema(), response)
end end
test "with a contractaddress and address that doesn't exist", %{conn: conn} do test "with a contractaddress and address that doesn't exist", %{conn: conn} do
@ -1948,6 +2030,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == "0" assert response["result"] == "0"
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(tokenbalance_schema(), response)
end end
test "with contractaddress and address without row in token_balances table", %{conn: conn} do test "with contractaddress and address without row in token_balances table", %{conn: conn} do
@ -1969,6 +2052,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == "0" assert response["result"] == "0"
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(tokenbalance_schema(), response)
end end
test "with contractaddress and address with existing balance in token_balances table", %{conn: conn} do test "with contractaddress and address with existing balance in token_balances table", %{conn: conn} do
@ -1989,6 +2073,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == to_string(token_balance.value) assert response["result"] == to_string(token_balance.value)
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(tokenbalance_schema(), response)
end end
end end
@ -2008,6 +2093,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(tokenlist_schema(), response)
end end
test "with an invalid address hash", %{conn: conn} do test "with an invalid address hash", %{conn: conn} do
@ -2026,6 +2112,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(tokenlist_schema(), response)
end end
test "with an address that doesn't exist", %{conn: conn} do test "with an address that doesn't exist", %{conn: conn} do
@ -2043,6 +2130,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == [] assert response["result"] == []
assert response["status"] == "0" assert response["status"] == "0"
assert response["message"] == "No tokens found" assert response["message"] == "No tokens found"
assert :ok = ExJsonSchema.Validator.validate(tokenlist_schema(), response)
end end
test "with an address without row in token_balances table", %{conn: conn} do test "with an address without row in token_balances table", %{conn: conn} do
@ -2062,6 +2150,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == [] assert response["result"] == []
assert response["status"] == "0" assert response["status"] == "0"
assert response["message"] == "No tokens found" assert response["message"] == "No tokens found"
assert :ok = ExJsonSchema.Validator.validate(tokenlist_schema(), response)
end end
test "with address with existing balance in token_balances table", %{conn: conn} do test "with address with existing balance in token_balances table", %{conn: conn} do
@ -2092,6 +2181,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(tokenlist_schema(), response)
end end
test "with address with multiple tokens", %{conn: conn} do test "with address with multiple tokens", %{conn: conn} do
@ -2115,6 +2205,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert length(response["result"]) == 2 assert length(response["result"]) == 2
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(tokenlist_schema(), response)
end end
end end
@ -2134,6 +2225,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(block_schema(), response)
end end
test "with an invalid address hash", %{conn: conn} do test "with an invalid address hash", %{conn: conn} do
@ -2152,6 +2244,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(block_schema(), response)
end end
test "with an address that doesn't exist", %{conn: conn} do test "with an address that doesn't exist", %{conn: conn} do
@ -2169,6 +2262,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == [] assert response["result"] == []
assert response["status"] == "0" assert response["status"] == "0"
assert response["message"] == "No blocks found" assert response["message"] == "No blocks found"
assert :ok = ExJsonSchema.Validator.validate(block_schema(), response)
end end
test "returns all the required fields", %{conn: conn} do test "returns all the required fields", %{conn: conn} do
@ -2208,6 +2302,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(block_schema(), response)
end end
test "with a block with one transaction", %{conn: conn} do test "with a block with one transaction", %{conn: conn} do
@ -2247,6 +2342,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(block_schema(), response)
end end
test "with pagination options", %{conn: conn} do test "with pagination options", %{conn: conn} do
@ -2297,6 +2393,7 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(block_schema(), response)
end end
end end
@ -2439,4 +2536,162 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert result == {:required_params, {:ok, params}} assert result == {:required_params, {:ok, params}}
end end
end end
defp listaccounts_schema do
resolve_schema(%{
"type" => "array",
"items" => %{
"type" => "object",
"properties" => %{
"address" => %{"type" => "string"},
"balance" => %{"type" => "string"},
"stale" => %{"type" => "boolean"}
}
}
})
end
defp balance_schema do
resolve_schema(%{
"type" => ["string", "null", "array"],
"items" => %{
"type" => "object",
"properties" => %{
"account" => %{"type" => "string"},
"balance" => %{"type" => "string"},
"stale" => %{"type" => "boolean"}
}
}
})
end
defp txlist_schema do
resolve_schema(%{
"type" => ["null", "array"],
"items" => %{
"type" => "object",
"properties" => %{
"blockNumber" => %{"type" => "string"},
"timeStamp" => %{"type" => "string"},
"hash" => %{"type" => "string"},
"nonce" => %{"type" => "string"},
"blockHash" => %{"type" => "string"},
"transactionIndex" => %{"type" => "string"},
"from" => %{"type" => "string"},
"to" => %{"type" => "string"},
"value" => %{"type" => "string"},
"gas" => %{"type" => "string"},
"gasPrice" => %{"type" => "string"},
"isError" => %{"type" => "string"},
"txreceipt_status" => %{"type" => "string"},
"input" => %{"type" => "string"},
"contractAddress" => %{"type" => "string"},
"cumulativeGasUsed" => %{"type" => "string"},
"gasUsed" => %{"type" => "string"},
"confirmations" => %{"type" => "string"}
}
}
})
end
defp txlistinternal_schema do
resolve_schema(%{
"type" => ["array", "null"],
"items" => %{
"type" => "object",
"properties" => %{
"blockNumber" => %{"type" => "string"},
"timeStamp" => %{"type" => "string"},
"from" => %{"type" => "string"},
"to" => %{"type" => "string"},
"value" => %{"type" => "string"},
"contractAddress" => %{"type" => "string"},
"transactionHash" => %{"type" => "string"},
"index" => %{"type" => "string"},
"input" => %{"type" => "string"},
"type" => %{"type" => "string"},
"gas" => %{"type" => "string"},
"gasUsed" => %{"type" => "string"},
"isError" => %{"type" => "string"},
"errCode" => %{"type" => "string"}
}
}
})
end
defp tokentx_schema do
resolve_schema(%{
"type" => ["array", "null"],
"items" => %{
"type" => "object",
"properties" => %{
"blockNumber" => %{"type" => "string"},
"timeStamp" => %{"type" => "string"},
"hash" => %{"type" => "string"},
"nonce" => %{"type" => "string"},
"blockHash" => %{"type" => "string"},
"from" => %{"type" => "string"},
"contractAddress" => %{"type" => "string"},
"to" => %{"type" => "string"},
"logIndex" => %{"type" => "string"},
"value" => %{"type" => "string"},
"tokenName" => %{"type" => "string"},
"tokenSymbol" => %{"type" => "string"},
"tokenDecimal" => %{"type" => "string"},
"transactionIndex" => %{"type" => "string"},
"gas" => %{"type" => "string"},
"gasPrice" => %{"type" => "string"},
"gasUsed" => %{"type" => "string"},
"cumulativeGasUsed" => %{"type" => "string"},
"input" => %{"type" => "string"},
"confirmations" => %{"type" => "string"}
}
}
})
end
defp tokenbalance_schema, do: resolve_schema(%{"type" => ["string", "null"]})
defp tokenlist_schema do
resolve_schema(%{
"type" => ["array", "null"],
"items" => %{
"type" => "object",
"properties" => %{
"balance" => %{"type" => "string"},
"contractAddress" => %{"type" => "string"},
"name" => %{"type" => "string"},
"decimals" => %{"type" => "string"},
"symbol" => %{"type" => "string"},
"type" => %{"type" => "string"}
}
}
})
end
defp block_schema do
resolve_schema(%{
"type" => ["array", "null"],
"items" => %{
"type" => "object",
"properties" => %{
"blockNumber" => %{"type" => "string"},
"timeStamp" => %{"type" => "string"},
"blockReward" => %{"type" => "string"}
}
}
})
end
defp resolve_schema(result \\ %{}) do
%{
"type" => "object",
"properties" => %{
"message" => %{"type" => "string"},
"status" => %{"type" => "string"}
}
}
|> put_in(["properties", "result"], result)
|> ExJsonSchema.Schema.resolve()
end
end end

@ -14,6 +14,8 @@ defmodule BlockScoutWeb.API.RPC.BlockControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
schema = resolve_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
end end
test "with an invalid block number", %{conn: conn} do test "with an invalid block number", %{conn: conn} do
@ -26,6 +28,8 @@ defmodule BlockScoutWeb.API.RPC.BlockControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
schema = resolve_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
end end
test "with a block that doesn't exist", %{conn: conn} do test "with a block that doesn't exist", %{conn: conn} do
@ -38,6 +42,8 @@ defmodule BlockScoutWeb.API.RPC.BlockControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
schema = resolve_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
end end
test "with a valid block", %{conn: conn} do test "with a valid block", %{conn: conn} do
@ -71,6 +77,29 @@ defmodule BlockScoutWeb.API.RPC.BlockControllerTest do
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
schema = resolve_schema()
assert :ok = ExJsonSchema.Validator.validate(schema, response)
end end
end end
defp resolve_schema() do
ExJsonSchema.Schema.resolve(%{
"type" => "object",
"properties" => %{
"message" => %{"type" => "string"},
"status" => %{"type" => "string"},
"result" => %{
"type" => ["object", "null"],
"properties" => %{
"blockNumber" => %{"type" => "string"},
"timeStamp" => %{"type" => "number"},
"blockMiner" => %{"type" => "string"},
"blockReward" => %{"type" => "string"},
"uncles" => %{"type" => "null"},
"uncleInclusionReward" => %{"type" => "null"}
}
}
}
})
end
end end

@ -17,6 +17,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"invalid is not a valid value for `filter`. Please use one of: verified, decompiled, unverified, not_decompiled, 1, 2, 3, 4." "invalid is not a valid value for `filter`. Please use one of: verified, decompiled, unverified, not_decompiled, 1, 2, 3, 4."
assert response["status"] == "0" assert response["status"] == "0"
assert :ok = ExJsonSchema.Validator.validate(listcontracts_schema(), response)
end end
test "with no contracts", %{conn: conn, params: params} do test "with no contracts", %{conn: conn, params: params} do
@ -28,6 +29,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["message"] == "OK" assert response["message"] == "OK"
assert response["status"] == "1" assert response["status"] == "1"
assert response["result"] == [] assert response["result"] == []
assert :ok = ExJsonSchema.Validator.validate(listcontracts_schema(), response)
end end
test "with a verified smart contract, all contract information is shown", %{conn: conn, params: params} do test "with a verified smart contract, all contract information is shown", %{conn: conn, params: params} do
@ -50,6 +52,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"OptimizationUsed" => if(contract.optimization, do: "1", else: "0") "OptimizationUsed" => if(contract.optimization, do: "1", else: "0")
} }
] ]
assert :ok = ExJsonSchema.Validator.validate(listcontracts_schema(), response)
end end
test "with an unverified contract address, only basic information is shown", %{conn: conn, params: params} do test "with an unverified contract address, only basic information is shown", %{conn: conn, params: params} do
@ -72,6 +76,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"OptimizationUsed" => "" "OptimizationUsed" => ""
} }
] ]
assert :ok = ExJsonSchema.Validator.validate(listcontracts_schema(), response)
end end
test "filtering for only unverified contracts shows only unverified contracts", %{params: params, conn: conn} do test "filtering for only unverified contracts shows only unverified contracts", %{params: params, conn: conn} do
@ -95,6 +101,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"OptimizationUsed" => "" "OptimizationUsed" => ""
} }
] ]
assert :ok = ExJsonSchema.Validator.validate(listcontracts_schema(), response)
end end
test "filtering for only unverified contracts does not show self destructed contracts", %{ test "filtering for only unverified contracts does not show self destructed contracts", %{
@ -122,6 +130,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"OptimizationUsed" => "" "OptimizationUsed" => ""
} }
] ]
assert :ok = ExJsonSchema.Validator.validate(listcontracts_schema(), response)
end end
test "filtering for only verified contracts shows only verified contracts", %{params: params, conn: conn} do test "filtering for only verified contracts shows only verified contracts", %{params: params, conn: conn} do
@ -145,6 +155,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"OptimizationUsed" => if(contract.optimization, do: "1", else: "0") "OptimizationUsed" => if(contract.optimization, do: "1", else: "0")
} }
] ]
assert :ok = ExJsonSchema.Validator.validate(listcontracts_schema(), response)
end end
test "filtering for only decompiled contracts shows only decompiled contracts", %{params: params, conn: conn} do test "filtering for only decompiled contracts shows only decompiled contracts", %{params: params, conn: conn} do
@ -168,6 +180,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"OptimizationUsed" => "" "OptimizationUsed" => ""
} }
] ]
assert :ok = ExJsonSchema.Validator.validate(listcontracts_schema(), response)
end end
test "filtering for only decompiled contracts, with a decompiled with version filter", %{params: params, conn: conn} do test "filtering for only decompiled contracts, with a decompiled with version filter", %{params: params, conn: conn} do
@ -191,6 +205,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"OptimizationUsed" => "" "OptimizationUsed" => ""
} }
] ]
assert :ok = ExJsonSchema.Validator.validate(listcontracts_schema(), response)
end end
test "filtering for only decompiled contracts, with a decompiled with version filter, where another decompiled version exists", test "filtering for only decompiled contracts, with a decompiled with version filter, where another decompiled version exists",
@ -216,6 +232,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
} in response["result"] } in response["result"]
refute to_string(non_match.address_hash) in Enum.map(response["result"], &Map.get(&1, "Address")) refute to_string(non_match.address_hash) in Enum.map(response["result"], &Map.get(&1, "Address"))
assert :ok = ExJsonSchema.Validator.validate(listcontracts_schema(), response)
end end
test "filtering for only not_decompiled (and by extension not verified contracts)", %{params: params, conn: conn} do test "filtering for only not_decompiled (and by extension not verified contracts)", %{params: params, conn: conn} do
@ -240,6 +257,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"OptimizationUsed" => "" "OptimizationUsed" => ""
} }
] ]
assert :ok = ExJsonSchema.Validator.validate(listcontracts_schema(), response)
end end
test "filtering for only not_decompiled (and by extension not verified contracts) does not show empty contracts", %{ test "filtering for only not_decompiled (and by extension not verified contracts) does not show empty contracts", %{
@ -268,6 +287,8 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
"OptimizationUsed" => "" "OptimizationUsed" => ""
} }
] ]
assert :ok = ExJsonSchema.Validator.validate(listcontracts_schema(), response)
end end
end end
@ -287,6 +308,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(getabi_schema(), response)
end end
test "with an invalid address hash", %{conn: conn} do test "with an invalid address hash", %{conn: conn} do
@ -305,6 +327,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(getabi_schema(), response)
end end
test "with an address that doesn't exist", %{conn: conn} do test "with an address that doesn't exist", %{conn: conn} do
@ -322,6 +345,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["result"] == nil assert response["result"] == nil
assert response["status"] == "0" assert response["status"] == "0"
assert response["message"] == "Contract source code not verified" assert response["message"] == "Contract source code not verified"
assert :ok = ExJsonSchema.Validator.validate(getabi_schema(), response)
end end
test "with a verified contract address", %{conn: conn} do test "with a verified contract address", %{conn: conn} do
@ -341,6 +365,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["result"] == Jason.encode!(contract.abi) assert response["result"] == Jason.encode!(contract.abi)
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(getabi_schema(), response)
end end
end end
@ -360,6 +385,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(getsourcecode_schema(), response)
end end
test "with an invalid address hash", %{conn: conn} do test "with an invalid address hash", %{conn: conn} do
@ -378,6 +404,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(getsourcecode_schema(), response)
end end
test "with an address that doesn't exist", %{conn: conn} do test "with an address that doesn't exist", %{conn: conn} do
@ -408,6 +435,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(getsourcecode_schema(), response)
end end
test "with a verified contract address", %{conn: conn} do test "with a verified contract address", %{conn: conn} do
@ -443,6 +471,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(getsourcecode_schema(), response)
end end
end end
@ -481,6 +510,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert response["status"] == "1" assert response["status"] == "1"
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(verify_schema(), response)
end end
test "with external libraries", %{conn: conn} do test "with external libraries", %{conn: conn} do
@ -539,6 +569,76 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
assert result["DecompiledSourceCode"] == "Contract source code not decompiled." assert result["DecompiledSourceCode"] == "Contract source code not decompiled."
assert result["DecompilerVersion"] == "" assert result["DecompilerVersion"] == ""
assert result["OptimizationUsed"] == "1" assert result["OptimizationUsed"] == "1"
assert :ok = ExJsonSchema.Validator.validate(verify_schema(), response)
end
end
defp listcontracts_schema do
resolve_schema(%{
"type" => ["array", "null"],
"items" => %{
"type" => "object",
"properties" => %{
"Address" => %{"type" => "string"},
"ABI" => %{"type" => "string"},
"ContractName" => %{"type" => "string"},
"CompilerVersion" => %{"type" => "string"},
"OptimizationUsed" => %{"type" => "string"}
}
}
})
end end
defp getabi_schema do
resolve_schema(%{
"type" => ["string", "null"]
})
end
defp getsourcecode_schema do
resolve_schema(%{
"type" => ["array", "null"],
"items" => %{
"type" => "object",
"properties" => %{
"Address" => %{"type" => "string"},
"SourceCode" => %{"type" => "string"},
"ABI" => %{"type" => "string"},
"ContractName" => %{"type" => "string"},
"CompilerVersion" => %{"type" => "string"},
"OptimizationUsed" => %{"type" => "string"},
"DecompiledSourceCode" => %{"type" => "string"},
"DecompilerVersion" => %{"type" => "string"}
}
}
})
end
defp verify_schema do
resolve_schema(%{
"type" => "object",
"properties" => %{
"Address" => %{"type" => "string"},
"SourceCode" => %{"type" => "string"},
"ABI" => %{"type" => "string"},
"ContractName" => %{"type" => "string"},
"CompilerVersion" => %{"type" => "string"},
"DecompiledSourceCode" => %{"type" => "string"},
"DecompilerVersion" => %{"type" => "string"},
"OptimizationUsed" => %{"type" => "string"}
}
})
end
defp resolve_schema(result \\ %{}) do
%{
"type" => "object",
"properties" => %{
"message" => %{"type" => "string"},
"status" => %{"type" => "string"}
}
}
|> put_in(["properties", "result"], result)
|> ExJsonSchema.Schema.resolve()
end end
end end

@ -22,6 +22,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
end end
test "without fromBlock", %{conn: conn} do test "without fromBlock", %{conn: conn} do
@ -43,6 +44,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
end end
test "without toBlock", %{conn: conn} do test "without toBlock", %{conn: conn} do
@ -64,6 +66,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
end end
test "without address and topic{x}", %{conn: conn} do test "without address and topic{x}", %{conn: conn} do
@ -85,6 +88,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
end end
test "without topic{x}_{x}_opr", %{conn: conn} do test "without topic{x}_{x}_opr", %{conn: conn} do
@ -118,6 +122,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
end end
end end
@ -146,6 +151,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
end end
test "with invalid fromBlock", %{conn: conn} do test "with invalid fromBlock", %{conn: conn} do
@ -166,6 +172,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
end end
test "with invalid toBlock", %{conn: conn} do test "with invalid toBlock", %{conn: conn} do
@ -186,6 +193,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
end end
test "with an invalid address hash", %{conn: conn} do test "with an invalid address hash", %{conn: conn} do
@ -206,6 +214,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
end end
test "with invalid topic{x}_{x}_opr", %{conn: conn} do test "with invalid topic{x}_{x}_opr", %{conn: conn} do
@ -238,6 +247,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
end end
end end
@ -258,6 +268,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert response["result"] == [] assert response["result"] == []
assert response["status"] == "0" assert response["status"] == "0"
assert response["message"] == "No logs found" assert response["message"] == "No logs found"
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
end end
test "with a valid contract address", %{conn: conn} do test "with a valid contract address", %{conn: conn} do
@ -302,6 +313,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
end end
test "ignores logs with block below fromBlock", %{conn: conn} do test "ignores logs with block below fromBlock", %{conn: conn} do
@ -340,6 +352,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
[found_log] = response["result"] [found_log] = response["result"]
@ -383,6 +396,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
[found_log] = response["result"] [found_log] = response["result"]
@ -445,6 +459,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
end end
test "with a topic{x} AND another", %{conn: conn} do test "with a topic{x} AND another", %{conn: conn} do
@ -493,6 +508,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert found_log["topics"] == get_topics(log1) assert found_log["topics"] == get_topics(log1)
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
end end
test "with a topic{x} OR another", %{conn: conn} do test "with a topic{x} OR another", %{conn: conn} do
@ -540,6 +556,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert length(result) == 2 assert length(result) == 2
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
end end
test "with all available 'topic{x}'s and 'topic{x}_{x}_opr's", %{conn: conn} do test "with all available 'topic{x}'s and 'topic{x}_{x}_opr's", %{conn: conn} do
@ -598,6 +615,7 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
assert length(result) == 2 assert length(result) == 2
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(getlogs_schema(), response)
end end
end end
@ -771,4 +789,32 @@ defmodule BlockScoutWeb.API.RPC.LogsControllerTest do
|> DateTime.to_unix() |> DateTime.to_unix()
|> integer_to_hex() |> integer_to_hex()
end end
defp getlogs_schema do
ExJsonSchema.Schema.resolve(%{
"type" => "object",
"properties" => %{
"message" => %{"type" => "string"},
"status" => %{"type" => "string"},
"result" => %{
"type" => ["array", "null"],
"items" => %{
"type" => "object",
"properties" => %{
"address" => %{"type" => "string"},
"topics" => %{"type" => "array", "items" => %{"type" => ["string", "null"]}},
"data" => %{"type" => "string"},
"blockNumber" => %{"type" => "string"},
"timeStamp" => %{"type" => "string"},
"gasPrice" => %{"type" => "string"},
"gasUsed" => %{"type" => "string"},
"logIndex" => %{"type" => "string"},
"transactionHash" => %{"type" => "string"},
"transactionIndex" => %{"type" => "string"}
}
}
}
}
})
end
end end

@ -23,6 +23,7 @@ defmodule BlockScoutWeb.API.RPC.StatsControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(tokensupply_schema(), response)
end end
test "with an invalid contractaddress hash", %{conn: conn} do test "with an invalid contractaddress hash", %{conn: conn} do
@ -41,6 +42,7 @@ defmodule BlockScoutWeb.API.RPC.StatsControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(tokensupply_schema(), response)
end end
test "with a contractaddress that doesn't exist", %{conn: conn} do test "with a contractaddress that doesn't exist", %{conn: conn} do
@ -59,6 +61,7 @@ defmodule BlockScoutWeb.API.RPC.StatsControllerTest do
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
refute response["result"] refute response["result"]
assert :ok = ExJsonSchema.Validator.validate(tokensupply_schema(), response)
end end
test "with valid contractaddress", %{conn: conn} do test "with valid contractaddress", %{conn: conn} do
@ -78,6 +81,7 @@ defmodule BlockScoutWeb.API.RPC.StatsControllerTest do
assert response["result"] == to_string(token.total_supply) assert response["result"] == to_string(token.total_supply)
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(tokensupply_schema(), response)
end end
end end
@ -96,6 +100,7 @@ defmodule BlockScoutWeb.API.RPC.StatsControllerTest do
assert response["result"] == "252460800000000000000000000" assert response["result"] == "252460800000000000000000000"
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(ethsupply_schema(), response)
end end
end end
@ -158,6 +163,43 @@ defmodule BlockScoutWeb.API.RPC.StatsControllerTest do
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
assert :ok = ExJsonSchema.Validator.validate(ethprice_schema(), response)
end end
end end
defp tokensupply_schema do
resolve_schema(%{
"type" => ["string", "null"]
})
end
defp ethsupply_schema do
resolve_schema(%{
"type" => ["string", "null"]
})
end
defp ethprice_schema do
resolve_schema(%{
"type" => "object",
"properties" => %{
"ethbtc" => %{"type" => "string"},
"ethbtc_timestamp" => %{"type" => "string"},
"ethusd" => %{"type" => "string"},
"ethusd_timestamp" => %{"type" => "string"}
}
})
end
defp resolve_schema(result \\ %{}) do
%{
"type" => "object",
"properties" => %{
"message" => %{"type" => "string"},
"status" => %{"type" => "string"}
}
}
|> put_in(["properties", "result"], result)
|> ExJsonSchema.Schema.resolve()
end
end end

@ -84,4 +84,26 @@ defmodule BlockScoutWeb.API.RPC.TokenControllerTest do
assert response["message"] == "OK" assert response["message"] == "OK"
end end
end end
defp gettoken_schema do
ExJsonSchema.Schema.resolve(%{
"type" => "object",
"properties" => %{
"message" => %{"type" => "string"},
"status" => %{"type" => "string"},
"result" => %{
"type" => "object",
"properties" => %{
"name" => %{"type" => "string"},
"symbol" => %{"type" => "string"},
"totalSupply" => %{"type" => "string"},
"decimals" => %{"type" => "string"},
"type" => %{"type" => "string"},
"cataloged" => %{"type" => "string"},
"contractAddress" => %{"type" => "string"}
}
}
}
})
end
end end

@ -15,6 +15,8 @@ defmodule BlockScoutWeb.API.RPC.TransactionControllerTest do
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
schema = resolve_schema()
assert ExJsonSchema.Validator.valid?(schema, response)
assert response["message"] =~ "txhash is required" assert response["message"] =~ "txhash is required"
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
@ -33,6 +35,8 @@ defmodule BlockScoutWeb.API.RPC.TransactionControllerTest do
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
schema = resolve_schema()
assert ExJsonSchema.Validator.valid?(schema, response)
assert response["message"] =~ "Invalid txhash format" assert response["message"] =~ "Invalid txhash format"
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
@ -46,11 +50,20 @@ defmodule BlockScoutWeb.API.RPC.TransactionControllerTest do
"txhash" => "0x40eb908387324f2b575b4879cd9d7188f69c8fc9d87c901b9e2daaea4b442170" "txhash" => "0x40eb908387324f2b575b4879cd9d7188f69c8fc9d87c901b9e2daaea4b442170"
} }
schema =
resolve_schema(%{
"type" => "object",
"properties" => %{
"status" => %{"type" => "string"}
}
})
assert response = assert response =
conn conn
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
assert ExJsonSchema.Validator.valid?(schema, response)
assert response["result"] == %{"status" => ""} assert response["result"] == %{"status" => ""}
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
@ -136,6 +149,8 @@ defmodule BlockScoutWeb.API.RPC.TransactionControllerTest do
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
schema = resolve_schema()
assert ExJsonSchema.Validator.valid?(schema, response)
assert response["message"] =~ "txhash is required" assert response["message"] =~ "txhash is required"
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
@ -154,6 +169,8 @@ defmodule BlockScoutWeb.API.RPC.TransactionControllerTest do
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
schema = resolve_schema()
assert ExJsonSchema.Validator.valid?(schema, response)
assert response["message"] =~ "Invalid txhash format" assert response["message"] =~ "Invalid txhash format"
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
@ -172,11 +189,21 @@ defmodule BlockScoutWeb.API.RPC.TransactionControllerTest do
"errDescription" => "" "errDescription" => ""
} }
schema =
resolve_schema(%{
"type" => "object",
"properties" => %{
"isError" => %{"type" => "string"},
"errDescription" => %{"type" => "string"}
}
})
assert response = assert response =
conn conn
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
assert ExJsonSchema.Validator.valid?(schema, response)
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
@ -325,6 +352,8 @@ defmodule BlockScoutWeb.API.RPC.TransactionControllerTest do
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
schema = resolve_schema()
assert ExJsonSchema.Validator.valid?(schema, response)
assert response["message"] =~ "txhash is required" assert response["message"] =~ "txhash is required"
assert response["status"] == "0" assert response["status"] == "0"
assert Map.has_key?(response, "result") assert Map.has_key?(response, "result")
@ -392,11 +421,32 @@ defmodule BlockScoutWeb.API.RPC.TransactionControllerTest do
"txhash" => "#{transaction.hash}" "txhash" => "#{transaction.hash}"
} }
schema =
resolve_schema(%{
"type" => "object",
"properties" => %{
"next_page_params" => %{
"type" => ["object", "null"],
"properties" => %{
"action" => %{"type" => "string"},
"index" => %{"type" => "number"},
"module" => %{"type" => "string"},
"txhash" => %{"type" => "string"}
}
},
"logs" => %{
"type" => "array",
"items" => %{"type" => "object"}
}
}
})
assert response1 = assert response1 =
conn conn
|> get("/api", params1) |> get("/api", params1)
|> json_response(200) |> json_response(200)
assert ExJsonSchema.Validator.valid?(schema, response1)
assert response1["status"] == "1" assert response1["status"] == "1"
assert response1["message"] == "OK" assert response1["message"] == "OK"
@ -414,6 +464,7 @@ defmodule BlockScoutWeb.API.RPC.TransactionControllerTest do
|> get("/api", params2) |> get("/api", params2)
|> json_response(200) |> json_response(200)
assert ExJsonSchema.Validator.valid?(schema, response2)
assert response2["status"] == "1" assert response2["status"] == "1"
assert response2["message"] == "OK" assert response2["message"] == "OK"
assert is_nil(response2["result"]["next_page_params"]) assert is_nil(response2["result"]["next_page_params"])
@ -468,14 +519,70 @@ defmodule BlockScoutWeb.API.RPC.TransactionControllerTest do
"next_page_params" => nil "next_page_params" => nil
} }
schema =
resolve_schema(%{
"type" => "object",
"properties" => %{
"hash" => %{"type" => "string"},
"timeStamp" => %{"type" => "string"},
"blockNumber" => %{"type" => "string"},
"confirmations" => %{"type" => "string"},
"success" => %{"type" => "boolean"},
"from" => %{"type" => "string"},
"to" => %{"type" => "string"},
"value" => %{"type" => "string"},
"input" => %{"type" => "string"},
"gasLimit" => %{"type" => "string"},
"gasUsed" => %{"type" => "string"},
"gasPrice" => %{"type" => "string"},
"logs" => %{
"type" => "array",
"items" => %{
"type" => "object",
"properties" => %{
"address" => %{"type" => "string"},
"data" => %{"type" => "string"},
"topics" => %{
"type" => "array",
"items" => %{"type" => ["string", "null"]}
},
"index" => %{"type" => "string"}
}
}
},
"next_page_params" => %{
"type" => ["object", "null"],
"properties" => %{
"action" => %{"type" => "string"},
"index" => %{"type" => "number"},
"module" => %{"type" => "string"},
"txhash" => %{"type" => "string"}
}
}
}
})
assert response = assert response =
conn conn
|> get("/api", params) |> get("/api", params)
|> json_response(200) |> json_response(200)
assert ExJsonSchema.Validator.valid?(schema, response)
assert response["result"] == expected_result assert response["result"] == expected_result
assert response["status"] == "1" assert response["status"] == "1"
assert response["message"] == "OK" assert response["message"] == "OK"
end end
end end
defp resolve_schema(result \\ %{}) do
%{
"type" => "object",
"properties" => %{
"message" => %{"type" => "string"},
"status" => %{"type" => "string"}
}
}
|> put_in(["properties", "result"], result)
|> ExJsonSchema.Schema.resolve()
end
end end

@ -35,11 +35,23 @@ defmodule EthereumJSONRPC.DecodeError do
%EthereumJSONRPC.DecodeError{request: request, response: response} %EthereumJSONRPC.DecodeError{request: request, response: response}
end end
@request_body_limit 700
@impl Exception @impl Exception
def message(%EthereumJSONRPC.DecodeError{ def message(%EthereumJSONRPC.DecodeError{
request: %EthereumJSONRPC.DecodeError.Request{url: request_url, body: request_body}, request: %EthereumJSONRPC.DecodeError.Request{url: request_url, body: request_body},
response: %EthereumJSONRPC.DecodeError.Response{status_code: response_status_code, body: response_body} response: %EthereumJSONRPC.DecodeError.Response{status_code: response_status_code, body: response_body}
}) do }) do
request_body_binary = IO.iodata_to_binary(request_body)
truncated_request_body =
if byte_size(request_body_binary) < @request_body_limit do
request_body_binary
else
<<result::binary-size(@request_body_limit), _::binary>> = request_body_binary
result
end
""" """
Failed to decode Ethereum JSONRPC response: Failed to decode Ethereum JSONRPC response:
@ -47,7 +59,7 @@ defmodule EthereumJSONRPC.DecodeError do
url: #{request_url} url: #{request_url}
body: #{IO.iodata_to_binary(request_body)} body: #{truncated_request_body}
response: response:

@ -0,0 +1,8 @@
defmodule Explorer.Repo.Migrations.CreateSuggestedIndexes do
use Ecto.Migration
def change do
create_if_not_exists(index(:address_token_balances, [:block_number, :address_hash]))
create_if_not_exists(index(:block_rewards, [:block_hash]))
end
end

@ -1,6 +1,6 @@
%{ %{
"absinthe": {:hex, :absinthe, "1.4.16", "0933e4d9f12652b12115d5709c0293a1bf78a22578032e9ad0dad4efee6b9eb1", [:mix], [{:dataloader, "~> 1.0.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, "absinthe": {:hex, :absinthe, "1.4.16", "0933e4d9f12652b12115d5709c0293a1bf78a22578032e9ad0dad4efee6b9eb1", [:mix], [{:dataloader, "~> 1.0.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
"absinthe_phoenix": {:git, "https://github.com/ayrat555/absinthe_phoenix.git", "4dbb73a25a0935a4d292e63876698e18534d835f", [branch: "master"]}, "absinthe_phoenix": {:git, "https://github.com/ayrat555/absinthe_phoenix.git", "4dbb73a25a0935a4d292e63876698e18534d835f", [branch: "ab-update-plug"]},
"absinthe_plug": {:git, "https://github.com/ayrat555/absinthe_plug.git", "cbe1c170e11e60b3b0146b925a1ce6ec562840ce", [branch: "ab-enable-default-query"]}, "absinthe_plug": {:git, "https://github.com/ayrat555/absinthe_plug.git", "cbe1c170e11e60b3b0146b925a1ce6ec562840ce", [branch: "ab-enable-default-query"]},
"absinthe_relay": {:hex, :absinthe_relay, "1.4.6", "ec0e2288994b388556247cf9601245abec785cdf206d6e844f2992d29de21624", [:mix], [{:absinthe, "~> 1.4.0", [hex: :absinthe, repo: "hexpm", optional: false]}, {:ecto, "~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"}, "absinthe_relay": {:hex, :absinthe_relay, "1.4.6", "ec0e2288994b388556247cf9601245abec785cdf206d6e844f2992d29de21624", [:mix], [{:absinthe, "~> 1.4.0", [hex: :absinthe, repo: "hexpm", optional: false]}, {:ecto, "~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"},
"accept": {:hex, :accept, "0.3.5", "b33b127abca7cc948bbe6caa4c263369abf1347cfa9d8e699c6d214660f10cd1", [:rebar3], [], "hexpm"}, "accept": {:hex, :accept, "0.3.5", "b33b127abca7cc948bbe6caa4c263369abf1347cfa9d8e699c6d214660f10cd1", [:rebar3], [], "hexpm"},
@ -39,6 +39,7 @@
"ex_cldr_numbers": {:hex, :ex_cldr_numbers, "2.6.4", "5b1ac8451f889576bb29dee70412de1170974298727ab944aa4d17e91bdd3472", [:mix], [{:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:ex_cldr, "~> 2.6", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_currencies, "~> 2.3", [hex: :ex_cldr_currencies, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"}, "ex_cldr_numbers": {:hex, :ex_cldr_numbers, "2.6.4", "5b1ac8451f889576bb29dee70412de1170974298727ab944aa4d17e91bdd3472", [:mix], [{:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:ex_cldr, "~> 2.6", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_currencies, "~> 2.3", [hex: :ex_cldr_currencies, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
"ex_cldr_units": {:hex, :ex_cldr_units, "2.5.1", "0e65067a22a7c5146266c313d6333c2700868c32aa6d536f47c6c0d84aac3ac1", [:mix], [{:ex_cldr, "~> 2.6", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_lists, "~> 2.2", [hex: :ex_cldr_lists, repo: "hexpm", optional: false]}, {:ex_cldr_numbers, "~> 2.6", [hex: :ex_cldr_numbers, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"}, "ex_cldr_units": {:hex, :ex_cldr_units, "2.5.1", "0e65067a22a7c5146266c313d6333c2700868c32aa6d536f47c6c0d84aac3ac1", [:mix], [{:ex_cldr, "~> 2.6", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_lists, "~> 2.2", [hex: :ex_cldr_lists, repo: "hexpm", optional: false]}, {:ex_cldr_numbers, "~> 2.6", [hex: :ex_cldr_numbers, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
"ex_doc": {:hex, :ex_doc, "0.19.3", "3c7b0f02851f5fc13b040e8e925051452e41248f685e40250d7e40b07b9f8c10", [:mix], [{:earmark, "~> 1.2", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, "ex_doc": {:hex, :ex_doc, "0.19.3", "3c7b0f02851f5fc13b040e8e925051452e41248f685e40250d7e40b07b9f8c10", [:mix], [{:earmark, "~> 1.2", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
"ex_json_schema": {:hex, :ex_json_schema, "0.6.1", "b57c0588385b8262b80f19d33d9b9b71fcd60d247691abf2635b57a03ec0ad44", [:mix], [], "hexpm"},
"ex_machina": {:hex, :ex_machina, "2.3.0", "92a5ad0a8b10ea6314b876a99c8c9e3f25f4dde71a2a835845b136b9adaf199a", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm"}, "ex_machina": {:hex, :ex_machina, "2.3.0", "92a5ad0a8b10ea6314b876a99c8c9e3f25f4dde71a2a835845b136b9adaf199a", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm"},
"ex_rlp": {:hex, :ex_rlp, "0.5.2", "7f4ce7bd55e543c054ce6d49629b01e9833c3462e3d547952be89865f39f2c58", [:mix], [], "hexpm"}, "ex_rlp": {:hex, :ex_rlp, "0.5.2", "7f4ce7bd55e543c054ce6d49629b01e9833c3462e3d547952be89865f39f2c58", [:mix], [], "hexpm"},
"ex_utils": {:hex, :ex_utils, "0.1.7", "2c133e0bcdc49a858cf8dacf893308ebc05bc5fba501dc3d2935e65365ec0bf3", [:mix], [], "hexpm"}, "ex_utils": {:hex, :ex_utils, "0.1.7", "2c133e0bcdc49a858cf8dacf893308ebc05bc5fba501dc3d2935e65365ec0bf3", [:mix], [], "hexpm"},

Loading…
Cancel
Save