Skip to content

Commit

Permalink
Merge pull request #1234 from Naupio/issue-1231
Browse files Browse the repository at this point in the history
feat: add search api of graphql
  • Loading branch information
Naupio authored Dec 28, 2022
2 parents ffccc17 + 48fb303 commit 9d51236
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 6 deletions.
10 changes: 10 additions & 0 deletions docs/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,16 @@ type Address {
""".bit alias."""
bit_alias: String
}
type Address {
"""ETH address hash"""
eth_address: HashFull

"""The address cached token transfer count."""
token_transfer_count: Int

""".bit alias."""
bit_alias: String
}

input BlockInput {
hash: HashFull
Expand Down
3 changes: 2 additions & 1 deletion lib/godwoken_explorer/chain.ex
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,8 @@ defmodule GodwokenExplorer.Chain do
end

@spec from_param(String.t()) ::
{:ok, Address.t() | Block.t() | Transaction.t()} | {:error, :not_found}
{:ok, Address.t() | Block.t() | Transaction.t() | Account.t() | UDT.t()}
| {:error, :not_found}
def from_param(param)

def from_param("0x" <> number_string = param)
Expand Down
4 changes: 2 additions & 2 deletions lib/godwoken_explorer/graphql/resolovers/account.ex
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ defmodule GodwokenExplorer.Graphql.Resolvers.Account do
{:ok, account}

nil ->
address = Address.find_or_insert_from_hash(address)
{:ok, address}
Address.find_or_insert_from_hash(address)
# {:ok, address}
end
end
end
Expand Down
48 changes: 47 additions & 1 deletion lib/godwoken_explorer/graphql/resolovers/search.ex
Original file line number Diff line number Diff line change
@@ -1,9 +1,55 @@
defmodule GodwokenExplorer.Graphql.Resolvers.Search do
alias GodwokenExplorer.UDT
alias GodwokenExplorer.{UDT, Transaction, Block, Address, Account}
alias GodwokenExplorer.Chain
import Ecto.Query

import GodwokenExplorer.Graphql.Resolvers.Common, only: [paginate_query: 3]

def search_keyword(_parent, %{input: %{keyword: keyword}} = _args, _resolution) do
do_search_keyword(keyword)
end

def do_search_keyword(keyword) do
keyword
|> String.trim()
|> Chain.from_param()
|> case do
{:ok, item} ->
return = process_result(item)
{:ok, return}

{:error, :not_found} ->
{:error, :not_found}
end
end

defp process_result(%Account{} = item) do
id =
case item.type do
:eth_user -> item.eth_address
:polyjuice_contract -> item.eth_address
_ -> item.script_hash
end

%{type: :account, id: id}
end

defp process_result(%Address{} = item) do
%{type: :address, id: item.eth_address}
end

defp process_result(%Block{} = item) do
%{type: :block, id: item.number}
end

defp process_result(%Transaction{} = item) do
%{type: :transaction, id: item.eth_hash || item.hash}
end

defp process_result(%UDT{} = item) do
%{type: :udt, id: item.id}
end

def search_udt(_parent, %{input: input} = _args, _resolution) do
return =
from(u in UDT)
Expand Down
35 changes: 34 additions & 1 deletion lib/godwoken_explorer/graphql/types/search.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@ defmodule GodwokenExplorer.Graphql.Types.Search do
alias GodwokenExplorer.Graphql.Resolvers, as: Resolvers

object :search_querys do
@desc """
keyword can be: udt name| account eth_address | address | transaction hash | block number
```graphql
query {
search_keyword(input: { keyword: "UDT"}){
type
id
}
}
```
"""
field :search_keyword, :search_result do
arg(:input, non_null(:search_keyword_input))
resolve(&Resolvers.Search.search_keyword/3)
end

@desc """
```graphql
search_udt example:
Expand Down Expand Up @@ -52,6 +68,11 @@ defmodule GodwokenExplorer.Graphql.Types.Search do
end
end

object :search_result do
field(:type, :search_type)
field(:id, :string)
end

object :paginate_search_udts do
field(:entries, list_of(:search_udt_result))
field(:metadata, :paginate_metadata)
Expand Down Expand Up @@ -80,7 +101,19 @@ defmodule GodwokenExplorer.Graphql.Types.Search do

field(:type, :udt_type, description: " Bridge means from layer1;Native means layer2 contract.")

field :eth_type, :eth_type, description: "EVM token type."
field(:eth_type, :eth_type, description: "EVM token type.")
end

enum :search_type do
value(:address)
value(:block)
value(:transaction)
value(:udt)
value(:account)
end

input_object :search_keyword_input do
field(:keyword, non_null(:string))
end

input_object :search_udt_input do
Expand Down
156 changes: 155 additions & 1 deletion test/graphql/search_test.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule GodwokenExplorer.Graphql.SearchTest do
use GodwokenExplorerWeb.ConnCase

import GodwokenExplorer.Factory, only: [insert: 2]
import GodwokenExplorer.Factory, only: [insert: 1, insert: 2, insert!: 1]

setup do
for _ <- 1..10 do
Expand All @@ -15,6 +15,160 @@ defmodule GodwokenExplorer.Graphql.SearchTest do
[second_last_udt: second_last_udt, last_udt: last_udt]
end

test "graphql: search_keyword with udt", %{conn: conn} do
# exact matching
name = "SSS_UDT"
fuzzy_name = "%UDT%"
insert(:native_udt, eth_type: :erc721, name: name)
insert(:native_udt, eth_type: :erc1155)

query = search_keyword(name)

conn =
post(conn, "/graphql", %{
"query" => query,
"variables" => %{}
})

assert match?(
%{
"data" => %{
"search_keyword" => %{
"type" => "UDT"
}
}
},
json_response(conn, 200)
)

# more than one matching
query = search_keyword(fuzzy_name)

conn =
post(conn, "/graphql", %{
"query" => query,
"variables" => %{}
})

assert match?(
%{
"data" => %{
"search_keyword" => nil
},
"errors" => _
},
json_response(conn, 200)
)

## polyjuice contract account
account = insert!(:polyjuice_contract_account)
keyword = to_string(account.eth_address)
query = search_keyword(keyword)

conn =
post(conn, "/graphql", %{
"query" => query,
"variables" => %{}
})

assert match?(
%{
"data" => %{
"search_keyword" => %{
"type" => "ACCOUNT"
}
}
},
json_response(conn, 200)
)

## not exist address
keyword = "0xbFbE23681D99A158f632e64A31288946770c7A9e"
query = search_keyword(keyword)

conn =
post(conn, "/graphql", %{
"query" => query,
"variables" => %{}
})

assert match?(
%{
"data" => %{
"search_keyword" => %{
"type" => "ADDRESS"
}
}
},
json_response(conn, 200)
)

block = insert(:block)
from_account = insert!(:user)
to_account = insert!(:polyjuice_contract_account)

transaction =
insert(:transaction,
from_account: from_account,
to_account: to_account,
block: block,
block_number: block.number
)

## test block keyword
keyword = block.number |> to_string()
query = search_keyword(keyword)

conn =
post(conn, "/graphql", %{
"query" => query,
"variables" => %{}
})

assert match?(
%{
"data" => %{
"search_keyword" => %{
"type" => "BLOCK"
}
}
},
json_response(conn, 200)
)

## test transaction keyword
keyword = transaction.hash |> to_string()
query = search_keyword(keyword)

conn =
post(conn, "/graphql", %{
"query" => query,
"variables" => %{}
})

assert match?(
%{
"data" => %{
"search_keyword" => %{
"type" => "TRANSACTION"
}
}
},
json_response(conn, 200)
)
end

defp search_keyword(keyword) do
"""
query {
search_keyword(input: { keyword: "#{keyword}"}){
type
id
}
}
"""
end

test "graphql: search_udt ", %{conn: conn} do
fuzzy_name = "%UD%"

Expand Down

0 comments on commit 9d51236

Please sign in to comment.