rippled
Loading...
Searching...
No Matches
BookOffers.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012-2014 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpld/app/main/Application.h>
21#include <xrpld/app/misc/NetworkOPs.h>
22#include <xrpld/ledger/ReadView.h>
23#include <xrpld/rpc/BookChanges.h>
24#include <xrpld/rpc/Context.h>
25#include <xrpld/rpc/detail/RPCHelpers.h>
26
27#include <xrpl/basics/Log.h>
28#include <xrpl/protocol/ErrorCodes.h>
29#include <xrpl/protocol/RPCErr.h>
30#include <xrpl/protocol/UintTypes.h>
31#include <xrpl/protocol/jss.h>
32#include <xrpl/resource/Fees.h>
33
34namespace ripple {
35
38{
39 // VFALCO TODO Here is a terrible place for this kind of business
40 // logic. It needs to be moved elsewhere and documented,
41 // and encapsulated into a function.
42 if (context.app.getJobQueue().getJobCountGE(jtCLIENT) > 200)
43 return rpcError(rpcTOO_BUSY);
44
46 auto jvResult = RPC::lookupLedger(lpLedger, context);
47
48 if (!lpLedger)
49 return jvResult;
50
51 if (!context.params.isMember(jss::taker_pays))
52 return RPC::missing_field_error(jss::taker_pays);
53
54 if (!context.params.isMember(jss::taker_gets))
55 return RPC::missing_field_error(jss::taker_gets);
56
57 Json::Value const& taker_pays = context.params[jss::taker_pays];
58 Json::Value const& taker_gets = context.params[jss::taker_gets];
59
60 if (!taker_pays.isObjectOrNull())
61 return RPC::object_field_error(jss::taker_pays);
62
63 if (!taker_gets.isObjectOrNull())
64 return RPC::object_field_error(jss::taker_gets);
65
66 if (!taker_pays.isMember(jss::currency))
67 return RPC::missing_field_error("taker_pays.currency");
68
69 if (!taker_pays[jss::currency].isString())
70 return RPC::expected_field_error("taker_pays.currency", "string");
71
72 if (!taker_gets.isMember(jss::currency))
73 return RPC::missing_field_error("taker_gets.currency");
74
75 if (!taker_gets[jss::currency].isString())
76 return RPC::expected_field_error("taker_gets.currency", "string");
77
78 Currency pay_currency;
79
80 if (!to_currency(pay_currency, taker_pays[jss::currency].asString()))
81 {
82 JLOG(context.j.info()) << "Bad taker_pays currency.";
83 return RPC::make_error(
85 "Invalid field 'taker_pays.currency', bad currency.");
86 }
87
88 Currency get_currency;
89
90 if (!to_currency(get_currency, taker_gets[jss::currency].asString()))
91 {
92 JLOG(context.j.info()) << "Bad taker_gets currency.";
93 return RPC::make_error(
95 "Invalid field 'taker_gets.currency', bad currency.");
96 }
97
98 AccountID pay_issuer;
99
100 if (taker_pays.isMember(jss::issuer))
101 {
102 if (!taker_pays[jss::issuer].isString())
103 return RPC::expected_field_error("taker_pays.issuer", "string");
104
105 if (!to_issuer(pay_issuer, taker_pays[jss::issuer].asString()))
106 return RPC::make_error(
108 "Invalid field 'taker_pays.issuer', bad issuer.");
109
110 if (pay_issuer == noAccount())
111 return RPC::make_error(
113 "Invalid field 'taker_pays.issuer', bad issuer account one.");
114 }
115 else
116 {
117 pay_issuer = xrpAccount();
118 }
119
120 if (isXRP(pay_currency) && !isXRP(pay_issuer))
121 return RPC::make_error(
123 "Unneeded field 'taker_pays.issuer' for "
124 "XRP currency specification.");
125
126 if (!isXRP(pay_currency) && isXRP(pay_issuer))
127 return RPC::make_error(
129 "Invalid field 'taker_pays.issuer', expected non-XRP issuer.");
130
131 AccountID get_issuer;
132
133 if (taker_gets.isMember(jss::issuer))
134 {
135 if (!taker_gets[jss::issuer].isString())
136 return RPC::expected_field_error("taker_gets.issuer", "string");
137
138 if (!to_issuer(get_issuer, taker_gets[jss::issuer].asString()))
139 return RPC::make_error(
141 "Invalid field 'taker_gets.issuer', bad issuer.");
142
143 if (get_issuer == noAccount())
144 return RPC::make_error(
146 "Invalid field 'taker_gets.issuer', bad issuer account one.");
147 }
148 else
149 {
150 get_issuer = xrpAccount();
151 }
152
153 if (isXRP(get_currency) && !isXRP(get_issuer))
154 return RPC::make_error(
156 "Unneeded field 'taker_gets.issuer' for "
157 "XRP currency specification.");
158
159 if (!isXRP(get_currency) && isXRP(get_issuer))
160 return RPC::make_error(
162 "Invalid field 'taker_gets.issuer', expected non-XRP issuer.");
163
165 if (context.params.isMember(jss::taker))
166 {
167 if (!context.params[jss::taker].isString())
168 return RPC::expected_field_error(jss::taker, "string");
169
170 takerID = parseBase58<AccountID>(context.params[jss::taker].asString());
171 if (!takerID)
172 return RPC::invalid_field_error(jss::taker);
173 }
174
175 if (pay_currency == get_currency && pay_issuer == get_issuer)
176 {
177 JLOG(context.j.info()) << "taker_gets same as taker_pays.";
179 }
180
181 unsigned int limit;
182 if (auto err = readLimitField(limit, RPC::Tuning::bookOffers, context))
183 return *err;
184
185 bool const bProof(context.params.isMember(jss::proof));
186
187 Json::Value const jvMarker(
188 context.params.isMember(jss::marker) ? context.params[jss::marker]
190
191 context.netOps.getBookPage(
192 lpLedger,
193 {{pay_currency, pay_issuer}, {get_currency, get_issuer}},
194 takerID ? *takerID : beast::zero,
195 bProof,
196 limit,
197 jvMarker,
198 jvResult);
199
201
202 return jvResult;
203}
204
207{
209
210 Json::Value result = RPC::lookupLedger(ledger, context);
211 if (ledger == nullptr)
212 return result;
213
214 return RPC::computeBookChanges(ledger);
215}
216
217} // namespace ripple
Represents a JSON value.
Definition: json_value.h:148
bool isObjectOrNull() const
bool isString() const
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:475
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:949
Stream info() const
Definition: Journal.h:334
virtual JobQueue & getJobQueue()=0
int getJobCountGE(JobType t) const
All waiting jobs at or greater than this priority.
Definition: JobQueue.cpp:162
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
@ nullValue
'null' value
Definition: json_value.h:37
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.
Definition: ErrorCodes.cpp:185
Json::Value computeBookChanges(std::shared_ptr< L const > const &lpAccepted)
Definition: BookChanges.h:47
Json::Value invalid_field_error(std::string const &name)
Definition: ErrorCodes.h:315
Json::Value object_field_error(std::string const &name)
Definition: ErrorCodes.h:291
Json::Value expected_field_error(std::string const &name, std::string const &type)
Definition: ErrorCodes.h:339
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.
Definition: RPCHelpers.cpp:622
Json::Value missing_field_error(std::string const &name)
Definition: ErrorCodes.h:273
Charge const feeMediumBurdenRPC
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
AccountID const & noAccount()
A placeholder for empty accounts.
Definition: AccountID.cpp:185
bool isXRP(AccountID const &c)
Definition: AccountID.h:91
AccountID const & xrpAccount()
Compute AccountID from public key.
Definition: AccountID.cpp:178
bool to_issuer(AccountID &, std::string const &)
Convert hex or base58 string to AccountID.
Definition: AccountID.cpp:192
@ rpcTOO_BUSY
Definition: ErrorCodes.h:56
@ rpcBAD_MARKET
Definition: ErrorCodes.h:97
@ rpcDST_ISR_MALFORMED
Definition: ErrorCodes.h:108
@ rpcSRC_ISR_MALFORMED
Definition: ErrorCodes.h:125
@ rpcDST_AMT_MALFORMED
Definition: ErrorCodes.h:106
@ rpcSRC_CUR_MALFORMED
Definition: ErrorCodes.h:124
Json::Value doBookChanges(RPC::JsonContext &context)
Definition: BookOffers.cpp:206
Json::Value rpcError(int iError)
Definition: RPCErr.cpp:31
Json::Value doBookOffers(RPC::JsonContext &context)
Definition: BookOffers.cpp:37
@ jtCLIENT
Definition: Job.h:45
bool to_currency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.
Definition: UintTypes.cpp:84
Resource::Charge & loadType
Definition: Context.h:42
Application & app
Definition: Context.h:41
beast::Journal const j
Definition: Context.h:40
NetworkOPs & netOps
Definition: Context.h:43
Json::Value params
Definition: Context.h:63