rippled
Loading...
Searching...
No Matches
AccountOffers.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/ledger/ReadView.h>
21#include <xrpld/ledger/View.h>
22#include <xrpld/rpc/Context.h>
23#include <xrpld/rpc/detail/RPCHelpers.h>
24#include <xrpld/rpc/detail/Tuning.h>
25
26#include <xrpl/json/json_value.h>
27#include <xrpl/protocol/ErrorCodes.h>
28#include <xrpl/protocol/RPCErr.h>
29#include <xrpl/protocol/jss.h>
30#include <xrpl/resource/Fees.h>
31
32namespace ripple {
33
34void
36{
37 STAmount dirRate =
38 amountFromQuality(getQuality(offer->getFieldH256(sfBookDirectory)));
39 Json::Value& obj(offers.append(Json::objectValue));
40 offer->getFieldAmount(sfTakerPays).setJson(obj[jss::taker_pays]);
41 offer->getFieldAmount(sfTakerGets).setJson(obj[jss::taker_gets]);
42 obj[jss::seq] = offer->getFieldU32(sfSequence);
43 obj[jss::flags] = offer->getFieldU32(sfFlags);
44 obj[jss::quality] = dirRate.getText();
45 if (offer->isFieldPresent(sfExpiration))
46 obj[jss::expiration] = offer->getFieldU32(sfExpiration);
47};
48
49// {
50// account: <account>
51// ledger_hash : <ledger>
52// ledger_index : <ledger_index>
53// limit: integer // optional
54// marker: opaque // optional, resume previous query
55// }
58{
59 auto const& params(context.params);
60 if (!params.isMember(jss::account))
61 return RPC::missing_field_error(jss::account);
62
63 if (!params[jss::account].isString())
64 return RPC::invalid_field_error(jss::account);
65
67 auto result = RPC::lookupLedger(ledger, context);
68 if (!ledger)
69 return result;
70
71 auto id = parseBase58<AccountID>(params[jss::account].asString());
72 if (!id)
73 {
75 return result;
76 }
77 auto const accountID{std::move(id.value())};
78
79 // Get info on account.
80 result[jss::account] = toBase58(accountID);
81
82 if (!ledger->exists(keylet::account(accountID)))
84
85 unsigned int limit;
86 if (auto err = readLimitField(limit, RPC::Tuning::accountOffers, context))
87 return *err;
88
89 if (limit == 0)
90 return RPC::invalid_field_error(jss::limit);
91
92 Json::Value& jsonOffers(result[jss::offers] = Json::arrayValue);
94 uint256 startAfter = beast::zero;
95 std::uint64_t startHint = 0;
96
97 if (params.isMember(jss::marker))
98 {
99 if (!params[jss::marker].isString())
100 return RPC::expected_field_error(jss::marker, "string");
101
102 // Marker is composed of a comma separated index and start hint. The
103 // former will be read as hex, and the latter using boost lexical cast.
104 std::stringstream marker(params[jss::marker].asString());
105 std::string value;
106 if (!std::getline(marker, value, ','))
107 return RPC::invalid_field_error(jss::marker);
108
109 if (!startAfter.parseHex(value))
110 return RPC::invalid_field_error(jss::marker);
111
112 if (!std::getline(marker, value, ','))
113 return RPC::invalid_field_error(jss::marker);
114
115 try
116 {
117 startHint = boost::lexical_cast<std::uint64_t>(value);
118 }
119 catch (boost::bad_lexical_cast&)
120 {
121 return RPC::invalid_field_error(jss::marker);
122 }
123
124 // We then must check if the object pointed to by the marker is actually
125 // owned by the account in the request.
126 auto const sle = ledger->read({ltANY, startAfter});
127
128 if (!sle)
130
131 if (!RPC::isRelatedToAccount(*ledger, sle, accountID))
133 }
134
135 auto count = 0;
136 std::optional<uint256> marker = {};
137 std::uint64_t nextHint = 0;
138 if (!forEachItemAfter(
139 *ledger,
140 accountID,
141 startAfter,
142 startHint,
143 limit + 1,
144 [&offers, &count, &marker, &limit, &nextHint, &accountID](
145 std::shared_ptr<SLE const> const& sle) {
146 if (!sle)
147 {
148 UNREACHABLE("ripple::doAccountOffers : null SLE");
149 return false;
150 }
151
152 if (++count == limit)
153 {
154 marker = sle->key();
155 nextHint = RPC::getStartHint(sle, accountID);
156 }
157
158 if (count <= limit && sle->getType() == ltOFFER)
159 {
160 offers.emplace_back(sle);
161 }
162
163 return true;
164 }))
165 {
167 }
168
169 // Both conditions need to be checked because marker is set on the limit-th
170 // item, but if there is no item on the limit + 1 iteration, then there is
171 // no need to return a marker.
172 if (count == limit + 1 && marker)
173 {
174 result[jss::limit] = limit;
175 result[jss::marker] =
176 to_string(*marker) + "," + std::to_string(nextHint);
177 }
178
179 for (auto const& offer : offers)
180 appendOfferJson(offer, jsonOffers);
181
183 return result;
184}
185
186} // namespace ripple
Represents a JSON value.
Definition: json_value.h:148
std::string getText() const override
Definition: STAmount.cpp:547
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:503
T getline(T... args)
@ arrayValue
array value (ordered list)
Definition: json_value.h:43
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:44
static LimitRange constexpr accountOffers
Limits for the account_offers command.
Json::Value invalid_field_error(std::string const &name)
Definition: ErrorCodes.h:315
bool isRelatedToAccount(ReadView const &ledger, std::shared_ptr< SLE const > const &sle, AccountID const &accountID)
Tests if a SLE is owned by accountID.
Definition: RPCHelpers.cpp:115
void inject_error(error_code_i code, JsonValue &json)
Add or update the json update to reflect the error code.
Definition: ErrorCodes.h:223
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
std::uint64_t getStartHint(std::shared_ptr< SLE const > const &sle, AccountID const &accountID)
Gets the start hint for traversing account objects.
Definition: RPCHelpers.cpp:98
Json::Value missing_field_error(std::string const &name)
Definition: ErrorCodes.h:273
Charge const feeMediumBurdenRPC
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:176
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:114
std::uint64_t getQuality(uint256 const &uBase)
Definition: Indexes.cpp:141
@ rpcACT_NOT_FOUND
Definition: ErrorCodes.h:70
@ rpcACT_MALFORMED
Definition: ErrorCodes.h:90
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:84
STAmount amountFromQuality(std::uint64_t rate)
Definition: STAmount.cpp:854
Json::Value rpcError(int iError)
Definition: RPCErr.cpp:31
Json::Value doAccountOffers(RPC::JsonContext &context)
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:630
@ ltANY
A special type, matching any ledger entry type.
Definition: LedgerFormats.h:78
bool forEachItemAfter(ReadView const &view, Keylet const &root, uint256 const &after, std::uint64_t const hint, unsigned int limit, std::function< bool(std::shared_ptr< SLE const > const &)> const &f)
Iterate all items after an item in the given directory.
Definition: View.cpp:572
void appendOfferJson(std::shared_ptr< SLE const > const &offer, Json::Value &offers)
Resource::Charge & loadType
Definition: Context.h:42
Json::Value params
Definition: Context.h:63
T to_string(T... args)