diff --git a/cashu/nuts/nut05/nut05.go b/cashu/nuts/nut05/nut05.go index e50277e..6a2f5da 100644 --- a/cashu/nuts/nut05/nut05.go +++ b/cashu/nuts/nut05/nut05.go @@ -5,6 +5,7 @@ package nut05 import ( "encoding/json" + "errors" "github.com/elnosh/gonuts/cashu" ) @@ -31,6 +32,18 @@ func (state State) String() string { } } +func StringToState(state string) State { + switch state { + case "UNPAID": + return Unpaid + case "PENDING": + return Pending + case "PAID": + return Paid + } + return Unknown +} + type PostMeltQuoteBolt11Request struct { Request string `json:"request"` Unit string `json:"unit"` @@ -51,17 +64,18 @@ type PostMeltBolt11Request struct { Inputs cashu.Proofs `json:"inputs"` } -// Custom marshaler to display state as string +type TempQuote struct { + Quote string `json:"quote"` + Amount uint64 `json:"amount"` + FeeReserve uint64 `json:"fee_reserve"` + State string `json:"state"` + Paid bool `json:"paid"` // DEPRECATED: use state instead + Expiry int64 `json:"expiry"` + Preimage string `json:"payment_preimage,omitempty"` +} + func (quoteResponse *PostMeltQuoteBolt11Response) MarshalJSON() ([]byte, error) { - var response = struct { - Quote string `json:"quote"` - Amount uint64 `json:"amount"` - FeeReserve uint64 `json:"fee_reserve"` - State string `json:"state"` - Paid bool `json:"paid"` // DEPRECATED: use state instead - Expiry int64 `json:"expiry"` - Preimage string `json:"payment_preimage,omitempty"` - }{ + var tempQuote = TempQuote{ Quote: quoteResponse.Quote, Amount: quoteResponse.Amount, FeeReserve: quoteResponse.FeeReserve, @@ -70,5 +84,27 @@ func (quoteResponse *PostMeltQuoteBolt11Response) MarshalJSON() ([]byte, error) Expiry: quoteResponse.Expiry, Preimage: quoteResponse.Preimage, } - return json.Marshal(response) + return json.Marshal(tempQuote) +} + +func (quoteResponse *PostMeltQuoteBolt11Response) UnmarshalJSON(data []byte) error { + tempQuote := &TempQuote{} + + if err := json.Unmarshal(data, tempQuote); err != nil { + return err + } + + quoteResponse.Quote = tempQuote.Quote + quoteResponse.Amount = tempQuote.Amount + quoteResponse.FeeReserve = tempQuote.FeeReserve + state := StringToState(tempQuote.State) + if state == Unknown { + return errors.New("invalid state") + } + quoteResponse.State = state + quoteResponse.Paid = tempQuote.Paid + quoteResponse.Expiry = tempQuote.Expiry + quoteResponse.Preimage = tempQuote.Preimage + + return nil } diff --git a/mint/mint_integration_test.go b/mint/mint_integration_test.go index 129703a..01dde91 100644 --- a/mint/mint_integration_test.go +++ b/mint/mint_integration_test.go @@ -287,7 +287,6 @@ func TestMelt(t *testing.T) { // test already used proofs _, err = testMint.MeltTokens(testutils.BOLT11_METHOD, meltQuote.Id, validProofs) - //if !errors.Is(err, cashu.ProofAlreadyUsedErr) { if !errors.Is(err, cashu.QuoteAlreadyPaid) { t.Fatalf("expected error '%v' but got '%v' instead", cashu.QuoteAlreadyPaid, err) } diff --git a/wallet/wallet.go b/wallet/wallet.go index 1b12cea..afd807c 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -545,10 +545,18 @@ func (w *Wallet) Melt(invoice string, mint string) (*nut05.PostMeltQuoteBolt11Re meltBolt11Request := nut05.PostMeltBolt11Request{Quote: meltQuoteResponse.Quote, Inputs: proofs} meltBolt11Response, err := PostMeltBolt11(selectedMint.mintURL, meltBolt11Request) - if err != nil || !meltBolt11Response.Paid { + if err != nil { + w.saveProofs(proofs) + return nil, err + } + + // TODO: deprecate paid field and only use State + // TODO: check for PENDING as well + paid := meltBolt11Response.Paid && meltBolt11Response.State == nut05.Paid + if !paid { // save proofs if invoice was not paid w.saveProofs(proofs) - } else if meltBolt11Response.Paid { // TODO: USE STATE FIELD INSTEAD OF PAID + } else if paid { bolt11, err := decodepay.Decodepay(invoice) if err != nil { return nil, fmt.Errorf("error decoding bolt11 invoice: %v", err)