160        using namespace std::chrono_literals;
 
  163        auto baseFee = env.
current()->fees().base.drops();
 
  170            stream[jss::streams].append(
"transactions");
 
  171            auto jv = wsc->invoke(
"subscribe", stream);
 
  172            if (wsc->version() == 2)
 
  175                    jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == 
"2.0");
 
  177                    jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == 
"2.0");
 
  178                BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
 
  180            BEAST_EXPECT(jv[jss::status] == 
"success");
 
  188            BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
 
  189                return jv[jss::meta][
"AffectedNodes"][1u][
"CreatedNode"]
 
  190                         [
"NewFields"][jss::Account]  
 
  191                    == Account(
"alice").human() &&
 
  192                    jv[jss::transaction][jss::TransactionType]  
 
  194                    jv[jss::transaction][jss::DeliverMax]  
 
  195                    == std::to_string(10000000000 + baseFee) &&
 
  196                    jv[jss::transaction][jss::Fee]  
 
  197                    == std::to_string(baseFee) &&
 
  198                    jv[jss::transaction][jss::Sequence]  
 
  203            BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
 
  204                return jv[jss::meta][
"AffectedNodes"][0u][
"ModifiedNode"]
 
  205                         [
"FinalFields"][jss::Account] ==
 
  206                    Account(
"alice").human();
 
  213            BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
 
  214                return jv[jss::meta][
"AffectedNodes"][1u][
"CreatedNode"]
 
  215                         [
"NewFields"][jss::Account]  
 
  216                    == Account(
"bob").human() &&
 
  217                    jv[jss::transaction][jss::TransactionType]  
 
  219                    jv[jss::transaction][jss::DeliverMax]  
 
  220                    == std::to_string(10000000000 + baseFee) &&
 
  221                    jv[jss::transaction][jss::Fee]  
 
  222                    == std::to_string(baseFee) &&
 
  223                    jv[jss::transaction][jss::Sequence]  
 
  228            BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
 
  229                return jv[jss::meta][
"AffectedNodes"][0u][
"ModifiedNode"]
 
  230                         [
"FinalFields"][jss::Account] ==
 
  231                    Account(
"bob").human();
 
  237            auto jv = wsc->invoke(
"unsubscribe", stream);
 
  238            if (wsc->version() == 2)
 
  241                    jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == 
"2.0");
 
  243                    jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == 
"2.0");
 
  244                BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
 
  246            BEAST_EXPECT(jv[jss::status] == 
"success");
 
  253            stream[jss::accounts].append(
Account(
"alice").human());
 
  254            auto jv = wsc->invoke(
"subscribe", stream);
 
  255            if (wsc->version() == 2)
 
  258                    jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == 
"2.0");
 
  260                    jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == 
"2.0");
 
  261                BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
 
  263            BEAST_EXPECT(jv[jss::status] == 
"success");
 
  270            BEAST_EXPECT(!wsc->getMsg(10ms));
 
  277            BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
 
  278                return jv[jss::meta][
"AffectedNodes"][1u][
"ModifiedNode"]
 
  279                         [
"FinalFields"][jss::Account] ==
 
  280                    Account(
"alice").human();
 
  283            BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
 
  284                return jv[jss::meta][
"AffectedNodes"][1u][
"CreatedNode"]
 
  285                         [
"NewFields"][
"LowLimit"][jss::issuer] ==
 
  286                    Account(
"alice").human();
 
  291        auto jv = wsc->invoke(
"unsubscribe", stream);
 
  292        if (wsc->version() == 2)
 
  295                jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == 
"2.0");
 
  297                jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == 
"2.0");
 
  298            BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
 
  300        BEAST_EXPECT(jv[jss::status] == 
"success");
 
 
  428        auto& cfg = env.app().config();
 
  429        if (!BEAST_EXPECT(cfg.section(SECTION_VALIDATION_SEED).empty()))
 
  431        auto const parsedseed =
 
  432            parseBase58<Seed>(cfg.section(SECTION_VALIDATION_SEED).values()[0]);
 
  433        if (!BEAST_EXPECT(parsedseed))
 
  448            stream[jss::streams].append(
"validations");
 
  449            auto jv = wsc->invoke(
"subscribe", stream);
 
  450            if (wsc->version() == 2)
 
  453                    jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == 
"2.0");
 
  455                    jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == 
"2.0");
 
  456                BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
 
  458            BEAST_EXPECT(jv[jss::status] == 
"success");
 
  463            auto validValidationFields = [&env, &valPublicKey](
 
  465                if (jv[jss::type] != 
"validationReceived")
 
  468                if (jv[jss::validation_public_key].asString() != valPublicKey)
 
  471                if (jv[jss::ledger_hash] !=
 
  475                if (jv[jss::ledger_index] !=
 
  482                if (jv[jss::full] != 
true)
 
  485                if (jv.isMember(jss::load_fee))
 
  488                if (!jv.isMember(jss::signature))
 
  491                if (!jv.isMember(jss::signing_time))
 
  494                if (!jv.isMember(jss::cookie))
 
  497                if (!jv.isMember(jss::validated_hash))
 
  500                uint32_t netID = env.app().config().NETWORK_ID;
 
  501                if (!jv.isMember(jss::network_id) ||
 
  502                    jv[jss::network_id] != netID)
 
  507                    (env.closed()->info().seq + 1) % 256 == 0;
 
  523            while (env.closed()->info().seq < 300)
 
  526                using namespace std::chrono_literals;
 
  527                BEAST_EXPECT(wsc->findMsg(5s, validValidationFields));
 
  532        auto jv = wsc->invoke(
"unsubscribe", stream);
 
  533        if (wsc->version() == 2)
 
  536                jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == 
"2.0");
 
  538                jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == 
"2.0");
 
  539            BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
 
  541        BEAST_EXPECT(jv[jss::status] == 
"success");
 
 
  577        auto const method = subscribe ? 
"subscribe" : 
"unsubscribe";
 
  578        testcase << 
"Error cases for " << method;
 
  584            auto jr = env.rpc(
"json", method, 
"{}")[jss::result];
 
  585            BEAST_EXPECT(jr[jss::error] == 
"invalidParams");
 
  586            BEAST_EXPECT(jr[jss::error_message] == 
"Invalid parameters.");
 
  591            jv[jss::url] = 
"not-a-url";
 
  592            jv[jss::username] = 
"admin";
 
  593            jv[jss::password] = 
"password";
 
  594            auto jr = env.rpc(
"json", method, 
to_string(jv))[jss::result];
 
  597                BEAST_EXPECT(jr[jss::error] == 
"invalidParams");
 
  598                BEAST_EXPECT(jr[jss::error_message] == 
"Failed to parse url.");
 
  606            jv[jss::url] = 
"ftp://scheme.not.supported.tld";
 
  607            auto jr = env.rpc(
"json", method, 
to_string(jv))[jss::result];
 
  610                BEAST_EXPECT(jr[jss::error] == 
"invalidParams");
 
  612                    jr[jss::error_message] ==
 
  613                    "Only http and https is supported.");
 
  620            jv[jss::url] = 
"no-url";
 
  622                env_nonadmin.rpc(
"json", method, 
to_string(jv))[jss::result];
 
  623            BEAST_EXPECT(jr[jss::error] == 
"noPermission");
 
  625                jr[jss::error_message] ==
 
  626                "You don't have permission for this command.");
 
  638        for (
auto const& f : {jss::accounts_proposed, jss::accounts})
 
  640            for (
auto const& nonArray : nonArrays)
 
  644                auto jr = wsc->invoke(method, jv)[jss::result];
 
  645                BEAST_EXPECT(jr[jss::error] == 
"invalidParams");
 
  646                BEAST_EXPECT(jr[jss::error_message] == 
"Invalid parameters.");
 
  652                auto jr = wsc->invoke(method, jv)[jss::result];
 
  653                BEAST_EXPECT(jr[jss::error] == 
"actMalformed");
 
  654                BEAST_EXPECT(jr[jss::error_message] == 
"Account malformed.");
 
  658        for (
auto const& nonArray : nonArrays)
 
  661            jv[jss::books] = nonArray;
 
  662            auto jr = wsc->invoke(method, jv)[jss::result];
 
  663            BEAST_EXPECT(jr[jss::error] == 
"invalidParams");
 
  664            BEAST_EXPECT(jr[jss::error_message] == 
"Invalid parameters.");
 
  670            jv[jss::books][0u] = 1;
 
  671            auto jr = wsc->invoke(method, jv)[jss::result];
 
  672            BEAST_EXPECT(jr[jss::error] == 
"invalidParams");
 
  673            BEAST_EXPECT(jr[jss::error_message] == 
"Invalid parameters.");
 
  682            auto jr = wsc->invoke(method, jv)[jss::result];
 
  683            BEAST_EXPECT(jr[jss::error] == 
"srcCurMalformed");
 
  685                jr[jss::error_message] == 
"Source currency is malformed.");
 
  694            jv[jss::books][0u][jss::taker_pays][jss::currency] = 
"ZZZZ";
 
  695            auto jr = wsc->invoke(method, jv)[jss::result];
 
  696            BEAST_EXPECT(jr[jss::error] == 
"srcCurMalformed");
 
  698                jr[jss::error_message] == 
"Source currency is malformed.");
 
  707            jv[jss::books][0u][jss::taker_pays][jss::currency] = 
"USD";
 
  708            jv[jss::books][0u][jss::taker_pays][jss::issuer] = 1;
 
  709            auto jr = wsc->invoke(method, jv)[jss::result];
 
  710            BEAST_EXPECT(jr[jss::error] == 
"srcIsrMalformed");
 
  712                jr[jss::error_message] == 
"Source issuer is malformed.");
 
  721            jv[jss::books][0u][jss::taker_pays][jss::currency] = 
"USD";
 
  722            jv[jss::books][0u][jss::taker_pays][jss::issuer] =
 
  724            auto jr = wsc->invoke(method, jv)[jss::result];
 
  725            BEAST_EXPECT(jr[jss::error] == 
"srcIsrMalformed");
 
  727                jr[jss::error_message] == 
"Source issuer is malformed.");
 
  734            jv[jss::books][0u][jss::taker_pays] =
 
  735                Account{
"gateway"}[
"USD"](1).value().getJson(
 
  738            auto jr = wsc->invoke(method, jv)[jss::result];
 
  741            BEAST_EXPECT(jr[jss::error] == 
"dstAmtMalformed");
 
  743                jr[jss::error_message] ==
 
  744                "Destination amount/currency/issuer is malformed.");
 
  751            jv[jss::books][0u][jss::taker_pays] =
 
  752                Account{
"gateway"}[
"USD"](1).value().getJson(
 
  754            jv[jss::books][0u][jss::taker_gets][jss::currency] = 
"ZZZZ";
 
  755            auto jr = wsc->invoke(method, jv)[jss::result];
 
  758            BEAST_EXPECT(jr[jss::error] == 
"dstAmtMalformed");
 
  760                jr[jss::error_message] ==
 
  761                "Destination amount/currency/issuer is malformed.");
 
  768            jv[jss::books][0u][jss::taker_pays] =
 
  769                Account{
"gateway"}[
"USD"](1).value().getJson(
 
  771            jv[jss::books][0u][jss::taker_gets][jss::currency] = 
"USD";
 
  772            jv[jss::books][0u][jss::taker_gets][jss::issuer] = 1;
 
  773            auto jr = wsc->invoke(method, jv)[jss::result];
 
  774            BEAST_EXPECT(jr[jss::error] == 
"dstIsrMalformed");
 
  776                jr[jss::error_message] == 
"Destination issuer is malformed.");
 
  783            jv[jss::books][0u][jss::taker_pays] =
 
  784                Account{
"gateway"}[
"USD"](1).value().getJson(
 
  786            jv[jss::books][0u][jss::taker_gets][jss::currency] = 
"USD";
 
  787            jv[jss::books][0u][jss::taker_gets][jss::issuer] =
 
  789            auto jr = wsc->invoke(method, jv)[jss::result];
 
  790            BEAST_EXPECT(jr[jss::error] == 
"dstIsrMalformed");
 
  792                jr[jss::error_message] == 
"Destination issuer is malformed.");
 
  799            jv[jss::books][0u][jss::taker_pays] =
 
  800                Account{
"gateway"}[
"USD"](1).value().getJson(
 
  802            jv[jss::books][0u][jss::taker_gets] =
 
  803                Account{
"gateway"}[
"USD"](1).value().getJson(
 
  805            auto jr = wsc->invoke(method, jv)[jss::result];
 
  806            BEAST_EXPECT(jr[jss::error] == 
"badMarket");
 
  807            BEAST_EXPECT(jr[jss::error_message] == 
"No such market.");
 
  810        for (
auto const& nonArray : nonArrays)
 
  813            jv[jss::streams] = nonArray;
 
  814            auto jr = wsc->invoke(method, jv)[jss::result];
 
  815            BEAST_EXPECT(jr[jss::error] == 
"invalidParams");
 
  816            BEAST_EXPECT(jr[jss::error_message] == 
"Invalid parameters.");
 
  822            jv[jss::streams][0u] = 1;
 
  823            auto jr = wsc->invoke(method, jv)[jss::result];
 
  824            BEAST_EXPECT(jr[jss::error] == 
"malformedStream");
 
  825            BEAST_EXPECT(jr[jss::error_message] == 
"Stream malformed.");
 
  831            jv[jss::streams][0u] = 
"not_a_stream";
 
  832            auto jr = wsc->invoke(method, jv)[jss::result];
 
  833            BEAST_EXPECT(jr[jss::error] == 
"malformedStream");
 
  834            BEAST_EXPECT(jr[jss::error_message] == 
"Stream malformed.");
 
 
  843        using namespace std::chrono_literals;
 
  856        auto goodSubRPC = [](
Json::Value const& subReply) -> 
bool {
 
  857            return subReply.isMember(jss::result) &&
 
  858                subReply[jss::result].isMember(jss::status) &&
 
  859                subReply[jss::result][jss::status] == jss::success;
 
  870            bool first_flag = 
false;
 
  872            for (
int i = 0; i < numReplies; ++i)
 
  875                auto reply = wsc.
getMsg(100ms);
 
  879                    if (r.isMember(jss::account_history_tx_index))
 
  880                        idx = r[jss::account_history_tx_index].asInt();
 
  881                    if (r.isMember(jss::account_history_tx_first))
 
  883                    bool boundary = r.isMember(jss::account_history_boundary);
 
  884                    int ledger_idx = r[jss::ledger_index].asInt();
 
  885                    if (r.isMember(jss::transaction) &&
 
  886                        r[jss::transaction].isMember(jss::hash))
 
  888                        auto t{r[jss::transaction]};
 
  890                            idx, t[jss::hash].asString(), boundary, ledger_idx);
 
  894                return {
false, first_flag};
 
  897            return {
true, first_flag};
 
  904        auto sendPayments = [](
Env& env,
 
  912            for (
int i = 0; i < newTxns; ++i)
 
  914                auto& from = (i % 2 == 0) ? a : b;
 
  915                auto& to = (i % 2 == 0) ? b : a;
 
  922            for (
int i = 0; i < ledgersToClose; ++i)
 
  932        auto hashCompare = [](IdxHashVec 
const& accountVec,
 
  933                              IdxHashVec 
const& txHistoryVec,
 
  934                              bool sizeCompare) -> 
bool {
 
  935            if (accountVec.empty() || txHistoryVec.empty())
 
  937            if (sizeCompare && accountVec.size() != (txHistoryVec.size()))
 
  941            for (
auto const& tx : txHistoryVec)
 
  947                if (i >= accountVec.size())
 
  950                if (it == txHistoryMap.
end())
 
  955            auto firstHistoryIndex = getHistoryIndex(0);
 
  956            if (!firstHistoryIndex)
 
  958            for (
std::size_t i = 1; i < accountVec.size(); ++i)
 
  960                if (
auto idx = getHistoryIndex(i);
 
  961                    !idx || *idx != *firstHistoryIndex + i)
 
  997        auto checkBoundary = [](IdxHashVec 
const& vec, 
bool ) {
 
  998            size_t num_tx = vec.size();
 
  999            for (
size_t i = 0; i < num_tx; ++i)
 
 1001                auto [idx, hash, boundary, ledger] = vec[i];
 
 1002                if ((i + 1 == num_tx || ledger != 
std::get<3>(vec[i + 1])) !=
 
 1022            request[jss::account_history_tx_stream][jss::account] =
 
 1024            auto jv = wscTxHistory->invoke(
"subscribe", request);
 
 1025            if (!BEAST_EXPECT(goodSubRPC(jv)))
 
 1028            jv = wscTxHistory->invoke(
"subscribe", request);
 
 1029            BEAST_EXPECT(!goodSubRPC(jv));
 
 1034            request[jss::account_history_tx_stream][jss::stop_history_tx_only] =
 
 1036            jv = wscTxHistory->invoke(
"unsubscribe", request);
 
 1037            if (!BEAST_EXPECT(goodSubRPC(jv)))
 
 1040            sendPayments(env, env.
master, alice, 1, 1, 123456);
 
 1043            auto r = getTxHash(*wscTxHistory, vec, 1);
 
 1044            if (!BEAST_EXPECT(r.first && r.second))
 
 1050            request[jss::account_history_tx_stream][jss::stop_history_tx_only] =
 
 1052            jv = wscTxHistory->invoke(
"unsubscribe", request);
 
 1053            BEAST_EXPECT(goodSubRPC(jv));
 
 1055            sendPayments(env, env.
master, alice, 1, 1);
 
 1056            r = getTxHash(*wscTxHistory, vec, 1);
 
 1057            BEAST_EXPECT(!r.first);
 
 1068            request[jss::account_history_tx_stream][jss::account] =
 
 1069                "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
 
 1070            auto jv = wscTxHistory->invoke(
"subscribe", request);
 
 1071            if (!BEAST_EXPECT(goodSubRPC(jv)))
 
 1073            IdxHashVec genesisFullHistoryVec;
 
 1075                    !getTxHash(*wscTxHistory, genesisFullHistoryVec, 1).first))
 
 1082            sendPayments(env, env.
master, bob, 1, 1, 654321);
 
 1084            auto r = getTxHash(*wscTxHistory, genesisFullHistoryVec, 1);
 
 1085            if (!BEAST_EXPECT(r.first && r.second))
 
 1088            request[jss::account_history_tx_stream][jss::account] = bob.
human();
 
 1089            jv = wscTxHistory->invoke(
"subscribe", request);
 
 1090            if (!BEAST_EXPECT(goodSubRPC(jv)))
 
 1092            IdxHashVec bobFullHistoryVec;
 
 1093            r = getTxHash(*wscTxHistory, bobFullHistoryVec, 1);
 
 1094            if (!BEAST_EXPECT(r.first && r.second))
 
 1103            jv = wscTxHistory->invoke(
"unsubscribe", request);
 
 1104            if (!BEAST_EXPECT(goodSubRPC(jv)))
 
 1106            request[jss::account_history_tx_stream][jss::account] =
 
 1107                "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
 
 1108            jv = wscTxHistory->invoke(
"unsubscribe", request);
 
 1109            BEAST_EXPECT(goodSubRPC(jv));
 
 1115            sendPayments(env, env.
master, bob, 30, 300);
 
 1117            request[jss::account_history_tx_stream][jss::account] = bob.
human();
 
 1118            jv = wscTxHistory->invoke(
"subscribe", request);
 
 1120            bobFullHistoryVec.
clear();
 
 1122                getTxHash(*wscTxHistory, bobFullHistoryVec, 31).second);
 
 1123            jv = wscTxHistory->invoke(
"unsubscribe", request);
 
 1125            request[jss::account_history_tx_stream][jss::account] =
 
 1126                "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
 
 1127            jv = wscTxHistory->invoke(
"subscribe", request);
 
 1128            genesisFullHistoryVec.
clear();
 
 1130                getTxHash(*wscTxHistory, genesisFullHistoryVec, 31).second);
 
 1131            jv = wscTxHistory->invoke(
"unsubscribe", request);
 
 1148            env.
fund(
XRP(222222), accounts);
 
 1154            stream[jss::accounts].append(alice.
human());
 
 1155            auto jv = wscAccount->invoke(
"subscribe", stream);
 
 1157            sendPayments(env, alice, bob, 5, 1);
 
 1158            sendPayments(env, alice, bob, 5, 1);
 
 1159            IdxHashVec accountVec;
 
 1160            if (!BEAST_EXPECT(getTxHash(*wscAccount, accountVec, 10).first))
 
 1166            request[jss::account_history_tx_stream][jss::account] =
 
 1168            jv = wscTxHistory->invoke(
"subscribe", request);
 
 1171            IdxHashVec txHistoryVec;
 
 1172            if (!BEAST_EXPECT(getTxHash(*wscTxHistory, txHistoryVec, 10).first))
 
 1174            if (!BEAST_EXPECT(hashCompare(accountVec, txHistoryVec, 
true)))
 
 1179            if (!BEAST_EXPECT(checkBoundary(txHistoryVec, 
false)))
 
 1184                IdxHashVec initFundTxns;
 
 1186                        getTxHash(*wscTxHistory, initFundTxns, 10).second) ||
 
 1187                    !BEAST_EXPECT(checkBoundary(initFundTxns, 
false)))
 
 1192            sendPayments(env, alice, bob, 10, 1);
 
 1193            if (!BEAST_EXPECT(getTxHash(*wscAccount, accountVec, 10).first))
 
 1195            if (!BEAST_EXPECT(getTxHash(*wscTxHistory, txHistoryVec, 10).first))
 
 1197            if (!BEAST_EXPECT(hashCompare(accountVec, txHistoryVec, 
true)))
 
 1202            if (!BEAST_EXPECT(checkBoundary(txHistoryVec, 
false)))
 
 1205            wscTxHistory->invoke(
"unsubscribe", request);
 
 1206            wscAccount->invoke(
"unsubscribe", stream);
 
 1215            auto const USD_a = alice[
"USD"];
 
 1218            env.
fund(
XRP(333333), accounts);
 
 1219            env.
trust(USD_a(20000), carol);
 
 1222            auto mixedPayments = [&]() -> 
int {
 
 1223                sendPayments(env, alice, carol, 1, 0);
 
 1224                env(
pay(alice, carol, USD_a(100)));
 
 1232            request[jss::account_history_tx_stream][jss::account] =
 
 1235            auto jv = ws->invoke(
"subscribe", request);
 
 1239                getTxHash(*ws, tempVec, 100);
 
 1242            auto count = mixedPayments();
 
 1244            if (!BEAST_EXPECT(getTxHash(*ws, vec1, count).first))
 
 1246            ws->invoke(
"unsubscribe", request);
 
 1255            env.
fund(
XRP(444444), accounts);
 
 1259            auto oneRound = [&](
int numPayments) {
 
 1260                return sendPayments(env, alice, carol, numPayments, 300);
 
 1266            request[jss::account_history_tx_stream][jss::account] =
 
 1269            auto jv = wscLong->invoke(
"subscribe", request);
 
 1273                getTxHash(*wscLong, tempVec, 100);
 
 1277            for (
int kk = 2; kk < 10; ++kk)
 
 1279                auto count = oneRound(kk);
 
 1281                if (!BEAST_EXPECT(getTxHash(*wscLong, vec1, count).first))
 
 1286                auto jv = wscShort->invoke(
"subscribe", request);
 
 1288                if (!BEAST_EXPECT(getTxHash(*wscShort, vec2, count).first))
 
 1290                if (!BEAST_EXPECT(hashCompare(vec1, vec2, 
true)))
 
 1292                wscShort->invoke(
"unsubscribe", request);
 
 
 1367        testcase(
"Test synthetic fields from Subscribe response");
 
 1369        using namespace test::jtx;
 
 1370        using namespace std::chrono_literals;
 
 1374        Account const broker{
"broker"};
 
 1376        Env env{*
this, features};
 
 1377        env.fund(
XRP(10000), alice, bob, broker);
 
 1383        stream[jss::streams].append(
"transactions");
 
 1384        auto jv = wsc->invoke(
"subscribe", stream);
 
 1389        auto verifyNFTokenID = [&](
uint256 const& actualNftID) {
 
 1390            BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
 
 1393                    nftID.parseHex(jv[jss::meta][jss::nftoken_id].asString()));
 
 1394                return nftID == actualNftID;
 
 1400        auto verifyNFTokenIDsInCancelOffer =
 
 1402                BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
 
 1403                    std::vector<uint256> metaIDs;
 
 1405                        jv[jss::meta][jss::nftoken_ids].begin(),
 
 1406                        jv[jss::meta][jss::nftoken_ids].end(),
 
 1407                        std::back_inserter(metaIDs),
 
 1408                        [this](Json::Value id) {
 
 1410                            BEAST_EXPECT(nftID.parseHex(id.asString()));
 
 1414                    std::sort(metaIDs.begin(), metaIDs.end());
 
 1415                    std::sort(actualNftIDs.begin(), actualNftIDs.end());
 
 1418                    BEAST_EXPECT(metaIDs.size() == actualNftIDs.size());
 
 1422                    for (
size_t i = 0; i < metaIDs.size(); ++i)
 
 1423                        BEAST_EXPECT(metaIDs[i] == actualNftIDs[i]);
 
 1430        auto verifyNFTokenOfferID = [&](
uint256 const& offerID) {
 
 1431            BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
 
 1432                uint256 metaOfferID;
 
 1433                BEAST_EXPECT(metaOfferID.parseHex(
 
 1434                    jv[jss::meta][jss::offer_id].asString()));
 
 1435                return metaOfferID == offerID;
 
 1447            verifyNFTokenID(nftId1);
 
 1453            verifyNFTokenID(nftId2);
 
 1458            uint256 const aliceOfferIndex1 =
 
 1463            verifyNFTokenOfferID(aliceOfferIndex1);
 
 1465            uint256 const aliceOfferIndex2 =
 
 1470            verifyNFTokenOfferID(aliceOfferIndex2);
 
 1476                alice, {aliceOfferIndex1, aliceOfferIndex2}));
 
 1478            verifyNFTokenIDsInCancelOffer({nftId1, nftId2});
 
 1482            auto const bobBuyOfferIndex =
 
 1486            verifyNFTokenOfferID(bobBuyOfferIndex);
 
 1492            verifyNFTokenID(nftId1);
 
 1502            verifyNFTokenID(nftId);
 
 1505            uint256 const offerAliceToBroker =
 
 1508                token::destination(broker),
 
 1511            verifyNFTokenOfferID(offerAliceToBroker);
 
 1514            uint256 const offerBobToBroker =
 
 1518            verifyNFTokenOfferID(offerBobToBroker);
 
 1522                broker, offerBobToBroker, offerAliceToBroker));
 
 1524            verifyNFTokenID(nftId);
 
 1535            verifyNFTokenID(nftId);
 
 1538            uint256 const aliceOfferIndex1 =
 
 1543            verifyNFTokenOfferID(aliceOfferIndex1);
 
 1545            uint256 const aliceOfferIndex2 =
 
 1550            verifyNFTokenOfferID(aliceOfferIndex2);
 
 1555                alice, {aliceOfferIndex1, aliceOfferIndex2}));
 
 1557            verifyNFTokenIDsInCancelOffer({nftId});
 
 1560        if (features[featureNFTokenMintOffer])
 
 1562            uint256 const aliceMintWithOfferIndex1 =
 
 1566            verifyNFTokenOfferID(aliceMintWithOfferIndex1);