diff --git a/integration-tests/nut05.rs b/integration-tests/nut05.rs index 659f296..07c64f9 100644 --- a/integration-tests/nut05.rs +++ b/integration-tests/nut05.rs @@ -23,19 +23,31 @@ pub async fn melt_quote_ok() { assert_matches!( melt_quote, MeltQuote { - id, + ref id, unit: _, amount, request: _, fee_reserve, state, expiry, - payment_preimage - } if Uuid::try_parse(&id).is_ok() + ref payment_preimage + } if Uuid::try_parse(id).is_ok() && amount == Amount::from(10) && fee_reserve == Amount::from(1) && state == MeltQuoteState::Unpaid && expiry >= now && payment_preimage.is_none() - ) + ); + + let melt_quote_status = wallet.melt_quote_status(&melt_quote.id).await.unwrap(); + + assert_eq!(melt_quote.id, melt_quote_status.quote); + assert_eq!(melt_quote.amount, melt_quote_status.amount); + assert_eq!(melt_quote.fee_reserve, melt_quote_status.fee_reserve); + assert_eq!(melt_quote.state, melt_quote_status.state); + assert_eq!(melt_quote.expiry, melt_quote_status.expiry); + assert_eq!( + melt_quote.payment_preimage, + melt_quote_status.payment_preimage + ); } diff --git a/lib/cashubrew/NUTs/NUT-05/impl.ex b/lib/cashubrew/NUTs/NUT-05/impl.ex index 3f222ef..0eb2031 100644 --- a/lib/cashubrew/NUTs/NUT-05/impl.ex +++ b/lib/cashubrew/NUTs/NUT-05/impl.ex @@ -3,6 +3,7 @@ defmodule Cashubrew.Nuts.Nut05.Impl do Implementation and structs of the NUT-05 """ alias Cashubrew.Schema + require Logger defp percent_fee_reserve, do: 1 defp min_fee_reserve, do: 1 @@ -26,8 +27,7 @@ defmodule Cashubrew.Nuts.Nut05.Impl do fee = max(relative_fee_reserve, min_fee_reserve()) expiry = System.os_time(:second) + melt_quote_validity_duration_in_sec() - quote_id = Ecto.UUID.bingenerate() - quote_id_as_string = Ecto.UUID.cast!(quote_id) + quote_id = Ecto.UUID.generate() Schema.MeltQuote.create!(repo, %{ id: quote_id, @@ -40,11 +40,17 @@ defmodule Cashubrew.Nuts.Nut05.Impl do }) %{ - quote: quote_id_as_string, + quote: quote_id, amount: amount, fee_reserve: fee, state: "UNPAID", expiry: expiry } end + + def get_melt_quote_by_id(quote_id) do + repo = Application.get_env(:cashubrew, :repo) + + repo.get!(Schema.MeltQuote, quote_id) + end end diff --git a/lib/cashubrew/NUTs/NUT-05/routes.ex b/lib/cashubrew/NUTs/NUT-05/routes.ex index 3c47e3a..7f8d839 100644 --- a/lib/cashubrew/NUTs/NUT-05/routes.ex +++ b/lib/cashubrew/NUTs/NUT-05/routes.ex @@ -13,7 +13,7 @@ defmodule Cashubrew.Nuts.Nut05.Routes do @doc """ The route to check a melt quote state """ - def v1_melt_quote_for_quote_id do + def v1_melt_quote_by_id do v1_melt_quote() <> "/:quote_id" end diff --git a/lib/cashubrew/NUTs/NUT-05/serde.ex b/lib/cashubrew/NUTs/NUT-05/serde.ex index 47740fc..9d8d606 100644 --- a/lib/cashubrew/NUTs/NUT-05/serde.ex +++ b/lib/cashubrew/NUTs/NUT-05/serde.ex @@ -32,4 +32,15 @@ defmodule Cashubrew.Nuts.Nut05.Serde.PostMeltQuoteBolt11Response do @enforce_keys [:quote, :amount, :fee_reserve, :state, :expiry] @derive [Jason.Encoder] defstruct [:quote, :amount, :fee_reserve, :state, :expiry, :payment_preimage] + + def from_melt_quote(melt_quote, state, payment_preimage) do + %__MODULE__{ + quote: Ecto.UUID.cast!(melt_quote.id), + amount: melt_quote.amount, + fee_reserve: melt_quote.fee_reserve, + expiry: melt_quote.expiry, + state: state, + payment_preimage: payment_preimage + } + end end diff --git a/lib/cashubrew/schema/melt_quote.ex b/lib/cashubrew/schema/melt_quote.ex index fea0357..3aba7d3 100644 --- a/lib/cashubrew/schema/melt_quote.ex +++ b/lib/cashubrew/schema/melt_quote.ex @@ -20,8 +20,16 @@ defmodule Cashubrew.Schema.MeltQuote do def changeset(quote, attrs) do quote - |> cast(attrs, [:request, :unit, :amount, :fee_reserve, :expiry, :request_lookup_id]) - |> validate_required([:request, :unit, :amount, :fee_reserve, :expiry, :request_lookup_id]) + |> cast(attrs, [:id, :request, :unit, :amount, :fee_reserve, :expiry, :request_lookup_id]) + |> validate_required([ + :id, + :request, + :unit, + :amount, + :fee_reserve, + :expiry, + :request_lookup_id + ]) end def create!(repo, values) do diff --git a/lib/cashubrew/web/controllers/mint_controller.ex b/lib/cashubrew/web/controllers/mint_controller.ex index 84b976d..223994d 100644 --- a/lib/cashubrew/web/controllers/mint_controller.ex +++ b/lib/cashubrew/web/controllers/mint_controller.ex @@ -2,7 +2,6 @@ defmodule Cashubrew.Web.MintController do use Cashubrew.Web, :controller require :logger require Logger - alias Cashubrew.Lightning alias Cashubrew.Mint alias Cashubrew.Nuts.Nut00 alias Cashubrew.Nuts.Nut01 @@ -96,28 +95,26 @@ defmodule Cashubrew.Web.MintController do e in RuntimeError -> conn |> put_status(:bad_request) |> json(Nut00.Error.new_error(0, e)) end - def create_melt_quote(conn, params) do - method = params["method"] - + def create_melt_quote(conn, %{"method" => method, "request" => request, "unit" => unit}) do if method != "bolt11" do raise "UnsuportedMethod" end - request = params["request"] - - if !request do - raise "NoRequest" - end + res = Nut05.Impl.create_melt_quote!(request, unit) - unit = params["unit"] + json(conn, struct(Nut05.Serde.PostMeltQuoteBolt11Response, res)) + rescue + e in RuntimeError -> conn |> put_status(:bad_request) |> json(Nut00.Error.new_error(0, e)) + end - if !unit do - raise "NoUnit" + def get_melt_quote(conn, %{"method" => method, "quote_id" => quote_id}) do + if method != "bolt11" do + raise "UnsuportedMethod" end - res = Nut05.Impl.create_melt_quote!(request, unit) - - json(conn, struct(Nut05.Serde.PostMeltQuoteBolt11Response, res)) + melt_quote = Nut05.Impl.get_melt_quote_by_id(quote_id) + # TODO: get actual state from ln and payment_preimage + json(conn, Nut05.Serde.PostMeltQuoteBolt11Response.from_melt_quote(melt_quote, "UNPAID", nil)) rescue e in RuntimeError -> conn |> put_status(:bad_request) |> json(Nut00.Error.new_error(0, e)) end diff --git a/lib/cashubrew/web/router.ex b/lib/cashubrew/web/router.ex index 9a8a28b..e139fd0 100644 --- a/lib/cashubrew/web/router.ex +++ b/lib/cashubrew/web/router.ex @@ -45,6 +45,7 @@ defmodule Cashubrew.Web.Router do get("/v1/info", MintController, :info) # NUT-05 post(Nut05.Routes.v1_melt_quote(), MintController, :create_melt_quote) + get(Nut05.Routes.v1_melt_quote_by_id(), MintController, :get_melt_quote) end if Mix.env() == :dev do diff --git a/priv/repo/migrations/20240918113124_create_melt_quote.exs b/priv/repo/migrations/20240918113124_create_melt_quote.exs index 2af4a99..48c9a20 100644 --- a/priv/repo/migrations/20240918113124_create_melt_quote.exs +++ b/priv/repo/migrations/20240918113124_create_melt_quote.exs @@ -2,7 +2,8 @@ defmodule Cashubrew.Repo.Migrations.CreateMeltQuote do use Ecto.Migration def change do - create table(:melt_quote) do + create table(:melt_quote, primary_key: false) do + add :id, :binary_id, primary_key: true add :request, :string, null: false add :unit, :string, null: false add :amount, :integer, null: false