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#include <xrpl/basics/Log.h>
27#include <xrpl/protocol/ErrorCodes.h>
28#include <xrpl/protocol/RPCErr.h>
29#include <xrpl/protocol/UintTypes.h>
30#include <xrpl/protocol/jss.h>
31#include <xrpl/resource/Fees.h>
32
33namespace ripple {
34
37{
38 // VFALCO TODO Here is a terrible place for this kind of business
39 // logic. It needs to be moved elsewhere and documented,
40 // and encapsulated into a function.
41 if (context.app.getJobQueue().getJobCountGE(jtCLIENT) > 200)
42 return rpcError(rpcTOO_BUSY);
43
45 auto jvResult = RPC::lookupLedger(lpLedger, context);
46
47 if (!lpLedger)
48 return jvResult;
49
50 if (!context.params.isMember(jss::taker_pays))
51 return RPC::missing_field_error(jss::taker_pays);
52
53 if (!context.params.isMember(jss::taker_gets))
54 return RPC::missing_field_error(jss::taker_gets);
55
56 Json::Value const& taker_pays = context.params[jss::taker_pays];
57 Json::Value const& taker_gets = context.params[jss::taker_gets];
58
59 if (!taker_pays.isObjectOrNull())
60 return RPC::object_field_error(jss::taker_pays);
61
62 if (!taker_gets.isObjectOrNull())
63 return RPC::object_field_error(jss::taker_gets);
64
65 if (!taker_pays.isMember(jss::currency))
66 return RPC::missing_field_error("taker_pays.currency");
67
68 if (!taker_pays[jss::currency].isString())
69 return RPC::expected_field_error("taker_pays.currency", "string");
70
71 if (!taker_gets.isMember(jss::currency))
72 return RPC::missing_field_error("taker_gets.currency");
73
74 if (!taker_gets[jss::currency].isString())
75 return RPC::expected_field_error("taker_gets.currency", "string");
76
77 Currency pay_currency;
78
79 if (!to_currency(pay_currency, taker_pays[jss::currency].asString()))
80 {
81 JLOG(context.j.info()) << "Bad taker_pays currency.";
82 return RPC::make_error(
84 "Invalid field 'taker_pays.currency', bad currency.");
85 }
86
87 Currency get_currency;
88
89 if (!to_currency(get_currency, taker_gets[jss::currency].asString()))
90 {
91 JLOG(context.j.info()) << "Bad taker_gets currency.";
92 return RPC::make_error(
94 "Invalid field 'taker_gets.currency', bad currency.");
95 }
96
97 AccountID pay_issuer;
98
99 if (taker_pays.isMember(jss::issuer))
100 {
101 if (!taker_pays[jss::issuer].isString())
102 return RPC::expected_field_error("taker_pays.issuer", "string");
103
104 if (!to_issuer(pay_issuer, taker_pays[jss::issuer].asString()))
105 return RPC::make_error(
107 "Invalid field 'taker_pays.issuer', bad issuer.");
108
109 if (pay_issuer == noAccount())
110 return RPC::make_error(
112 "Invalid field 'taker_pays.issuer', bad issuer account one.");
113 }
114 else
115 {
116 pay_issuer = xrpAccount();
117 }
118
119 if (isXRP(pay_currency) && !isXRP(pay_issuer))
120 return RPC::make_error(
122 "Unneeded field 'taker_pays.issuer' for "
123 "XRP currency specification.");
124
125 if (!isXRP(pay_currency) && isXRP(pay_issuer))
126 return RPC::make_error(
128 "Invalid field 'taker_pays.issuer', expected non-XRP issuer.");
129
130 AccountID get_issuer;
131
132 if (taker_gets.isMember(jss::issuer))
133 {
134 if (!taker_gets[jss::issuer].isString())
135 return RPC::expected_field_error("taker_gets.issuer", "string");
136
137 if (!to_issuer(get_issuer, taker_gets[jss::issuer].asString()))
138 return RPC::make_error(
140 "Invalid field 'taker_gets.issuer', bad issuer.");
141
142 if (get_issuer == noAccount())
143 return RPC::make_error(
145 "Invalid field 'taker_gets.issuer', bad issuer account one.");
146 }
147 else
148 {
149 get_issuer = xrpAccount();
150 }
151
152 if (isXRP(get_currency) && !isXRP(get_issuer))
153 return RPC::make_error(
155 "Unneeded field 'taker_gets.issuer' for "
156 "XRP currency specification.");
157
158 if (!isXRP(get_currency) && isXRP(get_issuer))
159 return RPC::make_error(
161 "Invalid field 'taker_gets.issuer', expected non-XRP issuer.");
162
164 if (context.params.isMember(jss::taker))
165 {
166 if (!context.params[jss::taker].isString())
167 return RPC::expected_field_error(jss::taker, "string");
168
169 takerID = parseBase58<AccountID>(context.params[jss::taker].asString());
170 if (!takerID)
171 return RPC::invalid_field_error(jss::taker);
172 }
173
174 if (pay_currency == get_currency && pay_issuer == get_issuer)
175 {
176 JLOG(context.j.info()) << "taker_gets same as taker_pays.";
178 }
179
180 unsigned int limit;
181 if (auto err = readLimitField(limit, RPC::Tuning::bookOffers, context))
182 return *err;
183
184 bool const bProof(context.params.isMember(jss::proof));
185
186 Json::Value const jvMarker(
187 context.params.isMember(jss::marker) ? context.params[jss::marker]
189
190 context.netOps.getBookPage(
191 lpLedger,
192 {{pay_currency, pay_issuer}, {get_currency, get_issuer}},
193 takerID ? *takerID : beast::zero,
194 bProof,
195 limit,
196 jvMarker,
197 jvResult);
198
200
201 return jvResult;
202}
203
206{
208
209 Json::Value result = RPC::lookupLedger(ledger, context);
210 if (ledger == nullptr)
211 return result;
212
213 return RPC::computeBookChanges(ledger);
214}
215
216} // namespace ripple
Represents a JSON value.
Definition: json_value.h:147
bool isObjectOrNull() const
bool isString() const
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:943
Stream info() const
Definition: Journal.h:323
virtual JobQueue & getJobQueue()=0
int getJobCountGE(JobType t) const
All waiting jobs at or greater than this priority.
Definition: JobQueue.cpp:160
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:36
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:181
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:623
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:177
bool isXRP(AccountID const &c)
Definition: AccountID.h:91
AccountID const & xrpAccount()
Compute AccountID from public key.
Definition: AccountID.cpp:170
bool to_issuer(AccountID &, std::string const &)
Convert hex or base58 string to AccountID.
Definition: AccountID.cpp:184
@ 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:205
Json::Value rpcError(int iError)
Definition: RPCErr.cpp:29
Json::Value doBookOffers(RPC::JsonContext &context)
Definition: BookOffers.cpp:36
@ 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:80
Resource::Charge & loadType
Definition: Context.h:43
Application & app
Definition: Context.h:42
beast::Journal const j
Definition: Context.h:41
NetworkOPs & netOps
Definition: Context.h:44
Json::Value params
Definition: Context.h:64