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