rippled
Loading...
Searching...
No Matches
DeliveredAmount.cpp
1#include <xrpld/app/ledger/LedgerMaster.h>
2#include <xrpld/app/ledger/OpenLedger.h>
3#include <xrpld/app/misc/Transaction.h>
4#include <xrpld/rpc/Context.h>
5#include <xrpld/rpc/DeliveredAmount.h>
6
7#include <xrpl/protocol/Feature.h>
8#include <xrpl/protocol/RPCErr.h>
9
10namespace xrpl {
11namespace RPC {
12
13/*
14 GetLedgerIndex and GetCloseTime are lambdas that allow the close time and
15 ledger index to be lazily calculated. Without these lambdas, these values
16 would be calculated even when not needed, and in some circumstances they are
17 not trivial to compute.
18
19 GetLedgerIndex is a callable that returns a LedgerIndex
20 GetCloseTime is a callable that returns a
21 std::optional<NetClock::time_point>
22 */
23template <class GetLedgerIndex, class GetCloseTime>
26 GetLedgerIndex const& getLedgerIndex,
27 GetCloseTime const& getCloseTime,
28 std::shared_ptr<STTx const> const& serializedTx,
29 TxMeta const& transactionMeta)
30{
31 if (!serializedTx)
32 return {};
33
34 if (auto const& deliveredAmount = transactionMeta.getDeliveredAmount(); deliveredAmount.has_value())
35 {
36 return *deliveredAmount;
37 }
38
39 if (serializedTx->isFieldPresent(sfAmount))
40 {
41 using namespace std::chrono_literals;
42
43 // Ledger 4594095 is the first ledger in which the DeliveredAmount field
44 // was present when a partial payment was made and its absence indicates
45 // that the amount delivered is listed in the Amount field.
46 //
47 // If the ledger closed long after the DeliveredAmount code was deployed
48 // then its absence indicates that the amount delivered is listed in the
49 // Amount field. DeliveredAmount went live January 24, 2014.
50 // 446000000 is in Feb 2014, well after DeliveredAmount went live
51 if (getLedgerIndex() >= 4594095 || getCloseTime() > NetClock::time_point{446000000s})
52 {
53 return serializedTx->getFieldAmount(sfAmount);
54 }
55 }
56
57 return {};
58}
59
60// Returns true if transaction meta could contain a delivered amount field,
61// based on transaction type and transaction result
62bool
63canHaveDeliveredAmount(std::shared_ptr<STTx const> const& serializedTx, TxMeta const& transactionMeta)
64{
65 if (!serializedTx)
66 return false;
67
68 TxType const tt{serializedTx->getTxnType()};
69 // Transaction type should be ttPAYMENT, ttACCOUNT_DELETE or ttCHECK_CASH
70 // and if the transaction failed nothing could have been delivered.
71 if ((tt == ttPAYMENT || tt == ttCHECK_CASH || tt == ttACCOUNT_DELETE) &&
72 transactionMeta.getResultTER() == tesSUCCESS)
73 {
74 return true;
75 }
76
77 return false;
78}
79
80void
82 Json::Value& meta,
83 ReadView const& ledger,
84 std::shared_ptr<STTx const> const& serializedTx,
85 TxMeta const& transactionMeta)
86{
87 auto const info = ledger.header();
88
89 if (canHaveDeliveredAmount(serializedTx, transactionMeta))
90 {
91 auto const getLedgerIndex = [&info] { return info.seq; };
92 auto const getCloseTime = [&info] { return info.closeTime; };
93
94 auto amt = getDeliveredAmount(getLedgerIndex, getCloseTime, serializedTx, transactionMeta);
95 if (amt)
96 {
97 meta[jss::delivered_amount] = amt->getJson(JsonOptions::include_date);
98 }
99 else
100 {
101 // report "unavailable" which cannot be parsed into a sensible
102 // amount.
103 meta[jss::delivered_amount] = Json::Value("unavailable");
104 }
105 }
106}
107
108template <class GetLedgerIndex>
111 RPC::Context const& context,
112 std::shared_ptr<STTx const> const& serializedTx,
113 TxMeta const& transactionMeta,
114 GetLedgerIndex const& getLedgerIndex)
115{
116 if (canHaveDeliveredAmount(serializedTx, transactionMeta))
117 {
118 auto const getCloseTime = [&context, &getLedgerIndex]() -> std::optional<NetClock::time_point> {
119 return context.ledgerMaster.getCloseTimeBySeq(getLedgerIndex());
120 };
121 return getDeliveredAmount(getLedgerIndex, getCloseTime, serializedTx, transactionMeta);
122 }
123
124 return {};
125}
126
129 RPC::Context const& context,
130 std::shared_ptr<STTx const> const& serializedTx,
131 TxMeta const& transactionMeta,
132 LedgerIndex const& ledgerIndex)
133{
134 return getDeliveredAmount(context, serializedTx, transactionMeta, [&ledgerIndex]() { return ledgerIndex; });
135}
136
137void
139 Json::Value& meta,
140 RPC::JsonContext const& context,
141 std::shared_ptr<Transaction> const& transaction,
142 TxMeta const& transactionMeta)
143{
144 insertDeliveredAmount(meta, context, transaction->getSTransaction(), transactionMeta);
145}
146
147void
149 Json::Value& meta,
150 RPC::JsonContext const& context,
151 std::shared_ptr<STTx const> const& transaction,
152 TxMeta const& transactionMeta)
153{
154 if (canHaveDeliveredAmount(transaction, transactionMeta))
155 {
156 auto amt = getDeliveredAmount(
157 context, transaction, transactionMeta, [&transactionMeta]() { return transactionMeta.getLgrSeq(); });
158
159 if (amt)
160 {
161 meta[jss::delivered_amount] = amt->getJson(JsonOptions::include_date);
162 }
163 else
164 {
165 // report "unavailable" which cannot be parsed into a sensible
166 // amount.
167 meta[jss::delivered_amount] = Json::Value("unavailable");
168 }
169 }
170}
171
172} // namespace RPC
173} // namespace xrpl
Represents a JSON value.
Definition json_value.h:130
std::optional< NetClock::time_point > getCloseTimeBySeq(LedgerIndex ledgerIndex)
A view into a ledger.
Definition ReadView.h:31
virtual LedgerHeader const & header() const =0
Returns information about the ledger.
TER getResultTER() const
Definition TxMeta.h:37
std::optional< STAmount > const & getDeliveredAmount() const
Definition TxMeta.h:90
std::uint32_t getLgrSeq() const
Definition TxMeta.h:27
std::optional< STAmount > getDeliveredAmount(RPC::Context const &context, std::shared_ptr< STTx const > const &serializedTx, TxMeta const &transactionMeta, LedgerIndex const &ledgerIndex)
bool canHaveDeliveredAmount(std::shared_ptr< STTx const > const &serializedTx, TxMeta const &transactionMeta)
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.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
TxType
Transaction type identifiers.
Definition TxFormats.h:37
@ tesSUCCESS
Definition TER.h:225
The context of information needed to call an RPC.
Definition Context.h:19
LedgerMaster & ledgerMaster
Definition Context.h:24