22#include <xrpld/app/misc/AMMHelpers.h>
24#include <xrpl/protocol/Quality.h>
26#include <boost/regex.hpp>
57 str = boost::regex_replace(str, boost::regex(
"^(A|O)[(]"),
"");
60 boost::regex rx(
"^([^(]+)[(]([^)]+)[)]([)])?$");
61 if (boost::regex_search(str,
match, rx))
64 *delimited = (
match[3] !=
"");
65 if (
match[1] ==
"XRP")
68 else if (
match[1] ==
"XRPA")
81 str = boost::regex_replace(str, boost::regex(
"^T[(]"),
"");
84 boost::regex rx(
"^([^(]+)[(]([^)]+)[)]([)])?$");
85 if (boost::regex_search(str,
match, rx))
91 return {{currency,
rate,
match[3] !=
"" ? true :
false}};
113 bool const amm = s[0] ==
'O' ? false :
true;
114 auto const a1 =
getAmt(p++);
115 if (!a1 || p ==
end_)
117 auto const a2 =
getAmt(p++);
120 return {{{*a1, *a2}, amm}};
137 auto const [currency, trate, delimited] = *
rate;
138 rates[currency] = trate;
154 auto isPair = [](
auto const& p) {
156 return s[0] ==
'A' || s[0] ==
'O';
162 if (!res || p ==
end_)
167 auto const swap =
getAmt(p++);
175 return {{pairs, *swap, *
rate,
fee}};
206 int limitingStep = vp.size();
208 auto trate = [&](
auto const& amt) {
209 auto const currency =
to_string(amt.issue().currency);
210 return rates.find(currency) != rates.end() ? rates.at(currency)
215 for (
auto it = vp.rbegin(); it != vp.rend(); ++it)
217 sout =
mulratio(sin, trate(sin), QUALITY_ONE,
true);
218 auto const [amts, amm] = *it;
224 else if (sout <= amts.out)
226 sin = Quality{amts}.ceil_out(amts, sout).in;
232 limitingStep = vp.rend() - it - 1;
234 if (it == vp.rbegin())
235 resultOut = amts.out;
241 for (
int i = limitingStep + 1; i < vp.size(); ++i)
243 auto const [amts, amm] = vp[i];
244 sin =
mulratio(sin, QUALITY_ONE, trate(sin),
false);
252 sout = Quality{amts}.ceil_in(amts, sin).out;
271 int limitingStep = 0;
273 auto trate = [&](
auto const& amt) {
274 auto const currency =
to_string(amt.issue().currency);
275 return rates.find(currency) != rates.end() ? rates.at(currency)
279 for (
auto it = vp.begin(); it != vp.end(); ++it)
281 auto const [amts, amm] = *it;
292 else if (sin <= amts.in)
294 sout = Quality{amts}.ceil_in(amts, sin).out;
301 limitingStep = it - vp.begin();
309 for (
int i = limitingStep - 1; i >= 0; --i)
311 sout =
mulratio(sin, trate(sin), QUALITY_ONE,
false);
312 auto const [amts, amm] = vp[i];
320 sin = Quality{amts}.ceil_out(amts, sout).in;
324 resultOut =
mulratio(resultOut, QUALITY_ONE, trate(resultOut),
true);
333 auto const a =
arg();
334 boost::regex re(
",");
352 auto const exec = [&]() ->
bool {
367 if (
auto const swap =
getSwap(++p); swap)
382 else if (*p ==
"swapout")
384 if (
auto const swap =
getSwap(++p); swap)
394 else if (*p ==
"lptokens")
399 auto const LPT = amm[
"LPT"];
416 else if (*p ==
"changespq")
426 Quality{offer->first},
432 <<
"amm offer: " <<
toString(ammOffer->in)
435 <<
toString(pool->first.in + ammOffer->in)
437 <<
toString(pool->first.out - ammOffer->out)
440 std::cout <<
"can't change the pool's SP quality"
461BEAST_DEFINE_TESTSUITE_MANUAL(AMMCalc, app,
ripple);
A generic endpoint for log messages.
static Sink & getNullSink()
Returns a Sink which does nothing.
std::string const & arg() const
Return the argument associated with the runner.
std::string getText() const override
Issue const & issue() const
bool native() const noexcept
std::optional< std::pair< Amounts, bool > > getAmounts(token_iter &p)
void swapOut(swapargs const &args)
void swapIn(swapargs const &args)
std::optional< trates > getTransferRate(token_iter &p)
std::optional< std::tuple< std::string, std::uint32_t, bool > > getRate(token_iter const &p)
boost::sregex_token_iterator token_iter
STAmount mulratio(STAmount const &amt, std::uint32_t a, std::uint32_t b, bool round)
std::uint32_t getFee(token_iter const &p)
std::optional< STAmount > getAmt(token_iter const &p, bool *delimited=nullptr)
std::string toString(STAmount const &a)
std::optional< swapargs > getSwap(token_iter &p)
void run() override
Runs the suite.
Immutable cryptographic account descriptor.
A transaction testing environment.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
XRP_t const XRP
Converts to XRP Issue or STAmount.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
static void limitStepIn(Offer const &offer, TAmounts< TIn, TOut > &ofrAmt, TAmounts< TIn, TOut > &stpAmt, TOut &ownerGives, std::uint32_t transferRateIn, std::uint32_t transferRateOut, TIn const &limit)
TOut swapAssetIn(TAmounts< TIn, TOut > const &pool, TIn const &assetIn, std::uint16_t tfee)
AMM pool invariant - the product (A * B) after swap in/out has to remain at least the same: (A + in) ...
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
std::optional< TAmounts< TIn, TOut > > changeSpotPriceQuality(TAmounts< TIn, TOut > const &pool, Quality const &quality, std::uint16_t tfee, Rules const &rules, beast::Journal j)
Generate AMM offer so that either updated Spot Price Quality (SPQ) is equal to LOB quality (in this c...
static void limitStepOut(Offer const &offer, TAmounts< TIn, TOut > &ofrAmt, TAmounts< TIn, TOut > &stpAmt, TOut &ownerGives, std::uint32_t transferRateIn, std::uint32_t transferRateOut, TOut const &limit)
IOUAmount mulRatio(IOUAmount const &amt, std::uint32_t num, std::uint32_t den, bool roundUp)
STAmount ammLPTokens(STAmount const &asset1, STAmount const &asset2, Issue const &lptIssue)
Calculate LP Tokens given AMM pool reserves.
std::string to_string(base_uint< Bits, Tag > const &a)
STAmount amountFromString(Asset const &asset, std::string const &amount)
TIn swapAssetOut(TAmounts< TIn, TOut > const &pool, TOut const &assetOut, std::uint16_t tfee)
Swap assetOut out of the pool and swap in a proportional amount of the other asset.