1#include <test/jtx/AMM.h>
2#include <test/jtx/AMMTest.h>
3#include <test/jtx/Account.h>
4#include <test/jtx/Env.h>
5#include <test/jtx/PathSet.h>
6#include <test/jtx/TestHelpers.h>
7#include <test/jtx/amount.h>
8#include <test/jtx/balance.h>
9#include <test/jtx/delivermin.h>
10#include <test/jtx/fee.h>
11#include <test/jtx/flags.h>
12#include <test/jtx/jtx_json.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/quality.h>
20#include <test/jtx/rate.h>
21#include <test/jtx/regkey.h>
22#include <test/jtx/require.h>
23#include <test/jtx/sendmax.h>
24#include <test/jtx/sig.h>
25#include <test/jtx/tags.h>
26#include <test/jtx/ter.h>
27#include <test/jtx/trust.h>
28#include <test/jtx/txflags.h>
30#include <xrpl/basics/Number.h>
31#include <xrpl/beast/unit_test/suite.h>
32#include <xrpl/json/json_value.h>
33#include <xrpl/json/to_string.h>
34#include <xrpl/ledger/ApplyView.h>
35#include <xrpl/ledger/OpenView.h>
36#include <xrpl/ledger/PaymentSandbox.h>
37#include <xrpl/ledger/Sandbox.h>
38#include <xrpl/ledger/helpers/OfferHelpers.h>
39#include <xrpl/protocol/AccountID.h>
40#include <xrpl/protocol/Feature.h>
41#include <xrpl/protocol/Indexes.h>
42#include <xrpl/protocol/Issue.h>
43#include <xrpl/protocol/KeyType.h>
44#include <xrpl/protocol/LedgerFormats.h>
45#include <xrpl/protocol/SField.h>
46#include <xrpl/protocol/STPathSet.h>
47#include <xrpl/protocol/Seed.h>
48#include <xrpl/protocol/TER.h>
49#include <xrpl/protocol/TxFlags.h>
50#include <xrpl/protocol/UintTypes.h>
51#include <xrpl/protocol/XRPAmount.h>
52#include <xrpl/protocol/jss.h>
53#include <xrpl/tx/paths/Flow.h>
54#include <xrpl/tx/paths/detail/Steps.h>
83 testcase(
"Incorrect Removal of Funded Offers");
96 Env env{*
this, features};
121 if (!features[fixAMMv1_1])
124 STAmount{BTC, UINT64_C(1'001'000000374812), -12},
USD(100'000), ammCarol.
tokens()));
129 STAmount{BTC, UINT64_C(1'001'000000374815), -12},
USD(100'000), ammCarol.
tokens()));
144 Env env{*
this, features};
149 auto const usD1 = gw1[
"USD"];
150 auto const usD2 = gw2[
"USD"];
155 env(
trust(
bob_, usD1(1'000), tfSetNoRipple));
157 env(
trust(
bob_, usD2(1'000), tfSetNoRipple));
160 env(
pay(gw1, dan, usD1(10'000)));
165 AMM const ammDan(env, dan,
XRP(10'000), usD1(10'000));
176 Env env{*
this, features};
181 auto const usD1 = gw1[
"USD"];
182 auto const usD2 = gw2[
"USD"];
191 env(
pay(gw1, dan, usD1(10'050)));
196 AMM const ammDan(env, dan,
XRP(10'000), usD1(10'050));
217 auto const startBalance =
XRP(1'000'000);
223 [&](
AMM& ammAlice,
Env& env) {
242 {{
XRP(10'100),
USD(10'000)}},
250 [&](
AMM& ammAlice,
Env& env) {
265 {{
XRP(10'100),
USD(10'000)}},
272 [&](
AMM& ammAlice,
Env& env) {
281 {{
XRP(10'100),
USD(10'000)}},
288 [&](
AMM& ammAlice,
Env& env) {
303 {{
XRP(11'000),
USD(9'000)}},
312 testcase(
"Offer Crossing with XRP, Normal order");
316 Env env{*
this, features};
325 auto const xrpTransferred =
XRPAmount{3'061'224'490};
328 BEAST_EXPECT(ammAlice.expectBalances(
329 XRP(150'000) + xrpTransferred,
USD(49),
IOUAmount{273'861'278752583, -8}));
340 testcase(
"Offer Crossing with Limit Override");
344 Env env{*
this, features};
359 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-1");
362 jrr[jss::node][sfBalance.fieldName] ==
369 testcase(
"Currency Conversion: Entire Offer");
373 Env env{*
this, features};
394 jrr[jss::node][sfBalance.fieldName] ==
401 testcase(
"Currency Conversion: In Parts");
406 [&](
AMM& ammAlice,
Env& env) {
426 {{
XRP(10'000),
USD(10'000)}},
435 testcase(
"Cross Currency Payment: Start with XRP");
440 [&](
AMM& ammAlice,
Env& env) {
449 {{
XRP(10'000),
USD(10'100)}},
458 testcase(
"Cross Currency Payment: End with XRP");
463 [&](
AMM& ammAlice,
Env& env) {
473 {{
XRP(10'100),
USD(10'000)}},
482 testcase(
"Cross Currency Payment: Bridged");
486 Env env{*
this, features};
488 auto const gw1 =
Account{
"gateway_1"};
489 auto const gw2 =
Account{
"gateway_2"};
490 auto const dan =
Account{
"dan"};
491 auto const usD1 = gw1[
"USD"];
492 auto const euR1 = gw2[
"EUR"];
501 env(
trust(dan, euR1(1'000)));
507 env(
pay(gw2, dan, dan[
"EUR"](400)));
510 AMM const ammCarol(env,
carol_, usD1(5'000),
XRP(50'000));
512 env(
offer(dan,
XRP(500), euR1(50)));
516 jtp[0u][0u][jss::currency] =
"XRP";
520 XRP(49'700),
STAmount{usD1, UINT64_C(5'030'181086519115), -12}, ammCarol.
tokens()));
528 testcase(
"Offer Fees Consume Funds");
532 Env env{*
this, features};
534 auto const gw1 =
Account{
"gateway_1"};
535 auto const gw2 =
Account{
"gateway_2"};
536 auto const gw3 =
Account{
"gateway_3"};
537 auto const localAlice =
Account{
"alice"};
538 auto const localBob =
Account{
"bob"};
539 auto const usD1 = gw1[
"USD"];
540 auto const usD2 = gw2[
"USD"];
541 auto const usD3 = gw3[
"USD"];
549 auto const startingXrp =
550 XRP(100) + env.
current()->fees().accountReserve(3, 1) + env.
current()->fees().base * 4;
552 env.
fund(startingXrp, gw1, gw2, gw3, localAlice);
553 env.
fund(
XRP(2'000), localBob);
556 env(
trust(localAlice, usD1(1'000)));
557 env(
trust(localAlice, usD2(1'000)));
558 env(
trust(localAlice, usD3(1'000)));
559 env(
trust(localBob, usD1(1'200)));
560 env(
trust(localBob, usD2(1'100)));
562 env(
pay(gw1, localBob, localBob[
"USD"](1'200)));
564 AMM const ammBob(env, localBob,
XRP(1'000), usD1(1'200));
567 env(
offer(localAlice, usD1(200),
XRP(200)));
572 XRP(1'100),
STAmount{usD1, UINT64_C(1'090'909090909091), -12}, ammBob.
tokens()));
575 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"109.090909090909");
577 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName] ==
XRP(350).value().getText());
583 testcase(
"Offer Create, then Cross");
587 Env env{*
this, features};
606 BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] ==
"-0.8995000001");
612 testcase(
"Offer tfSell: Basic Sell");
617 [&](
AMM& ammAlice,
Env& env) {
626 {{
XRP(9'900),
USD(10'100)}},
635 testcase(
"Offer tfSell: 2x Sell Exceed Limit");
639 Env env{*
this, features};
641 auto const startingXrp =
XRP(100) +
reserve(env, 1) + env.
current()->fees().base * 2;
668 testcase(
"Client Issue: Gateway Cross Currency");
672 Env env{*
this, features};
674 auto const xts =
gw_[
"XTS"];
675 auto const xxx =
gw_[
"XXX"];
677 auto const startingXrp =
XRP(100.1) +
reserve(env, 1) + env.
current()->fees().base * 2;
680 AMM const ammAlice(env,
alice_, xts(100), xxx(100));
684 payment[jss::id] = env.
seq(
bob_);
685 payment[jss::build_path] =
true;
687 payment[jss::tx_json][jss::Sequence] =
690 payment[jss::tx_json][jss::SendMax] =
692 payment[jss::tx_json][jss::Flags] = tfPartialPayment;
693 auto const jrr = env.
rpc(
"json",
"submit",
to_string(payment));
694 BEAST_EXPECT(jrr[jss::result][jss::status] ==
"success");
695 BEAST_EXPECT(jrr[jss::result][jss::engine_result] ==
"tesSUCCESS");
696 if (!features[fixAMMv1_1])
698 BEAST_EXPECT(ammAlice.expectBalances(
699 STAmount(xts, UINT64_C(101'010101010101), -12), xxx(99), ammAlice.tokens()));
704 BEAST_EXPECT(ammAlice.expectBalances(
705 STAmount(xts, UINT64_C(101'0101010101011), -13), xxx(99), ammAlice.tokens()));
719 Env env{*
this, features};
737 BEAST_EXPECT(ammAlice.expectBalances(
XRP(10'100),
USD(10'000), ammAlice.tokens()));
745 Env env{*
this, features};
765 BEAST_EXPECT(ammAlice.expectBalances(
XRP(10'100),
USD(10'000), ammAlice.tokens()));
773 Env env{*
this, features};
806 testcase(
"Combine tfSell with tfFillOrKill");
814 Env env{*
this, features};
820 BEAST_EXPECT(ammBob.expectBalances(
XRP(20'000),
USD(200), ammBob.tokens()));
824 Env env{*
this, features};
831 BEAST_EXPECT(ammBob.expectBalances(
832 XRP(20'220),
STAmount{
USD, UINT64_C(197'8239366963403), -13}, ammBob.tokens()));
840 Env env{*
this, features};
847 BEAST_EXPECT(ammBob.expectBalances(
848 XRP(21'500),
STAmount{
USD, UINT64_C(186'046511627907), -12}, ammBob.tokens()));
859 Env env{*
this, features};
879 [&](
AMM& ammAlice,
Env& env) {
891 {{
XRP(10'000),
USD(10'100)}},
899 [&](
AMM& ammAlice,
Env& env) {
911 {{
XRP(10'100),
USD(10'000)}},
918 Env env{*
this, features};
949 Env env{*
this, features};
984 Env env{*
this, features};
1027 Env env{*
this, features};
1072 using namespace jtx;
1074 Env env{*
this, features};
1076 auto const usdBob =
bob_[
"USD"];
1077 auto const f = env.
current()->fees().base;
1081 AMM const ammBob(env,
bob_,
XRP(10'000), usdBob(10'100));
1099 using namespace jtx;
1101 Env env{*
this, features};
1104 auto const fee = env.
current()->fees().base;
1107 auto const ann =
Account(
"ann");
1108 auto const aBux = ann[
"BUX"];
1109 auto const localBob =
Account(
"bob");
1110 auto const cam =
Account(
"cam");
1111 auto const dan =
Account(
"dan");
1112 auto const dBux = dan[
"BUX"];
1115 env.
fund(
reserve(env, 4) + (fee * 4), ann, localBob, cam, dan);
1118 env(
trust(localBob, aBux(400)));
1120 env(
trust(cam, dBux(100)));
1122 env(
pay(dan, localBob, dBux(100)));
1126 env(
pay(ann, cam, dBux(60)),
Path(localBob, dan),
Sendmax(aBux(200)));
1138 AMM const ammBob(env, localBob, aBux(30), dBux(30));
1140 env(
trust(ann, dBux(100)));
1166 using namespace jtx;
1168 Env env{*
this, features};
1170 auto const ann =
Account(
"ann");
1171 auto const localBob =
Account(
"bob");
1172 auto const cam =
Account(
"cam");
1173 auto const carol =
Account(
"carol");
1174 auto const aBux = ann[
"BUX"];
1175 auto const bBux = localBob[
"BUX"];
1177 auto const fee = env.
current()->fees().base;
1179 env.
fund(
reserve(env, 4) + (fee * 5), ann, localBob, cam);
1182 env(
trust(ann, bBux(40)));
1183 env(
trust(cam, aBux(40)));
1184 env(
trust(localBob, aBux(30)));
1185 env(
trust(cam, bBux(40)));
1186 env(
trust(carol, bBux(400)));
1187 env(
trust(carol, aBux(400)));
1190 env(
pay(ann, cam, aBux(35)));
1191 env(
pay(localBob, cam, bBux(35)));
1192 env(
pay(localBob, carol, bBux(400)));
1193 env(
pay(ann, carol, aBux(400)));
1195 AMM const ammCarol(env, carol, aBux(300), bBux(330));
1200 env(
offer(cam, aBux(29), bBux(30), tfPassive));
1207 env(
offer(cam, bBux(30), aBux(30)));
1210 if (!features[fixAMMv1_1])
1213 STAmount{aBux, UINT64_C(309'3541659651605), -13},
1214 STAmount{bBux, UINT64_C(320'0215509984417), -13},
1221 STAmount{bBux, UINT64_C(20'0215509984417), -13},
1222 STAmount{aBux, UINT64_C(20'0215509984417), -13}}}}));
1227 STAmount{aBux, UINT64_C(309'3541659651604), -13},
1228 STAmount{bBux, UINT64_C(320'0215509984419), -13},
1235 STAmount{bBux, UINT64_C(20'0215509984419), -13},
1236 STAmount{aBux, UINT64_C(20'0215509984419), -13}}}}));
1245 using namespace jtx;
1247 Env env{*
this, features};
1249 auto const aliceUSD =
alice_[
"USD"];
1250 auto const bobUSD =
bob_[
"USD"];
1256 env(
fset(
gw_, asfRequireAuth));
1295 testcase(
"lsfRequireAuth, unauthorized AMM pseudo-account");
1297 using namespace jtx;
1299 bool const pseudoExempt = features[fixCleanup3_4_0];
1301 Env env{*
this, features};
1303 auto const aliceUSD =
alice_[
"USD"];
1304 auto const bobUSD =
bob_[
"USD"];
1309 env(
fset(
gw_, asfRequireAuth));
1323 auto const ammLineAuthorized = [&]() ->
bool {
1326 if (!BEAST_EXPECT(line))
1328 return line->isFlag(
1329 ammAlice.
ammAccount() >
USD.issue().account ? lsfLowAuth : lsfHighAuth);
1331 BEAST_EXPECT(!ammLineAuthorized());
1357 BEAST_EXPECT(!ammLineAuthorized());
1365 using namespace jtx;
1367 Env env{*
this, features};
1377 env(
fset(
gw_, asfRequireAuth));
1429 using namespace jtx;
1465 using namespace jtx;
1478 BEAST_EXPECT(st.
empty());
1482 BEAST_EXPECT(sa ==
XRP(100'000'000));
1495 using namespace jtx;
1498 auto const aud =
gw_[
"AUD"];
1513 BEAST_EXPECT(std::get<0>(result).empty());
1520 using namespace jtx;
1521 auto const charlie =
Account(
"charlie");
1526 AMM const ammCharlie(env, charlie,
XRP(10),
USD(11));
1528 BEAST_EXPECT(sa ==
XRP(1));
1530 if (BEAST_EXPECT(st.size() == 1 && st[0].size() == 1))
1532 auto const& pathElem = st[0][0];
1534 pathElem.isOffer() && pathElem.getIssuerID() ==
gw_.id() &&
1535 pathElem.getCurrency() ==
USD.currency);
1542 AMM const ammCharlie(env, charlie,
XRP(11),
USD(10));
1545 BEAST_EXPECT(sa ==
USD(1));
1547 if (BEAST_EXPECT(st.size() == 1 && st[0].size() == 1))
1549 auto const& pathElem = st[0][0];
1551 pathElem.isOffer() && pathElem.getIssuerID() ==
xrpAccount() &&
1560 testcase(
"Path Find: XRP -> XRP and XRP -> IOU");
1561 using namespace jtx;
1573 env.
fund(
XRP(1'000), a3, g1, g2, g3);
1577 env.
trust(g1[
"XYZ"](5'000), a1);
1578 env.
trust(g3[
"ABC"](5'000), a1);
1579 env.
trust(g2[
"XYZ"](5'000), a2);
1580 env.
trust(g3[
"ABC"](5'000), a2);
1581 env.
trust(a2[
"ABC"](1'000), a3);
1582 env.
trust(g1[
"XYZ"](100'000), m1);
1583 env.
trust(g2[
"XYZ"](100'000), m1);
1584 env.
trust(g3[
"ABC"](100'000), m1);
1587 env(
pay(g1, a1, g1[
"XYZ"](3'500)));
1588 env(
pay(g3, a1, g3[
"ABC"](1'200)));
1589 env(
pay(g1, m1, g1[
"XYZ"](25'000)));
1590 env(
pay(g2, m1, g2[
"XYZ"](25'000)));
1591 env(
pay(g3, m1, g3[
"ABC"](25'000)));
1594 AMM const ammM1G1G2(env, m1, g1[
"XYZ"](1'000), g2[
"XYZ"](1'000));
1595 AMM const ammM1XrpG3(env, m1,
XRP(10'000), g3[
"ABC"](1'000));
1601 auto const& sendAmt =
XRP(10);
1603 BEAST_EXPECT(
equal(da, sendAmt));
1604 BEAST_EXPECT(st.
empty());
1610 auto const& sendAmt =
XRP(200);
1613 BEAST_EXPECT(
equal(da, sendAmt));
1614 BEAST_EXPECT(st.
empty());
1618 auto const& sendAmt = g3[
"ABC"](10);
1620 BEAST_EXPECT(
equal(da, sendAmt));
1626 auto const& sendAmt = a2[
"ABC"](1);
1628 BEAST_EXPECT(
equal(da, sendAmt));
1634 auto const& sendAmt = a3[
"ABC"](1);
1636 BEAST_EXPECT(
equal(da, sendAmt));
1645 testcase(
"Path Find: non-XRP -> XRP");
1646 using namespace jtx;
1653 env.
fund(
XRP(1'000), a1, a2, g3);
1657 env.
trust(g3[
"ABC"](1'000), a1, a2);
1658 env.
trust(g3[
"ABC"](100'000), m1);
1661 env(
pay(g3, a1, g3[
"ABC"](1'000)));
1662 env(
pay(g3, a2, g3[
"ABC"](1'000)));
1663 env(
pay(g3, m1, g3[
"ABC"](1'200)));
1666 AMM const ammM1(env, m1, g3[
"ABC"](1'000),
XRP(10'010));
1671 auto const& sendAmt =
XRP(10);
1672 std::tie(st, sa, da) =
findPaths(env, a1, a2, sendAmt, std::nullopt, a2[
"ABC"].currency);
1673 BEAST_EXPECT(
equal(da, sendAmt));
1674 BEAST_EXPECT(
equal(sa, a1[
"ABC"](1)));
1681 testcase(
"Path Find: non-XRP -> non-XRP, same currency");
1682 using namespace jtx;
1695 env.
fund(
XRP(1'000), a1, a2, a3, g1, g2, g3, g4);
1697 env.
fund(
XRP(21'000), m1, m2);
1700 env.
trust(g1[
"HKD"](2'000), a1);
1701 env.
trust(g2[
"HKD"](2'000), a2);
1702 env.
trust(g1[
"HKD"](2'000), a3);
1703 env.
trust(g1[
"HKD"](100'000), m1);
1704 env.
trust(g2[
"HKD"](100'000), m1);
1705 env.
trust(g1[
"HKD"](100'000), m2);
1706 env.
trust(g2[
"HKD"](100'000), m2);
1709 env(
pay(g1, a1, g1[
"HKD"](1'000)));
1710 env(
pay(g2, a2, g2[
"HKD"](1'000)));
1711 env(
pay(g1, a3, g1[
"HKD"](1'000)));
1712 env(
pay(g1, m1, g1[
"HKD"](1'200)));
1713 env(
pay(g2, m1, g2[
"HKD"](5'000)));
1714 env(
pay(g1, m2, g1[
"HKD"](1'200)));
1715 env(
pay(g2, m2, g2[
"HKD"](5'000)));
1718 AMM const ammM1(env, m1, g1[
"HKD"](1'010), g2[
"HKD"](1'000));
1719 AMM const ammM2XrpG2(env, m2,
XRP(10'000), g2[
"HKD"](1'010));
1720 AMM const ammM2G1Xrp(env, m2, g1[
"HKD"](1'010),
XRP(10'000));
1728 auto const& sendAmt = g1[
"HKD"](10);
1730 findPaths(env, a1, g1, sendAmt, std::nullopt, g1[
"HKD"].currency);
1731 BEAST_EXPECT(st.
empty());
1732 BEAST_EXPECT(
equal(da, sendAmt));
1733 BEAST_EXPECT(
equal(sa, a1[
"HKD"](10)));
1739 auto const& sendAmt = a1[
"HKD"](10);
1741 findPaths(env, a1, g1, sendAmt, std::nullopt, g1[
"HKD"].currency);
1742 BEAST_EXPECT(st.
empty());
1743 BEAST_EXPECT(
equal(da, sendAmt));
1744 BEAST_EXPECT(
equal(sa, a1[
"HKD"](10)));
1750 auto const& sendAmt = a3[
"HKD"](10);
1752 findPaths(env, a1, a3, sendAmt, std::nullopt, g1[
"HKD"].currency);
1753 BEAST_EXPECT(
equal(da, sendAmt));
1754 BEAST_EXPECT(
equal(sa, a1[
"HKD"](10)));
1761 auto const& sendAmt = g2[
"HKD"](10);
1763 findPaths(env, g1, g2, sendAmt, std::nullopt, g1[
"HKD"].currency);
1764 BEAST_EXPECT(
equal(da, sendAmt));
1765 BEAST_EXPECT(
equal(sa, g1[
"HKD"](10)));
1777 auto const& sendAmt = g2[
"HKD"](10);
1779 findPaths(env, a1, g2, sendAmt, std::nullopt, g1[
"HKD"].currency);
1780 BEAST_EXPECT(
equal(da, sendAmt));
1781 BEAST_EXPECT(
equal(sa, a1[
"HKD"](10)));
1794 auto const& sendAmt = a2[
"HKD"](10);
1796 findPaths(env, a1, a2, sendAmt, std::nullopt, g1[
"HKD"].currency);
1797 BEAST_EXPECT(
equal(da, sendAmt));
1798 BEAST_EXPECT(
equal(sa, a1[
"HKD"](10)));
1811 testcase(
"Path Find: non-XRP -> non-XRP, same currency");
1812 using namespace jtx;
1822 env.
fund(
XRP(1'000), a1, a2, a3, g1, g2);
1825 env.
trust(g1[
"HKD"](2'000), a1);
1826 env.
trust(g2[
"HKD"](2'000), a2);
1827 env.
trust(a2[
"HKD"](2'000), a3);
1828 env.
trust(g1[
"HKD"](100'000), m1);
1829 env.
trust(g2[
"HKD"](100'000), m1);
1832 env(
pay(g1, a1, g1[
"HKD"](1'000)));
1833 env(
pay(g2, a2, g2[
"HKD"](1'000)));
1834 env(
pay(g1, m1, g1[
"HKD"](5'000)));
1835 env(
pay(g2, m1, g2[
"HKD"](5'000)));
1838 AMM const ammM1(env, m1, g1[
"HKD"](1'010), g2[
"HKD"](1'000));
1842 auto const& sendAmt = a2[
"HKD"](10);
1845 std::tie(st, sa, da) =
findPaths(env, g1, a2, sendAmt, std::nullopt, g1[
"HKD"].currency);
1846 BEAST_EXPECT(
equal(da, sendAmt));
1847 BEAST_EXPECT(
equal(sa, g1[
"HKD"](10)));
1856 using namespace jtx;
1858 Env env(*
this, features);
1864 auto const ammXrpPool = env.
current()->fees().increment * 2;
1881 AMM const ammBob(env,
bob_, ammXrpPool,
USD(150));
1886 Txflags(tfNoRippleDirect | tfPartialPayment));
1889 BEAST_EXPECT(carolUSD >
USD(0) && carolUSD <
USD(50));
1897 using namespace jtx;
1901 Env env(*
this, features);
1913 BEAST_EXPECT(ammBob.expectBalances(
BTC(150),
USD(100), ammBob.tokens()));
1917 Env env(*
this, features);
1930 BEAST_EXPECT(ammBobBtcXrp.expectBalances(
BTC(150),
XRP(100), ammBobBtcXrp.tokens()));
1935 Env env(*
this, features);
1947 BEAST_EXPECT(ammBob.expectBalances(
XRP(150),
USD(100), ammBob.tokens()));
1951 Env env(*
this, features);
1963 BEAST_EXPECT(ammBob.expectBalances(
USD(150),
XRP(100), ammBob.tokens()));
1967 Env env(*
this, features);
2016 Env env(*
this, features);
2049 auto const flowResult = [&] {
2086 BEAST_EXPECT(flowResult.removableOffers.size() == 1);
2088 if (flowResult.removableOffers.empty())
2091 for (
auto const& o : flowResult.removableOffers)
2115 Env env(*
this, features);
2135 Txflags(tfNoRippleDirect | tfPartialPayment));
2138 BEAST_EXPECT(ammBob.expectBalances(
USD(8.4),
XRPAmount{20}, ammBob.tokens()));
2146 using namespace jtx;
2150 Env env(*
this, features);
2161 Txflags(tfNoRippleDirect | tfPartialPayment));
2167 if (!features[fixAMMv1_1])
2170 BEAST_EXPECT(
amm.expectBalances(
2175 BEAST_EXPECT(
amm.expectBalances(
2186 Env env(*
this, features);
2206 Txflags(tfNoRippleDirect | tfPartialPayment));
2219 BEAST_EXPECT(
amm.expectBalances(
2227 Env env(*
this, features);
2240 AMM const amm2(env, ed,
EUR(1'000),
USD(1'000));
2245 Txflags(tfNoRippleDirect | tfPartialPayment));
2249 if (!features[fixAMMv1_1])
2283 Env env(*
this, features);
2294 BEAST_EXPECT(
amm.expectBalances(
USD(1'100),
EUR(1'000),
amm.tokens()));
2302 Env env(*
this, features);
2315 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2324 BEAST_EXPECT(
amm.expectBalances(
2325 STAmount{GBP, UINT64_C(1'142'857142857143), -12},
USD(875),
amm.tokens()));
2333 Env env(*
this, features);
2346 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2349 if (!features[fixAMMv1_1])
2356 BEAST_EXPECT(
amm.expectBalances(
GBP(1'024),
USD(1'171.875),
amm.tokens()));
2366 BEAST_EXPECT(
amm.expectBalances(
2367 STAmount{GBP, UINT64_C(1'024'000000000001), -12},
2378 Env env(*
this, features);
2400 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2403 if (!features[fixAMMv1_1])
2416 STAmount{
GBP, UINT64_C(1'470'421052631579), -12}));
2423 STAmount{
EUR, UINT64_C(929'5789473684212), -13}}}));
2426 BEAST_EXPECT(
amm.expectBalances(
2427 STAmount{EUR, UINT64_C(1'056'336842105263), -12},
2428 STAmount{USD, UINT64_C(1'325'334821428571), -12},
2444 STAmount{
GBP, UINT64_C(1'470'42105263158), -11}));
2451 STAmount{
EUR, UINT64_C(929'57894736842), -11}}}));
2454 BEAST_EXPECT(
amm.expectBalances(
2455 STAmount{EUR, UINT64_C(1'056'336842105264), -12},
2456 STAmount{USD, UINT64_C(1'325'334821428571), -12},
2466 Env env(*
this, features);
2488 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2491 if (!features[fixAMMv1_1])
2503 BEAST_EXPECT(
amm.expectBalances(
2504 STAmount{GBP, UINT64_C(1'056'336842105263), -12},
2505 STAmount{EUR, UINT64_C(946'6677295918366), -13},
2520 BEAST_EXPECT(
amm.expectBalances(
2521 STAmount{GBP, UINT64_C(1'056'336842105264), -12},
2522 STAmount{EUR, UINT64_C(946'6677295918366), -13},
2531 STAmount{
EUR, UINT64_C(1'442'665816326531), -12}));
2538 STAmount{
USD, UINT64_C(1'340'267857142857), -12}}}));
2546 Env env(*
this, features);
2559 AMM const amm2(env, ed,
EUR(1'000),
USD(1'400));
2566 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2569 if (!features[fixAMMv1_1])
2578 STAmount{GBP, UINT64_C(1'086'024691358025), -12},
2579 STAmount{EUR, UINT64_C(920'78937795562), -11},
2584 STAmount{EUR, UINT64_C(1'063'368497635504), -12},
2585 STAmount{USD, UINT64_C(1'316'570881226053), -12},
2597 STAmount{GBP, UINT64_C(1'086'024691358027), -12},
2598 STAmount{EUR, UINT64_C(920'7893779556188), -13},
2603 STAmount{EUR, UINT64_C(1'063'368497635505), -12},
2604 STAmount{USD, UINT64_C(1'316'570881226053), -12},
2614 Env env(*
this, features);
2629 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2632 if (!features[fixAMMv1_1])
2636 STAmount{GBP, UINT64_C(1'108'148148148149), -12},
2637 STAmount{EUR, UINT64_C(902'4064171122988), -13},
2642 STAmount{EUR, UINT64_C(1'078'074866310161), -12},
2643 STAmount{USD, UINT64_C(1'298'611111111111), -12},
2650 STAmount{GBP, UINT64_C(1'108'148148148151), -12},
2651 STAmount{EUR, UINT64_C(902'4064171122975), -13},
2656 STAmount{EUR, UINT64_C(1'078'074866310162), -12},
2657 STAmount{USD, UINT64_C(1'298'611111111111), -12},
2674 using namespace jtx;
2687 Txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality));
2689 BEAST_EXPECT(ammBob.expectBalances(
XRP(1'050),
USD(1'000), ammBob.tokens()));
2700 using namespace jtx;
2738 auto const jpy =
gw_[
"JPY"];
2746 AMM const ammAliceXrpJpy(env,
alice_,
XRP(100), jpy(100));
2761 using namespace jtx;
2762 Env env(*
this, features);
2763 auto const dan =
Account(
"dan");
2764 auto const ed =
Account(
"ed");
2775 AMM const ammEd(env, ed,
XRP(9),
USD(11));
2780 if (!features[fixAMMv1_1])
2808 testcase(
"Convert all of an asset using DeliverMin");
2810 using namespace jtx;
2813 Env env(*
this, features);
2847 Env env(*
this, features);
2861 Env env(*
this, features);
2882 auto const dan =
Account(
"dan");
2883 Env env(*
this, features);
2891 AMM const ammDan(env, dan,
XRP(1'000),
USD(1'100));
2892 if (!features[fixAMMv1_1])
2914 STAmount{USD, UINT64_C(999'99999909091), -11},
2925 using namespace jtx;
2931 Env env(*
this, features);
2951 env(
fset(becky, asfDepositAuth));
2967 using namespace jtx;
2988 auto failedIouPayments = [
this, &env]() {
3010 failedIouPayments();
3027 failedIouPayments();
3034 failedIouPayments();
3057 Env env(*
this, features);
3063 env.
fund(
XRP(1'000), g1, alice, bob);
3066 env.
trust(g1[
"USD"](100), bob);
3067 env.
trust(g1[
"USD"](205), alice);
3070 env(
pay(g1, bob, g1[
"USD"](10)));
3071 env(
pay(g1, alice, g1[
"USD"](205)));
3074 AMM const ammAlice(env, alice,
XRP(500), g1[
"USD"](105));
3080 BEAST_EXPECT(lines[jss::lines][0u][jss::account] == g1.
human());
3081 BEAST_EXPECT(lines[jss::lines][0u][jss::limit] ==
"100");
3082 BEAST_EXPECT(lines[jss::lines][0u][jss::balance] ==
"10");
3089 BEAST_EXPECT(lines[jss::lines][0u][jss::account] == g1.
human());
3090 BEAST_EXPECT(lines[jss::lines][0u][jss::limit] ==
"205");
3092 BEAST_EXPECT(lines[jss::lines][0u][jss::balance] ==
"100");
3097 env(
pay(alice, bob, g1[
"USD"](1)));
3100 env(
pay(bob, alice, g1[
"USD"](1)));
3105 env(
trust(g1, bob[
"USD"](0), tfSetFreeze));
3111 env(
offer(bob, g1[
"USD"](5),
XRP(25)));
3121 env(
pay(alice, bob, g1[
"USD"](1)));
3132 for (
auto const& it : lines[jss::lines])
3134 if (it[jss::account] == bob.
human())
3140 if (!BEAST_EXPECT(bobLine))
3142 BEAST_EXPECT(bobLine[jss::freeze] ==
true);
3143 BEAST_EXPECT(bobLine[jss::balance] ==
"-16");
3150 for (
auto const& it : lines[jss::lines])
3152 if (it[jss::account] == g1.
human())
3158 if (!BEAST_EXPECT(g1Line))
3160 BEAST_EXPECT(g1Line[jss::freeze_peer] ==
true);
3161 BEAST_EXPECT(g1Line[jss::balance] ==
"16");
3167 env(
trust(g1, bob[
"USD"](0), tfClearFreeze));
3172 auto ff = affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName];
3174 ff[sfLowLimit.fieldName] ==
3176 BEAST_EXPECT(!(ff[jss::Flags].asUInt() & lsfLowFreeze));
3177 BEAST_EXPECT(!(ff[jss::Flags].asUInt() & lsfHighFreeze));
3188 Env env(*
this, features);
3198 env.
fund(
XRP(20'000), a2, a3, a4);
3201 env.
trust(g1[
"USD"](1'200), a1);
3202 env.
trust(g1[
"USD"](200), a2);
3203 env.
trust(g1[
"BTC"](100), a3);
3204 env.
trust(g1[
"BTC"](100), a4);
3207 env(
pay(g1, a1, g1[
"USD"](1'000)));
3208 env(
pay(g1, a2, g1[
"USD"](100)));
3209 env(
pay(g1, a3, g1[
"BTC"](100)));
3210 env(
pay(g1, a4, g1[
"BTC"](100)));
3213 AMM const ammG1(env, g1,
XRP(10'000), g1[
"USD"](100));
3222 auto offers = env.
rpc(
3223 "book_offers",
std::string(
"USD/") + g1.
human(),
"XRP")[jss::result][jss::offers];
3227 for (
auto const&
offer : offers)
3235 "book_offers",
"XRP",
std::string(
"USD/") + g1.
human())[jss::result][jss::offers];
3239 for (
auto const&
offer : offers)
3250 AMM ammA3(env, a3, g1[
"BTC"](1),
XRP(1));
3256 env(
pay(g1, a2, g1[
"USD"](1)));
3259 env(
pay(a2, g1, g1[
"USD"](1)));
3262 env(
pay(a2, a1, g1[
"USD"](1)));
3265 env(
pay(a1, a2, g1[
"USD"](1)));
3274 env(
fset(g1, asfGlobalFreeze));
3288 auto offers = env.
rpc(
3289 "book_offers",
"XRP",
std::string(
"USD/") + g1.
human())[jss::result][jss::offers];
3294 "book_offers",
std::string(
"USD/") + g1.
human(),
"XRP")[jss::result][jss::offers];
3302 env(
pay(g1, a2, g1[
"USD"](1)));
3305 env(
pay(a2, g1, g1[
"USD"](1)));
3315 testcase(
"Offers for Frozen Trust Lines");
3318 Env env(*
this, features);
3325 env.
fund(
XRP(2'000), g1, a3, a4);
3329 env.
trust(g1[
"USD"](1'000), a2);
3330 env.
trust(g1[
"USD"](2'000), a3);
3331 env.
trust(g1[
"USD"](2'001), a4);
3334 env(
pay(g1, a3, g1[
"USD"](2'000)));
3335 env(
pay(g1, a4, g1[
"USD"](2'001)));
3338 AMM const ammA3(env, a3,
XRP(1'000), g1[
"USD"](1'001));
3348 env(
offer(a4,
XRP(999), g1[
"USD"](999)));
3355 env(
trust(g1, a3am, tfSetFreeze));
3357 BEAST_EXPECT(info[jss::amm][jss::asset2_frozen].asBool());
3368 env(
trust(g1, a4[
"USD"](0), tfSetFreeze));
3372 env(
offer(a2, g1[
"USD"](999),
XRP(999)));
3384 testcase(
"Multisign AMM Transactions");
3386 using namespace jtx;
3387 Env env{*
this, features};
3392 fund(env,
gw_, {alice, becky, zelda},
XRP(20'000), {
USD(20'000)});
3396 env(
regkey(alice, alie));
3397 env(
fset(alice, asfDisableMaster),
Sig(alice));
3400 env(
signers(alice, 2, {{becky, 1}, {bogie, 1}}),
Sig(alie));
3404 Msig const ms{becky, bogie};
3421 ammAlice.
deposit(alice, 1'000'000);
3424 ammAlice.
withdraw(alice, 1'000'000);
3427 ammAlice.
vote({}, 1'000);
3430 env(ammAlice.
bid({.account = alice, .bidMin = 100}), ms).
close();
3441 using namespace jtx;
3445 Env env(*
this, features);
3463 using namespace jtx;
3467 Env env(*
this, features);
3468 auto const bobUsd =
bob_[
"USD"];
3469 auto const bobEur =
bob_[
"EUR"];
3476 AMM const ammBobXrpUsd(env,
bob_,
XRP(100), bobUsd(100));
3479 AMM const ammBobUsdEur(env,
bob_, bobUsd(100), bobEur(100));
3494 Txflags(tfNoRippleDirect | tfPartialPayment),
3499 Env env(*
this, features);
3513 Env env(*
this, features);
3532 using namespace jtx;
3534 auto const cny =
gw_[
"CNY"];
3537 Env env(*
this, features);
3558 Env env(*
this, features);
3572 AMM const ammBobEurCny(env,
bob_,
EUR(100), cny(100));
3598 using namespace jtx;
3611 using namespace jtx;
3619 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.
A currency issued by an account.
Sets the new scale and restores the old scale when it leaves scope.
bool modify(ModifyType const &f)
Modify the open ledger.
Writable ledger view that accumulates state and tx changes.
A wrapper which makes credits unavailable to balances.
bool pushBack(STPath const &e)
pushBack adds a path to the set.
Discardable, editable view to a ledger.
virtual beast::Journal getJournal(std::string const &name)=0
virtual OpenLedger & getOpenLedger()=0
SLE::pointer peek(Keylet const &k) override
Prepare to modify the SLE associated with key.
Tests of AMM that use offers too.
void testRippleState(FeatureBitset features)
void testOfferFeesConsumeFunds(FeatureBitset features)
void testTransferRateOffer(FeatureBitset features)
void testCrossCurrencyBridged(FeatureBitset features)
void testOffersWhenFrozen(FeatureBitset features)
void testDirectToDirectPath(FeatureBitset features)
void testTransferRateNoOwnerFee(FeatureBitset features)
void testFillModes(FeatureBitset features)
void pathFindConsumeAll()
void testSellFlagExceedLimit(FeatureBitset features)
void testRmFundedOffer(FeatureBitset features)
void viaOffersViaGateway()
void testSelfIssueOffer(FeatureBitset features)
void testStepLimit(FeatureBitset features)
void testSellFlagBasic(FeatureBitset features)
void testTxMultisign(FeatureBitset features)
void testEnforceNoRipple(FeatureBitset features)
void testGlobalFreeze(FeatureBitset features)
void testLoop(FeatureBitset features)
void testBadPathAssert(FeatureBitset features)
void run() override
Runs the suite.
void testBridgedCross(FeatureBitset features)
void testCrossingLimits()
void testMissingAuth(FeatureBitset features)
void testCurrencyConversionEntire(FeatureBitset features)
void testCurrencyConversionInParts(FeatureBitset features)
void testToStrand(FeatureBitset features)
NumberMantissaScaleGuard const sg_
void testCrossCurrencyEndXRP(FeatureBitset features)
void testFalseDry(FeatureBitset features)
void testOfferCreateThenCross(FeatureBitset features)
void testOfferCrossWithXRP(FeatureBitset features)
void testBookStep(FeatureBitset features)
void testConvertAllOfAnAsset(FeatureBitset features)
void testPseudoAccountRequireAuth(FeatureBitset features)
void testGatewayCrossCurrency(FeatureBitset features)
void testSellWithFillOrKill(FeatureBitset features)
void testRequireAuth(FeatureBitset features)
void testPayment(FeatureBitset features)
void testRIPD1373(FeatureBitset features)
void testOfferCrossWithLimitOverride(FeatureBitset features)
void testCrossCurrencyStartXRP(FeatureBitset features)
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.
std::string const & human() const
Returns the human readable public key.
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.
SLE::const_pointer le(Account const &account) const
Return an account root.
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.
std::shared_ptr< STObject const > meta()
Return metadata for the last JTx.
void require(Args const &... args)
Check a set of requirements.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Set a multisignature on a JTx.
Match clear account flags.
Match the number of items in the account's owner directory.
Set Paths, SendMax on a JTx.
Sets the QualityIn on a trust JTx.
Sets the QualityOut on a trust JTx as a percentage.
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.
Keylet trustLine(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
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.
PrettyAmount xrpMinusFee(Env const &env, std::int64_t xrpAmount)
bool expectOffers(Env &env, AccountID const &account, std::uint16_t size, std::vector< Amounts > const &toMatch)
STPathElement allPathElements(AccountID const &a, Asset const &asset)
bool expectHolding(Env &env, AccountID const &account, STAmount const &value, bool defaultLimits)
XrpT const XRP
Converts to XRP Issue or STAmount.
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 noop(Account const &account)
The null transaction.
bool same(STPathSet const &st1, Args const &... args)
XRPAmount txFee(Env const &env, std::uint16_t n)
json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
FeatureBitset testableAmendments()
OwnerCount< ltOFFER > Offers
Match the number of offers in the account's owner directory.
STPathElement cpe(PathAsset const &pa)
STPathElement ipe(Asset const &asset)
json::Value ledgerEntryState(Env &env, Account const &acctA, Account const &acctB, std::string const ¤cy)
std::array< Account, 1+sizeof...(Args)> noripple(Account const &account, Args const &... args)
Designate accounts as no-ripple in Env::fund.
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)
json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
STPath stpath(Args const &... args)
json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
json::Value getAccountLines(Env &env, AccountID const &acctId)
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.
TER offerDelete(ApplyView &view, SLE::Ref sle, beast::Journal j)
Delete an offer.
TAmounts< STAmount, STAmount > Amounts
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
bool toCurrency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
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.
TERSubset< CanCvtToTER > TER
AccountID const & xrpAccount()
Compute AccountID from public key.
Represents an XRP, IOU, or MPT quantity This customizes the string conversion and supports XRP conver...
STAmount const & value() const