1#include <test/jtx/AMM.h>
2#include <test/jtx/AMMTest.h>
3#include <test/jtx/Env.h>
4#include <test/jtx/PathSet.h>
5#include <test/jtx/TestHelpers.h>
6#include <test/jtx/amount.h>
7#include <test/jtx/balance.h>
8#include <test/jtx/delivermin.h>
9#include <test/jtx/fee.h>
10#include <test/jtx/flags.h>
11#include <test/jtx/jtx_json.h>
12#include <test/jtx/mpt.h>
13#include <test/jtx/multisign.h>
14#include <test/jtx/noop.h>
15#include <test/jtx/offer.h>
16#include <test/jtx/owners.h>
17#include <test/jtx/paths.h>
18#include <test/jtx/pay.h>
19#include <test/jtx/regkey.h>
20#include <test/jtx/require.h>
21#include <test/jtx/sendmax.h>
22#include <test/jtx/sig.h>
23#include <test/jtx/tags.h>
24#include <test/jtx/ter.h>
25#include <test/jtx/txflags.h>
27#include <xrpl/beast/unit_test/suite.h>
28#include <xrpl/json/json_value.h>
29#include <xrpl/json/to_string.h>
30#include <xrpl/ledger/ApplyView.h>
31#include <xrpl/ledger/OpenView.h>
32#include <xrpl/ledger/PaymentSandbox.h>
33#include <xrpl/ledger/Sandbox.h>
34#include <xrpl/ledger/helpers/OfferHelpers.h>
35#include <xrpl/protocol/AccountID.h>
36#include <xrpl/protocol/Feature.h>
37#include <xrpl/protocol/Indexes.h>
38#include <xrpl/protocol/Issue.h>
39#include <xrpl/protocol/KeyType.h>
40#include <xrpl/protocol/Quality.h>
41#include <xrpl/protocol/SField.h>
42#include <xrpl/protocol/STPathSet.h>
43#include <xrpl/protocol/Seed.h>
44#include <xrpl/protocol/TER.h>
45#include <xrpl/protocol/TxFlags.h>
46#include <xrpl/protocol/UintTypes.h>
47#include <xrpl/protocol/XRPAmount.h>
48#include <xrpl/protocol/jss.h>
49#include <xrpl/tx/paths/Flow.h>
50#include <xrpl/tx/paths/detail/Steps.h>
67 testcase(
"Incorrect Removal of Funded Offers");
79 Env env{*
this, features};
87 .pay = 200'000'000'000'000'000,
94 .pay = 2'000'000'000'000'000,
109 AMM const ammCarol(env,
carol_, btc(1'000'000'000'000'000), eth(100'100'000'000'000'000));
115 Sendmax(btc(1'000'000'000'000'000)),
119 btc(1'001'000'000'374'816), eth(100'000'000'000'000'000), ammCarol.
tokens()));
131 auto const startBalance =
XRP(1'000'000);
137 [&](
AMM& ammAlice,
Env& env) {
138 auto const& btc =
MPT(ammAlice[1]);
139 auto const baseFee = env.
current()->fees().base;
168 [&](
AMM& ammAlice,
Env& env) {
169 auto const& btc =
MPT(ammAlice[1]);
170 auto const baseFee = env.
current()->fees().base;
192 [&](
AMM& ammAlice,
Env& env) {
195 auto const& btc =
MPT(ammAlice[1]);
208 [&](
AMM& ammAlice,
Env& env) {
209 auto const& btc =
MPT(ammAlice[1]);
230 testcase(
"Offer Crossing with XRP, Normal order");
234 Env env{*
this, features};
245 AMM const ammAlice(env,
alice_,
XRP(150'000), btc(50'000'000));
250 auto const xrpTransferred =
XRPAmount{3'061'224'490};
253 BEAST_EXPECT(ammAlice.expectBalances(
254 XRP(150'000) + xrpTransferred, btc(49'000'000),
IOUAmount{273'861'278752583, -5}));
265 testcase(
"Offer Crossing with Limit Override");
269 Env env{*
this, features};
278 AMM const ammAlice(env,
alice_,
XRP(150'000), btc(51'000'000));
290 testcase(
"Currency Conversion: Entire Offer");
294 Env env{*
this, features};
306 AMM const ammBob(env,
bob_, btc(200'000'000),
XRP(1'500));
320 testcase(
"Currency Conversion: In Parts");
324 Env env{*
this, features};
332 .pay = 30'000'000'000,
336 AMM const ammAlice(env,
alice_,
XRP(10'000), btc(10'000'000'000));
361 testcase(
"Cross Currency Payment: Start with XRP");
365 Env env{*
this, features};
374 AMM const ammAlice(env,
alice_,
XRP(10'000), btc(10'100'000'000));
385 testcase(
"Cross Currency Payment: End with XRP");
389 Env env{*
this, features};
398 AMM const ammAlice(env,
alice_,
XRP(10'100), btc(10'000'000'000));
409 testcase(
"Cross Currency Payment: Bridged");
413 auto test = [&](
auto&& issue1,
auto&& issue2) {
415 auto const dan =
Account{
"dan"};
418 auto const eth = issue1(
423 .limit = 10'000'000'000'000'000});
424 auto const btc = issue2(
429 .limit = 10'000'000'000'000'000});
432 env(
pay(
gw_, dan, eth(400'000'000'000'000)));
435 AMM const ammCarol(env,
carol_, btc(5'000'000'000'000'000),
XRP(50'000));
437 env(
offer(dan,
XRP(500), eth(50'000'000'000'000)));
441 jtp[0u][0u][jss::currency] =
"XRP";
443 Json(jss::Paths, jtp),
444 Sendmax(btc(333'000'000'000'000)));
447 XRP(49'700), btc(5'030'181'086'519'115), ammCarol.
tokens()));
457 testcase(
"Offer Fees Consume Funds");
461 Env env{*
this, features};
465 auto const startingXrp =
466 XRP(100) + env.
current()->fees().accountReserve(2) + env.
current()->fees().base * 3;
479 env(
pay(
gw_,
bob_, btc(1'200'000'000'000'000)));
481 AMM const ammBob(env,
bob_,
XRP(1'000), btc(1'200'000'000'000'000));
498 testcase(
"Offer Create, then Cross");
502 Env env{*
this, features};
516 AMM const ammAlice(env,
alice_, btc(150'000'000'000'000),
XRP(150'100));
529 testcase(
"Offer tfSell: Basic Sell");
533 Env env{*
this, features};
545 AMM const ammAlice(env,
alice_,
XRP(9'900), btc(10'100));
559 testcase(
"Offer tfSell: 2x Sell Exceed Limit");
563 Env env{*
this, features};
565 auto const startingXrp =
XRP(100) +
reserve(env, 1) + env.
current()->fees().base * 2;
575 AMM const ammBob(env,
bob_,
XRP(1'000), btc(2'200'000'000));
591 testcase(
"Client Issue: Gateway Cross Currency");
595 Env env{*
this, features};
597 auto const startingXrp =
XRP(100.1) +
reserve(env, 1) + env.
current()->fees().base * 2;
604 .pay = 1'000'000'000'000'000,
610 .pay = 1'000'000'000'000'000,
613 AMM const ammAlice(env,
alice_, xts(1'000'000'000'000'000), xxx(1'000'000'000'000'000));
617 payment[jss::id] = env.
seq(
bob_);
618 payment[jss::build_path] =
true;
619 payment[jss::tx_json] =
pay(
bob_,
bob_, xxx(10'000'000'000'000));
620 payment[jss::tx_json][jss::Sequence] =
623 payment[jss::tx_json][jss::SendMax] =
625 payment[jss::tx_json][jss::Flags] = tfPartialPayment;
626 auto const jrr = env.
rpc(
"json",
"submit",
to_string(payment));
627 BEAST_EXPECT(jrr[jss::result][jss::status] ==
"success");
628 BEAST_EXPECT(jrr[jss::result][jss::engine_result] ==
"tesSUCCESS");
630 BEAST_EXPECT(ammAlice.expectBalances(
631 xts(1'010'101'010'101'011), xxx(990'000'000'000'000), ammAlice.tokens()));
644 Env env{*
this, features};
651 .pay = 15'000'000'000,
657 .pay = 15'000'000'000,
666 AMM const ammAlice(env,
alice_,
XRP(10'000), btc(10'100'000'000));
667 AMM const ammBob(env,
bob_, eth(10'000'000'000),
XRP(10'100));
671 env(
offer(
carol_, btc(100'000'000), eth(100'000'000)));
675 ammAlice.expectBalances(
XRP(10'100), btc(10'000'000'000), ammAlice.tokens()));
683 Env env{*
this, features};
690 .pay = 15'000'000'000,
696 .pay = 15'000'000'000,
706 AMM const ammAlice(env,
alice_,
XRP(10'000), btc(10'100'000'000));
712 env(
offer(
carol_, btc(100'000'000), eth(100'000'000)));
716 ammAlice.expectBalances(
XRP(10'100), btc(10'000'000'000), ammAlice.tokens()));
724 Env env{*
this, features};
731 .pay = 15'000'000'000,
737 .pay = 15'000'000'000,
749 AMM const ammBob(env,
bob_, eth(10'000'000'000),
XRP(10'100));
753 env(
offer(
carol_, btc(100'000'000), eth(100'000'000)));
769 testcase(
"Combine tfSell with tfFillOrKill");
774 Env env{*
this, features};
781 .pay = 20'000'000'000,
783 AMM const ammBob(env,
bob_,
XRP(20'000), btc(200'000'000));
787 BEAST_EXPECT(ammBob.expectBalances(
XRP(20'000), btc(200'000'000), ammBob.tokens()));
791 Env env{*
this, features};
798 .pay = 1'000'000'000'000'000,
800 AMM const ammBob(env,
bob_,
XRP(20'000), btc(200'000'000'000'000));
803 env(
offer(
alice_, btc(2'000'000'000'000),
XRP(220), tfSell | tfFillOrKill));
806 ammBob.expectBalances(
XRP(20'220), btc(197'823'936'696'341), ammBob.tokens()));
813 Env env{*
this, features};
820 .pay = 1'000'000'000'000'000,
822 AMM const ammBob(env,
bob_,
XRP(20'000), btc(200'000'000'000'000));
824 env(
offer(
alice_, btc(10'000'000'000'000),
XRP(1'500), tfSell | tfFillOrKill));
828 ammBob.expectBalances(
XRP(21'500), btc(186'046'511'627'907), ammBob.tokens()));
838 Env env{*
this, features};
845 .pay = 10'000'000'000,
847 AMM const ammBob(env,
bob_,
XRP(5000), btc(10'000'000));
865 Env env(*
this, features);
873 .transferFee = 25'000,
878 AMM const ammAlice(env,
alice_,
XRP(10'000), btc(10'100'000));
891 Env env(*
this, features);
899 .transferFee = 25'000,
904 AMM const ammAlice(env,
alice_,
XRP(10'100), btc(10'000'000));
918 Env env{*
this, features};
925 .transferFee = 25'000,
932 .transferFee = 25'000,
942 AMM const ammAlice(env,
alice_,
XRP(10'000), btc(10'100'000));
952 BEAST_EXPECT(ammAlice.expectBalances(
XRP(10'100), btc(10'000'000), ammAlice.tokens()));
963 Env env{*
this, features};
970 .transferFee = 25'000,
977 .transferFee = 25'000,
987 AMM const ammAlice(env,
alice_,
XRP(10'000), btc(10'050'000));
1000 BEAST_EXPECT(ammAlice.expectBalances(
XRP(10'050), btc(10'000'000), ammAlice.tokens()));
1015 using namespace jtx;
1017 Env env{*
this, features};
1019 auto const f = env.
current()->fees().base;
1027 AMM const ammBob(env,
bob_,
XRP(10'000), btc(10'100));
1032 BEAST_EXPECT(ammBob.expectBalances(
XRP(10'100), btc(10'000), ammBob.tokens()));
1046 using namespace jtx;
1048 Env env{*
this, features};
1050 auto const ann =
Account(
"ann");
1051 auto const bob =
Account(
"bob");
1052 auto const cam =
Account(
"cam");
1053 auto const carol =
Account(
"carol");
1055 auto const fee = env.
current()->fees().base;
1057 env.
fund(
reserve(env, 4) + (fee * 5), ann, bob, cam);
1061 {.env = env, .issuer = ann, .holders = {bob, cam, carol}, .flags =
kMptDexFlags});
1064 {.env = env, .issuer = bob, .holders = {ann, cam, carol}, .flags =
kMptDexFlags});
1066 env(
pay(ann, cam, aBux(350'000'000'000'000)));
1067 env(
pay(bob, cam, bBux(350'000'000'000'000)));
1068 env(
pay(bob, carol, bBux(4'000'000'000'000'000)));
1069 env(
pay(ann, carol, aBux(4'000'000'000'000'000)));
1071 AMM const ammCarol(env, carol, aBux(3'000'000'000'000'000), bBux(3'300'000'000'000'000));
1076 env(
offer(cam, aBux(290'000'000'000'000), bBux(300'000'000'000'000), tfPassive));
1083 env(
offer(cam, bBux(300'000'000'000'000), aBux(300'000'000'000'000)));
1087 aBux(3'093'541'659'651'604), bBux(3'200'215'509'984'418), ammCarol.
tokens()));
1089 env, cam, 1, {{
Amounts{bBux(200'215'509'984'418), aBux(200'215'509'984'419)}}}));
1097 using namespace jtx;
1099 Env env{*
this, features};
1110 btc.authorize({.holder =
bob_});
1116 AMM const ammAlice(env,
alice_, btc(1'000),
XRP(1'050));
1137 using namespace jtx;
1139 Env env{*
this, features};
1170 AMM const ammAlice(env,
alice_, btc(1'000),
XRP(1'050));
1188 using namespace jtx;
1217 using namespace jtx;
1227 .pay = 100'000'000'000'000,
1230 AMM const ammCarol(env,
carol_,
XRP(100), eth(100'000'000'000'000));
1237 BEAST_EXPECT(st.
empty());
1241 BEAST_EXPECT(sa ==
XRP(100'000'000));
1244 BEAST_EXPECT(
equal(da, eth(99'999'900'000'100)));
1254 using namespace jtx;
1264 .transferFee = 10'000,
1271 .transferFee = 10'000,
1284 BEAST_EXPECT(std::get<0>(result).empty());
1291 using namespace jtx;
1292 auto const charlie =
Account(
"charlie");
1302 .pay = 11'000'000'000'000,
1305 AMM const ammCharlie(env, charlie,
XRP(10), eth(11'000'000'000'000));
1307 BEAST_EXPECT(sa ==
XRP(1));
1308 BEAST_EXPECT(
equal(da, eth(1'000'000'000'000)));
1309 if (BEAST_EXPECT(st.size() == 1 && st[0].size() == 1))
1311 auto const& pathElem = st[0][0];
1313 pathElem.isOffer() && pathElem.getIssuerID() ==
gw_.id() &&
1314 pathElem.getMPTID() == eth.issuanceID());
1326 .pay = 11'000'000'000'000,
1329 AMM const ammCharlie(env, charlie,
XRP(11), eth(10'000'000'000'000));
1333 BEAST_EXPECT(sa == eth(1'000'000'000'000));
1335 if (BEAST_EXPECT(st.size() == 1 && st[0].size() == 1))
1337 auto const& pathElem = st[0][0];
1339 pathElem.isOffer() && pathElem.getIssuerID() ==
xrpAccount() &&
1348 testcase(
"Path Find: XRP -> XRP and XRP -> MPT");
1349 using namespace jtx;
1361 env.
fund(
XRP(1'000), a3, g1, g2, g3);
1366 {.env = env, .issuer = g1, .holders = {a1, m1, a2}, .flags =
kMptDexFlags});
1369 {.env = env, .issuer = g2, .holders = {a2, m1, a1}, .flags =
kMptDexFlags});
1372 {.env = env, .issuer = g3, .holders = {a1, a2, m1, a3}, .flags =
kMptDexFlags});
1375 {.env = env, .issuer = a2, .holders = {g3, a1}, .flags =
kMptDexFlags});
1377 env(
pay(g1, a1, xyzG1(3'500'000'000)));
1378 env(
pay(g3, a1, abcG3(1'200'000'000)));
1379 env(
pay(g1, m1, xyzG1(25'000'000'000)));
1380 env(
pay(g2, m1, xyzG2(25'000'000'000)));
1381 env(
pay(g3, m1, abcG3(25'000'000'000)));
1382 env(
pay(a2, g3, abcA2(101'000'000)));
1385 AMM const ammM1XyzG1XyzG2(env, m1, xyzG1(1'000'000'000), xyzG2(1'000'000'000));
1386 AMM const ammM1XrpAbcG3(env, m1,
XRP(10'000), abcG3(1'000'000'000));
1387 AMM const ammG3AbcG3AbcA2(env, g3, abcG3(100'000'000), abcA2(101'000'000));
1394 auto const& sendAmt =
XRP(10);
1396 BEAST_EXPECT(
equal(da, sendAmt));
1397 BEAST_EXPECT(st.
empty());
1403 auto const& sendAmt =
XRP(200);
1406 BEAST_EXPECT(
equal(da, sendAmt));
1407 BEAST_EXPECT(st.
empty());
1411 auto const& sendAmt = abcG3(10'000'000);
1413 BEAST_EXPECT(
equal(da, sendAmt));
1419 auto const& sendAmt = abcA2(1'000'000);
1421 BEAST_EXPECT(
equal(da, sendAmt));
1430 testcase(
"Path Find: non-XRP -> XRP");
1431 using namespace jtx;
1438 env.
fund(
XRP(1'000), a1, a2, g3);
1445 .holders = {a1, a2, m1},
1446 .pay = 1'000'000'000,
1449 AMM const ammM1(env, m1, eth(1'000'000'000),
XRP(10'010));
1454 auto const& sendAmt =
XRP(10);
1458 BEAST_EXPECT(
equal(da, sendAmt));
1459 BEAST_EXPECT(
equal(sa, eth(1'000'000)));
1466 testcase(
"Path Find: non-XRP -> non-XRP, same issuanceID");
1467 using namespace jtx;
1478 env.
fund(
XRP(1'000), a1, a2, a3, g1, g2);
1484 .holders = {a1, m1},
1485 .pay = 5'000'000'000,
1491 .holders = {a2, m1},
1492 .pay = 5'000'000'000,
1495 AMM const ammM1(env, m1, hkdG1(1'000'000'000), hkdG2(1'010'000'000));
1497 auto const& sendAmt = hkdG2(10'000'000);
1501 env, g1, a2, sendAmt, std::nullopt, hkdG1.issuanceID(), std::nullopt, std::nullopt);
1502 BEAST_EXPECT(
equal(da, sendAmt));
1503 BEAST_EXPECT(
equal(sa, hkdG1(10'000'000)));
1513 using namespace jtx;
1515 Env env(*
this, features);
1520 auto const ammxrpPool = env.
current()->fees().increment * 2;
1541 AMM const ammBob(env,
bob_, ammxrpPool, btc(150'000));
1546 Txflags(tfNoRippleDirect | tfPartialPayment));
1549 BEAST_EXPECT(carolBTC > btc(0) && carolBTC < btc(50'000));
1557 using namespace jtx;
1561 auto test = [&](
auto&& issue1,
auto&& issue2) {
1565 auto const eth = issue1(
1570 .limit = 100'000'000});
1571 auto const btc = issue2(
1576 .limit = 100'000'000});
1584 AMM const ammBob(env,
bob_, btc(100'000), eth(150'000));
1599 Env env(*
this, features);
1616 AMM const ammBobBtcXrp(env,
bob_, btc(100'000),
XRP(150));
1617 AMM const ammBobXrpEth(env,
bob_,
XRP(100), eth(150'000));
1626 ammBobBtcXrp.expectBalances(btc(150'000),
XRP(100), ammBobBtcXrp.tokens()));
1632 Env env(*
this, features);
1643 AMM const ammBob(env,
bob_,
XRP(100), eth(150'000));
1651 BEAST_EXPECT(ammBob.expectBalances(
XRP(150), eth(100'000), ammBob.tokens()));
1655 Env env(*
this, features);
1666 AMM const ammBob(env,
bob_, eth(100'000),
XRP(150));
1675 BEAST_EXPECT(ammBob.expectBalances(eth(150'000),
XRP(100), ammBob.tokens()));
1680 auto test = [&](
auto&& issue1,
auto&& issue2,
auto&& issue3) {
1681 Env env(*
this, features);
1684 auto const btc = issue1(
1689 .limit = 1000'000000});
1690 auto const eth = issue2(
1695 .limit = 1000'000000});
1696 auto const gbp = issue3(
1701 .limit = 1000'000000});
1706 env(
offer(
bob_, btc(50'000), eth(50'000)));
1707 env(
offer(
bob_, btc(40'000), gbp(50'000)));
1709 AMM const ammBob(env,
bob_, gbp(100'000), eth(150'000));
1713 BEAST_EXPECT(
isOffer(env,
bob_, btc(50'000), eth(50'000)));
1714 BEAST_EXPECT(
isOffer(env,
bob_, btc(40'000), gbp(50'000)));
1725 BEAST_EXPECT(!
isOffer(env,
bob_, btc(50'000), eth(50'000)));
1727 BEAST_EXPECT(!
isOffer(env,
bob_, btc(40'000), gbp(50'000)));
1744 Env env(*
this, features);
1778 AMM const ammBobBtcEth(env,
bob_, btc(50'000'000), eth(50'000'000));
1779 env(
offer(
bob_, btc(60'000'000), gbp(50'000'000)));
1780 env(
offer(
carol_, btc(1'000'000'000), gbp(1'000'000)));
1781 env(
offer(
bob_, gbp(50'000'000), eth(50'000'000)));
1786 btc(50'000'000), eth(50'000'000), ammBobBtcEth.
tokens()));
1787 BEAST_EXPECT(
isOffer(env,
bob_, btc(60'000'000), gbp(50'000'000)));
1788 BEAST_EXPECT(
isOffer(env,
carol_, btc(1'000'000'000), gbp(1'000'000)));
1789 BEAST_EXPECT(
isOffer(env,
bob_, gbp(50'000'000), eth(50'000'000)));
1792 auto const flowResult = [&] {
1793 STAmount const deliver(eth(51'000'000));
1829 BEAST_EXPECT(flowResult.removableOffers.size() == 1);
1831 if (flowResult.removableOffers.empty())
1834 for (
auto const& o : flowResult.removableOffers)
1847 btc(50'000'000), eth(50'000'000), ammBobBtcEth.
tokens()));
1848 BEAST_EXPECT(
isOffer(env,
carol_, btc(1'000'000'000), gbp(1'000'000)));
1850 BEAST_EXPECT(!
isOffer(env,
bob_, btc(60'000'000), gbp(50'000'000)));
1861 auto test = [&](
auto&& issue1,
auto&& issue2) {
1865 auto const eth = issue1(
1870 .limit = 10'000'000});
1871 auto const btc = issue2(
1876 .limit = 10'000'000});
1889 Txflags(tfNoRippleDirect | tfPartialPayment));
1892 BEAST_EXPECT(ammBob.expectBalances(eth(8400),
XRPAmount{20}, ammBob.tokens()));
1902 using namespace jtx;
1906 Env env(*
this, features);
1913 .transferFee = 25'000,
1914 .pay = 1'000'000'000'000'000,
1921 .transferFee = 25'000,
1922 .pay = 1'000'000'000'000'000,
1925 AMM const amm(env,
bob_, gbp(1'000'000'000'000'000), btc(1'000'000'000'000'000));
1929 Sendmax(gbp(150'000'000'000'000)),
1930 Txflags(tfNoRippleDirect | tfPartialPayment));
1937 BEAST_EXPECT(
amm.expectBalances(
1938 gbp(1'120'000'000'000'000), btc(892'857'142'857'143),
amm.tokens()));
1946 Env env(*
this, features);
1955 .transferFee = 25'000,
1956 .pay = 1'000'000'000'000'000,
1963 .transferFee = 25'000,
1964 .pay = 1'000'000'000'000'000,
1971 .transferFee = 25'000,
1972 .pay = 1'000'000'000'000'000,
1975 env(
offer(ed, gbp(1'000'000'000'000'000), eth(1'000'000'000'000'000)),
1979 AMM const amm(env,
bob_, eth(1'000'000'000'000'000), btc(1'000'000'000'000'000));
1983 Sendmax(gbp(150'000'000'000'000)),
1984 Txflags(tfNoRippleDirect | tfPartialPayment));
1996 env, ed, 1, {
Amounts{gbp(880'000'000'000'000), eth(880'000'000'000'000)}}));
1999 BEAST_EXPECT(
amm.expectBalances(
2000 eth(1'096'000'000'000'000), btc(912'408'759'124'088),
amm.tokens()));
2007 Env env(*
this, features);
2016 .transferFee = 25'000,
2017 .pay = 1'000'000'000'000'000,
2024 .transferFee = 25'000,
2025 .pay = 1'000'000'000'000'000,
2032 .transferFee = 25'000,
2033 .pay = 1'000'000'000'000'000,
2036 AMM const amm1(env,
bob_, gbp(1'000'000'000'000'000), eth(1'000'000'000'000'000));
2037 AMM const amm2(env, ed, eth(1'000'000'000'000'000), btc(1'000'000'000'000'000));
2041 Sendmax(gbp(150'000'000'000'000)),
2042 Txflags(tfNoRippleDirect | tfPartialPayment));
2050 BEAST_EXPECT(amm1.expectBalances(
2051 gbp(1'120'000'000'000'000), eth(892'857'142'857'143), amm1.tokens()));
2055 eth(1'085'714'285'714'285), btc(921'052'631'578'948), amm2.
tokens()));
2063 Env env(*
this, features);
2071 .transferFee = 25'000,
2079 .transferFee = 25'000,
2083 AMM const amm(env,
bob_, btc(1'000'000), eth(1'100'000));
2088 BEAST_EXPECT(
amm.expectBalances(btc(1'100'000), eth(1'000'000),
amm.tokens()));
2096 Env env(*
this, features);
2104 .transferFee = 25'000,
2105 .pay = 1'000'000'000'000'000,
2112 .transferFee = 25'000,
2113 .pay = 1'000'000'000'000'000,
2116 AMM const amm(env,
bob_, gbp(1'000'000'000'000'000), btc(1'000'000'000'000'000));
2122 Sendmax(gbp(178'580'000'000'000)),
2123 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2131 BEAST_EXPECT(
amm.expectBalances(
2132 gbp(1'142'857'142'857'143), btc(875'000'000'000'000),
amm.tokens()));
2140 Env env(*
this, features);
2148 .transferFee = 25'000,
2149 .pay = 1'200'000'000'000'000,
2156 .transferFee = 25'000,
2157 .pay = 1'200'000'000'000'000,
2160 AMM const amm(env,
bob_, gbp(1'000'000'000'000'000), btc(1'200'000'000'000'000));
2166 Sendmax(gbp(120'000'000'000'000)),
2167 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2175 BEAST_EXPECT(
amm.expectBalances(
2176 gbp(1'024'000'000'000'000), btc(1'171'875'000'000'000),
amm.tokens()));
2185 Env env(*
this, features);
2194 .transferFee = 25'000,
2195 .pay = 1'400'000'000'000'000,
2202 .transferFee = 25'000,
2203 .pay = 1'400'000'000'000'000,
2210 .transferFee = 25'000,
2211 .pay = 1'400'000'000'000'000,
2214 env(
offer(ed, gbp(1'000'000'000'000'000), eth(1'000'000'000'000'000)),
2218 AMM const amm(env,
bob_, eth(1'000'000'000'000'000), btc(1'400'000'000'000'000));
2224 Sendmax(gbp(140'000'000'000'000)),
2225 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2238 env, ed, 1, {
Amounts{gbp(929'578'947'368'420), eth(929'578'947'368'420)}}));
2241 BEAST_EXPECT(
amm.expectBalances(
2242 eth(1'056'336'842'105'264), btc(1'325'334'821'428'571),
amm.tokens()));
2251 Env env(*
this, features);
2260 .transferFee = 25'000,
2261 .pay = 1'400'000'000'000'000,
2268 .transferFee = 25'000,
2269 .pay = 1'400'000'000'000'000,
2276 .transferFee = 25'000,
2277 .pay = 1'400'000'000'000'000,
2280 AMM const amm(env,
bob_, gbp(1'000'000'000'000'000), eth(1'000'000'000'000'000));
2282 env(
offer(ed, eth(1'000'000'000'000'000), btc(1'400'000'000'000'000)),
2290 Sendmax(gbp(140'000'000'000'000)),
2291 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2302 BEAST_EXPECT(
amm.expectBalances(
2303 gbp(1'056'336'842'105'264), eth(946'667'729'591'836),
amm.tokens()));
2310 env, ed, 1, {
Amounts{eth(957'334'183'673'469), btc(1'340'267'857'142'857)}}));
2318 Env env(*
this, features);
2327 .transferFee = 25'000,
2328 .pay = 1'400'000'000'000'000,
2335 .transferFee = 25'000,
2336 .pay = 1'400'000'000'000'000,
2343 .transferFee = 25'000,
2344 .pay = 1'400'000'000'000'000,
2347 AMM const amm1(env,
bob_, gbp(1'000'000'000'000'000), eth(1'000'000'000'000'000));
2348 AMM const amm2(env, ed, eth(1'000'000'000'000'000), btc(1'400'000'000'000'000));
2354 Sendmax(gbp(145'000'000'000'000)),
2355 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2364 BEAST_EXPECT(amm1.expectBalances(
2365 gbp(1'086'024'691'358'028), eth(920'789'377'955'618), amm1.tokens()));
2369 eth(1'063'368'497'635'505), btc(1'316'570'881'226'053), amm2.
tokens()));
2378 Env env(*
this, features);
2386 .transferFee = 25'000,
2387 .pay = 1'400'000'000'000'000,
2394 .transferFee = 25'000,
2395 .pay = 1'400'000'000'000'000,
2402 .transferFee = 25'000,
2403 .pay = 1'400'000'000'000'000,
2406 AMM const amm1(env,
alice_, gbp(1'000'000'000'000'000), eth(1'000'000'000'000'000));
2407 AMM const amm2(env,
bob_, eth(1'000'000'000'000'000), btc(1'400'000'000'000'000));
2413 Sendmax(gbp(120'000'000'000'000)),
2414 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2418 BEAST_EXPECT(amm1.expectBalances(
2419 gbp(1'108'148'148'148'150), eth(902'406'417'112'298), amm1.tokens()));
2423 eth(1'078'074'866'310'161), btc(1'298'611'111'111'111), amm2.
tokens()));
2439 using namespace jtx;
2452 AMM const ammBob(env,
bob_,
XRP(1'000), eth(1'050'000));
2458 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2460 BEAST_EXPECT(ammBob.expectBalances(
XRP(1'050), eth(1'000'000), ammBob.tokens()));
2471 using namespace jtx;
2475 auto test = [&](
auto&& issue1,
auto&& issue2) {
2479 auto const eth = issue1(
2484 .limit = 2000'000});
2485 auto const btc = issue2(
2490 .limit = 2000'000});
2498 AMM const ammAliceXrpBtc(env,
alice_,
XRP(100), btc(101'000));
2499 AMM const ammAliceXrpEth(env,
alice_,
XRP(100), eth(101'000));
2511 auto test = [&](
auto&& issue1,
auto&& issue2) {
2515 auto const eth = issue1(
2520 .limit = 2000'000});
2521 auto const btc = issue2(
2526 .limit = 2000'000});
2534 AMM const ammAliceXrpBtc(env,
alice_,
XRP(100), btc(100'000));
2535 AMM const ammAliceXrpEth(env,
alice_,
XRP(100), eth(100'000));
2549 auto test = [&](
auto&& issue1,
auto&& issue2,
auto&& issue3) {
2553 auto const eth = issue1(
2558 .limit = 2000'000});
2559 auto const btc = issue2(
2564 .limit = 2000'000});
2565 auto const jpy = issue2(
2570 .limit = 2000'000});
2580 AMM const ammAliceXrpBtc(env,
alice_,
XRP(100), btc(100'000));
2581 AMM const ammAliceXrpEth(env,
alice_,
XRP(100), eth(100'000));
2582 AMM const ammAliceXrpJpy(env,
alice_,
XRP(100), jpy(100'000));
2599 using namespace jtx;
2601 Env env(*
this, features);
2602 auto const dan =
Account(
"dan");
2603 auto const ed =
Account(
"ed");
2610 env(
pay(
gw_, ed, btc(11'000'000'000'000)));
2612 env(
pay(
gw_, dan, btc(1'000'000'000'000)));
2615 nOffers(env, 1, dan,
XRP(1), btc(1'000'000'000'000));
2616 AMM const ammEd(env, ed,
XRP(9), btc(11'000'000'000'000));
2642 Env env(*
this, features);
2643 auto const dan =
Account(
"dan");
2644 auto const ed =
Account(
"ed");
2653 .pay = 10000'000'000,
2656 env.
trust(
BTC(11'000'000'000'000), ed);
2657 env(
pay(
gw_, ed,
BTC(11'000'000'000'000)));
2660 env.
trust(
BTC(1'000'000'000'000), dan);
2661 env(
pay(
gw_, dan,
BTC(1'000'000'000'000)));
2665 nOffers(env, 1, dan, usd(1000000),
BTC(1'000'000'000'000));
2666 AMM const ammEd(env, ed, usd(9000000),
BTC(11'000'000'000'000));
2667 env(
offer(
alice_,
BTC(1'000'000'000'000'000), usd(1'000000000)));
2679 Env env(*
this, features);
2680 auto const dan =
Account(
"dan");
2681 auto const ed =
Account(
"ed");
2692 env.
trust(
USD(10000'000'000), dan);
2701 env(
pay(
gw_, ed, btc(11'000'000'000'000)));
2703 env(
pay(
gw_, dan, btc(1'000'000'000'000)));
2707 nOffers(env, 1, dan,
USD(1000000), btc(1'000'000'000'000));
2708 AMM const ammEd(env, ed,
USD(9000000), btc(11'000'000'000'000));
2709 env(
offer(
alice_, btc(1'000'000'000'000'000),
USD(1'000000000)));
2721 Env env(*
this, features);
2722 auto const dan =
Account(
"dan");
2723 auto const ed =
Account(
"ed");
2734 .pay = 10000'000'000,
2737 env(
pay(
gw_, ed, btc(11'000'000'000'000)));
2739 env(
pay(
gw_, dan, btc(1'000'000'000'000)));
2742 nOffers(env, 2'000,
bob_, usd(1000000), btc(1'000'000'000'000));
2743 nOffers(env, 1, dan, usd(1000000), btc(1'000'000'000'000));
2744 AMM const ammEd(env, ed, usd(9000000), btc(11'000'000'000'000));
2745 env(
offer(
alice_, btc(1'000'000'000'000'000), usd(1'000000000)));
2759 testcase(
"Convert all of an asset using DeliverMin");
2761 using namespace jtx;
2764 Env env(*
this, features);
2804 Env env(*
this, features);
2811 AMM const ammBob(env,
bob_,
XRP(1'000), btc(1'100'000));
2822 auto test = [&](
auto&& issue1,
auto&& issue2) {
2826 auto const usd = issue1(
2831 .limit = 3000'000});
2832 auto const btc = issue2(
2837 .limit = 1'000'000});
2844 AMM const ammBob(env,
bob_, usd(1'000), btc(1'100));
2856 Env env(*
this, features);
2863 AMM const ammBob(env,
bob_,
XRP(5'500), btc(1'200'000));
2881 auto test = [&](
auto&& issue1,
auto&& issue2) {
2885 auto const usd = issue1(
2890 .limit = 3000'000});
2891 auto const btc = issue2(
2896 .limit = 1'000'000});
2905 AMM const ammBob(env,
bob_, usd(5'500), btc(1'200));
2924 auto const dan =
Account(
"dan");
2925 Env env(*
this, features);
2932 env(
pay(
gw_, dan, btc(1'100'000'000)));
2935 AMM const ammDan(env, dan,
XRP(1'000), btc(1'100'000'000));
2954 using namespace jtx;
2957 Env env(*
this, features);
2966 AMM const ammAlice(env,
alice_,
XRP(100), btc(140'000));
2976 env(
fset(becky, asfDepositAuth));
2992 using namespace jtx;
3013 auto failedMptPayments = [
this, &env, &btc]() {
3035 failedMptPayments();
3052 failedMptPayments();
3059 failedMptPayments();
3082 Env env(*
this, features);
3088 env.
fund(
XRP(1'000), g1, alice, bob);
3093 .holders = {alice, bob},
3096 env(
pay(g1, bob, btc(10)));
3097 env(
pay(g1, alice, btc(205)));
3100 AMM const ammAlice(env, alice,
XRP(500), btc(105));
3107 env(
pay(alice, bob, btc(1)));
3110 env(
pay(bob, alice, btc(1)));
3114 btc.set({.holder = bob, .flags = tfMPTLock});
3138 btc.set({.holder = bob, .flags = tfMPTUnlock});
3140 env(
pay(bob, alice, btc(1)));
3141 env(
pay(alice, bob, btc(1)));
3152 Env env(*
this, features);
3162 env.
fund(
XRP(20'000), a2, a3, a4);
3167 .holders = {a1, a2, a3, a4},
3173 .holders = {a1, a2, a3, a4},
3176 env(
pay(g1, a1, eth(1'000)));
3177 env(
pay(g1, a2, eth(100)));
3178 env(
pay(g1, a3, btc(100)));
3179 env(
pay(g1, a4, btc(100)));
3182 AMM const ammG1(env, g1,
XRP(10'000), eth(100));
3204 AMM ammA3(env, a3, btc(1),
XRP(1));
3208 env(
pay(g1, a2, eth(1)));
3209 env(
pay(a2, g1, eth(1)));
3210 env(
pay(a2, a1, eth(1)));
3211 env(
pay(a1, a2, eth(1)));
3218 btc.set({.flags = tfMPTLock});
3224 env(
pay(g1, a2, btc(1)));
3225 env(
pay(a2, g1, btc(1)));
3245 testcase(
"Offers for Locked MPTs");
3248 Env env(*
this, features);
3255 env.
fund(
XRP(2'000), g1, a3, a4);
3262 .holders = {a2, a3, a4},
3265 env(
pay(g1, a3, btc(2'000)));
3266 env(
pay(g1, a4, btc(2'001)));
3269 AMM const ammA3(env, a3,
XRP(1'000), btc(1'001));
3279 env(
offer(a4,
XRP(999), btc(999)));
3285 btc.set({.holder = ammA3.
ammAccount(), .flags = tfMPTLock});
3287 BEAST_EXPECT(info[jss::amm][jss::asset2_frozen].asBool());
3298 btc.set({.holder = a4, .flags = tfMPTUnlock});
3302 env(
offer(a2, btc(999),
XRP(999)));
3314 testcase(
"Multisign AMM Transactions");
3316 using namespace jtx;
3317 Env env{*
this, features};
3322 fund(env,
gw_, {alice, becky, zelda},
XRP(20'000));
3327 .holders = {alice, becky, zelda},
3328 .pay = 20'000'000'000,
3333 env(
regkey(alice, alie));
3334 env(
fset(alice, asfDisableMaster),
Sig(alice));
3337 env(
signers(alice, 2, {{becky, 1}, {bogie, 1}}),
Sig(alie));
3339 static constexpr int kSignerListOwners{2};
3342 Msig const ms{becky, bogie};
3359 ammAlice.
deposit(alice, 1'000'000);
3362 ammAlice.
withdraw(alice, 1'000'000);
3365 ammAlice.
vote({}, 1'000);
3368 env(ammAlice.
bid({.account = alice, .bidMin = 100}), ms).
close();
3379 using namespace jtx;
3383 auto test = [&](
auto&& issue1,
auto&& issue2) {
3387 auto const eth = issue1(
3392 .limit = 1'000'000});
3393 auto const btc = issue2(
3398 .limit = 1'000'000});
3406 AMM const bobXrpBtc(env,
bob_,
XRP(1'000), btc(1'000));
3407 AMM const bobBtcEth(env,
bob_, btc(1'000), eth(1'000));
3411 Path(~btc, ~eth, ~btc),
3423 using namespace jtx;
3427 Env env(*
this, features);
3444 AMM const ammXrpBtc(env,
bob_,
XRP(100), btc(100'000));
3447 AMM const ammBtcEth(env,
bob_, btc(100'000), eth(100'000));
3462 Txflags(tfNoRippleDirect | tfPartialPayment),
3467 Env env(*
this, features);
3478 AMM const ammBob(env,
bob_,
XRP(100), btc(100));
3488 Env env(*
this, features);
3499 AMM const ammBob(env,
bob_,
XRP(100), btc(100));
3514 using namespace jtx;
3517 Env env(*
this, features);
3531 AMM const ammBob(env,
bob_,
XRP(100), btc(100'000'000));
3542 auto test = [&](
auto&& issue1,
auto&& issue2,
auto&& issue3) {
3543 Env env(*
this, features);
3548 auto const btc = issue1(
3550 auto const eth = issue2(
3552 auto const cny = issue3(
3560 AMM const ammBobXrpBtc(env,
bob_,
XRP(100), btc(100));
3561 AMM const ammBobBtcEth(env,
bob_, btc(100), eth(100));
3562 AMM const ammBobEthCny(env,
bob_, eth(100), cny(100));
3567 Path(~btc, ~eth, ~btc, ~cny),
3589 using namespace jtx;
3602 using namespace jtx;
3610 using namespace jtx;
3636 using namespace jtx;
3645 using namespace jtx;
A generic endpoint for log messages.
TestcaseT testcase
Memberspace for declaring test cases.
Floating point representation of amounts with high dynamic range.
beast::Journal journal(std::string const &name)
bool modify(modify_type const &f)
Modify the open ledger.
Writable ledger view that accumulates state and tx changes.
A wrapper which makes credits unavailable to balances.
void pushBack(STPath const &e)
Discardable, editable view to a ledger.
virtual OpenLedger & getOpenLedger()=0
virtual Logs & getLogs()=0
SLE::pointer peek(Keylet const &k) override
Prepare to modify the SLE associated with key.
TestPath & pushBack(Issue const &iss)
jtx::Account const alice_
void testAMM(std::function< void(jtx::AMM &, jtx::Env &)> const &cb, std::optional< std::pair< STAmount, STAmount > > const &pool=std::nullopt, std::uint16_t tfee=0, std::optional< jtx::Ter > const &ter=std::nullopt, std::vector< FeatureBitset > const &features={testableAmendments()})
testAMM() funds 30,000XRP and 30,000IOU for each non-XRP asset to Alice and Carol
static FeatureBitset testableAmendments()
jtx::Account const carol_
static XRPAmount reserve(jtx::Env &env, std::uint32_t count)
static XRPAmount ammCrtFee(jtx::Env &env)
Convenience class to test AMM functionality.
bool expectTradingFee(std::uint16_t fee) const
json::Value bid(BidArg const &arg)
IOUAmount withdrawAll(std::optional< Account > const &account, std::optional< STAmount > const &asset1OutDetails=std::nullopt, std::optional< Ter > const &ter=std::nullopt)
bool expectAuctionSlot(std::uint32_t fee, std::optional< std::uint8_t > timeSlot, IOUAmount expectedPrice) const
IOUAmount deposit(std::optional< Account > const &account, LPToken tokens, std::optional< STAmount > const &asset1InDetails=std::nullopt, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< Ter > const &ter=std::nullopt)
IOUAmount withdraw(std::optional< Account > const &account, std::optional< LPToken > const &tokens, std::optional< STAmount > const &asset1OutDetails=std::nullopt, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< Ter > const &ter=std::nullopt)
AccountID const & ammAccount() const
void vote(std::optional< Account > const &account, std::uint32_t feeVal, std::optional< std::uint32_t > const &flags=std::nullopt, std::optional< jtx::Seq > const &seq=std::nullopt, std::optional< std::pair< Asset, Asset > > const &assets=std::nullopt, std::optional< Ter > const &ter=std::nullopt)
json::Value ammRpcInfo(std::optional< AccountID > const &account=std::nullopt, std::optional< std::string > const &ledgerIndex=std::nullopt, std::optional< Asset > const &asset1=std::nullopt, std::optional< Asset > const &asset2=std::nullopt, std::optional< AccountID > const &ammAccount=std::nullopt, bool ignoreParams=false, unsigned apiVersion=RPC::kApiInvalidVersion) const
Send amm_info RPC command.
bool expectBalances(STAmount const &asset1, STAmount const &asset2, IOUAmount const &lpt, std::optional< AccountID > const &account=std::nullopt) const
Verify the AMM balances.
Immutable cryptographic account descriptor.
Sets the DeliverMin on a JTx.
A transaction testing environment.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
void memoize(Account const &account)
Associate AccountID with account.
void require(Args const &... args)
Check a set of requirements.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Test helper for creating, mutating, and asserting MPT and confidential MPT ledger state.
void authorize(MPTAuthorize const &arg=MPTAuthorize{})
Converts to MPT Issue or STAmount.
Set a multisignature on a JTx.
Match the number of items in the account's owner directory.
Set Paths, SendMax on a JTx.
Check a set of conditions.
Sets the SendMax on a JTx.
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.
@ Array
array value (ordered list)
Keylet offer(AccountID const &id, std::uint32_t seq) noexcept
An offer from an account.
Keylet account(AccountID const &id) noexcept
AccountID root.
void nOffers(Env &env, std::size_t n, Account const &account, STAmount const &in, STAmount const &out)
json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
std::vector< STAmount > fund(jtx::Env &env, jtx::Account const &gw, std::vector< jtx::Account > const &accounts, std::vector< STAmount > const &amts, Fund how)
bool expectLedgerEntryRoot(Env &env, Account const &acct, STAmount const &expectedValue)
json::Value regkey(Account const &account, DisabledT)
Disable the regular key.
bool expectOffers(Env &env, AccountID const &account, std::uint16_t size, std::vector< Amounts > const &toMatch)
STPathElement allPathElements(AccountID const &a, Asset const &asset)
void testHelper2TokensMix(TTester &&tester)
XrpT const XRP
Converts to XRP Issue or STAmount.
json::Value noop(Account const &account)
The null transaction.
bool same(STPathSet const &st1, Args const &... args)
XRPAmount txFee(Env const &env, std::uint16_t n)
std::tuple< STPathSet, STAmount, STAmount > findPaths(jtx::Env &env, jtx::Account const &src, jtx::Account const &dst, STAmount const &saDstAmount, std::optional< STAmount > const &saSendMax, std::optional< PathAsset > const &srcAsset, std::optional< AccountID > const &srcIssuer, std::optional< uint256 > const &domain)
json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
FeatureBitset testableAmendments()
void testHelper3TokensMix(TTester &&tester)
STPathElement cpe(PathAsset const &pa)
std::tuple< STPathSet, STAmount, STAmount > findPathsByElement(jtx::Env &env, jtx::Account const &src, jtx::Account const &dst, STAmount const &saDstAmount, std::optional< STAmount > const &saSendMax, std::optional< STPathElement > const &srcElement, std::optional< AccountID > const &srcIssuer, std::optional< uint256 > const &domain)
STPathElement ipe(Asset const &asset)
bool equal(STAmount const &sa1, STAmount const &sa2)
json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
json::Value ledgerEntryRoot(Env &env, Account const &acct)
OwnerCount< ltOFFER > offers
Match the number of offers in the account's owner directory.
STPath stpath(Args const &... args)
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
json::Value signers(Account const &account, std::uint32_t quorum, std::vector< Signer > const &v)
bool checkArraySize(json::Value const &val, unsigned int size)
json::Value getAccountOffers(Env &env, AccountID const &acct, bool current)
json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
constexpr XRPAmount
Convert XRP to drops (integral types).
BEAST_DEFINE_TESTSUITE_PRIO(AccountDelete, app, xrpl, 2)
bool isOffer(jtx::Env &env, jtx::Account const &account, STAmount const &takerPays, STAmount const &takerGets)
An offer exists.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
TAmounts< STAmount, STAmount > Amounts
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
TER offerDelete(ApplyView &view, SLE::ref sle, beast::Journal j)
Delete an offer.
Currency const & xrpCurrency()
XRP currency.
std::string to_string(BaseUInt< Bits, Tag > const &a)
StrandResult< TInAmt, TOutAmt > flow(PaymentSandbox const &baseView, Strand const &strand, std::optional< TInAmt > const &maxIn, TOutAmt const &out, beast::Journal j)
Request out amount from a strand.
AccountID const & xrpAccount()
Compute AccountID from public key.
Tests of AMM MPT that use offers.
void pathFindConsumeAll()
void testOfferCrossWithXRP(FeatureBitset features)
void testSellFlagBasic(FeatureBitset features)
void testSellWithFillOrKill(FeatureBitset features)
void testBridgedCross(FeatureBitset features)
void testCrossCurrencyEndXRP(FeatureBitset features)
void testCurrencyConversionEntire(FeatureBitset features)
void testTxMultisign(FeatureBitset features)
void testDirectToDirectPath(FeatureBitset features)
void testOffersWhenLocked(FeatureBitset features)
void testFalseDry(FeatureBitset features)
void testCrossCurrencyBridged(FeatureBitset features)
void testCrossingLimits()
void testOfferFeesConsumeFunds(FeatureBitset features)
void testRequireAuth(FeatureBitset features)
void testCurrencyConversionInParts(FeatureBitset features)
void testOfferCreateThenCross(FeatureBitset features)
void run() override
Runs the suite.
void testStepLimit(FeatureBitset features)
void testSellFlagExceedLimit(FeatureBitset features)
void testFillModes(FeatureBitset features)
void testPayment(FeatureBitset features)
void testSelfIssueOffer(FeatureBitset features)
void testOfferCrossWithLimitOverride(FeatureBitset features)
void testTransferRateOffer(FeatureBitset features)
void testRmFundedOffer(FeatureBitset features)
void testLoop(FeatureBitset features)
void testConvertAllOfAnAsset(FeatureBitset features)
void testCrossCurrencyStartXRP(FeatureBitset features)
void testToStrand(FeatureBitset features)
void testGlobalLock(FeatureBitset features)
void viaOffersViaGateway()
void testTransferRateNoOwnerFee(FeatureBitset features)
void testMissingAuth(FeatureBitset features)
void testGatewayCrossCurrency(FeatureBitset features)
void testRIPD1373(FeatureBitset features)
void testIndividualLock(FeatureBitset features)
void testBookStep(FeatureBitset features)
Represents an XRP, IOU, or MPT quantity This customizes the string conversion and supports XRP conver...