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)));
2276 env.trust(asset(1000), charlie);
2277 env(
pay(issuer, charlie, asset(5)));
2280 auto [tx, keylet] = vault.create(
2284 BEAST_EXPECT(env.le(keylet));
2287 testcase(
"private vault owner can deposit");
2288 auto tx = vault.deposit(
2289 {.depositor = owner, .id = keylet.
key, .amount = asset(50)});
2294 testcase(
"private vault depositor not authorized yet");
2295 auto tx = vault.deposit(
2296 {.depositor = depositor,
2298 .amount = asset(50)});
2303 testcase(
"private vault cannot set non-existing domain");
2304 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2310 testcase(
"private vault set domainId");
2314 {.issuer = credIssuer1, .credType = credType}};
2317 auto const domainId1 = [&]() {
2322 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2334 {.issuer = credIssuer1, .credType = credType},
2335 {.issuer = credIssuer2, .credType = credType}};
2338 auto const domainId = [&]() {
2343 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2351 testcase(
"private vault depositor still not authorized");
2352 auto tx = vault.deposit(
2353 {.depositor = depositor,
2355 .amount = asset(50)});
2360 auto const credKeylet =
2361 credentials::keylet(depositor, credIssuer1, credType);
2363 testcase(
"private vault depositor now authorized");
2364 env(credentials::create(depositor, credIssuer1, credType));
2365 env(credentials::accept(depositor, credIssuer1, credType));
2366 env(credentials::create(charlie, credIssuer1, credType));
2369 auto credSle = env.le(credKeylet);
2370 BEAST_EXPECT(credSle !=
nullptr);
2372 auto tx = vault.deposit(
2373 {.depositor = depositor,
2375 .amount = asset(50)});
2380 {.depositor = charlie, .id = keylet.
key, .amount = asset(50)});
2386 testcase(
"private vault depositor lost authorization");
2387 env(credentials::deleteCred(
2388 credIssuer1, depositor, credIssuer1, credType));
2389 env(credentials::deleteCred(
2390 credIssuer1, charlie, credIssuer1, credType));
2392 auto credSle = env.le(credKeylet);
2393 BEAST_EXPECT(credSle ==
nullptr);
2395 auto tx = vault.deposit(
2396 {.depositor = depositor,
2398 .amount = asset(50)});
2403 auto const shares = [&env, keylet = keylet,
this]() ->
Asset {
2404 auto const vault = env.le(keylet);
2405 BEAST_EXPECT(vault !=
nullptr);
2406 return MPTIssue(vault->at(sfShareMPTID));
2410 testcase(
"private vault expired authorization");
2411 uint32_t
const closeTime = env.current()
2413 .parentCloseTime.time_since_epoch()
2417 credentials::create(depositor, credIssuer2, credType);
2418 tx0[sfExpiration] = closeTime + 20;
2420 tx0 = credentials::create(charlie, credIssuer2, credType);
2421 tx0[sfExpiration] = closeTime + 20;
2425 env(credentials::accept(depositor, credIssuer2, credType));
2426 env(credentials::accept(charlie, credIssuer2, credType));
2431 auto tx1 = vault.deposit(
2432 {.depositor = depositor,
2434 .amount = asset(50)});
2440 BEAST_EXPECT(env.le(tokenKeylet) !=
nullptr);
2449 auto const credsKeylet =
2450 credentials::keylet(depositor, credIssuer2, credType);
2451 BEAST_EXPECT(env.le(credsKeylet) !=
nullptr);
2453 auto tx2 = vault.deposit(
2454 {.depositor = depositor,
2456 .amount = asset(1)});
2460 BEAST_EXPECT(env.le(credsKeylet) ==
nullptr);
2464 auto const credsKeylet =
2465 credentials::keylet(charlie, credIssuer2, credType);
2466 BEAST_EXPECT(env.le(credsKeylet) !=
nullptr);
2469 BEAST_EXPECT(env.le(tokenKeylet) ==
nullptr);
2471 auto tx3 = vault.deposit(
2472 {.depositor = charlie,
2474 .amount = asset(2)});
2478 BEAST_EXPECT(env.le(credsKeylet) ==
nullptr);
2479 BEAST_EXPECT(env.le(tokenKeylet) ==
nullptr);
2484 testcase(
"private vault reset domainId");
2485 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2486 tx[sfDomainID] =
"0";
2491 {.depositor = depositor,
2493 .amount = asset(50)});
2497 tx = vault.withdraw(
2498 {.depositor = depositor,
2500 .amount = asset(50)});
2503 tx = vault.clawback(
2506 .holder = depositor,
2507 .amount = asset(0)});
2510 tx = vault.clawback(
2514 .amount = asset(0)});
2532 Account depositor{
"depositor"};
2536 env.fund(
XRP(100000), owner, depositor, alice);
2540 auto [tx, keylet] = vault.create(
2545 auto const [vaultAccount, issuanceId] =
2547 auto const vault = env.le(keylet);
2548 BEAST_EXPECT(vault !=
nullptr);
2549 return {vault->at(sfAccount), vault->at(sfShareMPTID)};
2556 testcase(
"private XRP vault owner can deposit");
2557 auto tx = vault.deposit(
2558 {.depositor = owner, .id = keylet.
key, .amount = asset(50)});
2563 testcase(
"private XRP vault cannot pay shares to depositor yet");
2568 testcase(
"private XRP vault depositor not authorized yet");
2569 auto tx = vault.deposit(
2570 {.depositor = depositor,
2572 .amount = asset(50)});
2577 testcase(
"private XRP vault set DomainID");
2579 {.issuer = owner, .credType = credType}};
2582 auto const domainId = [&]() {
2587 auto tx = vault.set({.owner = owner, .id = keylet.
key});
2593 auto const credKeylet = credentials::keylet(depositor, owner, credType);
2595 testcase(
"private XRP vault depositor now authorized");
2596 env(credentials::create(depositor, owner, credType));
2597 env(credentials::accept(depositor, owner, credType));
2600 BEAST_EXPECT(env.le(credKeylet));
2601 auto tx = vault.deposit(
2602 {.depositor = depositor,
2604 .amount = asset(50)});
2610 testcase(
"private XRP vault can pay shares to depositor");
2611 env(
pay(owner, depositor, shares(1)));
2615 testcase(
"private XRP vault cannot pay shares to 3rd party");
2617 jv[sfAccount] = alice.human();
2618 jv[sfTransactionType] = jss::MPTokenAuthorize;
2619 jv[sfMPTokenIssuanceID] =
to_string(issuanceId);
2630 using namespace test::jtx;
2632 testcase(
"failed pseudo-account allocation");
2636 env.fund(
XRP(1000), owner);
2638 auto const keylet =
keylet::vault(owner.id(), env.seq(owner));
2639 for (
int i = 0; i < 256; ++i)
2644 env(
pay(env.master.id(), accountId,
XRP(1000)),
2650 auto [tx, keylet1] =
2651 vault.create({.owner = owner, .asset =
xrpIssue()});
2652 BEAST_EXPECT(keylet.
key == keylet1.key);
2662 Account const issuer{
"issuer"};
2664 env.fund(
XRP(1000), issuer, owner);
2668 env.trust(asset(1000), owner);
2669 env(
pay(issuer, owner, asset(200)));
2672 auto const sequence = env.seq(owner);
2673 auto [tx, keylet] = vault.create({.owner = owner, .asset = asset});
2679 auto tx1 = vault.deposit(
2680 {.depositor = owner, .id = keylet.
key, .amount = asset(50)});
2683 auto tx2 = vault.set({.owner = owner, .id = keylet.
key});
2684 tx2[sfAssetsMaximum] = asset(1000).number();
2689 auto const sleVault = [&env, keylet = keylet,
this]() {
2690 auto const vault = env.le(keylet);
2691 BEAST_EXPECT(vault !=
nullptr);
2695 auto const check = [&, keylet = keylet, sle = sleVault,
this](
2698 BEAST_EXPECT(vault.isObject());
2700 constexpr auto checkString =
2702 return node.isMember(field.fieldName) &&
2703 node[field.fieldName].isString() &&
2704 node[field.fieldName] == v;
2706 constexpr auto checkObject =
2708 return node.isMember(field.fieldName) &&
2709 node[field.fieldName].isObject() &&
2710 node[field.fieldName] == v;
2712 constexpr auto checkInt =
2713 [](
auto& node,
SField const& field,
int v) ->
bool {
2714 return node.isMember(field.fieldName) &&
2715 ((node[field.fieldName].isInt() &&
2716 node[field.fieldName] ==
Json::Int(v)) ||
2717 (node[field.fieldName].isUInt() &&
2721 BEAST_EXPECT(vault[
"LedgerEntryType"].asString() ==
"Vault");
2722 BEAST_EXPECT(vault[jss::index].asString() ==
strHex(keylet.
key));
2723 BEAST_EXPECT(checkInt(vault, sfFlags, 0));
2727 checkString(vault, sfAccount,
toBase58(sle->at(sfAccount))));
2729 checkObject(vault, sfAsset,
to_json(sle->at(sfAsset))));
2730 BEAST_EXPECT(checkString(vault, sfAssetsAvailable,
"50"));
2731 BEAST_EXPECT(checkString(vault, sfAssetsMaximum,
"1000"));
2732 BEAST_EXPECT(checkString(vault, sfAssetsTotal,
"50"));
2733 BEAST_EXPECT(checkString(vault, sfLossUnrealized,
"0"));
2735 auto const strShareID =
strHex(sle->at(sfShareMPTID));
2736 BEAST_EXPECT(checkString(vault, sfShareMPTID, strShareID));
2737 BEAST_EXPECT(checkString(vault, sfOwner,
toBase58(owner.id())));
2738 BEAST_EXPECT(checkInt(vault, sfSequence, sequence));
2739 BEAST_EXPECT(checkInt(
2742 if (issuance.isObject())
2745 issuance[
"LedgerEntryType"].asString() ==
2748 issuance[jss::mpt_issuance_id].asString() == strShareID);
2749 BEAST_EXPECT(checkInt(issuance, sfSequence, 1));
2750 BEAST_EXPECT(checkInt(
2754 BEAST_EXPECT(checkString(issuance, sfOutstandingAmount,
"50"));
2759 testcase(
"RPC ledger_entry selected by key");
2761 jvParams[jss::ledger_index] = jss::validated;
2762 jvParams[jss::vault] =
strHex(keylet.
key);
2763 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2765 BEAST_EXPECT(!jvVault[jss::result].isMember(jss::error));
2766 BEAST_EXPECT(jvVault[jss::result].isMember(jss::node));
2767 check(jvVault[jss::result][jss::node]);
2771 testcase(
"RPC ledger_entry selected by owner and seq");
2773 jvParams[jss::ledger_index] = jss::validated;
2774 jvParams[jss::vault][jss::owner] = owner.human();
2775 jvParams[jss::vault][jss::seq] = sequence;
2776 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2778 BEAST_EXPECT(!jvVault[jss::result].isMember(jss::error));
2779 BEAST_EXPECT(jvVault[jss::result].isMember(jss::node));
2780 check(jvVault[jss::result][jss::node]);
2784 testcase(
"RPC ledger_entry cannot find vault by key");
2786 jvParams[jss::ledger_index] = jss::validated;
2788 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2790 jvVault[jss::result][jss::error].asString() ==
"entryNotFound");
2794 testcase(
"RPC ledger_entry cannot find vault by owner and seq");
2796 jvParams[jss::ledger_index] = jss::validated;
2797 jvParams[jss::vault][jss::owner] = issuer.human();
2798 jvParams[jss::vault][jss::seq] = 1'000'000;
2799 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2801 jvVault[jss::result][jss::error].asString() ==
"entryNotFound");
2805 testcase(
"RPC ledger_entry malformed key");
2807 jvParams[jss::ledger_index] = jss::validated;
2808 jvParams[jss::vault] = 42;
2809 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2811 jvVault[jss::result][jss::error].asString() ==
2812 "malformedRequest");
2816 testcase(
"RPC ledger_entry malformed owner");
2818 jvParams[jss::ledger_index] = jss::validated;
2819 jvParams[jss::vault][jss::owner] = 42;
2820 jvParams[jss::vault][jss::seq] = sequence;
2821 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2823 jvVault[jss::result][jss::error].asString() ==
2828 testcase(
"RPC ledger_entry malformed seq");
2830 jvParams[jss::ledger_index] = jss::validated;
2831 jvParams[jss::vault][jss::owner] = issuer.human();
2832 jvParams[jss::vault][jss::seq] =
"foo";
2833 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2835 jvVault[jss::result][jss::error].asString() ==
2836 "malformedRequest");
2840 testcase(
"RPC ledger_entry zero seq");
2842 jvParams[jss::ledger_index] = jss::validated;
2843 jvParams[jss::vault][jss::owner] = issuer.human();
2844 jvParams[jss::vault][jss::seq] = 0;
2845 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2847 jvVault[jss::result][jss::error].asString() ==
2848 "malformedRequest");
2852 testcase(
"RPC ledger_entry negative seq");
2854 jvParams[jss::ledger_index] = jss::validated;
2855 jvParams[jss::vault][jss::owner] = issuer.human();
2856 jvParams[jss::vault][jss::seq] = -1;
2857 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2859 jvVault[jss::result][jss::error].asString() ==
2860 "malformedRequest");
2864 testcase(
"RPC ledger_entry oversized seq");
2866 jvParams[jss::ledger_index] = jss::validated;
2867 jvParams[jss::vault][jss::owner] = issuer.human();
2868 jvParams[jss::vault][jss::seq] = 1e20;
2869 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2871 jvVault[jss::result][jss::error].asString() ==
2872 "malformedRequest");
2876 testcase(
"RPC ledger_entry bool seq");
2878 jvParams[jss::ledger_index] = jss::validated;
2879 jvParams[jss::vault][jss::owner] = issuer.human();
2880 jvParams[jss::vault][jss::seq] =
true;
2881 auto jvVault = env.rpc(
"json",
"ledger_entry",
to_string(jvParams));
2883 jvVault[jss::result][jss::error].asString() ==
2884 "malformedRequest");
2891 jvParams[jss::account] = owner.human();
2892 jvParams[jss::type] = jss::vault;
2894 "json",
"account_objects",
to_string(jvParams))[jss::result];
2896 BEAST_EXPECT(jv[jss::account_objects].size() == 1);
2897 check(jv[jss::account_objects][0u]);
2904 jvParams[jss::ledger_index] = jss::validated;
2905 jvParams[jss::binary] =
false;
2906 jvParams[jss::type] = jss::vault;
2908 env.rpc(
"json",
"ledger_data",
to_string(jvParams));
2909 BEAST_EXPECT(jv[jss::result][jss::state].size() == 1);
2910 check(jv[jss::result][jss::state][0u]);
2914 testcase(
"RPC vault_info command line");
2916 env.rpc(
"vault_info",
strHex(keylet.
key),
"validated");
2918 BEAST_EXPECT(!jv[jss::result].isMember(jss::error));
2919 BEAST_EXPECT(jv[jss::result].isMember(jss::vault));
2921 jv[jss::result][jss::vault],
2922 jv[jss::result][jss::vault][jss::shares]);
2928 jvParams[jss::ledger_index] = jss::validated;
2929 jvParams[jss::vault_id] =
strHex(keylet.
key);
2930 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2932 BEAST_EXPECT(!jv[jss::result].isMember(jss::error));
2933 BEAST_EXPECT(jv[jss::result].isMember(jss::vault));
2935 jv[jss::result][jss::vault],
2936 jv[jss::result][jss::vault][jss::shares]);
2940 testcase(
"RPC vault_info invalid vault_id");
2942 jvParams[jss::ledger_index] = jss::validated;
2943 jvParams[jss::vault_id] =
"foobar";
2944 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2946 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2950 testcase(
"RPC vault_info json invalid index");
2952 jvParams[jss::ledger_index] = jss::validated;
2953 jvParams[jss::vault_id] = 0;
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 by owner and sequence");
2962 jvParams[jss::ledger_index] = jss::validated;
2963 jvParams[jss::owner] = owner.human();
2964 jvParams[jss::seq] = sequence;
2965 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2967 BEAST_EXPECT(!jv[jss::result].isMember(jss::error));
2968 BEAST_EXPECT(jv[jss::result].isMember(jss::vault));
2970 jv[jss::result][jss::vault],
2971 jv[jss::result][jss::vault][jss::shares]);
2975 testcase(
"RPC vault_info json malformed sequence");
2977 jvParams[jss::ledger_index] = jss::validated;
2978 jvParams[jss::owner] = owner.human();
2979 jvParams[jss::seq] =
"foobar";
2980 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2982 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2986 testcase(
"RPC vault_info json invalid sequence");
2988 jvParams[jss::ledger_index] = jss::validated;
2989 jvParams[jss::owner] = owner.human();
2990 jvParams[jss::seq] = 0;
2991 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
2993 jv[jss::result][jss::error].asString() ==
"malformedRequest");
2997 testcase(
"RPC vault_info json negative sequence");
2999 jvParams[jss::ledger_index] = jss::validated;
3000 jvParams[jss::owner] = owner.human();
3001 jvParams[jss::seq] = -1;
3002 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3004 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3008 testcase(
"RPC vault_info json oversized sequence");
3010 jvParams[jss::ledger_index] = jss::validated;
3011 jvParams[jss::owner] = owner.human();
3012 jvParams[jss::seq] = 1e20;
3013 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3015 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3019 testcase(
"RPC vault_info json bool sequence");
3021 jvParams[jss::ledger_index] = jss::validated;
3022 jvParams[jss::owner] = owner.human();
3023 jvParams[jss::seq] =
true;
3024 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3026 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3030 testcase(
"RPC vault_info json malformed owner");
3032 jvParams[jss::ledger_index] = jss::validated;
3033 jvParams[jss::owner] =
"foobar";
3034 jvParams[jss::seq] = sequence;
3035 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3037 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3041 testcase(
"RPC vault_info json invalid combination only owner");
3043 jvParams[jss::ledger_index] = jss::validated;
3044 jvParams[jss::owner] = owner.human();
3045 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3047 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3051 testcase(
"RPC vault_info json invalid combination only seq");
3053 jvParams[jss::ledger_index] = jss::validated;
3054 jvParams[jss::seq] = sequence;
3055 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3057 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3061 testcase(
"RPC vault_info json invalid combination seq vault_id");
3063 jvParams[jss::ledger_index] = jss::validated;
3064 jvParams[jss::vault_id] =
strHex(keylet.
key);
3065 jvParams[jss::seq] = sequence;
3066 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3068 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3072 testcase(
"RPC vault_info json invalid combination owner vault_id");
3074 jvParams[jss::ledger_index] = jss::validated;
3075 jvParams[jss::vault_id] =
strHex(keylet.
key);
3076 jvParams[jss::owner] = owner.human();
3077 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3079 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3084 "RPC vault_info json invalid combination owner seq "
3087 jvParams[jss::ledger_index] = jss::validated;
3088 jvParams[jss::vault_id] =
strHex(keylet.
key);
3089 jvParams[jss::seq] = sequence;
3090 jvParams[jss::owner] = owner.human();
3091 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3093 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3097 testcase(
"RPC vault_info json no input");
3099 jvParams[jss::ledger_index] = jss::validated;
3100 auto jv = env.rpc(
"json",
"vault_info",
to_string(jvParams));
3102 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3106 testcase(
"RPC vault_info command line invalid index");
3107 Json::Value jv = env.rpc(
"vault_info",
"foobar",
"validated");
3108 BEAST_EXPECT(jv[jss::error].asString() ==
"invalidParams");
3112 testcase(
"RPC vault_info command line invalid index");
3113 Json::Value jv = env.rpc(
"vault_info",
"0",
"validated");
3115 jv[jss::result][jss::error].asString() ==
"malformedRequest");
3119 testcase(
"RPC vault_info command line invalid index");
3123 jv[jss::result][jss::error].asString() ==
"entryNotFound");
3127 testcase(
"RPC vault_info command line invalid ledger");
3130 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 mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
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.