#pragma once #include #include #include #include #include namespace xrpl { inline STAmount toSTAmount(IOUAmount const& iou, Asset const& asset) { XRPL_ASSERT(asset.holds(), "xrpl::toSTAmount : is Issue"); bool const isNeg = iou.signum() < 0; std::uint64_t const umant = isNeg ? -iou.mantissa() : iou.mantissa(); return STAmount(asset, umant, iou.exponent(), isNeg, STAmount::unchecked()); } inline STAmount toSTAmount(IOUAmount const& iou) { return toSTAmount(iou, noIssue()); } inline STAmount toSTAmount(XRPAmount const& xrp) { bool const isNeg = xrp.signum() < 0; std::uint64_t const umant = isNeg ? -xrp.drops() : xrp.drops(); return STAmount(umant, isNeg); } inline STAmount toSTAmount(XRPAmount const& xrp, Asset const& asset) { XRPL_ASSERT(isXRP(asset), "xrpl::toSTAmount : is XRP"); return toSTAmount(xrp); } inline STAmount toSTAmount(MPTAmount const& mpt) { return STAmount(mpt, noMPT()); } inline STAmount toSTAmount(MPTAmount const& mpt, Asset const& asset) { XRPL_ASSERT(asset.holds(), "xrpl::toSTAmount : is MPT"); return STAmount(mpt, asset.get()); } template T toAmount(STAmount const& amt) = delete; template <> inline STAmount toAmount(STAmount const& amt) { return amt; } template <> inline IOUAmount toAmount(STAmount const& amt) { XRPL_ASSERT( amt.mantissa() < std::numeric_limits::max(), "xrpl::toAmount : maximum mantissa"); bool const isNeg = amt.negative(); std::int64_t const sMant = isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa(); XRPL_ASSERT(!isXRP(amt), "xrpl::toAmount : is not XRP"); return IOUAmount(sMant, amt.exponent()); } template <> inline XRPAmount toAmount(STAmount const& amt) { XRPL_ASSERT( amt.mantissa() < std::numeric_limits::max(), "xrpl::toAmount : maximum mantissa"); bool const isNeg = amt.negative(); std::int64_t const sMant = isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa(); XRPL_ASSERT(isXRP(amt), "xrpl::toAmount : is XRP"); return XRPAmount(sMant); } template <> inline MPTAmount toAmount(STAmount const& amt) { XRPL_ASSERT( amt.holds() && amt.mantissa() <= maxMPTokenAmount && amt.exponent() == 0, "xrpl::toAmount : maximum mantissa"); if (amt.mantissa() > maxMPTokenAmount || amt.exponent() != 0) Throw("toAmount: invalid mantissa or exponent"); bool const isNeg = amt.negative(); std::int64_t const sMant = isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa(); return MPTAmount(sMant); } template T toAmount(IOUAmount const& amt) = delete; template <> inline IOUAmount toAmount(IOUAmount const& amt) { return amt; } template T toAmount(XRPAmount const& amt) = delete; template <> inline XRPAmount toAmount(XRPAmount const& amt) { return amt; } template T toAmount(MPTAmount const& amt) = delete; template <> inline MPTAmount toAmount(MPTAmount const& amt) { return amt; } template T toAmount(Asset const& asset, Number const& n, Number::rounding_mode mode = Number::getround()) { saveNumberRoundMode const rm(Number::getround()); if (isXRP(asset)) Number::setround(mode); if constexpr (std::is_same_v) { return IOUAmount(n); } else if constexpr (std::is_same_v) { return XRPAmount(static_cast(n)); } else if constexpr (std::is_same_v) { return MPTAmount(static_cast(n)); } else if constexpr (std::is_same_v) { if (isXRP(asset)) return STAmount(asset, static_cast(n)); return STAmount(asset, n); } else { constexpr bool alwaysFalse = !std::is_same_v; static_assert(alwaysFalse, "Unsupported type for toAmount"); } } template T toMaxAmount(Asset const& asset) { if constexpr (std::is_same_v) { return IOUAmount(STAmount::cMaxValue, STAmount::cMaxOffset); } else if constexpr (std::is_same_v) { return XRPAmount(static_cast(STAmount::cMaxNativeN)); } else if constexpr (std::is_same_v) { return MPTAmount(maxMPTokenAmount); } else if constexpr (std::is_same_v) { return asset.visit( [](Issue const& issue) { if (isXRP(issue)) return STAmount(issue, static_cast(STAmount::cMaxNativeN)); return STAmount(issue, STAmount::cMaxValue, STAmount::cMaxOffset); }, [](MPTIssue const& issue) { return STAmount(issue, maxMPTokenAmount); }); } else { constexpr bool alwaysFalse = !std::is_same_v; static_assert(alwaysFalse, "Unsupported type for toMaxAmount"); } } inline STAmount toSTAmount(Asset const& asset, Number const& n, Number::rounding_mode mode = Number::getround()) { return toAmount(asset, n, mode); } template Asset getAsset(T const& amt) { if constexpr (std::is_same_v) { return noIssue(); } else if constexpr (std::is_same_v) { return xrpIssue(); } else if constexpr (std::is_same_v) { return noMPT(); } else if constexpr (std::is_same_v) { return amt.asset(); } else { constexpr bool alwaysFalse = !std::is_same_v; static_assert(alwaysFalse, "Unsupported type for getIssue"); } } template constexpr T get(STAmount const& a) { if constexpr (std::is_same_v) { return a.iou(); } else if constexpr (std::is_same_v) { return a.xrp(); } else if constexpr (std::is_same_v) { return a.mpt(); } else if constexpr (std::is_same_v) { return a; } else { constexpr bool alwaysFalse = !std::is_same_v; static_assert(alwaysFalse, "Unsupported type for get"); } } } // namespace xrpl