922 using namespace test::jtx;
931 Env env{*
this, features - featureMPTokensV1};
935 env.fund(
XRP(1'000), alice);
936 env.fund(
XRP(1'000), bob);
944 Env env{*
this, features - featureMPTokensV1};
947 auto const USD = alice[
"USD"];
949 env.fund(
XRP(1'000), alice);
950 env.fund(
XRP(1'000), carol);
954 jv[jss::secret] = alice.
name();
955 jv[jss::tx_json] =
pay(alice, carol, mpt);
956 jv[jss::tx_json][jss::Fee] =
to_string(env.current()->fees().base);
957 auto const jrr = env.rpc(
"json",
"submit",
to_string(jv));
958 BEAST_EXPECT(jrr[jss::result][jss::engine_result] ==
"temDISABLED");
963 Env env{*
this, features};
965 MPTTester mptAlice(env, alice, {.holders = {bob}});
967 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
968 auto const MPT = mptAlice[
"MPT"];
970 mptAlice.authorize({.account = bob});
973 env(
pay(alice, bob,
MPT(10)),
980 Env env{*
this, features};
984 MPTTester mptAlice(env, alice, {.holders = {carol}});
986 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
988 mptAlice.authorize({.account = carol});
992 auto const MPT = mptAlice[
"MPT"];
993 env(
pay(alice, carol,
MPT(100)),
996 env(
pay(alice, carol,
MPT(100)),
1000 auto const USD = alice[
"USD"];
1001 env(
pay(alice, carol, USD(100)),
1004 env(
pay(alice, carol,
XRP(100)),
1007 env(
pay(alice, carol, USD(100)),
1010 env(
pay(alice, carol,
XRP(100)),
1015 "MPT",
makeMptID(env.seq(alice) + 10, alice));
1016 env(
pay(alice, carol, MPT1(100)),
1025 Env env{*
this, features};
1029 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1031 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1032 auto const MPT = mptAlice[
"MPT"];
1034 mptAlice.authorize({.account = carol});
1037 payment[jss::secret] = alice.
name();
1038 payment[jss::tx_json] =
pay(alice, carol,
MPT(100));
1040 payment[jss::build_path] =
true;
1041 auto jrr = env.rpc(
"json",
"submit",
to_string(payment));
1042 BEAST_EXPECT(jrr[jss::result][jss::error] ==
"invalidParams");
1044 jrr[jss::result][jss::error_message] ==
1045 "Field 'build_path' not allowed in this context.");
1050 Env env{*
this, features};
1052 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1054 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1055 auto const MPT = mptAlice[
"MPT"];
1057 mptAlice.authorize({.account = bob});
1058 mptAlice.authorize({.account = carol});
1071 Env env{*
this, features};
1073 MPTTester mptAlice(env, alice, {.holders = {bob}});
1075 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1077 mptAlice.authorize({.account = bob});
1086 Env env{*
this, features};
1088 MPTTester mptAlice(env, alice, {.holders = {bob}});
1090 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1092 mptAlice.authorize({.account = bob});
1105 Env env{*
this, features};
1107 MPTTester mptAlice(env, alice, {.holders = {bob}});
1114 mptAlice.authorize({.account = bob});
1122 Env env{*
this, features};
1124 MPTTester mptAlice(env, alice, {.holders = {bob}});
1132 mptAlice.authorize({.account = bob});
1135 mptAlice.authorize({.account = alice, .holder = bob});
1138 mptAlice.pay(alice, bob, 100);
1149 if (features[featureSingleAssetVault] &&
1150 features[featurePermissionedDomains])
1154 Env env{*
this, features};
1156 Account const credIssuer1{
"credIssuer1"};
1157 env.fund(
XRP(1000), credIssuer1, bob);
1159 auto const domainId1 = [&]() {
1161 {.issuer = credIssuer1, .credType = credType}};
1181 .domainID = domainId1,
1184 mptAlice.authorize({.account = bob});
1188 mptAlice.pay(alice, bob, 100);
1189 mptAlice.set({.domainID = beast::zero});
1196 Env env{*
this, features};
1198 Account const credIssuer1{
"credIssuer1"};
1199 env.fund(
XRP(1000), credIssuer1, bob);
1201 auto const domainId1 = [&]() {
1203 {.issuer = credIssuer1, .credType = credType}};
1223 .domainID = domainId1,
1227 mptAlice.authorize({.account = bob});
1230 mptAlice.authorize({.account = alice, .holder = bob});
1233 mptAlice.pay(alice, bob, 100);
1242 mptAlice.pay(bob, alice, 10);
1244 mptAlice.set({.domainID = beast::zero});
1252 Env env{*
this, features};
1255 Account const credIssuer1{
"credIssuer1"};
1258 Account const credIssuer2{
"credIssuer2"};
1259 env.fund(
XRP(1000), credIssuer1, credIssuer2, bob, carol);
1261 auto const domainId1 = [&]() {
1263 {.issuer = credIssuer1, .credType = credType}};
1272 auto const domainId2 = [&]() {
1274 {.issuer = credIssuer1, .credType = credType},
1275 {.issuer = credIssuer2, .credType = credType}};
1303 .domainID = domainId1,
1307 mptAlice.authorize({.account = bob});
1308 mptAlice.authorize({.account = carol});
1312 mptAlice.pay(alice, bob, 50);
1323 mptAlice.set({.domainID = domainId2});
1325 mptAlice.pay(alice, carol, 10);
1330 mptAlice.pay(bob, carol, 10);
1335 credIssuer1, bob, credIssuer1, credType));
1345 Env env(*
this, features);
1350 MPTTester mptAlice(env, alice, {.holders = {bob, cindy}});
1353 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1356 mptAlice.authorize({.account = bob});
1359 mptAlice.authorize({.account = cindy});
1362 mptAlice.pay(alice, bob, 100);
1369 mptAlice.pay(bob, alice, 10);
1374 Env env{*
this, features};
1376 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1393 Env env{*
this, features};
1395 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1399 mptAlice.authorize({.account = bob});
1400 mptAlice.authorize({.account = carol});
1402 mptAlice.pay(alice, bob, 100);
1413 Env env{*
this, features};
1415 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1420 mptAlice.authorize({.account = bob});
1421 mptAlice.authorize({.account = carol});
1423 mptAlice.pay(alice, bob, 100);
1424 mptAlice.pay(alice, carol, 100);
1427 mptAlice.set({.account = alice, .flags =
tfMPTLock});
1432 mptAlice.pay(alice, bob, 3);
1434 mptAlice.pay(bob, alice, 4);
1437 mptAlice.set({.account = alice, .flags =
tfMPTUnlock});
1439 mptAlice.set({.account = alice, .holder = bob, .flags =
tfMPTLock});
1444 mptAlice.pay(alice, bob, 7);
1446 mptAlice.pay(bob, alice, 8);
1451 Env env{*
this, features};
1453 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1457 {.transferFee = 10'000,
1463 mptAlice.authorize({.account = bob});
1464 mptAlice.authorize({.account = carol});
1467 mptAlice.pay(alice, bob, 2'000);
1470 mptAlice.pay(bob, alice, 1'000);
1471 BEAST_EXPECT(mptAlice.checkMPTokenAmount(bob, 1'000));
1481 auto const MPT = mptAlice[
"MPT"];
1483 env(
pay(bob, carol,
MPT(100)),
1492 BEAST_EXPECT(mptAlice.checkMPTokenAmount(bob, 780));
1493 BEAST_EXPECT(mptAlice.checkMPTokenAmount(carol, 200));
1496 env(
pay(bob, carol,
MPT(100)),
1501 BEAST_EXPECT(mptAlice.checkMPTokenAmount(bob, 690));
1502 BEAST_EXPECT(mptAlice.checkMPTokenAmount(carol, 282));
1507 Env env{*
this, features};
1509 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1515 mptAlice.authorize({.account = bob});
1516 mptAlice.authorize({.account = carol});
1517 mptAlice.pay(alice, bob, 1'000);
1519 auto const MPT = mptAlice[
"MPT"];
1521 env(
pay(bob, carol,
MPT(100)),
1524 env(
pay(bob, alice,
MPT(100)),
1530 BEAST_EXPECT(mptAlice.checkMPTokenAmount(carol, 100));
1532 env(
pay(bob, carol,
MPT(100)),
1535 BEAST_EXPECT(mptAlice.checkMPTokenAmount(carol, 199));
1540 Env env{*
this, features};
1542 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1548 mptAlice.authorize({.account = bob});
1549 mptAlice.authorize({.account = carol});
1550 mptAlice.pay(alice, bob, 1'000);
1552 auto const MPT = mptAlice[
"MPT"];
1555 env(
pay(bob, alice,
MPT(100)),
1561 env(
pay(bob, alice,
MPT(100)),
1569 Env env{*
this, features};
1571 MPTTester mptAlice(env, alice, {.holders = {bob}});
1579 mptAlice.authorize({.account = bob});
1582 mptAlice.pay(alice, bob, 100);
1591 Env env{*
this, features};
1593 MPTTester mptAlice(env, alice, {.holders = {bob}});
1595 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1597 mptAlice.authorize({.account = bob});
1609 Env env{*
this, features};
1610 env.fund(
XRP(1'000), alice, bob);
1613 jv[jss::secret] = alice.
name();
1614 jv[jss::tx_json] =
pay(alice, bob, mpt);
1615 jv[jss::tx_json][jss::Amount][jss::value] =
1617 auto const jrr = env.rpc(
"json",
"submit",
to_string(jv));
1618 BEAST_EXPECT(jrr[jss::result][jss::error] ==
"invalidParams");
1624 Env env{*
this, features};
1626 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1634 auto const MPT = mptAlice[
"MPT"];
1636 mptAlice.authorize({.account = bob});
1637 mptAlice.authorize({.account = carol});
1640 mptAlice.pay(alice, bob, 10'000);
1643 env(
pay(bob, carol,
MPT(10'000)),
1647 auto const meta = env.meta()->getJson(
1651 meta[0u][sfModifiedNode.fieldName][sfFinalFields.fieldName]
1652 [sfOutstandingAmount.fieldName] ==
"9990");
1655 meta[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName]
1656 [sfMPTAmount.fieldName] ==
"9990");
1659 meta[2u][sfModifiedNode.fieldName][sfPreviousFields.fieldName]
1660 [sfMPTAmount.fieldName] ==
"10000");
1662 !meta[2u][sfModifiedNode.fieldName][sfFinalFields.fieldName]
1663 .isMember(sfMPTAmount.fieldName));
1667 env(
pay(bob, carol,
MPT(10'000)),
1674 Env env{*
this, features};
1676 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1683 auto const MPT = mptAlice[
"MPT"];
1685 mptAlice.authorize({.account = bob});
1686 mptAlice.authorize({.account = carol});
1699 BEAST_EXPECT(mptAlice.checkMPTokenOutstandingAmount(0));
1704 Env env{*
this, features};
1706 MPTTester mptAlice(env, alice, {.holders = {bob}});
1708 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1710 mptAlice.authorize({.account = bob});
1713 mptAlice.destroy({.ownerCount = 0});
1722 Env env{*
this, features};
1724 env.fund(
XRP(1'000), alice, bob);
1733 Env env{*
this, features};
1735 MPTTester mptAlice(env, alice, {.holders = {bob}});
1737 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1740 mptAlice.destroy({.ownerCount = 0});
1750 Env env{*
this, features};
1755 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1760 mptAlice.authorize({.account = bob});
1761 mptAlice.authorize({.account = carol});
1763 mptAlice.pay(alice, bob, 100);
1766 mptAlice.pay(bob, carol, 100);
1771 Env env{*
this, features};
1773 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1778 mptAlice.authorize({.account = bob});
1779 mptAlice.authorize({.account = carol});
1782 mptAlice.pay(alice, bob, 100);
1785 mptAlice.pay(bob, alice, 100);
1788 mptAlice.pay(alice, bob, 100);
1789 mptAlice.pay(bob, carol, 50);
1948 testcase(
"MPT Issue Invalid in Transaction");
1949 using namespace test::jtx;
1958 for (
auto const& e : format.getSOTemplate())
1964 e.sField().getName() != jss::Fee &&
1965 format.getName() != jss::SetFee)
1968 format.getName() + e.sField().fieldName);
1975 auto const USD = alice[
"USD"];
1978 STAmount mpt{issue, UINT64_C(100)};
1979 auto const jvb =
bridge(alice, USD, alice, USD);
1980 for (
auto const& feature : {features, features - featureMPTokensV1})
1982 Env env{*
this, feature};
1983 env.fund(
XRP(1'000), alice);
1984 env.fund(
XRP(1'000), carol);
1987 txWithAmounts.
erase(
1988 jv[jss::TransactionType].asString() + mptField);
1991 auto jtx = env.jt(jv);
1996 jrr[jss::result][jss::error] ==
"invalidTransaction");
2000 jv1[jss::secret] = alice.
name();
2001 jv1[jss::tx_json] = jv;
2002 jrr = env.rpc(
"json",
"submit",
to_string(jv1));
2003 BEAST_EXPECT(jrr[jss::result][jss::error] ==
"invalidParams");
2005 jrr = env.rpc(
"json",
"sign",
to_string(jv1));
2006 BEAST_EXPECT(jrr[jss::result][jss::error] ==
"invalidParams");
2008 auto toSFieldRef = [](
SField const& field) {
2011 auto setMPTFields = [&](
SField const& field,
2013 bool withAmount =
true) {
2015 jv[jss::Asset2] =
to_json(USD.issue());
2017 jv[field.fieldName] =
2019 if (field == sfAsset)
2021 else if (field == sfAsset2)
2031 auto ammCreate = [&](
SField const& field) {
2033 jv[jss::TransactionType] = jss::AMMCreate;
2034 jv[jss::Account] = alice.
human();
2035 jv[jss::Amount] = (field.fieldName == sfAmount.fieldName)
2038 jv[jss::Amount2] = (field.fieldName == sfAmount2.fieldName)
2041 jv[jss::TradingFee] = 0;
2042 test(jv, field.fieldName);
2044 ammCreate(sfAmount);
2045 ammCreate(sfAmount2);
2047 auto ammDeposit = [&](
SField const& field) {
2049 jv[jss::TransactionType] = jss::AMMDeposit;
2050 jv[jss::Account] = alice.
human();
2052 setMPTFields(field, jv);
2053 test(jv, field.fieldName);
2055 for (
SField const& field :
2056 {toSFieldRef(sfAmount),
2057 toSFieldRef(sfAmount2),
2058 toSFieldRef(sfEPrice),
2059 toSFieldRef(sfLPTokenOut),
2060 toSFieldRef(sfAsset),
2061 toSFieldRef(sfAsset2)})
2064 auto ammWithdraw = [&](
SField const& field) {
2066 jv[jss::TransactionType] = jss::AMMWithdraw;
2067 jv[jss::Account] = alice.
human();
2069 setMPTFields(field, jv);
2070 test(jv, field.fieldName);
2072 ammWithdraw(sfAmount);
2073 for (
SField const& field :
2074 {toSFieldRef(sfAmount2),
2075 toSFieldRef(sfEPrice),
2076 toSFieldRef(sfLPTokenIn),
2077 toSFieldRef(sfAsset),
2078 toSFieldRef(sfAsset2)})
2081 auto ammBid = [&](
SField const& field) {
2083 jv[jss::TransactionType] = jss::AMMBid;
2084 jv[jss::Account] = alice.
human();
2085 setMPTFields(field, jv);
2086 test(jv, field.fieldName);
2088 for (
SField const& field :
2089 {toSFieldRef(sfBidMin),
2090 toSFieldRef(sfBidMax),
2091 toSFieldRef(sfAsset),
2092 toSFieldRef(sfAsset2)})
2095 auto ammClawback = [&](
SField const& field) {
2097 jv[jss::TransactionType] = jss::AMMClawback;
2098 jv[jss::Account] = alice.
human();
2099 jv[jss::Holder] = carol.
human();
2100 setMPTFields(field, jv);
2101 test(jv, field.fieldName);
2103 for (
SField const& field :
2104 {toSFieldRef(sfAmount),
2105 toSFieldRef(sfAsset),
2106 toSFieldRef(sfAsset2)})
2109 auto ammDelete = [&](
SField const& field) {
2111 jv[jss::TransactionType] = jss::AMMDelete;
2112 jv[jss::Account] = alice.
human();
2113 setMPTFields(field, jv,
false);
2114 test(jv, field.fieldName);
2117 ammDelete(sfAsset2);
2119 auto ammVote = [&](
SField const& field) {
2121 jv[jss::TransactionType] = jss::AMMVote;
2122 jv[jss::Account] = alice.
human();
2123 jv[jss::TradingFee] = 100;
2124 setMPTFields(field, jv,
false);
2125 test(jv, field.fieldName);
2130 auto checkCash = [&](
SField const& field) {
2132 jv[jss::TransactionType] = jss::CheckCash;
2133 jv[jss::Account] = alice.
human();
2136 test(jv, field.fieldName);
2138 checkCash(sfAmount);
2139 checkCash(sfDeliverMin);
2143 jv[jss::TransactionType] = jss::CheckCreate;
2144 jv[jss::Account] = alice.
human();
2145 jv[jss::Destination] = carol.
human();
2147 test(jv, jss::SendMax.c_str());
2152 test(jv, jss::TakerPays.c_str());
2153 jv =
offer(alice, mpt, USD(100));
2154 test(jv, jss::TakerGets.c_str());
2159 jv[jss::TransactionType] = jss::PaymentChannelCreate;
2160 jv[jss::Account] = alice.
human();
2161 jv[jss::Destination] = carol.
human();
2162 jv[jss::SettleDelay] = 1;
2165 test(jv, jss::Amount.c_str());
2170 jv[jss::TransactionType] = jss::PaymentChannelFund;
2171 jv[jss::Account] = alice.
human();
2174 test(jv, jss::Amount.c_str());
2179 jv[jss::TransactionType] = jss::PaymentChannelClaim;
2180 jv[jss::Account] = alice.
human();
2183 test(jv, jss::Amount.c_str());
2188 jv[jss::TransactionType] = jss::NFTokenCreateOffer;
2189 jv[jss::Account] = alice.
human();
2192 test(jv, jss::Amount.c_str());
2197 jv[jss::TransactionType] = jss::NFTokenAcceptOffer;
2198 jv[jss::Account] = alice.
human();
2199 jv[sfNFTokenBrokerFee.fieldName] =
2201 test(jv, sfNFTokenBrokerFee.fieldName);
2206 jv[jss::TransactionType] = jss::NFTokenMint;
2207 jv[jss::Account] = alice.
human();
2208 jv[sfNFTokenTaxon.fieldName] = 1;
2210 test(jv, jss::Amount.c_str());
2213 auto trustSet = [&](
SField const& field) {
2215 jv[jss::TransactionType] = jss::TrustSet;
2216 jv[jss::Account] = alice.
human();
2219 test(jv, field.fieldName);
2221 trustSet(sfLimitAmount);
2226 test(jv, jss::Amount.c_str());
2231 test(jv, jss::Amount.c_str());
2237 test(jv, sfSignatureReward.fieldName);
2251 test(jv, jss::Amount.c_str());
2266 for (
auto const& field :
2267 {sfAmount.fieldName, sfSignatureReward.fieldName})
2276 alice, jvb, alice, mpt,
XRP(10));
2277 for (
auto const& field :
2278 {sfAmount.fieldName, sfSignatureReward.fieldName})
2290 jv[jss::TransactionType] = tt;
2291 jv[jss::Account] = alice.
human();
2292 jv[sfXChainBridge.fieldName] = jvb;
2293 jv[sfSignatureReward.fieldName] =
2295 jv[sfMinAccountCreateAmount.fieldName] =
2299 auto reward =
STAmount{sfSignatureReward, mpt};
2300 auto minAmount =
STAmount{sfMinAccountCreateAmount, USD(10)};
2301 for (
SField const& field :
2303 std::ref(sfMinAccountCreateAmount)})
2306 jss::XChainCreateBridge,
2311 jss::XChainModifyBridge,
2315 reward =
STAmount{sfSignatureReward, USD(10)};
2316 minAmount =
STAmount{sfMinAccountCreateAmount, mpt};
2319 BEAST_EXPECT(txWithAmounts.
empty());