Skip to content

Commit bfa62a1

Browse files
authored
Merge pull request #22 from objkt-com/feat/error-handling
Improve error handling
2 parents 667ab6d + d21a38e commit bfa62a1

7 files changed

Lines changed: 198 additions & 130 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## vNext
44

5+
- [BREAKING][forge_operation]: error returns changed from `{:error, String.t()}` to `{:error, {:missing_keys, [String.t()]}}` (affects `validate_required_keys/3`, `operation/1`, `operation_group/1` and all per-operation builders)
6+
- [BREAKING][fee]: `calculate_fee/3` error shape changed accordingly (propagated from `forge_operation`)
7+
- [BREAKING][rpc]: unified all error returns to `{:error, {reason, detail}}` — transport errors are wrapped (`:transport`, `:http_status`, `:decode`); preapply returns `{:preapply_failed, errors}` / `{:unexpected_response, body}`; `fill_operation_fee/3` now returns `{:ok, operation} | {:error, _}` (previously crashed on fee errors); `get_counter_for_account/2` now returns `{:ok, integer()} | {:error, _}`; `get_balance/2` returns `{:error, {:invalid_balance, _}}` instead of raising on a non-integer body; `get_block_at_offset/2` returns `{:error, _}` instead of raising on a transport error, and now short-circuits to the head block for `offset <= 0`
58
- [BREAKING][crypto/bls]: drop `is_` prefix from predicates (`is_zero?``zero?`, `is_one?``one?`, `is_infinity?``infinity?`) across `Fq`, `Fr`, `Fq2`, `Fq12`, `FqP`, `G1`, `G2`
69
- [BREAKING][crypto/bls]: `Fq12.inv/1` and `FqP.inv/1` now return `{:ok, t} | {:error, :not_invertible}`
710
- [BREAKING][crypto/bls]: `Fr.from_bytes/1` rejects out-of-range scalars with `:out_of_range` instead of silently reducing

lib/fee.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ defmodule Tezex.Fee do
2424
@spec calculate_fee(map(), pos_integer(),
2525
extra_size: pos_integer(),
2626
minimal_nanotez_per_gas_unit: pos_integer()
27-
) :: {:ok, pos_integer()} | {:error, nonempty_binary()}
27+
) :: {:ok, pos_integer()} | {:error, ForgeOperation.error_reason()}
2828
def calculate_fee(content, consumed_gas, opts \\ []) do
2929
extra_size = Keyword.get(opts, :extra_size, @extra_size)
3030

lib/forge_operation.ex

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ defmodule Tezex.ForgeOperation do
88

99
alias Tezex.Forge
1010

11+
@type error_reason() :: {:missing_keys, [String.t()]}
12+
1113
@operation_tags %{
1214
"endorsement" => 0,
1315
"endorsement_with_slot" => 10,
@@ -57,7 +59,7 @@ defmodule Tezex.ForgeOperation do
5759
<<Map.fetch!(@operation_tags, kind)::size(8)>>
5860
end
5961

60-
@spec operation(map()) :: {:ok, nonempty_binary()} | {:error, nonempty_binary()}
62+
@spec operation(map()) :: {:ok, nonempty_binary()} | {:error, error_reason()}
6163
def operation(content) do
6264
case content["kind"] do
6365
"failing_noop" -> failing_noop(content)
@@ -77,7 +79,7 @@ defmodule Tezex.ForgeOperation do
7779
end
7880

7981
@keys ~w(branch contents)
80-
@spec operation_group(map()) :: {:ok, nonempty_binary()} | {:error, nonempty_binary()}
82+
@spec operation_group(map()) :: {:ok, nonempty_binary()} | {:error, error_reason()}
8183
def operation_group(operation_group) do
8284
with :ok <- validate_required_keys(operation_group, @keys),
8385
operations = Enum.map(operation_group["contents"], &operation/1),
@@ -97,7 +99,7 @@ defmodule Tezex.ForgeOperation do
9799
end
98100

99101
@keys ~w(kind pkh secret)
100-
@spec activate_account(map()) :: {:ok, nonempty_binary()} | {:error, nonempty_binary()}
102+
@spec activate_account(map()) :: {:ok, nonempty_binary()} | {:error, error_reason()}
101103
def activate_account(content) do
102104
with :ok <- validate_required_keys(content, @keys) do
103105
content =
@@ -113,7 +115,7 @@ defmodule Tezex.ForgeOperation do
113115
end
114116

115117
@keys ~w(kind source fee counter gas_limit storage_limit public_key)
116-
@spec reveal(map()) :: {:ok, nonempty_binary()} | {:error, nonempty_binary()}
118+
@spec reveal(map()) :: {:ok, nonempty_binary()} | {:error, error_reason()}
117119
def reveal(content) do
118120
with :ok <- validate_required_keys(content, @keys) do
119121
content =
@@ -141,7 +143,7 @@ defmodule Tezex.ForgeOperation do
141143

142144
@keys ~w(kind source fee counter gas_limit storage_limit amount destination)
143145
@params ~w(parameters parameters.entrypoint parameters.value)
144-
@spec transaction(map()) :: {:ok, nonempty_binary()} | {:error, nonempty_binary()}
146+
@spec transaction(map()) :: {:ok, nonempty_binary()} | {:error, error_reason()}
145147
def transaction(content) do
146148
with :ok <- validate_required_keys(content, @keys),
147149
:ok <-
@@ -178,7 +180,7 @@ defmodule Tezex.ForgeOperation do
178180
end
179181

180182
@keys ~w(kind source fee counter gas_limit storage_limit balance)
181-
@spec origination(map()) :: {:ok, nonempty_binary()} | {:error, nonempty_binary()}
183+
@spec origination(map()) :: {:ok, nonempty_binary()} | {:error, error_reason()}
182184
def origination(content) do
183185
with :ok <- validate_required_keys(content, @keys) do
184186
content =
@@ -206,7 +208,7 @@ defmodule Tezex.ForgeOperation do
206208
end
207209

208210
@keys ~w(kind source fee counter gas_limit storage_limit)
209-
@spec delegation(map()) :: {:ok, nonempty_binary()} | {:error, nonempty_binary()}
211+
@spec delegation(map()) :: {:ok, nonempty_binary()} | {:error, error_reason()}
210212
def delegation(content) do
211213
with :ok <- validate_required_keys(content, @keys) do
212214
content =
@@ -232,7 +234,7 @@ defmodule Tezex.ForgeOperation do
232234
end
233235

234236
@keys ~w(kind level)
235-
@spec endorsement(map()) :: {:ok, nonempty_binary()} | {:error, nonempty_binary()}
237+
@spec endorsement(map()) :: {:ok, nonempty_binary()} | {:error, error_reason()}
236238
def endorsement(content) do
237239
with :ok <- validate_required_keys(content, @keys) do
238240
content =
@@ -247,7 +249,7 @@ defmodule Tezex.ForgeOperation do
247249
end
248250

249251
@keys ~w(branch operations operations.kind operations.level signature)
250-
@spec inline_endorsement(map()) :: {:ok, nonempty_binary()} | {:error, nonempty_binary()}
252+
@spec inline_endorsement(map()) :: {:ok, nonempty_binary()} | {:error, error_reason()}
251253
def inline_endorsement(content) do
252254
with :ok <- validate_required_keys(content, @keys) do
253255
content =
@@ -264,7 +266,7 @@ defmodule Tezex.ForgeOperation do
264266
end
265267

266268
@keys ~w(kind endorsement slot)
267-
@spec endorsement_with_slot(map()) :: {:ok, nonempty_binary()} | {:error, nonempty_binary()}
269+
@spec endorsement_with_slot(map()) :: {:ok, nonempty_binary()} | {:error, error_reason()}
268270
def endorsement_with_slot(content) do
269271
with :ok <- validate_required_keys(content, @keys),
270272
{:ok, endorsement} <- inline_endorsement(content["endorsement"]) do
@@ -281,7 +283,7 @@ defmodule Tezex.ForgeOperation do
281283
end
282284

283285
@keys ~w(kind arbitrary)
284-
@spec failing_noop(map()) :: {:ok, nonempty_binary()} | {:error, nonempty_binary()}
286+
@spec failing_noop(map()) :: {:ok, nonempty_binary()} | {:error, error_reason()}
285287
def failing_noop(content) do
286288
with :ok <- validate_required_keys(content, @keys) do
287289
content =
@@ -296,7 +298,7 @@ defmodule Tezex.ForgeOperation do
296298
end
297299

298300
@keys ~w(kind source fee counter gas_limit storage_limit value)
299-
@spec register_global_constant(map()) :: {:ok, nonempty_binary()} | {:error, nonempty_binary()}
301+
@spec register_global_constant(map()) :: {:ok, nonempty_binary()} | {:error, error_reason()}
300302
def register_global_constant(content) do
301303
with :ok <- validate_required_keys(content, @keys) do
302304
content =
@@ -316,7 +318,7 @@ defmodule Tezex.ForgeOperation do
316318
end
317319

318320
@keys ~w(kind source fee counter gas_limit storage_limit ticket_contents ticket_ty ticket_ticketer ticket_amount destination entrypoint)
319-
@spec transfer_ticket(map()) :: {:ok, nonempty_binary()} | {:error, nonempty_binary()}
321+
@spec transfer_ticket(map()) :: {:ok, nonempty_binary()} | {:error, error_reason()}
320322
def transfer_ticket(content) do
321323
with :ok <- validate_required_keys(content, @keys) do
322324
content =
@@ -341,7 +343,7 @@ defmodule Tezex.ForgeOperation do
341343
end
342344

343345
@keys ~w(kind source fee counter gas_limit storage_limit message)
344-
@spec smart_rollup_add_messages(map()) :: {:ok, nonempty_binary()} | {:error, nonempty_binary()}
346+
@spec smart_rollup_add_messages(map()) :: {:ok, nonempty_binary()} | {:error, error_reason()}
345347
def smart_rollup_add_messages(content) do
346348
with :ok <- validate_required_keys(content, @keys) do
347349
content =
@@ -367,7 +369,7 @@ defmodule Tezex.ForgeOperation do
367369

368370
@keys ~w(kind source fee counter gas_limit storage_limit rollup cemented_commitment output_proof)
369371
@spec smart_rollup_execute_outbox_message(map()) ::
370-
{:ok, nonempty_binary()} | {:error, nonempty_binary()}
372+
{:ok, nonempty_binary()} | {:error, error_reason()}
371373
def smart_rollup_execute_outbox_message(content) do
372374
with :ok <- validate_required_keys(content, @keys) do
373375
content =
@@ -388,7 +390,7 @@ defmodule Tezex.ForgeOperation do
388390
end
389391
end
390392

391-
@spec validate_required_keys(map(), list()) :: :ok | {:error, nonempty_binary()}
393+
@spec validate_required_keys(map(), list()) :: :ok | {:error, error_reason()}
392394
def validate_required_keys(map, required_keys, acc \\ "")
393395
when is_map(map) and is_list(required_keys) do
394396
required_keys = Enum.group_by(required_keys, &String.contains?(&1, "."))
@@ -421,8 +423,7 @@ defmodule Tezex.ForgeOperation do
421423
end)
422424
end
423425
else
424-
{:error,
425-
"Operation content is missing required keys: #{acc}#{Enum.join(missing_keys, ", ")}"}
426+
{:error, {:missing_keys, Enum.map(missing_keys, &(acc <> &1))}}
426427
end
427428
end
428429
end

0 commit comments

Comments
 (0)