diff --git a/testutils/utils.go b/testutils/utils.go index dae4f3c..90180be 100644 --- a/testutils/utils.go +++ b/testutils/utils.go @@ -372,6 +372,20 @@ func GetValidProofsForAmount(amount uint64, mint *mint.Mint, payer *btcdocker.Ln return proofs, nil } +func Fees(proofs cashu.Proofs, mint string) (uint, error) { + keysetResponse, err := wallet.GetAllKeysets(mint) + if err != nil { + return 0, err + } + + feePpk := keysetResponse.Keysets[0].InputFeePpk + var fees uint = 0 + for i := 0; i < len(proofs); i++ { + fees += feePpk + } + return (fees + 999) / 1000, nil +} + type NutshellMintContainer struct { testcontainers.Container Host string diff --git a/wallet/wallet_integration_test.go b/wallet/wallet_integration_test.go index 6a5e3db..e1fe749 100644 --- a/wallet/wallet_integration_test.go +++ b/wallet/wallet_integration_test.go @@ -6,6 +6,7 @@ import ( "context" "errors" "flag" + "fmt" "log" "os" "path/filepath" @@ -87,6 +88,17 @@ func testMain(m *testing.M) int { }() go mint.StartMintServer(testMint) + mintPath := filepath.Join(".", "testmintwithfees") + mintWithFees, err := testutils.CreateTestMintServer(lnd1, "mintsecretkey", "8888", mintPath, 100) + if err != nil { + log.Println(err) + return 1 + } + defer func() { + os.RemoveAll(mintPath) + }() + go mint.StartMintServer(mintWithFees) + return m.Run() } @@ -173,6 +185,36 @@ func TestSend(t *testing.T) { if !errors.Is(err, wallet.ErrInsufficientMintBalance) { t.Fatalf("expected error '%v' but got error '%v'", wallet.ErrInsufficientMintBalance, err) } + + // test mint with fees + mintWithFeesURL := "http://127.0.0.1:8888" + feesWalletPath := filepath.Join(".", "/testsendwalletfees") + feesWallet, err := testutils.CreateTestWallet(feesWalletPath, mintWithFeesURL) + if err != nil { + t.Fatal(err) + } + defer func() { + os.RemoveAll(feesWalletPath) + }() + + err = testutils.FundCashuWallet(ctx, feesWallet, lnd2, 10000) + if err != nil { + t.Fatalf("error funding wallet: %v", err) + } + + sendAmount = 2000 + token, err = feesWallet.Send(sendAmount, mintWithFeesURL) + if err != nil { + t.Fatalf("got unexpected error: %v", err) + } + + fees, err := testutils.Fees(token.Token[0].Proofs, mintWithFeesURL) + if err != nil { + t.Fatalf("got unexpected error: %v", err) + } + if token.TotalAmount() != sendAmount+uint64(fees) { + t.Fatalf("expected token amount of '%v' but got '%v' instead", sendAmount+uint64(fees), token.TotalAmount()) + } } func TestReceive(t *testing.T) { @@ -255,7 +297,53 @@ func TestReceive(t *testing.T) { if !slices.Contains(trustedMints, mint2URL) { t.Fatalf("expected '%v' in list of trusted of trusted mints", mint2URL) } +} + +func TestReceiveFees(t *testing.T) { + // mint with fees url + mintURL := "http://127.0.0.1:8888" + testWalletPath := filepath.Join(".", "/testreceivefees") + testWallet, err := testutils.CreateTestWallet(testWalletPath, mintURL) + if err != nil { + t.Fatal(err) + } + defer func() { + os.RemoveAll(testWalletPath) + }() + + err = testutils.FundCashuWallet(ctx, testWallet, lnd2, 30000) + if err != nil { + t.Fatalf("error funding wallet: %v", err) + } + testWalletPath2 := filepath.Join(".", "/testreceivefees2") + testWallet2, err := testutils.CreateTestWallet(testWalletPath2, mintURL) + if err != nil { + t.Fatal(err) + } + defer func() { + os.RemoveAll(testWalletPath2) + }() + + var sendAmount uint64 = 2000 + token, err := testWallet.Send(sendAmount, mintURL) + if err != nil { + t.Fatalf("got unexpected error in send: %v", err) + } + + amountReceived, err := testWallet2.Receive(*token, false) + if err != nil { + t.Fatalf("got unexpected error in receive: %v", err) + } + + fees, err := testutils.Fees(token.Token[0].Proofs, mintURL) + if err != nil { + t.Fatalf("got unexpected error: %v", err) + } + + if amountReceived != token.TotalAmount()-uint64(fees) { + t.Fatalf("expected received amount of '%v' but got '%v' instead", token.TotalAmount()-uint64(fees), amountReceived) + } } func TestMelt(t *testing.T) { @@ -305,6 +393,36 @@ func TestMelt(t *testing.T) { t.Fatalf("expected error '%v' but got error '%v'", wallet.ErrMintNotExist, err) } + // test melt with fees + mintWithFeesURL := "http://127.0.0.1:8888" + feesWalletPath := filepath.Join(".", "/testsendwalletfees") + feesWallet, err := testutils.CreateTestWallet(feesWalletPath, mintWithFeesURL) + if err != nil { + t.Fatal(err) + } + defer func() { + os.RemoveAll(feesWalletPath) + }() + + err = testutils.FundCashuWallet(ctx, feesWallet, lnd2, 10000) + if err != nil { + t.Fatalf("error funding wallet: %v", err) + } + + // create invoice for melt request + invoice = lnrpc.Invoice{Value: 5000} + addInvoiceResponse, err = lnd2.Client.AddInvoice(ctx, &invoice) + if err != nil { + t.Fatalf("error creating invoice: %v", err) + } + + meltResponse, err = feesWallet.Melt(addInvoiceResponse.PaymentRequest, mintWithFeesURL) + if err != nil { + t.Fatalf("got unexpected melt error: %v", err) + } + if !meltResponse.Paid { + t.Fatalf("expected paid melt") + } } // check balance is correct after certain operations @@ -377,6 +495,64 @@ func TestWalletBalance(t *testing.T) { } } +// check balance is correct after ops with fees +func TestWalletBalanceFees(t *testing.T) { + mintURL := "http://127.0.0.1:8888" + testWalletPath := filepath.Join(".", "/testwalletbalancefees") + balanceTestWallet, err := testutils.CreateTestWallet(testWalletPath, mintURL) + if err != nil { + t.Fatal(err) + } + defer func() { + os.RemoveAll(testWalletPath) + }() + + err = testutils.FundCashuWallet(ctx, balanceTestWallet, lnd2, 30000) + if err != nil { + t.Fatalf("error funding wallet: %v", err) + } + + testWalletPath2 := filepath.Join(".", "/testreceivefees2") + balanceTestWallet2, err := testutils.CreateTestWallet(testWalletPath2, mintURL) + if err != nil { + t.Fatal(err) + } + defer func() { + os.RemoveAll(testWalletPath2) + }() + + sendAmounts := []uint64{1200, 2000, 5000} + + for _, sendAmount := range sendAmounts { + balance := balanceTestWallet.GetBalance() + // test balance after send + token, err := balanceTestWallet.Send(sendAmount, mintURL) + if err != nil { + t.Fatalf("unexpected error in send: %v", err) + } + fees, err := testutils.Fees(token.Token[0].Proofs, mintURL) + if err != nil { + t.Fatalf("got unexpected error: %v", err) + } + expectedBalance := balance - sendAmount - uint64(fees) + if balanceTestWallet.GetBalance() != expectedBalance { + t.Fatalf("expected balance of '%v' but got '%v' instead", expectedBalance, balanceTestWallet.GetBalance()) + } + + // test balance in receiving wallet + balanceBeforeReceive := balanceTestWallet2.GetBalance() + _, err = balanceTestWallet2.Receive(*token, false) + if err != nil { + t.Fatalf("got unexpected error: %v", err) + } + expectedBalance = balanceBeforeReceive + token.TotalAmount() - uint64(fees) + if balanceTestWallet2.GetBalance() != expectedBalance { + t.Fatalf("expected balance of '%v' but got '%v' instead", expectedBalance, balanceTestWallet2.GetBalance()) + } + } + +} + func TestSendToPubkey(t *testing.T) { nutshellMint, err := testutils.CreateNutshellMintContainer(ctx) if err != nil {