Files
rippled/src/test/jtx/Oracle.h

178 lines
5.1 KiB
C++

#pragma once
#include <test/jtx.h>
#include <date/date.h>
namespace xrpl::test::jtx::oracle {
using AnyValue = std::variant<std::string, double, Json::Int, Json::UInt>;
using OraclesData = std::vector<std::pair<std::optional<Account>, std::optional<AnyValue>>>;
// Special string value, which is converted to unquoted string in the string
// passed to rpc.
constexpr char const* NoneTag = "%None%";
constexpr char const* UnquotedNone = "None";
constexpr char const* NonePattern = "\"%None%\"";
std::uint32_t
asUInt(AnyValue const& v);
bool
validDocumentID(AnyValue const& v);
void
toJson(Json::Value& jv, AnyValue const& v);
void
toJsonHex(Json::Value& jv, AnyValue const& v);
// base asset, quote asset, price, scale
using DataSeries = std::vector<
std::
tuple<std::string, std::string, std::optional<std::uint32_t>, std::optional<std::uint8_t>>>;
// Typical defaults for Create
struct CreateArg
{
std::optional<AccountID> owner = std::nullopt;
std::optional<AnyValue> documentID = 1;
DataSeries series = {{"XRP", "USD", 740, 1}};
std::optional<AnyValue> assetClass = "currency";
std::optional<AnyValue> provider = "provider";
std::optional<AnyValue> uri = "URI";
std::optional<AnyValue> lastUpdateTime = std::nullopt;
std::uint32_t flags = 0;
std::optional<jtx::msig> msig = std::nullopt;
std::optional<jtx::seq> seq = std::nullopt;
int fee = 10;
std::optional<ter> err = std::nullopt;
bool close = false;
};
// Typical defaults for Update
struct UpdateArg
{
std::optional<AccountID> owner = std::nullopt;
std::optional<AnyValue> documentID = std::nullopt;
DataSeries series = {}; // NOLINT(readability-redundant-member-init)
std::optional<AnyValue> assetClass = std::nullopt;
std::optional<AnyValue> provider = std::nullopt;
std::optional<AnyValue> uri = "URI";
std::optional<AnyValue> lastUpdateTime = std::nullopt;
std::uint32_t flags = 0;
std::optional<jtx::msig> msig = std::nullopt;
std::optional<jtx::seq> seq = std::nullopt;
int fee = 10;
std::optional<ter> err = std::nullopt;
};
struct RemoveArg
{
std::optional<AccountID> const& owner = std::nullopt;
std::optional<AnyValue> const& documentID = std::nullopt;
std::uint32_t flags = 0;
std::optional<jtx::msig> const& msig = std::nullopt;
std::optional<jtx::seq> seq = std::nullopt;
int fee = 10;
std::optional<ter> const& err = std::nullopt;
};
// Simulate testStartTime as 10'000s from XRPL epoch time to make
// LastUpdateTime validation to work and to make unit-test consistent.
// The value doesn't matter much, it has to be greater
// than maxLastUpdateTimeDelta in order to pass LastUpdateTime
// validation {close-maxLastUpdateTimeDelta,close+maxLastUpdateTimeDelta}.
constexpr static std::chrono::seconds testStartTime = epoch_offset + std::chrono::seconds(10'000);
/** Oracle class facilitates unit-testing of the Price Oracle feature.
* It defines functions to create, update, and delete the Oracle object,
* to query for various states, and to call APIs.
*/
class Oracle
{
private:
// Global fee if not 0
static inline std::uint32_t fee = 0;
Env& env_;
AccountID owner_;
std::uint32_t documentID_{};
private:
void
submit(
Json::Value const& jv,
std::optional<jtx::msig> const& msig,
std::optional<jtx::seq> const& seq,
std::optional<ter> const& err);
public:
Oracle(Env& env, CreateArg const& arg, bool submit = true);
void
remove(RemoveArg const& arg);
void
set(CreateArg const& arg);
void
set(UpdateArg const& arg);
static Json::Value
aggregatePrice(
Env& env,
std::optional<AnyValue> const& baseAsset,
std::optional<AnyValue> const& quoteAsset,
std::optional<OraclesData> const& oracles = std::nullopt,
std::optional<AnyValue> const& trim = std::nullopt,
std::optional<AnyValue> const& timeThreshold = std::nullopt);
[[nodiscard]] std::uint32_t
documentID() const
{
return documentID_;
}
[[nodiscard]] bool
exists() const
{
return exists(env_, owner_, documentID_);
}
[[nodiscard]] static bool
exists(Env& env, AccountID const& account, std::uint32_t documentID);
[[nodiscard]] bool
expectPrice(DataSeries const& prices) const;
[[nodiscard]] bool
expectLastUpdateTime(std::uint32_t lastUpdateTime) const;
static Json::Value
ledgerEntry(
Env& env,
std::optional<std::variant<AccountID, std::string>> const& account,
std::optional<AnyValue> const& documentID,
std::optional<std::string> const& index = std::nullopt);
[[nodiscard]] Json::Value
ledgerEntry(std::optional<std::string> const& index = std::nullopt) const
{
return Oracle::ledgerEntry(env_, owner_, documentID_, index);
}
static void
setFee(std::uint32_t f)
{
fee = f;
}
friend std::ostream&
operator<<(std::ostream& strm, Oracle const& oracle)
{
strm << oracle.ledgerEntry().toStyledString();
return strm;
}
};
} // namespace xrpl::test::jtx::oracle