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