20#include <test/jtx/AMM.h>
21#include <test/jtx/AMMTest.h>
22#include <test/jtx/Account.h>
23#include <test/jtx/Env.h>
24#include <test/jtx/amount.h>
25#include <test/jtx/credentials.h>
26#include <test/jtx/fee.h>
27#include <test/jtx/flags.h>
28#include <test/jtx/mpt.h>
29#include <test/jtx/permissioned_domains.h>
30#include <test/jtx/utility.h>
31#include <test/jtx/vault.h>
33#include <xrpld/ledger/View.h>
35#include <xrpl/basics/base_uint.h>
36#include <xrpl/beast/unit_test/suite.h>
37#include <xrpl/json/json_forwards.h>
38#include <xrpl/json/json_value.h>
39#include <xrpl/protocol/AccountID.h>
40#include <xrpl/protocol/Asset.h>
41#include <xrpl/protocol/Feature.h>
42#include <xrpl/protocol/Indexes.h>
43#include <xrpl/protocol/Issue.h>
44#include <xrpl/protocol/MPTIssue.h>
45#include <xrpl/protocol/Protocol.h>
46#include <xrpl/protocol/SField.h>
47#include <xrpl/protocol/STAmount.h>
48#include <xrpl/protocol/STNumber.h>
49#include <xrpl/protocol/TER.h>
50#include <xrpl/protocol/TxFlags.h>
51#include <xrpl/protocol/XRPAmount.h>
52#include <xrpl/protocol/jss.h>
56using namespace test::jtx;
68 using namespace test::jtx;
70 auto const testSequence = [
this](
79 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
80 tx[sfData] =
"AFEED00E";
81 tx[sfAssetsMaximum] = asset(100).number();
84 BEAST_EXPECT(env.le(keylet));
86 auto const share = [&env, keylet = keylet,
this]() ->
PrettyAsset {
87 auto const vault = env.le(keylet);
88 BEAST_EXPECT(vault !=
nullptr);
89 return MPTIssue(vault->at(sfShareMPTID));
96 env.fund(
XRP(1000), alice, dave, erin);
102 testcase(prefix +
" fail to deposit more than assets held");
103 auto tx = vault.deposit(
104 {.depositor = depositor,
106 .amount = asset(10000)});
111 testcase(prefix +
" deposit non-zero amount");
112 auto tx = vault.deposit(
113 {.depositor = depositor,
115 .amount = asset(50)});
120 testcase(prefix +
" deposit non-zero amount again");
121 auto tx = vault.deposit(
122 {.depositor = depositor,
124 .amount = asset(50)});
129 testcase(prefix +
" fail to delete non-empty vault");
130 auto tx = vault.del({.owner = owner, .id = keylet.
key});
135 testcase(prefix +
" fail to update because wrong owner");
136 auto tx = vault.set({.owner = issuer, .id = keylet.
key});
137 tx[sfAssetsMaximum] = asset(50).number();
143 prefix +
" fail to set maximum lower than current amount");
144 auto tx = vault.set({.owner = owner, .id = keylet.
key});
145 tx[sfAssetsMaximum] = asset(50).number();
150 testcase(prefix +
" set maximum higher than current amount");
151 auto tx = vault.set({.owner = owner, .id = keylet.
key});
152 tx[sfAssetsMaximum] = asset(150).number();
158 auto tx = vault.set({.owner = owner, .id = keylet.
key});
164 testcase(prefix +
" fail to set domain on public vault");
165 auto tx = vault.set({.owner = owner, .id = keylet.
key});
171 testcase(prefix +
" fail to deposit more than maximum");
172 auto tx = vault.deposit(
173 {.depositor = depositor,
175 .amount = asset(100)});
180 testcase(prefix +
" reset maximum to zero i.e. not enforced");
181 auto tx = vault.set({.owner = owner, .id = keylet.
key});
182 tx[sfAssetsMaximum] = asset(0).number();
187 testcase(prefix +
" fail to withdraw more than assets held");
188 auto tx = vault.withdraw(
189 {.depositor = depositor,
191 .amount = asset(1000)});
196 testcase(prefix +
" deposit some more");
197 auto tx = vault.deposit(
198 {.depositor = depositor,
200 .amount = asset(100)});
205 testcase(prefix +
" clawback some");
208 auto tx = vault.clawback(
212 .amount = asset(10)});
220 auto tx = vault.clawback(
221 {.issuer = issuer, .id = keylet.
key, .holder = depositor});
225 if (!asset.raw().native())
227 testcase(prefix +
" deposit again");
228 auto tx = vault.deposit(
229 {.depositor = depositor,
231 .amount = asset(200)});
237 prefix +
" fail to withdraw to 3rd party lsfDepositAuth");
238 auto tx = vault.withdraw(
239 {.depositor = depositor,
241 .amount = asset(100)});
242 tx[sfDestination] = alice.human();
246 if (!asset.raw().native())
249 prefix +
" fail to withdraw to 3rd party no authorization");
250 auto tx = vault.withdraw(
251 {.depositor = depositor,
253 .amount = asset(100)});
254 tx[sfDestination] = erin.human();
259 if (!asset.raw().native() && asset.raw().holds<
Issue>())
261 testcase(prefix +
" temporary authorization for 3rd party");
262 env(
trust(erin, asset(1000)));
264 env(
pay(issuer, erin, asset(10)));
267 auto tx = vault.deposit(
268 {.depositor = erin, .id = keylet.
key, .amount = asset(10)});
270 env(
pay(erin, depositor, share(10)));
272 testcase(prefix +
" withdraw to authorized 3rd party");
275 {.depositor = depositor,
277 .amount = asset(10)});
278 tx[sfDestination] = erin.human();
281 env(
pay(erin, issuer, asset(10)));
283 testcase(prefix +
" fail to pay to unauthorized 3rd party");
284 env(
trust(erin, asset(0)));
292 " fail to withdraw to 3rd party lsfRequireDestTag");
293 auto tx = vault.withdraw(
294 {.depositor = depositor,
296 .amount = asset(100)});
297 tx[sfDestination] = dave.human();
302 testcase(prefix +
" withdraw to authorized 3rd party");
303 auto tx = vault.withdraw(
304 {.depositor = depositor,
306 .amount = asset(100)});
307 tx[sfDestination] = charlie.human();
312 testcase(prefix +
" withdraw to issuer");
313 auto tx = vault.withdraw(
314 {.depositor = depositor,
316 .amount = asset(50)});
317 tx[sfDestination] = issuer.human();
322 testcase(prefix +
" withdraw remaining assets");
323 auto tx = vault.withdraw(
324 {.depositor = depositor,
326 .amount = asset(50)});
331 testcase(prefix +
" fail to delete because wrong owner");
332 auto tx = vault.del({.owner = issuer, .id = keylet.
key});
337 testcase(prefix +
" delete empty vault");
338 auto tx = vault.del({.owner = owner, .id = keylet.
key});
340 BEAST_EXPECT(!env.le(keylet));
344 auto testCases = [
this, &testSequence](
351 Account const& charlie)> setup) {
355 Account depositor{
"depositor"};
358 env.fund(
XRP(1000), issuer, owner, depositor, charlie);
366 PrettyAsset asset = setup(env, issuer, owner, depositor, charlie);
368 prefix, env, issuer, owner, depositor, charlie, vault, asset);
389 env(
trust(owner, asset(1000)));
390 env(
trust(depositor, asset(1000)));
391 env(
trust(charlie, asset(1000)));
395 env(
pay(issuer, depositor, asset(1000)));
412 mptt.authorize({.account = depositor});
413 mptt.authorize({.account = charlie});
414 env(
pay(issuer, depositor, asset(1000)));
423 using namespace test::jtx;
431 auto testCase = [&,
this](
438 CaseArgs args = {}) {
439 Env env{*
this, args.features};
443 env.
fund(
XRP(1000), issuer, owner);
451 env(
trust(owner, asset(1000)));
453 env(
pay(issuer, owner, asset(1000)));
456 test(env, issuer, owner, asset, vault);
465 testcase(
"disabled single asset vault");
468 vault.create({.owner = owner, .asset = asset});
472 auto tx = vault.set({.owner = owner, .
id = keylet.
key});
477 auto tx = vault.deposit(
480 .amount = asset(10)});
485 auto tx = vault.withdraw(
488 .amount = asset(10)});
493 auto tx = vault.clawback(
497 .amount = asset(10)});
502 auto tx = vault.del({.owner = owner, .
id = keylet.
key});
508 testCase([&](
Env& env,
515 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
520 auto tx = vault.set({.owner = owner, .
id = keylet.
key});
526 auto tx = vault.deposit(
529 .amount = asset(10)});
535 auto tx = vault.withdraw(
538 .amount = asset(10)});
544 auto tx = vault.clawback(
548 .amount = asset(10)});
554 auto tx = vault.del({.owner = owner, .
id = keylet.
key});
560 testCase([&](
Env& env,
567 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
572 auto tx = vault.set({.owner = owner, .
id = keylet.
key});
578 auto tx = vault.deposit(
581 .amount = asset(10)});
587 auto tx = vault.withdraw(
590 .amount = asset(10)});
596 auto tx = vault.clawback(
600 .amount = asset(10)});
606 auto tx = vault.del({.owner = owner, .
id = keylet.
key});
618 testcase(
"disabled permissioned domain");
621 vault.create({.owner = owner, .asset =
xrpIssue()});
626 auto tx = vault.set({.owner = owner, .
id = keylet.
key});
632 auto tx = vault.set({.owner = owner, .
id = keylet.
key});
633 tx[sfDomainID] =
"0";
638 featurePermissionedDomains});
640 testCase([&](
Env& env,
648 vault.create({.owner = owner, .asset =
xrpIssue()});
651 auto tx = vault.set({
659 auto tx = vault.deposit(
662 .amount = asset(10)});
667 auto tx = vault.withdraw(
670 .amount = asset(10)});
675 auto tx = vault.clawback(
679 .amount = asset(10)});
684 auto tx = vault.del({
692 testCase([&](
Env& env,
699 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
702 auto tx = vault.clawback(
706 .amount = asset(10)});
711 testCase([&](
Env& env,
716 testcase(
"withdraw to bad destination");
718 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
721 auto tx = vault.withdraw(
724 .amount = asset(10)});
725 tx[jss::Destination] =
"0";
730 testCase([&](
Env& env,
735 testcase(
"create or set invalid data");
737 auto [tx1, keylet] = vault.create({.owner = owner, .asset = asset});
753 auto tx = vault.set({.owner = owner, .
id = keylet.
key});
759 auto tx = vault.set({.owner = owner, .
id = keylet.
key});
766 testCase([&](
Env& env,
773 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
776 auto tx = vault.set({.owner = owner, .
id = keylet.
key});
781 testCase([&](
Env& env,
786 testcase(
"create with invalid metadata");
788 auto [tx1, keylet] = vault.create({.owner = owner, .asset = asset});
792 tx[sfMPTokenMetadata] =
"";
805 testCase([&](
Env& env,
812 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
815 auto tx = vault.set({.owner = owner, .
id = keylet.
key});
821 testCase([&](
Env& env,
828 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
831 auto tx = vault.deposit(
839 auto tx = vault.deposit(
840 {.depositor = owner, .
id = keylet.
key, .amount = asset(0)});
845 testCase([&](
Env& env,
850 testcase(
"invalid set immutable flag");
852 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
855 auto tx = vault.set({.owner = owner, .
id = keylet.
key});
861 testCase([&](
Env& env,
866 testcase(
"invalid withdraw amount");
868 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
871 auto tx = vault.withdraw(
879 auto tx = vault.withdraw(
880 {.depositor = owner, .
id = keylet.
key, .amount = asset(0)});
885 testCase([&](
Env& env,
892 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
895 auto tx = vault.clawback(
899 .amount = asset(50)});
904 auto tx = vault.clawback(
913 testCase([&](
Env& env,
920 auto [tx1, keylet] = vault.create({.owner = owner, .asset = asset});
924 tx[sfWithdrawalPolicy] = 0;
943 tx[sfDomainID] =
"0";
953 using namespace test::jtx;
961 Vault& vault)> test) {
965 Account depositor{
"depositor"};
966 env.
fund(
XRP(1000), issuer, owner, depositor);
971 test(env, issuer, owner, depositor, asset, vault);
983 tx[sfAssetsMaximum] = asset(0).number();
995 auto tx = vault.deposit(
996 {.depositor = depositor,
998 .amount = asset(10)});
1009 testcase(
"nothing to withdraw from");
1010 auto tx = vault.withdraw(
1011 {.depositor = depositor,
1013 .amount = asset(10)});
1036 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1048 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1049 tx[sfWithdrawalPolicy] = 1;
1050 testcase(
"explicitly select withdrawal policy");
1061 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1073 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1077 env(
pay(owner, issuer,
XRP(775)));
1089 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1100 using namespace test::jtx;
1103 testcase(
"IOU fail create frozen");
1108 env.fund(
XRP(1000), issuer, owner);
1114 Asset asset = issuer[
"IOU"];
1116 vault.create({.owner = owner, .asset = asset});
1123 testcase(
"IOU fail create no ripling");
1128 env.fund(
XRP(1000), issuer, owner);
1134 Asset asset = issuer[
"IOU"];
1136 vault.create({.owner = owner, .asset = asset});
1147 env.fund(
XRP(1000), owner);
1151 Asset asset = issuer[
"IOU"];
1154 vault.create({.owner = owner, .asset = asset});
1162 testcase(
"IOU fail create vault for AMM LPToken");
1167 IOU const USD = gw[
"USD"];
1169 auto const [asset1, asset2] =
1174 auto const defXRP =
XRP(30000);
1177 return a +
XRP(1000);
1184 auto const toFund1 = tofund(asset1);
1185 auto const toFund2 = tofund(asset2);
1186 BEAST_EXPECT(asset1 <= toFund1 && asset2 <= toFund2);
1188 if (!asset1.native() && !asset2.native())
1189 fund(env, gw, {alice, carol}, {toFund1, toFund2}, Fund::All);
1190 else if (asset1.native())
1191 fund(env, gw, {alice, carol}, toFund1, {toFund2}, Fund::All);
1192 else if (asset2.native())
1193 fund(env, gw, {alice, carol}, toFund2, {toFund1}, Fund::All);
1196 env, alice, asset1, asset2,
CreateArg{.
log =
false, .tfee = 0});
1199 env.fund(
XRP(1000000), owner);
1203 vault.create({.owner = owner, .asset = ammAlice.lptIssue()});
1212 using namespace test::jtx;
1216 Account depositor{
"depositor"};
1217 env.fund(
XRP(1000), issuer, owner, depositor);
1225 Asset asset = mptt.issuanceID();
1226 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1233 using namespace test::jtx;
1237 Account depositor{
"depositor"};
1238 env.fund(
XRP(1000), issuer, owner, depositor);
1243 env.trust(asset(1000), owner);
1244 env(
pay(issuer, owner, asset(100)));
1245 env.trust(asset(1000), depositor);
1246 env(
pay(issuer, depositor, asset(100)));
1249 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1255 testcase(
"nontransferable deposits");
1256 auto tx1 = vault.deposit(
1257 {.depositor = depositor,
1259 .amount = asset(40)});
1262 auto tx2 = vault.deposit(
1263 {.depositor = owner, .id = keylet.
key, .amount = asset(60)});
1268 auto const vaultAccount =
1270 auto jvVault = env.rpc(
"vault_info",
strHex(key));
1273 jvVault[jss::result][jss::vault][sfAssetsTotal] ==
"100");
1275 jvVault[jss::result][jss::vault][jss::shares]
1276 [sfOutstandingAmount] ==
"100");
1279 return parseBase58<AccountID>(
1280 jvVault[jss::result][jss::vault][jss::Account]
1285 auto const MptID =
makeMptID(1, vaultAccount);
1286 Asset shares = MptID;
1289 testcase(
"nontransferable shares cannot be moved");
1295 testcase(
"nontransferable shares can be used to withdraw");
1296 auto tx1 = vault.withdraw(
1297 {.depositor = depositor,
1299 .amount = asset(20)});
1302 auto tx2 = vault.withdraw(
1303 {.depositor = owner, .id = keylet.
key, .amount = asset(30)});
1309 testcase(
"nontransferable shares balance check");
1310 auto jvVault = env.rpc(
"vault_info",
strHex(keylet.
key));
1312 jvVault[jss::result][jss::vault][sfAssetsTotal] ==
"50");
1314 jvVault[jss::result][jss::vault][jss::shares]
1315 [sfOutstandingAmount] ==
"50");
1319 testcase(
"nontransferable shares withdraw rest");
1320 auto tx1 = vault.withdraw(
1321 {.depositor = depositor,
1323 .amount = asset(20)});
1326 auto tx2 = vault.withdraw(
1327 {.depositor = owner, .id = keylet.
key, .amount = asset(30)});
1333 testcase(
"nontransferable shares delete empty vault");
1334 auto tx = vault.del({.owner = owner, .id = keylet.
key});
1336 BEAST_EXPECT(!env.le(keylet));
1343 using namespace test::jtx;
1347 bool enableClawback =
true;
1350 auto testCase = [
this](
1359 CaseArgs args = {}) {
1363 Account depositor{
"depositor"};
1364 env.
fund(
XRP(1000), issuer, owner, depositor);
1376 mptt.
authorize({.account = issuer, .holder = owner});
1378 mptt.
authorize({.account = issuer, .holder = depositor});
1379 env(
pay(issuer, depositor, asset(1000)));
1382 test(env, issuer, owner, depositor, asset, vault, mptt);
1393 testcase(
"MPT nothing to clawback from");
1394 auto tx = vault.clawback(
1397 .holder = depositor,
1398 .amount = asset(10)});
1410 testcase(
"MPT global lock blocks create");
1412 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1424 testcase(
"MPT global lock blocks deposit");
1425 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1433 {.depositor = depositor,
1435 .amount = asset(100)});
1440 tx = vault.del({.owner = owner, .
id = keylet.
key});
1452 testcase(
"MPT global lock blocks withdrawal");
1453 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1457 {.depositor = depositor,
1459 .amount = asset(100)});
1465 auto v = env.
le(keylet);
1467 MPTID share = (*v)[sfShareMPTID];
1469 BEAST_EXPECT(issuance);
1470 Number outstandingShares = issuance->at(sfOutstandingAmount);
1471 BEAST_EXPECT(outstandingShares == 100);
1476 tx = vault.withdraw(
1477 {.depositor = depositor,
1479 .amount = asset(100)});
1482 tx[sfDestination] = issuer.
human();
1486 tx = vault.clawback(
1489 .holder = depositor,
1490 .amount = asset(0)});
1495 tx = vault.del({.owner = owner, .
id = keylet.
key});
1507 testcase(
"MPT only issuer can clawback");
1509 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1514 {.depositor = depositor,
1516 .amount = asset(100)});
1521 auto tx = vault.clawback(
1522 {.issuer = owner, .
id = keylet.
key, .holder = depositor});
1537 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1542 {.depositor = depositor,
1544 .amount = asset(1000)});
1549 auto tx = vault.clawback(
1552 .holder = depositor,
1553 .amount = asset(0)});
1562 vault.create({.owner = depositor, .asset = asset});
1567 auto tx = vault.deposit(
1568 {.depositor = depositor,
1570 .amount = asset(10)});
1575 auto tx = vault.withdraw(
1576 {.depositor = depositor,
1578 .amount = asset(10)});
1583 auto tx = vault.clawback(
1586 .holder = depositor,
1587 .amount = asset(0)});
1591 env(vault.del({.owner = owner, .id = keylet.key}));
1606 vault.create({.owner = owner, .asset = asset});
1611 {.depositor = depositor,
1613 .amount = asset(1000)});
1618 auto tx = vault.clawback(
1621 .holder = depositor,
1622 .amount = asset(0)});
1626 {.enableClawback =
false});
1637 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1641 {.depositor = depositor,
1643 .amount = asset(1000)});
1649 .holder = depositor,
1654 auto tx = vault.withdraw(
1655 {.depositor = depositor,
1657 .amount = asset(100)});
1661 tx[sfDestination] = issuer.
human();
1663 tx[sfDestination] = owner.
human();
1670 auto tx = vault.deposit(
1671 {.depositor = depositor,
1673 .amount = asset(100)});
1678 tx = vault.clawback(
1681 .holder = depositor,
1682 .amount = asset(800)});
1685 env(vault.del({.owner = owner, .id = keylet.key}));
1696 testcase(
"MPT lock of vault pseudo-account");
1697 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1701 auto const vaultAccount =
1702 [&env, keylet = keylet,
this]() ->
AccountID {
1703 auto const vault = env.
le(keylet);
1704 BEAST_EXPECT(vault !=
nullptr);
1705 return vault->at(sfAccount);
1709 {.depositor = depositor,
1711 .amount = asset(100)});
1717 jv[jss::Account] = issuer.
human();
1718 jv[sfMPTokenIssuanceID] =
1720 jv[jss::Holder] =
toBase58(vaultAccount);
1721 jv[jss::TransactionType] = jss::MPTokenIssuanceSet;
1729 {.depositor = depositor,
1731 .amount = asset(100)});
1734 tx = vault.withdraw(
1735 {.depositor = depositor,
1737 .amount = asset(100)});
1741 tx = vault.clawback(
1744 .holder = depositor,
1745 .amount = asset(100)});
1749 tx = vault.del({.owner = owner, .
id = keylet.
key});
1759 env.
fund(
XRP(1000000), owner, issuer);
1768 mptt.
authorize({.account = issuer, .holder = owner});
1770 env(
pay(issuer, owner, asset(100)));
1771 auto [tx1, k1] = vault.create({.owner = owner, .asset = asset});
1775 auto const shares = [&env, keylet = k1,
this]() ->
Asset {
1776 auto const vault = env.
le(keylet);
1777 BEAST_EXPECT(vault !=
nullptr);
1778 return MPTIssue(vault->at(sfShareMPTID));
1781 auto [tx2, k2] = vault.create({.owner = owner, .asset = shares});
1806 Account const issuer{
"issuer"};
1807 Account const charlie{
"charlie"};
1809 env.
fund(
XRP(1000), issuer, owner, charlie);
1814 env.
trust(asset(1000), owner);
1815 env(
pay(issuer, owner, asset(200)));
1816 env(
rate(issuer, 1.25));
1819 auto const [tx, keylet] =
1820 vault.create({.owner = owner, .asset = asset});
1824 auto const vaultAccount =
1826 return env.
le(keylet)->at(sfAccount);
1829 return env.
le(keylet)->at(sfShareMPTID);
1831 auto const vaultBalance =
1832 [&env, &vaultAccount, issue = asset.
raw().
get<
Issue>()](
1834 auto const account = vaultAccount(keylet);
1840 auto amount = sle->getFieldAmount(sfBalance);
1841 amount.setIssuer(issue.account);
1842 if (account > issue.account)
1844 return {amount, env.
lookup(issue.account).
name()};
1868 testcase(
"IOU cannot use different asset");
1871 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1877 auto tx = [&, account = vaultAccount(keylet)]() {
1879 jv[jss::Account] = issuer.
human();
1881 auto& ja = jv[jss::LimitAmount] =
1883 ja[jss::issuer] =
toBase58(account);
1885 jv[jss::TransactionType] = jss::TrustSet;
1894 auto tx = vault.deposit(
1895 {.depositor = issuer, .
id = keylet.
key, .amount = foo(20)});
1901 auto tx = vault.withdraw(
1902 {.depositor = issuer, .
id = keylet.
key, .amount = foo(20)});
1907 env(vault.del({.owner = owner, .id = keylet.key}));
1921 testcase(
"IOU frozen trust line to vault account");
1923 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
1928 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
1931 Asset const share =
Asset(issuanceId(keylet));
1934 auto trustSet = [&, account = vaultAccount(keylet)]() {
1936 jv[jss::Account] = issuer.
human();
1938 auto& ja = jv[jss::LimitAmount] =
1940 ja[jss::issuer] =
toBase58(account);
1942 jv[jss::TransactionType] = jss::TrustSet;
1954 auto tx = vault.deposit(
1955 {.depositor = owner,
1957 .amount = asset(80)});
1962 auto tx = vault.withdraw(
1963 {.depositor = owner,
1965 .amount = asset(100)});
1969 tx[sfDestination] = charlie.
human();
1976 auto tx = vault.clawback(
1980 .amount = asset(50)});
1991 {.depositor = owner, .id = keylet.key, .amount = share(50)}));
1993 env(vault.del({.owner = owner, .id = keylet.key}));
2006 auto vaultBalance) {
2007 testcase(
"IOU transfer fees not applied");
2009 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2014 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2018 Asset const share =
Asset(issuanceId(keylet));
2021 BEAST_EXPECT(env.
balance(owner, issue) == asset(100));
2022 BEAST_EXPECT(vaultBalance(keylet) == asset(100));
2025 auto tx = vault.clawback(
2029 .amount = asset(50)});
2035 BEAST_EXPECT(env.
balance(owner, issue) == asset(100));
2036 BEAST_EXPECT(vaultBalance(keylet) == asset(50));
2039 {.depositor = owner, .id = keylet.key, .amount = share(20)}));
2042 BEAST_EXPECT(env.
balance(owner, issue) == asset(120));
2043 BEAST_EXPECT(vaultBalance(keylet) == asset(30));
2046 auto tx = vault.withdraw(
2047 {.depositor = owner,
2049 .amount = share(30)});
2050 tx[sfDestination] = charlie.
human();
2055 BEAST_EXPECT(env.
balance(owner, issue) == asset(120));
2056 BEAST_EXPECT(env.
balance(charlie, issue) == asset(30));
2057 BEAST_EXPECT(vaultBalance(keylet) == asset(0));
2059 env(vault.del({.owner = owner, .id = keylet.key}));
2072 testcase(
"IOU frozen trust line to depositor");
2074 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2079 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2084 auto tx = vault.withdraw(
2085 {.depositor = owner,
2087 .amount = asset(10)});
2088 tx[sfDestination] = charlie.
human();
2091 env(withdrawToCharlie);
2098 auto const withdraw = vault.withdraw(
2099 {.depositor = owner, .
id = keylet.
key, .amount = asset(10)});
2108 auto tx = vault.deposit(
2109 {.depositor = owner,
2111 .amount = asset(10)});
2117 auto tx = vault.clawback(
2121 .amount = asset(0)});
2126 env(vault.del({.owner = owner, .id = keylet.key}));
2139 testcase(
"IOU frozen trust line to 3rd party");
2141 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2146 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2151 auto tx = vault.withdraw(
2152 {.depositor = owner,
2154 .amount = asset(10)});
2155 tx[sfDestination] = charlie.
human();
2158 env(withdrawToCharlie);
2165 auto const withdraw = vault.withdraw(
2166 {.depositor = owner, .
id = keylet.
key, .amount = asset(10)});
2178 .amount = asset(0)}));
2181 env(vault.del({.owner = owner, .id = keylet.key}));
2196 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2201 {.depositor = owner, .id = keylet.key, .amount = asset(100)}));
2209 auto tx = vault.withdraw(
2210 {.depositor = owner,
2212 .amount = asset(10)});
2216 tx[sfDestination] = charlie.
human();
2222 {.depositor = owner,
2224 .amount = asset(10)});
2234 .amount = asset(0)}));
2237 env(vault.del({.owner = owner, .id = keylet.key}));
2250 Account depositor{
"depositor"};
2253 Account credIssuer1{
"credIssuer1"};
2254 Account credIssuer2{
"credIssuer2"};
2272 env.trust(asset(1000), owner);
2273 env(
pay(issuer, owner, asset(500)));
2274 env.trust(asset(1000), depositor);
2275 env(
pay(issuer, depositor, asset(500)));
2278 auto [tx, keylet] = vault.create(
2282 BEAST_EXPECT(env.le(keylet));
2285 testcase(
"private vault owner can deposit");
2286 auto tx = vault.deposit(
2287 {.depositor = owner, .id = keylet.
key, .amount = asset(50)});
2292 testcase(
"private vault depositor not authorized yet");
2293 auto tx = vault.deposit(
2294 {.depositor = depositor,
2296 .amount = asset(50)});
2301 testcase(
"private vault cannot set non-existing domain");
2302 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2308 testcase(
"private vault set domainId");
2312 {.issuer = credIssuer1, .credType = credType}};
2315 auto const domainId1 = [&]() {
2320 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2332 {.issuer = credIssuer1, .credType = credType},
2333 {.issuer = credIssuer2, .credType = credType}};
2336 auto const domainId = [&]() {
2341 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2349 testcase(
"private vault depositor still not authorized");
2350 auto tx = vault.deposit(
2351 {.depositor = depositor,
2353 .amount = asset(50)});
2358 auto const credKeylet =
2359 credentials::keylet(depositor, credIssuer1, credType);
2361 testcase(
"private vault depositor now authorized");
2362 env(credentials::create(depositor, credIssuer1, credType));
2363 env(credentials::accept(depositor, credIssuer1, credType));
2364 env(credentials::create(charlie, credIssuer1, credType));
2365 env(credentials::accept(charlie, credIssuer1, credType));
2367 auto credSle = env.le(credKeylet);
2368 BEAST_EXPECT(credSle !=
nullptr);
2370 auto tx = vault.deposit(
2371 {.depositor = depositor,
2373 .amount = asset(50)});
2378 {.depositor = charlie, .id = keylet.
key, .amount = asset(50)});
2384 testcase(
"private vault depositor lost authorization");
2385 env(credentials::deleteCred(
2386 credIssuer1, depositor, credIssuer1, credType));
2388 auto credSle = env.le(credKeylet);
2389 BEAST_EXPECT(credSle ==
nullptr);
2391 auto tx = vault.deposit(
2392 {.depositor = depositor,
2394 .amount = asset(50)});
2400 testcase(
"private vault depositor new authorization");
2401 env(credentials::create(depositor, credIssuer2, credType));
2402 env(credentials::accept(depositor, credIssuer2, credType));
2405 auto tx = vault.deposit(
2406 {.depositor = depositor,
2408 .amount = asset(50)});
2414 testcase(
"private vault reset domainId");
2415 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2416 tx[sfDomainID] =
"0";
2421 {.depositor = depositor,
2423 .amount = asset(50)});
2427 tx = vault.withdraw(
2428 {.depositor = depositor,
2430 .amount = asset(50)});
2433 tx = vault.clawback(
2436 .holder = depositor,
2437 .amount = asset(0)});
2440 tx = vault.clawback(
2444 .amount = asset(0)});
2462 Account depositor{
"depositor"};
2466 env.fund(
XRP(100000), owner, depositor, alice);
2470 auto [tx, keylet] = vault.create(
2475 auto const [vaultAccount, issuanceId] =
2477 auto const vault = env.le(keylet);
2478 BEAST_EXPECT(vault !=
nullptr);
2479 return {vault->at(sfAccount), vault->at(sfShareMPTID)};
2486 testcase(
"private XRP vault owner can deposit");
2487 auto tx = vault.deposit(
2488 {.depositor = owner, .id = keylet.
key, .amount = asset(50)});
2493 testcase(
"private XRP vault cannot pay shares to depositor yet");
2498 testcase(
"private XRP vault depositor not authorized yet");
2499 auto tx = vault.deposit(
2500 {.depositor = depositor,
2502 .amount = asset(50)});
2507 testcase(
"private XRP vault set DomainID");
2509 {.issuer = owner, .credType = credType}};
2512 auto const domainId = [&]() {
2517 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2523 auto const credKeylet = credentials::keylet(depositor, owner, credType);
2525 testcase(
"private XRP vault depositor now authorized");
2526 env(credentials::create(depositor, owner, credType));
2527 env(credentials::accept(depositor, owner, credType));
2530 BEAST_EXPECT(env.le(credKeylet));
2531 auto tx = vault.deposit(
2532 {.depositor = depositor,
2534 .amount = asset(50)});
2540 testcase(
"private XRP vault can pay shares to depositor");
2541 env(
pay(owner, depositor, shares(1)));
2545 testcase(
"private XRP vault cannot pay shares to 3rd party");
2547 jv[sfAccount] = alice.human();
2548 jv[sfTransactionType] = jss::MPTokenAuthorize;
2549 jv[sfMPTokenIssuanceID] =
to_string(issuanceId);
2560 using namespace test::jtx;
2562 testcase(
"failed pseudo-account allocation");
2566 env.fund(
XRP(1000), owner);
2568 auto const keylet =
keylet::vault(owner.id(), env.seq(owner));
2569 for (
int i = 0; i < 256; ++i)
2574 env(
pay(env.master.id(), accountId,
XRP(1000)),
2580 auto [tx, keylet1] =
2581 vault.create({.owner = owner, .asset =
xrpIssue()});
2582 BEAST_EXPECT(keylet.
key == keylet1.key);
2592 Account const issuer{
"issuer"};
2594 env.fund(
XRP(1000), issuer, owner);
2598 env.trust(asset(1000), owner);
2599 env(
pay(issuer, owner, asset(200)));
2602 auto const sequence = env.seq(owner);
2603 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2609 auto tx1 = vault.deposit(
2610 {.depositor = owner, .id = keylet.
key, .amount = asset(50)});
2613 auto tx2 = vault.set({.owner = owner, .id = keylet.
key});
2614 tx2[sfAssetsMaximum] = asset(1000).number();
2619 auto const sleVault = [&env, keylet = keylet,
this]() {
2620 auto const vault = env.le(keylet);
2621 BEAST_EXPECT(vault !=
nullptr);
2625 auto const check = [&, keylet = keylet, sle = sleVault,
this](
2628 BEAST_EXPECT(vault.isObject());
2630 constexpr auto checkString =
2632 return node.isMember(field.fieldName) &&
2633 node[field.fieldName].isString() &&
2634 node[field.fieldName] == v;
2636 constexpr auto checkObject =
2638 return node.isMember(field.fieldName) &&
2639 node[field.fieldName].isObject() &&
2640 node[field.fieldName] == v;
2642 constexpr auto checkInt =
2643 [](
auto& node,
SField const& field,
int v) ->
bool {
2644 return node.isMember(field.fieldName) &&
2645 ((node[field.fieldName].isInt() &&
2646 node[field.fieldName] ==
Json::Int(v)) ||
2647 (node[field.fieldName].isUInt() &&
2651 BEAST_EXPECT(vault[
"LedgerEntryType"].asString() ==
"Vault");
2652 BEAST_EXPECT(vault[jss::index].asString() ==
strHex(keylet.
key));
2653 BEAST_EXPECT(checkInt(vault, sfFlags, 0));
2657 checkString(vault, sfAccount,
toBase58(sle->at(sfAccount))));
2659 checkObject(vault, sfAsset,
to_json(sle->at(sfAsset))));
2660 BEAST_EXPECT(checkString(vault, sfAssetsAvailable,
"50"));
2661 BEAST_EXPECT(checkString(vault, sfAssetsMaximum,
"1000"));
2662 BEAST_EXPECT(checkString(vault, sfAssetsTotal,
"50"));
2663 BEAST_EXPECT(checkString(vault, sfLossUnrealized,
"0"));
2665 auto const strShareID =
strHex(sle->at(sfShareMPTID));
2666 BEAST_EXPECT(checkString(vault, sfShareMPTID, strShareID));
2667 BEAST_EXPECT(checkString(vault, sfOwner,
toBase58(owner.id())));
2668 BEAST_EXPECT(checkInt(vault, sfSequence, sequence));
2669 BEAST_EXPECT(checkInt(
2672 if (issuance.isObject())
2675 issuance[
"LedgerEntryType"].asString() ==
2678 issuance[jss::mpt_issuance_id].asString() == strShareID);
2679 BEAST_EXPECT(checkInt(issuance, sfSequence, 1));
2680 BEAST_EXPECT(checkInt(
2684 BEAST_EXPECT(checkString(issuance, sfOutstandingAmount,
"50"));
2689 testcase(
"RPC ledger_entry selected by key");
2691 jvParams[jss::ledger_index] = jss::validated;
2692 jvParams[jss::vault] =
strHex(keylet.
key);
2693 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2695 BEAST_EXPECT(!jvVault[jss::result].isMember(jss::error));
2696 BEAST_EXPECT(jvVault[jss::result].isMember(jss::node));
2697 check(jvVault[jss::result][jss::node]);
2701 testcase(
"RPC ledger_entry selected by owner and seq");
2703 jvParams[jss::ledger_index] = jss::validated;
2704 jvParams[jss::vault][jss::owner] = owner.human();
2705 jvParams[jss::vault][jss::seq] = sequence;
2706 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2708 BEAST_EXPECT(!jvVault[jss::result].isMember(jss::error));
2709 BEAST_EXPECT(jvVault[jss::result].isMember(jss::node));
2710 check(jvVault[jss::result][jss::node]);
2714 testcase(
"RPC ledger_entry cannot find vault by key");
2716 jvParams[jss::ledger_index] = jss::validated;
2718 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2720 jvVault[jss::result][jss::error].asString() ==
"entryNotFound");
2724 testcase(
"RPC ledger_entry cannot find vault by owner and seq");
2726 jvParams[jss::ledger_index] = jss::validated;
2727 jvParams[jss::vault][jss::owner] = issuer.human();
2728 jvParams[jss::vault][jss::seq] = 1'000'000;
2729 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2731 jvVault[jss::result][jss::error].asString() ==
"entryNotFound");
2735 testcase(
"RPC ledger_entry malformed key");
2737 jvParams[jss::ledger_index] = jss::validated;
2738 jvParams[jss::vault] = 42;
2739 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2741 jvVault[jss::result][jss::error].asString() ==
2742 "malformedRequest");
2746 testcase(
"RPC ledger_entry malformed owner");
2748 jvParams[jss::ledger_index] = jss::validated;
2749 jvParams[jss::vault][jss::owner] = 42;
2750 jvParams[jss::vault][jss::seq] = sequence;
2751 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2753 jvVault[jss::result][jss::error].asString() ==
2758 testcase(
"RPC ledger_entry malformed seq");
2760 jvParams[jss::ledger_index] = jss::validated;
2761 jvParams[jss::vault][jss::owner] = issuer.human();
2762 jvParams[jss::vault][jss::seq] =
"foo";
2763 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2765 jvVault[jss::result][jss::error].asString() ==
2766 "malformedRequest");
2770 testcase(
"RPC ledger_entry zero seq");
2772 jvParams[jss::ledger_index] = jss::validated;
2773 jvParams[jss::vault][jss::owner] = issuer.human();
2774 jvParams[jss::vault][jss::seq] = 0;
2775 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2777 jvVault[jss::result][jss::error].asString() ==
2778 "malformedRequest");
2782 testcase(
"RPC ledger_entry negative seq");
2784 jvParams[jss::ledger_index] = jss::validated;
2785 jvParams[jss::vault][jss::owner] = issuer.human();
2786 jvParams[jss::vault][jss::seq] = -1;
2787 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2789 jvVault[jss::result][jss::error].asString() ==
2790 "malformedRequest");
2794 testcase(
"RPC ledger_entry oversized seq");
2796 jvParams[jss::ledger_index] = jss::validated;
2797 jvParams[jss::vault][jss::owner] = issuer.human();
2798 jvParams[jss::vault][jss::seq] = 1e20;
2799 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2801 jvVault[jss::result][jss::error].asString() ==
2802 "malformedRequest");
2806 testcase(
"RPC ledger_entry bool seq");
2808 jvParams[jss::ledger_index] = jss::validated;
2809 jvParams[jss::vault][jss::owner] = issuer.human();
2810 jvParams[jss::vault][jss::seq] =
true;
2811 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2813 jvVault[jss::result][jss::error].asString() ==
2814 "malformedRequest");
2821 jvParams[jss::account] = owner.human();
2822 jvParams[jss::type] = jss::vault;
2824 "json",
"account_objects",
to_string(jvParams))[jss::result];
2826 BEAST_EXPECT(jv[jss::account_objects].size() == 1);
2827 check(jv[jss::account_objects][0u]);
2834 jvParams[jss::ledger_index] = jss::validated;
2835 jvParams[jss::binary] =
false;
2836 jvParams[jss::type] = jss::vault;
2838 env.rpc(
"json",
"ledger_data",
to_string(jvParams));
2839 BEAST_EXPECT(jv[jss::result][jss::state].size() == 1);
2840 check(jv[jss::result][jss::state][0u]);
2844 testcase(
"RPC vault_info command line");
2846 env.rpc(
"vault_info",
strHex(keylet.
key),
"validated");
2848 BEAST_EXPECT(!jv[jss::result].isMember(jss::error));
2849 BEAST_EXPECT(jv[jss::result].isMember(jss::vault));
2851 jv[jss::result][jss::vault],
2852 jv[jss::result][jss::vault][jss::shares]);
2858 jvParams[jss::ledger_index] = jss::validated;
2859 jvParams[jss::vault_id] =
strHex(keylet.
key);
2860 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2862 BEAST_EXPECT(!jv[jss::result].isMember(jss::error));
2863 BEAST_EXPECT(jv[jss::result].isMember(jss::vault));
2865 jv[jss::result][jss::vault],
2866 jv[jss::result][jss::vault][jss::shares]);
2870 testcase(
"RPC vault_info invalid vault_id");
2872 jvParams[jss::ledger_index] = jss::validated;
2873 jvParams[jss::vault_id] =
"foobar";
2874 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2876 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2880 testcase(
"RPC vault_info json invalid index");
2882 jvParams[jss::ledger_index] = jss::validated;
2883 jvParams[jss::vault_id] = 0;
2884 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2886 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2890 testcase(
"RPC vault_info json by owner and sequence");
2892 jvParams[jss::ledger_index] = jss::validated;
2893 jvParams[jss::owner] = owner.human();
2894 jvParams[jss::seq] = sequence;
2895 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2897 BEAST_EXPECT(!jv[jss::result].isMember(jss::error));
2898 BEAST_EXPECT(jv[jss::result].isMember(jss::vault));
2900 jv[jss::result][jss::vault],
2901 jv[jss::result][jss::vault][jss::shares]);
2905 testcase(
"RPC vault_info json malformed sequence");
2907 jvParams[jss::ledger_index] = jss::validated;
2908 jvParams[jss::owner] = owner.human();
2909 jvParams[jss::seq] =
"foobar";
2910 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2912 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2916 testcase(
"RPC vault_info json invalid sequence");
2918 jvParams[jss::ledger_index] = jss::validated;
2919 jvParams[jss::owner] = owner.human();
2920 jvParams[jss::seq] = 0;
2921 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2923 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2927 testcase(
"RPC vault_info json negative sequence");
2929 jvParams[jss::ledger_index] = jss::validated;
2930 jvParams[jss::owner] = owner.human();
2931 jvParams[jss::seq] = -1;
2932 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2934 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2938 testcase(
"RPC vault_info json oversized sequence");
2940 jvParams[jss::ledger_index] = jss::validated;
2941 jvParams[jss::owner] = owner.human();
2942 jvParams[jss::seq] = 1e20;
2943 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2945 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2949 testcase(
"RPC vault_info json bool sequence");
2951 jvParams[jss::ledger_index] = jss::validated;
2952 jvParams[jss::owner] = owner.human();
2953 jvParams[jss::seq] =
true;
2954 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2956 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2960 testcase(
"RPC vault_info json malformed owner");
2962 jvParams[jss::ledger_index] = jss::validated;
2963 jvParams[jss::owner] =
"foobar";
2964 jvParams[jss::seq] = sequence;
2965 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2967 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2971 testcase(
"RPC vault_info json invalid combination only owner");
2973 jvParams[jss::ledger_index] = jss::validated;
2974 jvParams[jss::owner] = owner.human();
2975 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2977 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2981 testcase(
"RPC vault_info json invalid combination only seq");
2983 jvParams[jss::ledger_index] = jss::validated;
2984 jvParams[jss::seq] = sequence;
2985 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2987 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2991 testcase(
"RPC vault_info json invalid combination seq vault_id");
2993 jvParams[jss::ledger_index] = jss::validated;
2994 jvParams[jss::vault_id] =
strHex(keylet.
key);
2995 jvParams[jss::seq] = sequence;
2996 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2998 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3002 testcase(
"RPC vault_info json invalid combination owner vault_id");
3004 jvParams[jss::ledger_index] = jss::validated;
3005 jvParams[jss::vault_id] =
strHex(keylet.
key);
3006 jvParams[jss::owner] = owner.human();
3007 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3009 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3014 "RPC vault_info json invalid combination owner seq "
3017 jvParams[jss::ledger_index] = jss::validated;
3018 jvParams[jss::vault_id] =
strHex(keylet.
key);
3019 jvParams[jss::seq] = sequence;
3020 jvParams[jss::owner] = owner.human();
3021 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3023 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3027 testcase(
"RPC vault_info json no input");
3029 jvParams[jss::ledger_index] = jss::validated;
3030 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3032 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3036 testcase(
"RPC vault_info command line invalid index");
3037 Json::Value jv = env.rpc(
"vault_info",
"foobar",
"validated");
3038 BEAST_EXPECT(jv[jss::error].asString() ==
"invalidParams");
3042 testcase(
"RPC vault_info command line invalid index");
3043 Json::Value jv = env.rpc(
"vault_info",
"0",
"validated");
3045 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3049 testcase(
"RPC vault_info command line invalid index");
3053 jv[jss::result][jss::error].asString() ==
"entryNotFound");
3057 testcase(
"RPC vault_info command line invalid ledger");
3060 jv[jss::result][jss::error].asString() ==
"lgrNotFound");
testcase_t testcase
Memberspace for declaring test cases.
constexpr TIss const & get() const
A currency issued by an account.
constexpr MPTID const & getMptID() const
Issue const & issue() const
void testFailedPseudoAccount()
void testNonTransferableShares()
void testWithDomainCheck()
static auto constexpr negativeAmount
void run() override
Runs the suite.
void testWithDomainCheckXRP()
Integers of any length that is a multiple of 32-bits.
Convenience class to test AMM functionality.
Immutable cryptographic account descriptor.
AccountID id() const
Returns the Account ID.
std::string const & name() const
Return the name.
std::string const & human() const
Returns the human readable public key.
A transaction testing environment.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
Account const & lookup(AccountID const &id) const
Returns the Account given the AccountID.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
Converts to IOU Issue or STAmount.
void authorize(MPTAuthorize const &arg=MPTAuthorize{})
void set(MPTSet const &set={})
MPTID const & issuanceID() const
void create(MPTCreate const &arg=MPTCreate{})
void destroy(MPTDestroy const &arg=MPTDestroy{})
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.
Keylet line(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet const & skip() noexcept
The index of the "short" skip list.
Json::Value setTx(AccountID const &account, Credentials const &credentials, std::optional< uint256 > domain)
uint256 getNewDomain(std::shared_ptr< STObject const > const &meta)
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
static autofill_t const autofill
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
void fund(jtx::Env &env, jtx::Account const &gw, std::vector< jtx::Account > const &accounts, std::vector< STAmount > const &amts, Fund how)
Json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
static MPTInit const mptInitNoFund
XRP_t const XRP
Converts to XRP Issue or STAmount.
FeatureBitset supported_amendments()
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
constexpr std::uint32_t asfGlobalFreeze
constexpr std::uint32_t asfDepositAuth
constexpr std::uint32_t const tfMPTCanTransfer
constexpr std::uint32_t asfRequireDest
base_uint< 192 > MPTID
MPTID is a 192-bit value representing MPT Issuance ID, which is a concatenation of a 32-bit sequence ...
constexpr std::uint32_t const tfVaultPrivate
Json::Value to_json(Asset const &asset)
std::string strHex(FwdIt begin, FwdIt end)
constexpr std::uint32_t const tfMPTUnauthorize
constexpr std::uint32_t tfSetfAuth
constexpr std::uint32_t asfDefaultRipple
constexpr std::uint32_t tfClearFreeze
@ tecINSUFFICIENT_RESERVE
constexpr std::uint32_t const tfMPTLock
constexpr std::uint32_t const tfVaultShareNonTransferable
AccountID pseudoAccountAddress(ReadView const &view, uint256 const &pseudoOwnerKey)
constexpr std::uint32_t tfClearDeepFreeze
std::string to_string(base_uint< Bits, Tag > const &a)
std::uint8_t constexpr vaultStrategyFirstComeFirstServe
Vault withdrawal policies.
constexpr std::uint32_t asfAllowTrustLineClawback
constexpr std::uint32_t asfRequireAuth
MPTID makeMptID(std::uint32_t sequence, AccountID const &account)
constexpr std::uint32_t const tfMPTRequireAuth
constexpr std::uint32_t tfSetFreeze
constexpr std::uint32_t const tfMPTCanLock
constexpr std::uint32_t const tfMPTCanClawback
A pair of SHAMap key and LedgerEntryType.
Represents an XRP or IOU quantity This customizes the string conversion and supports XRP conversions ...
Asset const & raw() const
Set the sequence number on a JTx.