20 #include <ripple/beast/unit_test.h>
21 #include <ripple/protocol/Feature.h>
22 #include <ripple/protocol/SField.h>
23 #include <ripple/protocol/jss.h>
25 #include <test/jtx/WSClient.h>
34 testcase(
"Payment to Nonexistent Account");
35 using namespace test::jtx;
37 Env env{*
this, features};
45 testcase(
"Trust Nonexistent Account");
46 using namespace test::jtx;
49 Account alice{
"alice"};
51 env(trust(env.master, alice[
"USD"](100)), ter(
tecNO_DST));
57 testcase(
"Credit Limit");
58 using namespace test::jtx;
61 Account gw{
"gateway"};
62 Account alice{
"alice"};
65 env.fund(XRP(10000), gw, alice, bob);
70 auto jrr = ledgerEntryState(env, gw, alice,
"USD");
71 BEAST_EXPECT(jrr[jss::error] ==
"entryNotFound");
74 env(trust(alice, gw[
"USD"](800)));
76 jrr = ledgerEntryState(env, gw, alice,
"USD");
92 env(trust(alice, gw[
"USD"](700)));
94 jrr = ledgerEntryState(env, gw, alice,
"USD");
113 env(trust(alice, gw[
"USD"](0)));
116 jrr = ledgerEntryState(env, gw, alice,
"USD");
117 BEAST_EXPECT(jrr[jss::error] ==
"entryNotFound");
122 env(trust(alice, bob[
"USD"](600)));
125 env(trust(bob, alice[
"USD"](500)));
128 jrr = ledgerEntryState(env, alice, bob,
"USD");
146 testcase(
"Direct Payment, Ripple");
147 using namespace test::jtx;
149 Env env{*
this, features};
150 Account alice{
"alice"};
153 env.fund(XRP(10000), alice, bob);
156 env(trust(alice, bob[
"USD"](600)));
157 env(trust(bob, alice[
"USD"](700)));
160 env(pay(alice, bob, alice[
"USD"](24)));
161 env.require(balance(bob, alice[
"USD"](24)));
164 env(pay(alice, bob, bob[
"USD"](33)));
165 env.require(balance(bob, alice[
"USD"](57)));
168 env(pay(bob, alice, bob[
"USD"](90)));
169 env.require(balance(bob, alice[
"USD"](-33)));
172 env(pay(alice, bob, bob[
"USD"](733)));
173 env.require(balance(bob, alice[
"USD"](700)));
176 env(pay(bob, alice, bob[
"USD"](1300)));
177 env.require(balance(bob, alice[
"USD"](-600)));
180 env(pay(bob, alice, bob[
"USD"](1)), ter(
tecPATH_DRY));
181 env.require(balance(bob, alice[
"USD"](-600)));
189 (with_rate ?
"With " :
"Without ") +
" Xfer Fee, " +
190 (subscribe ?
"With " :
"Without ") +
" Subscribe");
191 using namespace test::jtx;
193 Env env{*
this, features};
195 Account gw{
"gateway"};
196 Account alice{
"alice"};
199 env.fund(XRP(10000), gw, alice, bob);
202 env(trust(alice, gw[
"AUD"](100)));
203 env(trust(bob, gw[
"AUD"](100)));
205 env(pay(gw, alice, alice[
"AUD"](1)));
208 env.require(balance(alice, gw[
"AUD"](1)));
211 env(pay(alice, bob, gw[
"AUD"](1)));
214 env.require(balance(alice, gw[
"AUD"](0)));
215 env.require(balance(bob, gw[
"AUD"](1)));
216 env.require(balance(gw, bob[
"AUD"](-1)));
224 env(pay(bob, alice, gw[
"AUD"](0.5)), sendmax(gw[
"AUD"](0.55)));
229 env(pay(bob, alice, gw[
"AUD"](0.5)));
232 env.require(balance(alice, gw[
"AUD"](0.5)));
233 env.require(balance(bob, gw[
"AUD"](with_rate ? 0.45 : 0.5)));
234 env.require(balance(gw, bob[
"AUD"](with_rate ? -0.45 : -0.5)));
240 jvs[jss::accounts].
append(gw.human());
242 jvs[jss::streams].
append(
"transactions");
243 jvs[jss::streams].
append(
"ledger");
244 auto jv = wsc->invoke(
"subscribe", jvs);
245 BEAST_EXPECT(jv[jss::status] ==
"success");
249 using namespace std::chrono_literals;
250 BEAST_EXPECT(wsc->findMsg(5s, [](
auto const& jval) {
251 auto const& t = jval[jss::transaction];
252 return t[jss::TransactionType] == jss::Payment;
254 BEAST_EXPECT(wsc->findMsg(5s, [](
auto const& jval) {
255 return jval[jss::type] ==
"ledgerClosed";
259 wsc->invoke(
"unsubscribe", jv)[jss::status] ==
"success");
266 testcase(
"Payments With Paths and Fees");
267 using namespace test::jtx;
269 Env env{*
this, features};
270 Account gw{
"gateway"};
271 Account alice{
"alice"};
274 env.fund(XRP(10000), gw, alice, bob);
280 env(trust(alice, gw[
"AUD"](100)));
281 env(trust(bob, gw[
"AUD"](100)));
283 env(pay(gw, alice, alice[
"AUD"](4.4)));
284 env.require(balance(alice, gw[
"AUD"](4.4)));
288 env(pay(alice, bob, gw[
"AUD"](1)), sendmax(gw[
"AUD"](1.1)));
289 env.require(balance(alice, gw[
"AUD"](3.3)));
290 env.require(balance(bob, gw[
"AUD"](1)));
293 env(pay(alice, bob, bob[
"AUD"](1)), sendmax(gw[
"AUD"](1.1)));
294 env.require(balance(alice, gw[
"AUD"](2.2)));
295 env.require(balance(bob, gw[
"AUD"](2)));
298 env(pay(alice, bob, gw[
"AUD"](1)), sendmax(alice[
"AUD"](1.1)));
299 env.require(balance(alice, gw[
"AUD"](1.1)));
300 env.require(balance(bob, gw[
"AUD"](3)));
304 env(pay(alice, bob, bob[
"AUD"](1)),
305 sendmax(alice[
"AUD"](1.1)),
308 env.require(balance(alice, gw[
"AUD"](1.1)));
309 env.require(balance(bob, gw[
"AUD"](3)));
315 testcase(
"Indirect Payment");
316 using namespace test::jtx;
318 Env env{*
this, features};
319 Account gw{
"gateway"};
320 Account alice{
"alice"};
323 env.fund(XRP(10000), gw, alice, bob);
326 env(trust(alice, gw[
"USD"](600)));
327 env(trust(bob, gw[
"USD"](700)));
329 env(pay(gw, alice, alice[
"USD"](70)));
330 env(pay(gw, bob, bob[
"USD"](50)));
332 env.require(balance(alice, gw[
"USD"](70)));
333 env.require(balance(bob, gw[
"USD"](50)));
343 env.require(balance(alice, gw[
"USD"](70)));
344 env.require(balance(bob, gw[
"USD"](50)));
349 env.require(balance(alice, gw[
"USD"](65)));
350 env.require(balance(bob, gw[
"USD"](55)));
358 (with_rate ?
"With " :
"Without ") +
" Xfer Fee, ");
359 using namespace test::jtx;
361 Env env{*
this, features};
362 Account gw{
"gateway"};
363 Account amazon{
"amazon"};
364 Account alice{
"alice"};
366 Account carol{
"carol"};
368 env.fund(XRP(10000), gw, amazon, alice, bob, carol);
371 env(trust(amazon, gw[
"USD"](2000)));
372 env(trust(bob, alice[
"USD"](600)));
373 env(trust(bob, gw[
"USD"](1000)));
374 env(trust(carol, alice[
"USD"](700)));
375 env(trust(carol, gw[
"USD"](1000)));
380 env(pay(gw, bob, bob[
"USD"](100)));
381 env(pay(gw, carol, carol[
"USD"](100)));
386 env(pay(alice, amazon, gw[
"USD"](150)),
387 sendmax(alice[
"USD"](200)),
391 env(pay(alice, amazon, gw[
"USD"](150)),
400 carol[
"USD"].issue(),
406 env.require(balance(carol, gw[
"USD"](35)));
410 env.require(balance(alice, carol[
"USD"](-50)));
411 env.require(balance(carol, gw[
"USD"](50)));
413 env.require(balance(alice, bob[
"USD"](-100)));
414 env.require(balance(amazon, gw[
"USD"](150)));
415 env.require(balance(bob, gw[
"USD"](0)));
421 testcase(
"Set Invoice ID on Payment");
422 using namespace test::jtx;
424 Env env{*
this, features};
425 Account alice{
"alice"};
428 env.fund(XRP(10000), alice);
433 jvs[jss::accounts].
append(env.master.human());
435 jvs[jss::streams].
append(
"transactions");
436 BEAST_EXPECT(wsc->invoke(
"subscribe", jvs)[jss::status] ==
"success");
438 char const* invoiceid =
439 "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89";
443 pay(env.master, alice, XRP(10000)),
445 jv[jss::tx_blob] =
strHex(tx.stx->getSerializer().slice());
446 auto jrr = wsc->invoke(
"submit", jv)[jss::result];
447 BEAST_EXPECT(jrr[jss::status] ==
"success");
451 using namespace std::chrono_literals;
452 BEAST_EXPECT(wsc->findMsg(2s, [invoiceid](
auto const& jval) {
453 auto const& t = jval[jss::transaction];
454 return t[jss::TransactionType] == jss::Payment &&
455 t[sfInvoiceID.fieldName] == invoiceid;
458 BEAST_EXPECT(wsc->invoke(
"unsubscribe", jv)[jss::status] ==
"success");
482 using namespace test::jtx;
483 auto const sa = supported_amendments();
485 testWithFeatures(sa);