Skip to content

Commit

Permalink
feat: allow filtering transactions count by scope (#798)
Browse files Browse the repository at this point in the history
* feat: allow filtering transactions count by scope

refs #752

* chore: improve /txs/count filters error message
  • Loading branch information
sborrazas committed Jul 25, 2022
1 parent 1476e85 commit cae1dc3
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 4 deletions.
18 changes: 18 additions & 0 deletions lib/ae_mdw/txs.ex
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,24 @@ defmodule AeMdw.Txs do

@type_spend_tx "SpendTx"

@spec count(state(), range(), map()) :: {:ok, non_neg_integer()} | {:error, Error.t()}
def count(_state, nil, %{"type" => _tx_type}),
do: {:error, ErrInput.Query.exception(value: "counting by type not yet supported")}

def count(state, nil, params) when map_size(params) == 0,
do: {:ok, DbUtil.last_txi!(state)}

def count(_state, {:txi, first_txi..last_txi}, params) when map_size(params) == 0,
do: {:ok, last_txi - first_txi + 1}

def count(state, {:gen, first_gen..last_gen}, params) when map_size(params) == 0,
do: {:ok, DbUtil.gen_to_txi(state, last_gen + 1) - DbUtil.gen_to_txi(state, first_gen)}

def count(_state, _range, _params),
do:
{:error,
ErrInput.Query.exception(value: "can't query by multiple filters and/or invalid filters")}

@spec fetch_txs(
State.t(),
pagination(),
Expand Down
9 changes: 6 additions & 3 deletions lib/ae_mdw_web/controllers/tx_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ defmodule AeMdwWeb.TxController do
alias AeMdw.Validate
alias AeMdw.Db.Model
alias AeMdw.Db.State
alias AeMdw.Db.Util, as: DbUtil
alias AeMdw.Txs
alias AeMdwWeb.FallbackController
alias AeMdwWeb.Plugs.PaginatedPlug
Expand Down Expand Up @@ -63,8 +62,12 @@ defmodule AeMdwWeb.TxController do
end

@spec count(Conn.t(), map()) :: Conn.t()
def count(%Conn{assigns: %{state: state}} = conn, _req),
do: conn |> json(DbUtil.last_txi!(state))
def count(%Conn{assigns: %{state: state, scope: scope, query: query}} = conn, _params) do
case Txs.count(state, scope, query) do
{:ok, count} -> json(conn, count)
{:error, reason} -> {:error, reason}
end
end

@spec count_id(Conn.t(), map()) :: Conn.t()
def count_id(%Conn{assigns: %{state: state}} = conn, %{"id" => id}),
Expand Down
5 changes: 4 additions & 1 deletion lib/ae_mdw_web/plugs/paginated_plug.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ defmodule AeMdwWeb.Plugs.PaginatedPlug do

@default_scope nil

@pagination_params ~w(limit cursor rev direction scope tx_hash expand)

@spec init(opts()) :: opts()
def init(opts), do: opts

@spec call(Conn.t(), opts()) :: Conn.t()
def call(%Conn{params: params} = conn, opts) do
def call(%Conn{params: params, query_params: query_params} = conn, opts) do
with {:ok, direction, scope} <- extract_direction_and_scope(params),
{:ok, limit} <- extract_limit(params),
{:ok, is_reversed?} <- extract_is_reversed(params),
Expand All @@ -39,6 +41,7 @@ defmodule AeMdwWeb.Plugs.PaginatedPlug do
|> assign(:order_by, order_by)
|> assign(:scope, scope)
|> assign(:offset, {limit, page})
|> assign(:query, Map.drop(query_params, @pagination_params))
else
{:error, error_msg} ->
conn
Expand Down
37 changes: 37 additions & 0 deletions test/ae_mdw_web/controllers/tx_controller_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ defmodule AeMdwWeb.TxControllerTest do

import Mock

alias AeMdw.Db.Model
alias AeMdw.Db.Store
alias AeMdw.Db.Util
alias AeMdw.TestSamples, as: TS

require Model

describe "txs" do
test "it returns 400 when no direction specified", %{conn: conn} do
Expand All @@ -25,4 +30,36 @@ defmodule AeMdwWeb.TxControllerTest do
assert %{"error" => _error_msg} = conn |> get("/tx/#{tx_hash}") |> json_response(404)
end
end

describe "count" do
test "it returns all tx count by default", %{conn: conn, store: store} do
tx = Model.tx(index: tx_index) = TS.tx(0)
store = Store.put(store, Model.Tx, tx)

assert ^tx_index =
conn
|> with_store(store)
|> get("/txs/count")
|> json_response(200)
end

test "it returns the difference between first and last txi", %{conn: conn} do
first_txi = 600
last_txi = 500

assert 101 =
conn
|> get("/txs/count", scope: "txi:#{first_txi}-#{last_txi}")
|> json_response(200)
end

test "it returns error when filtering by type", %{conn: conn} do
error_msg = "invalid query: counting by type not yet supported"

assert %{"error" => ^error_msg} =
conn
|> get("/txs/count", type: "spend")
|> json_response(400)
end
end
end

0 comments on commit cae1dc3

Please sign in to comment.