1#include <xrpld/app/ledger/LedgerMaster.h>
2#include <xrpld/app/main/Application.h>
3#include <xrpld/app/misc/DeliverMax.h>
4#include <xrpld/app/misc/Transaction.h>
5#include <xrpld/app/rdb/backend/SQLiteDatabase.h>
6#include <xrpld/rpc/Context.h>
7#include <xrpld/rpc/DeliveredAmount.h>
8#include <xrpld/rpc/MPTokenIssuanceID.h>
9#include <xrpld/rpc/Role.h>
10#include <xrpld/rpc/detail/RPCHelpers.h>
11#include <xrpld/rpc/detail/Tuning.h>
13#include <xrpl/json/json_value.h>
14#include <xrpl/ledger/ReadView.h>
15#include <xrpl/protocol/ErrorCodes.h>
16#include <xrpl/protocol/NFTSyntheticSerializer.h>
17#include <xrpl/protocol/RPCErr.h>
18#include <xrpl/protocol/UintTypes.h>
19#include <xrpl/protocol/jss.h>
20#include <xrpl/resource/Fees.h>
42 if ((params.
isMember(jss::ledger_index_min) || params.
isMember(jss::ledger_index_max)) &&
46 status.inject(response);
50 if (params.
isMember(jss::ledger_index_min) || params.
isMember(jss::ledger_index_max))
52 uint32_t min = params.
isMember(jss::ledger_index_min) && params[jss::ledger_index_min].
asInt() >= 0
53 ? params[jss::ledger_index_min].
asUInt()
55 uint32_t max = params.
isMember(jss::ledger_index_max) && params[jss::ledger_index_max].
asInt() >= 0
56 ? params[jss::ledger_index_max].
asUInt()
61 else if (params.
isMember(jss::ledger_hash))
63 auto& hashValue = params[jss::ledger_hash];
64 if (!hashValue.isString())
67 status.inject(response);
72 if (!hash.
parseHex(hashValue.asString()))
75 status.inject(response);
80 else if (params.
isMember(jss::ledger_index))
83 if (params[jss::ledger_index].isNumeric())
84 ledger = params[jss::ledger_index].
asUInt();
89 if (ledgerStr ==
"current" || ledgerStr.
empty())
90 ledger = LedgerShortcut::Current;
91 else if (ledgerStr ==
"closed")
92 ledger = LedgerShortcut::Closed;
93 else if (ledgerStr ==
"validated")
94 ledger = LedgerShortcut::Validated;
98 status.inject(response);
137 if ((ls.max > uValidatedMax && ls.max != -1) || (ls.min < uValidatedMin && ls.min != 0))
142 if (ls.min > uValidatedMin)
146 if (ls.max < uValidatedMax)
150 if (uLedgerMax < uLedgerMin)
160 auto const status = getLedger(ledgerView, ls, context);
168 if (!validated || ledgerView->header().seq > uValidatedMax ||
169 ledgerView->header().seq < uValidatedMin)
173 uLedgerMin = uLedgerMax = ledgerView->header().seq;
196 return {result, *stat};
214 Throw<std::runtime_error>(
"Failed to get relational database");
220 auto [tx, marker] = db->oldestAccountTxPageB(options);
226 auto [tx, marker] = db->newestAccountTxPageB(options);
235 auto [tx, marker] = db->oldestAccountTxPage(options);
241 auto [tx, marker] = db->newestAccountTxPage(options);
248 JLOG(context.
j.
debug()) << __func__ <<
" : finished";
263 error.inject(response);
268 response[jss::validated] =
true;
269 response[jss::limit] = result.
limit;
278 XRPL_ASSERT(!args.
binary,
"xrpl::populateJsonResponse : binary is not set");
280 for (
auto const& [txn, txnMeta] : *txnsData)
285 jvObj[jss::validated] =
true;
287 auto const json_tx = (context.
apiVersion > 1 ? jss::tx_json : jss::tx);
292 jvObj[jss::hash] =
to_string(txn->getID());
293 jvObj[jss::ledger_index] = txn->getLedger();
302 auto const& sttx = txn->getSTransaction();
307 insertDeliveredAmount(jvObj[jss::meta], context, txn, *txnMeta);
315 "xrpl::populateJsonResponse : missing "
316 "transaction metadata");
324 XRPL_ASSERT(args.
binary,
"xrpl::populateJsonResponse : binary is set");
331 auto const json_meta = (context.
apiVersion > 1 ? jss::meta_blob : jss::meta);
333 jvObj[jss::ledger_index] =
std::get<2>(binaryData);
334 jvObj[jss::validated] =
true;
341 response[jss::marker][jss::ledger] = result.
marker->ledgerSeq;
342 response[jss::marker][jss::seq] = result.
marker->txnSeq;
346 JLOG(context.
j.
debug()) << __func__ <<
" : finished";
366 auto& params = context.
params;
374 if (context.
apiVersion > 1u && params.isMember(jss::binary) && !params[jss::binary].isBool())
378 if (context.
apiVersion > 1u && params.isMember(jss::forward) && !params[jss::forward].isBool())
386 args.
binary = params.isMember(jss::binary) && params[jss::binary].asBool();
387 args.
forward = params.isMember(jss::forward) && params[jss::forward].asBool();
389 if (!params.isMember(jss::account))
392 if (!params[jss::account].isString())
395 auto const account = parseBase58<AccountID>(params[jss::account].asString());
411 if (params.isMember(jss::marker))
413 auto& token = params[jss::marker];
414 if (!token.isMember(jss::ledger) || !token.isMember(jss::seq) ||
420 "invalid marker. Provide ledger index via ledger field, and "
421 "transaction sequence number via seq field"};
422 status.inject(response);
425 args.
marker = {token[jss::ledger].asUInt(), token[jss::seq].asUInt()};
429 JLOG(context.
j.
debug()) << __func__ <<
" populating response";
Value & append(Value const &value)
Append value to array at the end.
std::string asString() const
Returns the unquoted string value.
bool isMember(char const *key) const
Return true if the object has a member named key.
virtual Config & config()=0
virtual RelationalDatabase & getRelationalDatabase()=0
bool getValidatedRange(std::uint32_t &minVal, std::uint32_t &maxVal)
uint256 getHashBySeq(std::uint32_t index)
Get a ledger's hash by sequence number using the cache.
std::optional< NetClock::time_point > getCloseTimeBySeq(LedgerIndex ledgerIndex)
bool isValidated(ReadView const &ledger)
std::vector< AccountTx > AccountTxs
RPC::LedgerShortcut LedgerShortcut
std::vector< txnMetaLedgerType > MetaTxsList
std::variant< LedgerRange, LedgerShortcut, LedgerSequence, LedgerHash > LedgerSpecifier
std::tuple< Blob, Blob, std::uint32_t > txnMetaLedgerType
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
@ arrayValue
array value (ordered list)
@ objectValue
object value (collection of name/value pairs).
@ uintValue
unsigned integer value
static LimitRange constexpr accountTx
Limits for the account_tx command.
Json::Value invalid_field_error(std::string const &name)
void insertDeliverMax(Json::Value &tx_json, TxType txnType, unsigned int apiVersion)
Copy Amount field to DeliverMax field in transaction output JSON.
Json::Value missing_field_error(std::string const &name)
void insertMPTokenIssuanceID(Json::Value &response, std::shared_ptr< STTx const > const &transaction, TxMeta const &transactionMeta)
void insertNFTSyntheticInJson(Json::Value &, std::shared_ptr< STTx const > const &, TxMeta const &)
Adds common synthetic fields to transaction-related JSON responses.
std::optional< Json::Value > readLimitField(unsigned int &limit, Tuning::LimitRange const &range, JsonContext const &context)
Retrieves the limit value from a JsonContext or sets a default.
Charge const feeMediumBurdenRPC
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Json::Value populateJsonResponse(std::pair< AccountTxResult, RPC::Status > const &res, AccountTxArgs const &args, RPC::JsonContext const &context)
std::variant< std::optional< LedgerSpecifier >, Json::Value > parseLedgerArgs(RPC::Context &context, Json::Value const ¶ms)
std::string to_string(base_uint< Bits, Tag > const &a)
std::string strHex(FwdIt begin, FwdIt end)
Json::Value doAccountTxJson(RPC::JsonContext &context)
std::variant< LedgerRange, RPC::Status > getLedgerRange(RPC::Context &context, std::optional< LedgerSpecifier > const &ledgerSpecifier)
Json::Value rpcError(error_code_i iError)
std::string to_string_iso(date::sys_time< Duration > tp)
std::pair< AccountTxResult, RPC::Status > doAccountTxHelp(RPC::Context &context, AccountTxArgs const &args)
bool isUnlimited(Role const &role)
ADMIN and IDENTIFIED roles shall have unlimited resources.
The context of information needed to call an RPC.
Resource::Charge & loadType
LedgerMaster & ledgerMaster
Status represents the results of an operation that might fail.
std::optional< AccountTxMarker > marker
std::optional< LedgerSpecifier > ledger
std::variant< AccountTxs, MetaTxsList > transactions
std::optional< AccountTxMarker > marker