903 using namespace test::jtx;
912 Env env{*
this, features - featureMPTokensV1};
916 env.fund(
XRP(1'000), alice);
917 env.fund(
XRP(1'000), bob);
925 Env env{*
this, features - featureMPTokensV1};
928 auto const USD = alice[
"USD"];
930 env.fund(
XRP(1'000), alice);
931 env.fund(
XRP(1'000), carol);
935 jv[jss::secret] = alice.
name();
936 jv[jss::tx_json] =
pay(alice, carol, mpt);
937 jv[jss::tx_json][jss::Fee] =
to_string(env.current()->fees().base);
938 auto const jrr = env.rpc(
"json",
"submit",
to_string(jv));
939 BEAST_EXPECT(jrr[jss::result][jss::engine_result] ==
"temDISABLED");
944 Env env{*
this, features};
946 MPTTester mptAlice(env, alice, {.holders = {bob}});
948 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
949 auto const MPT = mptAlice[
"MPT"];
951 mptAlice.authorize({.account = bob});
954 env(
pay(alice, bob,
MPT(10)),
961 Env env{*
this, features};
965 MPTTester mptAlice(env, alice, {.holders = {carol}});
967 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
969 mptAlice.authorize({.account = carol});
973 auto const MPT = mptAlice[
"MPT"];
974 env(
pay(alice, carol,
MPT(100)),
977 env(
pay(alice, carol,
MPT(100)),
981 auto const USD = alice[
"USD"];
982 env(
pay(alice, carol, USD(100)),
985 env(
pay(alice, carol,
XRP(100)),
988 env(
pay(alice, carol, USD(100)),
991 env(
pay(alice, carol,
XRP(100)),
996 "MPT",
makeMptID(env.seq(alice) + 10, alice));
997 env(
pay(alice, carol, MPT1(100)),
1006 Env env{*
this, features};
1010 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1012 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1013 auto const MPT = mptAlice[
"MPT"];
1015 mptAlice.authorize({.account = carol});
1018 payment[jss::secret] = alice.
name();
1019 payment[jss::tx_json] =
pay(alice, carol,
MPT(100));
1021 payment[jss::build_path] =
true;
1022 auto jrr = env.rpc(
"json",
"submit",
to_string(payment));
1023 BEAST_EXPECT(jrr[jss::result][jss::error] ==
"invalidParams");
1025 jrr[jss::result][jss::error_message] ==
1026 "Field 'build_path' not allowed in this context.");
1031 Env env{*
this, features};
1033 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1035 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1036 auto const MPT = mptAlice[
"MPT"];
1038 mptAlice.authorize({.account = bob});
1039 mptAlice.authorize({.account = carol});
1052 Env env{*
this, features};
1054 MPTTester mptAlice(env, alice, {.holders = {bob}});
1056 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1058 mptAlice.authorize({.account = bob});
1067 Env env{*
this, features};
1069 MPTTester mptAlice(env, alice, {.holders = {bob}});
1071 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1073 mptAlice.authorize({.account = bob});
1086 Env env{*
this, features};
1088 MPTTester mptAlice(env, alice, {.holders = {bob}});
1095 mptAlice.authorize({.account = bob});
1103 Env env{*
this, features};
1105 MPTTester mptAlice(env, alice, {.holders = {bob}});
1113 mptAlice.authorize({.account = bob});
1116 mptAlice.authorize({.account = alice, .holder = bob});
1119 mptAlice.pay(alice, bob, 100);
1130 if (features[featureSingleAssetVault] &&
1131 features[featurePermissionedDomains])
1135 Env env{*
this, features};
1137 Account const credIssuer1{
"credIssuer1"};
1138 env.fund(
XRP(1000), credIssuer1, bob);
1140 auto const domainId1 = [&]() {
1142 {.issuer = credIssuer1, .credType = credType}};
1162 .domainID = domainId1,
1165 mptAlice.authorize({.account = bob});
1169 mptAlice.pay(alice, bob, 100);
1170 mptAlice.set({.domainID = beast::zero});
1177 Env env{*
this, features};
1179 Account const credIssuer1{
"credIssuer1"};
1180 env.fund(
XRP(1000), credIssuer1, bob);
1182 auto const domainId1 = [&]() {
1184 {.issuer = credIssuer1, .credType = credType}};
1204 .domainID = domainId1,
1208 mptAlice.authorize({.account = bob});
1211 mptAlice.authorize({.account = alice, .holder = bob});
1214 mptAlice.pay(alice, bob, 100);
1223 mptAlice.pay(bob, alice, 10);
1225 mptAlice.set({.domainID = beast::zero});
1233 Env env{*
this, features};
1236 Account const credIssuer1{
"credIssuer1"};
1239 Account const credIssuer2{
"credIssuer2"};
1240 env.fund(
XRP(1000), credIssuer1, credIssuer2, bob, carol);
1242 auto const domainId1 = [&]() {
1244 {.issuer = credIssuer1, .credType = credType}};
1253 auto const domainId2 = [&]() {
1255 {.issuer = credIssuer1, .credType = credType},
1256 {.issuer = credIssuer2, .credType = credType}};
1284 .domainID = domainId1,
1288 mptAlice.authorize({.account = bob});
1289 mptAlice.authorize({.account = carol});
1293 mptAlice.pay(alice, bob, 50);
1304 mptAlice.set({.domainID = domainId2});
1306 mptAlice.pay(alice, carol, 10);
1311 mptAlice.pay(bob, carol, 10);
1316 credIssuer1, bob, credIssuer1, credType));
1326 Env env(*
this, features);
1331 MPTTester mptAlice(env, alice, {.holders = {bob, cindy}});
1334 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1337 mptAlice.authorize({.account = bob});
1340 mptAlice.authorize({.account = cindy});
1343 mptAlice.pay(alice, bob, 100);
1350 mptAlice.pay(bob, alice, 10);
1355 Env env{*
this, features};
1357 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1374 Env env{*
this, features};
1376 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1380 mptAlice.authorize({.account = bob});
1381 mptAlice.authorize({.account = carol});
1383 mptAlice.pay(alice, bob, 100);
1394 Env env{*
this, features};
1396 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1401 mptAlice.authorize({.account = bob});
1402 mptAlice.authorize({.account = carol});
1404 mptAlice.pay(alice, bob, 100);
1405 mptAlice.pay(alice, carol, 100);
1408 mptAlice.set({.account = alice, .flags =
tfMPTLock});
1413 mptAlice.pay(alice, bob, 3);
1415 mptAlice.pay(bob, alice, 4);
1418 mptAlice.set({.account = alice, .flags =
tfMPTUnlock});
1420 mptAlice.set({.account = alice, .holder = bob, .flags =
tfMPTLock});
1425 mptAlice.pay(alice, bob, 7);
1427 mptAlice.pay(bob, alice, 8);
1432 Env env{*
this, features};
1434 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1438 {.transferFee = 10'000,
1444 mptAlice.authorize({.account = bob});
1445 mptAlice.authorize({.account = carol});
1448 mptAlice.pay(alice, bob, 2'000);
1451 mptAlice.pay(bob, alice, 1'000);
1452 BEAST_EXPECT(mptAlice.checkMPTokenAmount(bob, 1'000));
1462 auto const MPT = mptAlice[
"MPT"];
1464 env(
pay(bob, carol,
MPT(100)),
1473 BEAST_EXPECT(mptAlice.checkMPTokenAmount(bob, 780));
1474 BEAST_EXPECT(mptAlice.checkMPTokenAmount(carol, 200));
1477 env(
pay(bob, carol,
MPT(100)),
1482 BEAST_EXPECT(mptAlice.checkMPTokenAmount(bob, 690));
1483 BEAST_EXPECT(mptAlice.checkMPTokenAmount(carol, 282));
1488 Env env{*
this, features};
1490 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1496 mptAlice.authorize({.account = bob});
1497 mptAlice.authorize({.account = carol});
1498 mptAlice.pay(alice, bob, 1'000);
1500 auto const MPT = mptAlice[
"MPT"];
1502 env(
pay(bob, carol,
MPT(100)),
1505 env(
pay(bob, alice,
MPT(100)),
1511 BEAST_EXPECT(mptAlice.checkMPTokenAmount(carol, 100));
1513 env(
pay(bob, carol,
MPT(100)),
1516 BEAST_EXPECT(mptAlice.checkMPTokenAmount(carol, 199));
1521 Env env{*
this, features};
1523 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1529 mptAlice.authorize({.account = bob});
1530 mptAlice.authorize({.account = carol});
1531 mptAlice.pay(alice, bob, 1'000);
1533 auto const MPT = mptAlice[
"MPT"];
1536 env(
pay(bob, alice,
MPT(100)),
1542 env(
pay(bob, alice,
MPT(100)),
1550 Env env{*
this, features};
1552 MPTTester mptAlice(env, alice, {.holders = {bob}});
1560 mptAlice.authorize({.account = bob});
1563 mptAlice.pay(alice, bob, 100);
1572 Env env{*
this, features};
1574 MPTTester mptAlice(env, alice, {.holders = {bob}});
1576 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1578 mptAlice.authorize({.account = bob});
1590 Env env{*
this, features};
1591 env.fund(
XRP(1'000), alice, bob);
1594 jv[jss::secret] = alice.
name();
1595 jv[jss::tx_json] =
pay(alice, bob, mpt);
1596 jv[jss::tx_json][jss::Amount][jss::value] =
1598 auto const jrr = env.rpc(
"json",
"submit",
to_string(jv));
1599 BEAST_EXPECT(jrr[jss::result][jss::error] ==
"invalidParams");
1605 Env env{*
this, features};
1607 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1615 auto const MPT = mptAlice[
"MPT"];
1617 mptAlice.authorize({.account = bob});
1618 mptAlice.authorize({.account = carol});
1621 mptAlice.pay(alice, bob, 10'000);
1624 env(
pay(bob, carol,
MPT(10'000)),
1628 auto const meta = env.meta()->getJson(
1632 meta[0u][sfModifiedNode.fieldName][sfFinalFields.fieldName]
1633 [sfOutstandingAmount.fieldName] ==
"9990");
1636 meta[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName]
1637 [sfMPTAmount.fieldName] ==
"9990");
1640 meta[2u][sfModifiedNode.fieldName][sfPreviousFields.fieldName]
1641 [sfMPTAmount.fieldName] ==
"10000");
1643 !meta[2u][sfModifiedNode.fieldName][sfFinalFields.fieldName]
1644 .isMember(sfMPTAmount.fieldName));
1648 env(
pay(bob, carol,
MPT(10'000)),
1655 Env env{*
this, features};
1657 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1664 auto const MPT = mptAlice[
"MPT"];
1666 mptAlice.authorize({.account = bob});
1667 mptAlice.authorize({.account = carol});
1680 BEAST_EXPECT(mptAlice.checkMPTokenOutstandingAmount(0));
1685 Env env{*
this, features};
1687 MPTTester mptAlice(env, alice, {.holders = {bob}});
1689 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1691 mptAlice.authorize({.account = bob});
1694 mptAlice.destroy({.ownerCount = 0});
1703 Env env{*
this, features};
1705 env.fund(
XRP(1'000), alice, bob);
1714 Env env{*
this, features};
1716 MPTTester mptAlice(env, alice, {.holders = {bob}});
1718 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1721 mptAlice.destroy({.ownerCount = 0});
1731 Env env{*
this, features};
1736 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1741 mptAlice.authorize({.account = bob});
1742 mptAlice.authorize({.account = carol});
1744 mptAlice.pay(alice, bob, 100);
1747 mptAlice.pay(bob, carol, 100);
1752 Env env{*
this, features};
1754 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1759 mptAlice.authorize({.account = bob});
1760 mptAlice.authorize({.account = carol});
1763 mptAlice.pay(alice, bob, 100);
1766 mptAlice.pay(bob, alice, 100);
1769 mptAlice.pay(alice, bob, 100);
1770 mptAlice.pay(bob, carol, 50);
1929 testcase(
"MPT Issue Invalid in Transaction");
1930 using namespace test::jtx;
1939 for (
auto const& e : format.getSOTemplate())
1945 e.sField().getName() != jss::Fee &&
1946 format.getName() != jss::SetFee)
1949 format.getName() + e.sField().fieldName);
1956 auto const USD = alice[
"USD"];
1959 STAmount mpt{issue, UINT64_C(100)};
1960 auto const jvb =
bridge(alice, USD, alice, USD);
1961 for (
auto const& feature : {features, features - featureMPTokensV1})
1963 Env env{*
this, feature};
1964 env.fund(
XRP(1'000), alice);
1965 env.fund(
XRP(1'000), carol);
1968 txWithAmounts.
erase(
1969 jv[jss::TransactionType].asString() + mptField);
1972 auto jtx = env.jt(jv);
1977 jrr[jss::result][jss::error] ==
"invalidTransaction");
1981 jv1[jss::secret] = alice.
name();
1982 jv1[jss::tx_json] = jv;
1983 jrr = env.rpc(
"json",
"submit",
to_string(jv1));
1984 BEAST_EXPECT(jrr[jss::result][jss::error] ==
"invalidParams");
1986 jrr = env.rpc(
"json",
"sign",
to_string(jv1));
1987 BEAST_EXPECT(jrr[jss::result][jss::error] ==
"invalidParams");
1989 auto toSFieldRef = [](
SField const& field) {
1992 auto setMPTFields = [&](
SField const& field,
1994 bool withAmount =
true) {
1996 jv[jss::Asset2] =
to_json(USD.issue());
1998 jv[field.fieldName] =
2000 if (field == sfAsset)
2002 else if (field == sfAsset2)
2012 auto ammCreate = [&](
SField const& field) {
2014 jv[jss::TransactionType] = jss::AMMCreate;
2015 jv[jss::Account] = alice.
human();
2016 jv[jss::Amount] = (field.fieldName == sfAmount.fieldName)
2019 jv[jss::Amount2] = (field.fieldName == sfAmount2.fieldName)
2022 jv[jss::TradingFee] = 0;
2023 test(jv, field.fieldName);
2025 ammCreate(sfAmount);
2026 ammCreate(sfAmount2);
2028 auto ammDeposit = [&](
SField const& field) {
2030 jv[jss::TransactionType] = jss::AMMDeposit;
2031 jv[jss::Account] = alice.
human();
2033 setMPTFields(field, jv);
2034 test(jv, field.fieldName);
2036 for (
SField const& field :
2037 {toSFieldRef(sfAmount),
2038 toSFieldRef(sfAmount2),
2039 toSFieldRef(sfEPrice),
2040 toSFieldRef(sfLPTokenOut),
2041 toSFieldRef(sfAsset),
2042 toSFieldRef(sfAsset2)})
2045 auto ammWithdraw = [&](
SField const& field) {
2047 jv[jss::TransactionType] = jss::AMMWithdraw;
2048 jv[jss::Account] = alice.
human();
2050 setMPTFields(field, jv);
2051 test(jv, field.fieldName);
2053 ammWithdraw(sfAmount);
2054 for (
SField const& field :
2055 {toSFieldRef(sfAmount2),
2056 toSFieldRef(sfEPrice),
2057 toSFieldRef(sfLPTokenIn),
2058 toSFieldRef(sfAsset),
2059 toSFieldRef(sfAsset2)})
2062 auto ammBid = [&](
SField const& field) {
2064 jv[jss::TransactionType] = jss::AMMBid;
2065 jv[jss::Account] = alice.
human();
2066 setMPTFields(field, jv);
2067 test(jv, field.fieldName);
2069 for (
SField const& field :
2070 {toSFieldRef(sfBidMin),
2071 toSFieldRef(sfBidMax),
2072 toSFieldRef(sfAsset),
2073 toSFieldRef(sfAsset2)})
2076 auto ammClawback = [&](
SField const& field) {
2078 jv[jss::TransactionType] = jss::AMMClawback;
2079 jv[jss::Account] = alice.
human();
2080 jv[jss::Holder] = carol.
human();
2081 setMPTFields(field, jv);
2082 test(jv, field.fieldName);
2084 for (
SField const& field :
2085 {toSFieldRef(sfAmount),
2086 toSFieldRef(sfAsset),
2087 toSFieldRef(sfAsset2)})
2090 auto ammDelete = [&](
SField const& field) {
2092 jv[jss::TransactionType] = jss::AMMDelete;
2093 jv[jss::Account] = alice.
human();
2094 setMPTFields(field, jv,
false);
2095 test(jv, field.fieldName);
2098 ammDelete(sfAsset2);
2100 auto ammVote = [&](
SField const& field) {
2102 jv[jss::TransactionType] = jss::AMMVote;
2103 jv[jss::Account] = alice.
human();
2104 jv[jss::TradingFee] = 100;
2105 setMPTFields(field, jv,
false);
2106 test(jv, field.fieldName);
2111 auto checkCash = [&](
SField const& field) {
2113 jv[jss::TransactionType] = jss::CheckCash;
2114 jv[jss::Account] = alice.
human();
2117 test(jv, field.fieldName);
2119 checkCash(sfAmount);
2120 checkCash(sfDeliverMin);
2124 jv[jss::TransactionType] = jss::CheckCreate;
2125 jv[jss::Account] = alice.
human();
2126 jv[jss::Destination] = carol.
human();
2128 test(jv, jss::SendMax.c_str());
2133 test(jv, jss::TakerPays.c_str());
2134 jv =
offer(alice, mpt, USD(100));
2135 test(jv, jss::TakerGets.c_str());
2140 jv[jss::TransactionType] = jss::PaymentChannelCreate;
2141 jv[jss::Account] = alice.
human();
2142 jv[jss::Destination] = carol.
human();
2143 jv[jss::SettleDelay] = 1;
2146 test(jv, jss::Amount.c_str());
2151 jv[jss::TransactionType] = jss::PaymentChannelFund;
2152 jv[jss::Account] = alice.
human();
2155 test(jv, jss::Amount.c_str());
2160 jv[jss::TransactionType] = jss::PaymentChannelClaim;
2161 jv[jss::Account] = alice.
human();
2164 test(jv, jss::Amount.c_str());
2169 jv[jss::TransactionType] = jss::NFTokenCreateOffer;
2170 jv[jss::Account] = alice.
human();
2173 test(jv, jss::Amount.c_str());
2178 jv[jss::TransactionType] = jss::NFTokenAcceptOffer;
2179 jv[jss::Account] = alice.
human();
2180 jv[sfNFTokenBrokerFee.fieldName] =
2182 test(jv, sfNFTokenBrokerFee.fieldName);
2187 jv[jss::TransactionType] = jss::NFTokenMint;
2188 jv[jss::Account] = alice.
human();
2189 jv[sfNFTokenTaxon.fieldName] = 1;
2191 test(jv, jss::Amount.c_str());
2194 auto trustSet = [&](
SField const& field) {
2196 jv[jss::TransactionType] = jss::TrustSet;
2197 jv[jss::Account] = alice.
human();
2200 test(jv, field.fieldName);
2202 trustSet(sfLimitAmount);
2207 test(jv, jss::Amount.c_str());
2212 test(jv, jss::Amount.c_str());
2218 test(jv, sfSignatureReward.fieldName);
2232 test(jv, jss::Amount.c_str());
2247 for (
auto const& field :
2248 {sfAmount.fieldName, sfSignatureReward.fieldName})
2257 alice, jvb, alice, mpt,
XRP(10));
2258 for (
auto const& field :
2259 {sfAmount.fieldName, sfSignatureReward.fieldName})
2271 jv[jss::TransactionType] = tt;
2272 jv[jss::Account] = alice.
human();
2273 jv[sfXChainBridge.fieldName] = jvb;
2274 jv[sfSignatureReward.fieldName] =
2276 jv[sfMinAccountCreateAmount.fieldName] =
2280 auto reward =
STAmount{sfSignatureReward, mpt};
2281 auto minAmount =
STAmount{sfMinAccountCreateAmount, USD(10)};
2282 for (
SField const& field :
2284 std::ref(sfMinAccountCreateAmount)})
2287 jss::XChainCreateBridge,
2292 jss::XChainModifyBridge,
2296 reward =
STAmount{sfSignatureReward, USD(10)};
2297 minAmount =
STAmount{sfMinAccountCreateAmount, mpt};
2300 BEAST_EXPECT(txWithAmounts.
empty());