rippled
Loading...
Searching...
No Matches
AccountInfo_test.cpp
1#include <test/jtx.h>
2#include <test/jtx/WSClient.h>
3#include <test/rpc/GRPCTestClientBase.h>
4
5#include <xrpl/protocol/Feature.h>
6#include <xrpl/protocol/jss.h>
7
8namespace ripple {
9namespace test {
10
12{
13public:
14 void
16 {
17 testcase("Errors");
18 using namespace jtx;
19 Env env(*this);
20 {
21 // account_info with no account.
22 auto const info = env.rpc("json", "account_info", "{ }");
23 BEAST_EXPECT(
24 info[jss::result][jss::error_message] ==
25 "Missing field 'account'.");
26 }
27 {
28 // account_info with a malformed account string.
29 auto const info = env.rpc(
30 "json",
31 "account_info",
32 "{\"account\": "
33 "\"n94JNrQYkDrpt62bbSR7nVEhdyAvcJXRAsjEkFYyqRkh9SUTYEqV\"}");
34 BEAST_EXPECT(
35 info[jss::result][jss::error_code] == rpcACT_MALFORMED);
36 BEAST_EXPECT(
37 info[jss::result][jss::error_message] == "Account malformed.");
38 }
39 {
40 // account_info with an account that's not in the ledger.
41 Account const bogie{"bogie"};
42 Json::Value params;
43 params[jss::account] = bogie.human();
44 auto const info =
45 env.rpc("json", "account_info", to_string(params));
46 BEAST_EXPECT(
47 info[jss::result][jss::error_code] == rpcACT_NOT_FOUND);
48 BEAST_EXPECT(
49 info[jss::result][jss::error_message] == "Account not found.");
50 }
51 {
52 // Cannot use a seed as account
53 auto const info =
54 env.rpc("json", "account_info", R"({"account": "foo"})");
55 BEAST_EXPECT(
56 info[jss::result][jss::error_code] == rpcACT_MALFORMED);
57 BEAST_EXPECT(
58 info[jss::result][jss::error_message] == "Account malformed.");
59 }
60 {
61 // Cannot pass a non-string into the `account` param
62
63 auto testInvalidAccountParam = [&](auto const& param) {
64 Json::Value params;
65 params[jss::account] = param;
66 auto jrr = env.rpc(
67 "json", "account_info", to_string(params))[jss::result];
68 BEAST_EXPECT(jrr[jss::error] == "invalidParams");
69 BEAST_EXPECT(
70 jrr[jss::error_message] == "Invalid field 'account'.");
71 };
72
73 testInvalidAccountParam(1);
74 testInvalidAccountParam(1.1);
75 testInvalidAccountParam(true);
76 testInvalidAccountParam(Json::Value(Json::nullValue));
77 testInvalidAccountParam(Json::Value(Json::objectValue));
78 testInvalidAccountParam(Json::Value(Json::arrayValue));
79 }
80 {
81 // Cannot pass a non-string into the `ident` param
82
83 auto testInvalidIdentParam = [&](auto const& param) {
84 Json::Value params;
85 params[jss::ident] = param;
86 auto jrr = env.rpc(
87 "json", "account_info", to_string(params))[jss::result];
88 BEAST_EXPECT(jrr[jss::error] == "invalidParams");
89 BEAST_EXPECT(
90 jrr[jss::error_message] == "Invalid field 'ident'.");
91 };
92
93 testInvalidIdentParam(1);
94 testInvalidIdentParam(1.1);
95 testInvalidIdentParam(true);
96 testInvalidIdentParam(Json::Value(Json::nullValue));
97 testInvalidIdentParam(Json::Value(Json::objectValue));
98 testInvalidIdentParam(Json::Value(Json::arrayValue));
99 }
100 }
101
102 // Test the "signer_lists" argument in account_info.
103 void
105 {
106 testcase("Signer lists");
107 using namespace jtx;
108 Env env(*this);
109 Account const alice{"alice"};
110 env.fund(XRP(1000), alice);
111
112 Json::Value withoutSigners;
113 withoutSigners[jss::account] = alice.human();
114
115 Json::Value withSigners;
116 withSigners[jss::account] = alice.human();
117 withSigners[jss::signer_lists] = true;
118
119 // Alice has no SignerList yet.
120 {
121 // account_info without the "signer_lists" argument.
122 auto const info =
123 env.rpc("json", "account_info", to_string(withoutSigners));
124 BEAST_EXPECT(
125 info.isMember(jss::result) &&
126 info[jss::result].isMember(jss::account_data));
127 BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
128 jss::signer_lists));
129 }
130 {
131 // account_info with the "signer_lists" argument.
132 auto const info =
133 env.rpc("json", "account_info", to_string(withSigners));
134 BEAST_EXPECT(
135 info.isMember(jss::result) &&
136 info[jss::result].isMember(jss::account_data));
137 auto const& data = info[jss::result][jss::account_data];
138 BEAST_EXPECT(data.isMember(jss::signer_lists));
139 auto const& signerLists = data[jss::signer_lists];
140 BEAST_EXPECT(signerLists.isArray());
141 BEAST_EXPECT(signerLists.size() == 0);
142 }
143
144 // Give alice a SignerList.
145 Account const bogie{"bogie"};
146
147 Json::Value const smallSigners = signers(alice, 2, {{bogie, 3}});
148 env(smallSigners);
149 {
150 // account_info without the "signer_lists" argument.
151 auto const info =
152 env.rpc("json", "account_info", to_string(withoutSigners));
153 BEAST_EXPECT(
154 info.isMember(jss::result) &&
155 info[jss::result].isMember(jss::account_data));
156 BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
157 jss::signer_lists));
158 }
159 {
160 // account_info with the "signer_lists" argument.
161 auto const info =
162 env.rpc("json", "account_info", to_string(withSigners));
163 BEAST_EXPECT(
164 info.isMember(jss::result) &&
165 info[jss::result].isMember(jss::account_data));
166 auto const& data = info[jss::result][jss::account_data];
167 BEAST_EXPECT(data.isMember(jss::signer_lists));
168 auto const& signerLists = data[jss::signer_lists];
169 BEAST_EXPECT(signerLists.isArray());
170 BEAST_EXPECT(signerLists.size() == 1);
171 auto const& signers = signerLists[0u];
172 BEAST_EXPECT(signers.isObject());
173 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 2);
174 auto const& signerEntries = signers[sfSignerEntries.jsonName];
175 BEAST_EXPECT(signerEntries.size() == 1);
176 auto const& entry0 = signerEntries[0u][sfSignerEntry.jsonName];
177 BEAST_EXPECT(entry0[sfSignerWeight.jsonName] == 3);
178 }
179
180 // Give alice a big signer list
181 Account const demon{"demon"};
182 Account const ghost{"ghost"};
183 Account const haunt{"haunt"};
184 Account const jinni{"jinni"};
185 Account const phase{"phase"};
186 Account const shade{"shade"};
187 Account const spook{"spook"};
188
189 Json::Value const bigSigners = signers(
190 alice,
191 4,
192 {
193 {bogie, 1},
194 {demon, 1},
195 {ghost, 1},
196 {haunt, 1},
197 {jinni, 1},
198 {phase, 1},
199 {shade, 1},
200 {spook, 1},
201 });
202 env(bigSigners);
203 {
204 // account_info with the "signer_lists" argument.
205 auto const info =
206 env.rpc("json", "account_info", to_string(withSigners));
207 BEAST_EXPECT(
208 info.isMember(jss::result) &&
209 info[jss::result].isMember(jss::account_data));
210 auto const& data = info[jss::result][jss::account_data];
211 BEAST_EXPECT(data.isMember(jss::signer_lists));
212 auto const& signerLists = data[jss::signer_lists];
213 BEAST_EXPECT(signerLists.isArray());
214 BEAST_EXPECT(signerLists.size() == 1);
215 auto const& signers = signerLists[0u];
216 BEAST_EXPECT(signers.isObject());
217 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 4);
218 auto const& signerEntries = signers[sfSignerEntries.jsonName];
219 BEAST_EXPECT(signerEntries.size() == 8);
220 for (unsigned i = 0u; i < 8; ++i)
221 {
222 auto const& entry = signerEntries[i][sfSignerEntry.jsonName];
223 BEAST_EXPECT(entry.size() == 2);
224 BEAST_EXPECT(entry.isMember(sfAccount.jsonName));
225 BEAST_EXPECT(entry[sfSignerWeight.jsonName] == 1);
226 }
227 }
228 }
229
230 // Test the "signer_lists" argument in account_info, with api_version 2.
231 void
233 {
234 testcase("Signer lists APIv2");
235 using namespace jtx;
236 Env env{*this};
237 Account const alice{"alice"};
238 env.fund(XRP(1000), alice);
239
240 Json::Value withoutSigners;
241 withoutSigners[jss::api_version] = 2;
242 withoutSigners[jss::account] = alice.human();
243
244 Json::Value withSigners;
245 withSigners[jss::api_version] = 2;
246 withSigners[jss::account] = alice.human();
247 withSigners[jss::signer_lists] = true;
248
249 auto const withSignersAsString = std::string("{ ") +
250 "\"api_version\": 2, \"account\": \"" + alice.human() + "\", " +
251 "\"signer_lists\": asdfggh }";
252
253 // Alice has no SignerList yet.
254 {
255 // account_info without the "signer_lists" argument.
256 auto const info =
257 env.rpc("json", "account_info", to_string(withoutSigners));
258 BEAST_EXPECT(info.isMember(jss::result));
259 BEAST_EXPECT(!info[jss::result].isMember(jss::signer_lists));
260 }
261 {
262 // account_info with the "signer_lists" argument.
263 auto const info =
264 env.rpc("json", "account_info", to_string(withSigners));
265 BEAST_EXPECT(info.isMember(jss::result));
266 auto const& data = info[jss::result];
267 BEAST_EXPECT(data.isMember(jss::signer_lists));
268 auto const& signerLists = data[jss::signer_lists];
269 BEAST_EXPECT(signerLists.isArray());
270 BEAST_EXPECT(signerLists.size() == 0);
271 }
272
273 // Give alice a SignerList.
274 Account const bogie{"bogie"};
275
276 Json::Value const smallSigners = signers(alice, 2, {{bogie, 3}});
277 env(smallSigners);
278 {
279 // account_info without the "signer_lists" argument.
280 auto const info =
281 env.rpc("json", "account_info", to_string(withoutSigners));
282 BEAST_EXPECT(info.isMember(jss::result));
283 BEAST_EXPECT(!info[jss::result].isMember(jss::signer_lists));
284 }
285 {
286 // account_info with the "signer_lists" argument.
287 auto const info =
288 env.rpc("json", "account_info", to_string(withSigners));
289 BEAST_EXPECT(info.isMember(jss::result));
290 auto const& data = info[jss::result];
291 BEAST_EXPECT(data.isMember(jss::signer_lists));
292 auto const& signerLists = data[jss::signer_lists];
293 BEAST_EXPECT(signerLists.isArray());
294 BEAST_EXPECT(signerLists.size() == 1);
295 auto const& signers = signerLists[0u];
296 BEAST_EXPECT(signers.isObject());
297 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 2);
298 auto const& signerEntries = signers[sfSignerEntries.jsonName];
299 BEAST_EXPECT(signerEntries.size() == 1);
300 auto const& entry0 = signerEntries[0u][sfSignerEntry.jsonName];
301 BEAST_EXPECT(entry0[sfSignerWeight.jsonName] == 3);
302 }
303 {
304 // account_info with "signer_lists" as not bool should error out
305 auto const info =
306 env.rpc("json", "account_info", withSignersAsString);
307 BEAST_EXPECT(info[jss::status] == "error");
308 BEAST_EXPECT(info[jss::error] == "invalidParams");
309 }
310
311 // Give alice a big signer list
312 Account const demon{"demon"};
313 Account const ghost{"ghost"};
314 Account const haunt{"haunt"};
315 Account const jinni{"jinni"};
316 Account const phase{"phase"};
317 Account const shade{"shade"};
318 Account const spook{"spook"};
319
320 Json::Value const bigSigners = signers(
321 alice,
322 4,
323 {
324 {bogie, 1},
325 {demon, 1},
326 {ghost, 1},
327 {haunt, 1},
328 {jinni, 1},
329 {phase, 1},
330 {shade, 1},
331 {spook, 1},
332 });
333 env(bigSigners);
334 {
335 // account_info with the "signer_lists" argument.
336 auto const info =
337 env.rpc("json", "account_info", to_string(withSigners));
338 BEAST_EXPECT(info.isMember(jss::result));
339 auto const& data = info[jss::result];
340 BEAST_EXPECT(data.isMember(jss::signer_lists));
341 auto const& signerLists = data[jss::signer_lists];
342 BEAST_EXPECT(signerLists.isArray());
343 BEAST_EXPECT(signerLists.size() == 1);
344 auto const& signers = signerLists[0u];
345 BEAST_EXPECT(signers.isObject());
346 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 4);
347 auto const& signerEntries = signers[sfSignerEntries.jsonName];
348 BEAST_EXPECT(signerEntries.size() == 8);
349 for (unsigned i = 0u; i < 8; ++i)
350 {
351 auto const& entry = signerEntries[i][sfSignerEntry.jsonName];
352 BEAST_EXPECT(entry.size() == 2);
353 BEAST_EXPECT(entry.isMember(sfAccount.jsonName));
354 BEAST_EXPECT(entry[sfSignerWeight.jsonName] == 1);
355 }
356 }
357 }
358
359 // Test the "signer_lists" argument in account_info, version 2 API.
360 void
362 {
363 testcase("Signer lists v2");
364 using namespace jtx;
365 Env env(*this);
366 Account const alice{"alice"};
367 env.fund(XRP(1000), alice);
368
369 auto const withoutSigners = std::string("{ ") +
370 "\"jsonrpc\": \"2.0\", "
371 "\"ripplerpc\": \"2.0\", "
372 "\"id\": 5, "
373 "\"method\": \"account_info\", "
374 "\"params\": { "
375 "\"account\": \"" +
376 alice.human() + "\"}}";
377
378 auto const withSigners = std::string("{ ") +
379 "\"jsonrpc\": \"2.0\", "
380 "\"ripplerpc\": \"2.0\", "
381 "\"id\": 6, "
382 "\"method\": \"account_info\", "
383 "\"params\": { "
384 "\"account\": \"" +
385 alice.human() + "\", " + "\"signer_lists\": true }}";
386 // Alice has no SignerList yet.
387 {
388 // account_info without the "signer_lists" argument.
389 auto const info = env.rpc("json2", withoutSigners);
390 BEAST_EXPECT(
391 info.isMember(jss::result) &&
392 info[jss::result].isMember(jss::account_data));
393 BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
394 jss::signer_lists));
395 BEAST_EXPECT(
396 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
397 BEAST_EXPECT(
398 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
399 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
400 }
401 {
402 // account_info with the "signer_lists" argument.
403 auto const info = env.rpc("json2", withSigners);
404 BEAST_EXPECT(
405 info.isMember(jss::result) &&
406 info[jss::result].isMember(jss::account_data));
407 auto const& data = info[jss::result][jss::account_data];
408 BEAST_EXPECT(data.isMember(jss::signer_lists));
409 auto const& signerLists = data[jss::signer_lists];
410 BEAST_EXPECT(signerLists.isArray());
411 BEAST_EXPECT(signerLists.size() == 0);
412 BEAST_EXPECT(
413 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
414 BEAST_EXPECT(
415 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
416 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
417 }
418 {
419 // Do both of the above as a batch job
420 auto const info = env.rpc(
421 "json2", '[' + withoutSigners + ", " + withSigners + ']');
422 BEAST_EXPECT(
423 info[0u].isMember(jss::result) &&
424 info[0u][jss::result].isMember(jss::account_data));
425 BEAST_EXPECT(!info[0u][jss::result][jss::account_data].isMember(
426 jss::signer_lists));
427 BEAST_EXPECT(
428 info[0u].isMember(jss::jsonrpc) &&
429 info[0u][jss::jsonrpc] == "2.0");
430 BEAST_EXPECT(
431 info[0u].isMember(jss::ripplerpc) &&
432 info[0u][jss::ripplerpc] == "2.0");
433 BEAST_EXPECT(info[0u].isMember(jss::id) && info[0u][jss::id] == 5);
434
435 BEAST_EXPECT(
436 info[1u].isMember(jss::result) &&
437 info[1u][jss::result].isMember(jss::account_data));
438 auto const& data = info[1u][jss::result][jss::account_data];
439 BEAST_EXPECT(data.isMember(jss::signer_lists));
440 auto const& signerLists = data[jss::signer_lists];
441 BEAST_EXPECT(signerLists.isArray());
442 BEAST_EXPECT(signerLists.size() == 0);
443 BEAST_EXPECT(
444 info[1u].isMember(jss::jsonrpc) &&
445 info[1u][jss::jsonrpc] == "2.0");
446 BEAST_EXPECT(
447 info[1u].isMember(jss::ripplerpc) &&
448 info[1u][jss::ripplerpc] == "2.0");
449 BEAST_EXPECT(info[1u].isMember(jss::id) && info[1u][jss::id] == 6);
450 }
451
452 // Give alice a SignerList.
453 Account const bogie{"bogie"};
454
455 Json::Value const smallSigners = signers(alice, 2, {{bogie, 3}});
456 env(smallSigners);
457 {
458 // account_info without the "signer_lists" argument.
459 auto const info = env.rpc("json2", withoutSigners);
460 BEAST_EXPECT(
461 info.isMember(jss::result) &&
462 info[jss::result].isMember(jss::account_data));
463 BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(
464 jss::signer_lists));
465 BEAST_EXPECT(
466 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
467 BEAST_EXPECT(
468 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
469 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5);
470 }
471 {
472 // account_info with the "signer_lists" argument.
473 auto const info = env.rpc("json2", withSigners);
474 BEAST_EXPECT(
475 info.isMember(jss::result) &&
476 info[jss::result].isMember(jss::account_data));
477 auto const& data = info[jss::result][jss::account_data];
478 BEAST_EXPECT(data.isMember(jss::signer_lists));
479 auto const& signerLists = data[jss::signer_lists];
480 BEAST_EXPECT(signerLists.isArray());
481 BEAST_EXPECT(signerLists.size() == 1);
482 auto const& signers = signerLists[0u];
483 BEAST_EXPECT(signers.isObject());
484 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 2);
485 auto const& signerEntries = signers[sfSignerEntries.jsonName];
486 BEAST_EXPECT(signerEntries.size() == 1);
487 auto const& entry0 = signerEntries[0u][sfSignerEntry.jsonName];
488 BEAST_EXPECT(entry0[sfSignerWeight.jsonName] == 3);
489 BEAST_EXPECT(
490 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
491 BEAST_EXPECT(
492 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
493 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
494 }
495
496 // Give alice a big signer list
497 Account const demon{"demon"};
498 Account const ghost{"ghost"};
499 Account const haunt{"haunt"};
500 Account const jinni{"jinni"};
501 Account const phase{"phase"};
502 Account const shade{"shade"};
503 Account const spook{"spook"};
504
505 Json::Value const bigSigners = signers(
506 alice,
507 4,
508 {
509 {bogie, 1},
510 {demon, 1},
511 {ghost, 1},
512 {haunt, 1},
513 {jinni, 1},
514 {phase, 1},
515 {shade, 1},
516 {spook, 1},
517 });
518 env(bigSigners);
519 {
520 // account_info with the "signer_lists" argument.
521 auto const info = env.rpc("json2", withSigners);
522 BEAST_EXPECT(
523 info.isMember(jss::result) &&
524 info[jss::result].isMember(jss::account_data));
525 auto const& data = info[jss::result][jss::account_data];
526 BEAST_EXPECT(data.isMember(jss::signer_lists));
527 auto const& signerLists = data[jss::signer_lists];
528 BEAST_EXPECT(signerLists.isArray());
529 BEAST_EXPECT(signerLists.size() == 1);
530 auto const& signers = signerLists[0u];
531 BEAST_EXPECT(signers.isObject());
532 BEAST_EXPECT(signers[sfSignerQuorum.jsonName] == 4);
533 auto const& signerEntries = signers[sfSignerEntries.jsonName];
534 BEAST_EXPECT(signerEntries.size() == 8);
535 for (unsigned i = 0u; i < 8; ++i)
536 {
537 auto const& entry = signerEntries[i][sfSignerEntry.jsonName];
538 BEAST_EXPECT(entry.size() == 2);
539 BEAST_EXPECT(entry.isMember(sfAccount.jsonName));
540 BEAST_EXPECT(entry[sfSignerWeight.jsonName] == 1);
541 }
542 BEAST_EXPECT(
543 info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0");
544 BEAST_EXPECT(
545 info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0");
546 BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6);
547 }
548 }
549
550 void
552 {
553 testcase("Account flags");
554 using namespace jtx;
555
556 Env env(*this, features);
557 Account const alice{"alice"};
558 Account const bob{"bob"};
559 env.fund(XRP(1000), alice, bob);
560
561 auto getAccountFlag = [&env](
562 std::string_view fName,
563 Account const& account) {
564 Json::Value params;
565 params[jss::account] = account.human();
566 auto const info =
567 env.rpc("json", "account_info", to_string(params));
568
570 if (info[jss::result][jss::status] == "success" &&
571 info[jss::result][jss::account_flags].isMember(fName.data()))
572 res.emplace(info[jss::result][jss::account_flags][fName.data()]
573 .asBool());
574
575 return res;
576 };
577
578 static constexpr std::
580 asFlags{
581 {{"defaultRipple", asfDefaultRipple},
582 {"depositAuth", asfDepositAuth},
583 {"disallowIncomingXRP", asfDisallowXRP},
584 {"globalFreeze", asfGlobalFreeze},
585 {"noFreeze", asfNoFreeze},
586 {"requireAuthorization", asfRequireAuth},
587 {"requireDestinationTag", asfRequireDest}}};
588
589 for (auto& asf : asFlags)
590 {
591 // Clear a flag and check that account_info returns results
592 // as expected
593 env(fclear(alice, asf.second));
594 env.close();
595 auto const f1 = getAccountFlag(asf.first, alice);
596 BEAST_EXPECT(f1.has_value());
597 BEAST_EXPECT(!f1.value());
598
599 // Set a flag and check that account_info returns results
600 // as expected
601 env(fset(alice, asf.second));
602 env.close();
603 auto const f2 = getAccountFlag(asf.first, alice);
604 BEAST_EXPECT(f2.has_value());
605 BEAST_EXPECT(f2.value());
606 }
607
608 static constexpr std::
610 disallowIncomingFlags{
611 {{"disallowIncomingCheck", asfDisallowIncomingCheck},
612 {"disallowIncomingNFTokenOffer",
614 {"disallowIncomingPayChan", asfDisallowIncomingPayChan},
615 {"disallowIncomingTrustline",
617
618 if (features[featureDisallowIncoming])
619 {
620 for (auto& asf : disallowIncomingFlags)
621 {
622 // Clear a flag and check that account_info returns results
623 // as expected
624 env(fclear(alice, asf.second));
625 env.close();
626 auto const f1 = getAccountFlag(asf.first, alice);
627 BEAST_EXPECT(f1.has_value());
628 BEAST_EXPECT(!f1.value());
629
630 // Set a flag and check that account_info returns results
631 // as expected
632 env(fset(alice, asf.second));
633 env.close();
634 auto const f2 = getAccountFlag(asf.first, alice);
635 BEAST_EXPECT(f2.has_value());
636 BEAST_EXPECT(f2.value());
637 }
638 }
639 else
640 {
641 for (auto& asf : disallowIncomingFlags)
642 {
643 BEAST_EXPECT(!getAccountFlag(asf.first, alice));
644 }
645 }
646
648 allowTrustLineClawbackFlag{
649 "allowTrustLineClawback", asfAllowTrustLineClawback};
650
651 if (features[featureClawback])
652 {
653 // must use bob's account because alice has noFreeze set
654 auto const f1 =
655 getAccountFlag(allowTrustLineClawbackFlag.first, bob);
656 BEAST_EXPECT(f1.has_value());
657 BEAST_EXPECT(!f1.value());
658
659 // Set allowTrustLineClawback
660 env(fset(bob, allowTrustLineClawbackFlag.second));
661 env.close();
662 auto const f2 =
663 getAccountFlag(allowTrustLineClawbackFlag.first, bob);
664 BEAST_EXPECT(f2.has_value());
665 BEAST_EXPECT(f2.value());
666 }
667 else
668 {
669 BEAST_EXPECT(
670 !getAccountFlag(allowTrustLineClawbackFlag.first, bob));
671 }
672
674 allowTrustLineLockingFlag{
675 "allowTrustLineLocking", asfAllowTrustLineLocking};
676
677 if (features[featureTokenEscrow])
678 {
679 auto const f1 =
680 getAccountFlag(allowTrustLineLockingFlag.first, bob);
681 BEAST_EXPECT(f1.has_value());
682 BEAST_EXPECT(!f1.value());
683
684 // Set allowTrustLineLocking
685 env(fset(bob, allowTrustLineLockingFlag.second));
686 env.close();
687 auto const f2 =
688 getAccountFlag(allowTrustLineLockingFlag.first, bob);
689 BEAST_EXPECT(f2.has_value());
690 BEAST_EXPECT(f2.value());
691 }
692 else
693 {
694 BEAST_EXPECT(!getAccountFlag(allowTrustLineLockingFlag.first, bob));
695 }
696 }
697
698 void
699 run() override
700 {
701 testErrors();
705
706 FeatureBitset const allFeatures{
708 testAccountFlags(allFeatures);
709 testAccountFlags(allFeatures - featureDisallowIncoming);
711 allFeatures - featureDisallowIncoming - featureClawback);
713 allFeatures - featureDisallowIncoming - featureClawback -
714 featureTokenEscrow);
715 }
716};
717
718BEAST_DEFINE_TESTSUITE(AccountInfo, rpc, ripple);
719
720} // namespace test
721} // namespace ripple
Represents a JSON value.
Definition json_value.h:130
UInt size() const
Number of values in array or object.
bool isObject() const
bool isMember(char const *key) const
Return true if the object has a member named key.
A testsuite class.
Definition suite.h:52
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:152
void run() override
Runs the suite.
void testAccountFlags(FeatureBitset const &features)
Immutable cryptographic account descriptor.
Definition Account.h:20
A transaction testing environment.
Definition Env.h:102
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:103
Json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition Env.h:772
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:271
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition rpc.h:16
T data(T... args)
T emplace(T... args)
T is_same_v
@ nullValue
'null' value
Definition json_value.h:19
@ arrayValue
array value (ordered list)
Definition json_value.h:25
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:26
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Definition flags.h:102
auto const data
General field definitions, or fields used in multiple transaction namespaces.
Json::Value signers(Account const &account, std::uint32_t quorum, std::vector< signer > const &v)
Definition multisign.cpp:15
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Definition flags.cpp:10
FeatureBitset testable_amendments()
Definition Env.h:55
XRP_t const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:92
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
constexpr std::uint32_t asfGlobalFreeze
Definition TxFlags.h:64
constexpr std::uint32_t asfDepositAuth
Definition TxFlags.h:66
constexpr std::uint32_t asfDisallowIncomingNFTokenOffer
Definition TxFlags.h:71
constexpr std::uint32_t asfAllowTrustLineLocking
Definition TxFlags.h:76
constexpr std::uint32_t asfRequireDest
Definition TxFlags.h:58
@ rpcACT_NOT_FOUND
Definition ErrorCodes.h:51
@ rpcACT_MALFORMED
Definition ErrorCodes.h:71
constexpr std::uint32_t asfNoFreeze
Definition TxFlags.h:63
constexpr std::uint32_t asfDisallowIncomingTrustline
Definition TxFlags.h:74
constexpr std::uint32_t asfDefaultRipple
Definition TxFlags.h:65
constexpr std::uint32_t asfDisallowIncomingCheck
Definition TxFlags.h:72
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
constexpr std::uint32_t asfDisallowIncomingPayChan
Definition TxFlags.h:73
constexpr std::uint32_t asfAllowTrustLineClawback
Definition TxFlags.h:75
constexpr std::uint32_t asfRequireAuth
Definition TxFlags.h:59
constexpr std::uint32_t asfDisallowXRP
Definition TxFlags.h:60