20 #include <ripple/app/ledger/LedgerMaster.h>
21 #include <ripple/app/main/Application.h>
22 #include <ripple/app/misc/NetworkOPs.h>
23 #include <ripple/app/misc/Transaction.h>
24 #include <ripple/app/rdb/backend/PostgresDatabase.h>
25 #include <ripple/app/rdb/backend/SQLiteDatabase.h>
26 #include <ripple/core/Pg.h>
27 #include <ripple/json/json_reader.h>
28 #include <ripple/json/json_value.h>
29 #include <ripple/ledger/ReadView.h>
30 #include <ripple/net/RPCErr.h>
31 #include <ripple/protocol/ErrorCodes.h>
32 #include <ripple/protocol/UintTypes.h>
33 #include <ripple/protocol/jss.h>
34 #include <ripple/resource/Fees.h>
35 #include <ripple/rpc/Context.h>
36 #include <ripple/rpc/DeliveredAmount.h>
37 #include <ripple/rpc/NFTSyntheticSerializer.h>
38 #include <ripple/rpc/Role.h>
39 #include <ripple/rpc/impl/RPCHelpers.h>
41 #include <grpcpp/grpcpp.h>
59 if (params.
isMember(jss::ledger_index_min) ||
60 params.
isMember(jss::ledger_index_max))
62 uint32_t min = params.
isMember(jss::ledger_index_min) &&
63 params[jss::ledger_index_min].
asInt() >= 0
64 ? params[jss::ledger_index_min].
asUInt()
66 uint32_t max = params.
isMember(jss::ledger_index_max) &&
67 params[jss::ledger_index_max].
asInt() >= 0
68 ? params[jss::ledger_index_max].
asUInt()
73 else if (params.
isMember(jss::ledger_hash))
75 auto& hashValue = params[jss::ledger_hash];
76 if (!hashValue.isString())
79 status.inject(response);
84 if (!hash.
parseHex(hashValue.asString()))
87 status.inject(response);
92 else if (params.
isMember(jss::ledger_index))
95 if (params[jss::ledger_index].isNumeric())
96 ledger = params[jss::ledger_index].
asUInt();
101 if (ledgerStr ==
"current" || ledgerStr.
empty())
102 ledger = LedgerShortcut::CURRENT;
103 else if (ledgerStr ==
"closed")
104 ledger = LedgerShortcut::CLOSED;
105 else if (ledgerStr ==
"validated")
106 ledger = LedgerShortcut::VALIDATED;
111 status.inject(response);
146 if constexpr (std::is_same_v<T, LedgerRange>)
148 if (ls.min > uValidatedMin)
152 if (ls.max < uValidatedMax)
156 if (uLedgerMax < uLedgerMin)
166 auto const status = getLedger(ledgerView, ls, context);
175 if (!validated || ledgerView->
info().
seq > uValidatedMax ||
176 ledgerView->
info().
seq < uValidatedMin)
180 uLedgerMin = uLedgerMax = ledgerView->
info().
seq;
202 Throw<std::runtime_error>(
"Failed to get relational database");
204 return db->getAccountTx(args);
210 if (
auto stat = std::get_if<RPC::Status>(&lgrRange))
213 return {result, *stat};
216 result.
ledgerRange = std::get<LedgerRange>(lgrRange);
232 Throw<std::runtime_error>(
"Failed to get relational database");
238 auto [tx, marker] = db->oldestAccountTxPageB(options);
244 auto [tx, marker] = db->newestAccountTxPageB(options);
253 auto [tx, marker] = db->oldestAccountTxPage(options);
259 auto [tx, marker] = db->newestAccountTxPage(options);
266 JLOG(context.
j.
debug()) << __func__ <<
" : finished";
281 error.inject(response);
286 response[jss::validated] =
true;
287 response[jss::limit] = result.
limit;
294 if (
auto txnsData = std::get_if<TxnsData>(&result.
transactions))
297 for (
auto const& [txn, txnMeta] : *txnsData)
308 jvObj[jss::validated] =
true;
309 insertDeliveredAmount(
310 jvObj[jss::meta], context, txn, *txnMeta);
311 insertNFTSyntheticInJson(
312 jvObj, context, txn->getSTransaction(), *txnMeta);
321 for (
auto const& binaryData :
326 jvObj[jss::tx_blob] =
strHex(std::get<0>(binaryData));
327 jvObj[jss::meta] =
strHex(std::get<1>(binaryData));
328 jvObj[jss::ledger_index] = std::get<2>(binaryData);
329 jvObj[jss::validated] =
true;
336 response[jss::marker][jss::ledger] = result.
marker->ledgerSeq;
337 response[jss::marker][jss::seq] = result.
marker->txnSeq;
340 response[
"used_postgres"] =
true;
343 JLOG(context.
j.
debug()) << __func__ <<
" : finished";
363 auto& params = context.
params;
367 args.
limit = params.isMember(jss::limit) ? params[jss::limit].asUInt() : 0;
368 args.
binary = params.isMember(jss::binary) && params[jss::binary].asBool();
370 params.isMember(jss::forward) && params[jss::forward].asBool();
372 if (!params.isMember(jss::account))
376 parseBase58<AccountID>(params[jss::account].asString());
383 if (
auto jv = std::get_if<Json::Value>(&parseRes))
389 args.
ledger = std::get<std::optional<LedgerSpecifier>>(parseRes);
392 if (params.isMember(jss::marker))
394 auto& token = params[jss::marker];
395 if (!token.isMember(jss::ledger) || !token.isMember(jss::seq) ||
396 !token[jss::ledger].isConvertibleTo(Json::ValueType::uintValue) ||
397 !token[jss::seq].isConvertibleTo(Json::ValueType::uintValue))
401 "invalid marker. Provide ledger index via ledger field, and "
402 "transaction sequence number via seq field"};
403 status.inject(response);
406 args.
marker = {token[jss::ledger].asUInt(), token[jss::seq].asUInt()};
410 JLOG(context.
j.
debug()) << __func__ <<
" populating response";