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 }