3#include <xrpl/basics/chrono.h>
4#include <xrpl/ledger/Dir.h>
5#include <xrpl/protocol/Feature.h>
6#include <xrpl/protocol/Indexes.h>
7#include <xrpl/protocol/PayChan.h>
8#include <xrpl/protocol/TxFlags.h>
9#include <xrpl/protocol/jss.h>
13using namespace jtx::paychan;
24 return {k.key, view.
read(k)};
42 auto const slep = view.
read({ltPAYCHAN, chan});
45 return (*slep)[sfAmount];
51 auto const slep = view.
read({ltPAYCHAN, chan});
54 if (
auto const r = (*slep)[~sfExpiration])
65 Env env{*
this, features};
66 auto const alice =
Account(
"alice");
67 auto const bob =
Account(
"bob");
68 auto USDA = alice[
"USD"];
69 env.fund(
XRP(10000), alice, bob);
70 auto const pk = alice.pk();
71 auto const settleDelay = 100s;
72 auto const chan =
channel(alice, bob, env.seq(alice));
73 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
78 auto const preAlice = env.balance(alice);
79 env(
fund(alice, chan,
XRP(1000)));
80 auto const feeDrops = env.current()->fees().base;
81 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
86 BEAST_EXPECT(chanBal ==
XRP(0));
87 BEAST_EXPECT(chanAmt ==
XRP(2000));
103 env(
fund(alice,
channel(alice,
"noAccount", env.seq(alice) - 1),
XRP(1000)),
110 auto const iou = USDA(100).value();
111 auto const negXRP =
XRP(-100).value();
112 auto const posXRP =
XRP(100).value();
122 auto const delta =
XRP(500);
123 auto const reqBal = chanBal + delta;
124 auto const authAmt = reqBal +
XRP(-100);
125 assert(reqBal <= chanAmt);
130 auto const preBob = env.balance(bob);
131 auto const delta =
XRP(500);
132 auto const reqBal = chanBal + delta;
133 auto const authAmt = reqBal +
XRP(100);
134 assert(reqBal <= chanAmt);
135 env(
claim(alice, chan, reqBal, authAmt));
137 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
138 BEAST_EXPECT(env.balance(bob) == preBob + delta);
143 auto preBob = env.balance(bob);
144 auto const delta =
XRP(500);
145 auto const reqBal = chanBal + delta;
146 auto const authAmt = reqBal +
XRP(100);
147 assert(reqBal <= chanAmt);
149 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
151 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
152 auto const feeDrops = env.current()->fees().base;
153 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
157 preBob = env.balance(bob);
158 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
161 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
162 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
166 auto const preBob = env.balance(bob);
169 assert(reqAmt <= chanAmt);
173 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
174 BEAST_EXPECT(env.balance(bob) == preBob);
180 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
188 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
196 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
200 auto const preAlice = env.balance(alice);
201 auto const preBob = env.balance(bob);
204 auto const feeDrops = env.current()->fees().base;
205 auto const delta = chanAmt - chanBal;
206 assert(delta > beast::zero);
207 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
208 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
219 Env env{*
this, features};
220 auto const alice =
Account(
"alice");
221 auto const bob =
Account(
"bob");
222 auto const cho =
Account(
"cho");
223 env.fund(
XRP(10000), alice, bob, cho);
224 auto const pk = alice.pk();
225 auto const settleDelay = 100s;
228 env(
fset(bob, asfDisallowIncomingPayChan));
233 auto const chan =
channel(alice, bob, env.seq(alice));
239 env(
fset(alice, asfDisallowIncomingPayChan));
244 auto const chan =
channel(bob, alice, env.seq(bob));
250 env(
fclear(bob, asfDisallowIncomingPayChan));
255 auto const chan =
channel(alice, bob, env.seq(alice));
262 auto const chan =
channel(cho, alice, env.seq(cho));
268 env(
fclear(alice, asfDisallowIncomingPayChan));
273 auto const chan =
channel(cho, alice, env.seq(cho));
285 auto const alice =
Account(
"alice");
286 auto const bob =
Account(
"bob");
287 auto const carol =
Account(
"carol");
290 Env env{*
this, features};
291 env.fund(
XRP(10000), alice, bob);
292 auto const pk = alice.pk();
293 auto const settleDelay = 100s;
295 env.current()->header().parentCloseTime + 3600s;
296 auto const channelFunds =
XRP(1000);
297 auto const chan =
channel(alice, bob, env.seq(alice));
298 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
300 env.close(cancelAfter);
305 auto preAlice = env.balance(alice);
306 auto preBob = env.balance(bob);
307 auto const delta =
XRP(500);
308 auto const reqBal = chanBal + delta;
309 auto const authAmt = reqBal +
XRP(100);
310 assert(reqBal <= chanAmt);
312 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
313 auto const feeDrops = env.current()->fees().base;
315 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
316 BEAST_EXPECT(env.balance(alice) == preAlice + channelFunds);
321 Env env{*
this, features};
322 env.fund(
XRP(10000), alice, bob, carol);
323 auto const pk = alice.pk();
324 auto const settleDelay = 100s;
326 env.current()->header().parentCloseTime + 3600s;
327 auto const channelFunds =
XRP(1000);
328 auto const chan =
channel(alice, bob, env.seq(alice));
329 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
334 env.close(cancelAfter);
336 auto const preAlice = env.balance(alice);
339 BEAST_EXPECT(env.balance(alice) == preAlice + channelFunds);
344 for (
bool const withFixPayChan : {
true,
false})
346 auto const amend = withFixPayChan ? features : features - fixPayChanCancelAfter;
347 Env env{*
this, amend};
348 env.
fund(
XRP(10000), alice, bob);
351 auto const pk = alice.pk();
352 auto const settleDelay = 100s;
353 auto const channelFunds =
XRP(1000);
355 env.current()->header().parentCloseTime - 1s;
357 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter), txResult);
363 for (
bool const withFixPayChan : {
true,
false})
365 auto const amend = withFixPayChan ? features : features - fixPayChanCancelAfter;
366 Env env{*
this, amend};
367 env.
fund(
XRP(10000), alice, bob);
370 auto const pk = alice.pk();
371 auto const settleDelay = 100s;
372 auto const channelFunds =
XRP(1000);
374 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter),
386 Env env{*
this, features};
387 auto const alice =
Account(
"alice");
388 auto const bob =
Account(
"bob");
389 auto const carol =
Account(
"carol");
390 env.fund(
XRP(10000), alice, bob, carol);
391 auto const pk = alice.pk();
392 auto const settleDelay = 3600s;
393 auto const closeTime = env.current()->header().parentCloseTime;
394 auto const minExpiration = closeTime + settleDelay;
396 auto const channelFunds =
XRP(1000);
397 auto const chan =
channel(alice, bob, env.seq(alice));
398 env(
create(alice, bob, channelFunds, settleDelay, pk, cancelAfter));
403 auto counts = [](
auto const& t) {
return t.time_since_epoch().count(); };
409 BEAST_EXPECT(*
channelExpiration(*env.current(), chan) == counts(minExpiration) + 100);
413 BEAST_EXPECT(*
channelExpiration(*env.current(), chan) == counts(minExpiration) + 50);
418 BEAST_EXPECT(*
channelExpiration(*env.current(), chan) == counts(minExpiration) + 50);
421 BEAST_EXPECT(*
channelExpiration(*env.current(), chan) == counts(minExpiration) + 50);
429 env.close(minExpiration);
441 Env env{*
this, features};
442 auto const alice =
Account(
"alice");
443 auto const bob =
Account(
"bob");
444 env.fund(
XRP(10000), alice, bob);
445 auto const pk = alice.pk();
446 auto const settleDelay = 3600s;
448 env.current()->header().parentCloseTime + settleDelay;
449 auto const channelFunds =
XRP(1000);
450 auto const chan =
channel(alice, bob, env.seq(alice));
451 env(
create(alice, bob, channelFunds, settleDelay, pk));
456 env.close(settleTimepoint - settleDelay / 2);
461 auto preBob = env.balance(bob);
462 auto const delta =
XRP(500);
463 auto const reqBal = chanBal + delta;
464 auto const authAmt = reqBal +
XRP(100);
465 assert(reqBal <= chanAmt);
467 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
469 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
470 auto const feeDrops = env.current()->fees().base;
471 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
473 env.close(settleTimepoint);
478 auto const preAlice = env.balance(alice);
479 auto preBob = env.balance(bob);
480 auto const delta =
XRP(500);
481 auto const reqBal = chanBal + delta;
482 auto const authAmt = reqBal +
XRP(100);
483 assert(reqBal <= chanAmt);
485 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()));
487 auto const feeDrops = env.current()->fees().base;
488 BEAST_EXPECT(env.balance(alice) == preAlice + chanAmt - chanBal);
489 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
499 Env env{*
this, features};
500 auto const alice =
Account(
"alice");
501 auto const bob =
Account(
"bob");
502 env.fund(
XRP(10000), alice, bob);
503 auto const pk = alice.pk();
504 auto const settleDelay = 3600s;
505 auto const channelFunds =
XRP(1000);
506 auto const chan =
channel(alice, bob, env.seq(alice));
507 env(
create(alice, bob, channelFunds, settleDelay, pk));
514 auto const preBob = env.balance(bob);
515 env(
claim(alice, chan, channelFunds.value(), channelFunds.value()));
516 BEAST_EXPECT(
channelBalance(*env.current(), chan) == channelFunds);
517 BEAST_EXPECT(env.balance(bob) == preBob + channelFunds);
519 auto const preAlice = env.balance(alice);
523 auto const feeDrops = env.current()->fees().base;
524 BEAST_EXPECT(env.balance(alice) == preAlice - feeDrops);
534 Env env{*
this, features};
535 auto const alice =
Account(
"alice");
536 auto const bob =
Account(
"bob");
537 env.fund(
XRP(10000), alice, bob);
538 auto const pk = alice.pk();
539 auto const settleDelay = 3600s;
540 auto const channelFunds =
XRP(1000);
541 auto const chan =
channel(alice, bob, env.seq(alice));
542 env(
create(alice, bob, channelFunds, settleDelay, pk));
550 auto const preBob = env.balance(bob);
552 auto const delta =
XRP(500);
553 auto const reqBal = chanBal + delta;
554 assert(reqBal <= chanAmt);
558 auto const feeDrops = env.current()->fees().base;
559 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
566 auto const preBob = env.balance(bob);
568 auto const delta =
XRP(500);
569 auto const reqBal = chanBal + delta;
570 assert(reqBal <= chanAmt);
574 auto const feeDrops = env.current()->fees().base;
575 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
588 auto const alice =
Account(
"alice");
589 auto const bob =
Account(
"bob");
593 Env env{*
this, features};
594 env.fund(
XRP(10000), alice, bob);
595 env(
fset(bob, asfDisallowXRP));
596 auto const chan =
channel(alice, bob, env.seq(alice));
597 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
605 Env env{*
this, features};
606 env.fund(
XRP(10000), alice, bob);
607 auto const chan =
channel(alice, bob, env.seq(alice));
608 env(
create(alice, bob,
XRP(1000), 3600s, alice.pk()));
611 env(
fset(bob, asfDisallowXRP));
612 auto const reqBal =
XRP(500).value();
613 env(
claim(alice, chan, reqBal, reqBal));
625 Env env{*
this, features};
626 auto const alice =
Account(
"alice");
627 auto const bob =
Account(
"bob");
628 env.fund(
XRP(10000), alice, bob);
629 env(
fset(bob, asfRequireDest));
630 auto const pk = alice.pk();
631 auto const settleDelay = 3600s;
632 auto const channelFunds =
XRP(1000);
634 auto const chan =
channel(alice, bob, env.seq(alice));
639 auto const chan =
channel(alice, bob, env.seq(alice));
652 auto const alice =
Account(
"alice");
653 auto const bob =
Account(
"bob");
654 auto const carol =
Account(
"carol");
655 auto USDA = alice[
"USD"];
657 Env env{*
this, features};
658 env.fund(
XRP(10000), alice, bob, carol);
660 env(
fset(bob, asfDepositAuth));
663 auto const pk = alice.pk();
664 auto const settleDelay = 100s;
665 auto const chan =
channel(alice, bob, env.seq(alice));
666 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
674 env(
fund(alice, chan,
XRP(1000)));
682 auto const baseFee = env.current()->fees().base;
683 auto const preBob = env.balance(bob);
685 auto const delta =
XRP(500).value();
692 BEAST_EXPECT(env.balance(bob) == preBob);
704 BEAST_EXPECT(env.balance(bob) == preBob + delta - baseFee);
708 auto const delta =
XRP(600).value();
736 BEAST_EXPECT(env.balance(bob) == preBob + delta - (3 * baseFee));
741 auto const delta =
XRP(800).value();
751 env(
fclear(bob, asfDepositAuth));
755 env(
claim(alice, chan, delta, delta));
757 BEAST_EXPECT(env.balance(bob) == preBob +
XRP(800) - (5 * baseFee));
765 testcase(
"Deposit Authorization with Credentials");
769 char const credType[] =
"abcde";
774 Account const dillon(
"dillon");
779 env.
fund(
XRP(10000), alice, bob, carol, dillon, zelda);
781 auto const pk = alice.
pk();
782 auto const settleDelay = 100s;
783 auto const chan =
channel(alice, bob, env.seq(alice));
784 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
788 env(
fund(alice, chan,
XRP(1000)));
792 "D007AE4B6E1274B4AF872588267B810C2F82716726351D1C7D38D3E5499FC6"
795 auto const delta =
XRP(500).value();
800 env.current()->header().parentCloseTime.time_since_epoch().count() + 100;
801 jv[sfExpiration.jsonName] = t;
807 std::string const credIdx = jv[jss::result][jss::index].asString();
810 env(
fset(bob, asfDepositAuth));
814 env(
claim(alice, chan, delta, delta),
823 env(
claim(alice, chan, delta, delta),
833 env(
claim(dillon, chan, delta, delta),
841 env(
claim(alice, chan, delta, delta),
852 for (
int i = 0; i < 10; ++i)
866 std::string const credIdx = jv[jss::result][jss::index].asString();
875 env.
fund(
XRP(10000), alice, bob, carol, dillon, zelda);
877 auto const pk = alice.
pk();
878 auto const settleDelay = 100s;
879 auto const chan =
channel(alice, bob, env.seq(alice));
880 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
884 env(
fund(alice, chan,
XRP(1000)));
887 auto const delta =
XRP(500).value();
897 std::string const credIdx = jv[jss::result][jss::index].asString();
907 env.
fund(
XRP(5000),
"alice",
"bob");
910 auto const pk = alice.
pk();
911 auto const settleDelay = 100s;
912 auto const chan =
channel(alice, bob, env.
seq(alice));
913 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
916 env(
fund(alice, chan,
XRP(1000)));
919 "48004829F915654A81B11C4AB8218D96FED67F209B58328A72314FB6EA288B"
923 env(
fset(bob, asfDepositAuth));
928 env(
claim(alice, chan,
XRP(500).value(),
XRP(500).value()),
938 testcase(
"Multiple channels to the same account");
941 Env env{*
this, features};
942 auto const alice =
Account(
"alice");
943 auto const bob =
Account(
"bob");
944 env.fund(
XRP(10000), alice, bob);
945 auto const pk = alice.pk();
946 auto const settleDelay = 3600s;
947 auto const channelFunds =
XRP(1000);
948 auto const chan1 =
channel(alice, bob, env.seq(alice));
949 env(
create(alice, bob, channelFunds, settleDelay, pk));
951 auto const chan2 =
channel(alice, bob, env.seq(alice));
952 env(
create(alice, bob, channelFunds, settleDelay, pk));
954 BEAST_EXPECT(chan1 != chan2);
964 Env env{*
this, features};
965 auto const alice =
Account(
"alice");
966 auto const bob =
Account(
"bob");
968 env.fund(
XRP(10000), alice, bob, charlie);
969 auto const pk = alice.pk();
970 auto const settleDelay = 3600s;
971 auto const channelFunds =
XRP(1000);
973 env(
create(alice, bob, channelFunds, settleDelay, pk));
977 auto testInvalidAccountParam = [&](
auto const& param) {
979 params[jss::account] = param;
980 auto jrr = env.rpc(
"json",
"account_channels",
to_string(params))[jss::result];
981 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
982 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'account'.");
985 testInvalidAccountParam(1);
986 testInvalidAccountParam(1.1);
987 testInvalidAccountParam(
true);
993 auto const r = env.rpc(
"account_channels", alice.human(), bob.human());
994 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
995 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
996 BEAST_EXPECT(r[jss::result][jss::validated]);
999 auto const r = env.rpc(
"account_channels", alice.human());
1000 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1001 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1002 BEAST_EXPECT(r[jss::result][jss::validated]);
1005 auto const r = env.rpc(
"account_channels", bob.human(), alice.human());
1006 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
1007 BEAST_EXPECT(r[jss::result][jss::validated]);
1010 env(
create(alice, bob, channelFunds, settleDelay, pk));
1013 auto const r = env.rpc(
"account_channels", alice.human(), bob.human());
1014 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
1015 BEAST_EXPECT(r[jss::result][jss::validated]);
1016 BEAST_EXPECT(chan1Str != chan2Str);
1017 for (
auto const& c : {chan1Str, chan2Str})
1020 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1021 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1029 testcase(
"Account channels RPC markers");
1031 using namespace test::jtx;
1034 auto const alice =
Account(
"alice");
1039 for (
int i = 0; i < n; ++i)
1046 Env env{*
this, features};
1047 env.fund(
XRP(10000), alice);
1048 for (
auto const& a : bobs)
1050 env.fund(
XRP(10000), a);
1056 auto const settleDelay = 3600s;
1057 auto const channelFunds =
XRP(1);
1058 for (
auto const& b : bobs)
1060 env(
create(alice, b, channelFunds, settleDelay, alice.pk()));
1070 jvc[jss::account] = src.human();
1072 jvc[jss::destination_account] = dst->human();
1074 jvc[jss::limit] = *limit;
1076 jvc[jss::marker] = marker;
1078 return env.
rpc(
"json",
"account_channels",
to_string(jvc))[jss::result];
1083 auto const r = testLimit(env, alice);
1084 BEAST_EXPECT(r.isMember(jss::channels));
1085 BEAST_EXPECT(r[jss::channels].size() == bobs.size());
1090 for (
auto const& a : bobs)
1095 for (
int limit = 1; limit < bobs.size() + 1; ++limit)
1097 auto leftToFind = bobsB58;
1098 auto const numFull = bobs.
size() / limit;
1099 auto const numNonFull = ((bobs.size() % limit) != 0u) ? 1 : 0;
1103 auto const testIt = [&](
bool expectMarker,
int expectedBatchSize) {
1104 auto const r = testLimit(env, alice, limit, marker);
1105 BEAST_EXPECT(!expectMarker || r.isMember(jss::marker));
1106 if (r.isMember(jss::marker))
1107 marker = r[jss::marker];
1108 BEAST_EXPECT(r[jss::channels].size() == expectedBatchSize);
1109 auto const c = r[jss::channels];
1110 auto const s = r[jss::channels].size();
1111 for (
int j = 0; j < s; ++j)
1113 auto const dstAcc = c[j][jss::destination_account].asString();
1114 BEAST_EXPECT(leftToFind.count(dstAcc));
1115 leftToFind.erase(dstAcc);
1119 for (
int i = 0; i < numFull; ++i)
1121 bool const expectMarker = (numNonFull != 0 || i < numFull - 1);
1122 testIt(expectMarker, limit);
1125 if (numNonFull != 0)
1127 testIt(
false, bobs.size() % limit);
1129 BEAST_EXPECT(leftToFind.empty());
1134 auto const r = testLimit(env, alice, 0);
1135 BEAST_EXPECT(r.isMember(jss::error_message));
1144 testcase(
"Account channels RPC owner only");
1146 using namespace test::jtx;
1149 auto const alice =
Account(
"alice");
1150 auto const bob =
Account(
"bob");
1151 Env env{*
this, features};
1152 env.fund(
XRP(10000), alice, bob);
1157 auto const settleDelay = 3600s;
1158 auto const channelFunds =
XRP(1000);
1159 env(
create(alice, bob, channelFunds, settleDelay, alice.pk()));
1160 env(
create(bob, alice, channelFunds, settleDelay, bob.pk()));
1162 auto const r = [&] {
1164 jvc[jss::account] = alice.human();
1166 return env.rpc(
"json",
"account_channels",
to_string(jvc))[jss::result];
1168 BEAST_EXPECT(r.isMember(jss::channels));
1169 BEAST_EXPECT(r[jss::channels].size() == 1);
1170 BEAST_EXPECT(r[jss::channels][0u][jss::destination_account].asString() == bob.human());
1176 using namespace jtx;
1179 Env env{*
this, features};
1180 auto const alice =
Account(
"alice");
1181 auto const bob =
Account(
"bob");
1183 env.fund(
XRP(10000), alice, bob, charlie);
1184 auto const pk = alice.pk();
1185 auto const settleDelay = 3600s;
1186 auto const channelFunds =
XRP(1000);
1188 env(
create(alice, bob, channelFunds, settleDelay, pk));
1192 args[jss::channel_id] = chan1Str;
1193 args[jss::key_type] =
"ed255191";
1194 args[jss::seed] =
"snHq1rzQoN2qiUkC3XF5RyxBzUtN";
1195 args[jss::amount] = 51110000;
1200 args[jss::api_version] = apiVersion;
1202 env.rpc(
"json",
"channel_authorize", args.toStyledString())[jss::result];
1203 auto const error = apiVersion < 2u ?
"invalidParams" :
"badKeyType";
1204 BEAST_EXPECT(rs[jss::error] == error);
1211 testcase(
"PayChan Auth/Verify RPC");
1212 using namespace jtx;
1214 Env env{*
this, features};
1215 auto const alice =
Account(
"alice");
1216 auto const bob =
Account(
"bob");
1218 env.fund(
XRP(10000), alice, bob, charlie);
1219 auto const pk = alice.pk();
1220 auto const settleDelay = 3600s;
1221 auto const channelFunds =
XRP(1000);
1223 env(
create(alice, bob, channelFunds, settleDelay, pk));
1227 auto const r = env.rpc(
"account_channels", alice.human(), bob.human());
1228 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1229 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1230 BEAST_EXPECT(r[jss::result][jss::validated]);
1231 chan1PkStr = r[jss::result][jss::channels][0u][jss::public_key].asString();
1234 auto const r = env.rpc(
"account_channels", alice.human());
1235 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1236 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str);
1237 BEAST_EXPECT(r[jss::result][jss::validated]);
1238 chan1PkStr = r[jss::result][jss::channels][0u][jss::public_key].asString();
1241 auto const r = env.rpc(
"account_channels", bob.human(), alice.human());
1242 BEAST_EXPECT(r[jss::result][jss::channels].size() == 0);
1243 BEAST_EXPECT(r[jss::result][jss::validated]);
1246 env(
create(alice, bob, channelFunds, settleDelay, pk));
1249 auto const r = env.rpc(
"account_channels", alice.human(), bob.human());
1250 BEAST_EXPECT(r[jss::result][jss::channels].size() == 2);
1251 BEAST_EXPECT(r[jss::result][jss::validated]);
1252 BEAST_EXPECT(chan1Str != chan2Str);
1253 for (
auto const& c : {chan1Str, chan2Str})
1256 r[jss::result][jss::channels][0u][jss::channel_id] == c ||
1257 r[jss::result][jss::channels][1u][jss::channel_id] == c);
1266 s +=
"0123456789ABCDEF"[((
slice[i] & 0xf0) >> 4)];
1267 s +=
"0123456789ABCDEF"[((
slice[i] & 0x0f) >> 0)];
1274 auto const rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000");
1275 auto const sig = rs[jss::result][jss::signature].asString();
1276 BEAST_EXPECT(!
sig.empty());
1278 auto const rv = env.rpc(
"channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1279 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1285 auto const rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1286 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1291 auto rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000x",
sig);
1292 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1293 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000 ",
sig);
1294 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1295 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x1000",
sig);
1296 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1297 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"x",
sig);
1298 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1299 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" ",
sig);
1300 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1301 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000 1000",
sig);
1302 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1303 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1,000",
sig);
1304 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1305 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
" 1000",
sig);
1306 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1307 rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"",
sig);
1308 BEAST_EXPECT(rv[jss::error] ==
"channelAmtMalformed");
1313 auto chan1StrBad = chan1Str;
1314 chan1StrBad.pop_back();
1315 auto rv = env.rpc(
"channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1316 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1317 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1318 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1320 chan1StrBad = chan1Str;
1321 chan1StrBad.push_back(
'0');
1322 rv = env.rpc(
"channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1323 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1324 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1325 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1327 chan1StrBad = chan1Str;
1328 chan1StrBad.back() =
'x';
1329 rv = env.rpc(
"channel_verify", pkAsHex, chan1StrBad,
"1000",
sig);
1330 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1331 rv = env.rpc(
"channel_authorize",
"alice", chan1StrBad,
"1000");
1332 BEAST_EXPECT(rv[jss::error] ==
"channelMalformed");
1336 auto illFormedPk = chan1PkStr.
substr(0, chan1PkStr.
size() - 1);
1337 auto const rv = env.rpc(
"channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1338 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1343 auto illFormedPk = pkAsHex.substr(0, chan1PkStr.
size() - 1);
1344 auto const rv = env.rpc(
"channel_verify", illFormedPk, chan1Str,
"1000",
sig);
1345 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1350 auto const rs = env.rpc(
"channel_authorize",
"alice", chan2Str,
"1000");
1351 auto const sig = rs[jss::result][jss::signature].asString();
1352 BEAST_EXPECT(!
sig.empty());
1354 auto const rv = env.rpc(
"channel_verify", chan1PkStr, chan1Str,
"1000",
sig);
1355 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1360 auto const rv = env.rpc(
"channel_verify", pkAsHex, chan1Str,
"1000",
sig);
1361 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1367 env(
create(charlie, alice, channelFunds, settleDelay, charlie.pk()));
1372 auto const r = env.rpc(
"account_channels", charlie.human(), alice.human());
1373 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1374 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1375 BEAST_EXPECT(r[jss::result][jss::validated]);
1376 cpk = r[jss::result][jss::channels][0u][jss::public_key].asString();
1380 auto const rs = env.rpc(
"channel_authorize",
"charlie", chan,
"1000");
1381 auto const sig = rs[jss::result][jss::signature].asString();
1382 BEAST_EXPECT(!
sig.empty());
1384 auto const rv = env.rpc(
"channel_verify", cpk, chan,
"1000",
sig);
1385 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1389 auto const rs1 = env.rpc(
"channel_authorize",
"charlie",
"nyx", chan,
"1000");
1390 BEAST_EXPECT(rs1[jss::error] ==
"badKeyType");
1394 auto const rs2 = env.rpc(
"channel_authorize",
"charlie",
"secp256k1", chan,
"1000");
1395 auto const sig2 = rs2[jss::result][jss::signature].asString();
1396 BEAST_EXPECT(!sig2.empty());
1398 auto const rv = env.rpc(
"channel_verify", cpk, chan,
"1000", sig2);
1399 BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool());
1403 auto const rs3 = env.rpc(
"channel_authorize",
"charlie",
"ed25519", chan,
"1000");
1404 auto const sig3 = rs3[jss::result][jss::signature].asString();
1405 BEAST_EXPECT(!sig3.empty());
1407 auto const rv = env.rpc(
"channel_verify", cpk, chan,
"1000", sig3);
1408 BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool());
1414 auto rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"1000x");
1415 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1416 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x1000");
1417 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1418 rs = env.rpc(
"channel_authorize",
"alice", chan1Str,
"x");
1419 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1423 args[jss::amount] =
"2000";
1424 args[jss::key_type] =
"secp256k1";
1425 args[jss::passphrase] =
"passphrase_can_be_anything";
1426 rs = env.rpc(
"json",
"channel_authorize", args.toStyledString())[jss::result];
1427 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1432 args[jss::channel_id] = chan1Str;
1433 args[jss::key_type] =
"secp256k1";
1434 args[jss::passphrase] =
"passphrase_can_be_anything";
1435 rs = env.rpc(
"json",
"channel_authorize", args.toStyledString())[jss::result];
1436 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1441 args[jss::amount] =
"2000";
1442 args[jss::channel_id] = chan1Str;
1443 args[jss::passphrase] =
"passphrase_can_be_anything";
1444 rs = env.rpc(
"json",
"channel_authorize", args.toStyledString())[jss::result];
1445 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1450 args[jss::amount] =
"2000";
1451 args[jss::channel_id] = chan1Str;
1452 args[jss::key_type] =
"secp256k1";
1453 args[jss::passphrase] =
"passphrase_can_be_anything";
1454 args[jss::seed] =
"seed can be anything";
1455 rs = env.rpc(
"json",
"channel_authorize", args.toStyledString())[jss::result];
1456 BEAST_EXPECT(rs[jss::error] ==
"invalidParams");
1461 args[jss::amount] =
"2000";
1462 args[jss::channel_id] = chan1Str +
"1";
1463 args[jss::key_type] =
"secp256k1";
1464 args[jss::passphrase] =
"passphrase_can_be_anything";
1465 rs = env.rpc(
"json",
"channel_authorize", args.toStyledString())[jss::result];
1466 BEAST_EXPECT(rs[jss::error] ==
"channelMalformed");
1471 args[jss::amount] = 2000;
1472 args[jss::channel_id] = chan1Str;
1473 args[jss::key_type] =
"secp256k1";
1474 args[jss::passphrase] =
"passphrase_can_be_anything";
1475 rs = env.rpc(
"json",
"channel_authorize", args.toStyledString())[jss::result];
1476 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1481 args[jss::amount] =
"TwoThousand";
1482 args[jss::channel_id] = chan1Str;
1483 args[jss::key_type] =
"secp256k1";
1484 args[jss::passphrase] =
"passphrase_can_be_anything";
1485 rs = env.rpc(
"json",
"channel_authorize", args.toStyledString())[jss::result];
1486 BEAST_EXPECT(rs[jss::error] ==
"channelAmtMalformed");
1495 using namespace jtx;
1497 Env env{*
this, features};
1498 auto const alice =
Account(
"alice");
1499 auto const bob =
Account(
"bob");
1500 auto const carol =
Account(
"carol");
1501 auto const dan =
Account(
"dan");
1502 env.fund(
XRP(10000), alice, bob, carol, dan);
1503 auto const pk = alice.pk();
1504 auto const settleDelay = 3600s;
1505 auto const channelFunds =
XRP(1000);
1511 env(
create(alice, bob, channelFunds, settleDelay, pk));
1512 auto const r = env.rpc(
"account_channels", alice.human(), bob.human());
1513 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1514 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1515 BEAST_EXPECT(!r[jss::result][jss::channels][0u].isMember(jss::destination_tag));
1520 env(
create(alice, carol, channelFunds, settleDelay, pk, cancelAfter, dstTag));
1521 auto const r = env.rpc(
"account_channels", alice.human(), carol.human());
1522 BEAST_EXPECT(r[jss::result][jss::channels].size() == 1);
1523 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan);
1524 BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::destination_tag] == dstTag);
1532 using namespace jtx;
1534 Env env{*
this, features};
1535 auto const alice =
Account(
"alice");
1536 auto const bob =
Account(
"bob");
1537 auto USDA = alice[
"USD"];
1538 env.fund(
XRP(10000), alice, bob);
1539 auto const pk = alice.pk();
1540 auto const settleDelay = 100s;
1542 auto const chan =
channel(alice, bob, env.seq(alice));
1543 auto jv =
create(alice, bob,
XRP(1000), settleDelay, pk);
1544 auto const pkHex =
strHex(pk.slice());
1545 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1547 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1549 auto badPrefix = pkHex;
1552 jv[
"PublicKey"] = badPrefix;
1555 jv[
"PublicKey"] = pkHex;
1558 auto const authAmt =
XRP(100);
1560 jv =
claim(bob, chan, authAmt.value(), authAmt.value(),
Slice(
sig), alice.pk());
1561 jv[
"PublicKey"] = pkHex.substr(2, pkHex.size() - 2);
1563 jv[
"PublicKey"] = pkHex.substr(0, pkHex.size() - 2);
1568 jv[
"PublicKey"] = badPrefix;
1572 jv.removeMember(
"PublicKey");
1576 auto const txn = R
"*(
1579 "channel_id":"5DB01B7FFED6B67E6B0414DED11E051D2EE2B7619CE0EAA6286D67A3A4D5BDB3",
1581 "304402204EF0AFB78AC23ED1C472E74F4299C0C21F1B21D07EFC0A3838A420F76D783A400220154FB11B6F54320666E4C36CA7F686C16A3A0456800BBC43746F34AF50290064",
1583 "aKijDDiC2q2gXjMpM7i4BUS6cmixgsEe18e7CjsUxwihKfuoFgS5",
1587 auto const r = env.rpc(
"json",
"channel_verify", txn);
1588 BEAST_EXPECT(r[
"result"][
"error"] ==
"publicMalformed");
1597 using namespace jtx;
1600 auto const alice =
Account(
"alice");
1601 auto const bob =
Account(
"bob");
1602 auto const settleDelay = 100s;
1603 auto const pk = alice.pk();
1605 auto inOwnerDir = [](
ReadView const& view,
1609 return std::find(ownerDir.begin(), ownerDir.end(), chan) != ownerDir.end();
1619 Env env{*
this, features};
1620 env.fund(
XRP(10000), alice, bob);
1621 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1624 BEAST_EXPECT(inOwnerDir(*env.current(), alice, chanSle));
1625 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 1);
1626 BEAST_EXPECT(inOwnerDir(*env.current(), bob, chanSle));
1627 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 1);
1631 BEAST_EXPECT(!inOwnerDir(*env.current(), alice, chanSle));
1632 BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 0);
1633 BEAST_EXPECT(!inOwnerDir(*env.current(), bob, chanSle));
1634 BEAST_EXPECT(ownerDirCount(*env.current(), bob) == 0);
1640 Env env(*
this, features);
1641 env.
fund(
XRP(10000), alice, bob);
1643 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1646 BEAST_EXPECT(inOwnerDir(*env.
current(), alice, chanSle));
1647 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 1);
1648 BEAST_EXPECT(inOwnerDir(*env.
current(), bob, chanSle));
1649 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 1);
1653 BEAST_EXPECT(!inOwnerDir(*env.
current(), alice, chanSle));
1654 BEAST_EXPECT(ownerDirCount(*env.
current(), alice) == 0);
1655 BEAST_EXPECT(!inOwnerDir(*env.
current(), bob, chanSle));
1656 BEAST_EXPECT(ownerDirCount(*env.
current(), bob) == 0);
1664 using namespace test::jtx;
1671 for (
auto minRmSeq = env.
seq(toRm) + 257; env.
current()->seq() < minRmSeq;
1684 auto const alice =
Account(
"alice");
1685 auto const bob =
Account(
"bob");
1686 auto const carol =
Account(
"carol");
1689 Env env{*
this, features};
1690 env.
fund(
XRP(10000), alice, bob, carol);
1694 auto const pk = alice.pk();
1695 auto const settleDelay = 100s;
1696 auto const chan =
channel(alice, bob, env.
seq(alice));
1697 env(
create(alice, bob,
XRP(1000), settleDelay, pk));
1705 auto const feeDrops = env.
current()->fees().base;
1708 BEAST_EXPECT(chanBal ==
XRP(0));
1709 BEAST_EXPECT(chanAmt ==
XRP(1000));
1711 auto preBob = env.
balance(bob);
1712 auto const delta =
XRP(50);
1713 auto reqBal = chanBal + delta;
1714 auto authAmt = reqBal +
XRP(100);
1715 assert(reqBal <= chanAmt);
1717 env(
claim(alice, chan, reqBal, authAmt));
1721 BEAST_EXPECT(env.
balance(bob) == preBob + delta);
1724 auto const preAlice = env.
balance(alice);
1725 env(
fund(alice, chan,
XRP(1000)));
1727 BEAST_EXPECT(env.
balance(alice) == preAlice -
XRP(1000) - feeDrops);
1729 chanAmt = chanAmt +
XRP(1000);
1737 auto const closeTime = env.
current()->header().parentCloseTime;
1738 auto const minExpiration = closeTime + settleDelay;
1739 env.
close(minExpiration);
1750 using namespace jtx;
1752 Env env{*
this, features};
1753 auto const alice =
Account(
"alice");
1754 auto const bob =
Account(
"bob");
1755 auto USDA = alice[
"USD"];
1756 env.fund(
XRP(10000), alice, bob);
1769 auto const pk = alice.pk();
1770 auto const settleDelay = 100s;
1771 auto const chan =
channel(alice, bob, aliceTicketSeq);
1775 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1776 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1782 auto const preAlice = env.balance(alice);
1785 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1786 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1788 auto const feeDrops = env.current()->fees().base;
1789 BEAST_EXPECT(env.balance(alice) == preAlice -
XRP(1000) - feeDrops);
1794 BEAST_EXPECT(chanBal ==
XRP(0));
1795 BEAST_EXPECT(chanAmt ==
XRP(2000));
1799 auto const preBob = env.balance(bob);
1800 auto const delta =
XRP(500);
1801 auto const reqBal = chanBal + delta;
1802 auto const authAmt = reqBal +
XRP(100);
1803 assert(reqBal <= chanAmt);
1806 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1807 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1810 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
1811 BEAST_EXPECT(env.balance(bob) == preBob + delta);
1816 auto preBob = env.balance(bob);
1817 auto const delta =
XRP(500);
1818 auto const reqBal = chanBal + delta;
1819 auto const authAmt = reqBal +
XRP(100);
1820 assert(reqBal <= chanAmt);
1822 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
1825 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
1826 BEAST_EXPECT(env.seq(bob) == bobSeq);
1829 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
1830 auto const feeDrops = env.current()->fees().base;
1831 BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
1835 preBob = env.balance(bob);
1837 env(
claim(bob, chan, reqBal, authAmt,
Slice(
sig), alice.pk()),
1841 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
1842 BEAST_EXPECT(env.seq(bob) == bobSeq);
1845 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
1846 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
1850 auto const preBob = env.balance(bob);
1853 assert(reqAmt <= chanAmt);
1857 env(
claim(bob, chan, reqAmt, authAmt,
Slice(
sig), alice.pk()),
1861 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
1862 BEAST_EXPECT(env.seq(bob) == bobSeq);
1865 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
1866 BEAST_EXPECT(env.balance(bob) == preBob);
1872 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
1873 BEAST_EXPECT(env.seq(bob) == bobSeq);
1876 BEAST_EXPECT(
channelAmount(*env.current(), chan) == chanAmt);
1880 auto const preAlice = env.balance(alice);
1881 auto const preBob = env.balance(bob);
1884 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
1885 BEAST_EXPECT(env.seq(bob) == bobSeq);
1888 auto const feeDrops = env.current()->fees().base;
1889 auto const delta = chanAmt - chanBal;
1890 assert(delta > beast::zero);
1891 BEAST_EXPECT(env.balance(alice) == preAlice + delta);
1892 BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
1894 env.require(
tickets(alice, env.seq(alice) - aliceTicketSeq));
1895 BEAST_EXPECT(env.seq(alice) == aliceSeq);
1896 env.require(
tickets(bob, env.seq(bob) - bobTicketSeq));
1897 BEAST_EXPECT(env.seq(bob) == bobSeq);
1930 using namespace test::jtx;
1938BEAST_DEFINE_TESTSUITE(PayChan, app,
xrpl);
testcase_t testcase
Memberspace for declaring test cases.
Like std::vector<char> but better.
A class that simplifies iterating ledger directory pages.
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
Slice slice() const noexcept
An immutable linear range of bytes.
Immutable cryptographic account descriptor.
PublicKey const & pk() const
Return the public key.
A transaction testing environment.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
Json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Set the regular signature on a JTx.
Set the expected result code for a JTx The test will fail if the code doesn't match.
Set a ticket sequence on a JTx.
T emplace_back(T... args)
@ arrayValue
array value (ordered list)
@ objectValue
object value (collection of name/value pairs).
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet payChan(AccountID const &src, AccountID const &dst, std::uint32_t seq) noexcept
A PaymentChannel.
Keylet account(AccountID const &id) noexcept
AccountID root.
Json::Value accept(jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
Json::Value ledgerEntry(jtx::Env &env, jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
Json::Value create(jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
Json::Value authCredentials(jtx::Account const &account, std::vector< AuthorizeCredentials > const &auth)
Json::Value unauth(Account const &account, Account const &unauth)
Remove pre-authorization for deposit.
Json::Value auth(Account const &account, Account const &auth)
Preauthorize for deposit.
STAmount channelBalance(ReadView const &view, uint256 const &chan)
uint256 channel(AccountID const &account, AccountID const &dst, std::uint32_t seqProxyValue)
Json::Value claim(AccountID const &account, uint256 const &channel, std::optional< STAmount > const &balance, std::optional< STAmount > const &amount, std::optional< Slice > const &signature, std::optional< PublicKey > const &pk)
bool channelExists(ReadView const &view, uint256 const &chan)
Json::Value create(AccountID const &account, AccountID const &to, STAmount const &amount, NetClock::duration const &settleDelay, PublicKey const &pk, std::optional< NetClock::time_point > const &cancelAfter, std::optional< std::uint32_t > const &dstTag)
Json::Value create(Account const &account, std::uint32_t count)
Create one of more tickets.
void fund(jtx::Env &env, jtx::Account const &gw, std::vector< jtx::Account > const &accounts, std::vector< STAmount > const &amts, Fund how)
XRP_t const XRP
Converts to XRP Issue or STAmount.
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
FeatureBitset testable_amendments()
void sign(Json::Value &jv, Account const &account, Json::Value &sigObject)
Sign automatically into a specific Json field of the jv object.
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Json::Value acctdelete(Account const &account, Account const &dest)
Delete account.
owner_count< ltTICKET > tickets
Match the number of tickets on the account.
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::string to_string(base_uint< Bits, Tag > const &a)
std::string strHex(FwdIt begin, FwdIt end)
void serializePayChanAuthorization(Serializer &msg, uint256 const &key, XRPAmount const &amt)
void forAllApiVersions(Fn const &fn, Args &&... args)
TERSubset< CanCvtToTER > TER
static std::string sliceToHex(Slice const &slice)
bool isTesSuccess(TER x) noexcept
void testSettleDelay(FeatureBitset features)
void testOptionalFields(FeatureBitset features)
void testSimple(FeatureBitset features)
void testMetaAndOwnership(FeatureBitset features)
void testMultiple(FeatureBitset features)
static std::pair< uint256, std::shared_ptr< SLE const > > channelKeyAndSle(ReadView const &view, jtx::Account const &account, jtx::Account const &dst)
void testCancelAfter(FeatureBitset features)
static std::optional< std::int64_t > channelExpiration(ReadView const &view, uint256 const &chan)
void testWithFeats(FeatureBitset features)
void testDepositAuth(FeatureBitset features)
void testDefaultAmount(FeatureBitset features)
void testCloseDry(FeatureBitset features)
void testDepositAuthCreds()
void testUsingTickets(FeatureBitset features)
void testDstTag(FeatureBitset features)
void testAccountChannelAuthorize(FeatureBitset features)
void testAccountChannelsRPC(FeatureBitset features)
void testExpiration(FeatureBitset features)
static Buffer signClaimAuth(PublicKey const &pk, SecretKey const &sk, uint256 const &channel, STAmount const &authAmt)
void testDisallowIncoming(FeatureBitset features)
void testAuthVerifyRPC(FeatureBitset features)
void testAccountDelete(FeatureBitset features)
static STAmount channelAmount(ReadView const &view, uint256 const &chan)
void run() override
Runs the suite.
void testDisallowXRP(FeatureBitset features)
void testAccountChannelsRPCSenderOnly(FeatureBitset features)
void testMalformedPK(FeatureBitset features)
void testAccountChannelsRPCMarkers(FeatureBitset features)