499 testcase(
"Multiple Books, One Side Offers In Book");
500 using namespace std::chrono_literals;
504 auto usd =
Account(
"alice")[
"USD"];
505 auto cny =
Account(
"alice")[
"CNY"];
506 auto jpy =
Account(
"alice")[
"JPY"];
528 j[jss::snapshot] =
true;
529 j[jss::taker_gets][jss::currency] =
"XRP";
530 j[jss::taker_pays][jss::currency] =
"USD";
531 j[jss::taker_pays][jss::issuer] =
Account(
"alice").human();
535 j[jss::snapshot] =
true;
536 j[jss::taker_gets][jss::currency] =
"CNY";
537 j[jss::taker_gets][jss::issuer] =
Account(
"alice").human();
538 j[jss::taker_pays][jss::currency] =
"JPY";
539 j[jss::taker_pays][jss::issuer] =
Account(
"alice").human();
542 auto jv = wsc->invoke(
"subscribe", books);
543 if (wsc->version() == 2)
545 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
546 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
547 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
549 if (!BEAST_EXPECT(jv[jss::status] ==
"success"))
552 jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 2);
554 jv[jss::result][jss::offers][0u][jss::TakerGets] ==
557 jv[jss::result][jss::offers][0u][jss::TakerPays] ==
560 jv[jss::result][jss::offers][1u][jss::TakerGets] ==
563 jv[jss::result][jss::offers][1u][jss::TakerPays] ==
565 BEAST_EXPECT(!jv[jss::result].isMember(jss::asks));
566 BEAST_EXPECT(!jv[jss::result].isMember(jss::bids));
575 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
576 auto const& t = jv[jss::transaction];
577 return t[jss::TransactionType] == jss::OfferCreate &&
578 t[jss::TakerGets] == usd(100).value().getJson(JsonOptions::Values::None) &&
579 t[jss::TakerPays] == XRP(700).value().getJson(JsonOptions::Values::None);
587 BEAST_EXPECT(!wsc->getMsg(10ms));
596 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
597 auto const& t = jv[jss::transaction];
598 return t[jss::TransactionType] == jss::OfferCreate &&
599 t[jss::TakerGets] == jpy(100).value().getJson(JsonOptions::Values::None) &&
600 t[jss::TakerPays] == cny(700).value().getJson(JsonOptions::Values::None);
608 BEAST_EXPECT(!wsc->getMsg(10ms));
612 auto jv = wsc->invoke(
"unsubscribe", books);
613 BEAST_EXPECT(jv[jss::status] ==
"success");
614 if (wsc->version() == 2)
616 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
617 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
618 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
625 testcase(
"Multiple Books, Both Sides Empty Book");
626 using namespace std::chrono_literals;
630 auto usd =
Account(
"alice")[
"USD"];
631 auto cny =
Account(
"alice")[
"CNY"];
632 auto jpy =
Account(
"alice")[
"JPY"];
641 j[jss::snapshot] =
true;
643 j[jss::taker_gets][jss::currency] =
"XRP";
644 j[jss::taker_pays][jss::currency] =
"USD";
645 j[jss::taker_pays][jss::issuer] =
Account(
"alice").human();
649 j[jss::snapshot] =
true;
651 j[jss::taker_gets][jss::currency] =
"CNY";
652 j[jss::taker_gets][jss::issuer] =
Account(
"alice").human();
653 j[jss::taker_pays][jss::currency] =
"JPY";
654 j[jss::taker_pays][jss::issuer] =
Account(
"alice").human();
657 auto jv = wsc->invoke(
"subscribe", books);
658 if (wsc->version() == 2)
660 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
661 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
662 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
664 if (!BEAST_EXPECT(jv[jss::status] ==
"success"))
667 jv[jss::result].isMember(jss::asks) && jv[jss::result][jss::asks].size() == 0);
669 jv[jss::result].isMember(jss::bids) && jv[jss::result][jss::bids].size() == 0);
670 BEAST_EXPECT(!jv[jss::result].isMember(jss::offers));
679 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
680 auto const& t = jv[jss::transaction];
681 return t[jss::TransactionType] == jss::OfferCreate &&
682 t[jss::TakerGets] == usd(100).value().getJson(JsonOptions::Values::None) &&
683 t[jss::TakerPays] == XRP(700).value().getJson(JsonOptions::Values::None);
693 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
694 auto const& t = jv[jss::transaction];
695 return t[jss::TransactionType] == jss::OfferCreate &&
696 t[jss::TakerGets] == XRP(75).value().getJson(JsonOptions::Values::None) &&
697 t[jss::TakerPays] == usd(100).value().getJson(JsonOptions::Values::None);
707 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
708 auto const& t = jv[jss::transaction];
709 return t[jss::TransactionType] == jss::OfferCreate &&
710 t[jss::TakerGets] == jpy(100).value().getJson(JsonOptions::Values::None) &&
711 t[jss::TakerPays] == cny(700).value().getJson(JsonOptions::Values::None);
721 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
722 auto const& t = jv[jss::transaction];
723 return t[jss::TransactionType] == jss::OfferCreate &&
724 t[jss::TakerGets] == cny(75).value().getJson(JsonOptions::Values::None) &&
725 t[jss::TakerPays] == jpy(100).value().getJson(JsonOptions::Values::None);
730 auto jv = wsc->invoke(
"unsubscribe", books);
731 BEAST_EXPECT(jv[jss::status] ==
"success");
732 if (wsc->version() == 2)
734 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
735 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
736 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
743 testcase(
"Multiple Books, Both Sides Offers In Book");
744 using namespace std::chrono_literals;
748 auto usd =
Account(
"alice")[
"USD"];
749 auto cny =
Account(
"alice")[
"CNY"];
750 auto jpy =
Account(
"alice")[
"JPY"];
772 j[jss::snapshot] =
true;
774 j[jss::taker_gets][jss::currency] =
"XRP";
775 j[jss::taker_pays][jss::currency] =
"USD";
776 j[jss::taker_pays][jss::issuer] =
Account(
"alice").human();
781 j[jss::snapshot] =
true;
783 j[jss::taker_gets][jss::currency] =
"CNY";
784 j[jss::taker_gets][jss::issuer] =
Account(
"alice").human();
785 j[jss::taker_pays][jss::currency] =
"JPY";
786 j[jss::taker_pays][jss::issuer] =
Account(
"alice").human();
789 auto jv = wsc->invoke(
"subscribe", books);
790 if (wsc->version() == 2)
792 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
793 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
794 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
796 if (!BEAST_EXPECT(jv[jss::status] ==
"success"))
799 jv[jss::result].isMember(jss::asks) && jv[jss::result][jss::asks].size() == 2);
801 jv[jss::result].isMember(jss::bids) && jv[jss::result][jss::bids].size() == 2);
803 jv[jss::result][jss::asks][0u][jss::TakerGets] ==
806 jv[jss::result][jss::asks][0u][jss::TakerPays] ==
809 jv[jss::result][jss::asks][1u][jss::TakerGets] ==
812 jv[jss::result][jss::asks][1u][jss::TakerPays] ==
815 jv[jss::result][jss::bids][0u][jss::TakerGets] ==
818 jv[jss::result][jss::bids][0u][jss::TakerPays] ==
821 jv[jss::result][jss::bids][1u][jss::TakerGets] ==
824 jv[jss::result][jss::bids][1u][jss::TakerPays] ==
826 BEAST_EXPECT(!jv[jss::result].isMember(jss::offers));
835 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
836 auto const& t = jv[jss::transaction];
837 return t[jss::TransactionType] == jss::OfferCreate &&
838 t[jss::TakerGets] == usd(100).value().getJson(JsonOptions::Values::None) &&
839 t[jss::TakerPays] == XRP(700).value().getJson(JsonOptions::Values::None);
849 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
850 auto const& t = jv[jss::transaction];
851 return t[jss::TransactionType] == jss::OfferCreate &&
852 t[jss::TakerGets] == XRP(75).value().getJson(JsonOptions::Values::None) &&
853 t[jss::TakerPays] == usd(100).value().getJson(JsonOptions::Values::None);
863 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
864 auto const& t = jv[jss::transaction];
865 return t[jss::TransactionType] == jss::OfferCreate &&
866 t[jss::TakerGets] == jpy(100).value().getJson(JsonOptions::Values::None) &&
867 t[jss::TakerPays] == cny(700).value().getJson(JsonOptions::Values::None);
877 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jv) {
878 auto const& t = jv[jss::transaction];
879 return t[jss::TransactionType] == jss::OfferCreate &&
880 t[jss::TakerGets] == cny(75).value().getJson(JsonOptions::Values::None) &&
881 t[jss::TakerPays] == jpy(100).value().getJson(JsonOptions::Values::None);
886 auto jv = wsc->invoke(
"unsubscribe", books);
887 BEAST_EXPECT(jv[jss::status] ==
"success");
888 if (wsc->version() == 2)
890 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
891 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
892 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
906 env.
fund(
XRP(20000), alice, bob, gw);
908 auto usd = gw[
"USD"];
915 j[jss::snapshot] =
true;
916 j[jss::taker_gets][jss::currency] =
"XRP";
917 j[jss::taker_pays][jss::currency] =
"USD";
918 j[jss::taker_pays][jss::issuer] = gw.
human();
921 auto jv = wsc->invoke(
"subscribe", books);
922 if (wsc->version() == 2)
924 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
925 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
926 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
928 if (!BEAST_EXPECT(jv[jss::status] ==
"success"))
931 jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 0);
932 BEAST_EXPECT(!jv[jss::result].isMember(jss::asks));
933 BEAST_EXPECT(!jv[jss::result].isMember(jss::bids));
938 env.
trust(usd(1000), alice);
939 env.
trust(usd(1000), bob);
940 env(
pay(gw, alice, usd(100)));
941 env(
pay(gw, bob, usd(50)));
942 env(
offer(alice,
XRP(4000), usd(10)));
947 jvParams[jss::taker_pays][jss::currency] =
"XRP";
948 jvParams[jss::ledger_index] =
"validated";
949 jvParams[jss::taker_gets][jss::currency] =
"USD";
950 jvParams[jss::taker_gets][jss::issuer] = gw.
human();
952 auto jv = wsc->invoke(
"book_offers", jvParams);
953 if (wsc->version() == 2)
955 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
956 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
957 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
959 auto jrr = jv[jss::result];
961 BEAST_EXPECT(jrr[jss::offers].isArray());
962 BEAST_EXPECT(jrr[jss::offers].size() == 1);
963 auto const jrOffer = jrr[jss::offers][0u];
964 BEAST_EXPECT(jrOffer[sfAccount.fieldName] == alice.
human());
965 BEAST_EXPECT(jrOffer[sfBookDirectory.fieldName] ==
getBookDir(env,
XRP, usd));
966 BEAST_EXPECT(jrOffer[sfBookNode.fieldName] ==
"0");
967 BEAST_EXPECT(jrOffer[jss::Flags] == 0);
968 BEAST_EXPECT(jrOffer[sfLedgerEntryType.fieldName] == jss::Offer);
969 BEAST_EXPECT(jrOffer[sfOwnerNode.fieldName] ==
"0");
970 BEAST_EXPECT(jrOffer[sfSequence.fieldName] == 5);
974 BEAST_EXPECT(jrOffer[jss::owner_funds] ==
"100");
975 BEAST_EXPECT(jrOffer[jss::quality] ==
"400000000");
977 using namespace std::chrono_literals;
978 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jval) {
979 auto const& t = jval[jss::transaction];
980 return t[jss::TransactionType] == jss::OfferCreate &&
981 t[jss::TakerGets] == usd(10).value().getJson(JsonOptions::Values::None) &&
982 t[jss::owner_funds] ==
"100" &&
983 t[jss::TakerPays] == XRP(4000).value().getJson(JsonOptions::Values::None);
989 BEAST_EXPECT(wsc->findMsg(5s, [&](
auto const& jval) {
990 auto const& t = jval[jss::transaction];
991 return t[jss::TransactionType] == jss::OfferCreate &&
992 t[jss::TakerGets] == usd(5).value().getJson(JsonOptions::Values::None) &&
993 t[jss::owner_funds] ==
"50" &&
994 t[jss::TakerPays] == XRP(2000).value().getJson(JsonOptions::Values::None);
997 jv = wsc->invoke(
"book_offers", jvParams);
998 if (wsc->version() == 2)
1000 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
1001 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
1002 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
1004 jrr = jv[jss::result];
1006 BEAST_EXPECT(jrr[jss::offers].isArray());
1007 BEAST_EXPECT(jrr[jss::offers].size() == 2);
1008 auto const jrNextOffer = jrr[jss::offers][1u];
1009 BEAST_EXPECT(jrNextOffer[sfAccount.fieldName] == bob.
human());
1010 BEAST_EXPECT(jrNextOffer[sfBookDirectory.fieldName] ==
getBookDir(env,
XRP, usd));
1011 BEAST_EXPECT(jrNextOffer[sfBookNode.fieldName] ==
"0");
1012 BEAST_EXPECT(jrNextOffer[jss::Flags] == 0);
1013 BEAST_EXPECT(jrNextOffer[sfLedgerEntryType.fieldName] == jss::Offer);
1014 BEAST_EXPECT(jrNextOffer[sfOwnerNode.fieldName] ==
"0");
1015 BEAST_EXPECT(jrNextOffer[sfSequence.fieldName] == 5);
1020 BEAST_EXPECT(jrNextOffer[jss::owner_funds] ==
"50");
1021 BEAST_EXPECT(jrNextOffer[jss::quality] ==
"400000000");
1023 jv = wsc->invoke(
"unsubscribe", books);
1024 if (wsc->version() == 2)
1026 BEAST_EXPECT(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] ==
"2.0");
1027 BEAST_EXPECT(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] ==
"2.0");
1028 BEAST_EXPECT(jv.isMember(jss::id) && jv[jss::id] == 5);
1030 BEAST_EXPECT(jv[jss::status] ==
"success");
1212 using namespace jtx;
1216 env.
fund(
XRP(10000), alice, gw);
1218 auto usd = gw[
"USD"];
1222 jvParams[jss::ledger_index] = 10u;
1223 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1224 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1225 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1230 jvParams[jss::ledger_index] =
"validated";
1231 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1232 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1233 BEAST_EXPECT(jrr[jss::error_message] ==
"Missing field 'taker_pays'.");
1238 jvParams[jss::ledger_index] =
"validated";
1240 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1241 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1242 BEAST_EXPECT(jrr[jss::error_message] ==
"Missing field 'taker_gets'.");
1247 jvParams[jss::ledger_index] =
"validated";
1248 jvParams[jss::taker_pays] =
"not an object";
1250 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1251 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1252 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker_pays', not object.");
1257 jvParams[jss::ledger_index] =
"validated";
1259 jvParams[jss::taker_gets] =
"not an object";
1260 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1261 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1262 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker_gets', not object.");
1267 jvParams[jss::ledger_index] =
"validated";
1270 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1271 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1272 BEAST_EXPECT(jrr[jss::error_message] ==
"Missing field 'taker_pays.currency'.");
1277 jvParams[jss::ledger_index] =
"validated";
1278 jvParams[jss::taker_pays][jss::currency] = 1;
1280 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1281 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1283 jrr[jss::error_message] ==
"Invalid field 'taker_pays.currency', not string.");
1288 jvParams[jss::ledger_index] =
"validated";
1289 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1291 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1292 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1293 BEAST_EXPECT(jrr[jss::error_message] ==
"Missing field 'taker_gets.currency'.");
1298 jvParams[jss::ledger_index] =
"validated";
1299 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1300 jvParams[jss::taker_gets][jss::currency] = 1;
1301 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1302 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1304 jrr[jss::error_message] ==
"Invalid field 'taker_gets.currency', not string.");
1309 jvParams[jss::ledger_index] =
"validated";
1310 jvParams[jss::taker_pays][jss::currency] =
"NOT_VALID";
1311 jvParams[jss::taker_gets][jss::currency] =
"XRP";
1312 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1313 BEAST_EXPECT(jrr[jss::error] ==
"srcCurMalformed");
1315 jrr[jss::error_message] ==
"Invalid field 'taker_pays.currency', bad currency.");
1320 jvParams[jss::ledger_index] =
"validated";
1321 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1322 jvParams[jss::taker_gets][jss::currency] =
"NOT_VALID";
1323 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1324 BEAST_EXPECT(jrr[jss::error] ==
"dstAmtMalformed");
1326 jrr[jss::error_message] ==
"Invalid field 'taker_gets.currency', bad currency.");
1331 jvParams[jss::ledger_index] =
"validated";
1332 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1333 jvParams[jss::taker_gets][jss::currency] =
"USD";
1334 jvParams[jss::taker_gets][jss::issuer] = 1;
1335 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1336 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1338 jrr[jss::error_message] ==
"Invalid field 'taker_gets.issuer', not string.");
1343 jvParams[jss::ledger_index] =
"validated";
1344 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1345 jvParams[jss::taker_pays][jss::issuer] = 1;
1346 jvParams[jss::taker_gets][jss::currency] =
"USD";
1347 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1348 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1350 jrr[jss::error_message] ==
"Invalid field 'taker_pays.issuer', not string.");
1355 jvParams[jss::ledger_index] =
"validated";
1356 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1357 jvParams[jss::taker_pays][jss::issuer] = gw.
human() +
"DEAD";
1358 jvParams[jss::taker_gets][jss::currency] =
"USD";
1359 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1360 BEAST_EXPECT(jrr[jss::error] ==
"srcIsrMalformed");
1362 jrr[jss::error_message] ==
"Invalid field 'taker_pays.issuer', bad issuer.");
1367 jvParams[jss::ledger_index] =
"validated";
1368 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1370 jvParams[jss::taker_gets][jss::currency] =
"USD";
1371 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1372 BEAST_EXPECT(jrr[jss::error] ==
"srcIsrMalformed");
1374 jrr[jss::error_message] ==
1375 "Invalid field 'taker_pays.issuer', bad issuer account one.");
1380 jvParams[jss::ledger_index] =
"validated";
1381 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1382 jvParams[jss::taker_gets][jss::currency] =
"USD";
1383 jvParams[jss::taker_gets][jss::issuer] = gw.
human() +
"DEAD";
1384 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1385 BEAST_EXPECT(jrr[jss::error] ==
"dstIsrMalformed");
1387 jrr[jss::error_message] ==
"Invalid field 'taker_gets.issuer', bad issuer.");
1392 jvParams[jss::ledger_index] =
"validated";
1393 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1394 jvParams[jss::taker_gets][jss::currency] =
"USD";
1396 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1397 BEAST_EXPECT(jrr[jss::error] ==
"dstIsrMalformed");
1399 jrr[jss::error_message] ==
1400 "Invalid field 'taker_gets.issuer', bad issuer account one.");
1405 jvParams[jss::ledger_index] =
"validated";
1406 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1407 jvParams[jss::taker_pays][jss::issuer] = alice.
human();
1408 jvParams[jss::taker_gets][jss::currency] =
"USD";
1409 jvParams[jss::taker_gets][jss::issuer] = gw.
human();
1410 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1411 BEAST_EXPECT(jrr[jss::error] ==
"srcIsrMalformed");
1413 jrr[jss::error_message] ==
1414 "Unneeded field 'taker_pays.issuer' "
1415 "for XRP currency specification.");
1420 jvParams[jss::ledger_index] =
"validated";
1421 jvParams[jss::taker_pays][jss::currency] =
"USD";
1423 jvParams[jss::taker_gets][jss::currency] =
"USD";
1424 jvParams[jss::taker_gets][jss::issuer] = gw.
human();
1425 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1426 BEAST_EXPECT(jrr[jss::error] ==
"srcIsrMalformed");
1428 jrr[jss::error_message] ==
1429 "Invalid field 'taker_pays.issuer', expected non-XRP issuer.");
1434 jvParams[jss::ledger_index] =
"validated";
1435 jvParams[jss::taker] = 1;
1436 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1437 jvParams[jss::taker_gets][jss::currency] =
"USD";
1438 jvParams[jss::taker_gets][jss::issuer] = gw.
human();
1439 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1440 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1441 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker', not string.");
1446 jvParams[jss::ledger_index] =
"validated";
1447 jvParams[jss::taker] = env.
master.
human() +
"DEAD";
1448 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1449 jvParams[jss::taker_gets][jss::currency] =
"USD";
1450 jvParams[jss::taker_gets][jss::issuer] = gw.
human();
1451 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1452 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1453 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'taker'.");
1458 jvParams[jss::ledger_index] =
"validated";
1460 jvParams[jss::taker_pays][jss::currency] =
"USD";
1461 jvParams[jss::taker_pays][jss::issuer] = gw.
human();
1462 jvParams[jss::taker_gets][jss::currency] =
"USD";
1463 jvParams[jss::taker_gets][jss::issuer] = gw.
human();
1464 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1465 BEAST_EXPECT(jrr[jss::error] ==
"badMarket");
1466 BEAST_EXPECT(jrr[jss::error_message] ==
"No such market.");
1471 jvParams[jss::ledger_index] =
"validated";
1473 jvParams[jss::limit] =
"0";
1474 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1475 jvParams[jss::taker_gets][jss::currency] =
"USD";
1476 jvParams[jss::taker_gets][jss::issuer] = gw.
human();
1477 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1478 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1479 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'limit', not unsigned integer.");
1484 jvParams[jss::ledger_index] =
"validated";
1486 jvParams[jss::limit] = 0;
1487 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1488 jvParams[jss::taker_gets][jss::currency] =
"USD";
1489 jvParams[jss::taker_gets][jss::issuer] = gw.
human();
1490 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1491 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1492 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'limit'.");
1497 jvParams[jss::ledger_index] =
"validated";
1498 jvParams[jss::taker_pays][jss::currency] =
"USD";
1499 jvParams[jss::taker_pays][jss::issuer] = gw.
human();
1500 jvParams[jss::taker_gets][jss::currency] =
"USD";
1501 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1502 BEAST_EXPECT(jrr[jss::error] ==
"dstIsrMalformed");
1504 jrr[jss::error_message] ==
1505 "Invalid field 'taker_gets.issuer', "
1506 "expected non-XRP issuer.");
1511 jvParams[jss::ledger_index] =
"validated";
1512 jvParams[jss::taker_pays][jss::currency] =
"USD";
1513 jvParams[jss::taker_pays][jss::issuer] = gw.
human();
1514 jvParams[jss::taker_gets][jss::currency] =
"XRP";
1515 jvParams[jss::taker_gets][jss::issuer] = gw.
human();
1516 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1517 BEAST_EXPECT(jrr[jss::error] ==
"dstIsrMalformed");
1519 jrr[jss::error_message] ==
1520 "Unneeded field 'taker_gets.issuer' "
1521 "for XRP currency specification.");
1525 jvParams[jss::ledger_index] =
"validated";
1526 jvParams[jss::taker_pays][jss::currency] =
"USD";
1527 jvParams[jss::taker_pays][jss::issuer] = gw.
human();
1528 jvParams[jss::taker_gets][jss::currency] =
"EUR";
1529 jvParams[jss::taker_gets][jss::issuer] = gw.
human();
1530 jvParams[jss::domain] =
"badString";
1531 auto const jrr = env.
rpc(
"json",
"book_offers",
to_string(jvParams))[jss::result];
1532 BEAST_EXPECT(jrr[jss::error] ==
"domainMalformed");
1533 BEAST_EXPECT(jrr[jss::error_message] ==
"Unable to parse domain.");
1583 using namespace jtx;
1587 featurePermissionedDEX};
1589 Env env(*
this, all);
1591 auto const alice = permDex.
alice;
1592 auto const bob = permDex.
bob;
1593 auto const carol = permDex.
carol;
1594 auto const domainID = permDex.
domainID;
1595 auto const gw = permDex.
gw;
1596 auto const usd = permDex.
usd;
1603 auto checkBookOffers = [&](
json::Value const& jrr) {
1604 BEAST_EXPECT(jrr[jss::offers].isArray());
1605 BEAST_EXPECT(jrr[jss::offers].size() == 1);
1606 auto const jrOffer = jrr[jss::offers][0u];
1607 BEAST_EXPECT(jrOffer[sfAccount.fieldName] == alice.human());
1609 jrOffer[sfBookDirectory.fieldName] ==
getBookDir(env,
XRP, usd.issue(), domainID));
1610 BEAST_EXPECT(jrOffer[sfBookNode.fieldName] ==
"0");
1611 BEAST_EXPECT(jrOffer[jss::Flags] == 0);
1612 BEAST_EXPECT(jrOffer[sfLedgerEntryType.fieldName] == jss::Offer);
1613 BEAST_EXPECT(jrOffer[sfOwnerNode.fieldName] ==
"0");
1618 BEAST_EXPECT(jrOffer[sfDomainID.jsonName].asString() ==
to_string(domainID));
1625 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1626 jvParams[jss::ledger_index] =
"validated";
1627 jvParams[jss::taker_gets][jss::currency] =
"USD";
1628 jvParams[jss::taker_gets][jss::issuer] = gw.human();
1630 auto jv = wsc->invoke(
"book_offers", jvParams);
1631 auto jrr = jv[jss::result];
1632 BEAST_EXPECT(jrr[jss::offers].isArray());
1633 BEAST_EXPECT(jrr[jss::offers].size() == 0);
1638 jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 1);
1640 jv[jss::result][jss::offers][0u][jss::TakerGets] ==
1643 jv[jss::result][jss::offers][0u][jss::TakerPays] ==
1646 jv[jss::result][jss::offers][0u][sfDomainID.jsonName].asString() ==
1654 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1655 jvParams[jss::ledger_index] =
"validated";
1656 jvParams[jss::taker_gets][jss::currency] =
"USD";
1657 jvParams[jss::taker_gets][jss::issuer] = gw.human();
1658 jvParams[jss::domain] =
to_string(domainID);
1660 auto jv = wsc->invoke(
"book_offers", jvParams);
1661 auto jrr = jv[jss::result];
1662 checkBookOffers(jrr);
1671 j[jss::snapshot] =
true;
1672 j[jss::taker_pays][jss::currency] =
"XRP";
1673 j[jss::taker_gets][jss::currency] =
"USD";
1674 j[jss::taker_gets][jss::issuer] = gw.human();
1678 auto jv = wsc->invoke(
"subscribe", books);
1679 if (!BEAST_EXPECT(jv[jss::status] ==
"success"))
1690 j[jss::snapshot] =
true;
1691 j[jss::taker_pays][jss::currency] =
"XRP";
1692 j[jss::taker_gets][jss::currency] =
"USD";
1693 j[jss::taker_gets][jss::issuer] = gw.human();
1696 auto jv = wsc->invoke(
"subscribe", books);
1697 if (!BEAST_EXPECT(jv[jss::status] ==
"success"))
1700 jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 0);
1708 using namespace jtx;
1712 featurePermissionedDEX};
1714 Env env(*
this, all);
1716 auto const alice = permDex.
alice;
1717 auto const bob = permDex.
bob;
1718 auto const carol = permDex.
carol;
1719 auto const domainID = permDex.
domainID;
1720 auto const gw = permDex.
gw;
1721 auto const usd = permDex.
usd;
1728 auto checkBookOffers = [&](
json::Value const& jrr) {
1729 BEAST_EXPECT(jrr[jss::offers].isArray());
1730 BEAST_EXPECT(jrr[jss::offers].size() == 1);
1731 auto const jrOffer = jrr[jss::offers][0u];
1732 BEAST_EXPECT(jrOffer[sfAccount.fieldName] == alice.human());
1734 jrOffer[sfBookDirectory.fieldName] ==
getBookDir(env,
XRP, usd.issue(), domainID));
1735 BEAST_EXPECT(jrOffer[sfBookNode.fieldName] ==
"0");
1736 BEAST_EXPECT(jrOffer[jss::Flags] == lsfHybrid);
1737 BEAST_EXPECT(jrOffer[sfLedgerEntryType.fieldName] == jss::Offer);
1738 BEAST_EXPECT(jrOffer[sfOwnerNode.fieldName] ==
"0");
1743 BEAST_EXPECT(jrOffer[sfDomainID.jsonName].asString() ==
to_string(domainID));
1744 BEAST_EXPECT(jrOffer[sfAdditionalBooks.jsonName].size() == 1);
1751 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1752 jvParams[jss::ledger_index] =
"validated";
1753 jvParams[jss::taker_gets][jss::currency] =
"USD";
1754 jvParams[jss::taker_gets][jss::issuer] = gw.human();
1756 auto jv = wsc->invoke(
"book_offers", jvParams);
1757 auto jrr = jv[jss::result];
1758 checkBookOffers(jrr);
1763 jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 1);
1765 jv[jss::result][jss::offers][0u][jss::TakerGets] ==
1768 jv[jss::result][jss::offers][0u][jss::TakerPays] ==
1771 jv[jss::result][jss::offers][0u][sfDomainID.jsonName].asString() ==
1779 jvParams[jss::taker_pays][jss::currency] =
"XRP";
1780 jvParams[jss::ledger_index] =
"validated";
1781 jvParams[jss::taker_gets][jss::currency] =
"USD";
1782 jvParams[jss::taker_gets][jss::issuer] = gw.human();
1783 jvParams[jss::domain] =
to_string(domainID);
1785 auto jv = wsc->invoke(
"book_offers", jvParams);
1786 auto jrr = jv[jss::result];
1787 checkBookOffers(jrr);
1796 j[jss::snapshot] =
true;
1797 j[jss::taker_pays][jss::currency] =
"XRP";
1798 j[jss::taker_gets][jss::currency] =
"USD";
1799 j[jss::taker_gets][jss::issuer] = gw.human();
1803 auto jv = wsc->invoke(
"subscribe", books);
1804 if (!BEAST_EXPECT(jv[jss::status] ==
"success"))
1809 auto unsubJv = wsc->invoke(
"unsubscribe", books);
1810 if (wsc->version() == 2)
1811 BEAST_EXPECT(unsubJv[jss::status] ==
"success");
1820 j[jss::snapshot] =
true;
1821 j[jss::taker_pays][jss::currency] =
"XRP";
1822 j[jss::taker_gets][jss::currency] =
"USD";
1823 j[jss::taker_gets][jss::issuer] = gw.human();
1826 auto jv = wsc->invoke(
"subscribe", books);
1827 if (!BEAST_EXPECT(jv[jss::status] ==
"success"))