From 3f901954e632e10f3176dc9c266ef8f08118a75e Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Fri, 31 Jan 2025 15:20:41 -0300 Subject: [PATCH] nip60: emit history. --- nip60/pay.go | 20 ++++++++++++++++++-- nip60/receive.go | 12 ++++++++++++ nip60/send.go | 22 +++++++++++++++++++++- 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/nip60/pay.go b/nip60/pay.go index bcdfbc4..dd12f46 100644 --- a/nip60/pay.go +++ b/nip60/pay.go @@ -7,6 +7,7 @@ import ( "github.com/elnosh/gonuts/cashu" "github.com/elnosh/gonuts/cashu/nuts/nut05" + "github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr/nip60/client" ) @@ -117,14 +118,29 @@ inspectmeltstatusresponse: } // the invoice has been paid, now we save the change we got - change, err := constructProofs(preChange, meltStatus.Change, ksKeys) + changeProofs, err := constructProofs(preChange, meltStatus.Change, ksKeys) if err != nil { return "", fmt.Errorf("failed to construct principal proofs: %w", err) } - if err := w.saveChangeAndDeleteUsedTokens(ctx, chosen.mint, change, chosen.tokenIndexes); err != nil { + he := HistoryEntry{ + event: &nostr.Event{}, + tokenEventIDs: make([]string, 0, 1), + nutZaps: make([]bool, 0, 1), + createdAt: nostr.Now(), + In: false, + Amount: chosen.proofs.Amount() - changeProofs.Amount(), + } + + if err := w.saveChangeAndDeleteUsedTokens(ctx, chosen.mint, changeProofs, chosen.tokenIndexes, &he); err != nil { return "", err } + w.wl.Lock() + if err := he.toEvent(ctx, w.wl.kr, w.Identifier, he.event); err == nil { + w.wl.PublishUpdate(*he.event, nil, nil, nil, true) + } + w.wl.Unlock() + return meltStatus.Preimage, nil } diff --git a/nip60/receive.go b/nip60/receive.go index c56a107..ecdb9a9 100644 --- a/nip60/receive.go +++ b/nip60/receive.go @@ -106,8 +106,20 @@ saveproofs: return fmt.Errorf("failed to make new token: %w", err) } + he := HistoryEntry{ + event: &nostr.Event{}, + tokenEventIDs: []string{newToken.event.ID}, + nutZaps: []bool{false}, + createdAt: nostr.Now(), + In: true, + Amount: newToken.Proofs.Amount(), + } + w.wl.Lock() w.wl.PublishUpdate(*newToken.event, nil, &newToken, nil, false) + if err := he.toEvent(ctx, w.wl.kr, w.Identifier, he.event); err == nil { + w.wl.PublishUpdate(*he.event, nil, nil, nil, true) + } w.wl.Unlock() w.tokensMu.Lock() diff --git a/nip60/send.go b/nip60/send.go index 08e2d25..5a7d5a1 100644 --- a/nip60/send.go +++ b/nip60/send.go @@ -100,10 +100,25 @@ func (w *Wallet) SendToken(ctx context.Context, amount uint64, opts ...SendOptio return "", err } - if err := w.saveChangeAndDeleteUsedTokens(ctx, chosen.mint, changeProofs, chosen.tokenIndexes); err != nil { + he := HistoryEntry{ + event: &nostr.Event{}, + tokenEventIDs: make([]string, 0, 1), + nutZaps: make([]bool, 0, 1), + createdAt: nostr.Now(), + In: false, + Amount: chosen.proofs.Amount() - changeProofs.Amount(), + } + + if err := w.saveChangeAndDeleteUsedTokens(ctx, chosen.mint, changeProofs, chosen.tokenIndexes, &he); err != nil { return "", err } + w.wl.Lock() + if err := he.toEvent(ctx, w.wl.kr, w.Identifier, he.event); err == nil { + w.wl.PublishUpdate(*he.event, nil, nil, nil, true) + } + w.wl.Unlock() + // serialize token we're sending out token, err := cashu.NewTokenV4(proofsToSend, chosen.mint, cashu.Sat, true) if err != nil { @@ -118,6 +133,7 @@ func (w *Wallet) saveChangeAndDeleteUsedTokens( mintURL string, changeProofs cashu.Proofs, usedTokenIndexes []int, + he *HistoryEntry, ) error { // delete spent tokens and save our change updatedTokens := make([]Token, 0, len(w.Tokens)) @@ -161,6 +177,10 @@ func (w *Wallet) saveChangeAndDeleteUsedTokens( // we don't have to lock tokensMu here because this function will always be called with that lock already held w.Tokens = append(updatedTokens, changeToken) + + // fill in the history created token + he.tokenEventIDs = append(he.tokenEventIDs, changeToken.event.ID) + he.nutZaps = append(he.nutZaps, false) } return nil