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 ripple {
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 ||
53 getCloseTime() > NetClock::time_point{446000000s})
54 {
55 return serializedTx->getFieldAmount(sfAmount);
56 }
57 }
58
59 return {};
60}
61
62// Returns true if transaction meta could contain a delivered amount field,
63// based on transaction type and transaction result
64bool
66 std::shared_ptr<STTx const> const& serializedTx,
67 TxMeta const& transactionMeta)
68{
69 if (!serializedTx)
70 return false;
71
72 TxType const tt{serializedTx->getTxnType()};
73 // Transaction type should be ttPAYMENT, ttACCOUNT_DELETE or ttCHECK_CASH
74 // and if the transaction failed nothing could have been delivered.
75 if ((tt == ttPAYMENT || tt == ttCHECK_CASH || tt == ttACCOUNT_DELETE) &&
76 transactionMeta.getResultTER() == tesSUCCESS)
77 {
78 return true;
79 }
80
81 return false;
82}
83
84void
86 Json::Value& meta,
87 ReadView const& ledger,
88 std::shared_ptr<STTx const> const& serializedTx,
89 TxMeta const& transactionMeta)
90{
91 auto const info = ledger.info();
92
93 if (canHaveDeliveredAmount(serializedTx, transactionMeta))
94 {
95 auto const getLedgerIndex = [&info] { return info.seq; };
96 auto const getCloseTime = [&info] { return info.closeTime; };
97
98 auto amt = getDeliveredAmount(
99 getLedgerIndex, getCloseTime, serializedTx, transactionMeta);
100 if (amt)
101 {
102 meta[jss::delivered_amount] =
103 amt->getJson(JsonOptions::include_date);
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 =
125 [&context,
126 &getLedgerIndex]() -> std::optional<NetClock::time_point> {
127 return context.ledgerMaster.getCloseTimeBySeq(getLedgerIndex());
128 };
129 return getDeliveredAmount(
130 getLedgerIndex, getCloseTime, serializedTx, transactionMeta);
131 }
132
133 return {};
134}
135
138 RPC::Context const& context,
139 std::shared_ptr<STTx const> const& serializedTx,
140 TxMeta const& transactionMeta,
141 LedgerIndex const& ledgerIndex)
142{
143 return getDeliveredAmount(
144 context, serializedTx, transactionMeta, [&ledgerIndex]() {
145 return ledgerIndex;
146 });
147}
148
149void
151 Json::Value& meta,
152 RPC::JsonContext const& context,
153 std::shared_ptr<Transaction> const& transaction,
154 TxMeta const& transactionMeta)
155{
157 meta, context, transaction->getSTransaction(), transactionMeta);
158}
159
160void
162 Json::Value& meta,
163 RPC::JsonContext const& context,
164 std::shared_ptr<STTx const> const& transaction,
165 TxMeta const& transactionMeta)
166{
167 if (canHaveDeliveredAmount(transaction, transactionMeta))
168 {
169 auto amt = getDeliveredAmount(
170 context, transaction, transactionMeta, [&transactionMeta]() {
171 return transactionMeta.getLgrSeq();
172 });
173
174 if (amt)
175 {
176 meta[jss::delivered_amount] =
177 amt->getJson(JsonOptions::include_date);
178 }
179 else
180 {
181 // report "unavailable" which cannot be parsed into a sensible
182 // amount.
183 meta[jss::delivered_amount] = Json::Value("unavailable");
184 }
185 }
186}
187
188} // namespace RPC
189} // namespace ripple
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:32
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
std::uint32_t getLgrSeq() const
Definition TxMeta.h:28
TER getResultTER() const
Definition TxMeta.h:38
std::optional< STAmount > const & getDeliveredAmount() const
Definition TxMeta.h:91
std::optional< STAmount > getDeliveredAmount(RPC::Context const &context, std::shared_ptr< STTx const > const &serializedTx, TxMeta const &transactionMeta, LedgerIndex const &ledgerIndex)
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.
bool canHaveDeliveredAmount(std::shared_ptr< STTx const > const &serializedTx, TxMeta const &transactionMeta)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
TxType
Transaction type identifiers.
Definition TxFormats.h:38
@ tesSUCCESS
Definition TER.h:226
The context of information needed to call an RPC.
Definition Context.h:20
LedgerMaster & ledgerMaster
Definition Context.h:25