diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj
index afb4e95513..82ec2e5bf2 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj
+++ b/Builds/VisualStudio2013/RippleD.vcxproj
@@ -3090,6 +3090,9 @@
+
+ True
+
True
diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters
index 73f67976fe..3c51b56bc0 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters
@@ -4194,6 +4194,9 @@
ripple\rpc\impl
+
+ ripple\rpc\impl
+
ripple\rpc\impl
diff --git a/src/ripple/protocol/JsonFields.h b/src/ripple/protocol/JsonFields.h
index c586c1de4c..15f5c1ab54 100644
--- a/src/ripple/protocol/JsonFields.h
+++ b/src/ripple/protocol/JsonFields.h
@@ -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 );
diff --git a/src/ripple/rpc/handlers/AccountTx.cpp b/src/ripple/rpc/handlers/AccountTx.cpp
index 35b0351b61..918a98ad66 100644
--- a/src/ripple/rpc/handlers/AccountTx.cpp
+++ b/src/ripple/rpc/handlers/AccountTx.cpp
@@ -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;
}
}
diff --git a/src/ripple/rpc/handlers/Tx.cpp b/src/ripple/rpc/handlers/Tx.cpp
index 927bdac9c6..3f46fed4fc 100644
--- a/src/ripple/rpc/handlers/Tx.cpp
+++ b/src/ripple/rpc/handlers/Tx.cpp
@@ -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
diff --git a/src/ripple/rpc/impl/Utilities.cpp b/src/ripple/rpc/impl/Utilities.cpp
new file mode 100644
index 0000000000..ca4c7b847d
--- /dev/null
+++ b/src/ripple/rpc/impl/Utilities.cpp
@@ -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
+
+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");
+ }
+}
+
+}
+}
diff --git a/src/ripple/unity/rpcx.cpp b/src/ripple/unity/rpcx.cpp
index fb99addb35..a26d440d5c 100644
--- a/src/ripple/unity/rpcx.cpp
+++ b/src/ripple/unity/rpcx.cpp
@@ -33,6 +33,7 @@
#include
#include
#include
+#include
#include
#include