From c72d2594f953db849d602deff260a2e8e2db7678 Mon Sep 17 00:00:00 2001 From: Andres Ruiz Date: Mon, 21 Oct 2024 16:25:06 -0500 Subject: [PATCH 1/3] Add tests for NUT-02 and refactor a bit Adds tests for NUT-02 and refactors the code a bit so that it follows elixir conventions. --- lib/cashubrew/NUTs/NUT-01/serde.ex | 2 + .../NUTs/NUT-02/get_keysets_response.ex | 17 +++++ lib/cashubrew/NUTs/NUT-02/impl.ex | 7 +- lib/cashubrew/NUTs/NUT-02/keyset.ex | 17 +++++ lib/cashubrew/NUTs/NUT-02/keysets.ex | 2 +- lib/cashubrew/NUTs/NUT-02/routes.ex | 4 +- lib/cashubrew/NUTs/NUT-02/serde.ex | 33 --------- lib/cashubrew/core/mint.ex | 2 +- lib/cashubrew/schema/keyset.ex | 3 +- .../web/controllers/mint_controller.ex | 4 +- test/nut02_test.exs | 67 +++++++++++++++++++ 11 files changed, 112 insertions(+), 46 deletions(-) create mode 100644 lib/cashubrew/NUTs/NUT-02/get_keysets_response.ex create mode 100644 lib/cashubrew/NUTs/NUT-02/keyset.ex delete mode 100644 lib/cashubrew/NUTs/NUT-02/serde.ex create mode 100644 test/nut02_test.exs diff --git a/lib/cashubrew/NUTs/NUT-01/serde.ex b/lib/cashubrew/NUTs/NUT-01/serde.ex index efad75b..759d04f 100644 --- a/lib/cashubrew/NUTs/NUT-01/serde.ex +++ b/lib/cashubrew/NUTs/NUT-01/serde.ex @@ -4,6 +4,7 @@ defmodule Cashubrew.Nuts.Nut01.Serde.GetKeysResponse do """ @derive Jason.Encoder @enforce_keys [:keysets] + @derive [Jason.Encoder] defstruct [:keysets] def from_keysets(keysets) do @@ -60,6 +61,7 @@ defmodule Cashubrew.Nuts.Nut01.Serde.Keyset do """ @derive Jason.Encoder @enforce_keys [:id, :unit, :keys] + @derive [Jason.Encoder] defstruct [:id, :unit, :keys] def from_keyset(id, unit, keys) do diff --git a/lib/cashubrew/NUTs/NUT-02/get_keysets_response.ex b/lib/cashubrew/NUTs/NUT-02/get_keysets_response.ex new file mode 100644 index 0000000..6feb032 --- /dev/null +++ b/lib/cashubrew/NUTs/NUT-02/get_keysets_response.ex @@ -0,0 +1,17 @@ +defmodule Cashubrew.Nuts.Nut02.GetKeysetsResponse do + @moduledoc """ + The body of the get keysets rest response + """ + @enforce_keys [:keysets] + @derive [Jason.Encoder] + defstruct [:keysets] + + def from_keysets(keysets) do + keysets_responses = + Enum.map(keysets, &Cashubrew.Nuts.Nut02.Keyset.from_keyset(&1)) + + %__MODULE__{ + keysets: keysets_responses + } + end +end diff --git a/lib/cashubrew/NUTs/NUT-02/impl.ex b/lib/cashubrew/NUTs/NUT-02/impl.ex index 3dbb045..9e70ee8 100644 --- a/lib/cashubrew/NUTs/NUT-02/impl.ex +++ b/lib/cashubrew/NUTs/NUT-02/impl.ex @@ -3,10 +3,11 @@ defmodule Cashubrew.Nuts.Nut02.Impl do The mint logic for handling Nut02 """ alias Cashubrew.Mint + alias Cashubrew.Repo + alias Cashubrew.Schema.Keyset - def keysets do - repo = Application.get_env(:cashubrew, :repo) - Mint.get_all_keysets(repo) + def keysets() do + Repo.all(Keyset) end def keys_for_keyset_id!(id) do diff --git a/lib/cashubrew/NUTs/NUT-02/keyset.ex b/lib/cashubrew/NUTs/NUT-02/keyset.ex new file mode 100644 index 0000000..695e5e6 --- /dev/null +++ b/lib/cashubrew/NUTs/NUT-02/keyset.ex @@ -0,0 +1,17 @@ +defmodule Cashubrew.Nuts.Nut02.Keyset do + @moduledoc """ + A keyset + """ + @enforce_keys [:id, :unit, :active] + @derive [Jason.Encoder] + defstruct [:id, :unit, :active, :input_fee_ppk] + + def from_keyset(keyset) do + %__MODULE__{ + id: keyset.id, + unit: keyset.unit, + active: keyset.active, + input_fee_ppk: keyset.input_fee_ppk + } + end +end diff --git a/lib/cashubrew/NUTs/NUT-02/keysets.ex b/lib/cashubrew/NUTs/NUT-02/keysets.ex index 6c965db..c361a14 100644 --- a/lib/cashubrew/NUTs/NUT-02/keysets.ex +++ b/lib/cashubrew/NUTs/NUT-02/keysets.ex @@ -1,4 +1,4 @@ -defmodule Cashubrew.Nuts.Nut02.Keyset do +defmodule Cashubrew.Nuts.Nut02.Keysets do @moduledoc """ Contains the logic required for the Mint to generate keys and keysets """ diff --git a/lib/cashubrew/NUTs/NUT-02/routes.ex b/lib/cashubrew/NUTs/NUT-02/routes.ex index 62270d0..470f94d 100644 --- a/lib/cashubrew/NUTs/NUT-02/routes.ex +++ b/lib/cashubrew/NUTs/NUT-02/routes.ex @@ -1,6 +1,4 @@ defmodule Cashubrew.Nuts.Nut02.Routes do - alias Cashubrew.Nuts.Nut01 - @moduledoc """ List the rest routes defined in the NUT-02 """ @@ -9,7 +7,7 @@ defmodule Cashubrew.Nuts.Nut02.Routes do The route to query keys part of a specific keyset from the Mint """ def v1_keys_for_keyset_id do - Nut01.Routes.v1_keys() <> "/:keyset_id" + "/v1/keys/:keyset_id" end def v1_keyset do diff --git a/lib/cashubrew/NUTs/NUT-02/serde.ex b/lib/cashubrew/NUTs/NUT-02/serde.ex deleted file mode 100644 index 6b2c332..0000000 --- a/lib/cashubrew/NUTs/NUT-02/serde.ex +++ /dev/null @@ -1,33 +0,0 @@ -defmodule Cashubrew.Nuts.Nut02.Serde.Keyset do - @moduledoc """ - A keyset - """ - @enforce_keys [:id, :unit, :active] - defstruct [:id, :unit, :active, :input_fee_ppk] - - def from_keyset(keyset) do - %__MODULE__{ - id: keyset.id, - unit: keyset.unit, - active: keyset.active, - input_fee_ppk: keyset.input_fee_ppk - } - end -end - -defmodule Cashubrew.Nuts.Nut02.Serde.GetKeysetsResponse do - @moduledoc """ - The body of the get keysets rest response - """ - @enforce_keys [:keysets] - defstruct [:keysets] - - def from_keysets(keysets) do - keysets_responses = - Enum.map(keysets, fn keyset -> Cashubrew.Nuts.Nut02.Serde.Keyset.from_keyset(keyset) end) - - %__MODULE__{ - keysets: keysets_responses - } - end -end diff --git a/lib/cashubrew/core/mint.ex b/lib/cashubrew/core/mint.ex index 584d0f6..1e8d226 100644 --- a/lib/cashubrew/core/mint.ex +++ b/lib/cashubrew/core/mint.ex @@ -85,7 +85,7 @@ defmodule Cashubrew.Mint do defp load_or_create_keysets(repo, seed) do case repo.all(Schema.Keyset) do [] -> - keys = Nut02.Keyset.generate_keys(seed, keyset_generation_derivation_path()) + keys = Nut02.Keysets.generate_keys(seed, keyset_generation_derivation_path()) keyset = Schema.Keyset.register_keyset( diff --git a/lib/cashubrew/schema/keyset.ex b/lib/cashubrew/schema/keyset.ex index a3f7542..9e2af6f 100644 --- a/lib/cashubrew/schema/keyset.ex +++ b/lib/cashubrew/schema/keyset.ex @@ -4,7 +4,6 @@ defmodule Cashubrew.Schema.Keyset do """ use Ecto.Schema import Ecto.Changeset - alias Cashubrew.Nuts.Nut02 alias Cashubrew.Schema @primary_key {:id, :string, autogenerate: false} @@ -22,7 +21,7 @@ defmodule Cashubrew.Schema.Keyset do end def register_keyset(keys, unit, input_fee_ppk) do - id = Nut02.Keyset.derive_keyset_id(keys) + id = Cashubrew.Nuts.Nut02.Keysets.derive_keyset_id(keys) keyset = %__MODULE__{ id: id, diff --git a/lib/cashubrew/web/controllers/mint_controller.ex b/lib/cashubrew/web/controllers/mint_controller.ex index d143c98..665a118 100644 --- a/lib/cashubrew/web/controllers/mint_controller.ex +++ b/lib/cashubrew/web/controllers/mint_controller.ex @@ -15,9 +15,7 @@ defmodule Cashubrew.Web.MintController do def keysets(conn, _params) do keysets = Nut02.Impl.keysets() - json(conn, Nut02.Serde.GetKeysetsResponse.from_keysets(keysets)) - rescue - e in RuntimeError -> conn |> put_status(:bad_request) |> json(Nut00.Error.new_error(0, e)) + json(conn, Nut02.GetKeysetsResponse.from_keysets(keysets)) end def keys(conn, _params) do diff --git a/test/nut02_test.exs b/test/nut02_test.exs new file mode 100644 index 0000000..47c0ce4 --- /dev/null +++ b/test/nut02_test.exs @@ -0,0 +1,67 @@ +defmodule Cashubrew.Nuts.Nut02Test do + use Cashubrew.Test.ConnCase + alias Cashubrew.Schema.Key + alias Cashubrew.Schema.Keyset + alias Cashubrew.Repo + + test "get all keysets", %{conn: conn} do + data = conn |> get(~p"/api/v1/keysets") |> json_response(200) + + [keyset] = data["keysets"] + assert Map.has_key?(keyset, "id") + assert keyset["id"] |> String.starts_with?("00") + assert keyset["unit"] == "sat" + assert keyset["active"] == true + end + + test "get 2 keysets", %{conn: conn} do + pub_keys = [ + %{amount: 1, public_key: "pub_01", private_key: "priv_01"}, + %{amount: 2, public_key: "pub_02", private_key: "priv_02"}, + %{amount: 3, public_key: "pub_03", private_key: "priv_03"}, + %{amount: 4, public_key: "pub_04", private_key: "priv_04"} + ] + + id = Cashubrew.Nuts.Nut02.Keysets.derive_keyset_id(pub_keys) + + now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + + pub_keys = + Enum.map(pub_keys, fn key -> + key + |> Map.put(:keyset_id, id) + |> Map.put(:inserted_at, now) + |> Map.put(:updated_at, now) + end) + + Repo.insert!(%Keyset{id: id, unit: "sat", active: false}) + Repo.insert_all(Key, pub_keys) + + data = conn |> get(~p"/api/v1/keysets") |> json_response(200) + + [keyset1, keyset2] = data["keysets"] + + assert Map.has_key?(keyset1, "id") + assert keyset1["id"] |> String.starts_with?("00") + assert keyset1["unit"] == "sat" + assert keyset1["active"] == true + + assert Map.has_key?(keyset2, "id") + assert keyset2["id"] |> String.starts_with?("00") + assert keyset2["unit"] == "sat" + assert keyset2["active"] == false + end + + test "get one keyset", %{conn: conn} do + data = conn |> get(~p"/api/v1/keysets") |> json_response(200) + + [keyset] = data["keysets"] + id = keyset["id"] + + data = conn |> get(~p"/api/v1/keys/#{id}") |> json_response(200) + [keyset] = data["keysets"] + + assert keyset["id"] == id + assert map_size(keyset["keys"]) > 0 + end +end From c861aa17618a4d06753d71da96b258f66c17bfcc Mon Sep 17 00:00:00 2001 From: Andres Ruiz Date: Mon, 21 Oct 2024 16:30:07 -0500 Subject: [PATCH 2/3] format --- lib/cashubrew/NUTs/NUT-02/get_keysets_response.ex | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/cashubrew/NUTs/NUT-02/get_keysets_response.ex b/lib/cashubrew/NUTs/NUT-02/get_keysets_response.ex index 6feb032..a384128 100644 --- a/lib/cashubrew/NUTs/NUT-02/get_keysets_response.ex +++ b/lib/cashubrew/NUTs/NUT-02/get_keysets_response.ex @@ -7,8 +7,7 @@ defmodule Cashubrew.Nuts.Nut02.GetKeysetsResponse do defstruct [:keysets] def from_keysets(keysets) do - keysets_responses = - Enum.map(keysets, &Cashubrew.Nuts.Nut02.Keyset.from_keyset(&1)) + keysets_responses = Enum.map(keysets, &Cashubrew.Nuts.Nut02.Keyset.from_keyset(&1)) %__MODULE__{ keysets: keysets_responses From 7f42503d77ce4a52b15d390ac4d9d7a70c1af1db Mon Sep 17 00:00:00 2001 From: Andres Ruiz Date: Tue, 22 Oct 2024 15:07:10 -0500 Subject: [PATCH 3/3] Added suggested changes in PR --- .../NUTs/NUT-02/get_keysets_response.ex | 16 --------- lib/cashubrew/NUTs/NUT-02/keyset.ex | 17 ---------- lib/cashubrew/NUTs/NUT-02/routes.ex | 3 +- lib/cashubrew/NUTs/NUT-02/serde.ex | 34 +++++++++++++++++++ lib/cashubrew/schema/keyset.ex | 5 ++- .../web/controllers/mint_controller.ex | 4 ++- test/nut02_test.exs | 1 + 7 files changed, 44 insertions(+), 36 deletions(-) delete mode 100644 lib/cashubrew/NUTs/NUT-02/get_keysets_response.ex delete mode 100644 lib/cashubrew/NUTs/NUT-02/keyset.ex create mode 100644 lib/cashubrew/NUTs/NUT-02/serde.ex diff --git a/lib/cashubrew/NUTs/NUT-02/get_keysets_response.ex b/lib/cashubrew/NUTs/NUT-02/get_keysets_response.ex deleted file mode 100644 index a384128..0000000 --- a/lib/cashubrew/NUTs/NUT-02/get_keysets_response.ex +++ /dev/null @@ -1,16 +0,0 @@ -defmodule Cashubrew.Nuts.Nut02.GetKeysetsResponse do - @moduledoc """ - The body of the get keysets rest response - """ - @enforce_keys [:keysets] - @derive [Jason.Encoder] - defstruct [:keysets] - - def from_keysets(keysets) do - keysets_responses = Enum.map(keysets, &Cashubrew.Nuts.Nut02.Keyset.from_keyset(&1)) - - %__MODULE__{ - keysets: keysets_responses - } - end -end diff --git a/lib/cashubrew/NUTs/NUT-02/keyset.ex b/lib/cashubrew/NUTs/NUT-02/keyset.ex deleted file mode 100644 index 695e5e6..0000000 --- a/lib/cashubrew/NUTs/NUT-02/keyset.ex +++ /dev/null @@ -1,17 +0,0 @@ -defmodule Cashubrew.Nuts.Nut02.Keyset do - @moduledoc """ - A keyset - """ - @enforce_keys [:id, :unit, :active] - @derive [Jason.Encoder] - defstruct [:id, :unit, :active, :input_fee_ppk] - - def from_keyset(keyset) do - %__MODULE__{ - id: keyset.id, - unit: keyset.unit, - active: keyset.active, - input_fee_ppk: keyset.input_fee_ppk - } - end -end diff --git a/lib/cashubrew/NUTs/NUT-02/routes.ex b/lib/cashubrew/NUTs/NUT-02/routes.ex index 470f94d..bf5405e 100644 --- a/lib/cashubrew/NUTs/NUT-02/routes.ex +++ b/lib/cashubrew/NUTs/NUT-02/routes.ex @@ -2,12 +2,13 @@ defmodule Cashubrew.Nuts.Nut02.Routes do @moduledoc """ List the rest routes defined in the NUT-02 """ + alias Cashubrew.Nuts.Nut01 @doc """ The route to query keys part of a specific keyset from the Mint """ def v1_keys_for_keyset_id do - "/v1/keys/:keyset_id" + Nut01.Routes.v1_keys() <> "/:keyset_id" end def v1_keyset do diff --git a/lib/cashubrew/NUTs/NUT-02/serde.ex b/lib/cashubrew/NUTs/NUT-02/serde.ex new file mode 100644 index 0000000..28bf61b --- /dev/null +++ b/lib/cashubrew/NUTs/NUT-02/serde.ex @@ -0,0 +1,34 @@ +defmodule Cashubrew.Nuts.Nut02.Serde.Keyset do + @moduledoc """ + A keyset + """ + @enforce_keys [:id, :unit, :active] + @derive [Jason.Encoder] + defstruct [:id, :unit, :active, :input_fee_ppk] + + def from_keyset(keyset) do + %__MODULE__{ + id: keyset.id, + unit: keyset.unit, + active: keyset.active, + input_fee_ppk: keyset.input_fee_ppk + } + end +end + +defmodule Cashubrew.Nuts.Nut02.Serde.GetKeysetsResponse do + @moduledoc """ + The body of the get keysets rest response + """ + @enforce_keys [:keysets] + @derive [Jason.Encoder] + defstruct [:keysets] + + def from_keysets(keysets) do + keysets_responses = Enum.map(keysets, &Cashubrew.Nuts.Nut02.Serde.Keyset.from_keyset(&1)) + + %__MODULE__{ + keysets: keysets_responses + } + end +end diff --git a/lib/cashubrew/schema/keyset.ex b/lib/cashubrew/schema/keyset.ex index 9e2af6f..45ed0f5 100644 --- a/lib/cashubrew/schema/keyset.ex +++ b/lib/cashubrew/schema/keyset.ex @@ -3,8 +3,11 @@ defmodule Cashubrew.Schema.Keyset do Keyset schema for the Cashubrew mint. """ use Ecto.Schema + import Ecto.Changeset + alias Cashubrew.Schema + alias Cashubrew.Nuts.Nut02 @primary_key {:id, :string, autogenerate: false} schema "keysets" do @@ -21,7 +24,7 @@ defmodule Cashubrew.Schema.Keyset do end def register_keyset(keys, unit, input_fee_ppk) do - id = Cashubrew.Nuts.Nut02.Keysets.derive_keyset_id(keys) + id = Nut02.Keysets.derive_keyset_id(keys) keyset = %__MODULE__{ id: id, diff --git a/lib/cashubrew/web/controllers/mint_controller.ex b/lib/cashubrew/web/controllers/mint_controller.ex index 665a118..d143c98 100644 --- a/lib/cashubrew/web/controllers/mint_controller.ex +++ b/lib/cashubrew/web/controllers/mint_controller.ex @@ -15,7 +15,9 @@ defmodule Cashubrew.Web.MintController do def keysets(conn, _params) do keysets = Nut02.Impl.keysets() - json(conn, Nut02.GetKeysetsResponse.from_keysets(keysets)) + json(conn, Nut02.Serde.GetKeysetsResponse.from_keysets(keysets)) + rescue + e in RuntimeError -> conn |> put_status(:bad_request) |> json(Nut00.Error.new_error(0, e)) end def keys(conn, _params) do diff --git a/test/nut02_test.exs b/test/nut02_test.exs index 47c0ce4..09ee2f9 100644 --- a/test/nut02_test.exs +++ b/test/nut02_test.exs @@ -48,6 +48,7 @@ defmodule Cashubrew.Nuts.Nut02Test do assert Map.has_key?(keyset2, "id") assert keyset2["id"] |> String.starts_with?("00") + assert keyset2["id"] == id assert keyset2["unit"] == "sat" assert keyset2["active"] == false end