mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-21 04:05:51 +00:00
delivered amount
This commit is contained in:
@@ -7,7 +7,6 @@ template <class T, class F>
|
|||||||
void
|
void
|
||||||
processAsyncWriteResponse(T& requestParams, CassFuture* fut, F func)
|
processAsyncWriteResponse(T& requestParams, CassFuture* fut, F func)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(debug) << __func__ << " Processing async write response";
|
|
||||||
CassandraBackend const& backend = *requestParams.backend;
|
CassandraBackend const& backend = *requestParams.backend;
|
||||||
auto rc = cass_future_error_code(fut);
|
auto rc = cass_future_error_code(fut);
|
||||||
if (rc != CASS_OK)
|
if (rc != CASS_OK)
|
||||||
|
|||||||
@@ -1,6 +1,56 @@
|
|||||||
|
#include <backend/BackendInterface.h>
|
||||||
#include <handlers/RPCHelpers.h>
|
#include <handlers/RPCHelpers.h>
|
||||||
#include <handlers/Status.h>
|
#include <handlers/Status.h>
|
||||||
#include <backend/BackendInterface.h>
|
|
||||||
|
std::optional<ripple::STAmount>
|
||||||
|
getDeliveredAmount(
|
||||||
|
std::shared_ptr<ripple::STTx const> const& txn,
|
||||||
|
std::shared_ptr<ripple::STObject const> const& meta,
|
||||||
|
uint32_t ledgerSequence)
|
||||||
|
{
|
||||||
|
if (meta->isFieldPresent(ripple::sfDeliveredAmount))
|
||||||
|
return meta->getFieldAmount(ripple::sfDeliveredAmount);
|
||||||
|
if (txn->isFieldPresent(ripple::sfAmount))
|
||||||
|
{
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
// Ledger 4594095 is the first ledger in which the DeliveredAmount field
|
||||||
|
// was present when a partial payment was made and its absence indicates
|
||||||
|
// that the amount delivered is listed in the Amount field.
|
||||||
|
//
|
||||||
|
// If the ledger closed long after the DeliveredAmount code was deployed
|
||||||
|
// then its absence indicates that the amount delivered is listed in the
|
||||||
|
// Amount field. DeliveredAmount went live January 24, 2014.
|
||||||
|
// 446000000 is in Feb 2014, well after DeliveredAmount went live
|
||||||
|
if (ledgerSequence >= 4594095)
|
||||||
|
{
|
||||||
|
return txn->getFieldAmount(ripple::sfAmount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
canHaveDeliveredAmount(
|
||||||
|
std::shared_ptr<ripple::STTx const> const& txn,
|
||||||
|
std::shared_ptr<ripple::STObject const> const& meta)
|
||||||
|
{
|
||||||
|
ripple::TxType const tt{txn->getTxnType()};
|
||||||
|
if (tt != ripple::ttPAYMENT && tt != ripple::ttCHECK_CASH &&
|
||||||
|
tt != ripple::ttACCOUNT_DELETE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (tt == ttCHECK_CASH && !getFix1623Enabled())
|
||||||
|
return false;
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (ripple::TER::fromInt(meta->getFieldU8(ripple::sfTransactionResult)) !=
|
||||||
|
ripple::tesSUCCESS)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<ripple::AccountID>
|
std::optional<ripple::AccountID>
|
||||||
accountFromStringStrict(std::string const& account)
|
accountFromStringStrict(std::string const& account)
|
||||||
@@ -76,6 +126,23 @@ toJson(ripple::STBase const& obj)
|
|||||||
return value.as_object();
|
return value.as_object();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<boost::json::object, boost::json::object>
|
||||||
|
toExpandedJson(Backend::TransactionAndMetadata const& blobs)
|
||||||
|
{
|
||||||
|
auto [txn, meta] = deserializeTxPlusMeta(blobs);
|
||||||
|
auto txnJson = toJson(*txn);
|
||||||
|
auto metaJson = toJson(*meta);
|
||||||
|
if (canHaveDeliveredAmount(txn, meta))
|
||||||
|
{
|
||||||
|
if (auto amt = getDeliveredAmount(txn, meta, blobs.ledgerSequence))
|
||||||
|
metaJson["delivered_amount"] =
|
||||||
|
toBoostJson(amt->getJson(ripple::JsonOptions::include_date));
|
||||||
|
else
|
||||||
|
metaJson["delivered_amount"] = "unavailable";
|
||||||
|
}
|
||||||
|
return {txnJson, metaJson};
|
||||||
|
}
|
||||||
|
|
||||||
boost::json::object
|
boost::json::object
|
||||||
toJson(ripple::TxMeta const& meta)
|
toJson(ripple::TxMeta const& meta)
|
||||||
{
|
{
|
||||||
@@ -88,9 +155,8 @@ toJson(ripple::TxMeta const& meta)
|
|||||||
boost::json::value
|
boost::json::value
|
||||||
toBoostJson(Json::Value const& value)
|
toBoostJson(Json::Value const& value)
|
||||||
{
|
{
|
||||||
boost::json::value boostValue =
|
boost::json::value boostValue = boost::json::parse(value.toStyledString());
|
||||||
boost::json::parse(value.toStyledString());
|
|
||||||
|
|
||||||
return boostValue;
|
return boostValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,14 +204,15 @@ ledgerInfoFromRequest(RPC::Context const& ctx)
|
|||||||
if (!hashValue.is_null())
|
if (!hashValue.is_null())
|
||||||
{
|
{
|
||||||
if (!hashValue.is_string())
|
if (!hashValue.is_string())
|
||||||
return RPC::Status{RPC::Error::rpcINVALID_PARAMS, "ledgerHashNotString"};
|
return RPC::Status{
|
||||||
|
RPC::Error::rpcINVALID_PARAMS, "ledgerHashNotString"};
|
||||||
|
|
||||||
ripple::uint256 ledgerHash;
|
ripple::uint256 ledgerHash;
|
||||||
if (!ledgerHash.parseHex(hashValue.as_string().c_str()))
|
if (!ledgerHash.parseHex(hashValue.as_string().c_str()))
|
||||||
return RPC::Status{RPC::Error::rpcINVALID_PARAMS, "ledgerHashMalformed"};
|
return RPC::Status{
|
||||||
|
RPC::Error::rpcINVALID_PARAMS, "ledgerHashMalformed"};
|
||||||
|
|
||||||
lgrInfo = ctx.backend->fetchLedgerByHash(ledgerHash);
|
lgrInfo = ctx.backend->fetchLedgerByHash(ledgerHash);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (!indexValue.is_null())
|
else if (!indexValue.is_null())
|
||||||
{
|
{
|
||||||
@@ -155,15 +222,14 @@ ledgerInfoFromRequest(RPC::Context const& ctx)
|
|||||||
else if (!indexValue.is_string() && indexValue.is_int64())
|
else if (!indexValue.is_string() && indexValue.is_int64())
|
||||||
ledgerSequence = indexValue.as_int64();
|
ledgerSequence = indexValue.as_int64();
|
||||||
else
|
else
|
||||||
return RPC::Status{RPC::Error::rpcINVALID_PARAMS, "ledgerIndexMalformed"};
|
return RPC::Status{
|
||||||
|
RPC::Error::rpcINVALID_PARAMS, "ledgerIndexMalformed"};
|
||||||
|
|
||||||
lgrInfo =
|
lgrInfo = ctx.backend->fetchLedgerBySequence(ledgerSequence);
|
||||||
ctx.backend->fetchLedgerBySequence(ledgerSequence);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lgrInfo =
|
lgrInfo = ctx.backend->fetchLedgerBySequence(ctx.range.maxSequence);
|
||||||
ctx.backend->fetchLedgerBySequence(ctx.range.maxSequence);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lgrInfo)
|
if (!lgrInfo)
|
||||||
@@ -297,13 +363,15 @@ keypairFromRequst(boost::json::object const& request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
return RPC::Status{RPC::Error::rpcINVALID_PARAMS, "missing field secret"};
|
return RPC::Status{
|
||||||
|
RPC::Error::rpcINVALID_PARAMS, "missing field secret"};
|
||||||
|
|
||||||
if (count > 1)
|
if (count > 1)
|
||||||
{
|
{
|
||||||
return RPC::Status{RPC::Error::rpcINVALID_PARAMS,
|
return RPC::Status{
|
||||||
"Exactly one of the following must be specified: "
|
RPC::Error::rpcINVALID_PARAMS,
|
||||||
" passphrase, secret, seed, or seed_hex"};
|
"Exactly one of the following must be specified: "
|
||||||
|
" passphrase, secret, seed, or seed_hex"};
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<ripple::KeyType> keyType;
|
boost::optional<ripple::KeyType> keyType;
|
||||||
@@ -312,18 +380,20 @@ keypairFromRequst(boost::json::object const& request)
|
|||||||
if (has_key_type)
|
if (has_key_type)
|
||||||
{
|
{
|
||||||
if (!request.at("key_type").is_string())
|
if (!request.at("key_type").is_string())
|
||||||
return RPC::Status{RPC::Error::rpcINVALID_PARAMS, "keyTypeNotString"};
|
return RPC::Status{
|
||||||
|
RPC::Error::rpcINVALID_PARAMS, "keyTypeNotString"};
|
||||||
|
|
||||||
std::string key_type = request.at("key_type").as_string().c_str();
|
std::string key_type = request.at("key_type").as_string().c_str();
|
||||||
keyType = ripple::keyTypeFromString(key_type);
|
keyType = ripple::keyTypeFromString(key_type);
|
||||||
|
|
||||||
if (!keyType)
|
if (!keyType)
|
||||||
return RPC::Status{RPC::Error::rpcINVALID_PARAMS, "invalidFieldKeyType"};
|
return RPC::Status{
|
||||||
|
RPC::Error::rpcINVALID_PARAMS, "invalidFieldKeyType"};
|
||||||
|
|
||||||
if (secretType == "secret")
|
if (secretType == "secret")
|
||||||
return RPC::Status{RPC::Error::rpcINVALID_PARAMS,
|
return RPC::Status{
|
||||||
"The secret field is not allowed if key_type is used."};
|
RPC::Error::rpcINVALID_PARAMS,
|
||||||
|
"The secret field is not allowed if key_type is used."};
|
||||||
}
|
}
|
||||||
|
|
||||||
// ripple-lib encodes seed used to generate an Ed25519 wallet in a
|
// ripple-lib encodes seed used to generate an Ed25519 wallet in a
|
||||||
@@ -337,9 +407,11 @@ keypairFromRequst(boost::json::object const& request)
|
|||||||
{
|
{
|
||||||
// If the user passed in an Ed25519 seed but *explicitly*
|
// If the user passed in an Ed25519 seed but *explicitly*
|
||||||
// requested another key type, return an error.
|
// requested another key type, return an error.
|
||||||
if (keyType.value_or(ripple::KeyType::ed25519) != ripple::KeyType::ed25519)
|
if (keyType.value_or(ripple::KeyType::ed25519) !=
|
||||||
return RPC::Status{RPC::Error::rpcINVALID_PARAMS,
|
ripple::KeyType::ed25519)
|
||||||
"Specified seed is for an Ed25519 wallet."};
|
return RPC::Status{
|
||||||
|
RPC::Error::rpcINVALID_PARAMS,
|
||||||
|
"Specified seed is for an Ed25519 wallet."};
|
||||||
|
|
||||||
keyType = ripple::KeyType::ed25519;
|
keyType = ripple::KeyType::ed25519;
|
||||||
}
|
}
|
||||||
@@ -353,8 +425,9 @@ keypairFromRequst(boost::json::object const& request)
|
|||||||
if (has_key_type)
|
if (has_key_type)
|
||||||
{
|
{
|
||||||
if (!request.at(secretType).is_string())
|
if (!request.at(secretType).is_string())
|
||||||
return RPC::Status{RPC::Error::rpcINVALID_PARAMS,
|
return RPC::Status{
|
||||||
"secret value must be string"};
|
RPC::Error::rpcINVALID_PARAMS,
|
||||||
|
"secret value must be string"};
|
||||||
|
|
||||||
std::string key = request.at(secretType).as_string().c_str();
|
std::string key = request.at(secretType).as_string().c_str();
|
||||||
|
|
||||||
@@ -372,8 +445,9 @@ keypairFromRequst(boost::json::object const& request)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!request.at("secret").is_string())
|
if (!request.at("secret").is_string())
|
||||||
return RPC::Status{RPC::Error::rpcINVALID_PARAMS,
|
return RPC::Status{
|
||||||
"field secret should be a string"};
|
RPC::Error::rpcINVALID_PARAMS,
|
||||||
|
"field secret should be a string"};
|
||||||
|
|
||||||
std::string secret = request.at("secret").as_string().c_str();
|
std::string secret = request.at("secret").as_string().c_str();
|
||||||
seed = ripple::parseGenericSeed(secret);
|
seed = ripple::parseGenericSeed(secret);
|
||||||
@@ -381,13 +455,15 @@ keypairFromRequst(boost::json::object const& request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!seed)
|
if (!seed)
|
||||||
return RPC::Status{RPC::Error::rpcBAD_SEED,
|
return RPC::Status{
|
||||||
"Bad Seed: invalid field message secretType"};
|
RPC::Error::rpcBAD_SEED,
|
||||||
|
"Bad Seed: invalid field message secretType"};
|
||||||
|
|
||||||
if (keyType != ripple::KeyType::secp256k1
|
if (keyType != ripple::KeyType::secp256k1 &&
|
||||||
&& keyType != ripple::KeyType::ed25519)
|
keyType != ripple::KeyType::ed25519)
|
||||||
return RPC::Status{RPC::Error::rpcINVALID_PARAMS,
|
return RPC::Status{
|
||||||
"keypairForSignature: invalid key type"};
|
RPC::Error::rpcINVALID_PARAMS,
|
||||||
|
"keypairForSignature: invalid key type"};
|
||||||
|
|
||||||
return generateKeyPair(*keyType, *seed);
|
return generateKeyPair(*keyType, *seed);
|
||||||
}
|
}
|
||||||
@@ -433,7 +509,7 @@ isGlobalFrozen(
|
|||||||
|
|
||||||
ripple::SerialIter it{blob->data(), blob->size()};
|
ripple::SerialIter it{blob->data(), blob->size()};
|
||||||
ripple::SLE sle{it, key};
|
ripple::SLE sle{it, key};
|
||||||
|
|
||||||
return sle.isFlag(ripple::lsfGlobalFreeze);
|
return sle.isFlag(ripple::lsfGlobalFreeze);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,7 +532,7 @@ isFrozen(
|
|||||||
|
|
||||||
ripple::SerialIter it{blob->data(), blob->size()};
|
ripple::SerialIter it{blob->data(), blob->size()};
|
||||||
ripple::SLE sle{it, key};
|
ripple::SLE sle{it, key};
|
||||||
|
|
||||||
if (sle.isFlag(ripple::lsfGlobalFreeze))
|
if (sle.isFlag(ripple::lsfGlobalFreeze))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -471,7 +547,7 @@ isFrozen(
|
|||||||
ripple::SerialIter issuerIt{blob->data(), blob->size()};
|
ripple::SerialIter issuerIt{blob->data(), blob->size()};
|
||||||
ripple::SLE issuerLine{it, key};
|
ripple::SLE issuerLine{it, key};
|
||||||
|
|
||||||
auto frozen =
|
auto frozen =
|
||||||
(issuer > account) ? ripple::lsfHighFreeze : ripple::lsfLowFreeze;
|
(issuer > account) ? ripple::lsfHighFreeze : ripple::lsfLowFreeze;
|
||||||
|
|
||||||
if (issuerLine.isFlag(frozen))
|
if (issuerLine.isFlag(frozen))
|
||||||
@@ -498,7 +574,8 @@ xrpLiquid(
|
|||||||
|
|
||||||
std::uint32_t const ownerCount = sle.getFieldU32(ripple::sfOwnerCount);
|
std::uint32_t const ownerCount = sle.getFieldU32(ripple::sfOwnerCount);
|
||||||
|
|
||||||
auto const reserve = backend.fetchFees(sequence)->accountReserve(ownerCount);
|
auto const reserve =
|
||||||
|
backend.fetchFees(sequence)->accountReserve(ownerCount);
|
||||||
|
|
||||||
auto const balance = sle.getFieldAmount(ripple::sfBalance);
|
auto const balance = sle.getFieldAmount(ripple::sfBalance);
|
||||||
|
|
||||||
|
|||||||
@@ -2,15 +2,15 @@
|
|||||||
#ifndef XRPL_REPORTING_RPCHELPERS_H_INCLUDED
|
#ifndef XRPL_REPORTING_RPCHELPERS_H_INCLUDED
|
||||||
#define XRPL_REPORTING_RPCHELPERS_H_INCLUDED
|
#define XRPL_REPORTING_RPCHELPERS_H_INCLUDED
|
||||||
|
|
||||||
#include <ripple/protocol/STLedgerEntry.h>
|
|
||||||
#include <ripple/app/ledger/Ledger.h>
|
#include <ripple/app/ledger/Ledger.h>
|
||||||
#include <ripple/protocol/Indexes.h>
|
#include <ripple/protocol/Indexes.h>
|
||||||
#include <ripple/protocol/jss.h>
|
#include <ripple/protocol/STLedgerEntry.h>
|
||||||
#include <ripple/protocol/STTx.h>
|
#include <ripple/protocol/STTx.h>
|
||||||
|
#include <ripple/protocol/jss.h>
|
||||||
#include <boost/json.hpp>
|
#include <boost/json.hpp>
|
||||||
#include <handlers/Status.h>
|
|
||||||
#include <handlers/Context.h>
|
|
||||||
#include <backend/BackendInterface.h>
|
#include <backend/BackendInterface.h>
|
||||||
|
#include <handlers/Context.h>
|
||||||
|
#include <handlers/Status.h>
|
||||||
|
|
||||||
std::optional<ripple::AccountID>
|
std::optional<ripple::AccountID>
|
||||||
accountFromStringStrict(std::string const& account);
|
accountFromStringStrict(std::string const& account);
|
||||||
@@ -27,6 +27,9 @@ deserializeTxPlusMeta(
|
|||||||
Backend::TransactionAndMetadata const& blobs,
|
Backend::TransactionAndMetadata const& blobs,
|
||||||
std::uint32_t seq);
|
std::uint32_t seq);
|
||||||
|
|
||||||
|
std::pair<boost::json::object, boost::json::object>
|
||||||
|
toExpandedJson(Backend::TransactionAndMetadata const& blobs);
|
||||||
|
|
||||||
boost::json::object
|
boost::json::object
|
||||||
toJson(ripple::STBase const& obj);
|
toJson(ripple::STBase const& obj);
|
||||||
|
|
||||||
|
|||||||
@@ -194,11 +194,10 @@ doAccountTx(Context const& context)
|
|||||||
|
|
||||||
if (!binary)
|
if (!binary)
|
||||||
{
|
{
|
||||||
auto [txn, meta] = deserializeTxPlusMeta(txnPlusMeta);
|
auto [txn, meta] = toExpandedJson(txnPlusMeta);
|
||||||
obj["meta"] = toJson(*meta);
|
obj["meta"] = meta;
|
||||||
obj["tx"] = toJson(*txn);
|
obj["tx"] = txn;
|
||||||
obj["tx"].as_object()["ledger_index"] = txnPlusMeta.ledgerSequence;
|
obj["tx"].as_object()["ledger_index"] = txnPlusMeta.ledgerSequence;
|
||||||
obj["tx"].as_object()["inLedger"] = txnPlusMeta.ledgerSequence;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
#include <handlers/methods/Ledger.h>
|
|
||||||
#include <handlers/RPCHelpers.h>
|
|
||||||
#include <backend/BackendInterface.h>
|
#include <backend/BackendInterface.h>
|
||||||
|
#include <handlers/RPCHelpers.h>
|
||||||
|
#include <handlers/methods/Ledger.h>
|
||||||
|
|
||||||
namespace RPC
|
namespace RPC {
|
||||||
{
|
|
||||||
|
|
||||||
Result
|
Result
|
||||||
doLedger(Context const& context)
|
doLedger(Context const& context)
|
||||||
@@ -12,29 +11,29 @@ doLedger(Context const& context)
|
|||||||
boost::json::object response = {};
|
boost::json::object response = {};
|
||||||
|
|
||||||
bool binary = false;
|
bool binary = false;
|
||||||
if(params.contains("binary"))
|
if (params.contains("binary"))
|
||||||
{
|
{
|
||||||
if(!params.at("binary").is_bool())
|
if (!params.at("binary").is_bool())
|
||||||
return Status{Error::rpcINVALID_PARAMS, "binaryFlagNotBool"};
|
return Status{Error::rpcINVALID_PARAMS, "binaryFlagNotBool"};
|
||||||
|
|
||||||
binary = params.at("binary").as_bool();
|
binary = params.at("binary").as_bool();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool transactions = false;
|
bool transactions = false;
|
||||||
if(params.contains("transactions"))
|
if (params.contains("transactions"))
|
||||||
{
|
{
|
||||||
if(!params.at("transactions").is_bool())
|
if (!params.at("transactions").is_bool())
|
||||||
return Status{Error::rpcINVALID_PARAMS, "transactionsFlagNotBool"};
|
return Status{Error::rpcINVALID_PARAMS, "transactionsFlagNotBool"};
|
||||||
|
|
||||||
transactions = params.at("transactions").as_bool();
|
transactions = params.at("transactions").as_bool();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool expand = false;
|
bool expand = false;
|
||||||
if(params.contains("expand"))
|
if (params.contains("expand"))
|
||||||
{
|
{
|
||||||
if(!params.at("expand").is_bool())
|
if (!params.at("expand").is_bool())
|
||||||
return Status{Error::rpcINVALID_PARAMS, "expandFlagNotBool"};
|
return Status{Error::rpcINVALID_PARAMS, "expandFlagNotBool"};
|
||||||
|
|
||||||
expand = params.at("expand").as_bool();
|
expand = params.at("expand").as_bool();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +54,8 @@ doLedger(Context const& context)
|
|||||||
header["account_hash"] = ripple::strHex(lgrInfo.accountHash);
|
header["account_hash"] = ripple::strHex(lgrInfo.accountHash);
|
||||||
header["close_flags"] = lgrInfo.closeFlags;
|
header["close_flags"] = lgrInfo.closeFlags;
|
||||||
header["close_time"] = lgrInfo.closeTime.time_since_epoch().count();
|
header["close_time"] = lgrInfo.closeTime.time_since_epoch().count();
|
||||||
header["close_time_human"] = ripple::to_string(lgrInfo.closeTime);;
|
header["close_time_human"] = ripple::to_string(lgrInfo.closeTime);
|
||||||
|
;
|
||||||
header["close_time_resolution"] = lgrInfo.closeTimeResolution.count();
|
header["close_time_resolution"] = lgrInfo.closeTimeResolution.count();
|
||||||
header["closed"] = true;
|
header["closed"] = true;
|
||||||
header["hash"] = ripple::strHex(lgrInfo.hash);
|
header["hash"] = ripple::strHex(lgrInfo.hash);
|
||||||
@@ -69,6 +69,7 @@ doLedger(Context const& context)
|
|||||||
header["total_coins"] = ripple::to_string(lgrInfo.drops);
|
header["total_coins"] = ripple::to_string(lgrInfo.drops);
|
||||||
header["transaction_hash"] = ripple::strHex(lgrInfo.txHash);
|
header["transaction_hash"] = ripple::strHex(lgrInfo.txHash);
|
||||||
}
|
}
|
||||||
|
header["closed"] = true;
|
||||||
|
|
||||||
if (transactions)
|
if (transactions)
|
||||||
{
|
{
|
||||||
@@ -76,7 +77,8 @@ doLedger(Context const& context)
|
|||||||
boost::json::array& jsonTxs = header.at("transactions").as_array();
|
boost::json::array& jsonTxs = header.at("transactions").as_array();
|
||||||
if (expand)
|
if (expand)
|
||||||
{
|
{
|
||||||
auto txns = context.backend->fetchAllTransactionsInLedger(lgrInfo.seq);
|
auto txns =
|
||||||
|
context.backend->fetchAllTransactionsInLedger(lgrInfo.seq);
|
||||||
|
|
||||||
std::transform(
|
std::transform(
|
||||||
std::move_iterator(txns.begin()),
|
std::move_iterator(txns.begin()),
|
||||||
@@ -86,16 +88,16 @@ doLedger(Context const& context)
|
|||||||
boost::json::object entry;
|
boost::json::object entry;
|
||||||
if (!binary)
|
if (!binary)
|
||||||
{
|
{
|
||||||
auto [sttx, meta] = deserializeTxPlusMeta(obj);
|
auto [txn, meta] = toExpandedJson(obj);
|
||||||
entry = toJson(*sttx);
|
entry = txn;
|
||||||
entry["metaData"] = toJson(*meta);
|
entry["metaData"] = meta;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
entry["tx_blob"] = ripple::strHex(obj.transaction);
|
entry["tx_blob"] = ripple::strHex(obj.transaction);
|
||||||
entry["meta"] = ripple::strHex(obj.metadata);
|
entry["meta"] = ripple::strHex(obj.metadata);
|
||||||
}
|
}
|
||||||
entry["ledger_sequence"] = obj.ledgerSequence;
|
entry["ledger_index"] = obj.ledgerSequence;
|
||||||
return entry;
|
return entry;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -113,11 +115,11 @@ doLedger(Context const& context)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response["ledger"] = header;
|
response["ledger"] = header;
|
||||||
response["ledger_hash"] = ripple::strHex(lgrInfo.hash);
|
response["ledger_hash"] = ripple::strHex(lgrInfo.hash);
|
||||||
response["ledger_index"] = lgrInfo.seq;
|
response["ledger_index"] = lgrInfo.seq;
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace RPC
|
||||||
|
|||||||
@@ -17,13 +17,12 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <handlers/RPCHelpers.h>
|
|
||||||
#include <handlers/methods/Transaction.h>
|
|
||||||
#include <backend/BackendInterface.h>
|
#include <backend/BackendInterface.h>
|
||||||
#include <backend/Pg.h>
|
#include <backend/Pg.h>
|
||||||
|
#include <handlers/RPCHelpers.h>
|
||||||
|
#include <handlers/methods/Transaction.h>
|
||||||
|
|
||||||
namespace RPC
|
namespace RPC {
|
||||||
{
|
|
||||||
|
|
||||||
// {
|
// {
|
||||||
// transaction: <hex>
|
// transaction: <hex>
|
||||||
@@ -37,7 +36,7 @@ doTx(Context const& context)
|
|||||||
|
|
||||||
if (!request.contains("transaction"))
|
if (!request.contains("transaction"))
|
||||||
return Status{Error::rpcINVALID_PARAMS, "specifyTransaction"};
|
return Status{Error::rpcINVALID_PARAMS, "specifyTransaction"};
|
||||||
|
|
||||||
if (!request.at("transaction").is_string())
|
if (!request.at("transaction").is_string())
|
||||||
return Status{Error::rpcINVALID_PARAMS, "transactionNotString"};
|
return Status{Error::rpcINVALID_PARAMS, "transactionNotString"};
|
||||||
|
|
||||||
@@ -46,11 +45,11 @@ doTx(Context const& context)
|
|||||||
return Status{Error::rpcINVALID_PARAMS, "malformedTransaction"};
|
return Status{Error::rpcINVALID_PARAMS, "malformedTransaction"};
|
||||||
|
|
||||||
bool binary = false;
|
bool binary = false;
|
||||||
if(request.contains("binary"))
|
if (request.contains("binary"))
|
||||||
{
|
{
|
||||||
if(!request.at("binary").is_bool())
|
if (!request.at("binary").is_bool())
|
||||||
return Status{Error::rpcINVALID_PARAMS, "binaryFlagNotBool"};
|
return Status{Error::rpcINVALID_PARAMS, "binaryFlagNotBool"};
|
||||||
|
|
||||||
binary = request.at("binary").as_bool();
|
binary = request.at("binary").as_bool();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,9 +63,10 @@ doTx(Context const& context)
|
|||||||
|
|
||||||
if (!binary)
|
if (!binary)
|
||||||
{
|
{
|
||||||
auto [sttx, meta] = deserializeTxPlusMeta(dbResponse.value());
|
auto [txn, meta] = toExpandedJson(*dbResponse);
|
||||||
response = toJson(*sttx);
|
response = txn;
|
||||||
response["meta"] = toJson(*meta);
|
response["meta"] = meta;
|
||||||
|
response["ledger_index"] = dbResponse->ledgerSequence;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -77,4 +77,4 @@ doTx(Context const& context)
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace RPC
|
} // namespace RPC
|
||||||
|
|||||||
Reference in New Issue
Block a user