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>
39 jvParams[jss::ledger_index] =
"current";
40 jvParams[jss::ripple_state][jss::currency] = currency;
42 jvParams[jss::ripple_state][jss::accounts].
append(acct_a.
human());
43 jvParams[jss::ripple_state][jss::accounts].
append(acct_b.
human());
45 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
51 testcase(
"Payment to Nonexistent Account");
52 using namespace test::jtx;
54 Env env{*
this, features};
62 testcase(
"Trust Nonexistent Account");
63 using namespace test::jtx;
66 Account alice{
"alice"};
68 env(trust(env.master, alice[
"USD"](100)), ter(
tecNO_DST));
74 testcase(
"Credit Limit");
75 using namespace test::jtx;
78 Account gw{
"gateway"};
79 Account alice{
"alice"};
82 env.fund(XRP(10000), gw, alice, bob);
88 BEAST_EXPECT(jrr[jss::error] ==
"entryNotFound");
91 env(trust(alice, gw[
"USD"](800)));
109 env(trust(alice, gw[
"USD"](700)));
130 env(trust(alice, gw[
"USD"](0)));
134 BEAST_EXPECT(jrr[jss::error] ==
"entryNotFound");
139 env(trust(alice, bob[
"USD"](600)));
142 env(trust(bob, alice[
"USD"](500)));
163 testcase(
"Direct Payment, Ripple");
164 using namespace test::jtx;
166 Env env{*
this, features};
167 Account alice{
"alice"};
170 env.fund(XRP(10000), alice, bob);
173 env(trust(alice, bob[
"USD"](600)));
174 env(trust(bob, alice[
"USD"](700)));
177 env(pay(alice, bob, alice[
"USD"](24)));
178 env.require(balance(bob, alice[
"USD"](24)));
181 env(pay(alice, bob, bob[
"USD"](33)));
182 env.require(balance(bob, alice[
"USD"](57)));
185 env(pay(bob, alice, bob[
"USD"](90)));
186 env.require(balance(bob, alice[
"USD"](-33)));
189 env(pay(alice, bob, bob[
"USD"](733)));
190 env.require(balance(bob, alice[
"USD"](700)));
193 env(pay(bob, alice, bob[
"USD"](1300)));
194 env.require(balance(bob, alice[
"USD"](-600)));
197 env(pay(bob, alice, bob[
"USD"](1)), ter(
tecPATH_DRY));
198 env.require(balance(bob, alice[
"USD"](-600)));
206 (with_rate ?
"With " :
"Without ") +
" Xfer Fee, " +
207 (subscribe ?
"With " :
"Without ") +
" Subscribe");
208 using namespace test::jtx;
210 Env env{*
this, features};
212 Account gw{
"gateway"};
213 Account alice{
"alice"};
216 env.fund(XRP(10000), gw, alice, bob);
219 env(trust(alice, gw[
"AUD"](100)));
220 env(trust(bob, gw[
"AUD"](100)));
222 env(pay(gw, alice, alice[
"AUD"](1)));
225 env.require(balance(alice, gw[
"AUD"](1)));
228 env(pay(alice, bob, gw[
"AUD"](1)));
231 env.require(balance(alice, gw[
"AUD"](0)));
232 env.require(balance(bob, gw[
"AUD"](1)));
233 env.require(balance(gw, bob[
"AUD"](-1)));
241 env(pay(bob, alice, gw[
"AUD"](0.5)), sendmax(gw[
"AUD"](0.55)));
246 env(pay(bob, alice, gw[
"AUD"](0.5)));
249 env.require(balance(alice, gw[
"AUD"](0.5)));
250 env.require(balance(bob, gw[
"AUD"](with_rate ? 0.45 : 0.5)));
251 env.require(balance(gw, bob[
"AUD"](with_rate ? -0.45 : -0.5)));
257 jvs[jss::accounts].
append(gw.human());
259 jvs[jss::streams].
append(
"transactions");
260 jvs[jss::streams].
append(
"ledger");
261 auto jv = wsc->invoke(
"subscribe", jvs);
262 BEAST_EXPECT(jv[jss::status] ==
"success");
266 using namespace std::chrono_literals;
267 BEAST_EXPECT(wsc->findMsg(5s, [](
auto const& jval) {
268 auto const& t = jval[jss::transaction];
269 return t[jss::TransactionType] == jss::Payment;
271 BEAST_EXPECT(wsc->findMsg(5s, [](
auto const& jval) {
272 return jval[jss::type] ==
"ledgerClosed";
276 wsc->invoke(
"unsubscribe", jv)[jss::status] ==
"success");
283 testcase(
"Payments With Paths and Fees");
284 using namespace test::jtx;
286 Env env{*
this, features};
287 Account gw{
"gateway"};
288 Account alice{
"alice"};
291 env.fund(XRP(10000), gw, alice, bob);
297 env(trust(alice, gw[
"AUD"](100)));
298 env(trust(bob, gw[
"AUD"](100)));
300 env(pay(gw, alice, alice[
"AUD"](4.4)));
301 env.require(balance(alice, gw[
"AUD"](4.4)));
305 env(pay(alice, bob, gw[
"AUD"](1)), sendmax(gw[
"AUD"](1.1)));
306 env.require(balance(alice, gw[
"AUD"](3.3)));
307 env.require(balance(bob, gw[
"AUD"](1)));
310 env(pay(alice, bob, bob[
"AUD"](1)), sendmax(gw[
"AUD"](1.1)));
311 env.require(balance(alice, gw[
"AUD"](2.2)));
312 env.require(balance(bob, gw[
"AUD"](2)));
315 env(pay(alice, bob, gw[
"AUD"](1)), sendmax(alice[
"AUD"](1.1)));
316 env.require(balance(alice, gw[
"AUD"](1.1)));
317 env.require(balance(bob, gw[
"AUD"](3)));
321 env(pay(alice, bob, bob[
"AUD"](1)),
322 sendmax(alice[
"AUD"](1.1)),
325 env.require(balance(alice, gw[
"AUD"](1.1)));
326 env.require(balance(bob, gw[
"AUD"](3)));
332 testcase(
"Indirect Payment");
333 using namespace test::jtx;
335 Env env{*
this, features};
336 Account gw{
"gateway"};
337 Account alice{
"alice"};
340 env.fund(XRP(10000), gw, alice, bob);
343 env(trust(alice, gw[
"USD"](600)));
344 env(trust(bob, gw[
"USD"](700)));
346 env(pay(gw, alice, alice[
"USD"](70)));
347 env(pay(gw, bob, bob[
"USD"](50)));
349 env.require(balance(alice, gw[
"USD"](70)));
350 env.require(balance(bob, gw[
"USD"](50)));
360 env.require(balance(alice, gw[
"USD"](70)));
361 env.require(balance(bob, gw[
"USD"](50)));
366 env.require(balance(alice, gw[
"USD"](65)));
367 env.require(balance(bob, gw[
"USD"](55)));
375 (with_rate ?
"With " :
"Without ") +
" Xfer Fee, ");
376 using namespace test::jtx;
378 Env env{*
this, features};
379 Account gw{
"gateway"};
380 Account amazon{
"amazon"};
381 Account alice{
"alice"};
383 Account carol{
"carol"};
385 env.fund(XRP(10000), gw, amazon, alice, bob, carol);
388 env(trust(amazon, gw[
"USD"](2000)));
389 env(trust(bob, alice[
"USD"](600)));
390 env(trust(bob, gw[
"USD"](1000)));
391 env(trust(carol, alice[
"USD"](700)));
392 env(trust(carol, gw[
"USD"](1000)));
397 env(pay(gw, bob, bob[
"USD"](100)));
398 env(pay(gw, carol, carol[
"USD"](100)));
403 env(pay(alice, amazon, gw[
"USD"](150)),
404 sendmax(alice[
"USD"](200)),
408 env(pay(alice, amazon, gw[
"USD"](150)),
417 carol[
"USD"].issue(),
423 env.require(balance(carol, gw[
"USD"](35)));
427 env.require(balance(alice, carol[
"USD"](-50)));
428 env.require(balance(carol, gw[
"USD"](50)));
430 env.require(balance(alice, bob[
"USD"](-100)));
431 env.require(balance(amazon, gw[
"USD"](150)));
432 env.require(balance(bob, gw[
"USD"](0)));
438 testcase(
"Set Invoice ID on Payment");
439 using namespace test::jtx;
441 Env env{*
this, features};
442 Account alice{
"alice"};
445 env.fund(XRP(10000), alice);
450 jvs[jss::accounts].
append(env.master.human());
452 jvs[jss::streams].
append(
"transactions");
453 BEAST_EXPECT(wsc->invoke(
"subscribe", jvs)[jss::status] ==
"success");
455 char const* invoiceid =
456 "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89";
460 pay(env.master, alice, XRP(10000)),
462 jv[jss::tx_blob] =
strHex(tx.stx->getSerializer().slice());
463 auto jrr = wsc->invoke(
"submit", jv)[jss::result];
464 BEAST_EXPECT(jrr[jss::status] ==
"success");
468 using namespace std::chrono_literals;
469 BEAST_EXPECT(wsc->findMsg(2s, [invoiceid](
auto const& jval) {
470 auto const& t = jval[jss::transaction];
471 return t[jss::TransactionType] == jss::Payment &&
472 t[sfInvoiceID.fieldName] == invoiceid;
475 BEAST_EXPECT(wsc->invoke(
"unsubscribe", jv)[jss::status] ==
"success");
499 using namespace test::jtx;
500 auto const sa = supported_amendments();
502 testWithFeatures(sa);