18 #include <ripple/app/main/LoadManager.h>
19 #include <ripple/app/misc/LoadFeeTrack.h>
20 #include <ripple/app/misc/NetworkOPs.h>
21 #include <ripple/beast/unit_test.h>
22 #include <ripple/core/ConfigSections.h>
23 #include <ripple/protocol/Feature.h>
24 #include <ripple/protocol/jss.h>
26 #include <test/jtx/WSClient.h>
27 #include <test/jtx/envconfig.h>
38 using namespace std::chrono_literals;
47 stream[jss::streams].append(
"server");
48 auto jv = wsc->invoke(
"subscribe", stream);
49 if (wsc->version() == 2)
52 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
54 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
55 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
57 BEAST_EXPECT(jv[jss::status] ==
"success");
69 for (
int i = 0; i < 5; ++i)
74 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
75 return jv[jss::type] ==
"serverStatus";
81 auto jv = wsc->invoke(
"unsubscribe", stream);
82 if (wsc->version() == 2)
85 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
87 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
88 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
90 BEAST_EXPECT(jv[jss::status] ==
"success");
96 for (
int i = 0; i < 5; ++i)
101 auto jvo = wsc->getMsg(10ms);
102 BEAST_EXPECTS(!jvo,
"getMsg: " +
to_string(jvo.value()));
109 using namespace std::chrono_literals;
118 stream[jss::streams].append(
"ledger");
119 auto jv = wsc->invoke(
"subscribe", stream);
120 if (wsc->version() == 2)
123 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
125 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
126 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
128 BEAST_EXPECT(jv[jss::result][jss::ledger_index] == 2);
136 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
137 return jv[jss::ledger_index] == 3;
146 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
147 return jv[jss::ledger_index] == 4;
152 auto jv = wsc->invoke(
"unsubscribe", stream);
153 if (wsc->version() == 2)
156 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
158 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
159 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
161 BEAST_EXPECT(jv[jss::status] ==
"success");
167 using namespace std::chrono_literals;
176 stream[jss::streams].append(
"transactions");
177 auto jv = wsc->invoke(
"subscribe", stream);
178 if (wsc->version() == 2)
181 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
183 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
184 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
186 BEAST_EXPECT(jv[jss::status] ==
"success");
194 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
195 return jv[jss::meta][
"AffectedNodes"][1u][
"CreatedNode"]
196 [
"NewFields"][jss::Account] ==
197 Account(
"alice").human();
201 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
202 return jv[jss::meta][
"AffectedNodes"][0u][
"ModifiedNode"]
203 [
"FinalFields"][jss::Account] ==
204 Account(
"alice").human();
211 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
212 return jv[jss::meta][
"AffectedNodes"][1u][
"CreatedNode"]
213 [
"NewFields"][jss::Account] == Account(
"bob").human();
217 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
218 return jv[jss::meta][
"AffectedNodes"][0u][
"ModifiedNode"]
219 [
"FinalFields"][jss::Account] ==
220 Account(
"bob").human();
226 auto jv = wsc->invoke(
"unsubscribe", stream);
227 if (wsc->version() == 2)
230 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
232 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
233 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
235 BEAST_EXPECT(jv[jss::status] ==
"success");
242 stream[jss::accounts].append(
Account(
"alice").human());
243 auto jv = wsc->invoke(
"subscribe", stream);
244 if (wsc->version() == 2)
247 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
249 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
250 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
252 BEAST_EXPECT(jv[jss::status] ==
"success");
259 BEAST_EXPECT(!wsc->getMsg(10ms));
266 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
267 return jv[jss::meta][
"AffectedNodes"][1u][
"ModifiedNode"]
268 [
"FinalFields"][jss::Account] ==
269 Account(
"alice").human();
272 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
273 return jv[jss::meta][
"AffectedNodes"][1u][
"CreatedNode"]
274 [
"NewFields"][
"LowLimit"][jss::issuer] ==
275 Account(
"alice").human();
280 auto jv = wsc->invoke(
"unsubscribe", stream);
281 if (wsc->version() == 2)
284 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
286 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
287 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
289 BEAST_EXPECT(jv[jss::status] ==
"success");
303 stream[jss::streams].append(
"manifests");
304 auto jv = wsc->invoke(
"subscribe", stream);
305 if (wsc->version() == 2)
308 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
310 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
311 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
313 BEAST_EXPECT(jv[jss::status] ==
"success");
317 auto jv = wsc->invoke(
"unsubscribe", stream);
318 if (wsc->version() == 2)
321 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
323 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
324 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
326 BEAST_EXPECT(jv[jss::status] ==
"success");
335 auto& cfg = env.app().config();
336 if (!BEAST_EXPECT(cfg.section(SECTION_VALIDATION_SEED).empty()))
338 auto const parsedseed =
339 parseBase58<Seed>(cfg.section(SECTION_VALIDATION_SEED).values()[0]);
340 if (!BEAST_EXPECT(parsedseed))
355 stream[jss::streams].append(
"validations");
356 auto jv = wsc->invoke(
"subscribe", stream);
357 if (wsc->version() == 2)
360 jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
362 jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
363 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
365 BEAST_EXPECT(jv[jss::status] ==
"success");
370 auto validValidationFields = [&env, &valPublicKey](
372 if (jv[jss::type] !=
"validationReceived")
375 if (jv[jss::validation_public_key].asString() != valPublicKey)
378 if (jv[jss::ledger_hash] !=
382 if (jv[jss::ledger_index] !=
389 if (jv[jss::full] !=
true)
392 if (jv.isMember(jss::load_fee))
395 if (!jv.isMember(jss::signature))
398 if (!jv.isMember(jss::signing_time))
401 if (!jv.isMember(jss::cookie))
404 if (!jv.isMember(jss::validated_hash))
409 (env.closed()->info().seq + 1) % 256 == 0;
417 (xrpFees && jv.isMember(jss::reserve_base)))
422 (xrpFees && jv.isMember(jss::reserve_inc)))
426 jv.isMember(jss::reserve_base_drops) !=
isFlagLedger) ||
427 (!xrpFees && jv.isMember(jss::reserve_base_drops)))
432 (!xrpFees && jv.isMember(jss::reserve_inc_drops)))
440 while (env.closed()->info().seq < 300)
443 using namespace std::chrono_literals;
444 BEAST_EXPECT(wsc->findMsg(5s, validValidationFields));
449 auto jv = wsc->invoke(
"unsubscribe", 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");
465 testcase(
"Subscribe by url");
469 jv[jss::url] =
"http://localhost/events";
470 jv[jss::url_username] =
"admin";
471 jv[jss::url_password] =
"password";
473 jv[jss::streams][0u] =
"validations";
474 auto jr = env.rpc(
"json",
"subscribe",
to_string(jv))[jss::result];
475 BEAST_EXPECT(jr[jss::status] ==
"success");
477 jv[jss::streams][0u] =
"ledger";
478 jr = env.rpc(
"json",
"subscribe",
to_string(jv))[jss::result];
479 BEAST_EXPECT(jr[jss::status] ==
"success");
481 jr = env.rpc(
"json",
"unsubscribe",
to_string(jv))[jss::result];
482 BEAST_EXPECT(jr[jss::status] ==
"success");
484 jv[jss::streams][0u] =
"validations";
485 jr = env.rpc(
"json",
"unsubscribe",
to_string(jv))[jss::result];
486 BEAST_EXPECT(jr[jss::status] ==
"success");
493 auto const method = subscribe ?
"subscribe" :
"unsubscribe";
494 testcase <<
"Error cases for " << method;
500 auto jr = env.rpc(
"json", method,
"{}")[jss::result];
501 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
502 BEAST_EXPECT(jr[jss::error_message] ==
"Invalid parameters.");
507 jv[jss::url] =
"not-a-url";
508 jv[jss::username] =
"admin";
509 jv[jss::password] =
"password";
510 auto jr = env.rpc(
"json", method,
to_string(jv))[jss::result];
513 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
514 BEAST_EXPECT(jr[jss::error_message] ==
"Failed to parse url.");
522 jv[jss::url] =
"ftp://scheme.not.supported.tld";
523 auto jr = env.rpc(
"json", method,
to_string(jv))[jss::result];
526 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
528 jr[jss::error_message] ==
529 "Only http and https is supported.");
536 jv[jss::url] =
"no-url";
538 env_nonadmin.rpc(
"json", method,
to_string(jv))[jss::result];
539 BEAST_EXPECT(jr[jss::error] ==
"noPermission");
541 jr[jss::error_message] ==
542 "You don't have permission for this command.");
554 for (
auto const& f : {jss::accounts_proposed, jss::accounts})
556 for (
auto const& nonArray : nonArrays)
560 auto jr = wsc->invoke(method, jv)[jss::result];
561 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
562 BEAST_EXPECT(jr[jss::error_message] ==
"Invalid parameters.");
568 auto jr = wsc->invoke(method, jv)[jss::result];
569 BEAST_EXPECT(jr[jss::error] ==
"actMalformed");
570 BEAST_EXPECT(jr[jss::error_message] ==
"Account malformed.");
574 for (
auto const& nonArray : nonArrays)
577 jv[jss::books] = nonArray;
578 auto jr = wsc->invoke(method, jv)[jss::result];
579 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
580 BEAST_EXPECT(jr[jss::error_message] ==
"Invalid parameters.");
586 jv[jss::books][0u] = 1;
587 auto jr = wsc->invoke(method, jv)[jss::result];
588 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
589 BEAST_EXPECT(jr[jss::error_message] ==
"Invalid parameters.");
598 auto jr = wsc->invoke(method, jv)[jss::result];
599 BEAST_EXPECT(jr[jss::error] ==
"srcCurMalformed");
601 jr[jss::error_message] ==
"Source currency is malformed.");
610 jv[jss::books][0u][jss::taker_pays][jss::currency] =
"ZZZZ";
611 auto jr = wsc->invoke(method, jv)[jss::result];
612 BEAST_EXPECT(jr[jss::error] ==
"srcCurMalformed");
614 jr[jss::error_message] ==
"Source currency is malformed.");
623 jv[jss::books][0u][jss::taker_pays][jss::currency] =
"USD";
624 jv[jss::books][0u][jss::taker_pays][jss::issuer] = 1;
625 auto jr = wsc->invoke(method, jv)[jss::result];
626 BEAST_EXPECT(jr[jss::error] ==
"srcIsrMalformed");
628 jr[jss::error_message] ==
"Source issuer is malformed.");
637 jv[jss::books][0u][jss::taker_pays][jss::currency] =
"USD";
638 jv[jss::books][0u][jss::taker_pays][jss::issuer] =
640 auto jr = wsc->invoke(method, jv)[jss::result];
641 BEAST_EXPECT(jr[jss::error] ==
"srcIsrMalformed");
643 jr[jss::error_message] ==
"Source issuer is malformed.");
650 jv[jss::books][0u][jss::taker_pays] =
651 Account{
"gateway"}[
"USD"](1).value().getJson(
654 auto jr = wsc->invoke(method, jv)[jss::result];
657 BEAST_EXPECT(jr[jss::error] ==
"dstAmtMalformed");
659 jr[jss::error_message] ==
660 "Destination amount/currency/issuer is malformed.");
667 jv[jss::books][0u][jss::taker_pays] =
668 Account{
"gateway"}[
"USD"](1).value().getJson(
670 jv[jss::books][0u][jss::taker_gets][jss::currency] =
"ZZZZ";
671 auto jr = wsc->invoke(method, jv)[jss::result];
674 BEAST_EXPECT(jr[jss::error] ==
"dstAmtMalformed");
676 jr[jss::error_message] ==
677 "Destination amount/currency/issuer is malformed.");
684 jv[jss::books][0u][jss::taker_pays] =
685 Account{
"gateway"}[
"USD"](1).value().getJson(
687 jv[jss::books][0u][jss::taker_gets][jss::currency] =
"USD";
688 jv[jss::books][0u][jss::taker_gets][jss::issuer] = 1;
689 auto jr = wsc->invoke(method, jv)[jss::result];
690 BEAST_EXPECT(jr[jss::error] ==
"dstIsrMalformed");
692 jr[jss::error_message] ==
"Destination issuer is malformed.");
699 jv[jss::books][0u][jss::taker_pays] =
700 Account{
"gateway"}[
"USD"](1).value().getJson(
702 jv[jss::books][0u][jss::taker_gets][jss::currency] =
"USD";
703 jv[jss::books][0u][jss::taker_gets][jss::issuer] =
705 auto jr = wsc->invoke(method, jv)[jss::result];
706 BEAST_EXPECT(jr[jss::error] ==
"dstIsrMalformed");
708 jr[jss::error_message] ==
"Destination issuer is malformed.");
715 jv[jss::books][0u][jss::taker_pays] =
716 Account{
"gateway"}[
"USD"](1).value().getJson(
718 jv[jss::books][0u][jss::taker_gets] =
719 Account{
"gateway"}[
"USD"](1).value().getJson(
721 auto jr = wsc->invoke(method, jv)[jss::result];
722 BEAST_EXPECT(jr[jss::error] ==
"badMarket");
723 BEAST_EXPECT(jr[jss::error_message] ==
"No such market.");
726 for (
auto const& nonArray : nonArrays)
729 jv[jss::streams] = nonArray;
730 auto jr = wsc->invoke(method, jv)[jss::result];
731 BEAST_EXPECT(jr[jss::error] ==
"invalidParams");
732 BEAST_EXPECT(jr[jss::error_message] ==
"Invalid parameters.");
738 jv[jss::streams][0u] = 1;
739 auto jr = wsc->invoke(method, jv)[jss::result];
740 BEAST_EXPECT(jr[jss::error] ==
"malformedStream");
741 BEAST_EXPECT(jr[jss::error_message] ==
"Stream malformed.");
747 jv[jss::streams][0u] =
"not_a_stream";
748 auto jr = wsc->invoke(method, jv)[jss::result];
749 BEAST_EXPECT(jr[jss::error] ==
"malformedStream");
750 BEAST_EXPECT(jr[jss::error_message] ==
"Stream malformed.");
757 testcase(
"HistoryTxStream");
759 using namespace std::chrono_literals;
772 auto goodSubRPC = [](
Json::Value const& subReply) ->
bool {
773 return subReply.isMember(jss::result) &&
774 subReply[jss::result].isMember(jss::status) &&
775 subReply[jss::result][jss::status] == jss::success;
786 bool first_flag =
false;
788 for (
int i = 0; i < numReplies; ++i)
791 auto reply = wsc.
getMsg(100ms);
795 if (r.isMember(jss::account_history_tx_index))
796 idx = r[jss::account_history_tx_index].asInt();
797 if (r.isMember(jss::account_history_tx_first))
799 if (r.isMember(jss::transaction) &&
800 r[jss::transaction].isMember(jss::hash))
803 idx, r[jss::transaction][jss::hash].asString());
807 return {
false, first_flag};
810 return {
true, first_flag};
817 auto sendPayments = [](
Env& env,
825 for (
int i = 0; i < newTxns; ++i)
827 auto& from = (i % 2 == 0) ? a : b;
828 auto& to = (i % 2 == 0) ? b : a;
835 for (
int i = 0; i < ledgersToClose; ++i)
845 auto hashCompare = [](IdxHashVec
const& accountVec,
846 IdxHashVec
const& txHistoryVec,
847 bool sizeCompare) ->
bool {
848 if (accountVec.empty() || txHistoryVec.empty())
850 if (sizeCompare && accountVec.size() != (txHistoryVec.size()))
854 for (
auto const& tx : txHistoryVec)
856 txHistoryMap.
emplace(tx.second, tx.first);
860 if (i >= accountVec.size())
862 auto it = txHistoryMap.
find(accountVec[i].second);
863 if (it == txHistoryMap.
end())
868 auto firstHistoryIndex = getHistoryIndex(0);
869 if (!firstHistoryIndex)
871 for (
std::size_t i = 1; i < accountVec.size(); ++i)
873 if (
auto idx = getHistoryIndex(i);
874 !idx || *idx != *firstHistoryIndex + i)
893 request[jss::account_history_tx_stream][jss::account] =
895 auto jv = wscTxHistory->invoke(
"subscribe", request);
896 if (!BEAST_EXPECT(goodSubRPC(jv)))
898 jv = wscTxHistory->invoke(
"subscribe", request);
899 BEAST_EXPECT(!goodSubRPC(jv));
904 request[jss::account_history_tx_stream][jss::stop_history_tx_only] =
906 jv = wscTxHistory->invoke(
"unsubscribe", request);
907 if (!BEAST_EXPECT(goodSubRPC(jv)))
910 sendPayments(env, env.
master, alice, 1, 1, 123456);
913 auto r = getTxHash(*wscTxHistory, vec, 1);
914 if (!BEAST_EXPECT(r.first && r.second))
920 request[jss::account_history_tx_stream][jss::stop_history_tx_only] =
922 jv = wscTxHistory->invoke(
"unsubscribe", request);
923 BEAST_EXPECT(goodSubRPC(jv));
925 sendPayments(env, env.
master, alice, 1, 1);
926 r = getTxHash(*wscTxHistory, vec, 1);
927 BEAST_EXPECT(!r.first);
939 request[jss::account_history_tx_stream][jss::account] =
940 "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
941 auto jv = wscTxHistory->invoke(
"subscribe", request);
942 if (!BEAST_EXPECT(goodSubRPC(jv)))
944 IdxHashVec genesisFullHistoryVec;
946 !getTxHash(*wscTxHistory, genesisFullHistoryVec, 1).first))
953 sendPayments(env, env.
master, bob, 1, 1, 654321);
955 auto r = getTxHash(*wscTxHistory, genesisFullHistoryVec, 1);
956 if (!BEAST_EXPECT(r.first && r.second))
959 request[jss::account_history_tx_stream][jss::account] = bob.
human();
960 jv = wscTxHistory->invoke(
"subscribe", request);
961 if (!BEAST_EXPECT(goodSubRPC(jv)))
963 IdxHashVec bobFullHistoryVec;
964 r = getTxHash(*wscTxHistory, bobFullHistoryVec, 1);
965 if (!BEAST_EXPECT(r.first && r.second))
968 bobFullHistoryVec.back().second ==
969 genesisFullHistoryVec.back().second);
974 jv = wscTxHistory->invoke(
"unsubscribe", request);
975 if (!BEAST_EXPECT(goodSubRPC(jv)))
977 request[jss::account_history_tx_stream][jss::account] =
978 "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
979 jv = wscTxHistory->invoke(
"unsubscribe", request);
980 BEAST_EXPECT(goodSubRPC(jv));
986 sendPayments(env, env.
master, bob, 30, 300);
988 request[jss::account_history_tx_stream][jss::account] = bob.
human();
989 jv = wscTxHistory->invoke(
"subscribe", request);
991 bobFullHistoryVec.
clear();
993 getTxHash(*wscTxHistory, bobFullHistoryVec, 31).second);
994 jv = wscTxHistory->invoke(
"unsubscribe", request);
996 request[jss::account_history_tx_stream][jss::account] =
997 "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
998 jv = wscTxHistory->invoke(
"subscribe", request);
999 genesisFullHistoryVec.
clear();
1001 getTxHash(*wscTxHistory, genesisFullHistoryVec, 31).second);
1002 jv = wscTxHistory->invoke(
"unsubscribe", request);
1005 bobFullHistoryVec.back().second ==
1006 genesisFullHistoryVec.back().second);
1019 env.
fund(
XRP(222222), accounts);
1025 stream[jss::accounts].append(alice.
human());
1026 auto jv = wscAccount->invoke(
"subscribe", stream);
1028 sendPayments(env, alice, bob, 5, 1);
1029 sendPayments(env, alice, bob, 5, 1);
1030 IdxHashVec accountVec;
1031 if (!BEAST_EXPECT(getTxHash(*wscAccount, accountVec, 10).first))
1037 request[jss::account_history_tx_stream][jss::account] =
1039 jv = wscTxHistory->invoke(
"subscribe", request);
1042 IdxHashVec txHistoryVec;
1043 if (!BEAST_EXPECT(getTxHash(*wscTxHistory, txHistoryVec, 10).first))
1045 if (!BEAST_EXPECT(hashCompare(accountVec, txHistoryVec,
true)))
1050 IdxHashVec initFundTxns;
1052 getTxHash(*wscTxHistory, initFundTxns, 10).second))
1057 sendPayments(env, alice, bob, 10, 1);
1058 if (!BEAST_EXPECT(getTxHash(*wscAccount, accountVec, 10).first))
1060 if (!BEAST_EXPECT(getTxHash(*wscTxHistory, txHistoryVec, 10).first))
1062 if (!BEAST_EXPECT(hashCompare(accountVec, txHistoryVec,
true)))
1064 wscTxHistory->invoke(
"unsubscribe", request);
1065 wscAccount->invoke(
"unsubscribe", stream);
1074 auto const USD_a = alice[
"USD"];
1077 env.
fund(
XRP(333333), accounts);
1078 env.
trust(USD_a(20000), carol);
1081 auto mixedPayments = [&]() ->
int {
1082 sendPayments(env, alice, carol, 1, 0);
1083 env(
pay(alice, carol, USD_a(100)));
1091 request[jss::account_history_tx_stream][jss::account] =
1094 auto jv = ws->invoke(
"subscribe", request);
1098 getTxHash(*ws, tempVec, 100);
1101 auto count = mixedPayments();
1103 if (!BEAST_EXPECT(getTxHash(*ws, vec1, count).first))
1105 ws->invoke(
"unsubscribe", request);
1114 env.
fund(
XRP(444444), accounts);
1118 auto oneRound = [&](
int numPayments) {
1119 return sendPayments(env, alice, carol, numPayments, 300);
1125 request[jss::account_history_tx_stream][jss::account] =
1128 auto jv = wscLong->invoke(
"subscribe", request);
1132 getTxHash(*wscLong, tempVec, 100);
1136 for (
int kk = 2; kk < 10; ++kk)
1138 auto count = oneRound(kk);
1140 if (!BEAST_EXPECT(getTxHash(*wscLong, vec1, count).first))
1145 auto jv = wscShort->invoke(
"subscribe", request);
1147 if (!BEAST_EXPECT(getTxHash(*wscShort, vec2, count).first))
1149 if (!BEAST_EXPECT(hashCompare(vec1, vec2,
true)))
1151 wscShort->invoke(
"unsubscribe", request);
1159 using namespace test::jtx;