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"];
355 auto acct_objs = [&env](
Account const& acct,
char const* type) {
357 params[jss::account] = acct.
human();
358 params[jss::type] = type;
359 params[jss::ledger_index] =
"validated";
360 return env.
rpc(
"json",
"account_objects",
to_string(params));
364 auto acct_objs_is_size = [](
Json::Value const& resp,
unsigned size) {
365 return resp[jss::result][jss::account_objects].
isArray() &&
366 (resp[jss::result][jss::account_objects].
size() == size);
369 env.
fund(
XRP(10000), gw, alice);
374 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::account), 0));
375 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::amendments), 0));
376 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::check), 0));
377 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::deposit_preauth), 0));
378 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::directory), 0));
379 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::escrow), 0));
380 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::fee), 0));
381 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::hashes), 0));
382 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::offer), 0));
383 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::payment_channel), 0));
384 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::signer_list), 0));
385 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::state), 0));
386 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::ticket), 0));
389 env.
trust(USD(1000), alice);
391 env(
pay(gw, alice, USD(5)));
395 Json::Value const resp = acct_objs(gw, jss::state);
396 BEAST_EXPECT(acct_objs_is_size(resp, 1));
398 auto const& state = resp[jss::result][jss::account_objects][0u];
404 env(check::create(gw, alice, USD(10)));
408 Json::Value const resp = acct_objs(gw, jss::check);
409 BEAST_EXPECT(acct_objs_is_size(resp, 1));
411 auto const& check = resp[jss::result][jss::account_objects][0u];
417 env(deposit::auth(gw, alice));
421 Json::Value const resp = acct_objs(gw, jss::deposit_preauth);
422 BEAST_EXPECT(acct_objs_is_size(resp, 1));
424 auto const& preauth = resp[jss::result][jss::account_objects][0u];
431 jvEscrow[jss::TransactionType] = jss::EscrowCreate;
433 jvEscrow[jss::Account] = gw.human();
434 jvEscrow[jss::Destination] = gw.human();
443 Json::Value const resp = acct_objs(gw, jss::escrow);
444 BEAST_EXPECT(acct_objs_is_size(resp, 1));
446 auto const& escrow = resp[jss::result][jss::account_objects][0u];
452 env(offer(gw, USD(7),
XRP(14)));
456 Json::Value const resp = acct_objs(gw, jss::offer);
457 BEAST_EXPECT(acct_objs_is_size(resp, 1));
459 auto const& offer = resp[jss::result][jss::account_objects][0u];
467 jvPayChan[jss::TransactionType] = jss::PaymentChannelCreate;
469 jvPayChan[jss::Account] = gw.human();
470 jvPayChan[jss::Destination] = alice.human();
471 jvPayChan[jss::Amount] =
480 Json::Value const resp = acct_objs(gw, jss::payment_channel);
481 BEAST_EXPECT(acct_objs_is_size(resp, 1));
483 auto const& payChan = resp[jss::result][jss::account_objects][0u];
490 env(signers(gw, 6, {{alice, 7}}));
494 Json::Value const resp = acct_objs(gw, jss::signer_list);
495 BEAST_EXPECT(acct_objs_is_size(resp, 1));
497 auto const& signerList =
498 resp[jss::result][jss::account_objects][0u];
506 env(ticket::create(gw, 1));
510 Json::Value const resp = acct_objs(gw, jss::ticket);
511 BEAST_EXPECT(acct_objs_is_size(resp, 1));
513 auto const& ticket = resp[jss::result][jss::account_objects][0u];
521 params[jss::account] = gw.human();
522 params[jss::deletion_blockers_only] =
true;
523 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
529 jss::RippleState.c_str(),
530 jss::PayChannel.c_str()};
538 if (BEAST_EXPECT(acct_objs_is_size(resp, expectedAccountObjects)))
540 auto const& aobjs = resp[jss::result][jss::account_objects];
542 gotLedgerTypes.
reserve(expectedAccountObjects);
546 aobjs[i][
"LedgerEntryType"].asString());
549 BEAST_EXPECT(gotLedgerTypes == expectedLedgerTypes);
556 params[jss::account] = gw.human();
557 params[jss::deletion_blockers_only] =
true;
558 params[jss::type] = jss::escrow;
559 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
561 if (BEAST_EXPECT(acct_objs_is_size(resp, 1u)))
563 auto const& aobjs = resp[jss::result][jss::account_objects];
564 BEAST_EXPECT(aobjs[0u][
"LedgerEntryType"] == jss::Escrow);
570 for (
int d = 1
'000'032; d >= 1
'000'000; --d)
572 env(offer(gw, USD(1),
drops(d)));
577 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::account), 0));
578 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::amendments), 0));
579 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::directory), 0));
580 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::fee), 0));
581 BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::hashes), 0));