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/Context.h>
7#include <xrpld/rpc/DeliveredAmount.h>
8#include <xrpld/rpc/MPTokenIssuanceID.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/json/json_value.h>
16#include <xrpl/ledger/helpers/TokenHelpers.h>
17#include <xrpl/protocol/AccountID.h>
18#include <xrpl/protocol/ApiVersion.h>
19#include <xrpl/protocol/LedgerHeader.h>
20#include <xrpl/protocol/SField.h>
21#include <xrpl/protocol/STObject.h>
22#include <xrpl/protocol/Serializer.h>
23#include <xrpl/protocol/TER.h>
24#include <xrpl/protocol/TxFormats.h>
25#include <xrpl/protocol/Units.h>
26#include <xrpl/protocol/XRPAmount.h>
27#include <xrpl/protocol/jss.h>
28#include <xrpl/protocol/serialize.h>
57fillJson(json::Value& json,
bool closed,
LedgerHeader const& info,
bool bFull,
unsigned apiVersion)
59 json[jss::parent_hash] =
to_string(info.parentHash);
60 json[jss::ledger_index] =
61 (apiVersion > 1) ? json::Value(info.seq) : json::Value(
std::to_string(info.seq));
65 json[jss::closed] =
true;
69 json[jss::closed] =
false;
73 json[jss::ledger_hash] =
to_string(info.hash);
74 json[jss::transaction_hash] =
to_string(info.txHash);
75 json[jss::account_hash] =
to_string(info.accountHash);
76 json[jss::total_coins] =
to_string(info.drops);
78 json[jss::close_flags] = info.closeFlags;
81 json[jss::parent_close_time] = info.parentCloseTime.time_since_epoch().count();
82 json[jss::close_time] = info.closeTime.time_since_epoch().count();
83 json[jss::close_time_resolution] = info.closeTimeResolution.count();
87 json[jss::close_time_human] =
to_string(info.closeTime);
89 json[jss::close_time_estimated] =
true;
90 json[jss::close_time_iso] =
toStringIso(info.closeTime);
95fillJsonBinary(json::Value& json,
bool closed,
LedgerHeader const& info)
99 json[jss::closed] =
false;
103 json[jss::closed] =
true;
107 json[jss::ledger_data] =
strHex(s.peekData());
116 std::shared_ptr<STTx const>
const& txn,
117 std::shared_ptr<STObject const>
const& stMeta)
120 return to_string(txn->getTransactionID());
123 auto const txnType = txn->getTxnType();
127 if (
fill.context->apiVersion > 1)
128 txJson[jss::hash] =
to_string(txn->getTransactionID());
130 auto const jsonMeta = (
fill.context->apiVersion > 1 ? jss::meta_blob : jss::meta);
134 else if (
fill.context->apiVersion > 1)
137 txJson[jss::hash] =
to_string(txn->getTransactionID());
145 if (txnType == ttPAYMENT || txnType == ttCHECK_CASH)
151 {txn->getTransactionID(), fill.ledger.seq(), *stMeta});
156 txJson[jss::meta], txn, {txn->getTransactionID(),
fill.ledger.seq(), *stMeta});
159 if (!
fill.ledger.open())
160 txJson[jss::ledger_hash] =
to_string(
fill.ledger.header().hash);
162 bool const validated =
fill.context->ledgerMaster.isValidated(
fill.ledger);
163 txJson[jss::validated] = validated;
166 auto const seq =
fill.ledger.seq();
167 txJson[jss::ledger_index] = seq;
181 if (txnType == ttPAYMENT || txnType == ttCHECK_CASH)
184 txJson[jss::metaData],
187 {txn->getTransactionID(), fill.ledger.seq(), *stMeta});
192 txJson[jss::metaData], txn, {txn->getTransactionID(),
fill.ledger.seq(), *stMeta});
197 txn->getTxnType() == ttOFFER_CREATE)
199 auto const account = txn->getAccountID(sfAccount);
200 auto const amount = txn->getFieldAmount(sfTakerGets);
204 if (account != amount.getIssuer())
211 beast::Journal{beast::Journal::getNullSink()});
212 txJson[jss::owner_funds] = ownerFunds.getText();
220fillJsonTx(json::Value& json,
LedgerFill const& fill)
223 auto bBinary = isBinary(fill);
224 auto bExpanded = isExpanded(fill);
228 auto appendAll = [&](
auto const& txs) {
231 txns.append(fillJsonTx(fill, bBinary, bExpanded, i.first, i.second));
235 appendAll(
fill.ledger.txs);
237 catch (std::exception
const& ex)
240 if (
fill.context !=
nullptr)
242 JLOG(
fill.context->j.error()) <<
"Exception in " << __func__ <<
": " << ex.
what();
248fillJsonState(json::Value& json,
LedgerFill const& fill)
250 auto& ledger =
fill.ledger;
252 auto expanded = isExpanded(fill);
253 auto binary = isBinary(fill);
255 for (
auto const& sle : ledger.sles)
275fillJsonQueue(json::Value& json,
LedgerFill const& fill)
278 auto bBinary = isBinary(fill);
279 auto bExpanded = isExpanded(fill);
281 for (
auto const& tx :
fill.txQueue)
284 txJson[jss::fee_level] =
to_string(tx.feeLevel);
286 txJson[jss::LastLedgerSequence] = *tx.lastValid;
288 txJson[jss::fee] =
to_string(tx.consequences.fee());
289 auto const spend = tx.consequences.potentialSpend() + tx.consequences.fee();
290 txJson[jss::max_spend_drops] =
to_string(spend);
291 txJson[jss::auth_change] = tx.consequences.isBlocker();
293 txJson[jss::account] =
to_string(tx.account);
294 txJson[
"retries_remaining"] = tx.retriesRemaining;
295 txJson[
"preflight_result"] =
transToken(tx.preflightResult);
297 txJson[
"last_result"] =
transToken(*tx.lastResult);
299 auto&& temp = fillJsonTx(fill, bBinary, bExpanded, tx.txn,
nullptr);
302 if (
fill.context->apiVersion > 1)
311 else if (
fill.context->apiVersion > 1)
313 txJson[jss::hash] = temp;
317 txJson[jss::tx] = temp;
323fillJson(json::Value& json,
LedgerFill const& fill)
327 auto bFull = isFull(fill);
330 fillJsonBinary(json, !
fill.ledger.open(),
fill.ledger.header());
337 fill.ledger.header(),
339 ((
fill.context !=
nullptr) ?
fill.context->apiVersion
344 fillJsonTx(json, fill);
347 fillJsonState(json, fill);
356 fillJson(
object, fill);
359 !fill.txQueue.empty())
361 fillJsonQueue(
json, fill);
369 fillJson(
json, fill);
384 XRPL_ASSERT(from.
isObjectOrNull(),
"copyFrom : invalid input type");
386 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).
void insertMPTokenIssuanceID(json::Value &response, std::shared_ptr< STTx const > const &transaction, TxMeta const &transactionMeta)
void insertDeliverMax(json::Value &txJson, TxType txnType, unsigned int apiVersion)
Copy Amount field to DeliverMax field in transaction output JSON.
static constexpr auto kApiMaximumSupportedVersion
void insertDeliveredAmount(json::Value &meta, ReadView const &, std::shared_ptr< STTx const > const &serializedTx, TxMeta const &)
Add a delivered_amount field to the meta input/output parameter.
Keylet account(AccountID const &id) noexcept
AccountID root.
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.