From be651343545cf3cce55cd3f1ededf9c077711f4d Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Wed, 29 Jan 2025 22:17:57 -0300 Subject: [PATCH] nip60: an e2e test with two wallets sending tokens around, but it's broken. --- nip60/stash.go | 2 +- nip60/wallet_test.go | 131 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 nip60/wallet_test.go diff --git a/nip60/stash.go b/nip60/stash.go index 4f76be2..d709b59 100644 --- a/nip60/stash.go +++ b/nip60/stash.go @@ -141,7 +141,7 @@ func loadStash( // if we already have a wallet with this identifier then we must be careful if curr, ok := wl.wallets[wallet.Identifier]; ok { // if the metadata we have is newer ignore this event - if curr.event.CreatedAt > ie.Event.CreatedAt { + if curr.event != nil && curr.event.CreatedAt > ie.Event.CreatedAt { wl.Unlock() continue } diff --git a/nip60/wallet_test.go b/nip60/wallet_test.go new file mode 100644 index 0000000..2278d0c --- /dev/null +++ b/nip60/wallet_test.go @@ -0,0 +1,131 @@ +package nip60 + +import ( + "context" + "os" + "testing" + "time" + + "github.com/nbd-wtf/go-nostr" + "github.com/nbd-wtf/go-nostr/keyer" + "github.com/stretchr/testify/require" +) + +var testRelays = []string{ + "wss://relay.damus.io", + "wss://nos.lol", + "wss://relay.nostr.band", +} + +func TestWalletTransfer(t *testing.T) { + ctx := context.Background() + + // setup first wallet + sk1 := os.Getenv("NIP60_SECRET_KEY_1") + if sk1 == "" { + t.Skip("NIP60_SECRET_KEY_1 not set") + } + kr1, err := keyer.NewPlainKeySigner(sk1) + if err != nil { + t.Fatal(err) + } + + pool := nostr.NewSimplePool(ctx) + stash1 := LoadStash(ctx, kr1, pool, testRelays) + if stash1 == nil { + t.Fatal("failed to load stash 1") + } + + // setup second wallet + sk2 := os.Getenv("NIP60_SECRET_KEY_2") + if sk2 == "" { + t.Skip("NIP60_SECRET_KEY_2 not set") + } + kr2, err := keyer.NewPlainKeySigner(sk2) + if err != nil { + t.Fatal(err) + } + + stash2 := LoadStash(ctx, kr2, pool, testRelays) + if stash2 == nil { + t.Fatal("failed to load stash 2") + } + + // handle events from both stashes + go func() { + for { + select { + case evt := <-stash1.Changes: + pool.PublishMany(ctx, testRelays, evt) + case evt := <-stash2.Changes: + pool.PublishMany(ctx, testRelays, evt) + case err := <-stash1.Processed: + if err != nil { + t.Errorf("stash1 processing error: %v", err) + } + case err := <-stash2.Processed: + if err != nil { + t.Errorf("stash2 processing error: %v", err) + } + case <-ctx.Done(): + return + } + } + }() + + // wait for initial load + select { + case <-stash1.Stable: + case <-time.After(15 * time.Second): + t.Fatal("timeout waiting for stash 1 to load") + } + + select { + case <-stash2.Stable: + case <-time.After(15 * time.Second): + t.Fatal("timeout waiting for stash 2 to load") + } + + // ensure wallets exist and have tokens + w1 := stash1.EnsureWallet("test") + require.Greater(t, w1.Balance(), uint64(0), "wallet 1 has no balance") + + w2 := stash2.EnsureWallet("test") + initialBalance1 := w1.Balance() + initialBalance2 := w2.Balance() + + t.Logf("initial balances: w1=%d w2=%d", initialBalance1, initialBalance2) + + // send half of wallet 1's balance to wallet 2 + pk2, err := kr2.GetPublicKey(ctx) + require.NoError(t, err) + + halfBalance := initialBalance1 / 2 + token, err := w1.SendToken(ctx, halfBalance, WithP2PK(pk2)) + require.NoError(t, err) + + // receive token in wallet 2 + err = w2.ReceiveToken(ctx, token) + require.NoError(t, err) + + // verify balances + require.Equal(t, initialBalance1-halfBalance, w1.Balance(), "wallet 1 balance wrong after send") + require.Equal(t, initialBalance2+halfBalance, w2.Balance(), "wallet 2 balance wrong after receive") + + // now send it back + pk1, err := kr1.GetPublicKey(ctx) + require.NoError(t, err) + + token, err = w2.SendToken(ctx, halfBalance, WithP2PK(pk1)) + require.NoError(t, err) + + // receive token back in wallet 1 + err = w1.ReceiveToken(ctx, token) + require.NoError(t, err) + + // verify final balances match initial + require.Equal(t, initialBalance1, w1.Balance(), "wallet 1 final balance wrong") + require.Equal(t, initialBalance2, w2.Balance(), "wallet 2 final balance wrong") + + t.Logf("final balances: w1=%d w2=%d", w1.Balance(), w2.Balance()) +}