Search improvements: Add new fields, light refactoring (#7784)

* Search improvements: Add new fields, light refactoring

* Fix tests
np-improve-unverified-email-flow
nikitosing 1 year ago committed by GitHub
parent ae8bad1f57
commit dd7b689ed2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 2
      apps/block_scout_web/lib/block_scout_web/chain.ex
  3. 28
      apps/block_scout_web/lib/block_scout_web/views/api/v2/search_view.ex
  4. 2
      apps/block_scout_web/test/block_scout_web/controllers/api/v2/import_controller_test.exs
  5. 28
      apps/block_scout_web/test/block_scout_web/controllers/api/v2/search_controller_test.exs
  6. 146
      apps/explorer/lib/explorer/chain.ex
  7. 10
      apps/explorer/test/explorer/exchange_rates/token_exchange_rates_test.exs
  8. 4
      apps/explorer/test/support/factory.ex

@ -4,6 +4,7 @@
### Features
- [#7784](https://github.com/blockscout/blockscout/pull/7784) - Search improvements: Add new fields, light refactoring
- [#7811](https://github.com/blockscout/blockscout/pull/7811) - Filter addresses before insertion
### Fixes

@ -293,7 +293,7 @@ defmodule BlockScoutWeb.Chain do
with {id, ""} <- Integer.parse(id_string),
{value, ""} <- Decimal.parse(value),
{_id, _value, {fiat_value, ""}} <- {id, value, Decimal.parse(fiat_value_string)} do
[paging_options: %{@default_paging_options | key: {Decimal.round(fiat_value, 16), value, id}}]
[paging_options: %{@default_paging_options | key: {fiat_value, value, id}}]
else
{id, value, :error} ->
[paging_options: %{@default_paging_options | key: {nil, value, id}}]

@ -24,17 +24,22 @@ defmodule BlockScoutWeb.API.V2.SearchView do
"address" => search_result.address_hash,
"token_url" => token_path(Endpoint, :show, search_result.address_hash),
"address_url" => address_path(Endpoint, :show, search_result.address_hash),
"icon_url" => search_result.icon_url
"icon_url" => search_result.icon_url,
"token_type" => search_result.token_type,
"is_smart_contract_verified" => search_result.verified,
"exchange_rate" => search_result.exchange_rate && to_string(search_result.exchange_rate),
"total_supply" => search_result.total_supply
}
end
def prepare_search_result(%{type: address_or_contract} = search_result)
when address_or_contract in ["address", "contract"] do
def prepare_search_result(%{type: address_or_contract_or_label} = search_result)
when address_or_contract_or_label in ["address", "contract", "label"] do
%{
"type" => search_result.type,
"name" => search_result.name,
"address" => search_result.address_hash,
"url" => address_path(Endpoint, :show, search_result.address_hash)
"url" => address_path(Endpoint, :show, search_result.address_hash),
"is_smart_contract_verified" => search_result.verified
}
end
@ -45,7 +50,8 @@ defmodule BlockScoutWeb.API.V2.SearchView do
"type" => search_result.type,
"block_number" => search_result.block_number,
"block_hash" => block_hash,
"url" => block_path(Endpoint, :show, block_hash)
"url" => block_path(Endpoint, :show, block_hash),
"timestamp" => search_result.timestamp
}
end
@ -55,16 +61,8 @@ defmodule BlockScoutWeb.API.V2.SearchView do
%{
"type" => search_result.type,
"tx_hash" => tx_hash,
"url" => transaction_path(Endpoint, :show, tx_hash)
}
end
def prepare_search_result(%{type: "label"} = search_result) do
%{
"type" => search_result.type,
"address" => search_result.address_hash,
"name" => search_result.name,
"url" => address_path(Endpoint, :show, search_result.address_hash)
"url" => transaction_path(Endpoint, :show, tx_hash),
"timestamp" => search_result.timestamp
}
end

@ -24,7 +24,7 @@ defmodule BlockScoutWeb.API.V2.ImportControllerTest do
Application.put_env(:block_scout_web, :sensitive_endpoints_api_key, api_key)
token_address = to_string(insert(:token).contract_address_hash)
token_address = to_string(insert(:token, icon_url: nil).contract_address_hash)
body = %{"iconUrl" => icon_url, "tokenAddress" => token_address}

@ -2,6 +2,7 @@ defmodule BlockScoutWeb.API.V2.SearchControllerTest do
use BlockScoutWeb.ConnCase
alias Explorer.Chain.{Address, Block}
alias Explorer.Repo
setup do
insert(:block)
@ -43,6 +44,7 @@ defmodule BlockScoutWeb.API.V2.SearchControllerTest do
assert item["block_number"] == block.number
assert item["block_hash"] == to_string(block.hash)
assert item["url"] =~ to_string(block.hash)
assert item["timestamp"] == block.timestamp |> to_string() |> String.replace(" ", "T")
end
test "search address", %{conn: conn} do
@ -61,6 +63,7 @@ defmodule BlockScoutWeb.API.V2.SearchControllerTest do
assert item["name"] == name.name
assert item["address"] == Address.checksum(address.hash)
assert item["url"] =~ Address.checksum(address.hash)
assert item["is_smart_contract_verified"] == address.verified
end
test "search contract", %{conn: conn} do
@ -78,6 +81,7 @@ defmodule BlockScoutWeb.API.V2.SearchControllerTest do
assert item["name"] == contract.name
assert item["address"] == Address.checksum(contract.address_hash)
assert item["url"] =~ Address.checksum(contract.address_hash)
assert item["is_smart_contract_verified"] == true
end
test "check pagination", %{conn: conn} do
@ -126,6 +130,11 @@ defmodule BlockScoutWeb.API.V2.SearchControllerTest do
assert item["address"] == Address.checksum(token.contract_address_hash)
assert item["token_url"] =~ Address.checksum(token.contract_address_hash)
assert item["address_url"] =~ Address.checksum(token.contract_address_hash)
assert item["token_type"] == token.type
assert item["is_smart_contract_verified"] == token.contract_address.verified
assert item["exchange_rate"] == (token.fiat_value && to_string(token.fiat_value))
assert item["total_supply"] == to_string(token.total_supply)
assert item["icon_url"] == token.icon_url
end
test "search transaction", %{conn: conn} do
@ -142,6 +151,24 @@ defmodule BlockScoutWeb.API.V2.SearchControllerTest do
assert item["type"] == "transaction"
assert item["tx_hash"] == to_string(tx.hash)
assert item["url"] =~ to_string(tx.hash)
assert item["timestamp"] == nil
end
test "search transaction with timestamp", %{conn: conn} do
tx = :transaction |> insert() |> with_block()
request = get(conn, "/api/v2/search?q=#{tx.hash}")
assert response = json_response(request, 200)
assert Enum.count(response["items"]) == 1
assert response["next_page_params"] == nil
item = Enum.at(response["items"], 0)
assert item["type"] == "transaction"
assert item["tx_hash"] == to_string(tx.hash)
assert item["url"] =~ to_string(tx.hash)
assert item["timestamp"] == Repo.preload(tx, [:block]).block.timestamp |> to_string() |> String.replace(" ", "T")
end
test "search tags", %{conn: conn} do
@ -159,6 +186,7 @@ defmodule BlockScoutWeb.API.V2.SearchControllerTest do
assert item["address"] == Address.checksum(tag.address.hash)
assert item["name"] == tag.tag.display_name
assert item["url"] =~ Address.checksum(tag.address.hash)
assert item["is_smart_contract_verified"] == tag.address.verified
end
end

@ -1486,13 +1486,15 @@ defmodule Explorer.Chain do
def search_label_query(term) do
inner_query =
from(tag in AddressTag,
where: fragment("to_tsvector('english', display_name ) @@ to_tsquery(?)", ^term),
where: fragment("to_tsvector('english', ?) @@ to_tsquery(?)", tag.display_name, ^term),
select: tag
)
from(att in AddressToTag,
inner_join: at in subquery(inner_query),
on: att.tag_id == at.id,
left_join: smart_contract in SmartContract,
on: att.address_hash == smart_contract.address_hash,
select: %{
address_hash: att.address_hash,
tx_hash: fragment("CAST(NULL AS bytea)"),
@ -1503,14 +1505,21 @@ defmodule Explorer.Chain do
holder_count: ^nil,
inserted_at: att.inserted_at,
block_number: 0,
icon_url: nil
icon_url: nil,
token_type: nil,
timestamp: fragment("NULL::timestamp without time zone"),
verified: not is_nil(smart_contract),
exchange_rate: nil,
total_supply: nil
}
)
end
defp search_token_query(term) do
from(token in Token,
where: fragment("to_tsvector('english', symbol || ' ' || name ) @@ to_tsquery(?)", ^term),
left_join: smart_contract in SmartContract,
on: token.contract_address_hash == smart_contract.address_hash,
where: fragment("to_tsvector('english', ? || ' ' || ?) @@ to_tsquery(?)", token.symbol, token.name, ^term),
select: %{
address_hash: token.contract_address_hash,
tx_hash: fragment("CAST(NULL AS bytea)"),
@ -1521,7 +1530,12 @@ defmodule Explorer.Chain do
holder_count: token.holder_count,
inserted_at: token.inserted_at,
block_number: 0,
icon_url: token.icon_url
icon_url: token.icon_url,
token_type: token.type,
timestamp: fragment("NULL::timestamp without time zone"),
verified: not is_nil(smart_contract),
exchange_rate: token.fiat_value,
total_supply: token.total_supply
}
)
end
@ -1530,7 +1544,7 @@ defmodule Explorer.Chain do
from(smart_contract in SmartContract,
left_join: address in Address,
on: smart_contract.address_hash == address.hash,
where: fragment("to_tsvector('english', name) @@ to_tsquery(?)", ^term),
where: fragment("to_tsvector('english', ?) @@ to_tsquery(?)", smart_contract.name, ^term),
select: %{
address_hash: smart_contract.address_hash,
tx_hash: fragment("CAST(NULL AS bytea)"),
@ -1541,7 +1555,12 @@ defmodule Explorer.Chain do
holder_count: ^nil,
inserted_at: address.inserted_at,
block_number: 0,
icon_url: nil
icon_url: nil,
token_type: nil,
timestamp: fragment("NULL::timestamp without time zone"),
verified: true,
exchange_rate: nil,
total_supply: nil
}
)
end
@ -1570,7 +1589,12 @@ defmodule Explorer.Chain do
holder_count: ^nil,
inserted_at: address.inserted_at,
block_number: 0,
icon_url: nil
icon_url: nil,
token_type: nil,
timestamp: fragment("NULL::timestamp without time zone"),
verified: address.verified,
exchange_rate: nil,
total_supply: nil
}
)
@ -1583,6 +1607,8 @@ defmodule Explorer.Chain do
case Chain.string_to_transaction_hash(term) do
{:ok, tx_hash} ->
from(transaction in Transaction,
left_join: block in Block,
on: transaction.block_hash == block.hash,
where: transaction.hash == ^tx_hash,
select: %{
address_hash: fragment("CAST(NULL AS bytea)"),
@ -1594,7 +1620,12 @@ defmodule Explorer.Chain do
holder_count: ^nil,
inserted_at: transaction.inserted_at,
block_number: 0,
icon_url: nil
icon_url: nil,
token_type: nil,
timestamp: block.timestamp,
verified: nil,
exchange_rate: nil,
total_supply: nil
}
)
@ -1618,7 +1649,12 @@ defmodule Explorer.Chain do
holder_count: ^nil,
inserted_at: block.inserted_at,
block_number: block.number,
icon_url: nil
icon_url: nil,
token_type: nil,
timestamp: block.timestamp,
verified: nil,
exchange_rate: nil,
total_supply: nil
}
)
@ -1637,7 +1673,12 @@ defmodule Explorer.Chain do
holder_count: ^nil,
inserted_at: block.inserted_at,
block_number: block.number,
icon_url: nil
icon_url: nil,
token_type: nil,
timestamp: block.timestamp,
verified: nil,
exchange_rate: nil,
total_supply: nil
}
)
@ -1700,7 +1741,9 @@ defmodule Explorer.Chain do
search_results
|> Enum.map(fn result ->
compose_result_checksummed_address_hash(result)
result
|> compose_result_checksummed_address_hash()
|> format_timestamp()
end)
_ ->
@ -1717,80 +1760,13 @@ defmodule Explorer.Chain do
end
end
def search_tx(term) do
case Chain.string_to_transaction_hash(term) do
{:ok, tx_hash} ->
query =
from(transaction in Transaction,
where: transaction.hash == ^tx_hash,
select: %{
link: transaction.hash,
type: "transaction"
}
)
Repo.all(query)
_ ->
[]
end
end
def search_address(term) do
case Chain.string_to_address_hash(term) do
{:ok, address_hash} ->
query =
from(address in Address,
left_join: address_name in Address.Name,
on: address.hash == address_name.address_hash,
where: address.hash == ^address_hash,
select: %{
name: address_name.name,
link: address.hash,
type: "address"
}
)
Repo.all(query)
_ ->
[]
end
end
def search_block(term) do
case Chain.string_to_block_hash(term) do
{:ok, block_hash} ->
query =
from(block in Block,
where: block.hash == ^block_hash,
select: %{
link: block.hash,
block_number: block.number,
type: "block"
}
)
Repo.all(query)
_ ->
case Integer.parse(term) do
{block_number, _} ->
query =
from(block in Block,
where: block.number == ^block_number,
select: %{
link: block.hash,
block_number: block.number,
type: "block"
}
)
Repo.all(query)
_ ->
[]
end
# For some reasons timestamp for blocks and txs returns as ~N[2023-06-25 19:39:47.339493]
defp format_timestamp(result) do
if result.timestamp do
result
|> Map.put(:timestamp, DateTime.from_naive!(result.timestamp, "Etc/UTC"))
else
result
end
end

@ -36,7 +36,7 @@ defmodule Explorer.TokenExchangeRatesTest do
[_token_with_no_exchange_rate | tokens] =
for _ <- 0..4 do
insert(:token)
insert(:token, fiat_value: nil)
end
coins_list =
@ -101,7 +101,7 @@ defmodule Explorer.TokenExchangeRatesTest do
[_token_with_no_exchange_rate | _tokens] =
for _ <- 0..4 do
insert(:token)
insert(:token, fiat_value: nil)
end
Bypass.expect_once(bypass, "GET", "/coins/list", fn conn ->
@ -126,7 +126,7 @@ defmodule Explorer.TokenExchangeRatesTest do
[_token_with_no_exchange_rate | tokens] =
for _ <- 0..4 do
insert(:token)
insert(:token, fiat_value: nil)
end
coins_list =
@ -181,7 +181,7 @@ defmodule Explorer.TokenExchangeRatesTest do
[_token_with_no_exchange_rate | _tokens] =
for _ <- 0..4 do
insert(:token)
insert(:token, fiat_value: nil)
end
Bypass.expect_once(bypass, "GET", "/coins/list", fn conn ->
@ -206,7 +206,7 @@ defmodule Explorer.TokenExchangeRatesTest do
[_token_with_no_exchange_rate | tokens] =
for _ <- 0..4 do
insert(:token)
insert(:token, fiat_value: nil)
end
coins_list =

@ -654,7 +654,9 @@ defmodule Explorer.Factory do
decimals: 18,
contract_address: build(:address),
type: "ERC-20",
cataloged: true
cataloged: true,
icon_url: sequence("https://example.com/icon"),
fiat_value: 10.1
}
end

Loading…
Cancel
Save