rippled
Loading...
Searching...
No Matches
BookOffers.cpp
1#include <xrpld/app/main/Application.h>
2#include <xrpld/rpc/Context.h>
3#include <xrpld/rpc/detail/RPCHelpers.h>
4#include <xrpld/rpc/detail/RPCLedgerHelpers.h>
5
6#include <xrpl/basics/Log.h>
7#include <xrpl/ledger/ReadView.h>
8#include <xrpl/protocol/ErrorCodes.h>
9#include <xrpl/protocol/RPCErr.h>
10#include <xrpl/protocol/UintTypes.h>
11#include <xrpl/protocol/jss.h>
12#include <xrpl/resource/Fees.h>
13#include <xrpl/server/NetworkOPs.h>
14
15namespace xrpl {
16
19{
20 // VFALCO TODO Here is a terrible place for this kind of business
21 // logic. It needs to be moved elsewhere and documented,
22 // and encapsulated into a function.
23 if (context.app.getJobQueue().getJobCountGE(jtCLIENT) > 200)
24 return rpcError(rpcTOO_BUSY);
25
27 auto jvResult = RPC::lookupLedger(lpLedger, context);
28
29 if (!lpLedger)
30 return jvResult;
31
32 if (!context.params.isMember(jss::taker_pays))
33 return RPC::missing_field_error(jss::taker_pays);
34
35 if (!context.params.isMember(jss::taker_gets))
36 return RPC::missing_field_error(jss::taker_gets);
37
38 Json::Value const& taker_pays = context.params[jss::taker_pays];
39 Json::Value const& taker_gets = context.params[jss::taker_gets];
40
41 if (!taker_pays.isObjectOrNull())
42 return RPC::object_field_error(jss::taker_pays);
43
44 if (!taker_gets.isObjectOrNull())
45 return RPC::object_field_error(jss::taker_gets);
46
47 if (!taker_pays.isMember(jss::currency))
48 return RPC::missing_field_error("taker_pays.currency");
49
50 if (!taker_pays[jss::currency].isString())
51 return RPC::expected_field_error("taker_pays.currency", "string");
52
53 if (!taker_gets.isMember(jss::currency))
54 return RPC::missing_field_error("taker_gets.currency");
55
56 if (!taker_gets[jss::currency].isString())
57 return RPC::expected_field_error("taker_gets.currency", "string");
58
59 Currency pay_currency;
60
61 if (!to_currency(pay_currency, taker_pays[jss::currency].asString()))
62 {
63 JLOG(context.j.info()) << "Bad taker_pays currency.";
64 return RPC::make_error(
65 rpcSRC_CUR_MALFORMED, "Invalid field 'taker_pays.currency', bad currency.");
66 }
67
68 Currency get_currency;
69
70 if (!to_currency(get_currency, taker_gets[jss::currency].asString()))
71 {
72 JLOG(context.j.info()) << "Bad taker_gets currency.";
73 return RPC::make_error(
74 rpcDST_AMT_MALFORMED, "Invalid field 'taker_gets.currency', bad currency.");
75 }
76
77 AccountID pay_issuer;
78
79 if (taker_pays.isMember(jss::issuer))
80 {
81 if (!taker_pays[jss::issuer].isString())
82 return RPC::expected_field_error("taker_pays.issuer", "string");
83
84 if (!to_issuer(pay_issuer, taker_pays[jss::issuer].asString()))
85 {
86 return RPC::make_error(
87 rpcSRC_ISR_MALFORMED, "Invalid field 'taker_pays.issuer', bad issuer.");
88 }
89
90 if (pay_issuer == noAccount())
91 {
92 return RPC::make_error(
93 rpcSRC_ISR_MALFORMED, "Invalid field 'taker_pays.issuer', bad issuer account one.");
94 }
95 }
96 else
97 {
98 pay_issuer = xrpAccount();
99 }
100
101 if (isXRP(pay_currency) && !isXRP(pay_issuer))
102 {
103 return RPC::make_error(
105 "Unneeded field 'taker_pays.issuer' for "
106 "XRP currency specification.");
107 }
108
109 if (!isXRP(pay_currency) && isXRP(pay_issuer))
110 {
111 return RPC::make_error(
112 rpcSRC_ISR_MALFORMED, "Invalid field 'taker_pays.issuer', expected non-XRP issuer.");
113 }
114
115 AccountID get_issuer;
116
117 if (taker_gets.isMember(jss::issuer))
118 {
119 if (!taker_gets[jss::issuer].isString())
120 return RPC::expected_field_error("taker_gets.issuer", "string");
121
122 if (!to_issuer(get_issuer, taker_gets[jss::issuer].asString()))
123 {
124 return RPC::make_error(
125 rpcDST_ISR_MALFORMED, "Invalid field 'taker_gets.issuer', bad issuer.");
126 }
127
128 if (get_issuer == noAccount())
129 {
130 return RPC::make_error(
131 rpcDST_ISR_MALFORMED, "Invalid field 'taker_gets.issuer', bad issuer account one.");
132 }
133 }
134 else
135 {
136 get_issuer = xrpAccount();
137 }
138
139 if (isXRP(get_currency) && !isXRP(get_issuer))
140 {
141 return RPC::make_error(
143 "Unneeded field 'taker_gets.issuer' for "
144 "XRP currency specification.");
145 }
146
147 if (!isXRP(get_currency) && isXRP(get_issuer))
148 {
149 return RPC::make_error(
150 rpcDST_ISR_MALFORMED, "Invalid field 'taker_gets.issuer', expected non-XRP issuer.");
151 }
152
154 if (context.params.isMember(jss::taker))
155 {
156 if (!context.params[jss::taker].isString())
157 return RPC::expected_field_error(jss::taker, "string");
158
159 takerID = parseBase58<AccountID>(context.params[jss::taker].asString());
160 if (!takerID)
161 return RPC::invalid_field_error(jss::taker);
162 }
163
165 if (context.params.isMember(jss::domain))
166 {
167 uint256 num;
168 if (!context.params[jss::domain].isString() ||
169 !num.parseHex(context.params[jss::domain].asString()))
170 {
171 return RPC::make_error(rpcDOMAIN_MALFORMED, "Unable to parse domain.");
172 }
173
174 domain = num;
175 }
176
177 if (pay_currency == get_currency && pay_issuer == get_issuer)
178 {
179 JLOG(context.j.info()) << "taker_gets same as taker_pays.";
181 }
182
183 unsigned int limit = 0;
184 if (auto err = readLimitField(limit, RPC::Tuning::bookOffers, context))
185 return *err;
186
187 bool const bProof(context.params.isMember(jss::proof));
188
189 Json::Value const jvMarker(
190 context.params.isMember(jss::marker) ? context.params[jss::marker]
192
193 context.netOps.getBookPage(
194 lpLedger,
195 {{pay_currency, pay_issuer}, {get_currency, get_issuer}, domain},
196 takerID ? *takerID : beast::zero,
197 bProof,
198 limit,
199 jvMarker,
200 jvResult);
201
203
204 return jvResult;
205}
206
207} // namespace xrpl
Represents a JSON value.
Definition json_value.h:130
bool isObjectOrNull() const
bool isString() const
std::string asString() const
Returns the unquoted string value.
bool isMember(char const *key) const
Return true if the object has a member named key.
Stream info() const
Definition Journal.h:307
int getJobCountGE(JobType t) const
All waiting jobs at or greater than this priority.
Definition JobQueue.cpp:125
virtual void getBookPage(std::shared_ptr< ReadView const > &lpLedger, Book const &book, AccountID const &uTakerID, bool const bProof, unsigned int iLimit, Json::Value const &jvMarker, Json::Value &jvResult)=0
virtual JobQueue & getJobQueue()=0
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition base_uint.h:476
@ nullValue
'null' value
Definition json_value.h:19
static LimitRange constexpr bookOffers
Limits for the book_offers command.
Json::Value invalid_field_error(std::string const &name)
Definition ErrorCodes.h:273
Json::Value expected_field_error(std::string const &name, std::string const &type)
Definition ErrorCodes.h:297
Json::Value missing_field_error(std::string const &name)
Definition ErrorCodes.h:231
Json::Value object_field_error(std::string const &name)
Definition ErrorCodes.h:249
Status lookupLedger(std::shared_ptr< ReadView const > &ledger, JsonContext const &context, Json::Value &result)
Looks up a ledger from a request and fills a Json::Value with ledger data.
Json::Value make_error(error_code_i code)
Returns a new json object that reflects the error code.
Charge const feeMediumBurdenRPC
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
Json::Value doBookOffers(RPC::JsonContext &)
bool isXRP(AccountID const &c)
Definition AccountID.h:70
@ jtCLIENT
Definition Job.h:24
Json::Value rpcError(error_code_i iError)
Definition RPCErr.cpp:12
bool to_issuer(AccountID &, std::string const &)
Convert hex or base58 string to AccountID.
AccountID const & noAccount()
A placeholder for empty accounts.
AccountID const & xrpAccount()
Compute AccountID from public key.
bool to_currency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.
Definition UintTypes.cpp:64
@ rpcSRC_CUR_MALFORMED
Definition ErrorCodes.h:104
@ rpcTOO_BUSY
Definition ErrorCodes.h:36
@ rpcBAD_MARKET
Definition ErrorCodes.h:77
@ rpcSRC_ISR_MALFORMED
Definition ErrorCodes.h:105
@ rpcDST_AMT_MALFORMED
Definition ErrorCodes.h:86
@ rpcDOMAIN_MALFORMED
Definition ErrorCodes.h:138
@ rpcDST_ISR_MALFORMED
Definition ErrorCodes.h:88
beast::Journal const j
Definition Context.h:20
Application & app
Definition Context.h:21
Resource::Charge & loadType
Definition Context.h:22
NetworkOPs & netOps
Definition Context.h:23
Json::Value params
Definition Context.h:43