59 using namespace test::jtx;
61 auto const testSequence = [
this](
64 Account
const& issuer,
66 Account
const& depositor,
67 Account
const& charlie,
70 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
71 tx[sfData] =
"AFEED00E";
72 tx[sfAssetsMaximum] = asset(100).number();
75 BEAST_EXPECT(env.le(keylet));
77 auto const share = [&env, keylet = keylet,
this]() ->
PrettyAsset {
78 auto const vault = env.le(keylet);
79 BEAST_EXPECT(vault !=
nullptr);
80 return MPTIssue(vault->at(sfShareMPTID));
84 Account alice{
"alice"};
87 env.fund(XRP(1000), alice, dave, erin);
93 testcase(prefix +
" fail to deposit more than assets held");
94 auto tx = vault.deposit(
95 {.depositor = depositor,
97 .amount = asset(10000)});
102 testcase(prefix +
" deposit non-zero amount");
103 auto tx = vault.deposit(
104 {.depositor = depositor,
106 .amount = asset(50)});
111 testcase(prefix +
" deposit non-zero amount again");
112 auto tx = vault.deposit(
113 {.depositor = depositor,
115 .amount = asset(50)});
120 testcase(prefix +
" fail to delete non-empty vault");
121 auto tx = vault.del({.owner = owner, .id = keylet.
key});
126 testcase(prefix +
" fail to update because wrong owner");
127 auto tx = vault.set({.owner = issuer, .id = keylet.
key});
128 tx[sfAssetsMaximum] = asset(50).number();
134 prefix +
" fail to set maximum lower than current amount");
135 auto tx = vault.set({.owner = owner, .id = keylet.
key});
136 tx[sfAssetsMaximum] = asset(50).number();
141 testcase(prefix +
" set maximum higher than current amount");
142 auto tx = vault.set({.owner = owner, .id = keylet.
key});
143 tx[sfAssetsMaximum] = asset(150).number();
149 auto tx = vault.set({.owner = owner, .id = keylet.
key});
155 testcase(prefix +
" fail to set domain on public vault");
156 auto tx = vault.set({.owner = owner, .id = keylet.
key});
162 testcase(prefix +
" fail to deposit more than maximum");
163 auto tx = vault.deposit(
164 {.depositor = depositor,
166 .amount = asset(100)});
171 testcase(prefix +
" reset maximum to zero i.e. not enforced");
172 auto tx = vault.set({.owner = owner, .id = keylet.
key});
173 tx[sfAssetsMaximum] = asset(0).number();
178 testcase(prefix +
" fail to withdraw more than assets held");
179 auto tx = vault.withdraw(
180 {.depositor = depositor,
182 .amount = asset(1000)});
187 testcase(prefix +
" deposit some more");
188 auto tx = vault.deposit(
189 {.depositor = depositor,
191 .amount = asset(100)});
196 testcase(prefix +
" clawback some");
199 auto tx = vault.clawback(
203 .amount = asset(10)});
211 auto tx = vault.clawback(
212 {.issuer = issuer, .id = keylet.
key, .holder = depositor});
216 if (!asset.raw().native())
218 testcase(prefix +
" deposit again");
219 auto tx = vault.deposit(
220 {.depositor = depositor,
222 .amount = asset(200)});
228 prefix +
" fail to withdraw to 3rd party lsfDepositAuth");
229 auto tx = vault.withdraw(
230 {.depositor = depositor,
232 .amount = asset(100)});
233 tx[sfDestination] = alice.human();
238 testcase(prefix +
" fail to withdraw to zero destination");
239 auto tx = vault.withdraw(
240 {.depositor = depositor,
242 .amount = asset(1000)});
243 tx[sfDestination] =
"0";
250 " fail to withdraw with tag but without destination");
251 auto tx = vault.withdraw(
252 {.depositor = depositor,
254 .amount = asset(1000)});
255 tx[sfDestinationTag] =
"0";
259 if (!asset.raw().native())
262 prefix +
" fail to withdraw to 3rd party no authorization");
263 auto tx = vault.withdraw(
264 {.depositor = depositor,
266 .amount = asset(100)});
267 tx[sfDestination] = erin.human();
272 if (!asset.raw().native() && asset.raw().holds<
Issue>())
274 testcase(prefix +
" temporary authorization for 3rd party");
275 env(trust(erin, asset(1000)));
276 env(trust(issuer, asset(0), erin,
tfSetfAuth));
277 env(pay(issuer, erin, asset(10)));
280 auto tx = vault.deposit(
281 {.depositor = erin, .id = keylet.
key, .amount = asset(10)});
283 env(pay(erin, depositor, share(10)));
285 testcase(prefix +
" withdraw to authorized 3rd party");
288 {.depositor = depositor,
290 .amount = asset(10)});
291 tx[sfDestination] = erin.human();
294 env(pay(erin, issuer, asset(10)));
296 testcase(prefix +
" fail to pay to unauthorized 3rd party");
297 env(trust(erin, asset(0)));
299 env(pay(depositor, erin, share(1)), ter{
tecNO_LINE});
305 " fail to withdraw to 3rd party lsfRequireDestTag");
306 auto tx = vault.withdraw(
307 {.depositor = depositor,
309 .amount = asset(100)});
310 tx[sfDestination] = dave.human();
315 testcase(prefix +
" withdraw to authorized 3rd party");
316 auto tx = vault.withdraw(
317 {.depositor = depositor,
319 .amount = asset(100)});
320 tx[sfDestination] = charlie.human();
325 testcase(prefix +
" withdraw to issuer");
326 auto tx = vault.withdraw(
327 {.depositor = depositor,
329 .amount = asset(50)});
330 tx[sfDestination] = issuer.human();
335 testcase(prefix +
" withdraw remaining assets");
336 auto tx = vault.withdraw(
337 {.depositor = depositor,
339 .amount = asset(50)});
344 testcase(prefix +
" fail to delete because wrong owner");
345 auto tx = vault.del({.owner = issuer, .id = keylet.
key});
350 testcase(prefix +
" delete empty vault");
351 auto tx = vault.del({.owner = owner, .id = keylet.
key});
353 BEAST_EXPECT(!env.le(keylet));
357 auto testCases = [
this, &testSequence](
361 Account
const& issuer,
362 Account
const& owner,
363 Account
const& depositor,
364 Account
const& charlie)> setup) {
365 Env env{*
this, testable_amendments() | featureSingleAssetVault};
366 Account issuer{
"issuer"};
367 Account owner{
"owner"};
368 Account depositor{
"depositor"};
369 Account charlie{
"charlie"};
371 env.fund(XRP(1000), issuer, owner, depositor, charlie);
379 PrettyAsset asset = setup(env, issuer, owner, depositor, charlie);
381 prefix, env, issuer, owner, depositor, charlie, vault, asset);
387 Account
const& issuer,
388 Account
const& owner,
389 Account
const& depositor,
397 Account
const& issuer,
398 Account
const& owner,
399 Account
const& depositor,
400 Account
const& charlie) ->
Asset {
402 env(trust(owner, asset(1000)));
403 env(trust(depositor, asset(1000)));
404 env(trust(charlie, asset(1000)));
405 env(trust(issuer, asset(0), owner,
tfSetfAuth));
406 env(trust(issuer, asset(0), depositor,
tfSetfAuth));
407 env(trust(issuer, asset(0), charlie,
tfSetfAuth));
408 env(pay(issuer, depositor, asset(1000)));
416 Account
const& issuer,
417 Account
const& owner,
418 Account
const& depositor,
419 Account
const& charlie) ->
Asset {
420 MPTTester mptt{env, issuer, mptInitNoFund};
425 mptt.authorize({.account = depositor});
426 mptt.authorize({.account = charlie});
427 env(pay(issuer, depositor, asset(1000)));
436 using namespace test::jtx;
441 testable_amendments() | featureSingleAssetVault;
444 auto testCase = [&,
this](
447 Account
const& issuer,
448 Account
const& owner,
451 CaseArgs args = {}) {
452 Env env{*
this, args.features};
453 Account issuer{
"issuer"};
454 Account owner{
"owner"};
456 env.fund(XRP(1000), issuer, owner);
464 env(trust(owner, asset(1000)));
465 env(trust(issuer, asset(0), owner,
tfSetfAuth));
466 env(pay(issuer, owner, asset(1000)));
469 test(env, issuer, owner, asset, vault);
474 Account
const& issuer,
475 Account
const& owner,
478 testcase(
"disabled single asset vault");
481 vault.create({.owner = owner, .asset = asset});
485 auto tx = vault.set({.owner = owner, .id = keylet.
key});
490 auto tx = vault.deposit(
493 .amount = asset(10)});
498 auto tx = vault.withdraw(
501 .amount = asset(10)});
506 auto tx = vault.clawback(
510 .amount = asset(10)});
515 auto tx = vault.del({.owner = owner, .id = keylet.
key});
519 {.features = testable_amendments() - featureSingleAssetVault});
521 testCase([&](Env& env,
522 Account
const& issuer,
523 Account
const& owner,
528 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
533 auto tx = vault.set({.owner = owner, .id = keylet.
key});
539 auto tx = vault.deposit(
542 .amount = asset(10)});
548 auto tx = vault.withdraw(
551 .amount = asset(10)});
557 auto tx = vault.clawback(
561 .amount = asset(10)});
567 auto tx = vault.del({.owner = owner, .id = keylet.
key});
573 testCase([&](Env& env,
574 Account
const& issuer,
575 Account
const& owner,
580 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
585 auto tx = vault.set({.owner = owner, .id = keylet.
key});
591 auto tx = vault.deposit(
594 .amount = asset(10)});
600 auto tx = vault.withdraw(
603 .amount = asset(10)});
609 auto tx = vault.clawback(
613 .amount = asset(10)});
619 auto tx = vault.del({.owner = owner, .id = keylet.
key});
628 Account
const& owner,
631 testcase(
"disabled permissioned domain");
634 vault.create({.owner = owner, .asset =
xrpIssue()});
639 auto tx = vault.set({.owner = owner, .id = keylet.
key});
645 auto tx = vault.set({.owner = owner, .id = keylet.
key});
646 tx[sfDomainID] =
"0";
650 {.features = (testable_amendments() | featureSingleAssetVault) -
651 featurePermissionedDomains});
653 testCase([&](Env& env,
654 Account
const& issuer,
655 Account
const& owner,
661 vault.create({.owner = owner, .asset =
xrpIssue()});
664 auto tx = vault.set({
672 auto tx = vault.deposit(
675 .amount = asset(10)});
680 auto tx = vault.withdraw(
683 .amount = asset(10)});
688 auto tx = vault.clawback(
692 .amount = asset(10)});
697 auto tx = vault.del({
705 testCase([&](Env& env,
706 Account
const& issuer,
707 Account
const& owner,
712 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
715 auto tx = vault.clawback(
719 .amount = asset(10)});
724 testCase([&](Env& env,
726 Account
const& owner,
729 testcase(
"withdraw to bad destination");
731 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
734 auto tx = vault.withdraw(
737 .amount = asset(10)});
738 tx[jss::Destination] =
"0";
743 testCase([&](Env& env,
745 Account
const& owner,
748 testcase(
"create or set invalid data");
750 auto [tx1, keylet] = vault.create({.owner = owner, .asset = asset});
766 auto tx = vault.set({.owner = owner, .id = keylet.
key});
772 auto tx = vault.set({.owner = owner, .id = keylet.
key});
779 testCase([&](Env& env,
781 Account
const& owner,
786 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
789 auto tx = vault.set({.owner = owner, .id = keylet.
key});
794 testCase([&](Env& env,
796 Account
const& owner,
799 testcase(
"create with invalid metadata");
801 auto [tx1, keylet] = vault.create({.owner = owner, .asset = asset});
805 tx[sfMPTokenMetadata] =
"";
818 testCase([&](Env& env,
820 Account
const& owner,
825 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
828 auto tx = vault.set({.owner = owner, .id = keylet.
key});
834 testCase([&](Env& env,
836 Account
const& owner,
841 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
844 auto tx = vault.deposit(
852 auto tx = vault.deposit(
853 {.depositor = owner, .id = keylet.
key, .amount = asset(0)});
858 testCase([&](Env& env,
860 Account
const& owner,
863 testcase(
"invalid set immutable flag");
865 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
868 auto tx = vault.set({.owner = owner, .id = keylet.
key});
874 testCase([&](Env& env,
876 Account
const& owner,
879 testcase(
"invalid withdraw amount");
881 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
884 auto tx = vault.withdraw(
892 auto tx = vault.withdraw(
893 {.depositor = owner, .id = keylet.
key, .amount = asset(0)});
898 testCase([&](Env& env,
899 Account
const& issuer,
900 Account
const& owner,
905 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
908 auto tx = vault.clawback(
912 .amount = asset(50)});
917 auto tx = vault.clawback(
926 testCase([&](Env& env,
928 Account
const& owner,
933 auto [tx1, keylet] = vault.create({.owner = owner, .asset = asset});
937 tx[sfWithdrawalPolicy] = 0;
956 tx[sfDomainID] =
"0";
1113 using namespace test::jtx;
1116 testcase(
"IOU fail create frozen");
1117 Env env{*
this, testable_amendments() | featureSingleAssetVault};
1118 Account issuer{
"issuer"};
1119 Account owner{
"owner"};
1120 env.fund(XRP(1000), issuer, owner);
1126 Asset asset = issuer[
"IOU"];
1128 vault.create({.owner = owner, .asset = asset});
1135 testcase(
"IOU fail create no ripling");
1136 Env env{*
this, testable_amendments() | featureSingleAssetVault};
1137 Account issuer{
"issuer"};
1138 Account owner{
"owner"};
1139 env.fund(XRP(1000), issuer, owner);
1145 Asset asset = issuer[
"IOU"];
1147 vault.create({.owner = owner, .asset = asset});
1154 Env env{*
this, testable_amendments() | featureSingleAssetVault};
1155 Account issuer{
"issuer"};
1156 Account owner{
"owner"};
1157 env.fund(XRP(1000), owner);
1161 Asset asset = issuer[
"IOU"];
1164 vault.create({.owner = owner, .asset = asset});
1172 testcase(
"IOU fail create vault for AMM LPToken");
1173 Env env{*
this, testable_amendments() | featureSingleAssetVault};
1174 Account
const gw(
"gateway");
1175 Account
const alice(
"alice");
1176 Account
const carol(
"carol");
1177 IOU
const USD = gw[
"USD"];
1179 auto const [asset1, asset2] =
1184 auto const defXRP = XRP(30000);
1187 return a + XRP(1000);
1194 auto const toFund1 = tofund(asset1);
1195 auto const toFund2 = tofund(asset2);
1196 BEAST_EXPECT(asset1 <= toFund1 && asset2 <= toFund2);
1198 if (!asset1.native() && !asset2.native())
1199 fund(env, gw, {alice, carol}, {toFund1, toFund2}, Fund::All);
1200 else if (asset1.native())
1201 fund(env, gw, {alice, carol}, toFund1, {toFund2}, Fund::All);
1202 else if (asset2.native())
1203 fund(env, gw, {alice, carol}, toFund2, {toFund1}, Fund::All);
1206 env, alice, asset1, asset2, CreateArg{.log =
false, .tfee = 0});
1208 Account
const owner{
"owner"};
1209 env.fund(XRP(1000000), owner);
1213 vault.create({.owner = owner, .asset = ammAlice.lptIssue()});
1355 using namespace test::jtx;
1359 bool enableClawback =
true;
1363 auto testCase = [
this](
1366 Account
const& issuer,
1367 Account
const& owner,
1368 Account
const& depositor,
1371 MPTTester& mptt)> test,
1372 CaseArgs args = {}) {
1373 Env env{*
this, testable_amendments() | featureSingleAssetVault};
1374 Account issuer{
"issuer"};
1375 Account owner{
"owner"};
1376 Account depositor{
"depositor"};
1377 env.fund(XRP(1000), issuer, owner, depositor);
1381 MPTTester mptt{env, issuer, mptInitNoFund};
1388 mptt.authorize({.account = owner});
1389 mptt.authorize({.account = depositor});
1390 if (args.requireAuth)
1392 mptt.authorize({.account = issuer, .holder = owner});
1393 mptt.authorize({.account = issuer, .holder = depositor});
1396 env(pay(issuer, depositor, asset(1000)));
1399 test(env, issuer, owner, depositor, asset, vault, mptt);
1404 Account
const& issuer,
1405 Account
const& owner,
1406 Account
const& depositor,
1410 testcase(
"MPT nothing to clawback from");
1411 auto tx = vault.clawback(
1414 .holder = depositor,
1415 .amount = asset(10)});
1421 Account
const& issuer,
1422 Account
const& owner,
1423 Account
const& depositor,
1427 testcase(
"MPT global lock blocks create");
1428 mptt.set({.account = issuer, .flags =
tfMPTLock});
1429 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1435 Account
const& issuer,
1436 Account
const& owner,
1437 Account
const& depositor,
1441 testcase(
"MPT global lock blocks deposit");
1442 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1446 mptt.set({.account = issuer, .flags =
tfMPTLock});
1450 {.depositor = depositor,
1452 .amount = asset(100)});
1457 tx = vault.del({.owner = owner, .id = keylet.
key});
1463 Account
const& issuer,
1464 Account
const& owner,
1465 Account
const& depositor,
1469 testcase(
"MPT global lock blocks withdrawal");
1470 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1474 {.depositor = depositor,
1476 .amount = asset(100)});
1482 auto v = env.le(keylet);
1484 MPTID share = (*v)[sfShareMPTID];
1486 BEAST_EXPECT(issuance);
1487 Number outstandingShares = issuance->at(sfOutstandingAmount);
1488 BEAST_EXPECT(outstandingShares == 100);
1490 mptt.set({.account = issuer, .flags =
tfMPTLock});
1493 tx = vault.withdraw(
1494 {.depositor = depositor,
1496 .amount = asset(100)});
1499 tx[sfDestination] = issuer.human();
1503 tx = vault.clawback(
1506 .holder = depositor,
1507 .amount = asset(0)});
1512 tx = vault.del({.owner = owner, .id = keylet.
key});
1518 Account
const& issuer,
1519 Account
const& owner,
1520 Account
const& depositor,
1524 testcase(
"MPT only issuer can clawback");
1526 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1531 {.depositor = depositor,
1533 .amount = asset(100)});
1538 auto tx = vault.clawback(
1539 {.issuer = owner, .id = keylet.
key, .holder = depositor});
1547 Account
const& issuer,
1548 Account
const& owner,
1549 Account
const& depositor,
1554 "MPT 3rd party without MPToken cannot be withdrawal "
1558 vault.create({.owner = owner, .asset = asset});
1563 {.depositor = depositor,
1565 .amount = asset(100)});
1571 Account charlie{
"charlie"};
1572 env.fund(XRP(1000), charlie);
1575 tx = vault.withdraw(
1576 {.depositor = depositor,
1578 .amount = asset(100)});
1579 tx[sfDestination] = charlie.human();
1583 {.requireAuth =
false});
1588 Account
const& issuer,
1589 Account
const& owner,
1590 Account
const& depositor,
1594 testcase(
"MPT depositor without MPToken cannot withdraw");
1597 vault.create({.owner = owner, .asset = asset});
1602 {.depositor = depositor,
1604 .amount = asset(1000)});
1613 auto const mptoken =
1615 BEAST_EXPECT(mptoken ==
nullptr);
1617 tx = vault.withdraw(
1618 {.depositor = depositor,
1620 .amount = asset(100)});
1626 mptt.authorize({.account = depositor});
1629 tx = vault.withdraw(
1630 {.depositor = depositor,
1632 .amount = asset(100)});
1636 {.requireAuth =
false});
1640 Account
const& issuer,
1641 Account
const& owner,
1642 Account
const& depositor,
1648 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1653 {.depositor = depositor,
1655 .amount = asset(1000)});
1660 auto tx = vault.clawback(
1663 .holder = depositor,
1664 .amount = asset(0)});
1668 mptt.destroy({.issuer = issuer, .id = mptt.issuanceID()});
1673 vault.create({.owner = depositor, .asset = asset});
1678 auto tx = vault.deposit(
1679 {.depositor = depositor,
1681 .amount = asset(10)});
1686 auto tx = vault.withdraw(
1687 {.depositor = depositor,
1689 .amount = asset(10)});
1694 auto tx = vault.clawback(
1697 .holder = depositor,
1698 .amount = asset(0)});
1702 env(vault.del({.owner = owner, .id = keylet.key}));
1708 Account
const& issuer,
1709 Account
const& owner,
1710 Account
const& depositor,
1717 vault.create({.owner = owner, .asset = asset});
1722 {.depositor = depositor,
1724 .amount = asset(1000)});
1729 auto tx = vault.clawback(
1732 .holder = depositor,
1733 .amount = asset(0)});
1737 {.enableClawback =
false});
1741 Account
const& issuer,
1742 Account
const& owner,
1743 Account
const& depositor,
1748 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1752 {.depositor = depositor,
1754 .amount = asset(1000)});
1760 .holder = depositor,
1765 auto tx = vault.withdraw(
1766 {.depositor = depositor,
1768 .amount = asset(100)});
1772 tx[sfDestination] = issuer.human();
1774 tx[sfDestination] = owner.human();
1781 auto tx = vault.deposit(
1782 {.depositor = depositor,
1784 .amount = asset(100)});
1789 tx = vault.clawback(
1792 .holder = depositor,
1793 .amount = asset(800)});
1796 env(vault.del({.owner = owner, .id = keylet.key}));
1801 Account
const& issuer,
1802 Account
const& owner,
1803 Account
const& depositor,
1807 testcase(
"MPT lock of vault pseudo-account");
1808 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1812 auto const vaultAccount =
1813 [&env, keylet = keylet,
this]() ->
AccountID {
1814 auto const vault = env.le(keylet);
1815 BEAST_EXPECT(vault !=
nullptr);
1816 return vault->at(sfAccount);
1820 {.depositor = depositor,
1822 .amount = asset(100)});
1828 jv[jss::Account] = issuer.human();
1829 jv[sfMPTokenIssuanceID] =
1831 jv[jss::Holder] =
toBase58(vaultAccount);
1832 jv[jss::TransactionType] = jss::MPTokenIssuanceSet;
1840 {.depositor = depositor,
1842 .amount = asset(100)});
1845 tx = vault.withdraw(
1846 {.depositor = depositor,
1848 .amount = asset(100)});
1852 tx = vault.clawback(
1855 .holder = depositor,
1856 .amount = asset(100)});
1860 tx = vault.del({.owner = owner, .id = keylet.
key});
1867 Env env{*
this, testable_amendments() | featureSingleAssetVault};
1868 Account owner{
"owner"};
1869 Account issuer{
"issuer"};
1870 env.fund(XRP(1000000), owner, issuer);
1874 MPTTester mptt{env, issuer, mptInitNoFund};
1878 mptt.authorize({.account = owner});
1879 mptt.authorize({.account = issuer, .holder = owner});
1881 env(pay(issuer, owner, asset(100)));
1882 auto [tx1, k1] = vault.create({.owner = owner, .asset = asset});
1886 auto const shares = [&env, keylet = k1,
this]() ->
Asset {
1887 auto const vault = env.le(keylet);
1888 BEAST_EXPECT(vault !=
nullptr);
1889 return MPTIssue(vault->at(sfShareMPTID));
1892 auto [tx2, k2] = vault.create({.owner = owner, .asset = shares});
1901 using namespace test::jtx;
1907 Account
const& owner,
1908 Account
const& issuer,
1909 Account
const& charlie,
1916 Env env{*
this, testable_amendments() | featureSingleAssetVault};
1917 Account
const owner{
"owner"};
1918 Account
const issuer{
"issuer"};
1919 Account
const charlie{
"charlie"};
1921 env.fund(XRP(1000), issuer, owner, charlie);
1926 env.trust(asset(1000), owner);
1927 env.trust(asset(1000), charlie);
1928 env(pay(issuer, owner, asset(200)));
1929 env(rate(issuer, 1.25));
1932 auto const [tx, keylet] =
1933 vault.create({.owner = owner, .asset = asset});
1937 auto const vaultAccount =
1939 return env.le(keylet)->at(sfAccount);
1942 return env.le(keylet)->at(sfShareMPTID);
1944 auto const vaultBalance =
1945 [&env, &vaultAccount, issue = asset.
raw().
get<
Issue>()](
1947 auto const account = vaultAccount(keylet);
1952 env.lookup(issue.account).name()};
1953 auto amount = sle->getFieldAmount(sfBalance);
1955 if (account > issue.account)
1957 return {amount, env.lookup(issue.account).name()};
1974 Account
const& owner,
1975 Account
const& issuer,
1981 testcase(
"IOU cannot use different asset");
1984 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1990 auto tx = [&, account = vaultAccount(keylet)]() {
1992 jv[jss::Account] = issuer.human();
1994 auto& ja = jv[jss::LimitAmount] =
1996 ja[jss::issuer] =
toBase58(account);
1998 jv[jss::TransactionType] = jss::TrustSet;
2007 auto tx = vault.deposit(
2008 {.depositor = issuer, .id = keylet.
key, .amount = foo(20)});
2014 auto tx = vault.withdraw(
2015 {.depositor = issuer, .id = keylet.
key, .amount = foo(20)});
2020 env(vault.del({.owner = owner, .id = keylet.key}));
2026 Account
const& owner,
2027 Account
const& issuer,
2028 Account
const& charlie,
2034 testcase(
"IOU frozen trust line to vault account");
2036 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2041 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2044 Asset const share =
Asset(issuanceId(keylet));
2047 auto trustSet = [&, account = vaultAccount(keylet)]() {
2049 jv[jss::Account] = issuer.human();
2051 auto& ja = jv[jss::LimitAmount] =
2053 ja[jss::issuer] =
toBase58(account);
2055 jv[jss::TransactionType] = jss::TrustSet;
2067 auto tx = vault.deposit(
2068 {.depositor = owner,
2070 .amount = asset(80)});
2075 auto tx = vault.withdraw(
2076 {.depositor = owner,
2078 .amount = asset(100)});
2082 tx[sfDestination] = charlie.human();
2089 auto tx = vault.clawback(
2093 .amount = asset(50)});
2104 {.depositor = owner, .id = keylet.key, .amount = share(50)}));
2106 env(vault.del({.owner = owner, .id = keylet.key}));
2112 Account
const& owner,
2113 Account
const& issuer,
2114 Account
const& charlie,
2119 auto vaultBalance) {
2120 testcase(
"IOU transfer fees not applied");
2122 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2127 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2131 Asset const share =
Asset(issuanceId(keylet));
2134 BEAST_EXPECT(env.balance(owner, issue) == asset(100));
2135 BEAST_EXPECT(vaultBalance(keylet) == asset(100));
2138 auto tx = vault.clawback(
2142 .amount = asset(50)});
2148 BEAST_EXPECT(env.balance(owner, issue) == asset(100));
2149 BEAST_EXPECT(vaultBalance(keylet) == asset(50));
2152 {.depositor = owner, .id = keylet.key, .amount = share(20)}));
2155 BEAST_EXPECT(env.balance(owner, issue) == asset(120));
2156 BEAST_EXPECT(vaultBalance(keylet) == asset(30));
2159 auto tx = vault.withdraw(
2160 {.depositor = owner,
2162 .amount = share(30)});
2163 tx[sfDestination] = charlie.human();
2168 BEAST_EXPECT(env.balance(owner, issue) == asset(120));
2169 BEAST_EXPECT(env.balance(charlie, issue) == asset(30));
2170 BEAST_EXPECT(vaultBalance(keylet) == asset(0));
2172 env(vault.del({.owner = owner, .id = keylet.key}));
2178 Account
const& owner,
2179 Account
const& issuer,
2180 Account
const& charlie,
2185 testcase(
"IOU frozen trust line to depositor");
2187 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2192 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2197 auto tx = vault.withdraw(
2198 {.depositor = owner,
2200 .amount = asset(10)});
2201 tx[sfDestination] = charlie.human();
2204 env(withdrawToCharlie);
2211 auto const withdraw = vault.withdraw(
2212 {.depositor = owner, .id = keylet.
key, .amount = asset(10)});
2221 auto tx = vault.deposit(
2222 {.depositor = owner,
2224 .amount = asset(10)});
2230 auto tx = vault.clawback(
2234 .amount = asset(0)});
2239 env(vault.del({.owner = owner, .id = keylet.key}));
2245 Account
const& owner,
2246 Account
const& issuer,
2247 Account
const& charlie,
2252 testcase(
"IOU no trust line to 3rd party");
2254 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2259 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2262 Account
const erin{
"erin"};
2263 env.fund(XRP(1000), erin);
2268 auto tx = vault.withdraw(
2269 {.depositor = owner,
2271 .amount = asset(10)});
2272 tx[sfDestination] = erin.human();
2280 Account
const& owner,
2281 Account
const& issuer,
2282 Account
const& charlie,
2287 testcase(
"IOU no trust line to depositor");
2289 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2294 env.trust(asset(0), owner);
2298 {.depositor = owner, .id = keylet.key, .amount = asset(200)}));
2303 BEAST_EXPECT(trustline ==
nullptr);
2307 auto tx = vault.withdraw(
2308 {.depositor = owner,
2310 .amount = asset(10)});
2318 Account
const& owner,
2319 Account
const& issuer,
2320 Account
const& charlie,
2325 testcase(
"IOU frozen trust line to 3rd party");
2327 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2332 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2337 auto tx = vault.withdraw(
2338 {.depositor = owner,
2340 .amount = asset(10)});
2341 tx[sfDestination] = charlie.human();
2344 env(withdrawToCharlie);
2347 env(trust(issuer, asset(0), charlie,
tfSetFreeze));
2351 auto const withdraw = vault.withdraw(
2352 {.depositor = owner, .id = keylet.
key, .amount = asset(10)});
2364 .amount = asset(0)}));
2367 env(vault.del({.owner = owner, .id = keylet.key}));
2373 Account
const& owner,
2374 Account
const& issuer,
2375 Account
const& charlie,
2382 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2387 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2395 auto tx = vault.withdraw(
2396 {.depositor = owner,
2398 .amount = asset(10)});
2402 tx[sfDestination] = charlie.human();
2408 {.depositor = owner,
2410 .amount = asset(10)});
2420 .amount = asset(0)}));
2423 env(vault.del({.owner = owner, .id = keylet.key}));
2431 using namespace test::jtx;
2435 Env env{*
this, testable_amendments() | featureSingleAssetVault};
2436 Account issuer{
"issuer"};
2437 Account owner{
"owner"};
2438 Account depositor{
"depositor"};
2439 Account charlie{
"charlie"};
2440 Account pdOwner{
"pdOwner"};
2441 Account credIssuer1{
"credIssuer1"};
2442 Account credIssuer2{
"credIssuer2"};
2460 env.trust(asset(1000), owner);
2461 env(pay(issuer, owner, asset(500)));
2462 env.trust(asset(1000), depositor);
2463 env(pay(issuer, depositor, asset(500)));
2464 env.trust(asset(1000), charlie);
2465 env(pay(issuer, charlie, asset(5)));
2468 auto [tx, keylet] = vault.create(
2472 BEAST_EXPECT(env.le(keylet));
2475 testcase(
"private vault owner can deposit");
2476 auto tx = vault.deposit(
2477 {.depositor = owner, .id = keylet.
key, .amount = asset(50)});
2482 testcase(
"private vault depositor not authorized yet");
2483 auto tx = vault.deposit(
2484 {.depositor = depositor,
2486 .amount = asset(50)});
2491 testcase(
"private vault cannot set non-existing domain");
2492 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2498 testcase(
"private vault set domainId");
2501 pdomain::Credentials
const credentials1{
2502 {.issuer = credIssuer1, .credType = credType}};
2504 env(pdomain::setTx(pdOwner, credentials1));
2505 auto const domainId1 = [&]() {
2507 return pdomain::getNewDomain(env.meta());
2510 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2521 pdomain::Credentials
const credentials{
2522 {.issuer = credIssuer1, .credType = credType},
2523 {.issuer = credIssuer2, .credType = credType}};
2525 env(pdomain::setTx(pdOwner, credentials));
2526 auto const domainId = [&]() {
2528 return pdomain::getNewDomain(env.meta());
2531 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2539 testcase(
"private vault depositor still not authorized");
2540 auto tx = vault.deposit(
2541 {.depositor = depositor,
2543 .amount = asset(50)});
2548 auto const credKeylet =
2549 credentials::keylet(depositor, credIssuer1, credType);
2551 testcase(
"private vault depositor now authorized");
2552 env(credentials::create(depositor, credIssuer1, credType));
2553 env(credentials::accept(depositor, credIssuer1, credType));
2554 env(credentials::create(charlie, credIssuer1, credType));
2557 auto credSle = env.le(credKeylet);
2558 BEAST_EXPECT(credSle !=
nullptr);
2560 auto tx = vault.deposit(
2561 {.depositor = depositor,
2563 .amount = asset(50)});
2568 {.depositor = charlie, .id = keylet.
key, .amount = asset(50)});
2574 testcase(
"private vault depositor lost authorization");
2575 env(credentials::deleteCred(
2576 credIssuer1, depositor, credIssuer1, credType));
2577 env(credentials::deleteCred(
2578 credIssuer1, charlie, credIssuer1, credType));
2580 auto credSle = env.le(credKeylet);
2581 BEAST_EXPECT(credSle ==
nullptr);
2583 auto tx = vault.deposit(
2584 {.depositor = depositor,
2586 .amount = asset(50)});
2591 auto const shares = [&env, keylet = keylet,
this]() ->
Asset {
2592 auto const vault = env.le(keylet);
2593 BEAST_EXPECT(vault !=
nullptr);
2594 return MPTIssue(vault->at(sfShareMPTID));
2598 testcase(
"private vault expired authorization");
2599 uint32_t
const closeTime = env.current()
2601 .parentCloseTime.time_since_epoch()
2605 credentials::create(depositor, credIssuer2, credType);
2606 tx0[sfExpiration] = closeTime + 20;
2608 tx0 = credentials::create(charlie, credIssuer2, credType);
2609 tx0[sfExpiration] = closeTime + 20;
2613 env(credentials::accept(depositor, credIssuer2, credType));
2614 env(credentials::accept(charlie, credIssuer2, credType));
2619 auto tx1 = vault.deposit(
2620 {.depositor = depositor,
2622 .amount = asset(50)});
2628 BEAST_EXPECT(env.le(tokenKeylet) !=
nullptr);
2637 auto const credsKeylet =
2638 credentials::keylet(depositor, credIssuer2, credType);
2639 BEAST_EXPECT(env.le(credsKeylet) !=
nullptr);
2641 auto tx2 = vault.deposit(
2642 {.depositor = depositor,
2644 .amount = asset(1)});
2648 BEAST_EXPECT(env.le(credsKeylet) ==
nullptr);
2652 auto const credsKeylet =
2653 credentials::keylet(charlie, credIssuer2, credType);
2654 BEAST_EXPECT(env.le(credsKeylet) !=
nullptr);
2657 BEAST_EXPECT(env.le(tokenKeylet) ==
nullptr);
2659 auto tx3 = vault.deposit(
2660 {.depositor = charlie,
2662 .amount = asset(2)});
2666 BEAST_EXPECT(env.le(credsKeylet) ==
nullptr);
2667 BEAST_EXPECT(env.le(tokenKeylet) ==
nullptr);
2672 testcase(
"private vault reset domainId");
2673 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2674 tx[sfDomainID] =
"0";
2679 {.depositor = depositor,
2681 .amount = asset(50)});
2685 tx = vault.withdraw(
2686 {.depositor = depositor,
2688 .amount = asset(50)});
2691 tx = vault.clawback(
2694 .holder = depositor,
2695 .amount = asset(0)});
2698 tx = vault.clawback(
2702 .amount = asset(0)});
2716 using namespace test::jtx;
2720 Env env{*
this, testable_amendments() | featureSingleAssetVault};
2721 Account owner{
"owner"};
2722 Account depositor{
"depositor"};
2723 Account alice{
"charlie"};
2726 env.fund(XRP(100000), owner, depositor, alice);
2730 auto [tx, keylet] = vault.create(
2735 auto const [vaultAccount, issuanceId] =
2737 auto const vault = env.le(keylet);
2738 BEAST_EXPECT(vault !=
nullptr);
2739 return {vault->at(sfAccount), vault->at(sfShareMPTID)};
2746 testcase(
"private XRP vault owner can deposit");
2747 auto tx = vault.deposit(
2748 {.depositor = owner, .id = keylet.
key, .amount = asset(50)});
2753 testcase(
"private XRP vault cannot pay shares to depositor yet");
2754 env(pay(owner, depositor, shares(1)), ter{
tecNO_AUTH});
2758 testcase(
"private XRP vault depositor not authorized yet");
2759 auto tx = vault.deposit(
2760 {.depositor = depositor,
2762 .amount = asset(50)});
2767 testcase(
"private XRP vault set DomainID");
2768 pdomain::Credentials
const credentials{
2769 {.issuer = owner, .credType = credType}};
2771 env(pdomain::setTx(owner, credentials));
2772 auto const domainId = [&]() {
2774 return pdomain::getNewDomain(env.meta());
2777 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2783 auto const credKeylet = credentials::keylet(depositor, owner, credType);
2785 testcase(
"private XRP vault depositor now authorized");
2786 env(credentials::create(depositor, owner, credType));
2787 env(credentials::accept(depositor, owner, credType));
2790 BEAST_EXPECT(env.le(credKeylet));
2791 auto tx = vault.deposit(
2792 {.depositor = depositor,
2794 .amount = asset(50)});
2800 testcase(
"private XRP vault can pay shares to depositor");
2801 env(pay(owner, depositor, shares(1)));
2805 testcase(
"private XRP vault cannot pay shares to 3rd party");
2807 jv[sfAccount] = alice.human();
2808 jv[sfTransactionType] = jss::MPTokenAuthorize;
2809 jv[sfMPTokenIssuanceID] =
to_string(issuanceId);
2813 env(pay(owner, alice, shares(1)), ter{
tecNO_AUTH});
2849 using namespace test::jtx;
2852 Env env{*
this, testable_amendments() | featureSingleAssetVault};
2853 Account
const owner{
"owner"};
2854 Account
const issuer{
"issuer"};
2856 env.fund(XRP(1000), issuer, owner);
2860 env.trust(asset(1000), owner);
2861 env(pay(issuer, owner, asset(200)));
2864 auto const sequence = env.seq(owner);
2865 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2871 auto tx1 = vault.deposit(
2872 {.depositor = owner, .id = keylet.
key, .amount = asset(50)});
2875 auto tx2 = vault.set({.owner = owner, .id = keylet.
key});
2876 tx2[sfAssetsMaximum] = asset(1000).number();
2881 auto const sleVault = [&env, keylet = keylet,
this]() {
2882 auto const vault = env.le(keylet);
2883 BEAST_EXPECT(vault !=
nullptr);
2887 auto const check = [&, keylet = keylet, sle = sleVault,
this](
2890 BEAST_EXPECT(vault.isObject());
2892 constexpr auto checkString =
2894 return node.isMember(field.fieldName) &&
2895 node[field.fieldName].isString() &&
2896 node[field.fieldName] == v;
2898 constexpr auto checkObject =
2900 return node.isMember(field.fieldName) &&
2901 node[field.fieldName].isObject() &&
2902 node[field.fieldName] == v;
2904 constexpr auto checkInt =
2905 [](
auto& node,
SField const& field,
int v) ->
bool {
2906 return node.isMember(field.fieldName) &&
2907 ((node[field.fieldName].isInt() &&
2908 node[field.fieldName] ==
Json::Int(v)) ||
2909 (node[field.fieldName].isUInt() &&
2913 BEAST_EXPECT(vault[
"LedgerEntryType"].asString() ==
"Vault");
2914 BEAST_EXPECT(vault[jss::index].asString() ==
strHex(keylet.
key));
2915 BEAST_EXPECT(checkInt(vault, sfFlags, 0));
2919 checkString(vault, sfAccount,
toBase58(sle->at(sfAccount))));
2921 checkObject(vault, sfAsset,
to_json(sle->at(sfAsset))));
2922 BEAST_EXPECT(checkString(vault, sfAssetsAvailable,
"50"));
2923 BEAST_EXPECT(checkString(vault, sfAssetsMaximum,
"1000"));
2924 BEAST_EXPECT(checkString(vault, sfAssetsTotal,
"50"));
2925 BEAST_EXPECT(checkString(vault, sfLossUnrealized,
"0"));
2927 auto const strShareID =
strHex(sle->at(sfShareMPTID));
2928 BEAST_EXPECT(checkString(vault, sfShareMPTID, strShareID));
2929 BEAST_EXPECT(checkString(vault, sfOwner,
toBase58(owner.id())));
2930 BEAST_EXPECT(checkInt(vault, sfSequence, sequence));
2931 BEAST_EXPECT(checkInt(
2934 if (issuance.isObject())
2937 issuance[
"LedgerEntryType"].asString() ==
2940 issuance[jss::mpt_issuance_id].asString() == strShareID);
2941 BEAST_EXPECT(checkInt(issuance, sfSequence, 1));
2942 BEAST_EXPECT(checkInt(
2946 BEAST_EXPECT(checkString(issuance, sfOutstandingAmount,
"50"));
2951 testcase(
"RPC ledger_entry selected by key");
2953 jvParams[jss::ledger_index] = jss::validated;
2954 jvParams[jss::vault] =
strHex(keylet.
key);
2955 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2957 BEAST_EXPECT(!jvVault[jss::result].isMember(jss::error));
2958 BEAST_EXPECT(jvVault[jss::result].isMember(jss::node));
2959 check(jvVault[jss::result][jss::node]);
2963 testcase(
"RPC ledger_entry selected by owner and seq");
2965 jvParams[jss::ledger_index] = jss::validated;
2966 jvParams[jss::vault][jss::owner] = owner.human();
2967 jvParams[jss::vault][jss::seq] = sequence;
2968 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2970 BEAST_EXPECT(!jvVault[jss::result].isMember(jss::error));
2971 BEAST_EXPECT(jvVault[jss::result].isMember(jss::node));
2972 check(jvVault[jss::result][jss::node]);
2976 testcase(
"RPC ledger_entry cannot find vault by key");
2978 jvParams[jss::ledger_index] = jss::validated;
2980 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2982 jvVault[jss::result][jss::error].asString() ==
"entryNotFound");
2986 testcase(
"RPC ledger_entry cannot find vault by owner and seq");
2988 jvParams[jss::ledger_index] = jss::validated;
2989 jvParams[jss::vault][jss::owner] = issuer.human();
2990 jvParams[jss::vault][jss::seq] = 1'000'000;
2991 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2993 jvVault[jss::result][jss::error].asString() ==
"entryNotFound");
2997 testcase(
"RPC ledger_entry malformed key");
2999 jvParams[jss::ledger_index] = jss::validated;
3000 jvParams[jss::vault] = 42;
3001 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
3003 jvVault[jss::result][jss::error].asString() ==
3004 "malformedRequest");
3008 testcase(
"RPC ledger_entry malformed owner");
3010 jvParams[jss::ledger_index] = jss::validated;
3011 jvParams[jss::vault][jss::owner] = 42;
3012 jvParams[jss::vault][jss::seq] = sequence;
3013 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
3015 jvVault[jss::result][jss::error].asString() ==
3020 testcase(
"RPC ledger_entry malformed seq");
3022 jvParams[jss::ledger_index] = jss::validated;
3023 jvParams[jss::vault][jss::owner] = issuer.human();
3024 jvParams[jss::vault][jss::seq] =
"foo";
3025 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
3027 jvVault[jss::result][jss::error].asString() ==
3028 "malformedRequest");
3032 testcase(
"RPC ledger_entry zero seq");
3034 jvParams[jss::ledger_index] = jss::validated;
3035 jvParams[jss::vault][jss::owner] = issuer.human();
3036 jvParams[jss::vault][jss::seq] = 0;
3037 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
3039 jvVault[jss::result][jss::error].asString() ==
3040 "malformedRequest");
3044 testcase(
"RPC ledger_entry negative seq");
3046 jvParams[jss::ledger_index] = jss::validated;
3047 jvParams[jss::vault][jss::owner] = issuer.human();
3048 jvParams[jss::vault][jss::seq] = -1;
3049 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
3051 jvVault[jss::result][jss::error].asString() ==
3052 "malformedRequest");
3056 testcase(
"RPC ledger_entry oversized seq");
3058 jvParams[jss::ledger_index] = jss::validated;
3059 jvParams[jss::vault][jss::owner] = issuer.human();
3060 jvParams[jss::vault][jss::seq] = 1e20;
3061 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
3063 jvVault[jss::result][jss::error].asString() ==
3064 "malformedRequest");
3068 testcase(
"RPC ledger_entry bool seq");
3070 jvParams[jss::ledger_index] = jss::validated;
3071 jvParams[jss::vault][jss::owner] = issuer.human();
3072 jvParams[jss::vault][jss::seq] =
true;
3073 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
3075 jvVault[jss::result][jss::error].asString() ==
3076 "malformedRequest");
3083 jvParams[jss::account] = owner.human();
3084 jvParams[jss::type] = jss::vault;
3086 "json",
"account_objects",
to_string(jvParams))[jss::result];
3088 BEAST_EXPECT(jv[jss::account_objects].size() == 1);
3089 check(jv[jss::account_objects][0u]);
3096 jvParams[jss::ledger_index] = jss::validated;
3097 jvParams[jss::binary] =
false;
3098 jvParams[jss::type] = jss::vault;
3100 env.rpc(
"json",
"ledger_data",
to_string(jvParams));
3101 BEAST_EXPECT(jv[jss::result][jss::state].size() == 1);
3102 check(jv[jss::result][jss::state][0u]);
3106 testcase(
"RPC vault_info command line");
3108 env.rpc(
"vault_info",
strHex(keylet.
key),
"validated");
3110 BEAST_EXPECT(!jv[jss::result].isMember(jss::error));
3111 BEAST_EXPECT(jv[jss::result].isMember(jss::vault));
3113 jv[jss::result][jss::vault],
3114 jv[jss::result][jss::vault][jss::shares]);
3120 jvParams[jss::ledger_index] = jss::validated;
3121 jvParams[jss::vault_id] =
strHex(keylet.
key);
3122 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3124 BEAST_EXPECT(!jv[jss::result].isMember(jss::error));
3125 BEAST_EXPECT(jv[jss::result].isMember(jss::vault));
3127 jv[jss::result][jss::vault],
3128 jv[jss::result][jss::vault][jss::shares]);
3132 testcase(
"RPC vault_info invalid vault_id");
3134 jvParams[jss::ledger_index] = jss::validated;
3135 jvParams[jss::vault_id] =
"foobar";
3136 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3138 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3142 testcase(
"RPC vault_info json invalid index");
3144 jvParams[jss::ledger_index] = jss::validated;
3145 jvParams[jss::vault_id] = 0;
3146 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3148 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3152 testcase(
"RPC vault_info json by owner and sequence");
3154 jvParams[jss::ledger_index] = jss::validated;
3155 jvParams[jss::owner] = owner.human();
3156 jvParams[jss::seq] = sequence;
3157 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3159 BEAST_EXPECT(!jv[jss::result].isMember(jss::error));
3160 BEAST_EXPECT(jv[jss::result].isMember(jss::vault));
3162 jv[jss::result][jss::vault],
3163 jv[jss::result][jss::vault][jss::shares]);
3167 testcase(
"RPC vault_info json malformed sequence");
3169 jvParams[jss::ledger_index] = jss::validated;
3170 jvParams[jss::owner] = owner.human();
3171 jvParams[jss::seq] =
"foobar";
3172 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3174 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3178 testcase(
"RPC vault_info json invalid sequence");
3180 jvParams[jss::ledger_index] = jss::validated;
3181 jvParams[jss::owner] = owner.human();
3182 jvParams[jss::seq] = 0;
3183 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3185 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3189 testcase(
"RPC vault_info json negative sequence");
3191 jvParams[jss::ledger_index] = jss::validated;
3192 jvParams[jss::owner] = owner.human();
3193 jvParams[jss::seq] = -1;
3194 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3196 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3200 testcase(
"RPC vault_info json oversized sequence");
3202 jvParams[jss::ledger_index] = jss::validated;
3203 jvParams[jss::owner] = owner.human();
3204 jvParams[jss::seq] = 1e20;
3205 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3207 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3211 testcase(
"RPC vault_info json bool sequence");
3213 jvParams[jss::ledger_index] = jss::validated;
3214 jvParams[jss::owner] = owner.human();
3215 jvParams[jss::seq] =
true;
3216 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3218 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3222 testcase(
"RPC vault_info json malformed owner");
3224 jvParams[jss::ledger_index] = jss::validated;
3225 jvParams[jss::owner] =
"foobar";
3226 jvParams[jss::seq] = sequence;
3227 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3229 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3233 testcase(
"RPC vault_info json invalid combination only owner");
3235 jvParams[jss::ledger_index] = jss::validated;
3236 jvParams[jss::owner] = owner.human();
3237 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3239 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3243 testcase(
"RPC vault_info json invalid combination only seq");
3245 jvParams[jss::ledger_index] = jss::validated;
3246 jvParams[jss::seq] = sequence;
3247 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3249 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3253 testcase(
"RPC vault_info json invalid combination seq vault_id");
3255 jvParams[jss::ledger_index] = jss::validated;
3256 jvParams[jss::vault_id] =
strHex(keylet.
key);
3257 jvParams[jss::seq] = sequence;
3258 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3260 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3264 testcase(
"RPC vault_info json invalid combination owner vault_id");
3266 jvParams[jss::ledger_index] = jss::validated;
3267 jvParams[jss::vault_id] =
strHex(keylet.
key);
3268 jvParams[jss::owner] = owner.human();
3269 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3271 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3276 "RPC vault_info json invalid combination owner seq "
3279 jvParams[jss::ledger_index] = jss::validated;
3280 jvParams[jss::vault_id] =
strHex(keylet.
key);
3281 jvParams[jss::seq] = sequence;
3282 jvParams[jss::owner] = owner.human();
3283 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3285 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3289 testcase(
"RPC vault_info json no input");
3291 jvParams[jss::ledger_index] = jss::validated;
3292 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3294 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3298 testcase(
"RPC vault_info command line invalid index");
3299 Json::Value jv = env.rpc(
"vault_info",
"foobar",
"validated");
3300 BEAST_EXPECT(jv[jss::error].asString() ==
"invalidParams");
3304 testcase(
"RPC vault_info command line invalid index");
3305 Json::Value jv = env.rpc(
"vault_info",
"0",
"validated");
3307 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3311 testcase(
"RPC vault_info command line invalid index");
3315 jv[jss::result][jss::error].asString() ==
"entryNotFound");
3319 testcase(
"RPC vault_info command line invalid ledger");
3322 jv[jss::result][jss::error].asString() ==
"lgrNotFound");