mirror of
https://github.com/nbd-wtf/go-nostr.git
synced 2025-05-20 23:50:00 +02:00
128 lines
2.8 KiB
Go
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
|
|
}
|