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();
35 deliveredAmount.has_value())
36 {
37 return deliveredAmount;
38 }
39
40 if (serializedTx->isFieldPresent(sfAmount))
41 {
42 using namespace std::chrono_literals;
43
44 // Ledger 4594095 is the first ledger in which the DeliveredAmount field
45 // was present when a partial payment was made and its absence indicates
46 // that the amount delivered is listed in the Amount field.
47 //
48 // If the ledger closed long after the DeliveredAmount code was deployed
49 // then its absence indicates that the amount delivered is listed in the
50 // Amount field. DeliveredAmount went live January 24, 2014.
51 // 446000000 is in Feb 2014, well after DeliveredAmount went live
52 if (getLedgerIndex() >= 4594095 || getCloseTime() > NetClock::time_point{446000000s})
53 {
54 return serializedTx->getFieldAmount(sfAmount);
55 }
56 }
57
58 return {};
59}
60
61// Returns true if transaction meta could contain a delivered amount field,
62// based on transaction type and transaction result
63bool
65 std::shared_ptr<STTx const> const& serializedTx,
66 TxMeta const& transactionMeta)
67{
68 if (!serializedTx)
69 return false;
70
71 TxType const tt{serializedTx->getTxnType()};
72 // Transaction type should be ttPAYMENT, ttACCOUNT_DELETE or ttCHECK_CASH
73 // and if the transaction failed nothing could have been delivered.
74 return (tt == ttPAYMENT || tt == ttCHECK_CASH || tt == ttACCOUNT_DELETE) &&
75 transactionMeta.getResultTER() == tesSUCCESS;
76}
77
78void
80 Json::Value& meta,
81 ReadView const& ledger,
82 std::shared_ptr<STTx const> const& serializedTx,
83 TxMeta const& transactionMeta)
84{
85 auto const info = ledger.header();
86
87 if (canHaveDeliveredAmount(serializedTx, transactionMeta))
88 {
89 auto const getLedgerIndex = [&info] { return info.seq; };
90 auto const getCloseTime = [&info] { return info.closeTime; };
91
92 auto amt = getDeliveredAmount(getLedgerIndex, getCloseTime, serializedTx, transactionMeta);
93 if (amt)
94 {
95 meta[jss::delivered_amount] = amt->getJson(JsonOptions::include_date);
96 }
97 else
98 {
99 // report "unavailable" which cannot be parsed into a sensible
100 // amount.
101 meta[jss::delivered_amount] = Json::Value("unavailable");
102 }
103 }
104}
105
106template <class GetLedgerIndex>
109 RPC::Context const& context,
110 std::shared_ptr<STTx const> const& serializedTx,
111 TxMeta const& transactionMeta,
112 GetLedgerIndex const& getLedgerIndex)
113{
114 if (canHaveDeliveredAmount(serializedTx, transactionMeta))
115 {
116 auto const getCloseTime = [&context,
117 &getLedgerIndex]() -> std::optional<NetClock::time_point> {
118 return context.ledgerMaster.getCloseTimeBySeq(getLedgerIndex());
119 };
120 return getDeliveredAmount(getLedgerIndex, getCloseTime, serializedTx, transactionMeta);
121 }
122
123 return {};
124}
125
128 RPC::Context const& context,
129 std::shared_ptr<STTx const> const& serializedTx,
130 TxMeta const& transactionMeta,
131 LedgerIndex const& ledgerIndex)
132{
133 return getDeliveredAmount(
134 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(context, transaction, transactionMeta, [&transactionMeta]() {
157 return transactionMeta.getLgrSeq();
158 });
159
160 if (amt)
161 {
162 meta[jss::delivered_amount] = amt->getJson(JsonOptions::include_date);
163 }
164 else
165 {
166 // report "unavailable" which cannot be parsed into a sensible
167 // amount.
168 meta[jss::delivered_amount] = Json::Value("unavailable");
169 }
170 }
171}
172
173} // namespace RPC
174} // 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:39
@ tesSUCCESS
Definition TER.h:225
The context of information needed to call an RPC.
Definition Context.h:19
LedgerMaster & ledgerMaster
Definition Context.h:24