20 #include <ripple/protocol/Feature.h>
21 #include <ripple/protocol/jss.h>
24 #include <ripple/resource/Charge.h>
25 #include <ripple/resource/Fees.h>
26 #include <ripple/rpc/GRPCHandlers.h>
27 #include <test/jtx/WSClient.h>
28 #include <test/rpc/GRPCTestClientBase.h>
43 auto const info = env.
rpc(
"json",
"account_info",
"{ }");
45 info[jss::result][jss::error_message] ==
46 "Missing field 'account'.");
50 auto const info = env.
rpc(
54 "\"n94JNrQYkDrpt62bbSR7nVEhdyAvcJXRAsjEkFYyqRkh9SUTYEqV\"}");
58 info[jss::result][jss::error_message] ==
"Account malformed.");
63 auto const info = env.
rpc(
66 R
"({ "account": ")" + bogie.human() + R"("})");
70 info[jss::result][jss::error_message] == "Account not found.");
75 env.
rpc(
"json",
"account_info", R
"({"account": "foo"})");
79 info[jss::result][jss::error_message] == "Account malformed.");
90 env.fund(XRP(1000), alice);
92 auto const withoutSigners =
93 std::string(
"{ ") +
"\"account\": \"" + alice.human() +
"\"}";
95 auto const withSigners =
std::string(
"{ ") +
"\"account\": \"" +
96 alice.human() +
"\", " +
"\"signer_lists\": true }";
101 auto const info = env.rpc(
"json",
"account_info", withoutSigners);
103 info.isMember(jss::result) &&
104 info[jss::result].isMember(jss::account_data));
105 BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
110 auto const info = env.rpc(
"json",
"account_info", withSigners);
112 info.isMember(jss::result) &&
113 info[jss::result].isMember(jss::account_data));
114 auto const& data = info[jss::result][jss::account_data];
115 BEAST_EXPECT(data.isMember(jss::signer_lists));
116 auto const& signerLists = data[jss::signer_lists];
117 BEAST_EXPECT(signerLists.isArray());
118 BEAST_EXPECT(signerLists.size() == 0);
122 Account
const bogie{
"bogie"};
128 auto const info = env.rpc(
"json",
"account_info", withoutSigners);
130 info.isMember(jss::result) &&
131 info[jss::result].isMember(jss::account_data));
132 BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
137 auto const info = env.rpc(
"json",
"account_info", withSigners);
139 info.isMember(jss::result) &&
140 info[jss::result].isMember(jss::account_data));
141 auto const&
data = info[jss::result][jss::account_data];
142 BEAST_EXPECT(
data.isMember(jss::signer_lists));
143 auto const& signerLists =
data[jss::signer_lists];
144 BEAST_EXPECT(signerLists.isArray());
145 BEAST_EXPECT(signerLists.size() == 1);
146 auto const&
signers = signerLists[0u];
147 BEAST_EXPECT(
signers.isObject());
150 BEAST_EXPECT(signerEntries.size() == 1);
156 Account
const demon{
"demon"};
157 Account
const ghost{
"ghost"};
158 Account
const haunt{
"haunt"};
159 Account
const jinni{
"jinni"};
160 Account
const phase{
"phase"};
161 Account
const shade{
"shade"};
162 Account
const spook{
"spook"};
180 auto const info = env.rpc(
"json",
"account_info", withSigners);
182 info.isMember(jss::result) &&
183 info[jss::result].isMember(jss::account_data));
184 auto const&
data = info[jss::result][jss::account_data];
185 BEAST_EXPECT(
data.isMember(jss::signer_lists));
186 auto const& signerLists =
data[jss::signer_lists];
187 BEAST_EXPECT(signerLists.isArray());
188 BEAST_EXPECT(signerLists.size() == 1);
189 auto const&
signers = signerLists[0u];
190 BEAST_EXPECT(
signers.isObject());
193 BEAST_EXPECT(signerEntries.size() == 8);
194 for (
unsigned i = 0u; i < 8; ++i)
197 BEAST_EXPECT(entry.size() == 2);
206 testSignerListsApiVersion2()
210 c->loadFromString(
"\n[beta_rpc_api]\n1\n");
213 Account
const alice{
"alice"};
214 env.fund(
XRP(1000), alice);
217 "\"api_version\": 2, \"account\": \"" + alice.human() +
"\"}";
220 "\"api_version\": 2, \"account\": \"" + alice.human() +
"\", " +
221 "\"signer_lists\": true }";
226 auto const info = env.rpc(
"json",
"account_info", withoutSigners);
227 BEAST_EXPECT(info.isMember(jss::result));
228 BEAST_EXPECT(!info[jss::result].isMember(jss::signer_lists));
232 auto const info = env.rpc(
"json",
"account_info", withSigners);
233 BEAST_EXPECT(info.isMember(jss::result));
234 auto const&
data = info[jss::result];
235 BEAST_EXPECT(
data.isMember(jss::signer_lists));
236 auto const& signerLists =
data[jss::signer_lists];
237 BEAST_EXPECT(signerLists.isArray());
238 BEAST_EXPECT(signerLists.size() == 0);
242 Account
const bogie{
"bogie"};
248 auto const info = env.rpc(
"json",
"account_info", withoutSigners);
249 BEAST_EXPECT(info.isMember(jss::result));
250 BEAST_EXPECT(!info[jss::result].isMember(jss::signer_lists));
254 auto const info = env.rpc(
"json",
"account_info", withSigners);
255 BEAST_EXPECT(info.isMember(jss::result));
256 auto const&
data = info[jss::result];
257 BEAST_EXPECT(
data.isMember(jss::signer_lists));
258 auto const& signerLists =
data[jss::signer_lists];
259 BEAST_EXPECT(signerLists.isArray());
260 BEAST_EXPECT(signerLists.size() == 1);
261 auto const&
signers = signerLists[0u];
262 BEAST_EXPECT(
signers.isObject());
265 BEAST_EXPECT(signerEntries.size() == 1);
271 Account
const demon{
"demon"};
272 Account
const ghost{
"ghost"};
273 Account
const haunt{
"haunt"};
274 Account
const jinni{
"jinni"};
275 Account
const phase{
"phase"};
276 Account
const shade{
"shade"};
277 Account
const spook{
"spook"};
295 auto const info = env.rpc(
"json",
"account_info", withSigners);
296 BEAST_EXPECT(info.isMember(jss::result));
297 auto const&
data = info[jss::result];
298 BEAST_EXPECT(
data.isMember(jss::signer_lists));
299 auto const& signerLists =
data[jss::signer_lists];
300 BEAST_EXPECT(signerLists.isArray());
301 BEAST_EXPECT(signerLists.size() == 1);
302 auto const&
signers = signerLists[0u];
303 BEAST_EXPECT(
signers.isObject());
306 BEAST_EXPECT(signerEntries.size() == 8);
307 for (
unsigned i = 0u; i < 8; ++i)
310 BEAST_EXPECT(entry.size() == 2);
323 Account
const alice{
"alice"};
324 env.fund(
XRP(1000), alice);
327 "\"jsonrpc\": \"2.0\", "
328 "\"ripplerpc\": \"2.0\", "
330 "\"method\": \"account_info\", "
333 alice.human() +
"\"}}";
336 "\"jsonrpc\": \"2.0\", "
337 "\"ripplerpc\": \"2.0\", "
339 "\"method\": \"account_info\", "
342 alice.human() +
"\", " +
"\"signer_lists\": true }}";
346 auto const info = env.rpc(
"json2", withoutSigners);
348 info.isMember(jss::result) &&
349 info[jss::result].isMember(jss::account_data));
350 BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
353 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] ==
"2.0");
355 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] ==
"2.0");
356 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
360 auto const info = env.rpc(
"json2", withSigners);
362 info.isMember(jss::result) &&
363 info[jss::result].isMember(jss::account_data));
364 auto const&
data = info[jss::result][jss::account_data];
365 BEAST_EXPECT(
data.isMember(jss::signer_lists));
366 auto const& signerLists =
data[jss::signer_lists];
367 BEAST_EXPECT(signerLists.isArray());
368 BEAST_EXPECT(signerLists.size() == 0);
370 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] ==
"2.0");
372 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] ==
"2.0");
373 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
377 auto const info = env.rpc(
378 "json2",
'[' + withoutSigners +
", " + withSigners +
']');
380 info[0u].isMember(jss::result) &&
381 info[0u][jss::result].isMember(jss::account_data));
382 BEAST_EXPECT(!info[0u][jss::result][jss::account_data].isMember(
385 info[0u].isMember(jss::jsonrpc) &&
386 info[0u][jss::jsonrpc] ==
"2.0");
388 info[0u].isMember(jss::ripplerpc) &&
389 info[0u][jss::ripplerpc] ==
"2.0");
390 BEAST_EXPECT(info[0u].isMember(jss::id) && info[0u][jss::id] == 5);
393 info[1u].isMember(jss::result) &&
394 info[1u][jss::result].isMember(jss::account_data));
395 auto const&
data = info[1u][jss::result][jss::account_data];
396 BEAST_EXPECT(
data.isMember(jss::signer_lists));
397 auto const& signerLists =
data[jss::signer_lists];
398 BEAST_EXPECT(signerLists.isArray());
399 BEAST_EXPECT(signerLists.size() == 0);
401 info[1u].isMember(jss::jsonrpc) &&
402 info[1u][jss::jsonrpc] ==
"2.0");
404 info[1u].isMember(jss::ripplerpc) &&
405 info[1u][jss::ripplerpc] ==
"2.0");
406 BEAST_EXPECT(info[1u].isMember(jss::id) && info[1u][jss::id] == 6);
410 Account
const bogie{
"bogie"};
416 auto const info = env.rpc(
"json2", withoutSigners);
418 info.isMember(jss::result) &&
419 info[jss::result].isMember(jss::account_data));
420 BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
423 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] ==
"2.0");
425 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] ==
"2.0");
426 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
430 auto const info = env.rpc(
"json2", withSigners);
432 info.isMember(jss::result) &&
433 info[jss::result].isMember(jss::account_data));
434 auto const&
data = info[jss::result][jss::account_data];
435 BEAST_EXPECT(
data.isMember(jss::signer_lists));
436 auto const& signerLists =
data[jss::signer_lists];
437 BEAST_EXPECT(signerLists.isArray());
438 BEAST_EXPECT(signerLists.size() == 1);
439 auto const&
signers = signerLists[0u];
440 BEAST_EXPECT(
signers.isObject());
443 BEAST_EXPECT(signerEntries.size() == 1);
447 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] ==
"2.0");
449 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] ==
"2.0");
450 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
454 Account
const demon{
"demon"};
455 Account
const ghost{
"ghost"};
456 Account
const haunt{
"haunt"};
457 Account
const jinni{
"jinni"};
458 Account
const phase{
"phase"};
459 Account
const shade{
"shade"};
460 Account
const spook{
"spook"};
478 auto const info = env.rpc(
"json2", withSigners);
480 info.isMember(jss::result) &&
481 info[jss::result].isMember(jss::account_data));
482 auto const&
data = info[jss::result][jss::account_data];
483 BEAST_EXPECT(
data.isMember(jss::signer_lists));
484 auto const& signerLists =
data[jss::signer_lists];
485 BEAST_EXPECT(signerLists.isArray());
486 BEAST_EXPECT(signerLists.size() == 1);
487 auto const&
signers = signerLists[0u];
488 BEAST_EXPECT(
signers.isObject());
491 BEAST_EXPECT(signerEntries.size() == 8);
492 for (
unsigned i = 0u; i < 8; ++i)
495 BEAST_EXPECT(entry.size() == 2);
500 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] ==
"2.0");
502 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] ==
"2.0");
503 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
508 testAccountFlags(FeatureBitset
const& features)
512 Env env(*
this, features);
513 Account
const alice{
"alice"};
514 env.fund(
XRP(1000), alice);
517 auto const info = env.rpc(
520 R
"({"account" : ")" + alice.human() + R"("})");
523 if (info[jss::result][jss::status] ==
"success" &&
524 info[jss::result][jss::account_flags].isMember(fName.data()))
525 res.
emplace(info[jss::result][jss::account_flags][fName.data()]
531 static constexpr std::
532 array<std::pair<std::string_view, std::uint32_t>, 7>
542 for (
auto& asf : asFlags)
546 env(
fclear(alice, asf.second));
548 auto const f1 = getAccountFlag(asf.first);
549 BEAST_EXPECT(f1.has_value());
550 BEAST_EXPECT(!f1.value());
554 env(
fset(alice, asf.second));
556 auto const f2 = getAccountFlag(asf.first);
557 BEAST_EXPECT(f2.has_value());
558 BEAST_EXPECT(f2.value());
561 static constexpr std::
562 array<std::pair<std::string_view, std::uint32_t>, 4>
563 disallowIncomingFlags{
565 {
"disallowIncomingNFTokenOffer",
568 {
"disallowIncomingTrustline",
573 for (
auto& asf : disallowIncomingFlags)
577 env(
fclear(alice, asf.second));
579 auto const f1 = getAccountFlag(asf.first);
580 BEAST_EXPECT(f1.has_value());
581 BEAST_EXPECT(!f1.value());
585 env(
fset(alice, asf.second));
587 auto const f2 = getAccountFlag(asf.first);
588 BEAST_EXPECT(f2.has_value());
589 BEAST_EXPECT(f2.value());
594 for (
auto& asf : disallowIncomingFlags)
596 BEAST_EXPECT(!getAccountFlag(asf.first));
606 testSignerListsApiVersion2();
609 FeatureBitset
const allFeatures{
611 testAccountFlags(allFeatures);