github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/stellar/stellarsvc/minichat_test.go (about)

     1  package stellarsvc
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"testing"
     7  
     8  	"github.com/keybase/client/go/libkb"
     9  	"github.com/keybase/client/go/stellar"
    10  	"github.com/keybase/stellarnet"
    11  	"github.com/stretchr/testify/require"
    12  )
    13  
    14  type specTest struct {
    15  	payments []libkb.MiniChatPayment
    16  	summary  libkb.MiniChatPaymentSummary
    17  }
    18  
    19  var specTests = []specTest{
    20  	{
    21  		// check the nil response
    22  		payments: nil,
    23  		summary:  libkb.MiniChatPaymentSummary{XLMTotal: "0 XLM", DisplayTotal: "$0.00 USD"},
    24  	},
    25  	{
    26  		// check one payment, no currency
    27  		payments: []libkb.MiniChatPayment{
    28  			{Username: libkb.NewNormalizedUsername("alice"), Amount: "1"},
    29  		},
    30  		summary: libkb.MiniChatPaymentSummary{
    31  			Specs: []libkb.MiniChatPaymentSpec{
    32  				{Username: libkb.NewNormalizedUsername("alice"), XLMAmount: "1 XLM"},
    33  			},
    34  			XLMTotal:     "1 XLM",
    35  			DisplayTotal: "$0.32 USD",
    36  		},
    37  	},
    38  	{
    39  		// check one payment, XLM currency
    40  		payments: []libkb.MiniChatPayment{
    41  			{Username: libkb.NewNormalizedUsername("alice"), Amount: "1", Currency: "XLM"},
    42  		},
    43  		summary: libkb.MiniChatPaymentSummary{
    44  			Specs: []libkb.MiniChatPaymentSpec{
    45  				{Username: libkb.NewNormalizedUsername("alice"), XLMAmount: "1 XLM"},
    46  			},
    47  			XLMTotal:     "1 XLM",
    48  			DisplayTotal: "$0.32 USD",
    49  		},
    50  	},
    51  	{
    52  		// check one payment, USD currency
    53  		payments: []libkb.MiniChatPayment{
    54  			{Username: libkb.NewNormalizedUsername("alice"), Amount: "1", Currency: "USD"},
    55  		},
    56  		summary: libkb.MiniChatPaymentSummary{
    57  			Specs: []libkb.MiniChatPaymentSpec{
    58  				{
    59  					Username:      libkb.NewNormalizedUsername("alice"),
    60  					XLMAmount:     "3.1414139 XLM",
    61  					DisplayAmount: "$1.00 USD",
    62  				},
    63  			},
    64  			XLMTotal:     "3.1414139 XLM",
    65  			DisplayTotal: "$1.00 USD",
    66  		},
    67  	},
    68  	{
    69  		// check multiple payments
    70  		payments: []libkb.MiniChatPayment{
    71  			{Username: libkb.NewNormalizedUsername("alice"), Amount: "1", Currency: "USD"},
    72  			{Username: libkb.NewNormalizedUsername("bob"), Amount: "9.12", Currency: "XLM"},
    73  		},
    74  		summary: libkb.MiniChatPaymentSummary{
    75  			Specs: []libkb.MiniChatPaymentSpec{
    76  				{
    77  					Username:      libkb.NewNormalizedUsername("alice"),
    78  					XLMAmount:     "3.1414139 XLM",
    79  					DisplayAmount: "$1.00 USD",
    80  				},
    81  				{
    82  					Username:  libkb.NewNormalizedUsername("bob"),
    83  					XLMAmount: "9.1200000 XLM",
    84  				},
    85  			},
    86  			XLMTotal:     "12.2614139 XLM",
    87  			DisplayTotal: "$3.90 USD",
    88  		},
    89  	},
    90  	{
    91  		// check that the order of the results is the order of the payments argument
    92  		payments: []libkb.MiniChatPayment{
    93  			{Username: libkb.NewNormalizedUsername("bob"), Amount: "9.12", Currency: "XLM"},
    94  			{Username: libkb.NewNormalizedUsername("alice"), Amount: "1", Currency: "USD"},
    95  		},
    96  		summary: libkb.MiniChatPaymentSummary{
    97  			Specs: []libkb.MiniChatPaymentSpec{
    98  				{
    99  					Username:  libkb.NewNormalizedUsername("bob"),
   100  					XLMAmount: "9.1200000 XLM",
   101  				},
   102  				{
   103  					Username:      libkb.NewNormalizedUsername("alice"),
   104  					XLMAmount:     "3.1414139 XLM",
   105  					DisplayAmount: "$1.00 USD",
   106  				},
   107  			},
   108  			XLMTotal:     "12.2614139 XLM",
   109  			DisplayTotal: "$3.90 USD",
   110  		},
   111  	},
   112  	{
   113  		// check that an invalid currency returns an error in the spec
   114  		payments: []libkb.MiniChatPayment{
   115  			{Username: libkb.NewNormalizedUsername("alice"), Amount: "1", Currency: "USD"},
   116  			{Username: libkb.NewNormalizedUsername("bob"), Amount: "1", Currency: "XXX"},
   117  		},
   118  		summary: libkb.MiniChatPaymentSummary{
   119  			Specs: []libkb.MiniChatPaymentSpec{
   120  				{
   121  					Username:      libkb.NewNormalizedUsername("alice"),
   122  					XLMAmount:     "3.1414139 XLM",
   123  					DisplayAmount: "$1.00 USD",
   124  				},
   125  				{
   126  					Username: libkb.NewNormalizedUsername("bob"),
   127  					Error:    errors.New("FormatCurrencyWithCodeSuffix error: cannot find curency code \"XXX\""),
   128  				},
   129  			},
   130  			XLMTotal:     "3.1414139 XLM",
   131  			DisplayTotal: "$1.00 USD",
   132  		},
   133  	},
   134  }
   135  
   136  func TestSpecMiniChatPayments(t *testing.T) {
   137  	tc, cleanup := setupDesktopTest(t)
   138  	defer cleanup()
   139  	mctx := libkb.NewMetaContext(context.Background(), tc.G)
   140  
   141  	acceptDisclaimer(tc)
   142  
   143  	for i, st := range specTests {
   144  		out, err := stellar.SpecMiniChatPayments(mctx, tc.Srv.walletState, st.payments)
   145  		if err != nil {
   146  			t.Errorf("test %d: unexpected error: %s", i, err)
   147  			continue
   148  		}
   149  		require.NotNil(t, out)
   150  		require.Equal(t, st.summary, *out)
   151  	}
   152  }
   153  
   154  // TestPrepareMiniChatRelays checks that PrepareMiniChatPayments
   155  // (which is called by SendMiniChatPayments)
   156  // with a destination username that is a valid user but someone who
   157  // doesn't have a wallet will succeed and create a relay payment.
   158  func TestPrepareMiniChatRelays(t *testing.T) {
   159  	tc, cleanup := setupDesktopTest(t)
   160  	defer cleanup()
   161  	require.NotNil(t, tc.Srv.walletState)
   162  
   163  	tcw, cleanupw := setupDesktopTest(t)
   164  	defer cleanupw()
   165  
   166  	mctx := libkb.NewMetaContext(context.Background(), tc.G)
   167  
   168  	acceptDisclaimer(tc)
   169  	acceptDisclaimer(tcw)
   170  	payments := []libkb.MiniChatPayment{
   171  		{Username: libkb.NewNormalizedUsername("t_rebecca"), Amount: "1", Currency: "USD"},
   172  		{Username: libkb.NewNormalizedUsername(tcw.Fu.Username), Amount: "2", Currency: "XLM"},
   173  	}
   174  
   175  	_, senderAccountBundle, err := stellar.LookupSenderPrimary(mctx)
   176  	require.NoError(t, err)
   177  	senderSeed, err := stellarnet.NewSeedStr(senderAccountBundle.Signers[0].SecureNoLogString())
   178  	require.NoError(t, err)
   179  
   180  	prepared, unlock, err := stellar.PrepareMiniChatPayments(mctx, tc.Srv.walletState, senderSeed, nil, payments)
   181  	defer unlock()
   182  	require.NoError(t, err)
   183  	require.Len(t, prepared, 2)
   184  	for i, p := range prepared {
   185  		t.Logf("result %d: %+v", i, p)
   186  
   187  		switch p.Username.String() {
   188  		case "t_rebecca":
   189  			require.Nil(t, p.Direct)
   190  			require.NotNil(t, p.Relay)
   191  			require.Equal(t, "1", p.Relay.DisplayAmount)
   192  			require.Equal(t, "USD", p.Relay.DisplayCurrency)
   193  			require.True(t, p.Relay.QuickReturn)
   194  		case tcw.Fu.Username:
   195  			require.NotNil(t, p.Direct)
   196  			require.Nil(t, p.Relay)
   197  			require.True(t, p.Direct.QuickReturn)
   198  		default:
   199  			t.Fatalf("unknown username in result: %s", p.Username)
   200  		}
   201  	}
   202  }
   203  
   204  // TestPrepareMiniChatLowAmounts checks that PrepareMiniChatPayments
   205  // finds low amount errors early (and doesn't consume seqnos).
   206  func TestPrepareMiniChatLowAmounts(t *testing.T) {
   207  	tc, cleanup := setupDesktopTest(t)
   208  	defer cleanup()
   209  	require.NotNil(t, tc.Srv.walletState)
   210  
   211  	tcw, cleanupw := setupDesktopTest(t)
   212  	defer cleanupw()
   213  
   214  	mctx := libkb.NewMetaContext(context.Background(), tc.G)
   215  
   216  	acceptDisclaimer(tc)
   217  	acceptDisclaimer(tcw)
   218  	payments := []libkb.MiniChatPayment{
   219  		{Username: libkb.NewNormalizedUsername("t_rebecca"), Amount: "0.01", Currency: "USD"},
   220  		{Username: libkb.NewNormalizedUsername(tcw.Fu.Username), Amount: "0.5", Currency: "XLM"},
   221  	}
   222  
   223  	_, senderAccountBundle, err := stellar.LookupSenderPrimary(mctx)
   224  	require.NoError(t, err)
   225  	senderSeed, err := stellarnet.NewSeedStr(senderAccountBundle.Signers[0].SecureNoLogString())
   226  	require.NoError(t, err)
   227  
   228  	prepared, unlock, err := stellar.PrepareMiniChatPayments(mctx, tc.Srv.walletState, senderSeed, nil, payments)
   229  	defer unlock()
   230  	require.NoError(t, err)
   231  	require.Len(t, prepared, 2)
   232  	for i, p := range prepared {
   233  		t.Logf("result %d: %+v", i, p)
   234  
   235  		switch p.Username.String() {
   236  		case "t_rebecca":
   237  			require.Nil(t, p.Direct)
   238  			require.Nil(t, p.Relay)
   239  			require.Error(t, p.Error)
   240  			require.Empty(t, p.Seqno)
   241  			require.Empty(t, p.TxID)
   242  		case tcw.Fu.Username:
   243  			require.NotNil(t, p.Direct)
   244  			require.Nil(t, p.Relay)
   245  			require.Error(t, p.Error)
   246  			require.Empty(t, p.Seqno)
   247  			require.Empty(t, p.TxID)
   248  		default:
   249  			t.Fatalf("unknown username in result: %s", p.Username)
   250  		}
   251  	}
   252  }