920 using namespace test::jtx;
929 Env env{*
this, features - featureMPTokensV1};
933 env.fund(
XRP(1'000), alice);
934 env.fund(
XRP(1'000), bob);
942 Env env{*
this, features - featureMPTokensV1};
945 auto const USD = alice[
"USD"];
947 env.fund(
XRP(1'000), alice);
948 env.fund(
XRP(1'000), carol);
952 jv[jss::secret] = alice.
name();
953 jv[jss::tx_json] =
pay(alice, carol, mpt);
954 jv[jss::tx_json][jss::Fee] =
to_string(env.current()->fees().base);
955 auto const jrr = env.rpc(
"json",
"submit",
to_string(jv));
956 BEAST_EXPECT(jrr[jss::result][jss::engine_result] ==
"temDISABLED");
961 Env env{*
this, features};
963 MPTTester mptAlice(env, alice, {.holders = {bob}});
965 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
966 auto const MPT = mptAlice[
"MPT"];
968 mptAlice.authorize({.account = bob});
971 env(
pay(alice, bob,
MPT(10)),
978 Env env{*
this, features};
982 MPTTester mptAlice(env, alice, {.holders = {carol}});
984 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
986 mptAlice.authorize({.account = carol});
990 auto const MPT = mptAlice[
"MPT"];
991 env(
pay(alice, carol,
MPT(100)),
994 env(
pay(alice, carol,
MPT(100)),
998 auto const USD = alice[
"USD"];
999 env(
pay(alice, carol, USD(100)),
1002 env(
pay(alice, carol,
XRP(100)),
1005 env(
pay(alice, carol, USD(100)),
1008 env(
pay(alice, carol,
XRP(100)),
1013 "MPT",
makeMptID(env.seq(alice) + 10, alice));
1014 env(
pay(alice, carol, MPT1(100)),
1023 Env env{*
this, features};
1027 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1029 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1030 auto const MPT = mptAlice[
"MPT"];
1032 mptAlice.authorize({.account = carol});
1035 payment[jss::secret] = alice.
name();
1036 payment[jss::tx_json] =
pay(alice, carol,
MPT(100));
1038 payment[jss::build_path] =
true;
1039 auto jrr = env.rpc(
"json",
"submit",
to_string(payment));
1040 BEAST_EXPECT(jrr[jss::result][jss::error] ==
"invalidParams");
1042 jrr[jss::result][jss::error_message] ==
1043 "Field 'build_path' not allowed in this context.");
1048 Env env{*
this, features};
1050 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1052 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1053 auto const MPT = mptAlice[
"MPT"];
1055 mptAlice.authorize({.account = bob});
1056 mptAlice.authorize({.account = carol});
1069 Env env{*
this, features};
1071 MPTTester mptAlice(env, alice, {.holders = {bob}});
1073 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1075 mptAlice.authorize({.account = bob});
1084 Env env{*
this, features};
1086 MPTTester mptAlice(env, alice, {.holders = {bob}});
1088 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1090 mptAlice.authorize({.account = bob});
1103 Env env{*
this, features};
1105 MPTTester mptAlice(env, alice, {.holders = {bob}});
1112 mptAlice.authorize({.account = bob});
1120 Env env{*
this, features};
1122 MPTTester mptAlice(env, alice, {.holders = {bob}});
1130 mptAlice.authorize({.account = bob});
1133 mptAlice.authorize({.account = alice, .holder = bob});
1136 mptAlice.pay(alice, bob, 100);
1147 if (features[featureSingleAssetVault] &&
1148 features[featurePermissionedDomains])
1152 Env env{*
this, features};
1154 Account const credIssuer1{
"credIssuer1"};
1155 env.fund(
XRP(1000), credIssuer1, bob);
1157 auto const domainId1 = [&]() {
1159 {.issuer = credIssuer1, .credType = credType}};
1179 .domainID = domainId1,
1182 mptAlice.authorize({.account = bob});
1186 mptAlice.pay(alice, bob, 100);
1187 mptAlice.set({.domainID = beast::zero});
1194 Env env{*
this, features};
1196 Account const credIssuer1{
"credIssuer1"};
1197 env.fund(
XRP(1000), credIssuer1, bob);
1199 auto const domainId1 = [&]() {
1201 {.issuer = credIssuer1, .credType = credType}};
1221 .domainID = domainId1,
1225 mptAlice.authorize({.account = bob});
1228 mptAlice.authorize({.account = alice, .holder = bob});
1231 mptAlice.pay(alice, bob, 100);
1240 mptAlice.pay(bob, alice, 10);
1242 mptAlice.set({.domainID = beast::zero});
1250 Env env{*
this, features};
1253 Account const credIssuer1{
"credIssuer1"};
1256 Account const credIssuer2{
"credIssuer2"};
1257 env.fund(
XRP(1000), credIssuer1, credIssuer2, bob, carol);
1259 auto const domainId1 = [&]() {
1261 {.issuer = credIssuer1, .credType = credType}};
1270 auto const domainId2 = [&]() {
1272 {.issuer = credIssuer1, .credType = credType},
1273 {.issuer = credIssuer2, .credType = credType}};
1301 .domainID = domainId1,
1305 mptAlice.authorize({.account = bob});
1306 mptAlice.authorize({.account = carol});
1310 mptAlice.pay(alice, bob, 50);
1321 mptAlice.set({.domainID = domainId2});
1323 mptAlice.pay(alice, carol, 10);
1328 mptAlice.pay(bob, carol, 10);
1333 credIssuer1, bob, credIssuer1, credType));
1343 Env env(*
this, features);
1348 MPTTester mptAlice(env, alice, {.holders = {bob, cindy}});
1351 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1354 mptAlice.authorize({.account = bob});
1357 mptAlice.authorize({.account = cindy});
1360 mptAlice.pay(alice, bob, 100);
1367 mptAlice.pay(bob, alice, 10);
1372 Env env{*
this, features};
1374 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1391 Env env{*
this, features};
1393 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1397 mptAlice.authorize({.account = bob});
1398 mptAlice.authorize({.account = carol});
1400 mptAlice.pay(alice, bob, 100);
1411 Env env{*
this, features};
1413 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1418 mptAlice.authorize({.account = bob});
1419 mptAlice.authorize({.account = carol});
1421 mptAlice.pay(alice, bob, 100);
1422 mptAlice.pay(alice, carol, 100);
1425 mptAlice.set({.account = alice, .flags =
tfMPTLock});
1430 mptAlice.pay(alice, bob, 3);
1432 mptAlice.pay(bob, alice, 4);
1435 mptAlice.set({.account = alice, .flags =
tfMPTUnlock});
1437 mptAlice.set({.account = alice, .holder = bob, .flags =
tfMPTLock});
1442 mptAlice.pay(alice, bob, 7);
1444 mptAlice.pay(bob, alice, 8);
1449 Env env{*
this, features};
1451 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1455 {.transferFee = 10'000,
1461 mptAlice.authorize({.account = bob});
1462 mptAlice.authorize({.account = carol});
1465 mptAlice.pay(alice, bob, 2'000);
1468 mptAlice.pay(bob, alice, 1'000);
1469 BEAST_EXPECT(mptAlice.checkMPTokenAmount(bob, 1'000));
1479 auto const MPT = mptAlice[
"MPT"];
1481 env(
pay(bob, carol,
MPT(100)),
1490 BEAST_EXPECT(mptAlice.checkMPTokenAmount(bob, 780));
1491 BEAST_EXPECT(mptAlice.checkMPTokenAmount(carol, 200));
1494 env(
pay(bob, carol,
MPT(100)),
1499 BEAST_EXPECT(mptAlice.checkMPTokenAmount(bob, 690));
1500 BEAST_EXPECT(mptAlice.checkMPTokenAmount(carol, 282));
1505 Env env{*
this, features};
1507 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1513 mptAlice.authorize({.account = bob});
1514 mptAlice.authorize({.account = carol});
1515 mptAlice.pay(alice, bob, 1'000);
1517 auto const MPT = mptAlice[
"MPT"];
1519 env(
pay(bob, carol,
MPT(100)),
1522 env(
pay(bob, alice,
MPT(100)),
1528 BEAST_EXPECT(mptAlice.checkMPTokenAmount(carol, 100));
1530 env(
pay(bob, carol,
MPT(100)),
1533 BEAST_EXPECT(mptAlice.checkMPTokenAmount(carol, 199));
1538 Env env{*
this, features};
1540 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1546 mptAlice.authorize({.account = bob});
1547 mptAlice.authorize({.account = carol});
1548 mptAlice.pay(alice, bob, 1'000);
1550 auto const MPT = mptAlice[
"MPT"];
1553 env(
pay(bob, alice,
MPT(100)),
1559 env(
pay(bob, alice,
MPT(100)),
1567 Env env{*
this, features};
1569 MPTTester mptAlice(env, alice, {.holders = {bob}});
1577 mptAlice.authorize({.account = bob});
1580 mptAlice.pay(alice, bob, 100);
1589 Env env{*
this, features};
1591 MPTTester mptAlice(env, alice, {.holders = {bob}});
1593 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1595 mptAlice.authorize({.account = bob});
1607 Env env{*
this, features};
1608 env.fund(
XRP(1'000), alice, bob);
1611 jv[jss::secret] = alice.
name();
1612 jv[jss::tx_json] =
pay(alice, bob, mpt);
1613 jv[jss::tx_json][jss::Amount][jss::value] =
1615 auto const jrr = env.rpc(
"json",
"submit",
to_string(jv));
1616 BEAST_EXPECT(jrr[jss::result][jss::error] ==
"invalidParams");
1622 Env env{*
this, features};
1624 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1632 auto const MPT = mptAlice[
"MPT"];
1634 mptAlice.authorize({.account = bob});
1635 mptAlice.authorize({.account = carol});
1638 mptAlice.pay(alice, bob, 10'000);
1641 env(
pay(bob, carol,
MPT(10'000)),
1645 auto const meta = env.meta()->getJson(
1649 meta[0u][sfModifiedNode.fieldName][sfFinalFields.fieldName]
1650 [sfOutstandingAmount.fieldName] ==
"9990");
1653 meta[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName]
1654 [sfMPTAmount.fieldName] ==
"9990");
1657 meta[2u][sfModifiedNode.fieldName][sfPreviousFields.fieldName]
1658 [sfMPTAmount.fieldName] ==
"10000");
1660 !meta[2u][sfModifiedNode.fieldName][sfFinalFields.fieldName]
1661 .isMember(sfMPTAmount.fieldName));
1665 env(
pay(bob, carol,
MPT(10'000)),
1672 Env env{*
this, features};
1674 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1681 auto const MPT = mptAlice[
"MPT"];
1683 mptAlice.authorize({.account = bob});
1684 mptAlice.authorize({.account = carol});
1697 BEAST_EXPECT(mptAlice.checkMPTokenOutstandingAmount(0));
1702 Env env{*
this, features};
1704 MPTTester mptAlice(env, alice, {.holders = {bob}});
1706 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1708 mptAlice.authorize({.account = bob});
1711 mptAlice.destroy({.ownerCount = 0});
1720 Env env{*
this, features};
1722 env.fund(
XRP(1'000), alice, bob);
1731 Env env{*
this, features};
1733 MPTTester mptAlice(env, alice, {.holders = {bob}});
1735 mptAlice.
create({.ownerCount = 1, .holderCount = 0});
1738 mptAlice.destroy({.ownerCount = 0});
1748 Env env{*
this, features};
1753 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1758 mptAlice.authorize({.account = bob});
1759 mptAlice.authorize({.account = carol});
1761 mptAlice.pay(alice, bob, 100);
1764 mptAlice.pay(bob, carol, 100);
1769 Env env{*
this, features};
1771 MPTTester mptAlice(env, alice, {.holders = {bob, carol}});
1776 mptAlice.authorize({.account = bob});
1777 mptAlice.authorize({.account = carol});
1780 mptAlice.pay(alice, bob, 100);
1783 mptAlice.pay(bob, alice, 100);
1786 mptAlice.pay(alice, bob, 100);
1787 mptAlice.pay(bob, carol, 50);
1946 testcase(
"MPT Issue Invalid in Transaction");
1947 using namespace test::jtx;
1956 for (
auto const& e : format.getSOTemplate())
1962 e.sField().getName() != jss::Fee &&
1963 format.getName() != jss::SetFee)
1966 format.getName() + e.sField().fieldName);
1973 auto const USD = alice[
"USD"];
1976 STAmount mpt{issue, UINT64_C(100)};
1977 auto const jvb =
bridge(alice, USD, alice, USD);
1978 for (
auto const& feature : {features, features - featureMPTokensV1})
1980 Env env{*
this, feature};
1981 env.fund(
XRP(1'000), alice);
1982 env.fund(
XRP(1'000), carol);
1985 txWithAmounts.
erase(
1986 jv[jss::TransactionType].asString() + mptField);
1989 auto jtx = env.jt(jv);
1994 jrr[jss::result][jss::error] ==
"invalidTransaction");
1998 jv1[jss::secret] = alice.
name();
1999 jv1[jss::tx_json] = jv;
2000 jrr = env.rpc(
"json",
"submit",
to_string(jv1));
2001 BEAST_EXPECT(jrr[jss::result][jss::error] ==
"invalidParams");
2003 jrr = env.rpc(
"json",
"sign",
to_string(jv1));
2004 BEAST_EXPECT(jrr[jss::result][jss::error] ==
"invalidParams");
2006 auto toSFieldRef = [](
SField const& field) {
2009 auto setMPTFields = [&](
SField const& field,
2011 bool withAmount =
true) {
2013 jv[jss::Asset2] =
to_json(USD.issue());
2015 jv[field.fieldName] =
2017 if (field == sfAsset)
2019 else if (field == sfAsset2)
2029 auto ammCreate = [&](
SField const& field) {
2031 jv[jss::TransactionType] = jss::AMMCreate;
2032 jv[jss::Account] = alice.
human();
2033 jv[jss::Amount] = (field.fieldName == sfAmount.fieldName)
2036 jv[jss::Amount2] = (field.fieldName == sfAmount2.fieldName)
2039 jv[jss::TradingFee] = 0;
2040 test(jv, field.fieldName);
2042 ammCreate(sfAmount);
2043 ammCreate(sfAmount2);
2045 auto ammDeposit = [&](
SField const& field) {
2047 jv[jss::TransactionType] = jss::AMMDeposit;
2048 jv[jss::Account] = alice.
human();
2050 setMPTFields(field, jv);
2051 test(jv, field.fieldName);
2053 for (
SField const& field :
2054 {toSFieldRef(sfAmount),
2055 toSFieldRef(sfAmount2),
2056 toSFieldRef(sfEPrice),
2057 toSFieldRef(sfLPTokenOut),
2058 toSFieldRef(sfAsset),
2059 toSFieldRef(sfAsset2)})
2062 auto ammWithdraw = [&](
SField const& field) {
2064 jv[jss::TransactionType] = jss::AMMWithdraw;
2065 jv[jss::Account] = alice.
human();
2067 setMPTFields(field, jv);
2068 test(jv, field.fieldName);
2070 ammWithdraw(sfAmount);
2071 for (
SField const& field :
2072 {toSFieldRef(sfAmount2),
2073 toSFieldRef(sfEPrice),
2074 toSFieldRef(sfLPTokenIn),
2075 toSFieldRef(sfAsset),
2076 toSFieldRef(sfAsset2)})
2079 auto ammBid = [&](
SField const& field) {
2081 jv[jss::TransactionType] = jss::AMMBid;
2082 jv[jss::Account] = alice.
human();
2083 setMPTFields(field, jv);
2084 test(jv, field.fieldName);
2086 for (
SField const& field :
2087 {toSFieldRef(sfBidMin),
2088 toSFieldRef(sfBidMax),
2089 toSFieldRef(sfAsset),
2090 toSFieldRef(sfAsset2)})
2093 auto ammClawback = [&](
SField const& field) {
2095 jv[jss::TransactionType] = jss::AMMClawback;
2096 jv[jss::Account] = alice.
human();
2097 jv[jss::Holder] = carol.
human();
2098 setMPTFields(field, jv);
2099 test(jv, field.fieldName);
2101 for (
SField const& field :
2102 {toSFieldRef(sfAmount),
2103 toSFieldRef(sfAsset),
2104 toSFieldRef(sfAsset2)})
2107 auto ammDelete = [&](
SField const& field) {
2109 jv[jss::TransactionType] = jss::AMMDelete;
2110 jv[jss::Account] = alice.
human();
2111 setMPTFields(field, jv,
false);
2112 test(jv, field.fieldName);
2115 ammDelete(sfAsset2);
2117 auto ammVote = [&](
SField const& field) {
2119 jv[jss::TransactionType] = jss::AMMVote;
2120 jv[jss::Account] = alice.
human();
2121 jv[jss::TradingFee] = 100;
2122 setMPTFields(field, jv,
false);
2123 test(jv, field.fieldName);
2128 auto checkCash = [&](
SField const& field) {
2130 jv[jss::TransactionType] = jss::CheckCash;
2131 jv[jss::Account] = alice.
human();
2134 test(jv, field.fieldName);
2136 checkCash(sfAmount);
2137 checkCash(sfDeliverMin);
2141 jv[jss::TransactionType] = jss::CheckCreate;
2142 jv[jss::Account] = alice.
human();
2143 jv[jss::Destination] = carol.
human();
2145 test(jv, jss::SendMax.c_str());
2150 test(jv, jss::TakerPays.c_str());
2151 jv =
offer(alice, mpt, USD(100));
2152 test(jv, jss::TakerGets.c_str());
2157 jv[jss::TransactionType] = jss::PaymentChannelCreate;
2158 jv[jss::Account] = alice.
human();
2159 jv[jss::Destination] = carol.
human();
2160 jv[jss::SettleDelay] = 1;
2163 test(jv, jss::Amount.c_str());
2168 jv[jss::TransactionType] = jss::PaymentChannelFund;
2169 jv[jss::Account] = alice.
human();
2172 test(jv, jss::Amount.c_str());
2177 jv[jss::TransactionType] = jss::PaymentChannelClaim;
2178 jv[jss::Account] = alice.
human();
2181 test(jv, jss::Amount.c_str());
2186 jv[jss::TransactionType] = jss::NFTokenCreateOffer;
2187 jv[jss::Account] = alice.
human();
2190 test(jv, jss::Amount.c_str());
2195 jv[jss::TransactionType] = jss::NFTokenAcceptOffer;
2196 jv[jss::Account] = alice.
human();
2197 jv[sfNFTokenBrokerFee.fieldName] =
2199 test(jv, sfNFTokenBrokerFee.fieldName);
2204 jv[jss::TransactionType] = jss::NFTokenMint;
2205 jv[jss::Account] = alice.
human();
2206 jv[sfNFTokenTaxon.fieldName] = 1;
2208 test(jv, jss::Amount.c_str());
2211 auto trustSet = [&](
SField const& field) {
2213 jv[jss::TransactionType] = jss::TrustSet;
2214 jv[jss::Account] = alice.
human();
2217 test(jv, field.fieldName);
2219 trustSet(sfLimitAmount);
2224 test(jv, jss::Amount.c_str());
2229 test(jv, jss::Amount.c_str());
2235 test(jv, sfSignatureReward.fieldName);
2249 test(jv, jss::Amount.c_str());
2264 for (
auto const& field :
2265 {sfAmount.fieldName, sfSignatureReward.fieldName})
2274 alice, jvb, alice, mpt,
XRP(10));
2275 for (
auto const& field :
2276 {sfAmount.fieldName, sfSignatureReward.fieldName})
2288 jv[jss::TransactionType] = tt;
2289 jv[jss::Account] = alice.
human();
2290 jv[sfXChainBridge.fieldName] = jvb;
2291 jv[sfSignatureReward.fieldName] =
2293 jv[sfMinAccountCreateAmount.fieldName] =
2297 auto reward =
STAmount{sfSignatureReward, mpt};
2298 auto minAmount =
STAmount{sfMinAccountCreateAmount, USD(10)};
2299 for (
SField const& field :
2301 std::ref(sfMinAccountCreateAmount)})
2304 jss::XChainCreateBridge,
2309 jss::XChainModifyBridge,
2313 reward =
STAmount{sfSignatureReward, USD(10)};
2314 minAmount =
STAmount{sfMinAccountCreateAmount, mpt};
2317 BEAST_EXPECT(txWithAmounts.
empty());