Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add functional error responses and tests cases for it #1571

Merged
merged 2 commits into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions lib/ae_mdw/aex9.ex
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ defmodule AeMdw.Aex9 do

@type amounts :: map()

@spec fetch_balances(State.t(), pubkey(), boolean()) :: amounts()
@spec fetch_balances(State.t(), pubkey(), boolean()) :: {:ok, amounts()} | {:error, Error.t()}
def fetch_balances(state, contract_pk, top?) do
if top? do
{amounts, _height} = Db.aex9_balances!(contract_pk, true)
Expand All @@ -55,14 +55,16 @@ defmodule AeMdw.Aex9 do
end)
|> case do
amounts when map_size(amounts) == 0 ->
raise ErrInput.Aex9BalanceNotAvailable,
value: "contract #{encode_contract(contract_pk)}"
{:error,
ErrInput.Aex9BalanceNotAvailable.exception(
value: "contract #{encode_contract(contract_pk)}"
)}

%{{:address, <<>>} => nil} = amounts when map_size(amounts) == 1 ->
%{}
{:ok, %{}}

amounts ->
Map.delete(amounts, {:address, <<>>})
{:ok, Map.delete(amounts, {:address, <<>>})}
end
end
end
Expand Down
44 changes: 23 additions & 21 deletions lib/ae_mdw/aexn_transfers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ defmodule AeMdw.AexnTransfers do
alias AeMdw.Collection
alias AeMdw.Db.Model
alias AeMdw.Db.State
alias AeMdw.Error
alias AeMdw.Error.Input, as: ErrInput
alias AeMdw.Util

Expand Down Expand Up @@ -43,7 +44,7 @@ defmodule AeMdw.AexnTransfers do
pagination(),
cursor() | nil
) ::
contract_paginated_transfers()
{:ok, contract_paginated_transfers()} | {:error, Error.t()}
def fetch_contract_transfers(state, contract_txi, {filter_by, account_pk}, pagination, cursor) do
table =
if filter_by == :from,
Expand All @@ -61,7 +62,7 @@ defmodule AeMdw.AexnTransfers do
end

@spec fetch_sender_transfers(State.t(), aexn_type(), pubkey(), pagination(), cursor() | nil) ::
account_paginated_transfers()
{:ok, account_paginated_transfers()} | {:error, Error.t()}
def fetch_sender_transfers(state, aexn_type, sender_pk, pagination, cursor) do
paginate_transfers(
state,
Expand All @@ -74,7 +75,7 @@ defmodule AeMdw.AexnTransfers do
end

@spec fetch_recipient_transfers(State.t(), aexn_type(), pubkey(), pagination(), cursor() | nil) ::
account_paginated_transfers()
{:ok, account_paginated_transfers()} | {:error, Error.t()}
def fetch_recipient_transfers(state, aexn_type, recipient_pk, pagination, cursor) do
paginate_transfers(
state,
Expand All @@ -94,7 +95,7 @@ defmodule AeMdw.AexnTransfers do
pagination(),
cursor() | nil
) ::
pair_paginated_transfers()
{:ok, pair_paginated_transfers()} | {:error, Error.t()}
def fetch_pair_transfers(
state,
aexn_type,
Expand Down Expand Up @@ -124,20 +125,21 @@ defmodule AeMdw.AexnTransfers do
cursor,
account_pk_or_pair_pks
) do
cursor_key = deserialize_cursor(cursor)

key_boundary = key_boundary(aexn_type_or_txi, account_pk_or_pair_pks)

{prev_cursor_key, transfer_keys, next_cursor_key} =
state
|> build_streamer(table, cursor_key, key_boundary)
|> Collection.paginate(pagination)

{
serialize_cursor(prev_cursor_key),
transfer_keys,
serialize_cursor(next_cursor_key)
}
with {:ok, cursor_key} <- deserialize_cursor(cursor) do
key_boundary = key_boundary(aexn_type_or_txi, account_pk_or_pair_pks)

{prev_cursor_key, transfer_keys, next_cursor_key} =
state
|> build_streamer(table, cursor_key, key_boundary)
|> Collection.paginate(pagination)

{:ok,
{
serialize_cursor(prev_cursor_key),
transfer_keys,
serialize_cursor(next_cursor_key)
}}
end
end

defp build_streamer(state, table, cursor_key, key_boundary) do
Expand All @@ -151,7 +153,7 @@ defmodule AeMdw.AexnTransfers do
defp serialize_cursor({cursor, is_reversed?}),
do: {cursor |> :erlang.term_to_binary() |> Base.encode64(), is_reversed?}

defp deserialize_cursor(nil), do: nil
defp deserialize_cursor(nil), do: {:ok, nil}

defp deserialize_cursor(<<cursor_bin64::binary>>) do
with {:ok, cursor_bin} <- Base.decode64(cursor_bin64),
Expand All @@ -166,10 +168,10 @@ defmodule AeMdw.AexnTransfers do
{_type_or_pk, <<_pk1::256>>, <<_pk2::256>>, _txi, _amount, _idx},
cursor_term
)) do
cursor_term
{:ok, cursor_term}
else
_invalid ->
raise ErrInput.Cursor, value: cursor_bin64
{:error, ErrInput.Cursor.exception(value: cursor_bin64)}
end
end

Expand Down
9 changes: 3 additions & 6 deletions lib/ae_mdw/contracts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -443,9 +443,6 @@ defmodule AeMdw.Contracts do
end
end

defp build_calls_pagination(query, _scope, _state, _cursor),
do: raise(ErrInput.Query, value: query)

defp build_grp_id_calls_stream(state, direction, scope, cursor, tx_types) do
state
|> Collection.stream(@grp_id_int_contract_call_table, direction, scope, cursor)
Expand Down Expand Up @@ -527,10 +524,10 @@ defmodule AeMdw.Contracts do
defp convert_param(_state, {"aexn-args", _}), do: {:ok, {:ignore, nil}}

defp convert_param(_state, {id_key, id_val}) do
with {:ok, pubkey} <- Validate.id(id_val) do
with {:ok, pubkey} <- Validate.id(id_val),
{:ok, tx_types_positions} <- Parser.parse_field(id_key) do
pos_types =
id_key
|> Parser.parse_field()
tx_types_positions
|> Enum.flat_map(fn {tx_type, positions} -> Enum.map(positions, &{&1, tx_type}) end)
|> Enum.group_by(fn {pos, _tx_type} -> pos end, fn {_pos, tx_type} -> tx_type end)

Expand Down
27 changes: 19 additions & 8 deletions lib/ae_mdw/db/stream/query/parser.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
defmodule AeMdw.Db.Stream.Query.Parser do
@moduledoc false
alias AeMdw.Error
alias AeMdw.Node, as: AE
alias AeMdw.Validate
alias AeMdw.Error.Input, as: ErrInput
Expand All @@ -14,21 +15,31 @@ defmodule AeMdw.Db.Stream.Query.Parser do
def classify_ident("name"), do: &Validate.name_id!/1
def classify_ident(_ident), do: &Validate.id!/1

@spec parse_field(String.t()) :: map()
@spec parse_field(String.t()) :: {:ok, map()} | {:error, Error.t()}
def parse_field(field) do
case String.split(field, ["."]) do
[field] ->
field = Validate.tx_field!(field)
for tx_type <- field_types(field), reduce: %{}, do: (acc -> add_pos(acc, tx_type, field))
with {:ok, field} <- Validate.tx_field(field) do
tx_types_poss =
for tx_type <- field_types(field),
reduce: %{},
do: (acc -> add_pos(acc, tx_type, field))

{:ok, tx_types_poss}
end

[type_no_suffix, field] ->
tx_type = Validate.tx_type!(type_no_suffix)
field = Validate.tx_field!(field)
tx_type in field_types(field) || raise ErrInput.TxField, value: field
add_pos(%{}, tx_type, field)
with {:ok, tx_type} <- Validate.tx_type(type_no_suffix),
{:ok, field} <- Validate.tx_field(field) do
if tx_type in field_types(field) do
{:ok, add_pos(%{}, tx_type, field)}
else
{:error, ErrInput.TxField.exception(value: field)}
end
end

_invalid ->
raise ErrInput.TxField, value: field
{:error, ErrInput.TxField.exception(value: field)}
end
end

Expand Down
6 changes: 0 additions & 6 deletions lib/ae_mdw/error.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ defmodule AeMdw.Error do
def to_string(Input.ContractReturn, x), do: concat("invalid contract return", x)
def to_string(Input.ContractDryRun, x), do: concat("error calling contract", x)
def to_string(Input.Aex9BalanceNotAvailable, x), do: concat("balance is not available", x)
def to_string(Input.Base64, x), do: concat("invalid base64 encoding", x)
def to_string(Input.Hex32, x), do: concat("invalid hex32 encoding", x)
def to_string(Input.RangeTooBig, x), do: concat("invalid range", x)

defmodule Input do
Expand All @@ -53,8 +51,6 @@ defmodule AeMdw.Error do
| __MODULE__.ContractReturn
| __MODULE__.ContractDryRun
| __MODULE__.Aex9BalanceNotAvailable
| __MODULE__.Base64
| __MODULE__.Hex32
| __MODULE__.RangeTooBig
@type message() :: binary()
@type t() :: %__MODULE__{
Expand All @@ -78,8 +74,6 @@ defmodule AeMdw.Error do
defexception!(ContractReturn)
defexception!(ContractDryRun)
defexception!(Aex9BalanceNotAvailable)
defexception!(Base64)
defexception!(Hex32)
defexception!(RangeTooBig)
end
end
Loading
Loading