20 #include <ripple/json/json_reader.h>
21 #include <ripple/json/json_value.h>
22 #include <ripple/json/to_string.h>
23 #include <ripple/protocol/jss.h>
26 #include <boost/utility/string_ref.hpp>
35 "Account" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
36 "BookDirectory" : "50AD0A9E54D2B381288D535EB724E4275FFBF41580D28A925D038D7EA4C68000",
37 "BookNode" : "0000000000000000",
39 "LedgerEntryType" : "Offer",
40 "OwnerNode" : "0000000000000000",
44 "issuer" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
47 "TakerPays" : "100000000",
48 "index" : "29665262716C19830E26AEEC0916E476FC7D8EF195FF3B4F06829E64F82A3B3E"
53 "issuer" : "rrrrrrrrrrrrrrrrrrrrBZbvji",
59 "issuer" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
62 "HighNode" : "0000000000000000",
63 "LedgerEntryType" : "RippleState",
66 "issuer" : "r9cZvwKU3zzuZK9JFovGg1JC5n7QiqNL8L",
69 "LowNode" : "0000000000000000",
70 "index" : "D13183BCFFC9AAC9F96AEBB5F66E4A652AD1F5D10273AEB615478302BEBFD4A4"
75 "issuer" : "rrrrrrrrrrrrrrrrrrrrBZbvji",
81 "issuer" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
84 "HighNode" : "0000000000000000",
85 "LedgerEntryType" : "RippleState",
88 "issuer" : "r32rQHyesiTtdWFU7UJVtff4nCR5SHCbJW",
91 "LowNode" : "0000000000000000",
92 "index" : "D89BC239086183EB9458C396E643795C1134963E6550E682A190A5F021766D43"
95 "Account" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
96 "BookDirectory" : "B025997A323F5C3E03DDF1334471F5984ABDE31C59D463525D038D7EA4C68000",
97 "BookNode" : "0000000000000000",
99 "LedgerEntryType" : "Offer",
100 "OwnerNode" : "0000000000000000",
104 "issuer" : "r32rQHyesiTtdWFU7UJVtff4nCR5SHCbJW",
107 "TakerPays" : "100000000",
108 "index" : "F03ABE26CB8C5F4AFB31A86590BD25C64C5756FCE5CE9704C27AFE291A4A29A1"
117 testcase(
"error cases");
124 auto resp = env.
rpc(
"json",
"account_objects");
125 BEAST_EXPECT(resp[jss::error_message] ==
"Syntax error.");
130 params[jss::account] =
131 "n94JNrQYkDrpt62bbSR7nVEhdyAvcJXRAsjEkFYyqRkh9SUTYEqV";
132 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
134 resp[jss::result][jss::error_message] ==
"Disallowed seed.");
140 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
142 resp[jss::result][jss::error_message] ==
"Account not found.");
148 params[jss::account] = bob.human();
149 params[jss::ledger_index] = 10;
150 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
152 resp[jss::result][jss::error_message] ==
"ledgerNotFound");
159 params[jss::account] = bob.human();
160 params[jss::type] = 10;
161 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
163 resp[jss::result][jss::error_message] ==
164 "Invalid field 'type', not string.");
169 params[jss::account] = bob.human();
170 params[jss::type] =
"expedited";
171 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
173 resp[jss::result][jss::error_message] ==
174 "Invalid field 'type'.");
179 params[jss::account] = bob.human();
180 params[jss::limit] = -1;
181 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
183 resp[jss::result][jss::error_message] ==
184 "Invalid field 'limit', not unsigned integer.");
190 auto const USD = gw[
"USD"];
191 env.
trust(USD(1000), bob);
192 env(
pay(gw, bob,
XRP(1)));
196 params[jss::account] = bob.human();
197 params[jss::limit] = 1;
198 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
200 auto resume_marker = resp[jss::result][jss::marker];
202 params[jss::marker] = 10;
203 resp = env.
rpc(
"json",
"account_objects",
to_string(params));
205 resp[jss::result][jss::error_message] ==
206 "Invalid field 'marker', not string.");
208 params[jss::marker] =
"This is a string with no comma";
209 resp = env.
rpc(
"json",
"account_objects",
to_string(params));
211 resp[jss::result][jss::error_message] ==
212 "Invalid field 'marker'.");
214 params[jss::marker] =
"This string has a comma, but is not hex";
215 resp = env.
rpc(
"json",
"account_objects",
to_string(params));
217 resp[jss::result][jss::error_message] ==
218 "Invalid field 'marker'.");
221 resp = env.
rpc(
"json",
"account_objects",
to_string(params));
223 resp[jss::result][jss::error_message] ==
224 "Invalid field 'marker'.");
227 resp = env.
rpc(
"json",
"account_objects",
to_string(params));
229 resp[jss::result][jss::error_message] ==
230 "Invalid field 'marker'.");
232 params[jss::marker] =
std::string(&mark[1U], 65) +
"not hex";
233 resp = env.
rpc(
"json",
"account_objects",
to_string(params));
235 resp[jss::result][jss::error_message] ==
236 "Invalid field 'marker'.");
242 resp = env.
rpc(
"json",
"account_objects",
to_string(params));
243 BEAST_EXPECT(resp[jss::result][jss::account_objects].size() == 0);
250 testcase(
"unsteppedThenStepped");
259 auto const USD1 = gw1[
"USD"];
260 auto const USD2 = gw2[
"USD"];
262 env.
fund(
XRP(1000), gw1, gw2, bob);
263 env.
trust(USD1(1000), bob);
264 env.
trust(USD2(1000), bob);
266 env(
pay(gw1, bob, USD1(1000)));
267 env(
pay(gw2, bob, USD2(1000)));
273 for (
int i = 0; i < 4; ++i)
280 params[jss::account] = bob.human();
281 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
282 BEAST_EXPECT(!resp.isMember(jss::marker));
284 BEAST_EXPECT(resp[jss::result][jss::account_objects].size() == 4);
285 for (
int i = 0; i < 4; ++i)
287 auto& aobj = resp[jss::result][jss::account_objects][i];
288 aobj.removeMember(
"PreviousTxnID");
289 aobj.removeMember(
"PreviousTxnLgrSeq");
293 BEAST_EXPECT(aobj == bobj[i]);
299 params[jss::account] = bob.human();
300 params[jss::type] =
"state";
301 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
302 BEAST_EXPECT(!resp.isMember(jss::marker));
304 BEAST_EXPECT(resp[jss::result][jss::account_objects].size() == 2);
305 for (
int i = 0; i < 2; ++i)
307 auto& aobj = resp[jss::result][jss::account_objects][i];
308 aobj.removeMember(
"PreviousTxnID");
309 aobj.removeMember(
"PreviousTxnLgrSeq");
310 BEAST_EXPECT(aobj == bobj[i + 1]);
316 params[jss::account] = bob.human();
317 params[jss::limit] = 1;
318 for (
int i = 0; i < 4; ++i)
322 auto& aobjs = resp[jss::result][jss::account_objects];
323 BEAST_EXPECT(aobjs.size() == 1);
324 auto& aobj = aobjs[0U];
326 BEAST_EXPECT(resp[jss::result][jss::limit] == 1);
328 aobj.removeMember(
"PreviousTxnID");
329 aobj.removeMember(
"PreviousTxnLgrSeq");
331 BEAST_EXPECT(aobj == bobj[i]);
333 auto resume_marker = resp[jss::result][jss::marker];
334 params[jss::marker] = resume_marker;
342 testcase(
"object types");
350 auto const USD = gw[
"USD"];
356 auto acct_objs = [&env](
Account const& acct,
char const* type) {
358 params[jss::account] = acct.
human();
359 params[jss::type] = type;
360 params[jss::ledger_index] =
"validated";
361 return env.
rpc(
"json",
"account_objects",
to_string(params));
365 auto acct_objs_is_size = [](
Json::Value const& resp,
unsigned size) {
366 return resp[jss::result][jss::account_objects].
isArray() &&
367 (resp[jss::result][jss::account_objects].
size() == size);
370 env.
fund(
XRP(10000), gw, alice);
375 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::account), 0));
376 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::amendments), 0));
377 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::check), 0));
378 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::deposit_preauth), 0));
379 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::directory), 0));
380 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::escrow), 0));
381 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::fee), 0));
382 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::hashes), 0));
383 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::offer), 0));
384 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::payment_channel), 0));
385 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::signer_list), 0));
386 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::state), 0));
387 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::ticket), 0));
390 env.
trust(USD(1000), alice);
392 env(
pay(gw, alice, USD(5)));
396 Json::Value const resp = acct_objs(gw, jss::state);
397 BEAST_EXPECT(acct_objs_is_size(resp, 1));
399 auto const& state = resp[jss::result][jss::account_objects][0u];
405 env(check::create(gw, alice, USD(10)));
409 Json::Value const resp = acct_objs(gw, jss::check);
410 BEAST_EXPECT(acct_objs_is_size(resp, 1));
412 auto const& check = resp[jss::result][jss::account_objects][0u];
418 env(deposit::auth(gw, alice));
422 Json::Value const resp = acct_objs(gw, jss::deposit_preauth);
423 BEAST_EXPECT(acct_objs_is_size(resp, 1));
425 auto const& preauth = resp[jss::result][jss::account_objects][0u];
432 jvEscrow[jss::TransactionType] = jss::EscrowCreate;
434 jvEscrow[jss::Account] = gw.human();
435 jvEscrow[jss::Destination] = gw.human();
444 Json::Value const resp = acct_objs(gw, jss::escrow);
445 BEAST_EXPECT(acct_objs_is_size(resp, 1));
447 auto const& escrow = resp[jss::result][jss::account_objects][0u];
453 env(offer(gw, USD(7),
XRP(14)));
457 Json::Value const resp = acct_objs(gw, jss::offer);
458 BEAST_EXPECT(acct_objs_is_size(resp, 1));
460 auto const& offer = resp[jss::result][jss::account_objects][0u];
468 jvPayChan[jss::TransactionType] = jss::PaymentChannelCreate;
470 jvPayChan[jss::Account] = gw.human();
471 jvPayChan[jss::Destination] = alice.human();
472 jvPayChan[jss::Amount] =
481 Json::Value const resp = acct_objs(gw, jss::payment_channel);
482 BEAST_EXPECT(acct_objs_is_size(resp, 1));
484 auto const& payChan = resp[jss::result][jss::account_objects][0u];
491 env(signers(gw, 6, {{alice, 7}}));
495 Json::Value const resp = acct_objs(gw, jss::signer_list);
496 BEAST_EXPECT(acct_objs_is_size(resp, 1));
498 auto const& signerList =
499 resp[jss::result][jss::account_objects][0u];
507 env(ticket::create(gw, gw));
511 Json::Value const resp = acct_objs(gw, jss::ticket);
512 BEAST_EXPECT(acct_objs_is_size(resp, 1));
514 auto const& ticket = resp[jss::result][jss::account_objects][0u];
522 params[jss::account] = gw.human();
523 params[jss::deletion_blockers_only] =
true;
524 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
530 jss::RippleState.c_str(),
531 jss::PayChannel.c_str()};
539 if (BEAST_EXPECT(acct_objs_is_size(resp, expectedAccountObjects)))
541 auto const& aobjs = resp[jss::result][jss::account_objects];
543 gotLedgerTypes.
reserve(expectedAccountObjects);
547 aobjs[i][
"LedgerEntryType"].asString());
550 BEAST_EXPECT(gotLedgerTypes == expectedLedgerTypes);
557 params[jss::account] = gw.human();
558 params[jss::deletion_blockers_only] =
true;
559 params[jss::type] = jss::escrow;
560 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
562 if (BEAST_EXPECT(acct_objs_is_size(resp, 1u)))
564 auto const& aobjs = resp[jss::result][jss::account_objects];
565 BEAST_EXPECT(aobjs[0u][
"LedgerEntryType"] == jss::Escrow);
571 for (
int d = 1
'000'032; d >= 1
'000'000; --d)
573 env(offer(gw, USD(1),
drops(d)));
578 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::account), 0));
579 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::amendments), 0));
580 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::directory), 0));
581 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::fee), 0));
582 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::hashes), 0));