go-nostr/nip60/lib.go
2025-01-25 23:35:53 -03:00

128 lines
2.8 KiB
Go

package nip60
import (
"context"
"fmt"
"strings"
"sync"
"github.com/nbd-wtf/go-nostr"
)
type WalletStash struct {
sync.Mutex
wallets map[string]*Wallet
pendingTokens map[string][]Token // tokens not yet assigned to a wallet
pendingHistory map[string][]HistoryEntry // history entries not yet assigned to a wallet
}
func LoadWallets(
ctx context.Context,
kr nostr.Keyer,
events <-chan *nostr.Event,
errors chan<- error,
) *WalletStash {
wl := &WalletStash{
wallets: make(map[string]*Wallet, 1),
pendingTokens: make(map[string][]Token),
pendingHistory: make(map[string][]HistoryEntry),
}
go func() {
for evt := range events {
wl.Lock()
switch evt.Kind {
case 37375:
wallet := &Wallet{}
if err := wallet.parse(ctx, kr, evt); err != nil {
wl.Unlock()
if errors != nil {
errors <- fmt.Errorf("event %s failed: %w", evt, err)
}
continue
}
for _, he := range wl.pendingHistory[wallet.Identifier] {
wallet.History = append(wallet.History, he)
}
for _, token := range wl.pendingTokens[wallet.Identifier] {
wallet.Tokens = append(wallet.Tokens, token)
}
wl.wallets[wallet.Identifier] = wallet
case 7375: // token
ref := evt.Tags.GetFirst([]string{"a", ""})
if ref == nil {
wl.Unlock()
if errors != nil {
errors <- fmt.Errorf("event %s missing 'a' tag", evt)
}
continue
}
spl := strings.SplitN((*ref)[1], ":", 3)
if len(spl) < 3 {
wl.Unlock()
if errors != nil {
errors <- fmt.Errorf("event %s invalid 'a' tag", evt)
}
continue
}
token := Token{}
if err := token.parse(ctx, kr, evt); err != nil {
wl.Unlock()
if errors != nil {
errors <- fmt.Errorf("event %s failed: %w", evt, err)
}
continue
}
if wallet, ok := wl.wallets[spl[2]]; ok {
wallet.Tokens = append(wallet.Tokens, token)
} else {
wl.pendingTokens[spl[2]] = append(wl.pendingTokens[spl[2]], token)
}
case 7376: // history
ref := evt.Tags.GetFirst([]string{"a", ""})
if ref == nil {
wl.Unlock()
if errors != nil {
errors <- fmt.Errorf("event %s missing 'a' tag", evt)
}
continue
}
spl := strings.SplitN((*ref)[1], ":", 3)
if len(spl) < 3 {
wl.Unlock()
if errors != nil {
errors <- fmt.Errorf("event %s invalid 'a' tag", evt)
}
continue
}
he := HistoryEntry{}
if err := he.parse(ctx, kr, evt); err != nil {
wl.Unlock()
if errors != nil {
errors <- fmt.Errorf("event %s failed: %w", evt, err)
}
continue
}
if wallet, ok := wl.wallets[spl[2]]; ok {
wallet.History = append(wallet.History, he)
} else {
wl.pendingHistory[spl[2]] = append(wl.pendingHistory[spl[2]], he)
}
}
wl.Unlock()
}
}()
return wl
}