Clio develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
GetAggregatePrice.hpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of clio: https://github.com/XRPLF/clio
4 Copyright (c) 2024, the clio developers.
5
6 Permission to use, copy, modify, and 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#pragma once
21
22#include "data/BackendInterface.hpp"
23#include "rpc/Errors.hpp"
24#include "rpc/JS.hpp"
25#include "rpc/common/MetaProcessors.hpp"
26#include "rpc/common/Modifiers.hpp"
27#include "rpc/common/Specs.hpp"
28#include "rpc/common/Types.hpp"
29#include "rpc/common/Validators.hpp"
30
31#include <boost/asio/spawn.hpp>
32#include <boost/json/array.hpp>
33#include <boost/json/conversion.hpp>
34#include <xrpl/basics/Number.h>
35#include <xrpl/protocol/AccountID.h>
36#include <xrpl/protocol/STAmount.h>
37#include <xrpl/protocol/STObject.h>
38#include <xrpl/protocol/jss.h>
39
40#include <cstdint>
41#include <functional>
42#include <memory>
43#include <optional>
44#include <string>
45#include <string_view>
46#include <utility>
47#include <vector>
48
49namespace rpc {
50
55 std::shared_ptr<BackendInterface> sharedPtrBackend_;
56
57public:
61 struct Stats {
62 ripple::STAmount avg;
63 ripple::Number sd; // standard deviation
64 uint32_t size{0};
65 };
66
70 struct Output {
71 uint32_t time;
72 Stats extireStats;
73 std::optional<Stats> trimStats;
74 std::string ledgerHash;
75 uint32_t ledgerIndex;
76 std::string median;
77 bool validated = true;
78
85 Output(uint32_t time, std::string ledgerHash, uint32_t ledgerIndex)
86 : time(time), ledgerHash(std::move(ledgerHash)), ledgerIndex(ledgerIndex)
87 {
88 }
89 };
90
94 struct Oracle {
95 std::uint32_t documentId{0};
96 ripple::AccountID account;
97 };
98
102 struct Input {
103 std::optional<std::string> ledgerHash;
104 std::optional<std::uint32_t> ledgerIndex;
105 std::vector<Oracle> oracles; // valid range is 1-200
106 std::string baseAsset;
107 std::string quoteAsset;
108 std::optional<std::uint32_t> timeThreshold;
109 std::optional<std::uint8_t> trim; // valid range is 1-25
110 };
111
112 using Result = HandlerReturnType<Output>;
113
119 GetAggregatePriceHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend)
120 : sharedPtrBackend_(sharedPtrBackend)
121 {
122 }
123
130 static RpcSpecConstRef
131 spec([[maybe_unused]] uint32_t apiVersion)
132 {
133 static constexpr auto kORACLES_MAX = 200;
134
135 static auto const kORACLES_VALIDATOR =
136 modifiers::CustomModifier{[](boost::json::value& value, std::string_view) -> MaybeError {
137 if (!value.is_array() or value.as_array().empty() or value.as_array().size() > kORACLES_MAX)
138 return Error{Status{RippledError::rpcORACLE_MALFORMED}};
139
140 for (auto& oracle : value.as_array()) {
141 if (!oracle.is_object() or !oracle.as_object().contains(JS(oracle_document_id)) or
142 !oracle.as_object().contains(JS(account)))
143 return Error{Status{RippledError::rpcORACLE_MALFORMED}};
144
146 oracle.as_object(), JS(oracle_document_id)
147 );
148 if (!maybeError)
149 return maybeError;
150
151 maybeError = modifiers::ToNumber::modify(oracle, JS(oracle_document_id));
152 if (!maybeError)
153 return maybeError;
154
155 maybeError =
156 validation::CustomValidators::accountBase58Validator.verify(oracle.as_object(), JS(account));
157 if (!maybeError)
158 return Error{Status{RippledError::rpcINVALID_PARAMS}};
159 };
160
161 return MaybeError{};
162 }};
163
164 static auto const kRPC_SPEC = RpcSpec{
167 // validate quoteAsset and base_asset in accordance to the currency code found in XRPL doc:
168 // https://xrpl.org/docs/references/protocol/data-types/currency-formats#currency-codes
169 // usually Clio returns rpcMALFORMED_CURRENCY , return InvalidParam here just to mimic rippled
170 {JS(base_asset),
173 validation::CustomValidators::currencyValidator, Status(RippledError::rpcINVALID_PARAMS)
174 }},
175 {JS(quote_asset),
178 validation::CustomValidators::currencyValidator, Status(RippledError::rpcINVALID_PARAMS)
179 }},
180 {JS(oracles), validation::Required{}, kORACLES_VALIDATOR},
181 // note: Unlike `rippled`, Clio only supports UInt as input, no string, no `null`, etc.
182 {JS(time_threshold), validation::Type<std::uint32_t>{}},
183 {
184 JS(trim),
187 }
188 };
189
190 return kRPC_SPEC;
191 }
192
200 Result
201 process(Input input, Context const& ctx) const;
202
203private:
209 void
210 tracebackOracleObject(
211 boost::asio::yield_context yield,
212 ripple::STObject const& oracleObject,
213 std::function<bool(ripple::STObject const&)> const& callback
214 ) const;
215
222 friend void
223 tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output);
224
231 friend Input
232 tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
233};
234
235} // namespace rpc
The get_aggregate_price method.
Definition GetAggregatePrice.hpp:54
static RpcSpecConstRef spec(uint32_t apiVersion)
Returns the API specification for the command.
Definition GetAggregatePrice.hpp:131
GetAggregatePriceHandler(std::shared_ptr< BackendInterface > const &sharedPtrBackend)
Construct a new GetAggregatePrice handler object.
Definition GetAggregatePrice.hpp:119
friend void tag_invoke(boost::json::value_from_tag, boost::json::value &jv, Output const &output)
Convert the Output to a JSON object.
Definition GetAggregatePrice.cpp:287
Result process(Input input, Context const &ctx) const
Process the GetAggregatePrice command.
Definition GetAggregatePrice.cpp:62
A meta-processor that wraps a validator and produces a custom error in case the wrapped validator fai...
Definition MetaProcessors.hpp:166
Customised modifier allowing user define how to modify input in provided callable.
Definition Modifiers.hpp:145
Validate that value is between specified min and max.
Definition Validators.hpp:170
MaybeError verify(boost::json::value const &value, std::string_view key) const
Verify that the JSON value is valid according to the custom validation function stored.
Definition Validators.cpp:77
This namespace contains all the RPC logic and handlers.
Definition AMMHelpers.cpp:36
RpcSpec const & RpcSpecConstRef
An alias for a const reference to RpcSpec.
Definition Specs.hpp:145
std::expected< OutputType, Status > HandlerReturnType
Return type for each individual handler.
Definition Types.hpp:81
std::expected< void, Status > MaybeError
Return type used for Validators that can return error but don't have specific value to return.
Definition Types.hpp:55
std::unexpected< Status > Error
The type that represents just the error part of MaybeError.
Definition Types.hpp:75
Context of an RPC call.
Definition Types.hpp:118
A struct to hold the input data for the command.
Definition GetAggregatePrice.hpp:102
A struct to hold the input oracle data.
Definition GetAggregatePrice.hpp:94
A struct to hold the output data of the command.
Definition GetAggregatePrice.hpp:70
Output(uint32_t time, std::string ledgerHash, uint32_t ledgerIndex)
Construct a new Output object.
Definition GetAggregatePrice.hpp:85
A struct to hold the statistics.
Definition GetAggregatePrice.hpp:61
Result type used to return responses or error statuses to the Webserver subsystem.
Definition Types.hpp:129
Represents a Specification of an entire RPC command.
Definition Specs.hpp:98
A status returned from any RPC handler.
Definition Errors.hpp:82
static MaybeError modify(boost::json::value &value, std::string_view key)
Update the input string to integer if it can be converted to integer by stoi.
Definition Modifiers.hpp:121
static CustomValidator currencyValidator
Provides a commonly used validator for currency, including standard currency code and token code.
Definition Validators.hpp:535
static CustomValidator ledgerIndexValidator
Provides a commonly used validator for ledger index.
Definition Validators.hpp:484
static CustomValidator uint256HexStringValidator
Provides a commonly used validator for uint256 hex string.
Definition Validators.hpp:530
static CustomValidator accountBase58Validator
Provides a commonly used validator for accounts.
Definition Validators.hpp:498
A validator that simply requires a field to be present.
Definition Validators.hpp:47
Validates that the type of the value is one of the given types.
Definition Validators.hpp:142
MaybeError verify(boost::json::value const &value, std::string_view key) const
Verify that the JSON value is (one) of specified type(s).
Definition Validators.hpp:151