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 Env env{*
this, features};
202 AMM const ammAlice(env,
alice_,
XRP(10'100'000), btc(10'000'000));
210 ammAlice.expectBalances(
XRP(10'100'000), btc(10'000'000), ammAlice.tokens()));
216 [&](
AMM& ammAlice,
Env& env) {
217 auto const& btc =
MPT(ammAlice[1]);
238 testcase(
"Offer Crossing with XRP, Normal order");
242 Env env{*
this, features};
253 AMM const ammAlice(env,
alice_,
XRP(150'000), btc(50'000'000));
258 auto const xrpTransferred =
XRPAmount{3'061'224'490};
261 BEAST_EXPECT(ammAlice.expectBalances(
262 XRP(150'000) + xrpTransferred, btc(49'000'000),
IOUAmount{273'861'278752583, -5}));
273 testcase(
"Offer Crossing with Limit Override");
277 Env env{*
this, features};
286 AMM const ammAlice(env,
alice_,
XRP(150'000), btc(51'000'000));
298 testcase(
"Currency Conversion: Entire Offer");
302 Env env{*
this, features};
314 AMM const ammBob(env,
bob_, btc(200'000'000),
XRP(1'500));
328 testcase(
"Currency Conversion: In Parts");
332 Env env{*
this, features};
340 .pay = 30'000'000'000,
344 AMM const ammAlice(env,
alice_,
XRP(10'000), btc(10'000'000'000));
369 testcase(
"Cross Currency Payment: Start with XRP");
373 Env env{*
this, features};
382 AMM const ammAlice(env,
alice_,
XRP(10'000), btc(10'100'000'000));
393 testcase(
"Cross Currency Payment: End with XRP");
397 Env env{*
this, features};
406 AMM const ammAlice(env,
alice_,
XRP(10'100), btc(10'000'000'000));
417 testcase(
"Cross Currency Payment: Bridged");
421 auto test = [&](
auto&& issue1,
auto&& issue2) {
423 auto const dan =
Account{
"dan"};
426 auto const eth = issue1(
431 .limit = 10'000'000'000'000'000});
432 auto const btc = issue2(
437 .limit = 10'000'000'000'000'000});
440 env(
pay(
gw_, dan, eth(400'000'000'000'000)));
443 AMM const ammCarol(env,
carol_, btc(5'000'000'000'000'000),
XRP(50'000));
445 env(
offer(dan,
XRP(500), eth(50'000'000'000'000)));
449 jtp[0u][0u][jss::currency] =
"XRP";
451 Json(jss::Paths, jtp),
452 Sendmax(btc(333'000'000'000'000)));
455 XRP(49'700), btc(5'030'181'086'519'115), ammCarol.
tokens()));
465 testcase(
"Offer Fees Consume Funds");
469 Env env{*
this, features};
473 auto const startingXrp =
474 XRP(100) + env.
current()->fees().accountReserve(2, 1) + env.
current()->fees().base * 3;
487 env(
pay(
gw_,
bob_, btc(1'200'000'000'000'000)));
489 AMM const ammBob(env,
bob_,
XRP(1'000), btc(1'200'000'000'000'000));
506 testcase(
"Offer Create, then Cross");
510 Env env{*
this, features};
524 AMM const ammAlice(env,
alice_, btc(150'000'000'000'000),
XRP(150'100));
537 testcase(
"Offer tfSell: Basic Sell");
541 Env env{*
this, features};
553 AMM const ammAlice(env,
alice_,
XRP(9'900), btc(10'100));
567 testcase(
"Offer tfSell: 2x Sell Exceed Limit");
571 Env env{*
this, features};
573 auto const startingXrp =
XRP(100) +
reserve(env, 1) + env.
current()->fees().base * 2;
583 AMM const ammBob(env,
bob_,
XRP(1'000), btc(2'200'000'000));
599 testcase(
"Client Issue: Gateway Cross Currency");
603 Env env{*
this, features};
605 auto const startingXrp =
XRP(100.1) +
reserve(env, 1) + env.
current()->fees().base * 2;
612 .pay = 1'000'000'000'000'000,
618 .pay = 1'000'000'000'000'000,
621 AMM const ammAlice(env,
alice_, xts(1'000'000'000'000'000), xxx(1'000'000'000'000'000));
625 payment[jss::id] = env.
seq(
bob_);
626 payment[jss::build_path] =
true;
627 payment[jss::tx_json] =
pay(
bob_,
bob_, xxx(10'000'000'000'000));
628 payment[jss::tx_json][jss::Sequence] =
631 payment[jss::tx_json][jss::SendMax] =
633 payment[jss::tx_json][jss::Flags] = tfPartialPayment;
634 auto const jrr = env.
rpc(
"json",
"submit",
to_string(payment));
635 BEAST_EXPECT(jrr[jss::result][jss::status] ==
"success");
636 BEAST_EXPECT(jrr[jss::result][jss::engine_result] ==
"tesSUCCESS");
638 BEAST_EXPECT(ammAlice.expectBalances(
639 xts(1'010'101'010'101'011), xxx(990'000'000'000'000), ammAlice.tokens()));
652 Env env{*
this, features};
659 .pay = 15'000'000'000,
665 .pay = 15'000'000'000,
674 AMM const ammAlice(env,
alice_,
XRP(10'000), btc(10'100'000'000));
675 AMM const ammBob(env,
bob_, eth(10'000'000'000),
XRP(10'100));
679 env(
offer(
carol_, btc(100'000'000), eth(100'000'000)));
683 ammAlice.expectBalances(
XRP(10'100), btc(10'000'000'000), ammAlice.tokens()));
691 Env env{*
this, features};
698 .pay = 15'000'000'000,
704 .pay = 15'000'000'000,
714 AMM const ammAlice(env,
alice_,
XRP(10'000), btc(10'100'000'000));
720 env(
offer(
carol_, btc(100'000'000), eth(100'000'000)));
724 ammAlice.expectBalances(
XRP(10'100), btc(10'000'000'000), ammAlice.tokens()));
732 Env env{*
this, features};
739 .pay = 15'000'000'000,
745 .pay = 15'000'000'000,
757 AMM const ammBob(env,
bob_, eth(10'000'000'000),
XRP(10'100));
761 env(
offer(
carol_, btc(100'000'000), eth(100'000'000)));
777 testcase(
"Combine tfSell with tfFillOrKill");
782 Env env{*
this, features};
789 .pay = 20'000'000'000,
791 AMM const ammBob(env,
bob_,
XRP(20'000), btc(200'000'000));
795 BEAST_EXPECT(ammBob.expectBalances(
XRP(20'000), btc(200'000'000), ammBob.tokens()));
799 Env env{*
this, features};
806 .pay = 1'000'000'000'000'000,
808 AMM const ammBob(env,
bob_,
XRP(20'000), btc(200'000'000'000'000));
811 env(
offer(
alice_, btc(2'000'000'000'000),
XRP(220), tfSell | tfFillOrKill));
814 ammBob.expectBalances(
XRP(20'220), btc(197'823'936'696'341), ammBob.tokens()));
821 Env env{*
this, features};
828 .pay = 1'000'000'000'000'000,
830 AMM const ammBob(env,
bob_,
XRP(20'000), btc(200'000'000'000'000));
832 env(
offer(
alice_, btc(10'000'000'000'000),
XRP(1'500), tfSell | tfFillOrKill));
836 ammBob.expectBalances(
XRP(21'500), btc(186'046'511'627'907), ammBob.tokens()));
846 Env env{*
this, features};
853 .pay = 10'000'000'000,
855 AMM const ammBob(env,
bob_,
XRP(5000), btc(10'000'000));
873 Env env(*
this, features);
881 .transferFee = 25'000,
886 AMM const ammAlice(env,
alice_,
XRP(10'000), btc(10'100'000));
899 Env env(*
this, features);
907 .transferFee = 25'000,
912 AMM const ammAlice(env,
alice_,
XRP(10'100), btc(10'000'000));
926 Env env{*
this, features};
933 .transferFee = 25'000,
940 .transferFee = 25'000,
950 AMM const ammAlice(env,
alice_,
XRP(10'000), btc(10'100'000));
960 BEAST_EXPECT(ammAlice.expectBalances(
XRP(10'100), btc(10'000'000), ammAlice.tokens()));
971 Env env{*
this, features};
978 .transferFee = 25'000,
985 .transferFee = 25'000,
995 AMM const ammAlice(env,
alice_,
XRP(10'000), btc(10'050'000));
1008 BEAST_EXPECT(ammAlice.expectBalances(
XRP(10'050), btc(10'000'000), ammAlice.tokens()));
1023 using namespace jtx;
1025 Env env{*
this, features};
1027 auto const f = env.
current()->fees().base;
1035 AMM const ammBob(env,
bob_,
XRP(10'000), btc(10'100));
1040 BEAST_EXPECT(ammBob.expectBalances(
XRP(10'100), btc(10'000), ammBob.tokens()));
1054 using namespace jtx;
1056 Env env{*
this, features};
1058 auto const ann =
Account(
"ann");
1059 auto const bob =
Account(
"bob");
1060 auto const cam =
Account(
"cam");
1061 auto const carol =
Account(
"carol");
1063 auto const fee = env.
current()->fees().base;
1065 env.
fund(
reserve(env, 4) + (fee * 5), ann, bob, cam);
1069 {.env = env, .issuer = ann, .holders = {bob, cam, carol}, .flags =
kMptDexFlags});
1072 {.env = env, .issuer = bob, .holders = {ann, cam, carol}, .flags =
kMptDexFlags});
1074 env(
pay(ann, cam, aBux(350'000'000'000'000)));
1075 env(
pay(bob, cam, bBux(350'000'000'000'000)));
1076 env(
pay(bob, carol, bBux(4'000'000'000'000'000)));
1077 env(
pay(ann, carol, aBux(4'000'000'000'000'000)));
1079 AMM const ammCarol(env, carol, aBux(3'000'000'000'000'000), bBux(3'300'000'000'000'000));
1084 env(
offer(cam, aBux(290'000'000'000'000), bBux(300'000'000'000'000), tfPassive));
1091 env(
offer(cam, bBux(300'000'000'000'000), aBux(300'000'000'000'000)));
1095 aBux(3'093'541'659'651'603), bBux(3'200'215'509'984'419), ammCarol.
tokens()));
1097 env, cam, 1, {{
Amounts{bBux(200'215'509'984'419), aBux(200'215'509'984'419)}}}));
1105 using namespace jtx;
1107 Env env{*
this, features};
1118 btc.authorize({.holder =
bob_});
1124 AMM const ammAlice(env,
alice_, btc(1'000),
XRP(1'050));
1145 using namespace jtx;
1147 Env env{*
this, features};
1178 AMM const ammAlice(env,
alice_, btc(1'000),
XRP(1'050));
1196 using namespace jtx;
1225 using namespace jtx;
1235 .pay = 100'000'000'000'000,
1238 AMM const ammCarol(env,
carol_,
XRP(100), eth(100'000'000'000'000));
1245 BEAST_EXPECT(st.
empty());
1249 BEAST_EXPECT(sa ==
XRP(100'000'000));
1252 BEAST_EXPECT(
equal(da, eth(99'999'900'000'099)));
1262 using namespace jtx;
1272 .transferFee = 10'000,
1279 .transferFee = 10'000,
1292 BEAST_EXPECT(std::get<0>(result).empty());
1299 using namespace jtx;
1300 auto const charlie =
Account(
"charlie");
1310 .pay = 11'000'000'000'000,
1313 AMM const ammCharlie(env, charlie,
XRP(10), eth(11'000'000'000'000));
1315 BEAST_EXPECT(sa ==
XRP(1));
1316 BEAST_EXPECT(
equal(da, eth(1'000'000'000'000)));
1317 if (BEAST_EXPECT(st.size() == 1 && st[0].size() == 1))
1319 auto const& pathElem = st[0][0];
1321 pathElem.isOffer() && pathElem.getIssuerID() ==
gw_.id() &&
1322 pathElem.getMPTID() == eth.issuanceID());
1334 .pay = 11'000'000'000'000,
1337 AMM const ammCharlie(env, charlie,
XRP(11), eth(10'000'000'000'000));
1341 BEAST_EXPECT(sa == eth(1'000'000'000'000));
1343 if (BEAST_EXPECT(st.size() == 1 && st[0].size() == 1))
1345 auto const& pathElem = st[0][0];
1347 pathElem.isOffer() && pathElem.getIssuerID() ==
xrpAccount() &&
1356 testcase(
"Path Find: XRP -> XRP and XRP -> MPT");
1357 using namespace jtx;
1369 env.
fund(
XRP(1'000), a3, g1, g2, g3);
1374 {.env = env, .issuer = g1, .holders = {a1, m1, a2}, .flags =
kMptDexFlags});
1377 {.env = env, .issuer = g2, .holders = {a2, m1, a1}, .flags =
kMptDexFlags});
1380 {.env = env, .issuer = g3, .holders = {a1, a2, m1, a3}, .flags =
kMptDexFlags});
1383 {.env = env, .issuer = a2, .holders = {g3, a1}, .flags =
kMptDexFlags});
1385 env(
pay(g1, a1, xyzG1(3'500'000'000)));
1386 env(
pay(g3, a1, abcG3(1'200'000'000)));
1387 env(
pay(g1, m1, xyzG1(25'000'000'000)));
1388 env(
pay(g2, m1, xyzG2(25'000'000'000)));
1389 env(
pay(g3, m1, abcG3(25'000'000'000)));
1390 env(
pay(a2, g3, abcA2(101'000'000)));
1393 AMM const ammM1XyzG1XyzG2(env, m1, xyzG1(1'000'000'000), xyzG2(1'000'000'000));
1394 AMM const ammM1XrpAbcG3(env, m1,
XRP(10'000), abcG3(1'000'000'000));
1395 AMM const ammG3AbcG3AbcA2(env, g3, abcG3(100'000'000), abcA2(101'000'000));
1402 auto const& sendAmt =
XRP(10);
1404 BEAST_EXPECT(
equal(da, sendAmt));
1405 BEAST_EXPECT(st.
empty());
1411 auto const& sendAmt =
XRP(200);
1414 BEAST_EXPECT(
equal(da, sendAmt));
1415 BEAST_EXPECT(st.
empty());
1419 auto const& sendAmt = abcG3(10'000'000);
1421 BEAST_EXPECT(
equal(da, sendAmt));
1427 auto const& sendAmt = abcA2(1'000'000);
1429 BEAST_EXPECT(
equal(da, sendAmt));
1438 testcase(
"Path Find: non-XRP -> XRP");
1439 using namespace jtx;
1446 env.
fund(
XRP(1'000), a1, a2, g3);
1453 .holders = {a1, a2, m1},
1454 .pay = 1'000'000'000,
1457 AMM const ammM1(env, m1, eth(1'000'000'000),
XRP(10'010));
1462 auto const& sendAmt =
XRP(10);
1466 BEAST_EXPECT(
equal(da, sendAmt));
1467 BEAST_EXPECT(
equal(sa, eth(1'000'000)));
1474 testcase(
"Path Find: non-XRP -> non-XRP, same issuanceID");
1475 using namespace jtx;
1486 env.
fund(
XRP(1'000), a1, a2, a3, g1, g2);
1492 .holders = {a1, m1},
1493 .pay = 5'000'000'000,
1499 .holders = {a2, m1},
1500 .pay = 5'000'000'000,
1503 AMM const ammM1(env, m1, hkdG1(1'000'000'000), hkdG2(1'010'000'000));
1505 auto const& sendAmt = hkdG2(10'000'000);
1509 env, g1, a2, sendAmt, std::nullopt, hkdG1.issuanceID(), std::nullopt, std::nullopt);
1510 BEAST_EXPECT(
equal(da, sendAmt));
1511 BEAST_EXPECT(
equal(sa, hkdG1(10'000'000)));
1519 testcase(
"Path Find: MPT AMM source amount is executable");
1520 using namespace jtx;
1544 AMM const ammCarol(env,
carol_, usd(usdPool), eur(eurPool));
1549 auto const deliver = eur(deliverAmount);
1561 BEAST_EXPECT(
equal(da, deliver));
1562 BEAST_EXPECT(
equal(sa, usd(expectedSourceAmount)));
1563 BEAST_EXPECT(!st.
empty());
1565 auto const before = eur.getBalance(
bob_);
1570 BEAST_EXPECT(eur.getBalance(
bob_) == before + deliverAmount);
1583 TestCase
const testCases[] = {
1584 {.usdPool = 2'000'000, .eurPool = 1'000'000, .deliverAmount = 1, .expectedSourceAmount = 3},
1585 {.usdPool = 2'000'000, .eurPool = 1'000'000, .deliverAmount = 2, .expectedSourceAmount = 5},
1586 {.usdPool = 2'000'000, .eurPool = 1'000'000, .deliverAmount = 10, .expectedSourceAmount = 21},
1587 {.usdPool = 2'000'000, .eurPool = 1'000'000, .deliverAmount = 100, .expectedSourceAmount = 201},
1588 {.usdPool = 2'000'000, .eurPool = 1'000'000, .deliverAmount = 1'000, .expectedSourceAmount = 2'003},
1589 {.usdPool = 2'000, .eurPool = 1'000, .deliverAmount = 1, .expectedSourceAmount = 3},
1590 {.usdPool = 2'000, .eurPool = 1'000, .deliverAmount = 2, .expectedSourceAmount = 5},
1591 {.usdPool = 2'000, .eurPool = 1'000, .deliverAmount = 10, .expectedSourceAmount = 21},
1592 {.usdPool = 2'000, .eurPool = 1'000, .deliverAmount = 100, .expectedSourceAmount = 223},
1596 for (
auto const& testCase : testCases)
1601 testCase.deliverAmount,
1602 testCase.expectedSourceAmount);
1611 using namespace jtx;
1613 Env env(*
this, features);
1618 auto const ammxrpPool = env.
current()->fees().increment * 2;
1639 AMM const ammBob(env,
bob_, ammxrpPool, btc(150'000));
1644 Txflags(tfNoRippleDirect | tfPartialPayment));
1647 BEAST_EXPECT(carolBTC > btc(0) && carolBTC < btc(50'000));
1655 using namespace jtx;
1659 auto test = [&](
auto&& issue1,
auto&& issue2) {
1663 auto const eth = issue1(
1668 .limit = 100'000'000});
1669 auto const btc = issue2(
1674 .limit = 100'000'000});
1682 AMM const ammBob(env,
bob_, btc(100'000), eth(150'000));
1697 Env env(*
this, features);
1714 AMM const ammBobBtcXrp(env,
bob_, btc(100'000),
XRP(150));
1715 AMM const ammBobXrpEth(env,
bob_,
XRP(100), eth(150'000));
1724 ammBobBtcXrp.expectBalances(btc(150'000),
XRP(100), ammBobBtcXrp.tokens()));
1730 Env env(*
this, features);
1741 AMM const ammBob(env,
bob_,
XRP(100), eth(150'000));
1749 BEAST_EXPECT(ammBob.expectBalances(
XRP(150), eth(100'000), ammBob.tokens()));
1753 Env env(*
this, features);
1764 AMM const ammBob(env,
bob_, eth(100'000),
XRP(150));
1773 BEAST_EXPECT(ammBob.expectBalances(eth(150'000),
XRP(100), ammBob.tokens()));
1778 auto test = [&](
auto&& issue1,
auto&& issue2,
auto&& issue3) {
1779 Env env(*
this, features);
1782 auto const btc = issue1(
1787 .limit = 1000'000000});
1788 auto const eth = issue2(
1793 .limit = 1000'000000});
1794 auto const gbp = issue3(
1799 .limit = 1000'000000});
1804 env(
offer(
bob_, btc(50'000), eth(50'000)));
1805 env(
offer(
bob_, btc(40'000), gbp(50'000)));
1807 AMM const ammBob(env,
bob_, gbp(100'000), eth(150'000));
1811 BEAST_EXPECT(
isOffer(env,
bob_, btc(50'000), eth(50'000)));
1812 BEAST_EXPECT(
isOffer(env,
bob_, btc(40'000), gbp(50'000)));
1823 BEAST_EXPECT(!
isOffer(env,
bob_, btc(50'000), eth(50'000)));
1825 BEAST_EXPECT(!
isOffer(env,
bob_, btc(40'000), gbp(50'000)));
1842 Env env(*
this, features);
1876 AMM const ammBobBtcEth(env,
bob_, btc(50'000'000), eth(50'000'000));
1877 env(
offer(
bob_, btc(60'000'000), gbp(50'000'000)));
1878 env(
offer(
carol_, btc(1'000'000'000), gbp(1'000'000)));
1879 env(
offer(
bob_, gbp(50'000'000), eth(50'000'000)));
1884 btc(50'000'000), eth(50'000'000), ammBobBtcEth.
tokens()));
1885 BEAST_EXPECT(
isOffer(env,
bob_, btc(60'000'000), gbp(50'000'000)));
1886 BEAST_EXPECT(
isOffer(env,
carol_, btc(1'000'000'000), gbp(1'000'000)));
1887 BEAST_EXPECT(
isOffer(env,
bob_, gbp(50'000'000), eth(50'000'000)));
1890 auto const flowResult = [&] {
1891 STAmount const deliver(eth(51'000'000));
1927 BEAST_EXPECT(flowResult.removableOffers.size() == 1);
1929 if (flowResult.removableOffers.empty())
1932 for (
auto const& o : flowResult.removableOffers)
1945 btc(50'000'000), eth(50'000'000), ammBobBtcEth.
tokens()));
1946 BEAST_EXPECT(
isOffer(env,
carol_, btc(1'000'000'000), gbp(1'000'000)));
1948 BEAST_EXPECT(!
isOffer(env,
bob_, btc(60'000'000), gbp(50'000'000)));
1959 auto test = [&](
auto&& issue1,
auto&& issue2) {
1963 auto const eth = issue1(
1968 .limit = 10'000'000});
1969 auto const btc = issue2(
1974 .limit = 10'000'000});
1987 Txflags(tfNoRippleDirect | tfPartialPayment));
1990 BEAST_EXPECT(ammBob.expectBalances(eth(8400),
XRPAmount{20}, ammBob.tokens()));
2000 using namespace jtx;
2004 Env env(*
this, features);
2011 .transferFee = 25'000,
2012 .pay = 1'000'000'000'000'000,
2019 .transferFee = 25'000,
2020 .pay = 1'000'000'000'000'000,
2023 AMM const amm(env,
bob_, gbp(1'000'000'000'000'000), btc(1'000'000'000'000'000));
2027 Sendmax(gbp(150'000'000'000'000)),
2028 Txflags(tfNoRippleDirect | tfPartialPayment));
2035 BEAST_EXPECT(
amm.expectBalances(
2036 gbp(1'120'000'000'000'000), btc(892'857'142'857'143),
amm.tokens()));
2044 Env env(*
this, features);
2053 .transferFee = 25'000,
2054 .pay = 1'000'000'000'000'000,
2061 .transferFee = 25'000,
2062 .pay = 1'000'000'000'000'000,
2069 .transferFee = 25'000,
2070 .pay = 1'000'000'000'000'000,
2073 env(
offer(ed, gbp(1'000'000'000'000'000), eth(1'000'000'000'000'000)),
2077 AMM const amm(env,
bob_, eth(1'000'000'000'000'000), btc(1'000'000'000'000'000));
2081 Sendmax(gbp(150'000'000'000'000)),
2082 Txflags(tfNoRippleDirect | tfPartialPayment));
2094 env, ed, 1, {
Amounts{gbp(880'000'000'000'000), eth(880'000'000'000'000)}}));
2097 BEAST_EXPECT(
amm.expectBalances(
2098 eth(1'096'000'000'000'000), btc(912'408'759'124'088),
amm.tokens()));
2105 Env env(*
this, features);
2114 .transferFee = 25'000,
2115 .pay = 1'000'000'000'000'000,
2122 .transferFee = 25'000,
2123 .pay = 1'000'000'000'000'000,
2130 .transferFee = 25'000,
2131 .pay = 1'000'000'000'000'000,
2134 AMM const amm1(env,
bob_, gbp(1'000'000'000'000'000), eth(1'000'000'000'000'000));
2135 AMM const amm2(env, ed, eth(1'000'000'000'000'000), btc(1'000'000'000'000'000));
2139 Sendmax(gbp(150'000'000'000'000)),
2140 Txflags(tfNoRippleDirect | tfPartialPayment));
2148 BEAST_EXPECT(amm1.expectBalances(
2149 gbp(1'120'000'000'000'000), eth(892'857'142'857'143), amm1.tokens()));
2153 eth(1'085'714'285'714'285), btc(921'052'631'578'948), amm2.
tokens()));
2161 Env env(*
this, features);
2169 .transferFee = 25'000,
2177 .transferFee = 25'000,
2181 AMM const amm(env,
bob_, btc(1'000'000), eth(1'100'000));
2186 BEAST_EXPECT(
amm.expectBalances(btc(1'100'000), eth(1'000'000),
amm.tokens()));
2194 Env env(*
this, features);
2202 .transferFee = 25'000,
2203 .pay = 1'000'000'000'000'000,
2210 .transferFee = 25'000,
2211 .pay = 1'000'000'000'000'000,
2214 AMM const amm(env,
bob_, gbp(1'000'000'000'000'000), btc(1'000'000'000'000'000));
2220 Sendmax(gbp(178'580'000'000'000)),
2221 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2229 BEAST_EXPECT(
amm.expectBalances(
2230 gbp(1'142'857'142'857'143), btc(875'000'000'000'000),
amm.tokens()));
2238 Env env(*
this, features);
2246 .transferFee = 25'000,
2247 .pay = 1'200'000'000'000'000,
2254 .transferFee = 25'000,
2255 .pay = 1'200'000'000'000'000,
2258 AMM const amm(env,
bob_, gbp(1'000'000'000'000'000), btc(1'200'000'000'000'000));
2264 Sendmax(gbp(120'000'000'000'000)),
2265 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2273 BEAST_EXPECT(
amm.expectBalances(
2274 gbp(1'024'000'000'000'000), btc(1'171'875'000'000'000),
amm.tokens()));
2283 Env env(*
this, features);
2292 .transferFee = 25'000,
2293 .pay = 1'400'000'000'000'000,
2300 .transferFee = 25'000,
2301 .pay = 1'400'000'000'000'000,
2308 .transferFee = 25'000,
2309 .pay = 1'400'000'000'000'000,
2312 env(
offer(ed, gbp(1'000'000'000'000'000), eth(1'000'000'000'000'000)),
2316 AMM const amm(env,
bob_, eth(1'000'000'000'000'000), btc(1'400'000'000'000'000));
2322 Sendmax(gbp(140'000'000'000'000)),
2323 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2336 env, ed, 1, {
Amounts{gbp(929'578'947'368'420), eth(929'578'947'368'420)}}));
2339 BEAST_EXPECT(
amm.expectBalances(
2340 eth(1'056'336'842'105'264), btc(1'325'334'821'428'571),
amm.tokens()));
2349 Env env(*
this, features);
2358 .transferFee = 25'000,
2359 .pay = 1'400'000'000'000'000,
2366 .transferFee = 25'000,
2367 .pay = 1'400'000'000'000'000,
2374 .transferFee = 25'000,
2375 .pay = 1'400'000'000'000'000,
2378 AMM const amm(env,
bob_, gbp(1'000'000'000'000'000), eth(1'000'000'000'000'000));
2380 env(
offer(ed, eth(1'000'000'000'000'000), btc(1'400'000'000'000'000)),
2388 Sendmax(gbp(140'000'000'000'000)),
2389 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2402 BEAST_EXPECT(
amm.expectBalances(
2403 gbp(1'056'336'842'105'264), eth(946'667'729'591'836),
amm.tokens()));
2410 env, ed, 1, {
Amounts{eth(957'334'183'673'469), btc(1'340'267'857'142'857)}}));
2418 Env env(*
this, features);
2427 .transferFee = 25'000,
2428 .pay = 1'400'000'000'000'000,
2435 .transferFee = 25'000,
2436 .pay = 1'400'000'000'000'000,
2443 .transferFee = 25'000,
2444 .pay = 1'400'000'000'000'000,
2447 AMM const amm1(env,
bob_, gbp(1'000'000'000'000'000), eth(1'000'000'000'000'000));
2448 AMM const amm2(env, ed, eth(1'000'000'000'000'000), btc(1'400'000'000'000'000));
2454 Sendmax(gbp(145'000'000'000'000)),
2455 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2464 BEAST_EXPECT(amm1.expectBalances(
2465 gbp(1'086'024'691'358'028), eth(920'789'377'955'618), amm1.tokens()));
2469 eth(1'063'368'497'635'505), btc(1'316'570'881'226'053), amm2.
tokens()));
2478 Env env(*
this, features);
2486 .transferFee = 25'000,
2487 .pay = 1'400'000'000'000'000,
2494 .transferFee = 25'000,
2495 .pay = 1'400'000'000'000'000,
2502 .transferFee = 25'000,
2503 .pay = 1'400'000'000'000'000,
2506 AMM const amm1(env,
alice_, gbp(1'000'000'000'000'000), eth(1'000'000'000'000'000));
2507 AMM const amm2(env,
bob_, eth(1'000'000'000'000'000), btc(1'400'000'000'000'000));
2513 Sendmax(gbp(120'000'000'000'000)),
2514 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2518 BEAST_EXPECT(amm1.expectBalances(
2519 gbp(1'108'148'148'148'150), eth(902'406'417'112'298), amm1.tokens()));
2523 eth(1'078'074'866'310'161), btc(1'298'611'111'111'111), amm2.
tokens()));
2539 using namespace jtx;
2552 AMM const ammBob(env,
bob_,
XRP(1'000), eth(1'050'000));
2558 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2560 BEAST_EXPECT(ammBob.expectBalances(
XRP(1'050), eth(1'000'000), ammBob.tokens()));
2571 using namespace jtx;
2575 auto test = [&](
auto&& issue1,
auto&& issue2) {
2579 auto const eth = issue1(
2584 .limit = 2000'000});
2585 auto const btc = issue2(
2590 .limit = 2000'000});
2598 AMM const ammAliceXrpBtc(env,
alice_,
XRP(100), btc(101'000));
2599 AMM const ammAliceXrpEth(env,
alice_,
XRP(100), eth(101'000));
2611 auto test = [&](
auto&& issue1,
auto&& issue2) {
2615 auto const eth = issue1(
2620 .limit = 2000'000});
2621 auto const btc = issue2(
2626 .limit = 2000'000});
2634 AMM const ammAliceXrpBtc(env,
alice_,
XRP(100), btc(100'000));
2635 AMM const ammAliceXrpEth(env,
alice_,
XRP(100), eth(100'000));
2649 auto test = [&](
auto&& issue1,
auto&& issue2,
auto&& issue3) {
2653 auto const eth = issue1(
2658 .limit = 2000'000});
2659 auto const btc = issue2(
2664 .limit = 2000'000});
2665 auto const jpy = issue2(
2670 .limit = 2000'000});
2680 AMM const ammAliceXrpBtc(env,
alice_,
XRP(100), btc(100'000));
2681 AMM const ammAliceXrpEth(env,
alice_,
XRP(100), eth(100'000));
2682 AMM const ammAliceXrpJpy(env,
alice_,
XRP(100), jpy(100'000));
2699 using namespace jtx;
2701 Env env(*
this, features);
2702 auto const dan =
Account(
"dan");
2703 auto const ed =
Account(
"ed");
2710 env(
pay(
gw_, ed, btc(11'000'000'000'000)));
2712 env(
pay(
gw_, dan, btc(1'000'000'000'000)));
2715 nOffers(env, 1, dan,
XRP(1), btc(1'000'000'000'000));
2716 AMM const ammEd(env, ed,
XRP(9), btc(11'000'000'000'000));
2742 Env env(*
this, features);
2743 auto const dan =
Account(
"dan");
2744 auto const ed =
Account(
"ed");
2753 .pay = 10000'000'000,
2756 env.
trust(
BTC(11'000'000'000'000), ed);
2757 env(
pay(
gw_, ed,
BTC(11'000'000'000'000)));
2760 env.
trust(
BTC(1'000'000'000'000), dan);
2761 env(
pay(
gw_, dan,
BTC(1'000'000'000'000)));
2765 nOffers(env, 1, dan, usd(1000000),
BTC(1'000'000'000'000));
2766 AMM const ammEd(env, ed, usd(9000000),
BTC(11'000'000'000'000));
2767 env(
offer(
alice_,
BTC(1'000'000'000'000'000), usd(1'000000000)));
2779 Env env(*
this, features);
2780 auto const dan =
Account(
"dan");
2781 auto const ed =
Account(
"ed");
2792 env.
trust(
USD(10000'000'000), dan);
2801 env(
pay(
gw_, ed, btc(11'000'000'000'000)));
2803 env(
pay(
gw_, dan, btc(1'000'000'000'000)));
2807 nOffers(env, 1, dan,
USD(1000000), btc(1'000'000'000'000));
2808 AMM const ammEd(env, ed,
USD(9000000), btc(11'000'000'000'000));
2809 env(
offer(
alice_, btc(1'000'000'000'000'000),
USD(1'000000000)));
2821 Env env(*
this, features);
2822 auto const dan =
Account(
"dan");
2823 auto const ed =
Account(
"ed");
2834 .pay = 10000'000'000,
2837 env(
pay(
gw_, ed, btc(11'000'000'000'000)));
2839 env(
pay(
gw_, dan, btc(1'000'000'000'000)));
2842 nOffers(env, 2'000,
bob_, usd(1000000), btc(1'000'000'000'000));
2843 nOffers(env, 1, dan, usd(1000000), btc(1'000'000'000'000));
2844 AMM const ammEd(env, ed, usd(9000000), btc(11'000'000'000'000));
2845 env(
offer(
alice_, btc(1'000'000'000'000'000), usd(1'000000000)));
2859 testcase(
"Convert all of an asset using DeliverMin");
2861 using namespace jtx;
2864 Env env(*
this, features);
2904 Env env(*
this, features);
2911 AMM const ammBob(env,
bob_,
XRP(1'000), btc(1'100'000));
2922 auto test = [&](
auto&& issue1,
auto&& issue2) {
2926 auto const usd = issue1(
2931 .limit = 3000'000});
2932 auto const btc = issue2(
2937 .limit = 1'000'000});
2944 AMM const ammBob(env,
bob_, usd(1'000), btc(1'100));
2956 Env env(*
this, features);
2963 AMM const ammBob(env,
bob_,
XRP(5'500), btc(1'200'000));
2981 auto test = [&](
auto&& issue1,
auto&& issue2) {
2985 auto const usd = issue1(
2990 .limit = 3000'000});
2991 auto const btc = issue2(
2996 .limit = 1'000'000});
3005 AMM const ammBob(env,
bob_, usd(5'500), btc(1'200));
3024 auto const dan =
Account(
"dan");
3025 Env env(*
this, features);
3032 env(
pay(
gw_, dan, btc(1'100'000'000)));
3035 AMM const ammDan(env, dan,
XRP(1'000), btc(1'100'000'000));
3054 using namespace jtx;
3057 Env env(*
this, features);
3066 AMM const ammAlice(env,
alice_,
XRP(100), btc(140'000));
3076 env(
fset(becky, asfDepositAuth));
3092 using namespace jtx;
3113 auto failedMptPayments = [
this, &env, &btc]() {
3135 failedMptPayments();
3152 failedMptPayments();
3159 failedMptPayments();
3182 Env env(*
this, features);
3188 env.
fund(
XRP(1'000), g1, alice, bob);
3193 .holders = {alice, bob},
3196 env(
pay(g1, bob, btc(10)));
3197 env(
pay(g1, alice, btc(205)));
3200 AMM const ammAlice(env, alice,
XRP(500), btc(105));
3207 env(
pay(alice, bob, btc(1)));
3210 env(
pay(bob, alice, btc(1)));
3214 btc.set({.holder = bob, .flags = tfMPTLock});
3238 btc.set({.holder = bob, .flags = tfMPTUnlock});
3240 env(
pay(bob, alice, btc(1)));
3241 env(
pay(alice, bob, btc(1)));
3252 Env env(*
this, features);
3262 env.
fund(
XRP(20'000), a2, a3, a4);
3267 .holders = {a1, a2, a3, a4},
3273 .holders = {a1, a2, a3, a4},
3276 env(
pay(g1, a1, eth(1'000)));
3277 env(
pay(g1, a2, eth(100)));
3278 env(
pay(g1, a3, btc(100)));
3279 env(
pay(g1, a4, btc(100)));
3282 AMM const ammG1(env, g1,
XRP(10'000), eth(100));
3304 AMM ammA3(env, a3, btc(1),
XRP(1));
3308 env(
pay(g1, a2, eth(1)));
3309 env(
pay(a2, g1, eth(1)));
3310 env(
pay(a2, a1, eth(1)));
3311 env(
pay(a1, a2, eth(1)));
3318 btc.set({.flags = tfMPTLock});
3324 env(
pay(g1, a2, btc(1)));
3325 env(
pay(a2, g1, btc(1)));
3345 testcase(
"Offers for Locked MPTs");
3348 Env env(*
this, features);
3355 env.
fund(
XRP(2'000), g1, a3, a4);
3362 .holders = {a2, a3, a4},
3365 env(
pay(g1, a3, btc(2'000)));
3366 env(
pay(g1, a4, btc(2'001)));
3369 AMM const ammA3(env, a3,
XRP(1'000), btc(1'001));
3379 env(
offer(a4,
XRP(999), btc(999)));
3385 btc.set({.holder = ammA3.
ammAccount(), .flags = tfMPTLock});
3387 BEAST_EXPECT(info[jss::amm][jss::asset2_frozen].asBool());
3398 btc.set({.holder = a4, .flags = tfMPTUnlock});
3402 env(
offer(a2, btc(999),
XRP(999)));
3414 testcase(
"Multisign AMM Transactions");
3416 using namespace jtx;
3417 Env env{*
this, features};
3422 fund(env,
gw_, {alice, becky, zelda},
XRP(20'000));
3427 .holders = {alice, becky, zelda},
3428 .pay = 20'000'000'000,
3433 env(
regkey(alice, alie));
3434 env(
fset(alice, asfDisableMaster),
Sig(alice));
3437 env(
signers(alice, 2, {{becky, 1}, {bogie, 1}}),
Sig(alie));
3439 static constexpr int kSignerListOwners{2};
3442 Msig const ms{becky, bogie};
3459 ammAlice.
deposit(alice, 1'000'000);
3462 ammAlice.
withdraw(alice, 1'000'000);
3465 ammAlice.
vote({}, 1'000);
3468 env(ammAlice.
bid({.account = alice, .bidMin = 100}), ms).
close();
3479 using namespace jtx;
3483 auto test = [&](
auto&& issue1,
auto&& issue2) {
3487 auto const eth = issue1(
3492 .limit = 1'000'000});
3493 auto const btc = issue2(
3498 .limit = 1'000'000});
3506 AMM const bobXrpBtc(env,
bob_,
XRP(1'000), btc(1'000));
3507 AMM const bobBtcEth(env,
bob_, btc(1'000), eth(1'000));
3511 Path(~btc, ~eth, ~btc),
3523 using namespace jtx;
3527 Env env(*
this, features);
3544 AMM const ammXrpBtc(env,
bob_,
XRP(100), btc(100'000));
3547 AMM const ammBtcEth(env,
bob_, btc(100'000), eth(100'000));
3562 Txflags(tfNoRippleDirect | tfPartialPayment),
3567 Env env(*
this, features);
3578 AMM const ammBob(env,
bob_,
XRP(100), btc(100));
3588 Env env(*
this, features);
3599 AMM const ammBob(env,
bob_,
XRP(100), btc(100));
3614 using namespace jtx;
3617 Env env(*
this, features);
3631 AMM const ammBob(env,
bob_,
XRP(100), btc(100'000'000));
3642 auto test = [&](
auto&& issue1,
auto&& issue2,
auto&& issue3) {
3643 Env env(*
this, features);
3648 auto const btc = issue1(
3650 auto const eth = issue2(
3652 auto const cny = issue3(
3660 AMM const ammBobXrpBtc(env,
bob_,
XRP(100), btc(100));
3661 AMM const ammBobBtcEth(env,
bob_, btc(100), eth(100));
3662 AMM const ammBobEthCny(env,
bob_, eth(100), cny(100));
3667 Path(~btc, ~eth, ~btc, ~cny),
3690 using namespace jtx;
3703 using namespace jtx;
3711 using namespace jtx;
3737 using namespace jtx;
3746 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.
json::Value getJson(JsonOptions) const override
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)
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.
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)
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, SeqProxy const &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.
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
STPath stpath(Args const &... args)
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 pathFindMPTAMMExecutableSourceAmount()
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...