Add 'delivered_amount' to Transaction JSON (RIPD-643):

The synthetic field 'delivered_amount' can be used to determine the exact
amount delivered by a Payment without having to check the DeliveredAmount
field, if present, or the Amount field otherwise.

The field is only returned when metadata is available and the data is not
returned in binary format.
This commit is contained in:
Nik Bougalis
2014-12-30 16:55:54 -08:00
parent 98d5eefc86
commit 07737c6e5b
7 changed files with 132 additions and 55 deletions

View File

@@ -3090,6 +3090,9 @@
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\impl\Tuning.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\rpc\impl\Utilities.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\rpc\impl\WriteJson.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>

View File

@@ -4194,6 +4194,9 @@
<ClInclude Include="..\..\src\ripple\rpc\impl\Tuning.h">
<Filter>ripple\rpc\impl</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\rpc\impl\Utilities.cpp">
<Filter>ripple\rpc\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\rpc\impl\WriteJson.cpp">
<Filter>ripple\rpc\impl</Filter>
</ClCompile>

View File

@@ -68,6 +68,7 @@ JSS ( converge_time_s );
JSS ( currency );
JSS ( data );
JSS ( date );
JSS ( delivered_amount );
JSS ( engine_result );
JSS ( engine_result_code );
JSS ( engine_result_message );

View File

@@ -110,15 +110,15 @@ Json::Value doAccountTx (RPC::Context& context)
{
Json::Value& jvObj = jvTxns.append (Json::objectValue);
std::uint32_t uLedgerIndex = std::get<2> (it);
jvObj["tx_blob"] = std::get<0> (it);
jvObj["meta"] = std::get<1> (it);
jvObj["ledger_index"] = uLedgerIndex;
jvObj[jss::validated]
= bValidated
&& uValidatedMin <= uLedgerIndex
&& uValidatedMax >= uLedgerIndex;
std::uint32_t uLedgerIndex = std::get<2> (it);
jvObj["ledger_index"] = uLedgerIndex;
jvObj[jss::validated] = bValidated &&
uValidatedMin <= uLedgerIndex &&
uValidatedMax >= uLedgerIndex;
}
}
else
@@ -136,13 +136,15 @@ Json::Value doAccountTx (RPC::Context& context)
if (it.second)
{
auto meta = it.second->getJson (1);
addPaymentDeliveredAmount (meta, context, it.first, it.second);
jvObj[jss::meta] = meta;
std::uint32_t uLedgerIndex = it.second->getLgrSeq ();
jvObj[jss::meta] = it.second->getJson (0);
jvObj[jss::validated]
= bValidated
&& uValidatedMin <= uLedgerIndex
&& uValidatedMax >= uLedgerIndex;
jvObj[jss::validated] = bValidated &&
uValidatedMin <= uLedgerIndex &&
uValidatedMax >= uLedgerIndex;
}
}

View File

@@ -17,7 +17,6 @@
*/
//==============================================================================
namespace ripple {
// {
@@ -31,60 +30,53 @@ Json::Value doTx (RPC::Context& context)
bool binary = context.params.isMember (jss::binary)
&& context.params[jss::binary].asBool ();
std::string strTransaction = context.params[jss::transaction].asString ();
auto const txid = context.params[jss::transaction].asString ();
if (Transaction::isHexTxID (strTransaction))
if (!Transaction::isHexTxID (txid))
return rpcError (rpcNOT_IMPL);
auto txn = getApp().getMasterTransaction ().fetch (uint256 (txid), true);
if (!txn)
return rpcError (rpcTXN_NOT_FOUND);
Json::Value ret = txn->getJson (1, binary);
if (txn->getLedger () == 0)
return ret;
if (auto lgr = context.netOps.getLedgerBySeq (txn->getLedger ()))
{
// transaction by ID
uint256 txid (strTransaction);
bool okay = false;
auto txn = getApp().getMasterTransaction ().fetch (txid, true);
if (!txn)
return rpcError (rpcTXN_NOT_FOUND);
#ifdef READY_FOR_NEW_TX_FORMAT
// TODO(tom): what new format is this?
Json::Value ret;
ret[jss::transaction] = txn->getJson (1, binary);
#else
Json::Value ret = txn->getJson (1, binary);
#endif
if (txn->getLedger () != 0)
if (binary)
{
if (auto lgr = context.netOps.getLedgerBySeq (txn->getLedger ()))
std::string meta;
if (lgr->getMetaHex (txn->getID (), meta))
{
bool okay = false;
if (binary)
{
std::string meta;
ret[jss::meta] = meta;
okay = true;
}
}
else
{
TransactionMetaSet::pointer txMeta;
if (lgr->getMetaHex (txid, meta))
{
ret[jss::meta] = meta;
okay = true;
}
}
else
{
TransactionMetaSet::pointer set;
if (lgr->getTransactionMeta (txid, set))
{
okay = true;
ret[jss::meta] = set->getJson (0);
}
}
if (okay)
ret[jss::validated] = context.netOps.isValidated (lgr);
if (lgr->getTransactionMeta (txn->getID (), txMeta))
{
okay = true;
auto meta = txMeta->getJson (0);
addPaymentDeliveredAmount (meta, context, txn, txMeta);
ret[jss::meta] = meta;
}
}
return ret;
if (okay)
ret[jss::validated] = context.netOps.isValidated (lgr);
}
return rpcError (rpcNOT_IMPL);
return ret;
}
} // ripple

View File

@@ -0,0 +1,75 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include "boost/date_time/posix_time/posix_time.hpp"
#include <utility>
namespace ripple {
namespace RPC {
void
addPaymentDeliveredAmount (
Json::Value& meta,
RPC::Context& context,
Transaction::pointer transaction,
TransactionMetaSet::pointer transactionMeta)
{
STTx::pointer serializedTx;
if (transaction)
serializedTx = transaction->getSTransaction ();
if (serializedTx && serializedTx->getTxnType () == ttPAYMENT)
{
// If the transaction explicitly specifies a DeliveredAmount in the
// metadata then we use it.
if (transactionMeta && transactionMeta->hasDeliveredAmount ())
{
meta[jss::delivered_amount] =
transactionMeta->getDeliveredAmount ().getJson (1);
return;
}
if (auto ledger = context.netOps.getLedgerBySeq (transaction->getLedger ()))
{
// The first ledger where the DeliveredAmount flag appears is
// which closed on 2014-Jan-24 at 04:50:10. If the transaction we
// are dealing with is in a ledger that closed after this date then
// the absence of DeliveredAmount indicates that the correct amount
// is in the Amount field.
boost::posix_time::ptime const cutoff (
boost::posix_time::time_from_string ("2014-01-24 04:50:10"));
if (ledger->getCloseTime () >= cutoff)
{
meta[jss::delivered_amount] =
serializedTx->getFieldAmount (sfAmount).getJson (1);
return;
}
}
// Otherwise we report "unavailable" which cannot be parsed into a
// sensible amount.
meta[jss::delivered_amount] = Json::Value ("unavailable");
}
}
}
}

View File

@@ -33,6 +33,7 @@
#include <ripple/rpc/impl/RPCHandler.cpp>
#include <ripple/rpc/impl/Status.cpp>
#include <ripple/rpc/impl/Yield.cpp>
#include <ripple/rpc/impl/Utilities.cpp>
#include <ripple/rpc/handlers/Handlers.h>
#include <ripple/rpc/handlers/AccountCurrencies.cpp>