455 testcase(
"Multiple Books, One Side Offers In Book");
456 using namespace std::chrono_literals;
460 auto USD =
Account(
"alice")[
"USD"];
461 auto CNY =
Account(
"alice")[
"CNY"];
462 auto JPY =
Account(
"alice")[
"JPY"];
484 j[jss::snapshot] =
true;
485 j[jss::taker_gets][jss::currency] =
"XRP";
486 j[jss::taker_pays][jss::currency] =
"USD";
487 j[jss::taker_pays][jss::issuer] =
Account(
"alice").
human();
491 j[jss::snapshot] =
true;
492 j[jss::taker_gets][jss::currency] =
"CNY";
493 j[jss::taker_gets][jss::issuer] =
Account(
"alice").
human();
494 j[jss::taker_pays][jss::currency] =
"JPY";
495 j[jss::taker_pays][jss::issuer] =
Account(
"alice").
human();
498 auto jv = wsc->invoke(
"subscribe", books);
499 if (wsc->version() == 2)
501 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
502 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
503 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
505 if (!BEAST_EXPECT(jv[jss::status] ==
"success"))
507 BEAST_EXPECT(jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 2);
516 BEAST_EXPECT(!jv[jss::result].isMember(jss::asks));
517 BEAST_EXPECT(!jv[jss::result].isMember(jss::bids));
526 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
527 auto const& t = jv[jss::transaction];
528 return t[jss::TransactionType] == jss::OfferCreate &&
529 t[jss::TakerGets] == USD(100).value().getJson(JsonOptions::none) &&
530 t[jss::TakerPays] == XRP(700).value().getJson(JsonOptions::none);
538 BEAST_EXPECT(!wsc->getMsg(10ms));
547 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
548 auto const& t = jv[jss::transaction];
549 return t[jss::TransactionType] == jss::OfferCreate &&
550 t[jss::TakerGets] == JPY(100).value().getJson(JsonOptions::none) &&
551 t[jss::TakerPays] == CNY(700).value().getJson(JsonOptions::none);
559 BEAST_EXPECT(!wsc->getMsg(10ms));
563 auto jv = wsc->invoke(
"unsubscribe", books);
564 BEAST_EXPECT(jv[jss::status] ==
"success");
565 if (wsc->version() == 2)
567 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
568 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
569 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
576 testcase(
"Multiple Books, Both Sides Empty Book");
577 using namespace std::chrono_literals;
581 auto USD =
Account(
"alice")[
"USD"];
582 auto CNY =
Account(
"alice")[
"CNY"];
583 auto JPY =
Account(
"alice")[
"JPY"];
592 j[jss::snapshot] =
true;
594 j[jss::taker_gets][jss::currency] =
"XRP";
595 j[jss::taker_pays][jss::currency] =
"USD";
596 j[jss::taker_pays][jss::issuer] =
Account(
"alice").
human();
600 j[jss::snapshot] =
true;
602 j[jss::taker_gets][jss::currency] =
"CNY";
603 j[jss::taker_gets][jss::issuer] =
Account(
"alice").
human();
604 j[jss::taker_pays][jss::currency] =
"JPY";
605 j[jss::taker_pays][jss::issuer] =
Account(
"alice").
human();
608 auto jv = wsc->invoke(
"subscribe", books);
609 if (wsc->version() == 2)
611 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
612 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
613 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
615 if (!BEAST_EXPECT(jv[jss::status] ==
"success"))
617 BEAST_EXPECT(jv[jss::result].isMember(jss::asks) && jv[jss::result][jss::asks].size() == 0);
618 BEAST_EXPECT(jv[jss::result].isMember(jss::bids) && jv[jss::result][jss::bids].size() == 0);
619 BEAST_EXPECT(!jv[jss::result].isMember(jss::offers));
628 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
629 auto const& t = jv[jss::transaction];
630 return t[jss::TransactionType] == jss::OfferCreate &&
631 t[jss::TakerGets] == USD(100).value().getJson(JsonOptions::none) &&
632 t[jss::TakerPays] == XRP(700).value().getJson(JsonOptions::none);
642 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
643 auto const& t = jv[jss::transaction];
644 return t[jss::TransactionType] == jss::OfferCreate &&
645 t[jss::TakerGets] == XRP(75).value().getJson(JsonOptions::none) &&
646 t[jss::TakerPays] == USD(100).value().getJson(JsonOptions::none);
656 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
657 auto const& t = jv[jss::transaction];
658 return t[jss::TransactionType] == jss::OfferCreate &&
659 t[jss::TakerGets] == JPY(100).value().getJson(JsonOptions::none) &&
660 t[jss::TakerPays] == CNY(700).value().getJson(JsonOptions::none);
670 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
671 auto const& t = jv[jss::transaction];
672 return t[jss::TransactionType] == jss::OfferCreate &&
673 t[jss::TakerGets] == CNY(75).value().getJson(JsonOptions::none) &&
674 t[jss::TakerPays] == JPY(100).value().getJson(JsonOptions::none);
679 auto jv = wsc->invoke(
"unsubscribe", books);
680 BEAST_EXPECT(jv[jss::status] ==
"success");
681 if (wsc->version() == 2)
683 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
684 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
685 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
692 testcase(
"Multiple Books, Both Sides Offers In Book");
693 using namespace std::chrono_literals;
697 auto USD =
Account(
"alice")[
"USD"];
698 auto CNY =
Account(
"alice")[
"CNY"];
699 auto JPY =
Account(
"alice")[
"JPY"];
721 j[jss::snapshot] =
true;
723 j[jss::taker_gets][jss::currency] =
"XRP";
724 j[jss::taker_pays][jss::currency] =
"USD";
725 j[jss::taker_pays][jss::issuer] =
Account(
"alice").
human();
730 j[jss::snapshot] =
true;
732 j[jss::taker_gets][jss::currency] =
"CNY";
733 j[jss::taker_gets][jss::issuer] =
Account(
"alice").
human();
734 j[jss::taker_pays][jss::currency] =
"JPY";
735 j[jss::taker_pays][jss::issuer] =
Account(
"alice").
human();
738 auto jv = wsc->invoke(
"subscribe", books);
739 if (wsc->version() == 2)
741 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
742 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
743 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
745 if (!BEAST_EXPECT(jv[jss::status] ==
"success"))
747 BEAST_EXPECT(jv[jss::result].isMember(jss::asks) && jv[jss::result][jss::asks].size() == 2);
748 BEAST_EXPECT(jv[jss::result].isMember(jss::bids) && jv[jss::result][jss::bids].size() == 2);
757 BEAST_EXPECT(!jv[jss::result].isMember(jss::offers));
766 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
767 auto const& t = jv[jss::transaction];
768 return t[jss::TransactionType] == jss::OfferCreate &&
769 t[jss::TakerGets] == USD(100).value().getJson(JsonOptions::none) &&
770 t[jss::TakerPays] == XRP(700).value().getJson(JsonOptions::none);
780 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
781 auto const& t = jv[jss::transaction];
782 return t[jss::TransactionType] == jss::OfferCreate &&
783 t[jss::TakerGets] == XRP(75).value().getJson(JsonOptions::none) &&
784 t[jss::TakerPays] == USD(100).value().getJson(JsonOptions::none);
794 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
795 auto const& t = jv[jss::transaction];
796 return t[jss::TransactionType] == jss::OfferCreate &&
797 t[jss::TakerGets] == JPY(100).value().getJson(JsonOptions::none) &&
798 t[jss::TakerPays] == CNY(700).value().getJson(JsonOptions::none);
808 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
809 auto const& t = jv[jss::transaction];
810 return t[jss::TransactionType] == jss::OfferCreate &&
811 t[jss::TakerGets] == CNY(75).value().getJson(JsonOptions::none) &&
812 t[jss::TakerPays] == JPY(100).value().getJson(JsonOptions::none);
817 auto jv = wsc->invoke(
"unsubscribe", books);
818 BEAST_EXPECT(jv[jss::status] ==
"success");
819 if (wsc->version() == 2)
821 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
822 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
823 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
837 env.
fund(
XRP(20000), alice, bob, gw);
839 auto USD = gw[
"USD"];
846 j[jss::snapshot] =
true;
847 j[jss::taker_gets][jss::currency] =
"XRP";
848 j[jss::taker_pays][jss::currency] =
"USD";
849 j[jss::taker_pays][jss::issuer] = gw.human();
852 auto jv = wsc->invoke(
"subscribe", books);
853 if (wsc->version() == 2)
855 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
856 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
857 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
859 if (!BEAST_EXPECT(jv[jss::status] ==
"success"))
861 BEAST_EXPECT(jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 0);
862 BEAST_EXPECT(!jv[jss::result].isMember(jss::asks));
863 BEAST_EXPECT(!jv[jss::result].isMember(jss::bids));
868 env.
trust(USD(1000), alice);
869 env.
trust(USD(1000), bob);
870 env(
pay(gw, alice, USD(100)));
871 env(
pay(gw, bob, USD(50)));
872 env(
offer(alice,
XRP(4000), USD(10)));
877 jvParams[jss::taker_pays][jss::currency] =
"XRP";
878 jvParams[jss::ledger_index] =
"validated";
879 jvParams[jss::taker_gets][jss::currency] =
"USD";
880 jvParams[jss::taker_gets][jss::issuer] = gw.human();
882 auto jv = wsc->invoke(
"book_offers", jvParams);
883 if (wsc->version() == 2)
885 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
886 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
887 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
889 auto jrr = jv[jss::result];
891 BEAST_EXPECT(jrr[jss::offers].isArray());
892 BEAST_EXPECT(jrr[jss::offers].size() == 1);
893 auto const jrOffer = jrr[jss::offers][0u];
894 BEAST_EXPECT(jrOffer[sfAccount.fieldName] == alice.human());
895 BEAST_EXPECT(jrOffer[sfBookDirectory.fieldName] ==
getBookDir(env,
XRP, USD.issue()));
896 BEAST_EXPECT(jrOffer[sfBookNode.fieldName] ==
"0");
897 BEAST_EXPECT(jrOffer[jss::Flags] == 0);
898 BEAST_EXPECT(jrOffer[sfLedgerEntryType.fieldName] == jss::Offer);
899 BEAST_EXPECT(jrOffer[sfOwnerNode.fieldName] ==
"0");
900 BEAST_EXPECT(jrOffer[sfSequence.fieldName] == 5);
903 BEAST_EXPECT(jrOffer[jss::owner_funds] ==
"100");
904 BEAST_EXPECT(jrOffer[jss::quality] ==
"400000000");
906 using namespace std::chrono_literals;
907 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jval) {
908 auto const& t = jval[jss::transaction];
909 return t[jss::TransactionType] == jss::OfferCreate &&
910 t[jss::TakerGets] == USD(10).value().getJson(JsonOptions::none) && t[jss::owner_funds] ==
"100" &&
911 t[jss::TakerPays] == XRP(4000).value().getJson(JsonOptions::none);
917 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jval) {
918 auto const& t = jval[jss::transaction];
919 return t[jss::TransactionType] == jss::OfferCreate &&
920 t[jss::TakerGets] == USD(5).value().getJson(JsonOptions::none) && t[jss::owner_funds] ==
"50" &&
921 t[jss::TakerPays] == XRP(2000).value().getJson(JsonOptions::none);
924 jv = wsc->invoke(
"book_offers", jvParams);
925 if (wsc->version() == 2)
927 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
928 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
929 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
931 jrr = jv[jss::result];
933 BEAST_EXPECT(jrr[jss::offers].isArray());
934 BEAST_EXPECT(jrr[jss::offers].size() == 2);
935 auto const jrNextOffer = jrr[jss::offers][1u];
936 BEAST_EXPECT(jrNextOffer[sfAccount.fieldName] == bob.human());
937 BEAST_EXPECT(jrNextOffer[sfBookDirectory.fieldName] ==
getBookDir(env,
XRP, USD.issue()));
938 BEAST_EXPECT(jrNextOffer[sfBookNode.fieldName] ==
"0");
939 BEAST_EXPECT(jrNextOffer[jss::Flags] == 0);
940 BEAST_EXPECT(jrNextOffer[sfLedgerEntryType.fieldName] == jss::Offer);
941 BEAST_EXPECT(jrNextOffer[sfOwnerNode.fieldName] ==
"0");
942 BEAST_EXPECT(jrNextOffer[sfSequence.fieldName] == 5);
945 BEAST_EXPECT(jrNextOffer[jss::owner_funds] ==
"50");
946 BEAST_EXPECT(jrNextOffer[jss::quality] ==
"400000000");
948 jv = wsc->invoke(
"unsubscribe", books);
949 if (wsc->version() == 2)
951 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
952 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
953 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
955 BEAST_EXPECT(jv[jss::status] ==
"success");
1137 using namespace jtx;
1141 env.
fund(
XRP(10000), alice, gw);
1143 auto USD = gw[
"USD"];
1147 jvParams[jss::ledger_index] = 10u;
1148 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1149 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1150 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1155 jvParams[jss::ledger_index] =
"validated";
1156 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1157 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1158 BEAST_EXPECT(jrr[jss::error_message] ==
"Missing field 'taker_pays'.");
1163 jvParams[jss::ledger_index] =
"validated";
1165 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1166 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1167 BEAST_EXPECT(jrr[jss::error_message] ==
"Missing field 'taker_gets'.");
1172 jvParams[jss::ledger_index] =
"validated";
1173 jvParams[jss::taker_pays] =
"not an object";
1175 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1176 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1177 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker_pays', not object.");
1182 jvParams[jss::ledger_index] =
"validated";
1184 jvParams[jss::taker_gets] =
"not an object";
1185 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1186 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1187 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker_gets', not object.");
1192 jvParams[jss::ledger_index] =
"validated";
1195 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1196 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1197 BEAST_EXPECT(jrr[jss::error_message] ==
"Missing field 'taker_pays.currency'.");
1202 jvParams[jss::ledger_index] =
"validated";
1203 jvParams[jss::taker_pays][jss::currency] = 1;
1205 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1206 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1207 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker_pays.currency', not string.");
1212 jvParams[jss::ledger_index] =
"validated";
1213 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1215 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1216 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1217 BEAST_EXPECT(jrr[jss::error_message] ==
"Missing field 'taker_gets.currency'.");
1222 jvParams[jss::ledger_index] =
"validated";
1223 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1224 jvParams[jss::taker_gets][jss::currency] = 1;
1225 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1226 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1227 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker_gets.currency', not string.");
1232 jvParams[jss::ledger_index] =
"validated";
1233 jvParams[jss::taker_pays][jss::currency] =
"NOT_VALID";
1234 jvParams[jss::taker_gets][jss::currency] =
"XRP";
1235 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1236 BEAST_EXPECT(jrr[jss::error] ==
"srcCurMalformed");
1237 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker_pays.currency', bad currency.");
1242 jvParams[jss::ledger_index] =
"validated";
1243 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1244 jvParams[jss::taker_gets][jss::currency] =
"NOT_VALID";
1245 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1246 BEAST_EXPECT(jrr[jss::error] ==
"dstAmtMalformed");
1247 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker_gets.currency', bad currency.");
1252 jvParams[jss::ledger_index] =
"validated";
1253 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1254 jvParams[jss::taker_gets][jss::currency] =
"USD";
1255 jvParams[jss::taker_gets][jss::issuer] = 1;
1256 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1257 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1258 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker_gets.issuer', not string.");
1263 jvParams[jss::ledger_index] =
"validated";
1264 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1265 jvParams[jss::taker_pays][jss::issuer] = 1;
1266 jvParams[jss::taker_gets][jss::currency] =
"USD";
1267 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1268 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1269 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker_pays.issuer', not string.");
1274 jvParams[jss::ledger_index] =
"validated";
1275 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1276 jvParams[jss::taker_pays][jss::issuer] = gw.human() +
"DEAD";
1277 jvParams[jss::taker_gets][jss::currency] =
"USD";
1278 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1279 BEAST_EXPECT(jrr[jss::error] ==
"srcIsrMalformed");
1280 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker_pays.issuer', bad issuer.");
1285 jvParams[jss::ledger_index] =
"validated";
1286 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1288 jvParams[jss::taker_gets][jss::currency] =
"USD";
1289 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1290 BEAST_EXPECT(jrr[jss::error] ==
"srcIsrMalformed");
1291 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker_pays.issuer', bad issuer account one.");
1296 jvParams[jss::ledger_index] =
"validated";
1297 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1298 jvParams[jss::taker_gets][jss::currency] =
"USD";
1299 jvParams[jss::taker_gets][jss::issuer] = gw.human() +
"DEAD";
1300 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1301 BEAST_EXPECT(jrr[jss::error] ==
"dstIsrMalformed");
1302 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker_gets.issuer', bad issuer.");
1307 jvParams[jss::ledger_index] =
"validated";
1308 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1309 jvParams[jss::taker_gets][jss::currency] =
"USD";
1311 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1312 BEAST_EXPECT(jrr[jss::error] ==
"dstIsrMalformed");
1313 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker_gets.issuer', bad issuer account one.");
1318 jvParams[jss::ledger_index] =
"validated";
1319 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1320 jvParams[jss::taker_pays][jss::issuer] = alice.human();
1321 jvParams[jss::taker_gets][jss::currency] =
"USD";
1322 jvParams[jss::taker_gets][jss::issuer] = gw.human();
1323 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1324 BEAST_EXPECT(jrr[jss::error] ==
"srcIsrMalformed");
1326 jrr[jss::error_message] ==
1327 "Unneeded field 'taker_pays.issuer' "
1328 "for XRP currency specification.");
1333 jvParams[jss::ledger_index] =
"validated";
1334 jvParams[jss::taker_pays][jss::currency] =
"USD";
1336 jvParams[jss::taker_gets][jss::currency] =
"USD";
1337 jvParams[jss::taker_gets][jss::issuer] = gw.human();
1338 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1339 BEAST_EXPECT(jrr[jss::error] ==
"srcIsrMalformed");
1340 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker_pays.issuer', expected non-XRP issuer.");
1345 jvParams[jss::ledger_index] =
"validated";
1346 jvParams[jss::taker] = 1;
1347 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1348 jvParams[jss::taker_gets][jss::currency] =
"USD";
1349 jvParams[jss::taker_gets][jss::issuer] = gw.human();
1350 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1351 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1352 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker', not string.");
1357 jvParams[jss::ledger_index] =
"validated";
1358 jvParams[jss::taker] = env.
master.
human() +
"DEAD";
1359 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1360 jvParams[jss::taker_gets][jss::currency] =
"USD";
1361 jvParams[jss::taker_gets][jss::issuer] = gw.human();
1362 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1363 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1364 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker'.");
1369 jvParams[jss::ledger_index] =
"validated";
1371 jvParams[jss::taker_pays][jss::currency] =
"USD";
1372 jvParams[jss::taker_pays][jss::issuer] = gw.human();
1373 jvParams[jss::taker_gets][jss::currency] =
"USD";
1374 jvParams[jss::taker_gets][jss::issuer] = gw.human();
1375 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1376 BEAST_EXPECT(jrr[jss::error] ==
"badMarket");
1377 BEAST_EXPECT(jrr[jss::error_message] ==
"No such market.");
1382 jvParams[jss::ledger_index] =
"validated";
1384 jvParams[jss::limit] =
"0";
1385 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1386 jvParams[jss::taker_gets][jss::currency] =
"USD";
1387 jvParams[jss::taker_gets][jss::issuer] = gw.human();
1388 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1389 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1390 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'limit', not unsigned integer.");
1395 jvParams[jss::ledger_index] =
"validated";
1397 jvParams[jss::limit] = 0;
1398 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1399 jvParams[jss::taker_gets][jss::currency] =
"USD";
1400 jvParams[jss::taker_gets][jss::issuer] = gw.human();
1401 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1402 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1403 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'limit'.");
1408 jvParams[jss::ledger_index] =
"validated";
1409 jvParams[jss::taker_pays][jss::currency] =
"USD";
1410 jvParams[jss::taker_pays][jss::issuer] = gw.human();
1411 jvParams[jss::taker_gets][jss::currency] =
"USD";
1412 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1413 BEAST_EXPECT(jrr[jss::error] ==
"dstIsrMalformed");
1415 jrr[jss::error_message] ==
1416 "Invalid field 'taker_gets.issuer', "
1417 "expected non-XRP issuer.");
1422 jvParams[jss::ledger_index] =
"validated";
1423 jvParams[jss::taker_pays][jss::currency] =
"USD";
1424 jvParams[jss::taker_pays][jss::issuer] = gw.human();
1425 jvParams[jss::taker_gets][jss::currency] =
"XRP";
1426 jvParams[jss::taker_gets][jss::issuer] = gw.human();
1427 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1428 BEAST_EXPECT(jrr[jss::error] ==
"dstIsrMalformed");
1430 jrr[jss::error_message] ==
1431 "Unneeded field 'taker_gets.issuer' "
1432 "for XRP currency specification.");
1436 jvParams[jss::ledger_index] =
"validated";
1437 jvParams[jss::taker_pays][jss::currency] =
"USD";
1438 jvParams[jss::taker_pays][jss::issuer] = gw.human();
1439 jvParams[jss::taker_gets][jss::currency] =
"EUR";
1440 jvParams[jss::taker_gets][jss::issuer] = gw.human();
1441 jvParams[jss::domain] =
"badString";
1442 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1443 BEAST_EXPECT(jrr[jss::error] ==
"domainMalformed");
1444 BEAST_EXPECT(jrr[jss::error_message] ==
"Unable to parse domain.");
1494 using namespace jtx;
1501 auto const alice = permDex.
alice;
1502 auto const bob = permDex.
bob;
1503 auto const carol = permDex.
carol;
1504 auto const domainID = permDex.
domainID;
1505 auto const gw = permDex.
gw;
1506 auto const USD = permDex.
USD;
1513 auto checkBookOffers = [&](
Json::Value const& jrr) {
1514 BEAST_EXPECT(jrr[jss::offers].isArray());
1515 BEAST_EXPECT(jrr[jss::offers].size() == 1);
1516 auto const jrOffer = jrr[jss::offers][0u];
1517 BEAST_EXPECT(jrOffer[sfAccount.fieldName] == alice.human());
1518 BEAST_EXPECT(jrOffer[sfBookDirectory.fieldName] ==
getBookDir(env,
XRP, USD.issue(), domainID));
1519 BEAST_EXPECT(jrOffer[sfBookNode.fieldName] ==
"0");
1520 BEAST_EXPECT(jrOffer[jss::Flags] == 0);
1521 BEAST_EXPECT(jrOffer[sfLedgerEntryType.fieldName] == jss::Offer);
1522 BEAST_EXPECT(jrOffer[sfOwnerNode.fieldName] ==
"0");
1525 BEAST_EXPECT(jrOffer[sfDomainID.jsonName].asString() ==
to_string(domainID));
1532 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1533 jvParams[jss::ledger_index] =
"validated";
1534 jvParams[jss::taker_gets][jss::currency] =
"USD";
1535 jvParams[jss::taker_gets][jss::issuer] = gw.human();
1537 auto jv = wsc->invoke(
"book_offers", jvParams);
1538 auto jrr = jv[jss::result];
1539 BEAST_EXPECT(jrr[jss::offers].isArray());
1540 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1544 BEAST_EXPECT(jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 1);
1549 BEAST_EXPECT(jv[jss::result][jss::offers][0u][sfDomainID.jsonName].asString() ==
to_string(domainID));
1556 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1557 jvParams[jss::ledger_index] =
"validated";
1558 jvParams[jss::taker_gets][jss::currency] =
"USD";
1559 jvParams[jss::taker_gets][jss::issuer] = gw.human();
1560 jvParams[jss::domain] =
to_string(domainID);
1562 auto jv = wsc->invoke(
"book_offers", jvParams);
1563 auto jrr = jv[jss::result];
1564 checkBookOffers(jrr);
1573 j[jss::snapshot] =
true;
1574 j[jss::taker_pays][jss::currency] =
"XRP";
1575 j[jss::taker_gets][jss::currency] =
"USD";
1576 j[jss::taker_gets][jss::issuer] = gw.human();
1580 auto jv = wsc->invoke(
"subscribe", books);
1581 if (!BEAST_EXPECT(jv[jss::status] ==
"success"))
1592 j[jss::snapshot] =
true;
1593 j[jss::taker_pays][jss::currency] =
"XRP";
1594 j[jss::taker_gets][jss::currency] =
"USD";
1595 j[jss::taker_gets][jss::issuer] = gw.human();
1598 auto jv = wsc->invoke(
"subscribe", books);
1599 if (!BEAST_EXPECT(jv[jss::status] ==
"success"))
1601 BEAST_EXPECT(jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 0);
1609 using namespace jtx;
1616 auto const alice = permDex.
alice;
1617 auto const bob = permDex.
bob;
1618 auto const carol = permDex.
carol;
1619 auto const domainID = permDex.
domainID;
1620 auto const gw = permDex.
gw;
1621 auto const USD = permDex.
USD;
1628 auto checkBookOffers = [&](
Json::Value const& jrr) {
1629 BEAST_EXPECT(jrr[jss::offers].isArray());
1630 BEAST_EXPECT(jrr[jss::offers].size() == 1);
1631 auto const jrOffer = jrr[jss::offers][0u];
1632 BEAST_EXPECT(jrOffer[sfAccount.fieldName] == alice.human());
1633 BEAST_EXPECT(jrOffer[sfBookDirectory.fieldName] ==
getBookDir(env,
XRP, USD.issue(), domainID));
1634 BEAST_EXPECT(jrOffer[sfBookNode.fieldName] ==
"0");
1635 BEAST_EXPECT(jrOffer[jss::Flags] ==
lsfHybrid);
1636 BEAST_EXPECT(jrOffer[sfLedgerEntryType.fieldName] == jss::Offer);
1637 BEAST_EXPECT(jrOffer[sfOwnerNode.fieldName] ==
"0");
1640 BEAST_EXPECT(jrOffer[sfDomainID.jsonName].asString() ==
to_string(domainID));
1641 BEAST_EXPECT(jrOffer[sfAdditionalBooks.jsonName].size() == 1);
1648 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1649 jvParams[jss::ledger_index] =
"validated";
1650 jvParams[jss::taker_gets][jss::currency] =
"USD";
1651 jvParams[jss::taker_gets][jss::issuer] = gw.human();
1653 auto jv = wsc->invoke(
"book_offers", jvParams);
1654 auto jrr = jv[jss::result];
1655 checkBookOffers(jrr);
1659 BEAST_EXPECT(jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 1);
1664 BEAST_EXPECT(jv[jss::result][jss::offers][0u][sfDomainID.jsonName].asString() ==
to_string(domainID));
1671 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1672 jvParams[jss::ledger_index] =
"validated";
1673 jvParams[jss::taker_gets][jss::currency] =
"USD";
1674 jvParams[jss::taker_gets][jss::issuer] = gw.human();
1675 jvParams[jss::domain] =
to_string(domainID);
1677 auto jv = wsc->invoke(
"book_offers", jvParams);
1678 auto jrr = jv[jss::result];
1679 checkBookOffers(jrr);
1688 j[jss::snapshot] =
true;
1689 j[jss::taker_pays][jss::currency] =
"XRP";
1690 j[jss::taker_gets][jss::currency] =
"USD";
1691 j[jss::taker_gets][jss::issuer] = gw.human();
1695 auto jv = wsc->invoke(
"subscribe", books);
1696 if (!BEAST_EXPECT(jv[jss::status] ==
"success"))
1701 auto unsubJv = wsc->invoke(
"unsubscribe", books);
1702 if (wsc->version() == 2)
1703 BEAST_EXPECT(unsubJv[jss::status] ==
"success");
1712 j[jss::snapshot] =
true;
1713 j[jss::taker_pays][jss::currency] =
"XRP";
1714 j[jss::taker_gets][jss::currency] =
"USD";
1715 j[jss::taker_gets][jss::issuer] = gw.human();
1718 auto jv = wsc->invoke(
"subscribe", books);
1719 if (!BEAST_EXPECT(jv[jss::status] ==
"success"))