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