Skip to content

Commit

Permalink
chore: restructure v3 routes and remove tx_index (#1695)
Browse files Browse the repository at this point in the history
  • Loading branch information
sborrazas committed Mar 12, 2024
1 parent daffbf0 commit bc10039
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 50 deletions.
2 changes: 1 addition & 1 deletion docs/swagger_v3/activities.spec.yaml
Expand Up @@ -190,7 +190,7 @@ schemas:
payload:
type: object
oneOf:
- $ref: '#/components/schemas/Tx'
- $ref: '#/components/schemas/Transaction'
- $ref: '#/components/schemas/Aex9TransferEvent'
- $ref: '#/components/schemas/Aex141TransferEvent'
- $ref: '#/components/schemas/InternalContractCallEvent'
Expand Down
4 changes: 2 additions & 2 deletions docs/swagger_v3/blocks.spec.yaml
Expand Up @@ -302,7 +302,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/NotFoundResponse'
/micro-blocks/{hash}/txs:
/micro-blocks/{hash}/transactions:
get:
deprecated: false
description: Get a micro block transactions
Expand All @@ -327,7 +327,7 @@ paths:
data:
type: array
items:
$ref: '#/components/schemas/Tx'
$ref: '#/components/schemas/Transaction'
- $ref: '#/components/schemas/PaginatedResponse'
'400':
description: Bad request
Expand Down
2 changes: 1 addition & 1 deletion docs/swagger_v3/transactions.spec.yaml
Expand Up @@ -179,7 +179,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/transactions/{hash_or_index}:
/transactions/{hash}:
get:
deprecated: false
description: Get a single transaction.
Expand Down
67 changes: 37 additions & 30 deletions lib/ae_mdw/txs.ex
Expand Up @@ -20,6 +20,7 @@ defmodule AeMdw.Txs do
alias AeMdw.Error.Input, as: ErrInput
alias AeMdw.Log
alias AeMdw.Node
alias AeMdw.Node.Db
alias AeMdw.Util
alias AeMdw.Validate

Expand All @@ -38,13 +39,14 @@ defmodule AeMdw.Txs do
ids: term()
}
| %{}
@type add_spendtx_details?() :: boolean()
@type opt() :: {:add_spendtx_details?, boolean()} | {:render_v3?, boolean()}
@type opts() :: [opt()]

@typep state() :: State.t()
@typep pagination :: Collection.direction_limit()
@typep range :: {:gen, Range.t()} | {:txi, Range.t()} | nil
@typep page_cursor() :: Collection.pagination_cursor()
@typep pubkey :: Node.Db.pubkey()
@typep pubkey :: Db.pubkey()
@typep tx_type :: Node.tx_type()

@table Tx
Expand Down Expand Up @@ -156,11 +158,11 @@ defmodule AeMdw.Txs do
range(),
query(),
cursor() | nil,
add_spendtx_details?()
opts()
) :: {:ok, {page_cursor(), [tx()], page_cursor()}} | {:error, Error.t()}
def fetch_txs(state, pagination, range, query, cursor, add_spendtx_details?) do
def fetch_txs(state, pagination, range, query, cursor, opts) do
with {:ok, streamer} <- txs_streamer(state, range, query, cursor) do
{:ok, paginate_txs(state, streamer, pagination, add_spendtx_details?)}
{:ok, paginate_txs(state, streamer, pagination, opts)}
end
end

Expand All @@ -172,11 +174,11 @@ defmodule AeMdw.Txs do
end
end

@spec fetch_micro_block_txs(state(), binary(), query(), pagination(), cursor() | nil) ::
@spec fetch_micro_block_txs(state(), binary(), query(), pagination(), cursor() | nil, opts()) ::
{:ok, {page_cursor(), [tx()], page_cursor()}} | {:error, Error.t()}
def fetch_micro_block_txs(state, hash, query, pagination, cursor) do
def fetch_micro_block_txs(state, hash, query, pagination, cursor, opts \\ []) do
with {:ok, streamer} <- micro_block_txs_streamer(state, hash, query, cursor) do
{:ok, paginate_txs(state, streamer, pagination)}
{:ok, paginate_txs(state, streamer, pagination, opts)}
end
end

Expand All @@ -190,14 +192,8 @@ defmodule AeMdw.Txs do
#
# Streams txs of a microblock
#
defp paginate_txs(state, streamer, pagination, add_spendtx_details? \\ true) do
Collection.paginate(
streamer,
pagination,
&fetch!(state, &1, add_spendtx_details?),
&serialize_cursor/1
)
end
defp paginate_txs(state, streamer, pagination, opts),
do: Collection.paginate(streamer, pagination, &fetch!(state, &1, opts), &serialize_cursor/1)

defp micro_block_txs_streamer(state, hash, query, cursor \\ nil) do
with {:ok, height, mbi} <- DbUtil.micro_block_height_index(state, hash),
Expand Down Expand Up @@ -505,29 +501,26 @@ defmodule AeMdw.Txs do
{:error, ErrInput.TxField.exception(value: ":#{Enum.join(invalid_field, ".")}")}
end

@spec fetch!(State.t(), txi(), add_spendtx_details?()) :: tx()
def fetch!(state, txi, add_spendtx_details? \\ false) do
{:ok, tx} = fetch(state, txi, add_spendtx_details?)
@spec fetch!(State.t(), txi(), opts()) :: tx()
def fetch!(state, txi, opts \\ []) do
{:ok, tx} = fetch(state, txi, opts)

tx
end

@spec fetch(State.t(), txi() | tx_hash(), add_spendtx_details?()) ::
{:ok, tx()} | {:error, Error.t()}
def fetch(state, tx_hash, add_spendtx_details? \\ true)

def fetch(state, tx_hash, add_spendtx_details?) when is_binary(tx_hash) do
@spec fetch(State.t(), txi() | tx_hash(), opts()) :: {:ok, tx()} | {:error, Error.t()}
def fetch(state, tx_hash, opts) when is_binary(tx_hash) do
encoded_tx_hash = :aeser_api_encoder.encode(:tx_hash, tx_hash)

with mb_hash when is_binary(mb_hash) <- :aec_db.find_tx_location(tx_hash),
{:ok, mb_height} <- Node.Db.find_block_height(mb_hash) do
{:ok, mb_height} <- Db.find_block_height(mb_hash) do
state
|> Blocks.fetch_txis_from_gen(mb_height)
|> Stream.map(&State.fetch!(state, @table, &1))
|> Enum.find_value(
{:error, ErrInput.NotFound.exception(value: encoded_tx_hash)},
fn
Model.tx(id: ^tx_hash) = tx -> {:ok, render(state, tx, add_spendtx_details?)}
Model.tx(id: ^tx_hash) = tx -> {:ok, render(state, tx, opts)}
_tx -> nil
end
)
Expand All @@ -537,23 +530,37 @@ defmodule AeMdw.Txs do
end
end

def fetch(state, txi, add_spendtx_details?) do
def fetch(state, txi, opts) do
case State.get(state, @table, txi) do
{:ok, tx} -> {:ok, render(state, tx, add_spendtx_details?)}
{:ok, tx} -> {:ok, render(state, tx, opts)}
:not_found -> {:error, ErrInput.NotFound.exception(value: txi)}
end
end

defp render(state, tx, add_spendtx_details?) do
defp render(state, tx, opts) do
if Keyword.get(opts, :render_v3?, false) do
render_v3(state, tx)
else
render_v2(state, tx, opts)
end
end

defp render_v2(state, tx, opts) do
rendered_tx = Format.to_map(state, tx)

if add_spendtx_details? do
if Keyword.get(opts, :add_spendtx_details?, false) do
maybe_add_spendtx_details(state, rendered_tx)
else
rendered_tx
end
end

defp render_v3(state, tx) do
state
|> render_v2(tx, add_spendtx_details?: true)
|> Map.delete("tx_index")
end

defp maybe_add_spendtx_details(state, %{"tx" => block_tx, "tx_index" => tx_index} = block) do
recipient_id = block_tx["recipient_id"] || ""

Expand Down
59 changes: 54 additions & 5 deletions lib/ae_mdw_web/controllers/tx_controller.ex
Expand Up @@ -26,7 +26,7 @@ defmodule AeMdwWeb.TxController do
@spec tx(Conn.t(), map()) :: Conn.t()
def tx(%Conn{assigns: %{state: state}} = conn, %{"hash" => hash}) do
with {:ok, tx_hash} <- Validate.id(hash),
{:ok, tx} <- Txs.fetch(state, tx_hash) do
{:ok, tx} <- Txs.fetch(state, tx_hash, add_spendtx_details?: true, render_v3?: true) do
format_json(conn, tx)
end
end
Expand All @@ -38,7 +38,28 @@ defmodule AeMdwWeb.TxController do

:error ->
with {:ok, tx_hash} <- Validate.id(hash_or_index),
{:ok, tx} <- Txs.fetch(state, tx_hash) do
{:ok, tx} <- Txs.fetch(state, tx_hash, add_spendtx_details?: true, render_v3?: true) do
format_json(conn, tx)
end
end
end

@spec tx_v2(Conn.t(), map()) :: Conn.t()
def tx_v2(%Conn{assigns: %{state: state}} = conn, %{"hash" => hash}) do
with {:ok, tx_hash} <- Validate.id(hash),
{:ok, tx} <- Txs.fetch(state, tx_hash, add_spendtx_details?: true) do
format_json(conn, tx)
end
end

def tx_v2(%Conn{assigns: %{state: state}} = conn, %{"hash_or_index" => hash_or_index} = params) do
case Util.parse_int(hash_or_index) do
{:ok, _txi} ->
txi(conn, Map.put(params, "index", hash_or_index))

:error ->
with {:ok, tx_hash} <- Validate.id(hash_or_index),
{:ok, tx} <- Txs.fetch(state, tx_hash, add_spendtx_details?: true) do
format_json(conn, tx)
end
end
Expand All @@ -47,19 +68,33 @@ defmodule AeMdwWeb.TxController do
@spec txi(Conn.t(), map()) :: Conn.t()
def txi(%Conn{assigns: %{state: state}} = conn, %{"index" => index}) do
with {:ok, txi} <- Validate.nonneg_int(index),
{:ok, tx} <- Txs.fetch(state, txi) do
{:ok, tx} <- Txs.fetch(state, txi, add_spendtx_details?: true) do
format_json(conn, tx)
end
end

@spec txs(Conn.t(), map()) :: Conn.t()
def txs(%Conn{assigns: assigns, query_params: query_params} = conn, params) do
%{state: state, pagination: pagination, cursor: cursor, scope: scope} = assigns
add_spendtx_details? = Map.has_key?(params, "account")
opts = [add_spendtx_details?: Map.has_key?(params, "account")]

with {:ok, query} <- extract_query(query_params),
{:ok, paginated_txs} <-
Txs.fetch_txs(state, pagination, scope, query, cursor, add_spendtx_details?) do
Txs.fetch_txs(state, pagination, scope, query, cursor, [{:render_v3?, true} | opts]) do
WebUtil.render(conn, paginated_txs)
else
{:error, reason} when is_binary(reason) -> {:error, ErrInput.Query.exception(value: reason)}
{:error, reason} -> {:error, reason}
end
end

@spec txs_v2(Conn.t(), map()) :: Conn.t()
def txs_v2(%Conn{assigns: assigns, query_params: query_params} = conn, params) do
%{state: state, pagination: pagination, cursor: cursor, scope: scope} = assigns
opts = [add_spendtx_details?: Map.has_key?(params, "account")]

with {:ok, query} <- extract_query(query_params),
{:ok, paginated_txs} <- Txs.fetch_txs(state, pagination, scope, query, cursor, opts) do
WebUtil.render(conn, paginated_txs)
else
{:error, reason} when is_binary(reason) -> {:error, ErrInput.Query.exception(value: reason)}
Expand Down Expand Up @@ -117,6 +152,20 @@ defmodule AeMdwWeb.TxController do
}) do
%{state: state, pagination: pagination, cursor: cursor, scope: scope} = assigns

with :ok <- validate_without_scope(scope),
{:ok, query} <- extract_query(query_params),
{:ok, paginated_txs} <-
Txs.fetch_micro_block_txs(state, hash, query, pagination, cursor, render_v3?: true) do
WebUtil.render(conn, paginated_txs)
end
end

@spec micro_block_txs_v2(Conn.t(), map()) :: Conn.t()
def micro_block_txs_v2(%Conn{assigns: assigns, query_params: query_params} = conn, %{
"hash" => hash
}) do
%{state: state, pagination: pagination, cursor: cursor, scope: scope} = assigns

with :ok <- validate_without_scope(scope),
{:ok, query} <- extract_query(query_params),
{:ok, paginated_txs} <- Txs.fetch_micro_block_txs(state, hash, query, pagination, cursor) do
Expand Down
14 changes: 7 additions & 7 deletions lib/ae_mdw_web/router.ex
Expand Up @@ -54,7 +54,7 @@ defmodule AeMdwWeb.Router do
get "/key-blocks/:hash_or_kbi", BlockController, :key_block
get "/key-blocks/:hash_or_kbi/micro-blocks", BlockController, :key_block_micro_blocks
get "/micro-blocks/:hash", BlockController, :micro_block
get "/micro-blocks/:hash/txs", TxController, :micro_block_txs
get "/micro-blocks/:hash/transactions", TxController, :micro_block_txs

get "/transactions", TxController, :txs
get "/transactions/:hash", TxController, :tx
Expand Down Expand Up @@ -135,10 +135,10 @@ defmodule AeMdwWeb.Router do
get "/key-blocks/:hash_or_kbi", BlockController, :key_block
get "/key-blocks/:hash_or_kbi/micro-blocks", BlockController, :key_block_micro_blocks
get "/micro-blocks/:hash", BlockController, :micro_block
get "/micro-blocks/:hash/txs", TxController, :micro_block_txs
get "/micro-blocks/:hash/txs", TxController, :micro_block_txs_v2

get "/txs", TxController, :txs
get "/txs/:hash_or_index", TxController, :tx
get "/txs", TxController, :txs_v2
get "/txs/:hash_or_index", TxController, :tx_v2

get "/entities/:id", ActiveEntityController, :active_entities

Expand Down Expand Up @@ -214,10 +214,10 @@ defmodule AeMdwWeb.Router do
get "/blocki/:kbi", BlockController, :blocki
get "/blocki/:kbi/:mbi", BlockController, :blocki

get "/tx/:hash_or_index", TxController, :tx
get "/tx/:hash_or_index", TxController, :tx_v2
get "/txi/:index", TxController, :txi
get "/txs/:direction", TxController, :txs
get "/txs/:scope_type/:range", TxController, :txs
get "/txs/:direction", TxController, :txs_v2
get "/txs/:scope_type/:range", TxController, :txs_v2

get "/name/auction/:id", NameController, :auction_v2
get "/name/pointers/:id", NameController, :pointers
Expand Down
2 changes: 1 addition & 1 deletion lib/ae_mdw_web/websocket/broadcaster.ex
Expand Up @@ -182,7 +182,7 @@ defmodule AeMdwWeb.Websocket.Broadcaster do

defp serialize_tx(tx, {:state, state}) do
tx_hash = :aetx_sign.hash(tx)
Txs.fetch(state, tx_hash, true)
Txs.fetch(state, tx_hash, add_spendtx_details?: true)
end

defp serialize_tx(tx, {:block, block}) do
Expand Down
4 changes: 1 addition & 3 deletions test/ae_mdw_web/helpers/json_helper_test.exs
Expand Up @@ -17,11 +17,9 @@ defmodule AeMdwWeb.Helpers.JSONHelperTest do
} do
assert [%{"a" => "1"}] =
conn
|> put_query(%{"int-as-string" => "true"})
|> Conn.assign(:int_as_string, true)
|> JSONHelper.format_json([%{a: 1}])
|> json_response(200)
end
end

defp put_query(conn, query), do: %Conn{conn | params: query, query_params: query}
end

0 comments on commit bc10039

Please sign in to comment.