Skip to content

Commit

Permalink
[FOLD] Rename Max/MinBidPrice to BidMax/Min and other changes.
Browse files Browse the repository at this point in the history
* STIssue for XRP is json object with currency, no issuer
* Add Expiration, Account, AuthAccounts to AuctionSlot in amm_info
  • Loading branch information
gregtatcam committed Nov 8, 2022
1 parent c9d9e6b commit ffe6a55
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 85 deletions.
48 changes: 23 additions & 25 deletions src/ripple/app/tx/impl/AMMBid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ AMMBid::preflight(PreflightContext const& ctx)
return res;
}

if (auto const res = invalidAMMAmount(ctx.tx[~sfMinBidPrice]))
if (auto const res = invalidAMMAmount(ctx.tx[~sfBidMin]))
{
JLOG(ctx.j.debug()) << "AMM Bid: invalid min slot price.";
return res;
}

if (auto const res = invalidAMMAmount(ctx.tx[~sfMaxBidPrice]))
if (auto const res = invalidAMMAmount(ctx.tx[~sfBidMax]))
{
JLOG(ctx.j.debug()) << "AMM Bid: invalid max slot price.";
return res;
Expand Down Expand Up @@ -111,39 +111,38 @@ AMMBid::preclaim(PreclaimContext const& ctx)
ammLPHolds(ctx.view, **ammSle, ctx.tx[sfAccount], ctx.j);
auto const lpTokensBalance = (**ammSle)[sfLPTokenBalance];

auto const minBidSlotPrice = ctx.tx[~sfMinBidPrice];
auto const bidMin = ctx.tx[~sfBidMin];

if (minBidSlotPrice)
if (bidMin)
{
if (*minBidSlotPrice > lpTokens || *minBidSlotPrice >= lpTokensBalance)
if (*bidMin > lpTokens || *bidMin >= lpTokensBalance)
{
JLOG(ctx.j.debug()) << "AMM Bid: Invalid Tokens.";
return tecAMM_INVALID_TOKENS;
}
if (minBidSlotPrice->issue() != lpTokens.issue())
if (bidMin->issue() != lpTokens.issue())
{
JLOG(ctx.j.debug()) << "AMM Bid: Invalid LPToken.";
return temBAD_AMM_TOKENS;
}
}

auto const maxBidSlotPrice = ctx.tx[~sfMaxBidPrice];
if (maxBidSlotPrice)
auto const bidMax = ctx.tx[~sfBidMax];
if (bidMax)
{
if (*maxBidSlotPrice > lpTokens || *maxBidSlotPrice >= lpTokensBalance)
if (*bidMax > lpTokens || *bidMax >= lpTokensBalance)
{
JLOG(ctx.j.debug()) << "AMM Bid: Invalid Tokens.";
return tecAMM_INVALID_TOKENS;
}
if (maxBidSlotPrice->issue() != lpTokens.issue())
if (bidMax->issue() != lpTokens.issue())
{
JLOG(ctx.j.debug()) << "AMM Bid: Invalid LPToken.";
return temBAD_AMM_TOKENS;
}
}

if (minBidSlotPrice && maxBidSlotPrice &&
minBidSlotPrice >= maxBidSlotPrice)
if (bidMin && bidMax && bidMin >= bidMax)
{
JLOG(ctx.j.debug()) << "AMM Bid: Invalid Max/MinSlotPrice.";
return tecAMM_INVALID_TOKENS;
Expand Down Expand Up @@ -223,8 +222,8 @@ applyBid(

TER res = tesSUCCESS;

auto const minBidSlotPrice = ctx_.tx[~sfMinBidPrice];
auto const maxBidSlotPrice = ctx_.tx[~sfMaxBidPrice];
auto const bidMin = ctx_.tx[~sfBidMin];
auto const bidMax = ctx_.tx[~sfBidMax];

Number const MinSlotPrice = lptAMMBalance / 100000; // 0.001% TBD

Expand Down Expand Up @@ -252,27 +251,26 @@ applyBid(

auto const payPrice = [&]() -> std::optional<Number> {
// Both min/max bid price are defined
if (minBidSlotPrice && maxBidSlotPrice)
if (bidMin && bidMax)
{
if (computedPrice >= *minBidSlotPrice &&
computedPrice <= *maxBidSlotPrice)
if (computedPrice >= *bidMin && computedPrice <= *bidMax)
return computedPrice;
JLOG(ctx_.journal.debug())
<< "AMM Bid: not in range " << computedPrice
<< *minBidSlotPrice << " " << *maxBidSlotPrice;
<< "AMM Bid: not in range " << computedPrice << *bidMin
<< " " << *bidMax;
return std::nullopt;
}
// Bidder pays max(bidPrice, computedPrice)
if (minBidSlotPrice)
if (bidMin)
{
return std::max(computedPrice, Number(*minBidSlotPrice));
return std::max(computedPrice, Number(*bidMin));
}
else if (maxBidSlotPrice)
else if (bidMax)
{
if (computedPrice <= *maxBidSlotPrice)
if (computedPrice <= *bidMax)
return computedPrice;
JLOG(ctx_.journal.debug()) << "AMM Bid: not in range "
<< computedPrice << *maxBidSlotPrice;
JLOG(ctx_.journal.debug())
<< "AMM Bid: not in range " << computedPrice << *bidMax;
return std::nullopt;
}
else
Expand Down
4 changes: 2 additions & 2 deletions src/ripple/protocol/SField.h
Original file line number Diff line number Diff line change
Expand Up @@ -488,8 +488,8 @@ extern SF_AMOUNT const sfSendMax;
extern SF_AMOUNT const sfDeliverMin;
extern SF_AMOUNT const sfAmount2;
extern SF_AMOUNT const sfEPrice;
extern SF_AMOUNT const sfMinBidPrice;
extern SF_AMOUNT const sfMaxBidPrice;
extern SF_AMOUNT const sfBidMin;
extern SF_AMOUNT const sfBidMax;
extern SF_AMOUNT const sfPrice;
extern SF_AMOUNT const sfLPTokenBalance;

Expand Down
4 changes: 2 additions & 2 deletions src/ripple/protocol/impl/SField.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,8 @@ CONSTRUCT_TYPED_SFIELD(sfFee, "Fee", AMOUNT,
CONSTRUCT_TYPED_SFIELD(sfSendMax, "SendMax", AMOUNT, 9);
CONSTRUCT_TYPED_SFIELD(sfDeliverMin, "DeliverMin", AMOUNT, 10);
CONSTRUCT_TYPED_SFIELD(sfAmount2, "Amount2", AMOUNT, 11);
CONSTRUCT_TYPED_SFIELD(sfMinBidPrice, "MinBidPrice", AMOUNT, 12);
CONSTRUCT_TYPED_SFIELD(sfMaxBidPrice, "MaxBidPrice", AMOUNT, 13);
CONSTRUCT_TYPED_SFIELD(sfBidMin, "BidMin", AMOUNT, 12);
CONSTRUCT_TYPED_SFIELD(sfBidMax, "BidMax", AMOUNT, 13);

// currency amount (uncommon)
CONSTRUCT_TYPED_SFIELD(sfMinimumOffer, "MinimumOffer", AMOUNT, 16);
Expand Down
46 changes: 17 additions & 29 deletions src/ripple/protocol/impl/STIssue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,9 @@ Json::Value
STIssue::getJson(JsonOptions) const
{
Json::Value elem = Json::objectValue;
elem[jss::currency] = to_string(issue_.currency);
if (!isXRP(issue_.currency))
{
elem[jss::currency] = to_string(issue_.currency);
elem[jss::issuer] = to_string(issue_.account);
}
else
{
elem = getText();
}
return elem;
}

Expand Down Expand Up @@ -146,37 +140,31 @@ STIssue::move(std::size_t n, void* buf)
STIssue
issueFromJson(SField const& name, Json::Value const& v)
{
if (!v.isObject() && !v.isString())
if (!v.isObject())
{
Throw<std::runtime_error>(
"Issue must be specified with either an object or a string Json "
"value");
"Issue must be specified with as an 'object' Json value");
}

if (v.isObject())
{
Issue issue;

Json::Value const& currency = v[jss::currency];
Json::Value const& issuer = v[jss::issuer];
if (!to_currency(issue.currency, currency.asString()))
Throw<std::runtime_error>("invalid currency");
Issue issue;

if (!issuer.isString() || !to_issuer(issue.account, issuer.asString()))
Throw<std::runtime_error>("invalid issuer");
Json::Value const& currency = v[jss::currency];
Json::Value const& issuer = v[jss::issuer];
if (!to_currency(issue.currency, currency.asString()))
Throw<std::runtime_error>("Issue, invalid currency");

if (isXRP(issue.currency))
Throw<std::runtime_error>("invalid issuer");
if (isXRP(issue.currency))
{
if (!issuer.isNull())
Throw<std::runtime_error>("Issue, XRP should not have issuer");
issue.account = xrpAccount();
return STIssue{name, issue};
}

// String
if (v.asString() != systemCurrencyCode())
{
Throw<std::runtime_error>(
"If Issue is a string value it must specify XRP");
}
return STIssue{name, xrpIssue()};
if (!issuer.isString() || !to_issuer(issue.account, issuer.asString()))
Throw<std::runtime_error>("Issue, invalid issuer");

return STIssue{name, issue};
}

} // namespace ripple
4 changes: 2 additions & 2 deletions src/ripple/protocol/impl/TxFormats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ TxFormats::TxFormats()
{
{sfAsset, soeREQUIRED},
{sfAsset2, soeREQUIRED},
{sfMinBidPrice, soeOPTIONAL},
{sfMaxBidPrice, soeOPTIONAL},
{sfBidMin, soeOPTIONAL},
{sfBidMax, soeOPTIONAL},
{sfAuthAccounts, soeOPTIONAL},
{sfTicketSequence, soeOPTIONAL},
},
Expand Down
5 changes: 3 additions & 2 deletions src/ripple/protocol/jss.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ JSS(Escrow); // ledger type.
JSS(EscrowCancel); // transaction type.
JSS(EscrowCreate); // transaction type.
JSS(EscrowFinish); // transaction type.
JSS(Expiration); // out: AMM info
JSS(Fee); // in/out: TransactionSign; field.
JSS(FeeSettings); // ledger type.
JSS(Flags); // in/out: TransactionSign; field.
Expand All @@ -87,8 +88,8 @@ JSS(Invalid); //
JSS(LastLedgerSequence); // in: TransactionSign; field
JSS(LedgerHashes); // ledger type.
JSS(LimitAmount); // field.
JSS(MaxBidPrice); // in: AMM Bid
JSS(MinBidPrice); // in: AMM Bid
JSS(BidMax); // in: AMM Bid
JSS(BidMin); // in: AMM Bid
JSS(NFTokenBurn); // transaction type.
JSS(NFTokenMint); // transaction type.
JSS(NFTokenOffer); // ledger type.
Expand Down
60 changes: 49 additions & 11 deletions src/ripple/rpc/handlers/AMMInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,42 @@ getAccount(Json::Value const& v, Json::Value& result)
}

Expected<Issue, error_code_i>
getIssue(
Json::Value const& params,
Json::StaticString const& field,
beast::Journal j)
getIssue(Json::Value const& v, beast::Journal j)
{
try
if (!v.isObject())
{
return issueFromJson(params[field]);
JLOG(j.debug())
<< "getIssue must be specified as an 'object' Json value";
return Unexpected(rpcAMM_ISSUE_MALFORMED);
}
catch (std::runtime_error const& ex)

Issue issue = xrpIssue();

Json::Value const& currency = v[jss::currency];
Json::Value const& issuer = v[jss::issuer];
if (!to_currency(issue.currency, currency.asString()))
{
JLOG(j.debug()) << ex.what();
JLOG(j.debug()) << "getIssue, invalid currency";
return Unexpected(rpcAMM_ISSUE_MALFORMED);
}
return Unexpected(rpcAMM_ISSUE_MALFORMED);

if (isXRP(issue.currency))
{
if (!issuer.isNull())
{
JLOG(j.debug()) << "getIssue, XRP should not have issuer";
return Unexpected(rpcAMM_ISSUE_MALFORMED);
}
return issue;
}

if (!issuer.isString() || !to_issuer(issue.account, issuer.asString()))
{
JLOG(j.debug()) << "getIssue, invalid issuer";
return Unexpected(rpcAMM_ISSUE_MALFORMED);
}

return issue;
}

Json::Value
Expand All @@ -77,14 +99,14 @@ doAMMInfo(RPC::JsonContext& context)
return result;
}

if (auto const i = getIssue(params, jss::asset, context.j); !i)
if (auto const i = getIssue(params[jss::asset], context.j); !i)
{
RPC::inject_error(i.error(), result);
return result;
}
else
issue1 = *i;
if (auto const i = getIssue(params, jss::asset2, context.j); !i)
if (auto const i = getIssue(params[jss::asset2], context.j); !i)
{
RPC::inject_error(i.error(), result);
return result;
Expand Down Expand Up @@ -131,6 +153,7 @@ doAMMInfo(RPC::JsonContext& context)
for (auto const& voteEntry : amm->getFieldArray(sfVoteSlots))
{
Json::Value vote;
vote[jss::Account] = to_string(voteEntry.getAccountID(sfAccount));
vote[jss::TradingFee] = voteEntry[sfTradingFee];
vote[jss::VoteWeight] = voteEntry[sfVoteWeight];
voteSlots.append(vote);
Expand All @@ -151,6 +174,21 @@ doAMMInfo(RPC::JsonContext& context)
auction[jss::TimeInterval] = timeSlot ? *timeSlot : 0;
auctionSlot[sfPrice].setJson(auction[jss::Price]);
auction[jss::DiscountedFee] = auctionSlot[sfDiscountedFee];
auction[jss::Account] =
to_string(auctionSlot.getAccountID(sfAccount));
auction[jss::Expiration] = auctionSlot[sfExpiration];
if (auctionSlot.isFieldPresent(sfAuthAccounts))
{
Json::Value auth;
for (auto const& acct :
auctionSlot.getFieldArray(sfAuthAccounts))
{
Json::Value jv;
jv[jss::Account] = to_string(acct.getAccountID(sfAccount));
auth.append(jv);
}
auction = auth[jss::AuthAccounts];
}
result[jss::AuctionSlot] = auction;
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/test/jtx/AMM.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ class AMM
// Predict next purchase price
IOUAmount lastPurchasePrice_;
Number minSlotPrice_;
std::optional<IOUAmount> minBidPrice_;
std::optional<IOUAmount> maxBidPrice_;
std::optional<IOUAmount> bidMin_;
std::optional<IOUAmount> bidMax_;

public:
AMM(Env& env,
Expand Down
20 changes: 10 additions & 10 deletions src/test/jtx/impl/AMM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ AMM::AMM(
, log_(log)
, lastPurchasePrice_(0)
, minSlotPrice_(0)
, minBidPrice_()
, maxBidPrice_()
, bidMin_()
, bidMax_()
{
create(tfee, flags, seq);
}
Expand Down Expand Up @@ -585,23 +585,23 @@ AMM::bid(
}
minSlotPrice_ = (*amm)[sfLPTokenBalance].iou() / 100000;
}
minBidPrice_ = std::nullopt;
maxBidPrice_ = std::nullopt;
bidMin_ = std::nullopt;
bidMax_ = std::nullopt;

Json::Value jv;
jv[jss::Account] = account ? account->human() : creatorAccount_.human();
setTokens(jv, assets);
if (minSlotPrice)
{
STAmount saTokens{lptIssue_, *minSlotPrice, 0};
saTokens.setJson(jv[jss::MinBidPrice]);
minBidPrice_ = saTokens.iou();
saTokens.setJson(jv[jss::BidMin]);
bidMin_ = saTokens.iou();
}
if (maxSlotPrice)
{
STAmount saTokens{lptIssue_, *maxSlotPrice, 0};
saTokens.setJson(jv[jss::MaxBidPrice]);
maxBidPrice_ = saTokens.iou();
saTokens.setJson(jv[jss::BidMax]);
bidMax_ = saTokens.iou();
}
if (authAccounts.size() > 0)
{
Expand Down Expand Up @@ -652,8 +652,8 @@ AMM::expectedPurchasePrice(
}();

// assume price is in range
if (minBidPrice_ && !maxBidPrice_)
return std::max(computedPrice, *minBidPrice_);
if (bidMin_ && !bidMax_)
return std::max(computedPrice, *bidMin_);
return computedPrice;
}

Expand Down

0 comments on commit ffe6a55

Please sign in to comment.