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",
39 "LedgerEntryType" : "Offer",
44 "issuer" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
47 "TakerPays" : "100000000",
48 "index" : "29665262716C19830E26AEEC0916E476FC7D8EF195FF3B4F06829E64F82A3B3E"
53 "issuer" : "rrrrrrrrrrrrrrrrrrrrBZbvji",
59 "issuer" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
63 "LedgerEntryType" : "RippleState",
66 "issuer" : "r9cZvwKU3zzuZK9JFovGg1JC5n7QiqNL8L",
70 "index" : "D13183BCFFC9AAC9F96AEBB5F66E4A652AD1F5D10273AEB615478302BEBFD4A4"
75 "issuer" : "rrrrrrrrrrrrrrrrrrrrBZbvji",
81 "issuer" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
85 "LedgerEntryType" : "RippleState",
88 "issuer" : "r32rQHyesiTtdWFU7UJVtff4nCR5SHCbJW",
92 "index" : "D89BC239086183EB9458C396E643795C1134963E6550E682A190A5F021766D43"
95 "Account" : "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
96 "BookDirectory" : "B025997A323F5C3E03DDF1334471F5984ABDE31C59D463525D038D7EA4C68000",
99 "LedgerEntryType" : "Offer",
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");
290 BEAST_EXPECT(aobj == bobj[i]);
296 params[jss::account] = bob.human();
297 params[jss::type] =
"state";
298 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
299 BEAST_EXPECT(!resp.isMember(jss::marker));
301 BEAST_EXPECT(resp[jss::result][jss::account_objects].size() == 2);
302 for (
int i = 0; i < 2; ++i)
304 auto& aobj = resp[jss::result][jss::account_objects][i];
305 aobj.removeMember(
"PreviousTxnID");
306 aobj.removeMember(
"PreviousTxnLgrSeq");
307 BEAST_EXPECT(aobj == bobj[i + 1]);
313 params[jss::account] = bob.human();
314 params[jss::limit] = 1;
315 for (
int i = 0; i < 4; ++i)
319 auto& aobjs = resp[jss::result][jss::account_objects];
320 BEAST_EXPECT(aobjs.size() == 1);
321 auto& aobj = aobjs[0U];
323 BEAST_EXPECT(resp[jss::result][jss::limit] == 1);
325 aobj.removeMember(
"PreviousTxnID");
326 aobj.removeMember(
"PreviousTxnLgrSeq");
328 BEAST_EXPECT(aobj == bobj[i]);
330 auto resume_marker = resp[jss::result][jss::marker];
331 params[jss::marker] = resume_marker;
339 testcase(
"object types");
347 auto const USD = gw[
"USD"];
352 auto acct_objs = [&env](
Account const& acct,
char const* type) {
354 params[jss::account] = acct.
human();
355 params[jss::type] = type;
356 params[jss::ledger_index] =
"validated";
357 return env.
rpc(
"json",
"account_objects",
to_string(params));
361 auto acct_objs_is_size = [](
Json::Value const& resp,
unsigned size) {
362 return resp[jss::result][jss::account_objects].
isArray() &&
363 (resp[jss::result][jss::account_objects].
size() == size);
366 env.
fund(
XRP(10000), gw, alice);
371 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::account), 0));
372 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::amendments), 0));
373 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::check), 0));
374 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::deposit_preauth), 0));
375 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::directory), 0));
376 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::escrow), 0));
377 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::fee), 0));
378 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::hashes), 0));
379 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::offer), 0));
380 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::payment_channel), 0));
381 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::signer_list), 0));
382 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::state), 0));
383 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::ticket), 0));
386 env.
trust(USD(1000), alice);
388 env(
pay(gw, alice, USD(5)));
392 Json::Value const resp = acct_objs(gw, jss::state);
393 BEAST_EXPECT(acct_objs_is_size(resp, 1));
395 auto const& state = resp[jss::result][jss::account_objects][0u];
401 env(check::create(gw, alice, USD(10)));
405 Json::Value const resp = acct_objs(gw, jss::check);
406 BEAST_EXPECT(acct_objs_is_size(resp, 1));
408 auto const& check = resp[jss::result][jss::account_objects][0u];
414 env(deposit::auth(gw, alice));
418 Json::Value const resp = acct_objs(gw, jss::deposit_preauth);
419 BEAST_EXPECT(acct_objs_is_size(resp, 1));
421 auto const& preauth = resp[jss::result][jss::account_objects][0u];
428 jvEscrow[jss::TransactionType] = jss::EscrowCreate;
430 jvEscrow[jss::Account] = gw.human();
431 jvEscrow[jss::Destination] = gw.human();
440 Json::Value const resp = acct_objs(gw, jss::escrow);
441 BEAST_EXPECT(acct_objs_is_size(resp, 1));
443 auto const& escrow = resp[jss::result][jss::account_objects][0u];
449 env(offer(gw, USD(7),
XRP(14)));
453 Json::Value const resp = acct_objs(gw, jss::offer);
454 BEAST_EXPECT(acct_objs_is_size(resp, 1));
456 auto const& offer = resp[jss::result][jss::account_objects][0u];
464 jvPayChan[jss::TransactionType] = jss::PaymentChannelCreate;
466 jvPayChan[jss::Account] = gw.human();
467 jvPayChan[jss::Destination] = alice.human();
468 jvPayChan[jss::Amount] =
477 Json::Value const resp = acct_objs(gw, jss::payment_channel);
478 BEAST_EXPECT(acct_objs_is_size(resp, 1));
480 auto const& payChan = resp[jss::result][jss::account_objects][0u];
487 env(signers(gw, 6, {{alice, 7}}));
491 Json::Value const resp = acct_objs(gw, jss::signer_list);
492 BEAST_EXPECT(acct_objs_is_size(resp, 1));
494 auto const& signerList =
495 resp[jss::result][jss::account_objects][0u];
503 env(ticket::create(gw, 1));
507 Json::Value const resp = acct_objs(gw, jss::ticket);
508 BEAST_EXPECT(acct_objs_is_size(resp, 1));
510 auto const& ticket = resp[jss::result][jss::account_objects][0u];
518 params[jss::account] = gw.human();
519 params[jss::deletion_blockers_only] =
true;
520 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
526 jss::RippleState.c_str(),
527 jss::PayChannel.c_str()};
535 if (BEAST_EXPECT(acct_objs_is_size(resp, expectedAccountObjects)))
537 auto const& aobjs = resp[jss::result][jss::account_objects];
539 gotLedgerTypes.
reserve(expectedAccountObjects);
543 aobjs[i][
"LedgerEntryType"].asString());
546 BEAST_EXPECT(gotLedgerTypes == expectedLedgerTypes);
553 params[jss::account] = gw.human();
554 params[jss::deletion_blockers_only] =
true;
555 params[jss::type] = jss::escrow;
556 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
558 if (BEAST_EXPECT(acct_objs_is_size(resp, 1u)))
560 auto const& aobjs = resp[jss::result][jss::account_objects];
561 BEAST_EXPECT(aobjs[0u][
"LedgerEntryType"] == jss::Escrow);
567 for (
int d = 1
'000'032; d >= 1
'000'000; --d)
569 env(offer(gw, USD(1),
drops(d)));
574 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::account), 0));
575 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::amendments), 0));
576 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::directory), 0));
577 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::fee), 0));
578 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::hashes), 0));