From ecd9ee2b7a169d04943b07c4249d6a938584f2b4 Mon Sep 17 00:00:00 2001 From: elnosh Date: Mon, 27 May 2024 15:22:31 -0500 Subject: [PATCH] wallet - invoice struct for mints and melts --- wallet/storage/bolt.go | 15 ++++----- wallet/storage/storage.go | 40 ++++++++++++++++++++--- wallet/wallet.go | 54 +++++++++++++++++++++++-------- wallet/wallet_integration_test.go | 2 +- 4 files changed, 85 insertions(+), 26 deletions(-) diff --git a/wallet/storage/bolt.go b/wallet/storage/bolt.go index 2cd6503..562a02d 100644 --- a/wallet/storage/bolt.go +++ b/wallet/storage/bolt.go @@ -8,7 +8,6 @@ import ( "github.com/elnosh/gonuts/cashu" "github.com/elnosh/gonuts/crypto" - "github.com/elnosh/gonuts/mint/lightning" bolt "go.etcd.io/bbolt" ) @@ -182,7 +181,7 @@ func (db *BoltDB) GetKeysets() crypto.KeysetsMap { return keysets } -func (db *BoltDB) SaveInvoice(invoice lightning.Invoice) error { +func (db *BoltDB) SaveInvoice(invoice Invoice) error { jsonbytes, err := json.Marshal(invoice) if err != nil { return fmt.Errorf("invalid invoice: %v", err) @@ -198,8 +197,8 @@ func (db *BoltDB) SaveInvoice(invoice lightning.Invoice) error { return nil } -func (db *BoltDB) GetInvoice(paymentHash string) *lightning.Invoice { - var invoice *lightning.Invoice +func (db *BoltDB) GetInvoice(paymentHash string) *Invoice { + var invoice *Invoice db.bolt.View(func(tx *bolt.Tx) error { invoicesb := tx.Bucket([]byte(invoicesBucket)) @@ -214,17 +213,17 @@ func (db *BoltDB) GetInvoice(paymentHash string) *lightning.Invoice { return invoice } -func (db *BoltDB) GetInvoices() []lightning.Invoice { - var invoices []lightning.Invoice +func (db *BoltDB) GetInvoices() []Invoice { + var invoices []Invoice db.bolt.View(func(tx *bolt.Tx) error { invoicesb := tx.Bucket([]byte(invoicesBucket)) c := invoicesb.Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { - var invoice lightning.Invoice + var invoice Invoice if err := json.Unmarshal(v, &invoice); err != nil { - invoices = []lightning.Invoice{} + invoices = []Invoice{} return nil } invoices = append(invoices, invoice) diff --git a/wallet/storage/storage.go b/wallet/storage/storage.go index f01c7f3..5d4ddfe 100644 --- a/wallet/storage/storage.go +++ b/wallet/storage/storage.go @@ -3,9 +3,26 @@ package storage import ( "github.com/elnosh/gonuts/cashu" "github.com/elnosh/gonuts/crypto" - "github.com/elnosh/gonuts/mint/lightning" ) +type QuoteType int + +const ( + Mint QuoteType = iota + 1 + Melt +) + +func (quote QuoteType) String() string { + switch quote { + case Mint: + return "Mint" + case Melt: + return "Melt" + default: + return "unknown" + } +} + type DB interface { SaveProof(cashu.Proof) error GetProofsByKeysetId(string) cashu.Proofs @@ -13,7 +30,22 @@ type DB interface { DeleteProof(string) error SaveKeyset(*crypto.Keyset) error GetKeysets() crypto.KeysetsMap - SaveInvoice(lightning.Invoice) error - GetInvoice(string) *lightning.Invoice - GetInvoices() []lightning.Invoice + SaveInvoice(Invoice) error + GetInvoice(string) *Invoice + GetInvoices() []Invoice +} + +type Invoice struct { + TransactionType QuoteType + // mint or melt quote id + Id string + QuoteAmount uint64 + PaymentRequest string + PaymentHash string + Preimage string + CreatedAt int64 + Paid bool + SettledAt int64 + InvoiceAmount uint64 + QuoteExpiry int64 } diff --git a/wallet/wallet.go b/wallet/wallet.go index f69a4ba..604c146 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -7,6 +7,7 @@ import ( "fmt" "net/url" "slices" + "time" "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/elnosh/gonuts/cashu" @@ -14,7 +15,6 @@ import ( "github.com/elnosh/gonuts/cashu/nuts/nut04" "github.com/elnosh/gonuts/cashu/nuts/nut05" "github.com/elnosh/gonuts/crypto" - "github.com/elnosh/gonuts/mint/lightning" "github.com/elnosh/gonuts/wallet/storage" decodepay "github.com/nbd-wtf/ln-decodepay" @@ -214,12 +214,16 @@ func (w *Wallet) RequestMint(amount uint64) (*nut04.PostMintQuoteBolt11Response, return nil, fmt.Errorf("error decoding bolt11 invoice: %v", err) } - invoice := lightning.Invoice{ - Id: mintResponse.Quote, - PaymentRequest: mintResponse.Request, - PaymentHash: bolt11.PaymentHash, - Amount: amount, - Expiry: mintResponse.Expiry, + invoice := storage.Invoice{ + TransactionType: storage.Mint, + QuoteAmount: amount, + Id: mintResponse.Quote, + PaymentRequest: mintResponse.Request, + PaymentHash: bolt11.PaymentHash, + CreatedAt: int64(bolt11.CreatedAt), + Paid: false, + InvoiceAmount: uint64(bolt11.MSatoshi / 1000), + QuoteExpiry: mintResponse.Expiry, } err = w.db.SaveInvoice(invoice) @@ -264,7 +268,7 @@ func (w *Wallet) MintTokens(quoteId string) (cashu.Proofs, error) { // create blinded messages activeKeyset := w.GetActiveSatKeyset() - blindedMessages, secrets, rs, err := createBlindedMessages(invoice.Amount, activeKeyset) + blindedMessages, secrets, rs, err := createBlindedMessages(invoice.QuoteAmount, activeKeyset) if err != nil { return nil, fmt.Errorf("error creating blinded messages: %v", err) } @@ -283,8 +287,8 @@ func (w *Wallet) MintTokens(quoteId string) (cashu.Proofs, error) { } // mark invoice as redeemed - invoice.Settled = true - invoice.Redeemed = true + invoice.Paid = true + invoice.SettledAt = time.Now().Unix() err = w.db.SaveInvoice(*invoice) if err != nil { return nil, err @@ -450,6 +454,30 @@ func (w *Wallet) Melt(invoice string, mint string) (*nut05.PostMeltBolt11Respons if err != nil || !meltBolt11Response.Paid { // save proofs if invoice was not paid w.saveProofs(proofs) + } else if meltBolt11Response.Paid { // save invoice to db + bolt11, err := decodepay.Decodepay(invoice) + if err != nil { + return nil, fmt.Errorf("error decoding bolt11 invoice: %v", err) + } + + invoice := storage.Invoice{ + TransactionType: storage.Melt, + QuoteAmount: amountNeeded, + Id: meltQuoteResponse.Quote, + PaymentRequest: invoice, + PaymentHash: bolt11.PaymentHash, + Preimage: meltBolt11Response.Preimage, + CreatedAt: int64(bolt11.CreatedAt), + Paid: true, + SettledAt: time.Now().Unix(), + InvoiceAmount: uint64(bolt11.MSatoshi / 1000), + QuoteExpiry: meltQuoteResponse.Expiry, + } + + err = w.db.SaveInvoice(invoice) + if err != nil { + return nil, err + } } return meltBolt11Response, err } @@ -746,7 +774,7 @@ func (w *Wallet) saveProofs(proofs cashu.Proofs) error { return nil } -func (w *Wallet) GetInvoiceByPaymentRequest(pr string) (*lightning.Invoice, error) { +func (w *Wallet) GetInvoiceByPaymentRequest(pr string) (*storage.Invoice, error) { bolt11, err := decodepay.Decodepay(pr) if err != nil { return nil, fmt.Errorf("invalid payment request: %v", err) @@ -755,10 +783,10 @@ func (w *Wallet) GetInvoiceByPaymentRequest(pr string) (*lightning.Invoice, erro return w.db.GetInvoice(bolt11.PaymentHash), nil } -func (w *Wallet) GetInvoiceByPaymentHash(hash string) *lightning.Invoice { +func (w *Wallet) GetInvoiceByPaymentHash(hash string) *storage.Invoice { return w.db.GetInvoice(hash) } -func (w *Wallet) GetAllInvoices() []lightning.Invoice { +func (w *Wallet) GetAllInvoices() []storage.Invoice { return w.db.GetInvoices() } diff --git a/wallet/wallet_integration_test.go b/wallet/wallet_integration_test.go index 71bf1bf..e1398a7 100644 --- a/wallet/wallet_integration_test.go +++ b/wallet/wallet_integration_test.go @@ -123,7 +123,7 @@ func TestMintTokens(t *testing.T) { t.Fatal("got unexpected nil invoice") } - proofs, err := testWallet.MintTokens(mintRes.Quote) + proofs, err := testWallet.MintTokens(mintInvoice.Id) if err != nil { t.Fatalf("got unexpected error: %v", err) }