#ifndef XRPL_PROTOCOL_ASSET_H_INCLUDED #define XRPL_PROTOCOL_ASSET_H_INCLUDED #include #include #include #include namespace ripple { class Asset; class STAmount; template concept ValidIssueType = std::is_same_v || std::is_same_v; template concept AssetType = std::is_convertible_v || std::is_convertible_v || std::is_convertible_v || std::is_convertible_v; /* Asset is an abstraction of three different issue types: XRP, IOU, MPT. * For historical reasons, two issue types XRP and IOU are wrapped in Issue * type. Many functions and classes there were first written for Issue * have been rewritten for Asset. */ class Asset { public: using value_type = std::variant; private: value_type issue_; public: Asset() = default; /** Conversions to Asset are implicit and conversions to specific issue * type are explicit. This design facilitates the use of Asset. */ Asset(Issue const& issue) : issue_(issue) { } Asset(MPTIssue const& mptIssue) : issue_(mptIssue) { } Asset(MPTID const& issuanceID) : issue_(MPTIssue{issuanceID}) { } AccountID const& getIssuer() const; template constexpr TIss const& get() const; template TIss& get(); template constexpr bool holds() const; std::string getText() const; constexpr value_type const& value() const; void setJson(Json::Value& jv) const; STAmount operator()(Number const&) const; bool native() const { return holds() && get().native(); } friend constexpr bool operator==(Asset const& lhs, Asset const& rhs); friend constexpr std::weak_ordering operator<=>(Asset const& lhs, Asset const& rhs); friend constexpr bool operator==(Currency const& lhs, Asset const& rhs); /** Return true if both assets refer to the same currency (regardless of * issuer) or MPT issuance. Otherwise return false. */ friend constexpr bool equalTokens(Asset const& lhs, Asset const& rhs); }; inline Json::Value to_json(Asset const& asset) { Json::Value jv; asset.setJson(jv); return jv; } template constexpr bool Asset::holds() const { return std::holds_alternative(issue_); } template constexpr TIss const& Asset::get() const { if (!std::holds_alternative(issue_)) Throw("Asset is not a requested issue"); return std::get(issue_); } template TIss& Asset::get() { if (!std::holds_alternative(issue_)) Throw("Asset is not a requested issue"); return std::get(issue_); } constexpr Asset::value_type const& Asset::value() const { return issue_; } constexpr bool operator==(Asset const& lhs, Asset const& rhs) { return std::visit( [&]( TLhs const& issLhs, TRhs const& issRhs) { if constexpr (std::is_same_v) return issLhs == issRhs; else return false; }, lhs.issue_, rhs.issue_); } constexpr std::weak_ordering operator<=>(Asset const& lhs, Asset const& rhs) { return std::visit( []( TLhs const& lhs_, TRhs const& rhs_) { if constexpr (std::is_same_v) return std::weak_ordering(lhs_ <=> rhs_); else if constexpr ( std::is_same_v && std::is_same_v) return std::weak_ordering::greater; else return std::weak_ordering::less; }, lhs.issue_, rhs.issue_); } constexpr bool operator==(Currency const& lhs, Asset const& rhs) { return rhs.holds() && rhs.get().currency == lhs; } constexpr bool equalTokens(Asset const& lhs, Asset const& rhs) { return std::visit( [&]( TLhs const& issLhs, TRhs const& issRhs) { if constexpr ( std::is_same_v && std::is_same_v) return issLhs.currency == issRhs.currency; else if constexpr ( std::is_same_v && std::is_same_v) return issLhs.getMptID() == issRhs.getMptID(); else return false; }, lhs.issue_, rhs.issue_); } inline bool isXRP(Asset const& asset) { return asset.native(); } std::string to_string(Asset const& asset); bool validJSONAsset(Json::Value const& jv); Asset assetFromJson(Json::Value const& jv); } // namespace ripple #endif // XRPL_PROTOCOL_ASSET_H_INCLUDED