2#include <test/jtx/AMM.h> 
    3#include <test/jtx/AMMTest.h> 
    4#include <test/jtx/envconfig.h> 
    5#include <test/jtx/permissioned_dex.h> 
    7#include <xrpld/core/JobQueue.h> 
    8#include <xrpld/rpc/RPCHandler.h> 
    9#include <xrpld/rpc/detail/Tuning.h> 
   11#include <xrpl/beast/unit_test.h> 
   12#include <xrpl/json/json_reader.h> 
   13#include <xrpl/protocol/ApiVersion.h> 
   14#include <xrpl/protocol/STParsedJSON.h> 
   15#include <xrpl/protocol/TxFlags.h> 
   16#include <xrpl/protocol/jss.h> 
   17#include <xrpl/resource/Fees.h> 
   35    jv[jss::command] = 
"ripple_path_find";
 
   36    jv[jss::source_account] = 
toBase58(src);
 
   50    jv[jss::destination_account] = d;
 
   53    j[jss::currency] = 
"USD";
 
   54    j[jss::value] = 
"0.01";
 
 
   72            cfg->PATH_SEARCH_OLD = 7;
 
   74            cfg->PATH_SEARCH_MAX = 10;
 
 
   90        template <
class Rep, 
class Period>
 
 
  121        auto& app = env.
app();
 
  130             app.getLedgerMaster(),
 
  140        params[jss::command] = 
"ripple_path_find";
 
  141        params[jss::source_account] = 
toBase58(src);
 
  142        params[jss::destination_account] = 
toBase58(dst);
 
  143        params[jss::destination_amount] =
 
  151            j[jss::currency] = 
to_string(saSrcCurrency.value());
 
  159        app.getJobQueue().postCoro(
 
  160            jtCLIENT, 
"RPC-Client", [&](
auto const& coro) {
 
  161                context.params = std::move(params);
 
  167        using namespace std::chrono_literals;
 
  169        BEAST_EXPECT(!result.
isMember(jss::error));
 
 
  184            env, src, dst, saDstAmount, saSendMax, saSrcCurrency, 
domain);
 
  185        BEAST_EXPECT(!result.
isMember(jss::error));
 
  188        if (result.
isMember(jss::destination_amount))
 
  193        if (result.
isMember(jss::alternatives))
 
  195            auto const& alts = result[jss::alternatives];
 
  198                auto const& 
path = alts[0u];
 
  200                if (
path.isMember(jss::source_amount))
 
  203                if (
path.isMember(jss::destination_amount))
 
  207                if (
path.isMember(jss::paths_computed))
 
  210                    p[
"Paths"] = 
path[jss::paths_computed];
 
 
  224        using namespace std::chrono_literals;
 
  227        auto const gw = 
Account(
"gateway");
 
  228        env.
fund(
XRP(10000), 
"alice", 
"bob", gw);
 
  230        env.
trust(gw[
"USD"](100), 
"alice", 
"bob");
 
  233        auto& app = env.
app();
 
  242             app.getLedgerMaster(),
 
  253        app.getJobQueue().postCoro(
 
  254            jtCLIENT, 
"RPC-Client", [&](
auto const& coro) {
 
  255                context.params = 
rpf(
 
  262        BEAST_EXPECT(!result.
isMember(jss::error));
 
  265        app.getJobQueue().postCoro(
 
  266            jtCLIENT, 
"RPC-Client", [&](
auto const& coro) {
 
  276        BEAST_EXPECT(result.
isMember(jss::error));
 
  281        app.getJobQueue().postCoro(
 
  282            jtCLIENT, 
"RPC-Client", [&](
auto const& coro) {
 
  289        BEAST_EXPECT(!result.
isMember(jss::error));
 
  293        app.getJobQueue().postCoro(
 
  294            jtCLIENT, 
"RPC-Client", [&](
auto const& coro) {
 
  301        BEAST_EXPECT(result.
isMember(jss::error));
 
 
  307        testcase(
"no direct path no intermediary no alternatives");
 
  310        env.
fund(
XRP(10000), 
"alice", 
"bob");
 
 
  321        testcase(
"direct path no intermediary");
 
  324        env.
fund(
XRP(10000), 
"alice", 
"bob");
 
  332        BEAST_EXPECT(st.
empty());
 
 
  342        auto const gw = 
Account(
"gateway");
 
  343        auto const USD = gw[
"USD"];
 
  344        env.
fund(
XRP(10000), 
"alice", 
"bob", gw);
 
  346        env.
trust(USD(600), 
"alice");
 
  347        env.
trust(USD(700), 
"bob");
 
  348        env(
pay(gw, 
"alice", USD(70)));
 
  349        env(
pay(
"alice", 
"bob", USD(24)));
 
 
  360            std::string(
"path find") + (domainEnabled ? 
" w/ " : 
" w/o ") +
 
  364        auto const gw = 
Account(
"gateway");
 
  365        auto const USD = gw[
"USD"];
 
  366        env.
fund(
XRP(10000), 
"alice", 
"bob", gw);
 
  368        env.
trust(USD(600), 
"alice");
 
  369        env.
trust(USD(700), 
"bob");
 
  370        env(
pay(gw, 
"alice", USD(70)));
 
  371        env(
pay(gw, 
"bob", USD(50)));
 
 
  396            std::string(
"XRP to XRP") + (domainEnabled ? 
" w/ " : 
" w/o ") +
 
  399        env.
fund(
XRP(10000), 
"alice", 
"bob");
 
 
  416            (domainEnabled ? 
" w/ " : 
" w/o ") + 
"domain");
 
  421            env.
fund(
XRP(10000), 
"alice", 
"bob", 
"carol", 
"dan", 
"edward");
 
  432                    env, {
"alice", 
"bob", 
"carol", 
"dan", 
"edward"});
 
  452            auto const gw = 
Account(
"gateway");
 
  453            auto const USD = gw[
"USD"];
 
  454            env.
fund(
XRP(10000), 
"alice", 
"bob", 
"carol", gw);
 
  456            env.
trust(USD(100), 
"bob", 
"carol");
 
  458            env(
pay(gw, 
"carol", USD(100)));
 
  465                    setupDomain(env, {
"alice", 
"bob", 
"carol", 
"gateway"});
 
  470                env(
offer(
"carol", 
XRP(100), USD(100)));
 
  485            BEAST_EXPECT(st.
empty());
 
  494            BEAST_EXPECT(sa == 
XRP(100));
 
  509                BEAST_EXPECT(st.
empty());
 
 
  519            (domainEnabled ? 
" w/ " : 
" w/o ") + 
"domain");
 
  522        auto const gw = 
Account(
"gateway");
 
  523        auto const USD = gw[
"USD"];
 
  524        auto const gw2 = 
Account(
"gateway2");
 
  525        auto const gw2_USD = gw2[
"USD"];
 
  526        env.
fund(
XRP(10000), 
"alice", 
"bob", gw, gw2);
 
  528        env.
trust(USD(600), 
"alice");
 
  529        env.
trust(gw2_USD(800), 
"alice");
 
  530        env.
trust(USD(700), 
"bob");
 
  531        env.
trust(gw2_USD(900), 
"bob");
 
  537                setupDomain(env, {
"alice", 
"bob", 
"gateway", 
"gateway2"});
 
  538            env(
pay(gw, 
"alice", USD(70)), 
domain(*domainID));
 
  539            env(
pay(gw2, 
"alice", gw2_USD(70)), 
domain(*domainID));
 
  540            env(
pay(
"alice", 
"bob", 
Account(
"bob")[
"USD"](140)),
 
  546            env(
pay(gw, 
"alice", USD(70)));
 
  547            env(
pay(gw2, 
"alice", gw2_USD(70)));
 
  548            env(
pay(
"alice", 
"bob", 
Account(
"bob")[
"USD"](140)),
 
 
  566            std::string(
"alternative paths consume best transfer") +
 
  567            (domainEnabled ? 
" w/ " : 
" w/o ") + 
"domain");
 
  570        auto const gw = 
Account(
"gateway");
 
  571        auto const USD = gw[
"USD"];
 
  572        auto const gw2 = 
Account(
"gateway2");
 
  573        auto const gw2_USD = gw2[
"USD"];
 
  574        env.
fund(
XRP(10000), 
"alice", 
"bob", gw, gw2);
 
  577        env.
trust(USD(600), 
"alice");
 
  578        env.
trust(gw2_USD(800), 
"alice");
 
  579        env.
trust(USD(700), 
"bob");
 
  580        env.
trust(gw2_USD(900), 
"bob");
 
  586                setupDomain(env, {
"alice", 
"bob", 
"gateway", 
"gateway2"});
 
  587            env(
pay(gw, 
"alice", USD(70)), 
domain(*domainID));
 
  588            env(
pay(gw2, 
"alice", gw2_USD(70)), 
domain(*domainID));
 
  589            env(
pay(
"alice", 
"bob", USD(70)), 
domain(*domainID));
 
  593            env(
pay(gw, 
"alice", USD(70)));
 
  594            env(
pay(gw2, 
"alice", gw2_USD(70)));
 
  595            env(
pay(
"alice", 
"bob", USD(70)));
 
 
  610        testcase(
"alternative paths - consume best transfer first");
 
  613        auto const gw = 
Account(
"gateway");
 
  614        auto const USD = gw[
"USD"];
 
  615        auto const gw2 = 
Account(
"gateway2");
 
  616        auto const gw2_USD = gw2[
"USD"];
 
  617        env.
fund(
XRP(10000), 
"alice", 
"bob", gw, gw2);
 
  620        env.
trust(USD(600), 
"alice");
 
  621        env.
trust(gw2_USD(800), 
"alice");
 
  622        env.
trust(USD(700), 
"bob");
 
  623        env.
trust(gw2_USD(900), 
"bob");
 
  624        env(
pay(gw, 
"alice", USD(70)));
 
  625        env(
pay(gw2, 
"alice", gw2_USD(70)));
 
  626        env(
pay(
"alice", 
"bob", 
Account(
"bob")[
"USD"](77)),
 
 
  641        bool const domainEnabled)
 
  645                "alternative paths - limit returned paths to best quality") +
 
  646            (domainEnabled ? 
" w/ " : 
" w/o ") + 
"domain");
 
  649        auto const gw = 
Account(
"gateway");
 
  650        auto const USD = gw[
"USD"];
 
  651        auto const gw2 = 
Account(
"gateway2");
 
  652        auto const gw2_USD = gw2[
"USD"];
 
  653        env.
fund(
XRP(10000), 
"alice", 
"bob", 
"carol", 
"dan", gw, gw2);
 
  655        env(
rate(
"carol", 1.1));
 
  656        env.
trust(
Account(
"carol")[
"USD"](800), 
"alice", 
"bob");
 
  658        env.
trust(USD(800), 
"alice", 
"bob");
 
  659        env.
trust(gw2_USD(800), 
"alice", 
"bob");
 
  663        env(
pay(gw2, 
"alice", gw2_USD(100)));
 
  665        env(
pay(
"carol", 
"alice", 
Account(
"carol")[
"USD"](100)));
 
  667        env(
pay(gw, 
"alice", USD(100)));
 
  674                setupDomain(env, {
"alice", 
"bob", 
"carol", 
"dan", gw, gw2});
 
 
  701            (domainEnabled ? 
" w/ " : 
" w/o ") + 
"domain");
 
  704        env.
fund(
XRP(10000), 
"alice", 
"bob", 
"carol", 
"dan");
 
  706        env.
trust(
Account(
"bob")[
"USD"](100), 
"alice", 
"carol", 
"dan");
 
  709        env(
pay(
"bob", 
"carol", 
Account(
"bob")[
"USD"](75)));
 
  717            domainID = 
setupDomain(env, {
"alice", 
"bob", 
"carol", 
"dan"});
 
 
  761        testcase(
"path negative: ripple-client issue #23: smaller");
 
  764        env.
fund(
XRP(10000), 
"alice", 
"bob", 
"carol", 
"dan");
 
  770        env(
pay(
"alice", 
"bob", 
Account(
"bob")[
"USD"](55)),
 
 
  781        testcase(
"path negative: ripple-client issue #23: larger");
 
  784        env.
fund(
XRP(10000), 
"alice", 
"bob", 
"carol", 
"dan", 
"edward");
 
  791        env(
pay(
"alice", 
"bob", 
Account(
"bob")[
"USD"](50)),
 
 
  810            std::string(
"via gateway") + (domainEnabled ? 
" w/ " : 
" w/o ") +
 
  814        auto const gw = 
Account(
"gateway");
 
  815        auto const AUD = gw[
"AUD"];
 
  816        env.
fund(
XRP(10000), 
"alice", 
"bob", 
"carol", gw);
 
  820        env.
trust(AUD(100), 
"bob", 
"carol");
 
  822        env(
pay(gw, 
"carol", AUD(50)));
 
  828            domainID = 
setupDomain(env, {
"alice", 
"bob", 
"carol", gw});
 
  831            env(
pay(
"alice", 
"bob", AUD(10)),
 
  839            env(
offer(
"carol", 
XRP(50), AUD(50)));
 
 
  865        env.
fund(
XRP(10000), 
"alice", 
"bob", 
"carol");
 
 
  884        env.
fund(
XRP(10000), 
"alice", 
"bob");
 
  887            json(
"{\"" + sfQualityIn.fieldName + 
"\": 2000}"),
 
  888            json(
"{\"" + sfQualityOut.fieldName + 
"\": 1400000000}"));
 
  895                    "issuer" : "rrrrrrrrrrrrrrrrrrrrBZbvji", 
  901                    "issuer" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK", 
 
  905                "HighQualityIn" : 2000, 
  906                "HighQualityOut" : 1400000000, 
  907                "LedgerEntryType" : "RippleState", 
  910                    "issuer" : "rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn", 
  921        for (
auto it = jv.
begin(); it != jv.
end(); ++it)
 
  922            BEAST_EXPECT(*it == jv_l[it.memberName()]);
 
  931        env.
fund(
XRP(10000), 
"alice", 
"bob");
 
 
  941                    "issuer" : "rrrrrrrrrrrrrrrrrrrrBZbvji", 
  947                    "issuer" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK", 
  951                "LedgerEntryType" : "RippleState", 
  954                    "issuer" : "rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn", 
 
  965        for (
auto it = jv.
begin(); it != jv.
end(); ++it)
 
  966            BEAST_EXPECT(*it == jv_l[it.memberName()]);
 
  982        env.
fund(
XRP(10000), 
"alice", 
"bob");
 
  985        env(
pay(
"bob", 
"alice", 
Account(
"bob")[
"USD"](50)));
 
  994                    "issuer" : "rrrrrrrrrrrrrrrrrrrrBZbvji", 
 1001                    "issuer" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK", 
 1005                "LedgerEntryType" : "RippleState", 
 1009                    "issuer" : "rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn", 
 1020        for (
auto it = jv.
begin(); it != jv.
end(); ++it)
 
 1021            BEAST_EXPECT(*it == jv_l[it.memberName()]);
 
 1023        env(
pay(
"alice", 
"bob", 
Account(
"alice")[
"USD"](50)));
 
 1034            std::string(
"Path Find: XRP -> XRP and XRP -> IOU") +
 
 1035            (domainEnabled ? 
" w/ " : 
" w/o ") + 
"domain");
 
 1036        using namespace jtx;
 
 1046        env.fund(
XRP(100000), A1);
 
 1047        env.fund(
XRP(10000), A2);
 
 1048        env.fund(
XRP(1000), A3, G1, G2, G3, M1);
 
 1051        env.trust(G1[
"XYZ"](5000), A1);
 
 1052        env.trust(G3[
"ABC"](5000), A1);
 
 1053        env.trust(G2[
"XYZ"](5000), A2);
 
 1054        env.trust(G3[
"ABC"](5000), A2);
 
 1055        env.trust(A2[
"ABC"](1000), A3);
 
 1056        env.trust(G1[
"XYZ"](100000), M1);
 
 1057        env.trust(G2[
"XYZ"](100000), M1);
 
 1058        env.trust(G3[
"ABC"](100000), M1);
 
 1061        env(
pay(G1, A1, G1[
"XYZ"](3500)));
 
 1062        env(
pay(G3, A1, G3[
"ABC"](1200)));
 
 1063        env(
pay(G2, M1, G2[
"XYZ"](25000)));
 
 1064        env(
pay(G3, M1, G3[
"ABC"](25000)));
 
 1070            domainID = 
setupDomain(env, {A1, A2, A3, G1, G2, G3, M1});
 
 
 1071            env(
offer(M1, G1[
"XYZ"](1000), G2[
"XYZ"](1000)), domain(*domainID));
 
 1072            env(
offer(M1, 
XRP(10000), G3[
"ABC"](1000)), domain(*domainID));
 
 1077            env(
offer(M1, G1[
"XYZ"](1000), G2[
"XYZ"](1000)));
 
 1078            env(
offer(M1, 
XRP(10000), G3[
"ABC"](1000)));
 
 1086            auto const& send_amt = 
XRP(10);
 
 1089            BEAST_EXPECT(
equal(da, send_amt));
 
 1090            BEAST_EXPECT(st.
empty());
 
 1096            auto const& send_amt = 
XRP(200);
 
 1105            BEAST_EXPECT(
equal(da, send_amt));
 
 1106            BEAST_EXPECT(st.
empty());
 
 1110            auto const& send_amt = G3[
"ABC"](10);
 
 1113            BEAST_EXPECT(
equal(da, send_amt));
 
 1119            auto const& send_amt = A2[
"ABC"](1);
 
 1122            BEAST_EXPECT(
equal(da, send_amt));
 
 1128            auto const& send_amt = A3[
"ABC"](1);
 
 1131            BEAST_EXPECT(
equal(da, send_amt));
 
 
 1142            (domainEnabled ? 
" w/ " : 
" w/o ") + 
"domain");
 
 1143        using namespace jtx;
 
 1150        env.
fund(
XRP(1000), A1, A2, G3);
 
 1154        env.
trust(G3[
"ABC"](1000), A1, A2);
 
 1155        env.
trust(G3[
"ABC"](100000), M1);
 
 1158        env(
pay(G3, A1, G3[
"ABC"](1000)));
 
 1159        env(
pay(G3, A2, G3[
"ABC"](1000)));
 
 1160        env(
pay(G3, M1, G3[
"ABC"](1200)));
 
 1171            env(
offer(M1, G3[
"ABC"](1000), 
XRP(10000)));
 
 1176        auto const& send_amt = 
XRP(10);
 
 1187            BEAST_EXPECT(
equal(da, send_amt));
 
 1188            BEAST_EXPECT(
equal(sa, A1[
"ABC"](1)));
 
 1197                env, A1, A2, send_amt, 
std::nullopt, A2[
"ABC"].currency);
 
 1198            BEAST_EXPECT(
equal(da, send_amt));
 
 1199            BEAST_EXPECT(st.
empty());
 
 1208                "Path Find: Bitstamp and SnapSwap, liquidity with no offers") +
 
 1209            (domainEnabled ? 
" w/ " : 
" w/o ") + 
"domain");
 
 1210        using namespace jtx;
 
 1214        Account G1BS{
"G1BS"};
 
 1215        Account G2SW{
"G2SW"};
 
 1218        env.
fund(
XRP(1000), G1BS, G2SW, A1, A2);
 
 1222        env.
trust(G1BS[
"HKD"](2000), A1);
 
 1223        env.
trust(G2SW[
"HKD"](2000), A2);
 
 1224        env.
trust(G1BS[
"HKD"](100000), M1);
 
 1225        env.
trust(G2SW[
"HKD"](100000), M1);
 
 1228        env(
pay(G1BS, A1, G1BS[
"HKD"](1000)));
 
 1229        env(
pay(G2SW, A2, G2SW[
"HKD"](1000)));
 
 1233        env(
pay(G1BS, M1, G1BS[
"HKD"](1200)));
 
 1234        env(
pay(G2SW, M1, G2SW[
"HKD"](5000)));
 
 1239            domainID = 
setupDomain(env, {A1, A2, G1BS, G2SW, M1});
 
 1245            auto const& send_amt = A2[
"HKD"](10);
 
 
 1254            BEAST_EXPECT(
equal(da, send_amt));
 
 1255            BEAST_EXPECT(
equal(sa, A1[
"HKD"](10)));
 
 1260            auto const& send_amt = A1[
"HKD"](10);
 
 1269            BEAST_EXPECT(
equal(da, send_amt));
 
 1270            BEAST_EXPECT(
equal(sa, A2[
"HKD"](10)));
 
 1271            BEAST_EXPECT(
same(st, 
stpath(G2SW, M1, G1BS)));
 
 1275            auto const& send_amt = A2[
"HKD"](10);
 
 1284            BEAST_EXPECT(
equal(da, send_amt));
 
 1285            BEAST_EXPECT(
equal(sa, G1BS[
"HKD"](10)));
 
 1290            auto const& send_amt = M1[
"HKD"](10);
 
 1299            BEAST_EXPECT(
equal(da, send_amt));
 
 1300            BEAST_EXPECT(
equal(sa, M1[
"HKD"](10)));
 
 1301            BEAST_EXPECT(st.empty());
 
 1305            auto const& send_amt = A1[
"HKD"](10);
 
 1314            BEAST_EXPECT(
equal(da, send_amt));
 
 1315            BEAST_EXPECT(
equal(sa, G2SW[
"HKD"](10)));
 
 1324            std::string(
"Path Find: non-XRP -> non-XRP, same currency") +
 
 1325            (domainEnabled ? 
" w/ " : 
" w/o ") + 
"domain");
 
 1326        using namespace jtx;
 
 1339        env.fund(
XRP(1000), A1, A2, A3, G1, G2, G3, G4);
 
 1340        env.fund(
XRP(10000), A4);
 
 1341        env.fund(
XRP(11000), M1, M2);
 
 1344        env.trust(G1[
"HKD"](2000), A1);
 
 1345        env.trust(G2[
"HKD"](2000), A2);
 
 1346        env.trust(G1[
"HKD"](2000), A3);
 
 1347        env.trust(G1[
"HKD"](100000), M1);
 
 1348        env.trust(G2[
"HKD"](100000), M1);
 
 1349        env.trust(G1[
"HKD"](100000), M2);
 
 1350        env.trust(G2[
"HKD"](100000), M2);
 
 1353        env(
pay(G1, A1, G1[
"HKD"](1000)));
 
 1354        env(
pay(G2, A2, G2[
"HKD"](1000)));
 
 1355        env(
pay(G1, A3, G1[
"HKD"](1000)));
 
 1356        env(
pay(G1, M1, G1[
"HKD"](1200)));
 
 1357        env(
pay(G2, M1, G2[
"HKD"](5000)));
 
 1358        env(
pay(G1, M2, G1[
"HKD"](1200)));
 
 1359        env(
pay(G2, M2, G2[
"HKD"](5000)));
 
 1366                setupDomain(env, {A1, A2, A3, A4, G1, G2, G3, G4, M1, M2});
 
 1367            env(
offer(M1, G1[
"HKD"](1000), G2[
"HKD"](1000)), domain(*domainID));
 
 1368            env(
offer(M2, 
XRP(10000), G2[
"HKD"](1000)), domain(*domainID));
 
 1369            env(
offer(M2, G1[
"HKD"](1000), 
XRP(10000)), domain(*domainID));
 
 1373            env(
offer(M1, G1[
"HKD"](1000), G2[
"HKD"](1000)));
 
 1374            env(
offer(M2, 
XRP(10000), G2[
"HKD"](1000)));
 
 1375            env(
offer(M2, G1[
"HKD"](1000), 
XRP(10000)));
 
 1384            auto const& send_amt = G1[
"HKD"](10);
 
 1393            BEAST_EXPECT(st.empty());
 
 1394            BEAST_EXPECT(
equal(da, send_amt));
 
 1395            BEAST_EXPECT(
equal(sa, A1[
"HKD"](10)));
 
 1401            auto const& send_amt = A1[
"HKD"](10);
 
 1410            BEAST_EXPECT(st.empty());
 
 1411            BEAST_EXPECT(
equal(da, send_amt));
 
 1412            BEAST_EXPECT(
equal(sa, A1[
"HKD"](10)));
 
 1418            auto const& send_amt = A3[
"HKD"](10);
 
 1427            BEAST_EXPECT(
equal(da, send_amt));
 
 1428            BEAST_EXPECT(
equal(sa, A1[
"HKD"](10)));
 
 
 1435            auto const& send_amt = G2[
"HKD"](10);
 
 1444            BEAST_EXPECT(
equal(da, send_amt));
 
 1445            BEAST_EXPECT(
equal(sa, G1[
"HKD"](10)));
 
 1457            auto const& send_amt = G2[
"HKD"](10);
 
 1466            BEAST_EXPECT(
equal(da, send_amt));
 
 1467            BEAST_EXPECT(
equal(sa, A1[
"HKD"](10)));
 
 1480            auto const& send_amt = A2[
"HKD"](10);
 
 
 1489            BEAST_EXPECT(
equal(da, send_amt));
 
 1490            BEAST_EXPECT(
equal(sa, A1[
"HKD"](10)));
 
 1504            std::string(
"Path Find: non-XRP -> non-XRP, same currency)") +
 
 1505            (domainEnabled ? 
" w/ " : 
" w/o ") + 
"domain");
 
 1506        using namespace jtx;
 
 1515        env.fund(
XRP(11000), M1);
 
 1516        env.fund(
XRP(1000), A1, A2, A3, G1, G2);
 
 1519        env.trust(G1[
"HKD"](2000), A1);
 
 1520        env.trust(G2[
"HKD"](2000), A2);
 
 1521        env.trust(A2[
"HKD"](2000), A3);
 
 1522        env.trust(G1[
"HKD"](100000), M1);
 
 1523        env.trust(G2[
"HKD"](100000), M1);
 
 1526        env(
pay(G1, A1, G1[
"HKD"](1000)));
 
 1527        env(
pay(G2, A2, G2[
"HKD"](1000)));
 
 1528        env(
pay(G1, M1, G1[
"HKD"](5000)));
 
 1529        env(
pay(G2, M1, G2[
"HKD"](5000)));
 
 1535            domainID = 
setupDomain(env, {A1, A2, A3, G1, G2, M1});
 
 1536            env(
offer(M1, G1[
"HKD"](1000), G2[
"HKD"](1000)), domain(*domainID));
 
 1540            env(
offer(M1, G1[
"HKD"](1000), G2[
"HKD"](1000)));
 
 1545        auto const& send_amt = A2[
"HKD"](10);
 
 1549            env, G1, A2, send_amt, 
std::nullopt, G1[
"HKD"].currency, domainID);
 
 1550        BEAST_EXPECT(
equal(da, send_amt));
 
 1551        BEAST_EXPECT(
equal(sa, G1[
"HKD"](10)));
 
 1559            std::string(
"Receive max") + (domainEnabled ? 
" w/ " : 
" w/o ") +
 
 1562        using namespace jtx;
 
 1563        auto const alice = Account(
"alice");
 
 1564        auto const bob = Account(
"bob");
 
 1565        auto const charlie = Account(
"charlie");
 
 1566        auto const gw = Account(
"gw");
 
 1567        auto const USD = gw[
"USD"];
 
 1571            env.fund(
XRP(10000), alice, bob, charlie, gw);
 
 1573            env.trust(USD(100), alice, bob, charlie);
 
 1575            env(
pay(gw, charlie, USD(10)));
 
 1581                domainID = 
setupDomain(env, {alice, bob, charlie, gw});
 
 1582                env(
offer(charlie, 
XRP(10), USD(10)), domain(*domainID));
 
 
 1587                env(
offer(charlie, 
XRP(10), USD(10)));
 
 1599            BEAST_EXPECT(sa == 
XRP(10));
 
 1600            BEAST_EXPECT(
equal(da, USD(10)));
 
 1601            if (BEAST_EXPECT(st.size() == 1 && st[0].size() == 1))
 
 1603                auto const& pathElem = st[0][0];
 
 1605                    pathElem.isOffer() && pathElem.getIssuerID() == gw.id() &&
 
 1606                    pathElem.getCurrency() == USD.currency);
 
 1612            env.fund(
XRP(10000), alice, bob, charlie, gw);
 
 1614            env.trust(USD(100), alice, bob, charlie);
 
 1616            env(
pay(gw, alice, USD(10)));
 
 1622                domainID = 
setupDomain(env, {alice, bob, charlie, gw});
 
 1623                env(
offer(charlie, USD(10), 
XRP(10)), domain(*domainID));
 
 1628                env(
offer(charlie, USD(10), 
XRP(10)));
 
 1640            BEAST_EXPECT(sa == USD(10));
 
 1642            if (BEAST_EXPECT(st.size() == 1 && st[0].size() == 1))
 
 1644                auto const& pathElem = st[0][0];
 
 1646                    pathElem.isOffer() &&
 
 
 1656        using namespace jtx;
 
 1661        auto const alice = 
Account(
"alice");
 
 1662        auto const bob = 
Account(
"bob");
 
 1663        auto const george = 
Account(
"george");
 
 1664        auto const USD = george[
"USD"];
 
 1691            env(
pay(george, alice, USD(70)));
 
 1696            BEAST_EXPECT(
equal(da, bob[
"USD"](5)));
 
 1700                BEAST_EXPECT(st.size() == 1);
 
 1702                BEAST_EXPECT(
equal(sa, alice[
"USD"](5)));
 
 1706                BEAST_EXPECT(st.size() == 0);
 
 1710        test(
"ripple -> ripple", 
true, 
true, 
true);
 
 1711        test(
"ripple -> no ripple", 
true, 
false, 
true);
 
 1712        test(
"no ripple -> ripple", 
false, 
true, 
true);
 
 1713        test(
"no ripple -> no ripple", 
false, 
false, 
false);
 
 1720        using namespace jtx;
 
 1725        auto testPathfind = [&](
auto func, 
bool const domainEnabled = 
false) {
 
 1738            env.
fund(
XRP(1000), A1, A2, A3, G1, G2, G3, G4);
 
 1743            env.
trust(G1[
"HKD"](2000), A1);
 
 1744            env.
trust(G2[
"HKD"](2000), A2);
 
 1745            env.
trust(G1[
"HKD"](2000), A3);
 
 1746            env.
trust(G1[
"HKD"](100000), M1);
 
 1747            env.
trust(G2[
"HKD"](100000), M1);
 
 1748            env.
trust(G1[
"HKD"](100000), M2);
 
 1749            env.
trust(G2[
"HKD"](100000), M2);
 
 1752            env(
pay(G1, A1, G1[
"HKD"](1000)));
 
 1753            env(
pay(G2, A2, G2[
"HKD"](1000)));
 
 1754            env(
pay(G1, A3, G1[
"HKD"](1000)));
 
 1755            env(
pay(G1, M1, G1[
"HKD"](1200)));
 
 1756            env(
pay(G2, M1, G2[
"HKD"](5000)));
 
 1757            env(
pay(G1, M2, G1[
"HKD"](1200)));
 
 1758            env(
pay(G2, M2, G2[
"HKD"](5000)));
 
 1762                setupDomain(env, {A1, A2, A3, A4, G1, G2, G3, G4, M1, M2});
 
 1763            BEAST_EXPECT(domainID);
 
 1765            func(env, M1, M2, G1, G2, *domainID);
 
 1773                auto const& send_amt = G1[
"HKD"](10);
 
 1781                    domainEnabled ? domainID : 
std::nullopt);
 
 1782                BEAST_EXPECT(st.empty());
 
 1783                BEAST_EXPECT(
equal(da, send_amt));
 
 1784                BEAST_EXPECT(
equal(sa, A1[
"HKD"](10)));
 
 1790                auto const& send_amt = A1[
"HKD"](10);
 
 1798                    domainEnabled ? domainID : 
std::nullopt);
 
 1799                BEAST_EXPECT(st.empty());
 
 1800                BEAST_EXPECT(
equal(da, send_amt));
 
 1801                BEAST_EXPECT(
equal(sa, A1[
"HKD"](10)));
 
 1807                auto const& send_amt = A3[
"HKD"](10);
 
 1815                    domainEnabled ? domainID : 
std::nullopt);
 
 1816                BEAST_EXPECT(
equal(da, send_amt));
 
 1817                BEAST_EXPECT(
equal(sa, A1[
"HKD"](10)));
 
 1824                auto const& send_amt = G2[
"HKD"](10);
 
 1832                    domainEnabled ? domainID : 
std::nullopt);
 
 1833                BEAST_EXPECT(
equal(da, send_amt));
 
 1834                BEAST_EXPECT(
equal(sa, G1[
"HKD"](10)));
 
 1846                auto const& send_amt = G2[
"HKD"](10);
 
 1854                    domainEnabled ? domainID : 
std::nullopt);
 
 1855                BEAST_EXPECT(
equal(da, send_amt));
 
 1856                BEAST_EXPECT(
equal(sa, A1[
"HKD"](10)));
 
 1869                auto const& send_amt = A2[
"HKD"](10);
 
 1877                    domainEnabled ? domainID : 
std::nullopt);
 
 1878                BEAST_EXPECT(
equal(da, send_amt));
 
 1879                BEAST_EXPECT(
equal(sa, A1[
"HKD"](10)));
 
 1893            testPathfind([](Env& env,
 
 1899                env(
offer(M1, G1[
"HKD"](1000), G2[
"HKD"](1000)),
 
 1902                env(
offer(M2, 
XRP(10000), G2[
"HKD"](1000)));
 
 1903                env(
offer(M2, G1[
"HKD"](1000), 
XRP(10000)));
 
 1906            testPathfind([](Env& env,
 
 1912                env(
offer(M1, G1[
"HKD"](1000), G2[
"HKD"](1000)),
 
 1915                env(
offer(M2, 
XRP(10000), G2[
"HKD"](1000)),
 
 1918                env(
offer(M2, G1[
"HKD"](1000), 
XRP(10000)));
 
 1921            testPathfind([](Env& env,
 
 1927                env(
offer(M1, G1[
"HKD"](1000), G2[
"HKD"](1000)),
 
 1930                env(
offer(M2, 
XRP(10000), G2[
"HKD"](1000)),
 
 1933                env(
offer(M2, G1[
"HKD"](1000), 
XRP(10000)),
 
 1938            testPathfind([](Env& env,
 
 1944                env(
offer(M1, G1[
"HKD"](1000), G2[
"HKD"](1000)));
 
 1945                env(
offer(M2, 
XRP(10000), G2[
"HKD"](1000)));
 
 1946                env(
offer(M2, G1[
"HKD"](1000), 
XRP(10000)),
 
 1951            testPathfind([](Env& env,
 
 1957                env(
offer(M1, G1[
"HKD"](1000), G2[
"HKD"](1000)));
 
 1958                env(
offer(M2, 
XRP(10000), G2[
"HKD"](1000)),
 
 1961                env(
offer(M2, G1[
"HKD"](1000), 
XRP(10000)),
 
 
 1978                    env(
offer(M1, G1[
"HKD"](1000), G2[
"HKD"](1000)),
 
 1981                    env(
offer(M2, 
XRP(10000), G2[
"HKD"](1000)),
 
 1983                    env(
offer(M2, G1[
"HKD"](1000), 
XRP(10000)),
 
 1995                    env(
offer(M1, G1[
"HKD"](1000), G2[
"HKD"](1000)),
 
 1998                    env(
offer(M2, 
XRP(10000), G2[
"HKD"](1000)),
 
 2001                    env(
offer(M2, G1[
"HKD"](1000), 
XRP(10000)),
 
 
 2013                    env(
offer(M1, G1[
"HKD"](1000), G2[
"HKD"](1000)),
 
 2015                    env(
offer(M2, 
XRP(10000), G2[
"HKD"](1000)),
 
 2017                    env(
offer(M2, G1[
"HKD"](1000), 
XRP(10000)),
 
 2030                    env(
offer(M1, G1[
"HKD"](1000), G2[
"HKD"](1000)),
 
 2032                    env(
offer(M2, 
XRP(10000), G2[
"HKD"](1000)),
 
 2035                    env(
offer(M2, G1[
"HKD"](1000), 
XRP(10000)),
 
 2046        testcase(
"AMM not used in domain path");
 
 2047        using namespace jtx;
 
 2049        PermissionedDEX permDex(env);
 
 
 2050        auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] =
 
 2057        auto const& send_amt = 
XRP(1);
 
 2061            env, bob, carol, send_amt, 
std::nullopt, USD.currency, domainID);
 
 2062        BEAST_EXPECT(st.empty());
 
 2086        for (
bool const domainEnabled : {
false, 
true})
 
 
Unserialize a JSON document into a Value.
 
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
 
const_iterator begin() const
 
const_iterator end() const
 
bool isMember(char const *key) const
Return true if the object has a member named key.
 
testcase_t testcase
Memberspace for declaring test cases.
 
An endpoint that consumes resources.
 
Json::Value getJson(JsonOptions=JsonOptions::none) const override
 
Holds the serialized result of parsing an input JSON object.
 
std::optional< STObject > object
The STObject if the parse was successful.
 
std::condition_variable cv_
 
bool wait_for(std::chrono::duration< Rep, Period > const &rel_time)
 
void noripple_combinations()
 
void path_find_consume_all(bool const domainEnabled)
 
void trust_auto_clear_trust_normal_clear()
 
void alternative_path_consume_both(bool const domainEnabled)
 
void payment_auto_path_find()
 
void indirect_paths_path_find()
 
void via_offers_via_gateway(bool const domainEnabled)
 
void issues_path_negative_issue(bool const domainEnabled)
 
void trust_auto_clear_trust_auto_clear()
 
void direct_path_no_intermediary()
 
void receive_max(bool const domainEnabled)
 
void path_find_02(bool const domainEnabled)
 
void issues_path_negative_ripple_client_issue_23_larger()
 
void alternative_paths_consume_best_transfer(bool const domainEnabled)
 
std::tuple< STPathSet, STAmount, STAmount > find_paths(jtx::Env &env, jtx::Account const &src, jtx::Account const &dst, STAmount const &saDstAmount, std::optional< STAmount > const &saSendMax=std::nullopt, std::optional< Currency > const &saSrcCurrency=std::nullopt, std::optional< uint256 > const &domain=std::nullopt)
 
void alternative_paths_limit_returned_paths_to_best_quality(bool const domainEnabled)
 
void source_currencies_limit()
 
void path_find_04(bool const domainEnabled)
 
auto find_paths_request(jtx::Env &env, jtx::Account const &src, jtx::Account const &dst, STAmount const &saDstAmount, std::optional< STAmount > const &saSendMax=std::nullopt, std::optional< Currency > const &saSrcCurrency=std::nullopt, std::optional< uint256 > const &domain=std::nullopt)
 
void issues_path_negative_ripple_client_issue_23_smaller()
 
void alternative_paths_consume_best_transfer_first()
 
void path_find_05(bool const domainEnabled)
 
void path_find_01(bool const domainEnabled)
 
void path_find_06(bool const domainEnabled)
 
void quality_paths_quality_set_and_test()
 
void xrp_to_xrp(bool const domainEnabled)
 
void run() override
Runs the suite.
 
void path_find(bool const domainEnabled)
 
void no_direct_path_no_intermediary_no_alternatives()
 
Immutable cryptographic account descriptor.
 
A transaction testing environment.
 
void require(Args const &... args)
Check a set of requirements.
 
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
 
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
 
beast::Journal const journal
 
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
 
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
 
Set Paths, SendMax on a JTx.
 
Sets the SendMax on a JTx.
 
Set the expected result code for a JTx The test will fail if the code doesn't match.
 
@ arrayValue
array value (ordered list)
 
@ objectValue
object value (collection of name/value pairs).
 
static int constexpr max_src_cur
Maximum number of source currencies allowed in a path find request.
 
static int constexpr max_auto_src_cur
Maximum number of auto source currencies in a path find request.
 
Status doCommand(RPC::JsonContext &context, Json::Value &result)
Execute an RPC command and store the results in a Json::Value.
 
static constexpr auto apiVersionIfUnspecified
 
Charge const feeReferenceRPC
 
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
 
Keylet line(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
 
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
 
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
 
uint256 setupDomain(jtx::Env &env, std::vector< jtx::Account > const &accounts, jtx::Account const &domainOwner, std::string const &credType)
 
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
 
bool same(STPathSet const &st1, Args const &... args)
 
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
 
Json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
 
STPathElement IPE(Issue const &iss)
 
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
 
XRP_t const XRP
Converts to XRP Issue or STAmount.
 
STPath stpath(Args const &... args)
 
Json::Value rpf(jtx::Account const &src, jtx::Account const &dst, std::uint32_t num_src)
 
bool equal(std::unique_ptr< Step > const &s1, DirectStepInfo const &dsi)
 
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
 
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
 
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
 
AccountID const & xrpAccount()
Compute AccountID from public key.
 
STAmount amountFromJson(SField const &name, Json::Value const &v)
 
constexpr std::uint32_t tfHybrid
 
constexpr std::uint32_t tfClearNoRipple
 
Currency const & xrpCurrency()
XRP currency.
 
std::string to_string(base_uint< Bits, Tag > const &a)
 
constexpr std::uint32_t tfSetNoRipple