1#include <xrpld/app/ledger/LedgerToJson.h>
3#include <xrpld/app/ledger/LedgerMaster.h>
4#include <xrpld/app/misc/DeliverMax.h>
5#include <xrpld/app/misc/TxQ.h>
6#include <xrpld/rpc/CTID.h>
7#include <xrpld/rpc/Context.h>
8#include <xrpld/rpc/detail/SyntheticFields.h>
10#include <xrpl/basics/Log.h>
11#include <xrpl/basics/base_uint.h>
12#include <xrpl/basics/chrono.h>
13#include <xrpl/basics/strHex.h>
14#include <xrpl/beast/utility/instrumentation.h>
15#include <xrpl/core/NetworkIDService.h>
16#include <xrpl/json/json_value.h>
17#include <xrpl/ledger/helpers/TokenHelpers.h>
18#include <xrpl/protocol/AccountID.h>
19#include <xrpl/protocol/ApiVersion.h>
20#include <xrpl/protocol/LedgerHeader.h>
21#include <xrpl/protocol/SField.h>
22#include <xrpl/protocol/STObject.h>
23#include <xrpl/protocol/STTx.h>
24#include <xrpl/protocol/Serializer.h>
25#include <xrpl/protocol/TER.h>
26#include <xrpl/protocol/TxFormats.h>
27#include <xrpl/protocol/Units.h>
28#include <xrpl/protocol/XRPAmount.h>
29#include <xrpl/protocol/jss.h>
30#include <xrpl/protocol/serialize.h>
60fillJson(json::Value& json,
bool closed,
LedgerHeader const& info,
bool bFull,
unsigned apiVersion)
62 json[jss::parent_hash] =
to_string(info.parentHash);
63 json[jss::ledger_index] =
64 (apiVersion > 1) ? json::Value(info.seq) : json::Value(
std::to_string(info.seq));
68 json[jss::closed] =
true;
72 json[jss::closed] =
false;
76 json[jss::ledger_hash] =
to_string(info.hash);
77 json[jss::transaction_hash] =
to_string(info.txHash);
78 json[jss::account_hash] =
to_string(info.accountHash);
79 json[jss::total_coins] =
to_string(info.drops);
81 json[jss::close_flags] = info.closeFlags;
84 json[jss::parent_close_time] = info.parentCloseTime.time_since_epoch().count();
85 json[jss::close_time] = info.closeTime.time_since_epoch().count();
86 json[jss::close_time_resolution] = info.closeTimeResolution.count();
90 json[jss::close_time_human] =
to_string(info.closeTime);
92 json[jss::close_time_estimated] =
true;
93 json[jss::close_time_iso] =
toStringIso(info.closeTime);
98fillJsonBinary(json::Value& json,
bool closed,
LedgerHeader const& info)
102 json[jss::closed] =
false;
106 json[jss::closed] =
true;
110 json[jss::ledger_data] =
strHex(s.peekData());
119 std::shared_ptr<STTx const>
const& txn,
120 std::shared_ptr<STObject const>
const& stMeta)
123 return to_string(txn->getTransactionID());
126 auto const txnType = txn->getTxnType();
130 if (
fill.context->apiVersion > 1)
131 txJson[jss::hash] =
to_string(txn->getTransactionID());
133 auto const jsonMeta = (
fill.context->apiVersion > 1 ? jss::meta_blob : jss::meta);
137 else if (
fill.context->apiVersion > 1)
140 txJson[jss::hash] =
to_string(txn->getTransactionID());
152 {txn->getTransactionID(), fill.ledger.seq(), *stMeta});
155 if (!
fill.ledger.open())
156 txJson[jss::ledger_hash] =
to_string(
fill.ledger.header().hash);
158 bool const validated =
fill.context->ledgerMaster.isValidated(
fill.ledger);
159 txJson[jss::validated] = validated;
162 auto const seq =
fill.ledger.seq();
163 txJson[jss::ledger_index] = seq;
178 txJson[jss::metaData],
181 {txn->getTransactionID(), fill.ledger.seq(), *stMeta});
186 if (stMeta && stMeta->isFieldPresent(sfTransactionIndex))
188 uint32_t
const lgrSeq =
fill.ledger.seq();
189 uint32_t
const txnIdx = stMeta->getFieldU32(sfTransactionIndex);
190 uint32_t netID =
fill.context->app.getNetworkIDService().getNetworkID();
191 if (txn->isFieldPresent(sfNetworkID))
192 netID = txn->getFieldU32(sfNetworkID);
195 txJson[jss::ctid] = *ctid;
199 txn->getTxnType() == ttOFFER_CREATE)
201 auto const account = txn->getAccountID(sfAccount);
202 auto const amount = txn->getFieldAmount(sfTakerGets);
206 if (account != amount.getIssuer())
214 beast::Journal{beast::Journal::getNullSink()});
215 txJson[jss::owner_funds] = ownerFunds.getText();
223fillJsonTx(json::Value& json,
LedgerFill const& fill)
226 auto bBinary = isBinary(fill);
227 auto bExpanded = isExpanded(fill);
231 auto appendAll = [&](
auto const& txs) {
234 txns.append(fillJsonTx(fill, bBinary, bExpanded, i.first, i.second));
238 appendAll(
fill.ledger.txs);
240 catch (std::exception
const& ex)
243 if (
fill.context !=
nullptr)
245 JLOG(
fill.context->j.error()) <<
"Exception in " << __func__ <<
": " << ex.
what();
251fillJsonState(json::Value& json,
LedgerFill const& fill)
253 auto& ledger =
fill.ledger;
255 auto expanded = isExpanded(fill);
256 auto binary = isBinary(fill);
258 for (
auto const& sle : ledger.sles)
278fillJsonQueue(json::Value& json,
LedgerFill const& fill)
281 auto bBinary = isBinary(fill);
282 auto bExpanded = isExpanded(fill);
284 for (
auto const& tx :
fill.txQueue)
287 txJson[jss::fee_level] =
to_string(tx.feeLevel);
289 txJson[jss::LastLedgerSequence] = *tx.lastValid;
291 txJson[jss::fee] =
to_string(tx.consequences.fee());
292 auto const spend = tx.consequences.potentialSpend() + tx.consequences.fee();
293 txJson[jss::max_spend_drops] =
to_string(spend);
294 txJson[jss::auth_change] = tx.consequences.isBlocker();
296 txJson[jss::account] =
to_string(tx.account);
297 txJson[
"retries_remaining"] = tx.retriesRemaining;
298 txJson[
"preflight_result"] =
transToken(tx.preflightResult);
300 txJson[
"last_result"] =
transToken(*tx.lastResult);
302 auto&& temp = fillJsonTx(fill, bBinary, bExpanded, tx.txn,
nullptr);
305 if (
fill.context->apiVersion > 1)
314 else if (
fill.context->apiVersion > 1)
316 txJson[jss::hash] = temp;
320 txJson[jss::tx] = temp;
326fillJson(json::Value& json,
LedgerFill const& fill)
330 auto bFull = isFull(fill);
333 fillJsonBinary(json, !
fill.ledger.open(),
fill.ledger.header());
340 fill.ledger.header(),
342 ((
fill.context !=
nullptr) ?
fill.context->apiVersion
347 fillJsonTx(json, fill);
350 fillJsonState(json, fill);
359 fillJson(
object, fill);
362 !fill.txQueue.empty())
364 fillJsonQueue(
json, fill);
372 fillJson(
json, fill);
387 XRPL_ASSERT(from.
isObjectOrNull(),
"copyFrom : invalid input type");
389 for (
auto const& m : members)
Value & append(Value const &value)
Append value to array at the end.
Members getMemberNames() const
Return a list of the member names.
bool isObjectOrNull() const
std::chrono::time_point< NetClock > time_point
JSON (JavaScript Object Notation).
@ Array
array value (ordered list)
@ Object
object value (collection of name/value pairs).
Keylet account(AccountID const &id) noexcept
AccountID root.
static constexpr auto kApiMaximumSupportedVersion
std::optional< std::string > encodeCTID(uint32_t ledgerSeq, uint32_t txnIndex, uint32_t networkID) noexcept
Encodes ledger sequence, transaction index, and network ID into a CTID string.
void insertDeliverMax(json::Value &txJson, TxType txnType, unsigned int apiVersion)
Copy Amount field to DeliverMax field in transaction output JSON.
void insertAllSyntheticInJson(json::Value &metadata, ReadView const &ledger, std::shared_ptr< STTx const > const &transaction, TxMeta const &transactionMeta)
Adds all synthetic fields to transaction metadata JSON.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::string strHex(FwdIt begin, FwdIt end)
void addJson(json::Value &json, LedgerFill const &fill)
Given a Ledger and options, fill a json::Value with a description of the ledger.
std::string transToken(TER code)
bool getCloseAgree(LedgerHeader const &info)
std::string to_string(BaseUInt< Bits, Tag > const &a)
std::string toStringIso(date::sys_time< Duration > tp)
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, beast::Journal j)
void addRaw(LedgerHeader const &, Serializer &, bool includeHash=false)
std::string serializeHex(STObject const &o)
Serialize an object to a hex string.
json::Value getJson(LedgerFill const &fill)
Return a new json::Value representing the ledger with given options.
void copyFrom(json::Value &to, json::Value const &from)
Copy all the keys and values from one object into another.